ovr_sdk

changeset 0:1b39a1b46319

initial 0.4.4
author John Tsiombikas <nuclear@member.fsf.org>
date Wed, 14 Jan 2015 06:51:16 +0200
parents
children bd36c61436fa
files .hgignore 3rdParty/EDID/edid.cpp 3rdParty/EDID/edid.h 3rdParty/TinyXml/tinyxml2.cpp 3rdParty/TinyXml/tinyxml2.h ConfigureDebian.sh LINUX_README LibOVR/90-oculus.rules LibOVR/Include/OVR.h LibOVR/Include/OVR_Kernel.h LibOVR/Include/OVR_Version.h LibOVR/Makefile LibOVR/Src/CAPI/CAPI_DistortionRenderer.cpp LibOVR/Src/CAPI/CAPI_DistortionRenderer.h LibOVR/Src/CAPI/CAPI_FrameTimeManager.cpp LibOVR/Src/CAPI/CAPI_FrameTimeManager.h LibOVR/Src/CAPI/CAPI_HMDRenderState.cpp LibOVR/Src/CAPI/CAPI_HMDRenderState.h LibOVR/Src/CAPI/CAPI_HMDState.cpp LibOVR/Src/CAPI/CAPI_HMDState.h LibOVR/Src/CAPI/CAPI_HSWDisplay.cpp LibOVR/Src/CAPI/CAPI_HSWDisplay.h LibOVR/Src/CAPI/CAPI_LatencyStatistics.cpp LibOVR/Src/CAPI/CAPI_LatencyStatistics.h LibOVR/Src/CAPI/GL/CAPI_GLE.cpp LibOVR/Src/CAPI/GL/CAPI_GLE.h LibOVR/Src/CAPI/GL/CAPI_GLE_GL.h LibOVR/Src/CAPI/GL/CAPI_GL_DistortionRenderer.cpp LibOVR/Src/CAPI/GL/CAPI_GL_DistortionRenderer.h LibOVR/Src/CAPI/GL/CAPI_GL_DistortionShaders.h LibOVR/Src/CAPI/GL/CAPI_GL_HSWDisplay.cpp LibOVR/Src/CAPI/GL/CAPI_GL_HSWDisplay.h LibOVR/Src/CAPI/GL/CAPI_GL_Util.cpp LibOVR/Src/CAPI/GL/CAPI_GL_Util.h LibOVR/Src/CAPI/Textures/healthAndSafety.tga.h LibOVR/Src/Displays/OVR_Display.cpp LibOVR/Src/Displays/OVR_Display.h LibOVR/Src/Displays/OVR_Linux_Display.cpp LibOVR/Src/Displays/OVR_Linux_Display.h LibOVR/Src/Displays/OVR_Linux_SDKWindow.cpp LibOVR/Src/Displays/OVR_Linux_SDKWindow.h LibOVR/Src/Kernel/OVR_Alg.cpp LibOVR/Src/Kernel/OVR_Alg.h LibOVR/Src/Kernel/OVR_Allocator.cpp LibOVR/Src/Kernel/OVR_Allocator.h LibOVR/Src/Kernel/OVR_Array.h LibOVR/Src/Kernel/OVR_Atomic.cpp LibOVR/Src/Kernel/OVR_Atomic.h LibOVR/Src/Kernel/OVR_CRC32.cpp LibOVR/Src/Kernel/OVR_CRC32.h LibOVR/Src/Kernel/OVR_Color.h LibOVR/Src/Kernel/OVR_Compiler.h LibOVR/Src/Kernel/OVR_ContainerAllocator.h LibOVR/Src/Kernel/OVR_DebugHelp.cpp LibOVR/Src/Kernel/OVR_DebugHelp.h LibOVR/Src/Kernel/OVR_Delegates.h LibOVR/Src/Kernel/OVR_Deque.h LibOVR/Src/Kernel/OVR_File.cpp LibOVR/Src/Kernel/OVR_File.h LibOVR/Src/Kernel/OVR_FileFILE.cpp LibOVR/Src/Kernel/OVR_Hash.h LibOVR/Src/Kernel/OVR_KeyCodes.h LibOVR/Src/Kernel/OVR_List.h LibOVR/Src/Kernel/OVR_Lockless.cpp LibOVR/Src/Kernel/OVR_Lockless.h LibOVR/Src/Kernel/OVR_Log.cpp LibOVR/Src/Kernel/OVR_Log.h LibOVR/Src/Kernel/OVR_Math.cpp LibOVR/Src/Kernel/OVR_Math.h LibOVR/Src/Kernel/OVR_Nullptr.h LibOVR/Src/Kernel/OVR_Observer.h LibOVR/Src/Kernel/OVR_RefCount.cpp LibOVR/Src/Kernel/OVR_RefCount.h LibOVR/Src/Kernel/OVR_SharedMemory.cpp LibOVR/Src/Kernel/OVR_SharedMemory.h LibOVR/Src/Kernel/OVR_Std.cpp LibOVR/Src/Kernel/OVR_Std.h LibOVR/Src/Kernel/OVR_String.cpp LibOVR/Src/Kernel/OVR_String.h LibOVR/Src/Kernel/OVR_StringHash.h LibOVR/Src/Kernel/OVR_String_FormatUtil.cpp LibOVR/Src/Kernel/OVR_String_PathUtil.cpp LibOVR/Src/Kernel/OVR_SysFile.cpp LibOVR/Src/Kernel/OVR_SysFile.h LibOVR/Src/Kernel/OVR_System.cpp LibOVR/Src/Kernel/OVR_System.h LibOVR/Src/Kernel/OVR_ThreadCommandQueue.cpp LibOVR/Src/Kernel/OVR_ThreadCommandQueue.h LibOVR/Src/Kernel/OVR_Threads.h LibOVR/Src/Kernel/OVR_ThreadsPthread.cpp LibOVR/Src/Kernel/OVR_Timer.cpp LibOVR/Src/Kernel/OVR_Timer.h LibOVR/Src/Kernel/OVR_Types.h LibOVR/Src/Kernel/OVR_UTF8Util.cpp LibOVR/Src/Kernel/OVR_UTF8Util.h LibOVR/Src/Net/OVR_BitStream.cpp LibOVR/Src/Net/OVR_BitStream.h LibOVR/Src/Net/OVR_MessageIDTypes.h LibOVR/Src/Net/OVR_NetworkPlugin.cpp LibOVR/Src/Net/OVR_NetworkPlugin.h LibOVR/Src/Net/OVR_NetworkTypes.h LibOVR/Src/Net/OVR_PacketizedTCPSocket.cpp LibOVR/Src/Net/OVR_PacketizedTCPSocket.h LibOVR/Src/Net/OVR_RPC1.cpp LibOVR/Src/Net/OVR_RPC1.h LibOVR/Src/Net/OVR_Session.cpp LibOVR/Src/Net/OVR_Session.h LibOVR/Src/Net/OVR_Socket.cpp LibOVR/Src/Net/OVR_Socket.h LibOVR/Src/Net/OVR_Unix_Socket.cpp LibOVR/Src/Net/OVR_Unix_Socket.h LibOVR/Src/OVR_CAPI.cpp LibOVR/Src/OVR_CAPI.h LibOVR/Src/OVR_CAPI_GL.h LibOVR/Src/OVR_CAPI_Keys.h LibOVR/Src/OVR_JSON.cpp LibOVR/Src/OVR_JSON.h LibOVR/Src/OVR_Profile.cpp LibOVR/Src/OVR_Profile.h LibOVR/Src/OVR_SerialFormat.cpp LibOVR/Src/OVR_SerialFormat.h LibOVR/Src/OVR_Stereo.cpp LibOVR/Src/OVR_Stereo.h LibOVR/Src/Sensors/OVR_DeviceConstants.h LibOVR/Src/Service/Service_NetClient.cpp LibOVR/Src/Service/Service_NetClient.h LibOVR/Src/Service/Service_NetSessionCommon.cpp LibOVR/Src/Service/Service_NetSessionCommon.h LibOVR/Src/Tracking/Tracking_PoseState.h LibOVR/Src/Tracking/Tracking_SensorState.h LibOVR/Src/Tracking/Tracking_SensorStateReader.cpp LibOVR/Src/Tracking/Tracking_SensorStateReader.h LibOVR/Src/Util/GUIConsole.h LibOVR/Src/Util/Util_ImageWindow.h LibOVR/Src/Util/Util_Interface.cpp LibOVR/Src/Util/Util_Interface.h LibOVR/Src/Util/Util_LatencyTest2Reader.cpp LibOVR/Src/Util/Util_LatencyTest2Reader.h LibOVR/Src/Util/Util_LatencyTest2State.h LibOVR/Src/Util/Util_Render_Stereo.cpp LibOVR/Src/Util/Util_Render_Stereo.h LibOVR/Src/Util/Util_SystemGUI.cpp LibOVR/Src/Util/Util_SystemGUI.h LibOVR/Src/Util/Util_SystemInfo.cpp LibOVR/Src/Util/Util_SystemInfo.h Makefile
diffstat 146 files changed, 81669 insertions(+), 0 deletions(-) [+]
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/.hgignore	Wed Jan 14 06:51:16 2015 +0200
     1.3 @@ -0,0 +1,6 @@
     1.4 +\.o$
     1.5 +\.swp$
     1.6 +\.d$
     1.7 +^Samples/
     1.8 +^Firmware/
     1.9 +^ConfigUtil/
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/3rdParty/EDID/edid.cpp	Wed Jan 14 06:51:16 2015 +0200
     2.3 @@ -0,0 +1,446 @@
     2.4 +/*
     2.5 + * Copyright 2007 Red Hat, Inc.
     2.6 + *
     2.7 + * Permission is hereby granted, free of charge, to any person obtaining a
     2.8 + * copy of this software and associated documentation files (the "Software"),
     2.9 + * to deal in the Software without restriction, including without limitation
    2.10 + * on the rights to use, copy, modify, merge, publish, distribute, sub
    2.11 + * license, and/or sell copies of the Software, and to permit persons to whom
    2.12 + * the Software is furnished to do so, subject to the following conditions:
    2.13 + *
    2.14 + * The above copyright notice and this permission notice (including the next
    2.15 + * paragraph) shall be included in all copies or substantial portions of the
    2.16 + * Software.
    2.17 + *
    2.18 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    2.19 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    2.20 + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
    2.21 + * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
    2.22 + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
    2.23 + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    2.24 + */
    2.25 +
    2.26 +/* Author: Soren Sandmann <sandmann@redhat.com> */
    2.27 +#include "edid.h"
    2.28 +#include <stdint.h>
    2.29 +#include <math.h>
    2.30 +#include <memory.h>
    2.31 +#include <X11/Xatom.h>
    2.32 +
    2.33 +
    2.34 +static int get_bit(int in, int bit) {
    2.35 +    return (in & (1 << bit)) >> bit;
    2.36 +}
    2.37 +
    2.38 +static int get_bits(int in, int begin, int end) {
    2.39 +    int mask = (1 << (end - begin + 1)) - 1;
    2.40 +
    2.41 +    return (in >> begin) & mask;
    2.42 +}
    2.43 +
    2.44 +static bool decode_header(const uint8_t *edid) {
    2.45 +    if (memcmp(edid, "\x00\xff\xff\xff\xff\xff\xff\x00", 8) == 0)
    2.46 +        return true;
    2.47 +    return false;
    2.48 +}
    2.49 +
    2.50 +static int decode_vendor_and_product_identification(const uint8_t *edid, MonitorInfo *info) {
    2.51 +
    2.52 +    /* Manufacturer Code */
    2.53 +    info->manufacturer_code[0] = get_bits(edid[0x08], 2, 6);
    2.54 +    info->manufacturer_code[1] = get_bits(edid[0x08], 0, 1) << 3;
    2.55 +    info->manufacturer_code[1] |= get_bits(edid[0x09], 5, 7);
    2.56 +    info->manufacturer_code[2] = get_bits(edid[0x09], 0, 4);
    2.57 +    info->manufacturer_code[3] = '\0';
    2.58 +
    2.59 +    info->manufacturer_code[0] += 'A' - 1;
    2.60 +    info->manufacturer_code[1] += 'A' - 1;
    2.61 +    info->manufacturer_code[2] += 'A' - 1;
    2.62 +
    2.63 +    /* Product Code */
    2.64 +    info->product_code = edid[0x0b] << 8 | edid[0x0a];
    2.65 +
    2.66 +    /* Serial Number */
    2.67 +    info->serial_number = edid[0x0c] | edid[0x0d] << 8 | edid[0x0e] << 16 | edid[0x0f] << 24;
    2.68 +
    2.69 +    /* Week and Year */
    2.70 +    bool is_model_year = false;
    2.71 +    switch (edid[0x10]) {
    2.72 +    case 0x00:
    2.73 +        info->production_week = -1;
    2.74 +        break;
    2.75 +
    2.76 +    case 0xff:
    2.77 +        info->production_week = -1;
    2.78 +        is_model_year = true;
    2.79 +        break;
    2.80 +
    2.81 +    default:
    2.82 +        info->production_week = edid[0x10];
    2.83 +        break;
    2.84 +    }
    2.85 +
    2.86 +    if (is_model_year) {
    2.87 +        info->production_year = -1;
    2.88 +        info->model_year = 1990 + edid[0x11];
    2.89 +    } else {
    2.90 +        info->production_year = 1990 + edid[0x11];
    2.91 +        info->model_year = -1;
    2.92 +    }
    2.93 +
    2.94 +    return true;
    2.95 +}
    2.96 +
    2.97 +static bool decode_edid_version(const uint8_t *edid, MonitorInfo *info) {
    2.98 +    info->major_version = edid[0x12];
    2.99 +    info->minor_version = edid[0x13];
   2.100 +    return true;
   2.101 +}
   2.102 +
   2.103 +static bool decode_display_parameters(const uint8_t *edid, MonitorInfo *info) {
   2.104 +    /* Digital vs Analog */
   2.105 +    info->is_digital = get_bit(edid[0x14], 7);
   2.106 +
   2.107 +    if (info->is_digital) {
   2.108 +        static const int bit_depth[8] = { -1, 6, 8, 10, 12, 14, 16, -1 };
   2.109 +        static const Interface interfaces[6] = { UNDEFINED, DVI, HDMI_A, HDMI_B, MDDI, DISPLAY_PORT };
   2.110 +
   2.111 +        int bits = get_bits(edid[0x14], 4, 6);
   2.112 +        info->connector.digital.bits_per_primary = bit_depth[bits];
   2.113 +
   2.114 +        bits = get_bits(edid[0x14], 0, 3);
   2.115 +        if (bits <= 5)
   2.116 +            info->connector.digital.interface = interfaces[bits];
   2.117 +        else
   2.118 +            info->connector.digital.interface = UNDEFINED;
   2.119 +    } else {
   2.120 +        int bits = get_bits(edid[0x14], 5, 6);
   2.121 +        static const double levels[][3] = { //
   2.122 +                { 0.7, 0.3, 1.0 }, //
   2.123 +                { 0.714, 0.286, 1.0 }, //
   2.124 +                { 1.0, 0.4, 1.4 }, //
   2.125 +                { 0.7, 0.0, 0.7 }, //
   2.126 +                };
   2.127 +
   2.128 +        info->connector.analog.video_signal_level = levels[bits][0];
   2.129 +        info->connector.analog.sync_signal_level = levels[bits][1];
   2.130 +        info->connector.analog.total_signal_level = levels[bits][2];
   2.131 +        info->connector.analog.blank_to_black = get_bit(edid[0x14], 4);
   2.132 +        info->connector.analog.separate_hv_sync = get_bit(edid[0x14], 3);
   2.133 +        info->connector.analog.composite_sync_on_h = get_bit(edid[0x14], 2);
   2.134 +        info->connector.analog.composite_sync_on_green = get_bit(edid[0x14], 1);
   2.135 +        info->connector.analog.serration_on_vsync = get_bit(edid[0x14], 0);
   2.136 +    }
   2.137 +
   2.138 +    /* Screen Size / Aspect Ratio */
   2.139 +    if (edid[0x15] == 0 && edid[0x16] == 0) {
   2.140 +        info->width_mm = -1;
   2.141 +        info->height_mm = -1;
   2.142 +        info->aspect_ratio = -1.0;
   2.143 +    } else if (edid[0x16] == 0) {
   2.144 +        info->width_mm = -1;
   2.145 +        info->height_mm = -1;
   2.146 +        info->aspect_ratio = 100.0 / (edid[0x15] + 99);
   2.147 +    } else if (edid[0x15] == 0) {
   2.148 +        info->width_mm = -1;
   2.149 +        info->height_mm = -1;
   2.150 +        info->aspect_ratio = 100.0 / (edid[0x16] + 99);
   2.151 +        info->aspect_ratio = 1 / info->aspect_ratio; /* portrait */
   2.152 +    } else {
   2.153 +        info->width_mm = 10 * edid[0x15];
   2.154 +        info->height_mm = 10 * edid[0x16];
   2.155 +    }
   2.156 +
   2.157 +    /* Gamma */
   2.158 +    if (edid[0x17] == 0xFF)
   2.159 +        info->gamma = -1.0;
   2.160 +    else
   2.161 +        info->gamma = (edid[0x17] + 100.0) / 100.0;
   2.162 +
   2.163 +    /* Features */
   2.164 +    info->standby = get_bit(edid[0x18], 7);
   2.165 +    info->suspend = get_bit(edid[0x18], 6);
   2.166 +    info->active_off = get_bit(edid[0x18], 5);
   2.167 +
   2.168 +    if (info->is_digital) {
   2.169 +        info->connector.digital.rgb444 = 1;
   2.170 +        if (get_bit(edid[0x18], 3))
   2.171 +            info->connector.digital.ycrcb444 = 1;
   2.172 +        if (get_bit(edid[0x18], 4))
   2.173 +            info->connector.digital.ycrcb422 = 1;
   2.174 +    } else {
   2.175 +        int bits = get_bits(edid[0x18], 3, 4);
   2.176 +        ColorType color_type[4] = { MONOCHROME, RGB, OTHER_COLOR, UNDEFINED_COLOR };
   2.177 +
   2.178 +        info->connector.analog.color_type = color_type[bits];
   2.179 +    }
   2.180 +
   2.181 +    info->srgb_is_standard = get_bit(edid[0x18], 2);
   2.182 +
   2.183 +    /* In 1.3 this is called "has preferred timing" */
   2.184 +    info->preferred_timing_includes_native = get_bit(edid[0x18], 1);
   2.185 +
   2.186 +    /* FIXME: In 1.3 this indicates whether the monitor accepts GTF */
   2.187 +    info->continuous_frequency = get_bit(edid[0x18], 0);
   2.188 +    return true;
   2.189 +}
   2.190 +
   2.191 +static double decode_fraction(int high, int low) {
   2.192 +    double result = 0.0;
   2.193 +    high = (high << 2) | low;
   2.194 +    for (int i = 0; i < 10; ++i)
   2.195 +        result += get_bit(high, i) * pow(2, i - 10);
   2.196 +    return result;
   2.197 +}
   2.198 +
   2.199 +static bool decode_color_characteristics(const uint8_t *edid, MonitorInfo *info) {
   2.200 +    info->red_x = decode_fraction(edid[0x1b], get_bits(edid[0x19], 6, 7));
   2.201 +    info->red_y = decode_fraction(edid[0x1c], get_bits(edid[0x19], 5, 4));
   2.202 +    info->green_x = decode_fraction(edid[0x1d], get_bits(edid[0x19], 2, 3));
   2.203 +    info->green_y = decode_fraction(edid[0x1e], get_bits(edid[0x19], 0, 1));
   2.204 +    info->blue_x = decode_fraction(edid[0x1f], get_bits(edid[0x1a], 6, 7));
   2.205 +    info->blue_y = decode_fraction(edid[0x20], get_bits(edid[0x1a], 4, 5));
   2.206 +    info->white_x = decode_fraction(edid[0x21], get_bits(edid[0x1a], 2, 3));
   2.207 +    info->white_y = decode_fraction(edid[0x22], get_bits(edid[0x1a], 0, 1));
   2.208 +
   2.209 +    return true;
   2.210 +}
   2.211 +
   2.212 +static bool decode_established_timings(const uint8_t *edid, MonitorInfo *info) {
   2.213 +    static const Timing established[][8] = { //
   2.214 +            { { 800, 600, 60 }, { 800, 600, 56 }, //
   2.215 +              { 640, 480, 75 }, { 640, 480, 72 }, //
   2.216 +              { 640, 480, 67 }, { 640, 480, 60 }, //
   2.217 +              { 720, 400, 88 }, { 720, 400, 70 } }, //
   2.218 +            { { 1280, 1024, 75 }, { 1024, 768, 75 }, //
   2.219 +              { 1024, 768, 70 }, { 1024, 768, 60 }, //
   2.220 +              { 1024, 768, 87 }, { 832, 624, 75 }, //
   2.221 +              { 800, 600, 75 }, { 800, 600, 72 } }, //
   2.222 +            { { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, //
   2.223 +              { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 1152, 870, 75 } }, //
   2.224 +            };
   2.225 +
   2.226 +    int idx = 0;
   2.227 +    for (int i = 0; i < 3; ++i) {
   2.228 +        for (int j = 0; j < 8; ++j) {
   2.229 +            int byte = edid[0x23 + i];
   2.230 +
   2.231 +            if (get_bit(byte, j) && established[i][j].frequency != 0)
   2.232 +                info->established[idx++] = established[i][j];
   2.233 +        }
   2.234 +    }
   2.235 +    return true;
   2.236 +}
   2.237 +
   2.238 +static bool decode_standard_timings(const uint8_t *edid, MonitorInfo *info) {
   2.239 +    int i;
   2.240 +
   2.241 +    for (i = 0; i < 8; i++) {
   2.242 +        int first = edid[0x26 + 2 * i];
   2.243 +        int second = edid[0x27 + 2 * i];
   2.244 +
   2.245 +        if (first != 0x01 && second != 0x01) {
   2.246 +            int w = 8 * (first + 31);
   2.247 +            int h = 0;
   2.248 +
   2.249 +            switch (get_bits(second, 6, 7)) {
   2.250 +            case 0x00:
   2.251 +                h = (w / 16) * 10;
   2.252 +                break;
   2.253 +            case 0x01:
   2.254 +                h = (w / 4) * 3;
   2.255 +                break;
   2.256 +            case 0x02:
   2.257 +                h = (w / 5) * 4;
   2.258 +                break;
   2.259 +            case 0x03:
   2.260 +                h = (w / 16) * 9;
   2.261 +                break;
   2.262 +            }
   2.263 +
   2.264 +            info->standard[i].width = w;
   2.265 +            info->standard[i].height = h;
   2.266 +            info->standard[i].frequency = get_bits(second, 0, 5) + 60;
   2.267 +        }
   2.268 +    }
   2.269 +
   2.270 +    return true;
   2.271 +}
   2.272 +
   2.273 +static void decode_lf_string(const uint8_t *s, int n_chars, char *result) {
   2.274 +    int i;
   2.275 +    for (i = 0; i < n_chars; ++i) {
   2.276 +        if (s[i] == 0x0a) {
   2.277 +            *result++ = '\0';
   2.278 +            break;
   2.279 +        } else if (s[i] == 0x00) {
   2.280 +            /* Convert embedded 0's to spaces */
   2.281 +            *result++ = ' ';
   2.282 +        } else {
   2.283 +            *result++ = s[i];
   2.284 +        }
   2.285 +    }
   2.286 +}
   2.287 +
   2.288 +static void decode_display_descriptor(const uint8_t *desc, MonitorInfo *info) {
   2.289 +    switch (desc[0x03]) {
   2.290 +    case 0xFC:
   2.291 +        decode_lf_string(desc + 5, 13, info->dsc_product_name);
   2.292 +        break;
   2.293 +    case 0xFF:
   2.294 +        decode_lf_string(desc + 5, 13, info->dsc_serial_number);
   2.295 +        break;
   2.296 +    case 0xFE:
   2.297 +        decode_lf_string(desc + 5, 13, info->dsc_string);
   2.298 +        break;
   2.299 +    case 0xFD:
   2.300 +        /* Range Limits */
   2.301 +        break;
   2.302 +    case 0xFB:
   2.303 +        /* Color Point */
   2.304 +        break;
   2.305 +    case 0xFA:
   2.306 +        /* Timing Identifications */
   2.307 +        break;
   2.308 +    case 0xF9:
   2.309 +        /* Color Management */
   2.310 +        break;
   2.311 +    case 0xF8:
   2.312 +        /* Timing Codes */
   2.313 +        break;
   2.314 +    case 0xF7:
   2.315 +        /* Established Timings */
   2.316 +        break;
   2.317 +    case 0x10:
   2.318 +        break;
   2.319 +    }
   2.320 +}
   2.321 +
   2.322 +static void decode_detailed_timing(const uint8_t *timing, DetailedTiming *detailed) {
   2.323 +    int bits;
   2.324 +    StereoType stereo[] = { //
   2.325 +            NO_STEREO, NO_STEREO, //
   2.326 +            FIELD_RIGHT, FIELD_LEFT, //
   2.327 +            TWO_WAY_RIGHT_ON_EVEN, TWO_WAY_LEFT_ON_EVEN, //
   2.328 +            FOUR_WAY_INTERLEAVED, //
   2.329 +            SIDE_BY_SIDE //
   2.330 +            };
   2.331 +
   2.332 +    detailed->pixel_clock = (timing[0x00] | timing[0x01] << 8) * 10000;
   2.333 +    detailed->h_addr = timing[0x02] | ((timing[0x04] & 0xf0) << 4);
   2.334 +    detailed->h_blank = timing[0x03] | ((timing[0x04] & 0x0f) << 8);
   2.335 +    detailed->v_addr = timing[0x05] | ((timing[0x07] & 0xf0) << 4);
   2.336 +    detailed->v_blank = timing[0x06] | ((timing[0x07] & 0x0f) << 8);
   2.337 +    detailed->h_front_porch = timing[0x08] | get_bits(timing[0x0b], 6, 7) << 8;
   2.338 +    detailed->h_sync = timing[0x09] | get_bits(timing[0x0b], 4, 5) << 8;
   2.339 +    detailed->v_front_porch = get_bits(timing[0x0a], 4, 7) | get_bits(timing[0x0b], 2, 3) << 4;
   2.340 +    detailed->v_sync = get_bits(timing[0x0a], 0, 3) | get_bits(timing[0x0b], 0, 1) << 4;
   2.341 +    detailed->width_mm = timing[0x0c] | get_bits(timing[0x0e], 4, 7) << 8;
   2.342 +    detailed->height_mm = timing[0x0d] | get_bits(timing[0x0e], 0, 3) << 8;
   2.343 +    detailed->right_border = timing[0x0f];
   2.344 +    detailed->top_border = timing[0x10];
   2.345 +    detailed->interlaced = get_bit(timing[0x11], 7);
   2.346 +
   2.347 +    /* Stereo */
   2.348 +    bits = get_bits(timing[0x11], 5, 6) << 1 | get_bit(timing[0x11], 0);
   2.349 +    detailed->stereo = stereo[bits];
   2.350 +
   2.351 +    /* Sync */
   2.352 +    bits = timing[0x11];
   2.353 +
   2.354 +    detailed->digital_sync = get_bit(bits, 4);
   2.355 +    if (detailed->digital_sync) {
   2.356 +        detailed->connector.digital.composite = !get_bit(bits, 3);
   2.357 +        if (detailed->connector.digital.composite) {
   2.358 +            detailed->connector.digital.serrations = get_bit(bits, 2);
   2.359 +            detailed->connector.digital.negative_vsync = 0;
   2.360 +        } else {
   2.361 +            detailed->connector.digital.serrations = 0;
   2.362 +            detailed->connector.digital.negative_vsync = !get_bit(bits, 2);
   2.363 +        }
   2.364 +        detailed->connector.digital.negative_hsync = !get_bit(bits, 0);
   2.365 +    } else {
   2.366 +        detailed->connector.analog.bipolar = get_bit(bits, 3);
   2.367 +        detailed->connector.analog.serrations = get_bit(bits, 2);
   2.368 +        detailed->connector.analog.sync_on_green = !get_bit(bits, 1);
   2.369 +    }
   2.370 +}
   2.371 +
   2.372 +static bool decode_descriptors(const uint8_t *edid, MonitorInfo *info) {
   2.373 +    int timing_idx = 0;
   2.374 +    for (int i = 0; i < 4; ++i) {
   2.375 +        int index = 0x36 + i * 18;
   2.376 +        if (edid[index + 0] == 0x00 && edid[index + 1] == 0x00) {
   2.377 +            decode_display_descriptor(edid + index, info);
   2.378 +        } else {
   2.379 +            decode_detailed_timing(edid + index, &(info->detailed_timings[timing_idx++]));
   2.380 +        }
   2.381 +    }
   2.382 +    info->n_detailed_timings = timing_idx;
   2.383 +    return true;
   2.384 +}
   2.385 +
   2.386 +static void decode_check_sum(const uint8_t *edid, MonitorInfo *info) {
   2.387 +    uint8_t check = 0;
   2.388 +    for (int i = 0; i < 128; ++i)
   2.389 +        check += edid[i];
   2.390 +    info->checksum = check;
   2.391 +}
   2.392 +
   2.393 +MonitorInfo * decode_edid(const uint8_t *edid) {
   2.394 +    MonitorInfo *info = new MonitorInfo();
   2.395 +    decode_check_sum(edid, info);
   2.396 +    if (decode_header(edid) && //
   2.397 +            decode_vendor_and_product_identification(edid, info) && //
   2.398 +            decode_edid_version(edid, info) && //
   2.399 +            decode_display_parameters(edid, info) && //
   2.400 +            decode_color_characteristics(edid, info) && //
   2.401 +            decode_established_timings(edid, info) && //
   2.402 +            decode_standard_timings(edid, info) && //
   2.403 +            decode_descriptors(edid, info)) {
   2.404 +        return info;
   2.405 +    } else {
   2.406 +        delete info;
   2.407 +        return 0;
   2.408 +    }
   2.409 +}
   2.410 +
   2.411 +static uint8_t * get_property(Display *dpy, RROutput output, Atom atom, int *len) {
   2.412 +    unsigned char *prop;
   2.413 +    int actual_format;
   2.414 +    unsigned long nitems, bytes_after;
   2.415 +    Atom actual_type;
   2.416 +    uint8_t *result = NULL;
   2.417 +
   2.418 +    XRRGetOutputProperty(dpy, output, atom, 0, 100, False, False,
   2.419 +    AnyPropertyType, &actual_type, &actual_format, &nitems, &bytes_after, &prop);
   2.420 +
   2.421 +    if (actual_type == XA_INTEGER && actual_format == 8) {
   2.422 +        result = new uint8_t[nitems];
   2.423 +        memcpy(result, prop, nitems);
   2.424 +        if (len)
   2.425 +            *len = nitems;
   2.426 +    }
   2.427 +    XFree(prop);
   2.428 +    return result;
   2.429 +}
   2.430 +
   2.431 +MonitorInfo * read_edid_data(Display * disp, RROutput id) {
   2.432 +    int len;
   2.433 +    Atom edid_atom = XInternAtom(disp, "EDID", false);
   2.434 +    uint8_t *edid = get_property(disp, id, edid_atom, &len);
   2.435 +    if (!edid) {
   2.436 +        edid_atom = XInternAtom(disp, "EDID_DATA", false);
   2.437 +        edid = get_property(disp, id, edid_atom, &len);
   2.438 +    }
   2.439 +
   2.440 +    MonitorInfo * result = 0;
   2.441 +    if (edid) {
   2.442 +        if (len % 128 == 0) {
   2.443 +            result = decode_edid(edid);
   2.444 +        }
   2.445 +        delete[] edid;
   2.446 +    }
   2.447 +
   2.448 +    return result;
   2.449 +}
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/3rdParty/EDID/edid.h	Wed Jan 14 06:51:16 2015 +0200
     3.3 @@ -0,0 +1,174 @@
     3.4 +#include <X11/extensions/Xrandr.h>
     3.5 +#include <X11/Xlib.h>
     3.6 +
     3.7 +/*
     3.8 + * Copyright 2007 Red Hat, Inc.
     3.9 + *
    3.10 + * Permission is hereby granted, free of charge, to any person obtaining a
    3.11 + * copy of this software and associated documentation files (the "Software"),
    3.12 + * to deal in the Software without restriction, including without limitation
    3.13 + * on the rights to use, copy, modify, merge, publish, distribute, sub
    3.14 + * license, and/or sell copies of the Software, and to permit persons to whom
    3.15 + * the Software is furnished to do so, subject to the following conditions:
    3.16 + *
    3.17 + * The above copyright notice and this permission notice (including the next
    3.18 + * paragraph) shall be included in all copies or substantial portions of the
    3.19 + * Software.
    3.20 + *
    3.21 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    3.22 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    3.23 + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
    3.24 + * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
    3.25 + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
    3.26 + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    3.27 + */
    3.28 +
    3.29 +/* Author: Soren Sandmann <sandmann@redhat.com> */
    3.30 +
    3.31 +typedef enum {
    3.32 +    UNDEFINED,
    3.33 +    DVI,
    3.34 +    HDMI_A,
    3.35 +    HDMI_B,
    3.36 +    MDDI,
    3.37 +    DISPLAY_PORT
    3.38 +} Interface;
    3.39 +
    3.40 +typedef enum {
    3.41 +    UNDEFINED_COLOR,
    3.42 +    MONOCHROME,
    3.43 +    RGB,
    3.44 +    OTHER_COLOR
    3.45 +} ColorType;
    3.46 +
    3.47 +typedef enum {
    3.48 +    NO_STEREO,
    3.49 +    FIELD_RIGHT,
    3.50 +    FIELD_LEFT,
    3.51 +    TWO_WAY_RIGHT_ON_EVEN,
    3.52 +    TWO_WAY_LEFT_ON_EVEN,
    3.53 +    FOUR_WAY_INTERLEAVED,
    3.54 +    SIDE_BY_SIDE
    3.55 +} StereoType;
    3.56 +
    3.57 +struct Timing {
    3.58 +    int width;
    3.59 +    int height;
    3.60 +    int frequency;
    3.61 +};
    3.62 +
    3.63 +struct DetailedTiming {
    3.64 +    int pixel_clock;
    3.65 +    int h_addr;
    3.66 +    int h_blank;
    3.67 +    int h_sync;
    3.68 +    int h_front_porch;
    3.69 +    int v_addr;
    3.70 +    int v_blank;
    3.71 +    int v_sync;
    3.72 +    int v_front_porch;
    3.73 +    int width_mm;
    3.74 +    int height_mm;
    3.75 +    int right_border;
    3.76 +    int top_border;
    3.77 +    int interlaced;
    3.78 +    StereoType stereo;
    3.79 +
    3.80 +    int digital_sync;
    3.81 +    union {
    3.82 +        struct {
    3.83 +            int bipolar;
    3.84 +            int serrations;
    3.85 +            int sync_on_green;
    3.86 +        } analog;
    3.87 +
    3.88 +        struct {
    3.89 +            int composite;
    3.90 +            int serrations;
    3.91 +            int negative_vsync;
    3.92 +            int negative_hsync;
    3.93 +        } digital;
    3.94 +    } connector;
    3.95 +};
    3.96 +
    3.97 +struct MonitorInfo {
    3.98 +    int checksum;
    3.99 +    char manufacturer_code[4];
   3.100 +    int product_code;
   3.101 +    unsigned int serial_number;
   3.102 +
   3.103 +    int production_week; /* -1 if not specified */
   3.104 +    int production_year; /* -1 if not specified */
   3.105 +    int model_year; /* -1 if not specified */
   3.106 +
   3.107 +    int major_version;
   3.108 +    int minor_version;
   3.109 +
   3.110 +    int is_digital;
   3.111 +
   3.112 +    union {
   3.113 +        struct {
   3.114 +            int bits_per_primary;
   3.115 +            Interface interface;
   3.116 +            int rgb444;
   3.117 +            int ycrcb444;
   3.118 +            int ycrcb422;
   3.119 +        } digital;
   3.120 +
   3.121 +        struct {
   3.122 +            double video_signal_level;
   3.123 +            double sync_signal_level;
   3.124 +            double total_signal_level;
   3.125 +
   3.126 +            int blank_to_black;
   3.127 +
   3.128 +            int separate_hv_sync;
   3.129 +            int composite_sync_on_h;
   3.130 +            int composite_sync_on_green;
   3.131 +            int serration_on_vsync;
   3.132 +            ColorType color_type;
   3.133 +        } analog;
   3.134 +    } connector;
   3.135 +
   3.136 +    int width_mm; /* -1 if not specified */
   3.137 +    int height_mm; /* -1 if not specified */
   3.138 +    double aspect_ratio; /* -1.0 if not specififed */
   3.139 +
   3.140 +    double gamma; /* -1.0 if not specified */
   3.141 +
   3.142 +    int standby;
   3.143 +    int suspend;
   3.144 +    int active_off;
   3.145 +
   3.146 +    int srgb_is_standard;
   3.147 +    int preferred_timing_includes_native;
   3.148 +    int continuous_frequency;
   3.149 +
   3.150 +    double red_x;
   3.151 +    double red_y;
   3.152 +    double green_x;
   3.153 +    double green_y;
   3.154 +    double blue_x;
   3.155 +    double blue_y;
   3.156 +    double white_x;
   3.157 +    double white_y;
   3.158 +
   3.159 +    Timing established[24]; /* Terminated by 0x0x0 */
   3.160 +    Timing standard[8];
   3.161 +
   3.162 +    int n_detailed_timings;
   3.163 +    DetailedTiming detailed_timings[4]; /* If monitor has a preferred
   3.164 +     * mode, it is the first one
   3.165 +     * (whether it has, is
   3.166 +     * determined by the
   3.167 +     * preferred_timing_includes
   3.168 +     * bit.
   3.169 +     */
   3.170 +
   3.171 +    /* Optional product description */
   3.172 +    char dsc_serial_number[14];
   3.173 +    char dsc_product_name[14];
   3.174 +    char dsc_string[14]; /* Unspecified ASCII data */
   3.175 +};
   3.176 +
   3.177 +MonitorInfo * read_edid_data(Display * disp, RROutput id);
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/3rdParty/TinyXml/tinyxml2.cpp	Wed Jan 14 06:51:16 2015 +0200
     4.3 @@ -0,0 +1,2101 @@
     4.4 +/*
     4.5 +Original code by Lee Thomason (www.grinninglizard.com)
     4.6 +
     4.7 +This software is provided 'as-is', without any express or implied
     4.8 +warranty. In no event will the authors be held liable for any
     4.9 +damages arising from the use of this software.
    4.10 +
    4.11 +Permission is granted to anyone to use this software for any
    4.12 +purpose, including commercial applications, and to alter it and
    4.13 +redistribute it freely, subject to the following restrictions:
    4.14 +
    4.15 +1. The origin of this software must not be misrepresented; you must
    4.16 +not claim that you wrote the original software. If you use this
    4.17 +software in a product, an acknowledgment in the product documentation
    4.18 +would be appreciated but is not required.
    4.19 +
    4.20 +2. Altered source versions must be plainly marked as such, and
    4.21 +must not be misrepresented as being the original software.
    4.22 +
    4.23 +3. This notice may not be removed or altered from any source
    4.24 +distribution.
    4.25 +*/
    4.26 +
    4.27 +#include "tinyxml2.h"
    4.28 +
    4.29 +#include <new>		// yes, this one new style header, is in the Android SDK.
    4.30 +#   ifdef ANDROID_NDK
    4.31 +#   include <stddef.h>
    4.32 +#else
    4.33 +#   include <cstddef>
    4.34 +#endif
    4.35 +
    4.36 +static const char LINE_FEED				= (char)0x0a;			// all line endings are normalized to LF
    4.37 +static const char LF = LINE_FEED;
    4.38 +static const char CARRIAGE_RETURN		= (char)0x0d;			// CR gets filtered out
    4.39 +static const char CR = CARRIAGE_RETURN;
    4.40 +static const char SINGLE_QUOTE			= '\'';
    4.41 +static const char DOUBLE_QUOTE			= '\"';
    4.42 +
    4.43 +// Bunch of unicode info at:
    4.44 +//		http://www.unicode.org/faq/utf_bom.html
    4.45 +//	ef bb bf (Microsoft "lead bytes") - designates UTF-8
    4.46 +
    4.47 +static const unsigned char TIXML_UTF_LEAD_0 = 0xefU;
    4.48 +static const unsigned char TIXML_UTF_LEAD_1 = 0xbbU;
    4.49 +static const unsigned char TIXML_UTF_LEAD_2 = 0xbfU;
    4.50 +
    4.51 +
    4.52 +#define DELETE_NODE( node )	{			\
    4.53 +        if ( node ) {						\
    4.54 +            MemPool* pool = node->_memPool;	\
    4.55 +            node->~XMLNode();				\
    4.56 +            pool->Free( node );				\
    4.57 +        }									\
    4.58 +    }
    4.59 +#define DELETE_ATTRIBUTE( attrib ) {		\
    4.60 +        if ( attrib ) {							\
    4.61 +            MemPool* pool = attrib->_memPool;	\
    4.62 +            attrib->~XMLAttribute();			\
    4.63 +            pool->Free( attrib );				\
    4.64 +        }										\
    4.65 +    }
    4.66 +
    4.67 +namespace tinyxml2
    4.68 +{
    4.69 +
    4.70 +struct Entity {
    4.71 +    const char* pattern;
    4.72 +    int length;
    4.73 +    char value;
    4.74 +};
    4.75 +
    4.76 +static const int NUM_ENTITIES = 5;
    4.77 +static const Entity entities[NUM_ENTITIES] = {
    4.78 +    { "quot", 4,	DOUBLE_QUOTE },
    4.79 +    { "amp", 3,		'&'  },
    4.80 +    { "apos", 4,	SINGLE_QUOTE },
    4.81 +    { "lt",	2, 		'<'	 },
    4.82 +    { "gt",	2,		'>'	 }
    4.83 +};
    4.84 +
    4.85 +
    4.86 +StrPair::~StrPair()
    4.87 +{
    4.88 +    Reset();
    4.89 +}
    4.90 +
    4.91 +
    4.92 +void StrPair::Reset()
    4.93 +{
    4.94 +    if ( _flags & NEEDS_DELETE ) {
    4.95 +        delete [] _start;
    4.96 +    }
    4.97 +    _flags = 0;
    4.98 +    _start = 0;
    4.99 +    _end = 0;
   4.100 +}
   4.101 +
   4.102 +
   4.103 +void StrPair::SetStr( const char* str, int flags )
   4.104 +{
   4.105 +    Reset();
   4.106 +    size_t len = strlen( str );
   4.107 +    _start = new char[ len+1 ];
   4.108 +    memcpy( _start, str, len+1 );
   4.109 +    _end = _start + len;
   4.110 +    _flags = flags | NEEDS_DELETE;
   4.111 +}
   4.112 +
   4.113 +
   4.114 +char* StrPair::ParseText( char* p, const char* endTag, int strFlags )
   4.115 +{
   4.116 +    TIXMLASSERT( endTag && *endTag );
   4.117 +
   4.118 +    char* start = p;	// fixme: hides a member
   4.119 +    char  endChar = *endTag;
   4.120 +    size_t length = strlen( endTag );
   4.121 +
   4.122 +    // Inner loop of text parsing.
   4.123 +    while ( *p ) {
   4.124 +        if ( *p == endChar && strncmp( p, endTag, length ) == 0 ) {
   4.125 +            Set( start, p, strFlags );
   4.126 +            return p + length;
   4.127 +        }
   4.128 +        ++p;
   4.129 +    }
   4.130 +    return 0;
   4.131 +}
   4.132 +
   4.133 +
   4.134 +char* StrPair::ParseName( char* p )
   4.135 +{
   4.136 +    char* start = p;
   4.137 +
   4.138 +    if ( !start || !(*start) ) {
   4.139 +        return 0;
   4.140 +    }
   4.141 +
   4.142 +    while( *p && (
   4.143 +                XMLUtil::IsAlphaNum( (unsigned char) *p )
   4.144 +                || *p == '_'
   4.145 +                || *p == ':'
   4.146 +                || (*p == '-' && p>start )		// can be in a name, but not lead it.
   4.147 +                || (*p == '.' && p>start ) )) {	// can be in a name, but not lead it.
   4.148 +        ++p;
   4.149 +    }
   4.150 +
   4.151 +    if ( p > start ) {
   4.152 +        Set( start, p, 0 );
   4.153 +        return p;
   4.154 +    }
   4.155 +    return 0;
   4.156 +}
   4.157 +
   4.158 +
   4.159 +void StrPair::CollapseWhitespace()
   4.160 +{
   4.161 +    // Trim leading space.
   4.162 +    _start = XMLUtil::SkipWhiteSpace( _start );
   4.163 +
   4.164 +    if ( _start && *_start ) {
   4.165 +        char* p = _start;	// the read pointer
   4.166 +        char* q = _start;	// the write pointer
   4.167 +
   4.168 +        while( *p ) {
   4.169 +            if ( XMLUtil::IsWhiteSpace( *p )) {
   4.170 +                p = XMLUtil::SkipWhiteSpace( p );
   4.171 +                if ( *p == 0 ) {
   4.172 +                    break;    // don't write to q; this trims the trailing space.
   4.173 +                }
   4.174 +                *q = ' ';
   4.175 +                ++q;
   4.176 +            }
   4.177 +            *q = *p;
   4.178 +            ++q;
   4.179 +            ++p;
   4.180 +        }
   4.181 +        *q = 0;
   4.182 +    }
   4.183 +}
   4.184 +
   4.185 +
   4.186 +const char* StrPair::GetStr()
   4.187 +{
   4.188 +    if ( _flags & NEEDS_FLUSH ) {
   4.189 +        *_end = 0;
   4.190 +        _flags ^= NEEDS_FLUSH;
   4.191 +
   4.192 +        if ( _flags ) {
   4.193 +            char* p = _start;	// the read pointer
   4.194 +            char* q = _start;	// the write pointer
   4.195 +
   4.196 +            while( p < _end ) {
   4.197 +                if ( (_flags & NEEDS_NEWLINE_NORMALIZATION) && *p == CR ) {
   4.198 +                    // CR-LF pair becomes LF
   4.199 +                    // CR alone becomes LF
   4.200 +                    // LF-CR becomes LF
   4.201 +                    if ( *(p+1) == LF ) {
   4.202 +                        p += 2;
   4.203 +                    }
   4.204 +                    else {
   4.205 +                        ++p;
   4.206 +                    }
   4.207 +                    *q++ = LF;
   4.208 +                }
   4.209 +                else if ( (_flags & NEEDS_NEWLINE_NORMALIZATION) && *p == LF ) {
   4.210 +                    if ( *(p+1) == CR ) {
   4.211 +                        p += 2;
   4.212 +                    }
   4.213 +                    else {
   4.214 +                        ++p;
   4.215 +                    }
   4.216 +                    *q++ = LF;
   4.217 +                }
   4.218 +                else if ( (_flags & NEEDS_ENTITY_PROCESSING) && *p == '&' ) {
   4.219 +                    // Entities handled by tinyXML2:
   4.220 +                    // - special entities in the entity table [in/out]
   4.221 +                    // - numeric character reference [in]
   4.222 +                    //   &#20013; or &#x4e2d;
   4.223 +
   4.224 +                    if ( *(p+1) == '#' ) {
   4.225 +                        char buf[10] = { 0 };
   4.226 +                        int len;
   4.227 +                        p = const_cast<char*>( XMLUtil::GetCharacterRef( p, buf, &len ) );
   4.228 +                        for( int i=0; i<len; ++i ) {
   4.229 +                            *q++ = buf[i];
   4.230 +                        }
   4.231 +                        TIXMLASSERT( q <= p );
   4.232 +                    }
   4.233 +                    else {
   4.234 +                        int i=0;
   4.235 +                        for(; i<NUM_ENTITIES; ++i ) {
   4.236 +                            if (    strncmp( p+1, entities[i].pattern, entities[i].length ) == 0
   4.237 +                                    && *(p+entities[i].length+1) == ';' ) {
   4.238 +                                // Found an entity convert;
   4.239 +                                *q = entities[i].value;
   4.240 +                                ++q;
   4.241 +                                p += entities[i].length + 2;
   4.242 +                                break;
   4.243 +                            }
   4.244 +                        }
   4.245 +                        if ( i == NUM_ENTITIES ) {
   4.246 +                            // fixme: treat as error?
   4.247 +                            ++p;
   4.248 +                            ++q;
   4.249 +                        }
   4.250 +                    }
   4.251 +                }
   4.252 +                else {
   4.253 +                    *q = *p;
   4.254 +                    ++p;
   4.255 +                    ++q;
   4.256 +                }
   4.257 +            }
   4.258 +            *q = 0;
   4.259 +        }
   4.260 +        // The loop below has plenty going on, and this
   4.261 +        // is a less useful mode. Break it out.
   4.262 +        if ( _flags & COLLAPSE_WHITESPACE ) {
   4.263 +            CollapseWhitespace();
   4.264 +        }
   4.265 +        _flags = (_flags & NEEDS_DELETE);
   4.266 +    }
   4.267 +    return _start;
   4.268 +}
   4.269 +
   4.270 +
   4.271 +
   4.272 +
   4.273 +// --------- XMLUtil ----------- //
   4.274 +
   4.275 +const char* XMLUtil::ReadBOM( const char* p, bool* bom )
   4.276 +{
   4.277 +    *bom = false;
   4.278 +    const unsigned char* pu = reinterpret_cast<const unsigned char*>(p);
   4.279 +    // Check for BOM:
   4.280 +    if (    *(pu+0) == TIXML_UTF_LEAD_0
   4.281 +            && *(pu+1) == TIXML_UTF_LEAD_1
   4.282 +            && *(pu+2) == TIXML_UTF_LEAD_2 ) {
   4.283 +        *bom = true;
   4.284 +        p += 3;
   4.285 +    }
   4.286 +    return p;
   4.287 +}
   4.288 +
   4.289 +
   4.290 +void XMLUtil::ConvertUTF32ToUTF8( unsigned long input, char* output, int* length )
   4.291 +{
   4.292 +    const unsigned long BYTE_MASK = 0xBF;
   4.293 +    const unsigned long BYTE_MARK = 0x80;
   4.294 +    const unsigned long FIRST_BYTE_MARK[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
   4.295 +
   4.296 +    if (input < 0x80) {
   4.297 +        *length = 1;
   4.298 +    }
   4.299 +    else if ( input < 0x800 ) {
   4.300 +        *length = 2;
   4.301 +    }
   4.302 +    else if ( input < 0x10000 ) {
   4.303 +        *length = 3;
   4.304 +    }
   4.305 +    else if ( input < 0x200000 ) {
   4.306 +        *length = 4;
   4.307 +    }
   4.308 +    else {
   4.309 +        *length = 0;    // This code won't covert this correctly anyway.
   4.310 +        return;
   4.311 +    }
   4.312 +
   4.313 +    output += *length;
   4.314 +
   4.315 +    // Scary scary fall throughs.
   4.316 +    switch (*length) {
   4.317 +        case 4:
   4.318 +            --output;
   4.319 +            *output = (char)((input | BYTE_MARK) & BYTE_MASK);
   4.320 +            input >>= 6;
   4.321 +        case 3:
   4.322 +            --output;
   4.323 +            *output = (char)((input | BYTE_MARK) & BYTE_MASK);
   4.324 +            input >>= 6;
   4.325 +        case 2:
   4.326 +            --output;
   4.327 +            *output = (char)((input | BYTE_MARK) & BYTE_MASK);
   4.328 +            input >>= 6;
   4.329 +        case 1:
   4.330 +            --output;
   4.331 +            *output = (char)(input | FIRST_BYTE_MARK[*length]);
   4.332 +        default:
   4.333 +            break;
   4.334 +    }
   4.335 +}
   4.336 +
   4.337 +
   4.338 +const char* XMLUtil::GetCharacterRef( const char* p, char* value, int* length )
   4.339 +{
   4.340 +    // Presume an entity, and pull it out.
   4.341 +    *length = 0;
   4.342 +
   4.343 +    if ( *(p+1) == '#' && *(p+2) ) {
   4.344 +        unsigned long ucs = 0;
   4.345 +        ptrdiff_t delta = 0;
   4.346 +        unsigned mult = 1;
   4.347 +
   4.348 +        if ( *(p+2) == 'x' ) {
   4.349 +            // Hexadecimal.
   4.350 +            if ( !*(p+3) ) {
   4.351 +                return 0;
   4.352 +            }
   4.353 +
   4.354 +            const char* q = p+3;
   4.355 +            q = strchr( q, ';' );
   4.356 +
   4.357 +            if ( !q || !*q ) {
   4.358 +                return 0;
   4.359 +            }
   4.360 +
   4.361 +            delta = q-p;
   4.362 +            --q;
   4.363 +
   4.364 +            while ( *q != 'x' ) {
   4.365 +                if ( *q >= '0' && *q <= '9' ) {
   4.366 +                    ucs += mult * (*q - '0');
   4.367 +                }
   4.368 +                else if ( *q >= 'a' && *q <= 'f' ) {
   4.369 +                    ucs += mult * (*q - 'a' + 10);
   4.370 +                }
   4.371 +                else if ( *q >= 'A' && *q <= 'F' ) {
   4.372 +                    ucs += mult * (*q - 'A' + 10 );
   4.373 +                }
   4.374 +                else {
   4.375 +                    return 0;
   4.376 +                }
   4.377 +                mult *= 16;
   4.378 +                --q;
   4.379 +            }
   4.380 +        }
   4.381 +        else {
   4.382 +            // Decimal.
   4.383 +            if ( !*(p+2) ) {
   4.384 +                return 0;
   4.385 +            }
   4.386 +
   4.387 +            const char* q = p+2;
   4.388 +            q = strchr( q, ';' );
   4.389 +
   4.390 +            if ( !q || !*q ) {
   4.391 +                return 0;
   4.392 +            }
   4.393 +
   4.394 +            delta = q-p;
   4.395 +            --q;
   4.396 +
   4.397 +            while ( *q != '#' ) {
   4.398 +                if ( *q >= '0' && *q <= '9' ) {
   4.399 +                    ucs += mult * (*q - '0');
   4.400 +                }
   4.401 +                else {
   4.402 +                    return 0;
   4.403 +                }
   4.404 +                mult *= 10;
   4.405 +                --q;
   4.406 +            }
   4.407 +        }
   4.408 +        // convert the UCS to UTF-8
   4.409 +        ConvertUTF32ToUTF8( ucs, value, length );
   4.410 +        return p + delta + 1;
   4.411 +    }
   4.412 +    return p+1;
   4.413 +}
   4.414 +
   4.415 +
   4.416 +void XMLUtil::ToStr( int v, char* buffer, int bufferSize )
   4.417 +{
   4.418 +    TIXML_SNPRINTF( buffer, bufferSize, "%d", v );
   4.419 +}
   4.420 +
   4.421 +
   4.422 +void XMLUtil::ToStr( unsigned v, char* buffer, int bufferSize )
   4.423 +{
   4.424 +    TIXML_SNPRINTF( buffer, bufferSize, "%u", v );
   4.425 +}
   4.426 +
   4.427 +
   4.428 +void XMLUtil::ToStr( bool v, char* buffer, int bufferSize )
   4.429 +{
   4.430 +    TIXML_SNPRINTF( buffer, bufferSize, "%d", v ? 1 : 0 );
   4.431 +}
   4.432 +
   4.433 +
   4.434 +void XMLUtil::ToStr( float v, char* buffer, int bufferSize )
   4.435 +{
   4.436 +    TIXML_SNPRINTF( buffer, bufferSize, "%g", v );
   4.437 +}
   4.438 +
   4.439 +
   4.440 +void XMLUtil::ToStr( double v, char* buffer, int bufferSize )
   4.441 +{
   4.442 +    TIXML_SNPRINTF( buffer, bufferSize, "%g", v );
   4.443 +}
   4.444 +
   4.445 +
   4.446 +bool XMLUtil::ToInt( const char* str, int* value )
   4.447 +{
   4.448 +    if ( TIXML_SSCANF( str, "%d", value ) == 1 ) {
   4.449 +        return true;
   4.450 +    }
   4.451 +    return false;
   4.452 +}
   4.453 +
   4.454 +bool XMLUtil::ToUnsigned( const char* str, unsigned *value )
   4.455 +{
   4.456 +    if ( TIXML_SSCANF( str, "%u", value ) == 1 ) {
   4.457 +        return true;
   4.458 +    }
   4.459 +    return false;
   4.460 +}
   4.461 +
   4.462 +bool XMLUtil::ToBool( const char* str, bool* value )
   4.463 +{
   4.464 +    int ival = 0;
   4.465 +    if ( ToInt( str, &ival )) {
   4.466 +        *value = (ival==0) ? false : true;
   4.467 +        return true;
   4.468 +    }
   4.469 +    if ( StringEqual( str, "true" ) ) {
   4.470 +        *value = true;
   4.471 +        return true;
   4.472 +    }
   4.473 +    else if ( StringEqual( str, "false" ) ) {
   4.474 +        *value = false;
   4.475 +        return true;
   4.476 +    }
   4.477 +    return false;
   4.478 +}
   4.479 +
   4.480 +
   4.481 +bool XMLUtil::ToFloat( const char* str, float* value )
   4.482 +{
   4.483 +    if ( TIXML_SSCANF( str, "%f", value ) == 1 ) {
   4.484 +        return true;
   4.485 +    }
   4.486 +    return false;
   4.487 +}
   4.488 +
   4.489 +bool XMLUtil::ToDouble( const char* str, double* value )
   4.490 +{
   4.491 +    if ( TIXML_SSCANF( str, "%lf", value ) == 1 ) {
   4.492 +        return true;
   4.493 +    }
   4.494 +    return false;
   4.495 +}
   4.496 +
   4.497 +
   4.498 +char* XMLDocument::Identify( char* p, XMLNode** node )
   4.499 +{
   4.500 +    XMLNode* returnNode = 0;
   4.501 +    char* start = p;
   4.502 +    p = XMLUtil::SkipWhiteSpace( p );
   4.503 +    if( !p || !*p ) {
   4.504 +        return p;
   4.505 +    }
   4.506 +
   4.507 +    // What is this thing?
   4.508 +    // - Elements start with a letter or underscore, but xml is reserved.
   4.509 +    // - Comments: <!--
   4.510 +    // - Decleration: <?
   4.511 +    // - Everthing else is unknown to tinyxml.
   4.512 +    //
   4.513 +
   4.514 +    static const char* xmlHeader		= { "<?" };
   4.515 +    static const char* commentHeader	= { "<!--" };
   4.516 +    static const char* dtdHeader		= { "<!" };
   4.517 +    static const char* cdataHeader		= { "<![CDATA[" };
   4.518 +    static const char* elementHeader	= { "<" };	// and a header for everything else; check last.
   4.519 +
   4.520 +    static const int xmlHeaderLen		= 2;
   4.521 +    static const int commentHeaderLen	= 4;
   4.522 +    static const int dtdHeaderLen		= 2;
   4.523 +    static const int cdataHeaderLen		= 9;
   4.524 +    static const int elementHeaderLen	= 1;
   4.525 +
   4.526 +#if defined(_MSC_VER)
   4.527 +#pragma warning ( push )
   4.528 +#pragma warning ( disable : 4127 )
   4.529 +#endif
   4.530 +    TIXMLASSERT( sizeof( XMLComment ) == sizeof( XMLUnknown ) );		// use same memory pool
   4.531 +    TIXMLASSERT( sizeof( XMLComment ) == sizeof( XMLDeclaration ) );	// use same memory pool
   4.532 +#if defined(_MSC_VER)
   4.533 +#pragma warning (pop)
   4.534 +#endif
   4.535 +    if ( XMLUtil::StringEqual( p, xmlHeader, xmlHeaderLen ) ) {
   4.536 +        returnNode = new (_commentPool.Alloc()) XMLDeclaration( this );
   4.537 +        returnNode->_memPool = &_commentPool;
   4.538 +        p += xmlHeaderLen;
   4.539 +    }
   4.540 +    else if ( XMLUtil::StringEqual( p, commentHeader, commentHeaderLen ) ) {
   4.541 +        returnNode = new (_commentPool.Alloc()) XMLComment( this );
   4.542 +        returnNode->_memPool = &_commentPool;
   4.543 +        p += commentHeaderLen;
   4.544 +    }
   4.545 +    else if ( XMLUtil::StringEqual( p, cdataHeader, cdataHeaderLen ) ) {
   4.546 +        XMLText* text = new (_textPool.Alloc()) XMLText( this );
   4.547 +        returnNode = text;
   4.548 +        returnNode->_memPool = &_textPool;
   4.549 +        p += cdataHeaderLen;
   4.550 +        text->SetCData( true );
   4.551 +    }
   4.552 +    else if ( XMLUtil::StringEqual( p, dtdHeader, dtdHeaderLen ) ) {
   4.553 +        returnNode = new (_commentPool.Alloc()) XMLUnknown( this );
   4.554 +        returnNode->_memPool = &_commentPool;
   4.555 +        p += dtdHeaderLen;
   4.556 +    }
   4.557 +    else if ( XMLUtil::StringEqual( p, elementHeader, elementHeaderLen ) ) {
   4.558 +        returnNode = new (_elementPool.Alloc()) XMLElement( this );
   4.559 +        returnNode->_memPool = &_elementPool;
   4.560 +        p += elementHeaderLen;
   4.561 +    }
   4.562 +    else {
   4.563 +        returnNode = new (_textPool.Alloc()) XMLText( this );
   4.564 +        returnNode->_memPool = &_textPool;
   4.565 +        p = start;	// Back it up, all the text counts.
   4.566 +    }
   4.567 +
   4.568 +    *node = returnNode;
   4.569 +    return p;
   4.570 +}
   4.571 +
   4.572 +
   4.573 +bool XMLDocument::Accept( XMLVisitor* visitor ) const
   4.574 +{
   4.575 +    if ( visitor->VisitEnter( *this ) ) {
   4.576 +        for ( const XMLNode* node=FirstChild(); node; node=node->NextSibling() ) {
   4.577 +            if ( !node->Accept( visitor ) ) {
   4.578 +                break;
   4.579 +            }
   4.580 +        }
   4.581 +    }
   4.582 +    return visitor->VisitExit( *this );
   4.583 +}
   4.584 +
   4.585 +
   4.586 +// --------- XMLNode ----------- //
   4.587 +
   4.588 +XMLNode::XMLNode( XMLDocument* doc ) :
   4.589 +    _document( doc ),
   4.590 +    _parent( 0 ),
   4.591 +    _firstChild( 0 ), _lastChild( 0 ),
   4.592 +    _prev( 0 ), _next( 0 )
   4.593 +{
   4.594 +}
   4.595 +
   4.596 +
   4.597 +XMLNode::~XMLNode()
   4.598 +{
   4.599 +    DeleteChildren();
   4.600 +    if ( _parent ) {
   4.601 +        _parent->Unlink( this );
   4.602 +    }
   4.603 +}
   4.604 +
   4.605 +
   4.606 +void XMLNode::SetValue( const char* str, bool staticMem )
   4.607 +{
   4.608 +    if ( staticMem ) {
   4.609 +        _value.SetInternedStr( str );
   4.610 +    }
   4.611 +    else {
   4.612 +        _value.SetStr( str );
   4.613 +    }
   4.614 +}
   4.615 +
   4.616 +
   4.617 +void XMLNode::DeleteChildren()
   4.618 +{
   4.619 +    while( _firstChild ) {
   4.620 +        XMLNode* node = _firstChild;
   4.621 +        Unlink( node );
   4.622 +
   4.623 +        DELETE_NODE( node );
   4.624 +    }
   4.625 +    _firstChild = _lastChild = 0;
   4.626 +}
   4.627 +
   4.628 +
   4.629 +void XMLNode::Unlink( XMLNode* child )
   4.630 +{
   4.631 +    TIXMLASSERT( child->_parent == this );
   4.632 +    if ( child == _firstChild ) {
   4.633 +        _firstChild = _firstChild->_next;
   4.634 +    }
   4.635 +    if ( child == _lastChild ) {
   4.636 +        _lastChild = _lastChild->_prev;
   4.637 +    }
   4.638 +
   4.639 +    if ( child->_prev ) {
   4.640 +        child->_prev->_next = child->_next;
   4.641 +    }
   4.642 +    if ( child->_next ) {
   4.643 +        child->_next->_prev = child->_prev;
   4.644 +    }
   4.645 +    child->_parent = 0;
   4.646 +}
   4.647 +
   4.648 +
   4.649 +void XMLNode::DeleteChild( XMLNode* node )
   4.650 +{
   4.651 +    TIXMLASSERT( node->_parent == this );
   4.652 +    DELETE_NODE( node );
   4.653 +}
   4.654 +
   4.655 +
   4.656 +XMLNode* XMLNode::InsertEndChild( XMLNode* addThis )
   4.657 +{
   4.658 +    if ( _lastChild ) {
   4.659 +        TIXMLASSERT( _firstChild );
   4.660 +        TIXMLASSERT( _lastChild->_next == 0 );
   4.661 +        _lastChild->_next = addThis;
   4.662 +        addThis->_prev = _lastChild;
   4.663 +        _lastChild = addThis;
   4.664 +
   4.665 +        addThis->_next = 0;
   4.666 +    }
   4.667 +    else {
   4.668 +        TIXMLASSERT( _firstChild == 0 );
   4.669 +        _firstChild = _lastChild = addThis;
   4.670 +
   4.671 +        addThis->_prev = 0;
   4.672 +        addThis->_next = 0;
   4.673 +    }
   4.674 +    addThis->_parent = this;
   4.675 +    addThis->_memPool->SetTracked();
   4.676 +    return addThis;
   4.677 +}
   4.678 +
   4.679 +
   4.680 +XMLNode* XMLNode::InsertFirstChild( XMLNode* addThis )
   4.681 +{
   4.682 +    if ( _firstChild ) {
   4.683 +        TIXMLASSERT( _lastChild );
   4.684 +        TIXMLASSERT( _firstChild->_prev == 0 );
   4.685 +
   4.686 +        _firstChild->_prev = addThis;
   4.687 +        addThis->_next = _firstChild;
   4.688 +        _firstChild = addThis;
   4.689 +
   4.690 +        addThis->_prev = 0;
   4.691 +    }
   4.692 +    else {
   4.693 +        TIXMLASSERT( _lastChild == 0 );
   4.694 +        _firstChild = _lastChild = addThis;
   4.695 +
   4.696 +        addThis->_prev = 0;
   4.697 +        addThis->_next = 0;
   4.698 +    }
   4.699 +    addThis->_parent = this;
   4.700 +    addThis->_memPool->SetTracked();
   4.701 +    return addThis;
   4.702 +}
   4.703 +
   4.704 +
   4.705 +XMLNode* XMLNode::InsertAfterChild( XMLNode* afterThis, XMLNode* addThis )
   4.706 +{
   4.707 +    TIXMLASSERT( afterThis->_parent == this );
   4.708 +    if ( afterThis->_parent != this ) {
   4.709 +        return 0;
   4.710 +    }
   4.711 +
   4.712 +    if ( afterThis->_next == 0 ) {
   4.713 +        // The last node or the only node.
   4.714 +        return InsertEndChild( addThis );
   4.715 +    }
   4.716 +    addThis->_prev = afterThis;
   4.717 +    addThis->_next = afterThis->_next;
   4.718 +    afterThis->_next->_prev = addThis;
   4.719 +    afterThis->_next = addThis;
   4.720 +    addThis->_parent = this;
   4.721 +    addThis->_memPool->SetTracked();
   4.722 +    return addThis;
   4.723 +}
   4.724 +
   4.725 +
   4.726 +
   4.727 +
   4.728 +const XMLElement* XMLNode::FirstChildElement( const char* value ) const
   4.729 +{
   4.730 +    for( XMLNode* node=_firstChild; node; node=node->_next ) {
   4.731 +        XMLElement* element = node->ToElement();
   4.732 +        if ( element ) {
   4.733 +            if ( !value || XMLUtil::StringEqual( element->Name(), value ) ) {
   4.734 +                return element;
   4.735 +            }
   4.736 +        }
   4.737 +    }
   4.738 +    return 0;
   4.739 +}
   4.740 +
   4.741 +
   4.742 +const XMLElement* XMLNode::LastChildElement( const char* value ) const
   4.743 +{
   4.744 +    for( XMLNode* node=_lastChild; node; node=node->_prev ) {
   4.745 +        XMLElement* element = node->ToElement();
   4.746 +        if ( element ) {
   4.747 +            if ( !value || XMLUtil::StringEqual( element->Name(), value ) ) {
   4.748 +                return element;
   4.749 +            }
   4.750 +        }
   4.751 +    }
   4.752 +    return 0;
   4.753 +}
   4.754 +
   4.755 +
   4.756 +const XMLElement* XMLNode::NextSiblingElement( const char* value ) const
   4.757 +{
   4.758 +    for( XMLNode* element=this->_next; element; element = element->_next ) {
   4.759 +        if (    element->ToElement()
   4.760 +                && (!value || XMLUtil::StringEqual( value, element->Value() ))) {
   4.761 +            return element->ToElement();
   4.762 +        }
   4.763 +    }
   4.764 +    return 0;
   4.765 +}
   4.766 +
   4.767 +
   4.768 +const XMLElement* XMLNode::PreviousSiblingElement( const char* value ) const
   4.769 +{
   4.770 +    for( XMLNode* element=_prev; element; element = element->_prev ) {
   4.771 +        if (    element->ToElement()
   4.772 +                && (!value || XMLUtil::StringEqual( value, element->Value() ))) {
   4.773 +            return element->ToElement();
   4.774 +        }
   4.775 +    }
   4.776 +    return 0;
   4.777 +}
   4.778 +
   4.779 +
   4.780 +char* XMLNode::ParseDeep( char* p, StrPair* parentEnd )
   4.781 +{
   4.782 +    // This is a recursive method, but thinking about it "at the current level"
   4.783 +    // it is a pretty simple flat list:
   4.784 +    //		<foo/>
   4.785 +    //		<!-- comment -->
   4.786 +    //
   4.787 +    // With a special case:
   4.788 +    //		<foo>
   4.789 +    //		</foo>
   4.790 +    //		<!-- comment -->
   4.791 +    //
   4.792 +    // Where the closing element (/foo) *must* be the next thing after the opening
   4.793 +    // element, and the names must match. BUT the tricky bit is that the closing
   4.794 +    // element will be read by the child.
   4.795 +    //
   4.796 +    // 'endTag' is the end tag for this node, it is returned by a call to a child.
   4.797 +    // 'parentEnd' is the end tag for the parent, which is filled in and returned.
   4.798 +
   4.799 +    while( p && *p ) {
   4.800 +        XMLNode* node = 0;
   4.801 +
   4.802 +        p = _document->Identify( p, &node );
   4.803 +        if ( p == 0 || node == 0 ) {
   4.804 +            break;
   4.805 +        }
   4.806 +
   4.807 +        StrPair endTag;
   4.808 +        p = node->ParseDeep( p, &endTag );
   4.809 +        if ( !p ) {
   4.810 +            DELETE_NODE( node );
   4.811 +            node = 0;
   4.812 +            if ( !_document->Error() ) {
   4.813 +                _document->SetError( XML_ERROR_PARSING, 0, 0 );
   4.814 +            }
   4.815 +            break;
   4.816 +        }
   4.817 +
   4.818 +        // We read the end tag. Return it to the parent.
   4.819 +        if ( node->ToElement() && node->ToElement()->ClosingType() == XMLElement::CLOSING ) {
   4.820 +            if ( parentEnd ) {
   4.821 +                *parentEnd = static_cast<XMLElement*>(node)->_value;
   4.822 +            }
   4.823 +			node->_memPool->SetTracked();	// created and then immediately deleted.
   4.824 +            DELETE_NODE( node );
   4.825 +            return p;
   4.826 +        }
   4.827 +
   4.828 +        // Handle an end tag returned to this level.
   4.829 +        // And handle a bunch of annoying errors.
   4.830 +        XMLElement* ele = node->ToElement();
   4.831 +        if ( ele ) {
   4.832 +            if ( endTag.Empty() && ele->ClosingType() == XMLElement::OPEN ) {
   4.833 +                _document->SetError( XML_ERROR_MISMATCHED_ELEMENT, node->Value(), 0 );
   4.834 +                p = 0;
   4.835 +            }
   4.836 +            else if ( !endTag.Empty() && ele->ClosingType() != XMLElement::OPEN ) {
   4.837 +                _document->SetError( XML_ERROR_MISMATCHED_ELEMENT, node->Value(), 0 );
   4.838 +                p = 0;
   4.839 +            }
   4.840 +            else if ( !endTag.Empty() ) {
   4.841 +                if ( !XMLUtil::StringEqual( endTag.GetStr(), node->Value() )) {
   4.842 +                    _document->SetError( XML_ERROR_MISMATCHED_ELEMENT, node->Value(), 0 );
   4.843 +                    p = 0;
   4.844 +                }
   4.845 +            }
   4.846 +        }
   4.847 +        if ( p == 0 ) {
   4.848 +            DELETE_NODE( node );
   4.849 +            node = 0;
   4.850 +        }
   4.851 +        if ( node ) {
   4.852 +            this->InsertEndChild( node );
   4.853 +        }
   4.854 +    }
   4.855 +    return 0;
   4.856 +}
   4.857 +
   4.858 +// --------- XMLText ---------- //
   4.859 +char* XMLText::ParseDeep( char* p, StrPair* )
   4.860 +{
   4.861 +    const char* start = p;
   4.862 +    if ( this->CData() ) {
   4.863 +        p = _value.ParseText( p, "]]>", StrPair::NEEDS_NEWLINE_NORMALIZATION );
   4.864 +        if ( !p ) {
   4.865 +            _document->SetError( XML_ERROR_PARSING_CDATA, start, 0 );
   4.866 +        }
   4.867 +        return p;
   4.868 +    }
   4.869 +    else {
   4.870 +        int flags = _document->ProcessEntities() ? StrPair::TEXT_ELEMENT : StrPair::TEXT_ELEMENT_LEAVE_ENTITIES;
   4.871 +        if ( _document->WhitespaceMode() == COLLAPSE_WHITESPACE ) {
   4.872 +            flags |= StrPair::COLLAPSE_WHITESPACE;
   4.873 +        }
   4.874 +
   4.875 +        p = _value.ParseText( p, "<", flags );
   4.876 +        if ( !p ) {
   4.877 +            _document->SetError( XML_ERROR_PARSING_TEXT, start, 0 );
   4.878 +        }
   4.879 +        if ( p && *p ) {
   4.880 +            return p-1;
   4.881 +        }
   4.882 +    }
   4.883 +    return 0;
   4.884 +}
   4.885 +
   4.886 +
   4.887 +XMLNode* XMLText::ShallowClone( XMLDocument* doc ) const
   4.888 +{
   4.889 +    if ( !doc ) {
   4.890 +        doc = _document;
   4.891 +    }
   4.892 +    XMLText* text = doc->NewText( Value() );	// fixme: this will always allocate memory. Intern?
   4.893 +    text->SetCData( this->CData() );
   4.894 +    return text;
   4.895 +}
   4.896 +
   4.897 +
   4.898 +bool XMLText::ShallowEqual( const XMLNode* compare ) const
   4.899 +{
   4.900 +    return ( compare->ToText() && XMLUtil::StringEqual( compare->ToText()->Value(), Value() ));
   4.901 +}
   4.902 +
   4.903 +
   4.904 +bool XMLText::Accept( XMLVisitor* visitor ) const
   4.905 +{
   4.906 +    return visitor->Visit( *this );
   4.907 +}
   4.908 +
   4.909 +
   4.910 +// --------- XMLComment ---------- //
   4.911 +
   4.912 +XMLComment::XMLComment( XMLDocument* doc ) : XMLNode( doc )
   4.913 +{
   4.914 +}
   4.915 +
   4.916 +
   4.917 +XMLComment::~XMLComment()
   4.918 +{
   4.919 +}
   4.920 +
   4.921 +
   4.922 +char* XMLComment::ParseDeep( char* p, StrPair* )
   4.923 +{
   4.924 +    // Comment parses as text.
   4.925 +    const char* start = p;
   4.926 +    p = _value.ParseText( p, "-->", StrPair::COMMENT );
   4.927 +    if ( p == 0 ) {
   4.928 +        _document->SetError( XML_ERROR_PARSING_COMMENT, start, 0 );
   4.929 +    }
   4.930 +    return p;
   4.931 +}
   4.932 +
   4.933 +
   4.934 +XMLNode* XMLComment::ShallowClone( XMLDocument* doc ) const
   4.935 +{
   4.936 +    if ( !doc ) {
   4.937 +        doc = _document;
   4.938 +    }
   4.939 +    XMLComment* comment = doc->NewComment( Value() );	// fixme: this will always allocate memory. Intern?
   4.940 +    return comment;
   4.941 +}
   4.942 +
   4.943 +
   4.944 +bool XMLComment::ShallowEqual( const XMLNode* compare ) const
   4.945 +{
   4.946 +    return ( compare->ToComment() && XMLUtil::StringEqual( compare->ToComment()->Value(), Value() ));
   4.947 +}
   4.948 +
   4.949 +
   4.950 +bool XMLComment::Accept( XMLVisitor* visitor ) const
   4.951 +{
   4.952 +    return visitor->Visit( *this );
   4.953 +}
   4.954 +
   4.955 +
   4.956 +// --------- XMLDeclaration ---------- //
   4.957 +
   4.958 +XMLDeclaration::XMLDeclaration( XMLDocument* doc ) : XMLNode( doc )
   4.959 +{
   4.960 +}
   4.961 +
   4.962 +
   4.963 +XMLDeclaration::~XMLDeclaration()
   4.964 +{
   4.965 +    //printf( "~XMLDeclaration\n" );
   4.966 +}
   4.967 +
   4.968 +
   4.969 +char* XMLDeclaration::ParseDeep( char* p, StrPair* )
   4.970 +{
   4.971 +    // Declaration parses as text.
   4.972 +    const char* start = p;
   4.973 +    p = _value.ParseText( p, "?>", StrPair::NEEDS_NEWLINE_NORMALIZATION );
   4.974 +    if ( p == 0 ) {
   4.975 +        _document->SetError( XML_ERROR_PARSING_DECLARATION, start, 0 );
   4.976 +    }
   4.977 +    return p;
   4.978 +}
   4.979 +
   4.980 +
   4.981 +XMLNode* XMLDeclaration::ShallowClone( XMLDocument* doc ) const
   4.982 +{
   4.983 +    if ( !doc ) {
   4.984 +        doc = _document;
   4.985 +    }
   4.986 +    XMLDeclaration* dec = doc->NewDeclaration( Value() );	// fixme: this will always allocate memory. Intern?
   4.987 +    return dec;
   4.988 +}
   4.989 +
   4.990 +
   4.991 +bool XMLDeclaration::ShallowEqual( const XMLNode* compare ) const
   4.992 +{
   4.993 +    return ( compare->ToDeclaration() && XMLUtil::StringEqual( compare->ToDeclaration()->Value(), Value() ));
   4.994 +}
   4.995 +
   4.996 +
   4.997 +
   4.998 +bool XMLDeclaration::Accept( XMLVisitor* visitor ) const
   4.999 +{
  4.1000 +    return visitor->Visit( *this );
  4.1001 +}
  4.1002 +
  4.1003 +// --------- XMLUnknown ---------- //
  4.1004 +
  4.1005 +XMLUnknown::XMLUnknown( XMLDocument* doc ) : XMLNode( doc )
  4.1006 +{
  4.1007 +}
  4.1008 +
  4.1009 +
  4.1010 +XMLUnknown::~XMLUnknown()
  4.1011 +{
  4.1012 +}
  4.1013 +
  4.1014 +
  4.1015 +char* XMLUnknown::ParseDeep( char* p, StrPair* )
  4.1016 +{
  4.1017 +    // Unknown parses as text.
  4.1018 +    const char* start = p;
  4.1019 +
  4.1020 +    p = _value.ParseText( p, ">", StrPair::NEEDS_NEWLINE_NORMALIZATION );
  4.1021 +    if ( !p ) {
  4.1022 +        _document->SetError( XML_ERROR_PARSING_UNKNOWN, start, 0 );
  4.1023 +    }
  4.1024 +    return p;
  4.1025 +}
  4.1026 +
  4.1027 +
  4.1028 +XMLNode* XMLUnknown::ShallowClone( XMLDocument* doc ) const
  4.1029 +{
  4.1030 +    if ( !doc ) {
  4.1031 +        doc = _document;
  4.1032 +    }
  4.1033 +    XMLUnknown* text = doc->NewUnknown( Value() );	// fixme: this will always allocate memory. Intern?
  4.1034 +    return text;
  4.1035 +}
  4.1036 +
  4.1037 +
  4.1038 +bool XMLUnknown::ShallowEqual( const XMLNode* compare ) const
  4.1039 +{
  4.1040 +    return ( compare->ToUnknown() && XMLUtil::StringEqual( compare->ToUnknown()->Value(), Value() ));
  4.1041 +}
  4.1042 +
  4.1043 +
  4.1044 +bool XMLUnknown::Accept( XMLVisitor* visitor ) const
  4.1045 +{
  4.1046 +    return visitor->Visit( *this );
  4.1047 +}
  4.1048 +
  4.1049 +// --------- XMLAttribute ---------- //
  4.1050 +char* XMLAttribute::ParseDeep( char* p, bool processEntities )
  4.1051 +{
  4.1052 +    // Parse using the name rules: bug fix, was using ParseText before
  4.1053 +    p = _name.ParseName( p );
  4.1054 +    if ( !p || !*p ) {
  4.1055 +        return 0;
  4.1056 +    }
  4.1057 +
  4.1058 +    // Skip white space before =
  4.1059 +    p = XMLUtil::SkipWhiteSpace( p );
  4.1060 +    if ( !p || *p != '=' ) {
  4.1061 +        return 0;
  4.1062 +    }
  4.1063 +
  4.1064 +    ++p;	// move up to opening quote
  4.1065 +    p = XMLUtil::SkipWhiteSpace( p );
  4.1066 +    if ( *p != '\"' && *p != '\'' ) {
  4.1067 +        return 0;
  4.1068 +    }
  4.1069 +
  4.1070 +    char endTag[2] = { *p, 0 };
  4.1071 +    ++p;	// move past opening quote
  4.1072 +
  4.1073 +    p = _value.ParseText( p, endTag, processEntities ? StrPair::ATTRIBUTE_VALUE : StrPair::ATTRIBUTE_VALUE_LEAVE_ENTITIES );
  4.1074 +    return p;
  4.1075 +}
  4.1076 +
  4.1077 +
  4.1078 +void XMLAttribute::SetName( const char* n )
  4.1079 +{
  4.1080 +    _name.SetStr( n );
  4.1081 +}
  4.1082 +
  4.1083 +
  4.1084 +XMLError XMLAttribute::QueryIntValue( int* value ) const
  4.1085 +{
  4.1086 +    if ( XMLUtil::ToInt( Value(), value )) {
  4.1087 +        return XML_NO_ERROR;
  4.1088 +    }
  4.1089 +    return XML_WRONG_ATTRIBUTE_TYPE;
  4.1090 +}
  4.1091 +
  4.1092 +
  4.1093 +XMLError XMLAttribute::QueryUnsignedValue( unsigned int* value ) const
  4.1094 +{
  4.1095 +    if ( XMLUtil::ToUnsigned( Value(), value )) {
  4.1096 +        return XML_NO_ERROR;
  4.1097 +    }
  4.1098 +    return XML_WRONG_ATTRIBUTE_TYPE;
  4.1099 +}
  4.1100 +
  4.1101 +
  4.1102 +XMLError XMLAttribute::QueryBoolValue( bool* value ) const
  4.1103 +{
  4.1104 +    if ( XMLUtil::ToBool( Value(), value )) {
  4.1105 +        return XML_NO_ERROR;
  4.1106 +    }
  4.1107 +    return XML_WRONG_ATTRIBUTE_TYPE;
  4.1108 +}
  4.1109 +
  4.1110 +
  4.1111 +XMLError XMLAttribute::QueryFloatValue( float* value ) const
  4.1112 +{
  4.1113 +    if ( XMLUtil::ToFloat( Value(), value )) {
  4.1114 +        return XML_NO_ERROR;
  4.1115 +    }
  4.1116 +    return XML_WRONG_ATTRIBUTE_TYPE;
  4.1117 +}
  4.1118 +
  4.1119 +
  4.1120 +XMLError XMLAttribute::QueryDoubleValue( double* value ) const
  4.1121 +{
  4.1122 +    if ( XMLUtil::ToDouble( Value(), value )) {
  4.1123 +        return XML_NO_ERROR;
  4.1124 +    }
  4.1125 +    return XML_WRONG_ATTRIBUTE_TYPE;
  4.1126 +}
  4.1127 +
  4.1128 +
  4.1129 +void XMLAttribute::SetAttribute( const char* v )
  4.1130 +{
  4.1131 +    _value.SetStr( v );
  4.1132 +}
  4.1133 +
  4.1134 +
  4.1135 +void XMLAttribute::SetAttribute( int v )
  4.1136 +{
  4.1137 +    char buf[BUF_SIZE];
  4.1138 +    XMLUtil::ToStr( v, buf, BUF_SIZE );
  4.1139 +    _value.SetStr( buf );
  4.1140 +}
  4.1141 +
  4.1142 +
  4.1143 +void XMLAttribute::SetAttribute( unsigned v )
  4.1144 +{
  4.1145 +    char buf[BUF_SIZE];
  4.1146 +    XMLUtil::ToStr( v, buf, BUF_SIZE );
  4.1147 +    _value.SetStr( buf );
  4.1148 +}
  4.1149 +
  4.1150 +
  4.1151 +void XMLAttribute::SetAttribute( bool v )
  4.1152 +{
  4.1153 +    char buf[BUF_SIZE];
  4.1154 +    XMLUtil::ToStr( v, buf, BUF_SIZE );
  4.1155 +    _value.SetStr( buf );
  4.1156 +}
  4.1157 +
  4.1158 +void XMLAttribute::SetAttribute( double v )
  4.1159 +{
  4.1160 +    char buf[BUF_SIZE];
  4.1161 +    XMLUtil::ToStr( v, buf, BUF_SIZE );
  4.1162 +    _value.SetStr( buf );
  4.1163 +}
  4.1164 +
  4.1165 +void XMLAttribute::SetAttribute( float v )
  4.1166 +{
  4.1167 +    char buf[BUF_SIZE];
  4.1168 +    XMLUtil::ToStr( v, buf, BUF_SIZE );
  4.1169 +    _value.SetStr( buf );
  4.1170 +}
  4.1171 +
  4.1172 +
  4.1173 +// --------- XMLElement ---------- //
  4.1174 +XMLElement::XMLElement( XMLDocument* doc ) : XMLNode( doc ),
  4.1175 +    _closingType( 0 ),
  4.1176 +    _rootAttribute( 0 )
  4.1177 +{
  4.1178 +}
  4.1179 +
  4.1180 +
  4.1181 +XMLElement::~XMLElement()
  4.1182 +{
  4.1183 +    while( _rootAttribute ) {
  4.1184 +        XMLAttribute* next = _rootAttribute->_next;
  4.1185 +        DELETE_ATTRIBUTE( _rootAttribute );
  4.1186 +        _rootAttribute = next;
  4.1187 +    }
  4.1188 +}
  4.1189 +
  4.1190 +
  4.1191 +XMLAttribute* XMLElement::FindAttribute( const char* name )
  4.1192 +{
  4.1193 +    XMLAttribute* a = 0;
  4.1194 +    for( a=_rootAttribute; a; a = a->_next ) {
  4.1195 +        if ( XMLUtil::StringEqual( a->Name(), name ) ) {
  4.1196 +            return a;
  4.1197 +        }
  4.1198 +    }
  4.1199 +    return 0;
  4.1200 +}
  4.1201 +
  4.1202 +
  4.1203 +const XMLAttribute* XMLElement::FindAttribute( const char* name ) const
  4.1204 +{
  4.1205 +    XMLAttribute* a = 0;
  4.1206 +    for( a=_rootAttribute; a; a = a->_next ) {
  4.1207 +        if ( XMLUtil::StringEqual( a->Name(), name ) ) {
  4.1208 +            return a;
  4.1209 +        }
  4.1210 +    }
  4.1211 +    return 0;
  4.1212 +}
  4.1213 +
  4.1214 +
  4.1215 +const char* XMLElement::Attribute( const char* name, const char* value ) const
  4.1216 +{
  4.1217 +    const XMLAttribute* a = FindAttribute( name );
  4.1218 +    if ( !a ) {
  4.1219 +        return 0;
  4.1220 +    }
  4.1221 +    if ( !value || XMLUtil::StringEqual( a->Value(), value )) {
  4.1222 +        return a->Value();
  4.1223 +    }
  4.1224 +    return 0;
  4.1225 +}
  4.1226 +
  4.1227 +
  4.1228 +const char* XMLElement::GetText() const
  4.1229 +{
  4.1230 +    if ( FirstChild() && FirstChild()->ToText() ) {
  4.1231 +        return FirstChild()->ToText()->Value();
  4.1232 +    }
  4.1233 +    return 0;
  4.1234 +}
  4.1235 +
  4.1236 +
  4.1237 +XMLError XMLElement::QueryIntText( int* ival ) const
  4.1238 +{
  4.1239 +    if ( FirstChild() && FirstChild()->ToText() ) {
  4.1240 +        const char* t = FirstChild()->ToText()->Value();
  4.1241 +        if ( XMLUtil::ToInt( t, ival ) ) {
  4.1242 +            return XML_SUCCESS;
  4.1243 +        }
  4.1244 +        return XML_CAN_NOT_CONVERT_TEXT;
  4.1245 +    }
  4.1246 +    return XML_NO_TEXT_NODE;
  4.1247 +}
  4.1248 +
  4.1249 +
  4.1250 +XMLError XMLElement::QueryUnsignedText( unsigned* uval ) const
  4.1251 +{
  4.1252 +    if ( FirstChild() && FirstChild()->ToText() ) {
  4.1253 +        const char* t = FirstChild()->ToText()->Value();
  4.1254 +        if ( XMLUtil::ToUnsigned( t, uval ) ) {
  4.1255 +            return XML_SUCCESS;
  4.1256 +        }
  4.1257 +        return XML_CAN_NOT_CONVERT_TEXT;
  4.1258 +    }
  4.1259 +    return XML_NO_TEXT_NODE;
  4.1260 +}
  4.1261 +
  4.1262 +
  4.1263 +XMLError XMLElement::QueryBoolText( bool* bval ) const
  4.1264 +{
  4.1265 +    if ( FirstChild() && FirstChild()->ToText() ) {
  4.1266 +        const char* t = FirstChild()->ToText()->Value();
  4.1267 +        if ( XMLUtil::ToBool( t, bval ) ) {
  4.1268 +            return XML_SUCCESS;
  4.1269 +        }
  4.1270 +        return XML_CAN_NOT_CONVERT_TEXT;
  4.1271 +    }
  4.1272 +    return XML_NO_TEXT_NODE;
  4.1273 +}
  4.1274 +
  4.1275 +
  4.1276 +XMLError XMLElement::QueryDoubleText( double* dval ) const
  4.1277 +{
  4.1278 +    if ( FirstChild() && FirstChild()->ToText() ) {
  4.1279 +        const char* t = FirstChild()->ToText()->Value();
  4.1280 +        if ( XMLUtil::ToDouble( t, dval ) ) {
  4.1281 +            return XML_SUCCESS;
  4.1282 +        }
  4.1283 +        return XML_CAN_NOT_CONVERT_TEXT;
  4.1284 +    }
  4.1285 +    return XML_NO_TEXT_NODE;
  4.1286 +}
  4.1287 +
  4.1288 +
  4.1289 +XMLError XMLElement::QueryFloatText( float* fval ) const
  4.1290 +{
  4.1291 +    if ( FirstChild() && FirstChild()->ToText() ) {
  4.1292 +        const char* t = FirstChild()->ToText()->Value();
  4.1293 +        if ( XMLUtil::ToFloat( t, fval ) ) {
  4.1294 +            return XML_SUCCESS;
  4.1295 +        }
  4.1296 +        return XML_CAN_NOT_CONVERT_TEXT;
  4.1297 +    }
  4.1298 +    return XML_NO_TEXT_NODE;
  4.1299 +}
  4.1300 +
  4.1301 +
  4.1302 +
  4.1303 +XMLAttribute* XMLElement::FindOrCreateAttribute( const char* name )
  4.1304 +{
  4.1305 +    XMLAttribute* last = 0;
  4.1306 +    XMLAttribute* attrib = 0;
  4.1307 +    for( attrib = _rootAttribute;
  4.1308 +            attrib;
  4.1309 +            last = attrib, attrib = attrib->_next ) {
  4.1310 +        if ( XMLUtil::StringEqual( attrib->Name(), name ) ) {
  4.1311 +            break;
  4.1312 +        }
  4.1313 +    }
  4.1314 +    if ( !attrib ) {
  4.1315 +        attrib = new (_document->_attributePool.Alloc() ) XMLAttribute();
  4.1316 +        attrib->_memPool = &_document->_attributePool;
  4.1317 +        if ( last ) {
  4.1318 +            last->_next = attrib;
  4.1319 +        }
  4.1320 +        else {
  4.1321 +            _rootAttribute = attrib;
  4.1322 +        }
  4.1323 +        attrib->SetName( name );
  4.1324 +        attrib->_memPool->SetTracked(); // always created and linked.
  4.1325 +    }
  4.1326 +    return attrib;
  4.1327 +}
  4.1328 +
  4.1329 +
  4.1330 +void XMLElement::DeleteAttribute( const char* name )
  4.1331 +{
  4.1332 +    XMLAttribute* prev = 0;
  4.1333 +    for( XMLAttribute* a=_rootAttribute; a; a=a->_next ) {
  4.1334 +        if ( XMLUtil::StringEqual( name, a->Name() ) ) {
  4.1335 +            if ( prev ) {
  4.1336 +                prev->_next = a->_next;
  4.1337 +            }
  4.1338 +            else {
  4.1339 +                _rootAttribute = a->_next;
  4.1340 +            }
  4.1341 +            DELETE_ATTRIBUTE( a );
  4.1342 +            break;
  4.1343 +        }
  4.1344 +        prev = a;
  4.1345 +    }
  4.1346 +}
  4.1347 +
  4.1348 +
  4.1349 +char* XMLElement::ParseAttributes( char* p )
  4.1350 +{
  4.1351 +    const char* start = p;
  4.1352 +    XMLAttribute* prevAttribute = 0;
  4.1353 +
  4.1354 +    // Read the attributes.
  4.1355 +    while( p ) {
  4.1356 +        p = XMLUtil::SkipWhiteSpace( p );
  4.1357 +        if ( !p || !(*p) ) {
  4.1358 +            _document->SetError( XML_ERROR_PARSING_ELEMENT, start, Name() );
  4.1359 +            return 0;
  4.1360 +        }
  4.1361 +
  4.1362 +        // attribute.
  4.1363 +        if ( XMLUtil::IsAlpha( *p ) ) {
  4.1364 +            XMLAttribute* attrib = new (_document->_attributePool.Alloc() ) XMLAttribute();
  4.1365 +            attrib->_memPool = &_document->_attributePool;
  4.1366 +			attrib->_memPool->SetTracked();
  4.1367 +
  4.1368 +            p = attrib->ParseDeep( p, _document->ProcessEntities() );
  4.1369 +            if ( !p || Attribute( attrib->Name() ) ) {
  4.1370 +                DELETE_ATTRIBUTE( attrib );
  4.1371 +                _document->SetError( XML_ERROR_PARSING_ATTRIBUTE, start, p );
  4.1372 +                return 0;
  4.1373 +            }
  4.1374 +            // There is a minor bug here: if the attribute in the source xml
  4.1375 +            // document is duplicated, it will not be detected and the
  4.1376 +            // attribute will be doubly added. However, tracking the 'prevAttribute'
  4.1377 +            // avoids re-scanning the attribute list. Preferring performance for
  4.1378 +            // now, may reconsider in the future.
  4.1379 +            if ( prevAttribute ) {
  4.1380 +                prevAttribute->_next = attrib;
  4.1381 +            }
  4.1382 +            else {
  4.1383 +                _rootAttribute = attrib;
  4.1384 +            }
  4.1385 +            prevAttribute = attrib;
  4.1386 +        }
  4.1387 +        // end of the tag
  4.1388 +        else if ( *p == '/' && *(p+1) == '>' ) {
  4.1389 +            _closingType = CLOSED;
  4.1390 +            return p+2;	// done; sealed element.
  4.1391 +        }
  4.1392 +        // end of the tag
  4.1393 +        else if ( *p == '>' ) {
  4.1394 +            ++p;
  4.1395 +            break;
  4.1396 +        }
  4.1397 +        else {
  4.1398 +            _document->SetError( XML_ERROR_PARSING_ELEMENT, start, p );
  4.1399 +            return 0;
  4.1400 +        }
  4.1401 +    }
  4.1402 +    return p;
  4.1403 +}
  4.1404 +
  4.1405 +
  4.1406 +//
  4.1407 +//	<ele></ele>
  4.1408 +//	<ele>foo<b>bar</b></ele>
  4.1409 +//
  4.1410 +char* XMLElement::ParseDeep( char* p, StrPair* strPair )
  4.1411 +{
  4.1412 +    // Read the element name.
  4.1413 +    p = XMLUtil::SkipWhiteSpace( p );
  4.1414 +    if ( !p ) {
  4.1415 +        return 0;
  4.1416 +    }
  4.1417 +
  4.1418 +    // The closing element is the </element> form. It is
  4.1419 +    // parsed just like a regular element then deleted from
  4.1420 +    // the DOM.
  4.1421 +    if ( *p == '/' ) {
  4.1422 +        _closingType = CLOSING;
  4.1423 +        ++p;
  4.1424 +    }
  4.1425 +
  4.1426 +    p = _value.ParseName( p );
  4.1427 +    if ( _value.Empty() ) {
  4.1428 +        return 0;
  4.1429 +    }
  4.1430 +
  4.1431 +    p = ParseAttributes( p );
  4.1432 +    if ( !p || !*p || _closingType ) {
  4.1433 +        return p;
  4.1434 +    }
  4.1435 +
  4.1436 +    p = XMLNode::ParseDeep( p, strPair );
  4.1437 +    return p;
  4.1438 +}
  4.1439 +
  4.1440 +
  4.1441 +
  4.1442 +XMLNode* XMLElement::ShallowClone( XMLDocument* doc ) const
  4.1443 +{
  4.1444 +    if ( !doc ) {
  4.1445 +        doc = _document;
  4.1446 +    }
  4.1447 +    XMLElement* element = doc->NewElement( Value() );					// fixme: this will always allocate memory. Intern?
  4.1448 +    for( const XMLAttribute* a=FirstAttribute(); a; a=a->Next() ) {
  4.1449 +        element->SetAttribute( a->Name(), a->Value() );					// fixme: this will always allocate memory. Intern?
  4.1450 +    }
  4.1451 +    return element;
  4.1452 +}
  4.1453 +
  4.1454 +
  4.1455 +bool XMLElement::ShallowEqual( const XMLNode* compare ) const
  4.1456 +{
  4.1457 +    const XMLElement* other = compare->ToElement();
  4.1458 +    if ( other && XMLUtil::StringEqual( other->Value(), Value() )) {
  4.1459 +
  4.1460 +        const XMLAttribute* a=FirstAttribute();
  4.1461 +        const XMLAttribute* b=other->FirstAttribute();
  4.1462 +
  4.1463 +        while ( a && b ) {
  4.1464 +            if ( !XMLUtil::StringEqual( a->Value(), b->Value() ) ) {
  4.1465 +                return false;
  4.1466 +            }
  4.1467 +            a = a->Next();
  4.1468 +            b = b->Next();
  4.1469 +        }
  4.1470 +        if ( a || b ) {
  4.1471 +            // different count
  4.1472 +            return false;
  4.1473 +        }
  4.1474 +        return true;
  4.1475 +    }
  4.1476 +    return false;
  4.1477 +}
  4.1478 +
  4.1479 +
  4.1480 +bool XMLElement::Accept( XMLVisitor* visitor ) const
  4.1481 +{
  4.1482 +    if ( visitor->VisitEnter( *this, _rootAttribute ) ) {
  4.1483 +        for ( const XMLNode* node=FirstChild(); node; node=node->NextSibling() ) {
  4.1484 +            if ( !node->Accept( visitor ) ) {
  4.1485 +                break;
  4.1486 +            }
  4.1487 +        }
  4.1488 +    }
  4.1489 +    return visitor->VisitExit( *this );
  4.1490 +}
  4.1491 +
  4.1492 +
  4.1493 +// --------- XMLDocument ----------- //
  4.1494 +XMLDocument::XMLDocument( bool processEntities, Whitespace whitespace ) :
  4.1495 +    XMLNode( 0 ),
  4.1496 +    _writeBOM( false ),
  4.1497 +    _processEntities( processEntities ),
  4.1498 +    _errorID( XML_NO_ERROR ),
  4.1499 +    _whitespace( whitespace ),
  4.1500 +    _errorStr1( 0 ),
  4.1501 +    _errorStr2( 0 ),
  4.1502 +    _charBuffer( 0 )
  4.1503 +{
  4.1504 +    _document = this;	// avoid warning about 'this' in initializer list
  4.1505 +}
  4.1506 +
  4.1507 +
  4.1508 +XMLDocument::~XMLDocument()
  4.1509 +{
  4.1510 +    DeleteChildren();
  4.1511 +    delete [] _charBuffer;
  4.1512 +
  4.1513 +#if 0
  4.1514 +    textPool.Trace( "text" );
  4.1515 +    elementPool.Trace( "element" );
  4.1516 +    commentPool.Trace( "comment" );
  4.1517 +    attributePool.Trace( "attribute" );
  4.1518 +#endif
  4.1519 +
  4.1520 +#ifdef DEBUG
  4.1521 +	if ( Error() == false ) {
  4.1522 +		TIXMLASSERT( _elementPool.CurrentAllocs()   == _elementPool.Untracked() );
  4.1523 +		TIXMLASSERT( _attributePool.CurrentAllocs() == _attributePool.Untracked() );
  4.1524 +		TIXMLASSERT( _textPool.CurrentAllocs()      == _textPool.Untracked() );
  4.1525 +		TIXMLASSERT( _commentPool.CurrentAllocs()   == _commentPool.Untracked() );
  4.1526 +	}
  4.1527 +#endif
  4.1528 +}
  4.1529 +
  4.1530 +
  4.1531 +void XMLDocument::InitDocument()
  4.1532 +{
  4.1533 +    _errorID = XML_NO_ERROR;
  4.1534 +    _errorStr1 = 0;
  4.1535 +    _errorStr2 = 0;
  4.1536 +
  4.1537 +    delete [] _charBuffer;
  4.1538 +    _charBuffer = 0;
  4.1539 +}
  4.1540 +
  4.1541 +
  4.1542 +XMLElement* XMLDocument::NewElement( const char* name )
  4.1543 +{
  4.1544 +    XMLElement* ele = new (_elementPool.Alloc()) XMLElement( this );
  4.1545 +    ele->_memPool = &_elementPool;
  4.1546 +    ele->SetName( name );
  4.1547 +    return ele;
  4.1548 +}
  4.1549 +
  4.1550 +
  4.1551 +XMLComment* XMLDocument::NewComment( const char* str )
  4.1552 +{
  4.1553 +    XMLComment* comment = new (_commentPool.Alloc()) XMLComment( this );
  4.1554 +    comment->_memPool = &_commentPool;
  4.1555 +    comment->SetValue( str );
  4.1556 +    return comment;
  4.1557 +}
  4.1558 +
  4.1559 +
  4.1560 +XMLText* XMLDocument::NewText( const char* str )
  4.1561 +{
  4.1562 +    XMLText* text = new (_textPool.Alloc()) XMLText( this );
  4.1563 +    text->_memPool = &_textPool;
  4.1564 +    text->SetValue( str );
  4.1565 +    return text;
  4.1566 +}
  4.1567 +
  4.1568 +
  4.1569 +XMLDeclaration* XMLDocument::NewDeclaration( const char* str )
  4.1570 +{
  4.1571 +    XMLDeclaration* dec = new (_commentPool.Alloc()) XMLDeclaration( this );
  4.1572 +    dec->_memPool = &_commentPool;
  4.1573 +    dec->SetValue( str ? str : "xml version=\"1.0\" encoding=\"UTF-8\"" );
  4.1574 +    return dec;
  4.1575 +}
  4.1576 +
  4.1577 +
  4.1578 +XMLUnknown* XMLDocument::NewUnknown( const char* str )
  4.1579 +{
  4.1580 +    XMLUnknown* unk = new (_commentPool.Alloc()) XMLUnknown( this );
  4.1581 +    unk->_memPool = &_commentPool;
  4.1582 +    unk->SetValue( str );
  4.1583 +    return unk;
  4.1584 +}
  4.1585 +
  4.1586 +
  4.1587 +XMLError XMLDocument::LoadFile( const char* filename )
  4.1588 +{
  4.1589 +    DeleteChildren();
  4.1590 +    InitDocument();
  4.1591 +    FILE* fp = 0;
  4.1592 +
  4.1593 +#if defined(_MSC_VER) && (_MSC_VER >= 1400 )
  4.1594 +    errno_t err = fopen_s(&fp, filename, "rb" );
  4.1595 +    if ( !fp || err) {
  4.1596 +#else
  4.1597 +    fp = fopen( filename, "rb" );
  4.1598 +    if ( !fp) {
  4.1599 +#endif
  4.1600 +        SetError( XML_ERROR_FILE_NOT_FOUND, filename, 0 );
  4.1601 +        return _errorID;
  4.1602 +    }
  4.1603 +    LoadFile( fp );
  4.1604 +    fclose( fp );
  4.1605 +    return _errorID;
  4.1606 +}
  4.1607 +
  4.1608 +
  4.1609 +XMLError XMLDocument::LoadFile( FILE* fp )
  4.1610 +{
  4.1611 +    DeleteChildren();
  4.1612 +    InitDocument();
  4.1613 +
  4.1614 +    fseek( fp, 0, SEEK_END );
  4.1615 +    size_t size = ftell( fp );
  4.1616 +    fseek( fp, 0, SEEK_SET );
  4.1617 +
  4.1618 +    if ( size == 0 ) {
  4.1619 +        return _errorID;
  4.1620 +    }
  4.1621 +
  4.1622 +    _charBuffer = new char[size+1];
  4.1623 +    size_t read = fread( _charBuffer, 1, size, fp );
  4.1624 +    if ( read != size ) {
  4.1625 +        SetError( XML_ERROR_FILE_READ_ERROR, 0, 0 );
  4.1626 +        return _errorID;
  4.1627 +    }
  4.1628 +
  4.1629 +    _charBuffer[size] = 0;
  4.1630 +
  4.1631 +    const char* p = _charBuffer;
  4.1632 +    p = XMLUtil::SkipWhiteSpace( p );
  4.1633 +    p = XMLUtil::ReadBOM( p, &_writeBOM );
  4.1634 +    if ( !p || !*p ) {
  4.1635 +        SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 );
  4.1636 +        return _errorID;
  4.1637 +    }
  4.1638 +
  4.1639 +    ParseDeep( _charBuffer + (p-_charBuffer), 0 );
  4.1640 +    return _errorID;
  4.1641 +}
  4.1642 +
  4.1643 +
  4.1644 +XMLError XMLDocument::SaveFile( const char* filename, bool compact )
  4.1645 +{
  4.1646 +    FILE* fp = 0;
  4.1647 +#if defined(_MSC_VER) && (_MSC_VER >= 1400 )
  4.1648 +    errno_t err = fopen_s(&fp, filename, "w" );
  4.1649 +    if ( !fp || err) {
  4.1650 +#else
  4.1651 +    fp = fopen( filename, "w" );
  4.1652 +    if ( !fp) {
  4.1653 +#endif
  4.1654 +        SetError( XML_ERROR_FILE_COULD_NOT_BE_OPENED, filename, 0 );
  4.1655 +        return _errorID;
  4.1656 +    }
  4.1657 +    SaveFile(fp, compact);
  4.1658 +    fclose( fp );
  4.1659 +    return _errorID;
  4.1660 +}
  4.1661 +
  4.1662 +
  4.1663 +XMLError XMLDocument::SaveFile( FILE* fp, bool compact )
  4.1664 +{
  4.1665 +    XMLPrinter stream( fp, compact );
  4.1666 +    Print( &stream );
  4.1667 +    return _errorID;
  4.1668 +}
  4.1669 +
  4.1670 +
  4.1671 +XMLError XMLDocument::Parse( const char* p, size_t len )
  4.1672 +{
  4.1673 +    DeleteChildren();
  4.1674 +    InitDocument();
  4.1675 +
  4.1676 +    if ( !p || !*p ) {
  4.1677 +        SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 );
  4.1678 +        return _errorID;
  4.1679 +    }
  4.1680 +    if ( len == (size_t)(-1) ) {
  4.1681 +        len = strlen( p );
  4.1682 +    }
  4.1683 +    _charBuffer = new char[ len+1 ];
  4.1684 +    memcpy( _charBuffer, p, len );
  4.1685 +    _charBuffer[len] = 0;
  4.1686 +
  4.1687 +    p = XMLUtil::SkipWhiteSpace( p );
  4.1688 +    p = XMLUtil::ReadBOM( p, &_writeBOM );
  4.1689 +    if ( !p || !*p ) {
  4.1690 +        SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 );
  4.1691 +        return _errorID;
  4.1692 +    }
  4.1693 +
  4.1694 +    ParseDeep( _charBuffer, 0 );
  4.1695 +    return _errorID;
  4.1696 +}
  4.1697 +
  4.1698 +
  4.1699 +void XMLDocument::Print( XMLPrinter* streamer )
  4.1700 +{
  4.1701 +    XMLPrinter stdStreamer( stdout );
  4.1702 +    if ( !streamer ) {
  4.1703 +        streamer = &stdStreamer;
  4.1704 +    }
  4.1705 +    Accept( streamer );
  4.1706 +}
  4.1707 +
  4.1708 +
  4.1709 +void XMLDocument::SetError( XMLError error, const char* str1, const char* str2 )
  4.1710 +{
  4.1711 +    _errorID = error;
  4.1712 +    _errorStr1 = str1;
  4.1713 +    _errorStr2 = str2;
  4.1714 +}
  4.1715 +
  4.1716 +
  4.1717 +void XMLDocument::PrintError() const
  4.1718 +{
  4.1719 +    if ( _errorID ) {
  4.1720 +        static const int LEN = 20;
  4.1721 +        char buf1[LEN] = { 0 };
  4.1722 +        char buf2[LEN] = { 0 };
  4.1723 +
  4.1724 +        if ( _errorStr1 ) {
  4.1725 +            TIXML_SNPRINTF( buf1, LEN, "%s", _errorStr1 );
  4.1726 +        }
  4.1727 +        if ( _errorStr2 ) {
  4.1728 +            TIXML_SNPRINTF( buf2, LEN, "%s", _errorStr2 );
  4.1729 +        }
  4.1730 +
  4.1731 +        printf( "XMLDocument error id=%d str1=%s str2=%s\n",
  4.1732 +                _errorID, buf1, buf2 );
  4.1733 +    }
  4.1734 +}
  4.1735 +
  4.1736 +
  4.1737 +XMLPrinter::XMLPrinter( FILE* file, bool compact ) :
  4.1738 +    _elementJustOpened( false ),
  4.1739 +    _firstElement( true ),
  4.1740 +    _fp( file ),
  4.1741 +    _depth( 0 ),
  4.1742 +    _textDepth( -1 ),
  4.1743 +    _processEntities( true ),
  4.1744 +    _compactMode( compact )
  4.1745 +{
  4.1746 +    for( int i=0; i<ENTITY_RANGE; ++i ) {
  4.1747 +        _entityFlag[i] = false;
  4.1748 +        _restrictedEntityFlag[i] = false;
  4.1749 +    }
  4.1750 +    for( int i=0; i<NUM_ENTITIES; ++i ) {
  4.1751 +        TIXMLASSERT( entities[i].value < ENTITY_RANGE );
  4.1752 +        if ( entities[i].value < ENTITY_RANGE ) {
  4.1753 +            _entityFlag[ (int)entities[i].value ] = true;
  4.1754 +        }
  4.1755 +    }
  4.1756 +    _restrictedEntityFlag[(int)'&'] = true;
  4.1757 +    _restrictedEntityFlag[(int)'<'] = true;
  4.1758 +    _restrictedEntityFlag[(int)'>'] = true;	// not required, but consistency is nice
  4.1759 +    _buffer.Push( 0 );
  4.1760 +}
  4.1761 +
  4.1762 +
  4.1763 +void XMLPrinter::Print( const char* format, ... )
  4.1764 +{
  4.1765 +    va_list     va;
  4.1766 +    va_start( va, format );
  4.1767 +
  4.1768 +    if ( _fp ) {
  4.1769 +        vfprintf( _fp, format, va );
  4.1770 +    }
  4.1771 +    else {
  4.1772 +        // This seems brutally complex. Haven't figured out a better
  4.1773 +        // way on windows.
  4.1774 +#ifdef _MSC_VER
  4.1775 +        int len = -1;
  4.1776 +        int expand = 1000;
  4.1777 +        while ( len < 0 ) {
  4.1778 +            len = vsnprintf_s( _accumulator.Mem(), _accumulator.Capacity(), _TRUNCATE, format, va );
  4.1779 +            if ( len < 0 ) {
  4.1780 +                expand *= 3/2;
  4.1781 +                _accumulator.PushArr( expand );
  4.1782 +            }
  4.1783 +        }
  4.1784 +        char* p = _buffer.PushArr( len ) - 1;
  4.1785 +        memcpy( p, _accumulator.Mem(), len+1 );
  4.1786 +#else
  4.1787 +        int len = vsnprintf( 0, 0, format, va );
  4.1788 +        // Close out and re-start the va-args
  4.1789 +        va_end( va );
  4.1790 +        va_start( va, format );
  4.1791 +        char* p = _buffer.PushArr( len ) - 1;
  4.1792 +        vsnprintf( p, len+1, format, va );
  4.1793 +#endif
  4.1794 +    }
  4.1795 +    va_end( va );
  4.1796 +}
  4.1797 +
  4.1798 +
  4.1799 +void XMLPrinter::PrintSpace( int depth )
  4.1800 +{
  4.1801 +    for( int i=0; i<depth; ++i ) {
  4.1802 +        Print( "    " );
  4.1803 +    }
  4.1804 +}
  4.1805 +
  4.1806 +
  4.1807 +void XMLPrinter::PrintString( const char* p, bool restricted )
  4.1808 +{
  4.1809 +    // Look for runs of bytes between entities to print.
  4.1810 +    const char* q = p;
  4.1811 +    const bool* flag = restricted ? _restrictedEntityFlag : _entityFlag;
  4.1812 +
  4.1813 +    if ( _processEntities ) {
  4.1814 +        while ( *q ) {
  4.1815 +            // Remember, char is sometimes signed. (How many times has that bitten me?)
  4.1816 +            if ( *q > 0 && *q < ENTITY_RANGE ) {
  4.1817 +                // Check for entities. If one is found, flush
  4.1818 +                // the stream up until the entity, write the
  4.1819 +                // entity, and keep looking.
  4.1820 +                if ( flag[(unsigned)(*q)] ) {
  4.1821 +                    while ( p < q ) {
  4.1822 +                        Print( "%c", *p );
  4.1823 +                        ++p;
  4.1824 +                    }
  4.1825 +                    for( int i=0; i<NUM_ENTITIES; ++i ) {
  4.1826 +                        if ( entities[i].value == *q ) {
  4.1827 +                            Print( "&%s;", entities[i].pattern );
  4.1828 +                            break;
  4.1829 +                        }
  4.1830 +                    }
  4.1831 +                    ++p;
  4.1832 +                }
  4.1833 +            }
  4.1834 +            ++q;
  4.1835 +        }
  4.1836 +    }
  4.1837 +    // Flush the remaining string. This will be the entire
  4.1838 +    // string if an entity wasn't found.
  4.1839 +    if ( !_processEntities || (q-p > 0) ) {
  4.1840 +        Print( "%s", p );
  4.1841 +    }
  4.1842 +}
  4.1843 +
  4.1844 +
  4.1845 +void XMLPrinter::PushHeader( bool writeBOM, bool writeDec )
  4.1846 +{
  4.1847 +    static const unsigned char bom[] = { TIXML_UTF_LEAD_0, TIXML_UTF_LEAD_1, TIXML_UTF_LEAD_2, 0 };
  4.1848 +    if ( writeBOM ) {
  4.1849 +        Print( "%s", bom );
  4.1850 +    }
  4.1851 +    if ( writeDec ) {
  4.1852 +        PushDeclaration( "xml version=\"1.0\"" );
  4.1853 +    }
  4.1854 +}
  4.1855 +
  4.1856 +
  4.1857 +void XMLPrinter::OpenElement( const char* name )
  4.1858 +{
  4.1859 +    if ( _elementJustOpened ) {
  4.1860 +        SealElement();
  4.1861 +    }
  4.1862 +    _stack.Push( name );
  4.1863 +
  4.1864 +    if ( _textDepth < 0 && !_firstElement && !_compactMode ) {
  4.1865 +        Print( "\n" );
  4.1866 +        PrintSpace( _depth );
  4.1867 +    }
  4.1868 +
  4.1869 +    Print( "<%s", name );
  4.1870 +    _elementJustOpened = true;
  4.1871 +    _firstElement = false;
  4.1872 +    ++_depth;
  4.1873 +}
  4.1874 +
  4.1875 +
  4.1876 +void XMLPrinter::PushAttribute( const char* name, const char* value )
  4.1877 +{
  4.1878 +    TIXMLASSERT( _elementJustOpened );
  4.1879 +    Print( " %s=\"", name );
  4.1880 +    PrintString( value, false );
  4.1881 +    Print( "\"" );
  4.1882 +}
  4.1883 +
  4.1884 +
  4.1885 +void XMLPrinter::PushAttribute( const char* name, int v )
  4.1886 +{
  4.1887 +    char buf[BUF_SIZE];
  4.1888 +    XMLUtil::ToStr( v, buf, BUF_SIZE );
  4.1889 +    PushAttribute( name, buf );
  4.1890 +}
  4.1891 +
  4.1892 +
  4.1893 +void XMLPrinter::PushAttribute( const char* name, unsigned v )
  4.1894 +{
  4.1895 +    char buf[BUF_SIZE];
  4.1896 +    XMLUtil::ToStr( v, buf, BUF_SIZE );
  4.1897 +    PushAttribute( name, buf );
  4.1898 +}
  4.1899 +
  4.1900 +
  4.1901 +void XMLPrinter::PushAttribute( const char* name, bool v )
  4.1902 +{
  4.1903 +    char buf[BUF_SIZE];
  4.1904 +    XMLUtil::ToStr( v, buf, BUF_SIZE );
  4.1905 +    PushAttribute( name, buf );
  4.1906 +}
  4.1907 +
  4.1908 +
  4.1909 +void XMLPrinter::PushAttribute( const char* name, double v )
  4.1910 +{
  4.1911 +    char buf[BUF_SIZE];
  4.1912 +    XMLUtil::ToStr( v, buf, BUF_SIZE );
  4.1913 +    PushAttribute( name, buf );
  4.1914 +}
  4.1915 +
  4.1916 +
  4.1917 +void XMLPrinter::CloseElement()
  4.1918 +{
  4.1919 +    --_depth;
  4.1920 +    const char* name = _stack.Pop();
  4.1921 +
  4.1922 +    if ( _elementJustOpened ) {
  4.1923 +        Print( "/>" );
  4.1924 +    }
  4.1925 +    else {
  4.1926 +        if ( _textDepth < 0 && !_compactMode) {
  4.1927 +            Print( "\n" );
  4.1928 +            PrintSpace( _depth );
  4.1929 +        }
  4.1930 +        Print( "</%s>", name );
  4.1931 +    }
  4.1932 +
  4.1933 +    if ( _textDepth == _depth ) {
  4.1934 +        _textDepth = -1;
  4.1935 +    }
  4.1936 +    if ( _depth == 0 && !_compactMode) {
  4.1937 +        Print( "\n" );
  4.1938 +    }
  4.1939 +    _elementJustOpened = false;
  4.1940 +}
  4.1941 +
  4.1942 +
  4.1943 +void XMLPrinter::SealElement()
  4.1944 +{
  4.1945 +    _elementJustOpened = false;
  4.1946 +    Print( ">" );
  4.1947 +}
  4.1948 +
  4.1949 +
  4.1950 +void XMLPrinter::PushText( const char* text, bool cdata )
  4.1951 +{
  4.1952 +    _textDepth = _depth-1;
  4.1953 +
  4.1954 +    if ( _elementJustOpened ) {
  4.1955 +        SealElement();
  4.1956 +    }
  4.1957 +    if ( cdata ) {
  4.1958 +        Print( "<![CDATA[" );
  4.1959 +        Print( "%s", text );
  4.1960 +        Print( "]]>" );
  4.1961 +    }
  4.1962 +    else {
  4.1963 +        PrintString( text, true );
  4.1964 +    }
  4.1965 +}
  4.1966 +
  4.1967 +void XMLPrinter::PushText( int value )
  4.1968 +{
  4.1969 +    char buf[BUF_SIZE];
  4.1970 +    XMLUtil::ToStr( value, buf, BUF_SIZE );
  4.1971 +    PushText( buf, false );
  4.1972 +}
  4.1973 +
  4.1974 +
  4.1975 +void XMLPrinter::PushText( unsigned value )
  4.1976 +{
  4.1977 +    char buf[BUF_SIZE];
  4.1978 +    XMLUtil::ToStr( value, buf, BUF_SIZE );
  4.1979 +    PushText( buf, false );
  4.1980 +}
  4.1981 +
  4.1982 +
  4.1983 +void XMLPrinter::PushText( bool value )
  4.1984 +{
  4.1985 +    char buf[BUF_SIZE];
  4.1986 +    XMLUtil::ToStr( value, buf, BUF_SIZE );
  4.1987 +    PushText( buf, false );
  4.1988 +}
  4.1989 +
  4.1990 +
  4.1991 +void XMLPrinter::PushText( float value )
  4.1992 +{
  4.1993 +    char buf[BUF_SIZE];
  4.1994 +    XMLUtil::ToStr( value, buf, BUF_SIZE );
  4.1995 +    PushText( buf, false );
  4.1996 +}
  4.1997 +
  4.1998 +
  4.1999 +void XMLPrinter::PushText( double value )
  4.2000 +{
  4.2001 +    char buf[BUF_SIZE];
  4.2002 +    XMLUtil::ToStr( value, buf, BUF_SIZE );
  4.2003 +    PushText( buf, false );
  4.2004 +}
  4.2005 +
  4.2006 +
  4.2007 +void XMLPrinter::PushComment( const char* comment )
  4.2008 +{
  4.2009 +    if ( _elementJustOpened ) {
  4.2010 +        SealElement();
  4.2011 +    }
  4.2012 +    if ( _textDepth < 0 && !_firstElement && !_compactMode) {
  4.2013 +        Print( "\n" );
  4.2014 +        PrintSpace( _depth );
  4.2015 +    }
  4.2016 +    _firstElement = false;
  4.2017 +    Print( "<!--%s-->", comment );
  4.2018 +}
  4.2019 +
  4.2020 +
  4.2021 +void XMLPrinter::PushDeclaration( const char* value )
  4.2022 +{
  4.2023 +    if ( _elementJustOpened ) {
  4.2024 +        SealElement();
  4.2025 +    }
  4.2026 +    if ( _textDepth < 0 && !_firstElement && !_compactMode) {
  4.2027 +        Print( "\n" );
  4.2028 +        PrintSpace( _depth );
  4.2029 +    }
  4.2030 +    _firstElement = false;
  4.2031 +    Print( "<?%s?>", value );
  4.2032 +}
  4.2033 +
  4.2034 +
  4.2035 +void XMLPrinter::PushUnknown( const char* value )
  4.2036 +{
  4.2037 +    if ( _elementJustOpened ) {
  4.2038 +        SealElement();
  4.2039 +    }
  4.2040 +    if ( _textDepth < 0 && !_firstElement && !_compactMode) {
  4.2041 +        Print( "\n" );
  4.2042 +        PrintSpace( _depth );
  4.2043 +    }
  4.2044 +    _firstElement = false;
  4.2045 +    Print( "<!%s>", value );
  4.2046 +}
  4.2047 +
  4.2048 +
  4.2049 +bool XMLPrinter::VisitEnter( const XMLDocument& doc )
  4.2050 +{
  4.2051 +    _processEntities = doc.ProcessEntities();
  4.2052 +    if ( doc.HasBOM() ) {
  4.2053 +        PushHeader( true, false );
  4.2054 +    }
  4.2055 +    return true;
  4.2056 +}
  4.2057 +
  4.2058 +
  4.2059 +bool XMLPrinter::VisitEnter( const XMLElement& element, const XMLAttribute* attribute )
  4.2060 +{
  4.2061 +    OpenElement( element.Name() );
  4.2062 +    while ( attribute ) {
  4.2063 +        PushAttribute( attribute->Name(), attribute->Value() );
  4.2064 +        attribute = attribute->Next();
  4.2065 +    }
  4.2066 +    return true;
  4.2067 +}
  4.2068 +
  4.2069 +
  4.2070 +bool XMLPrinter::VisitExit( const XMLElement& )
  4.2071 +{
  4.2072 +    CloseElement();
  4.2073 +    return true;
  4.2074 +}
  4.2075 +
  4.2076 +
  4.2077 +bool XMLPrinter::Visit( const XMLText& text )
  4.2078 +{
  4.2079 +    PushText( text.Value(), text.CData() );
  4.2080 +    return true;
  4.2081 +}
  4.2082 +
  4.2083 +
  4.2084 +bool XMLPrinter::Visit( const XMLComment& comment )
  4.2085 +{
  4.2086 +    PushComment( comment.Value() );
  4.2087 +    return true;
  4.2088 +}
  4.2089 +
  4.2090 +bool XMLPrinter::Visit( const XMLDeclaration& declaration )
  4.2091 +{
  4.2092 +    PushDeclaration( declaration.Value() );
  4.2093 +    return true;
  4.2094 +}
  4.2095 +
  4.2096 +
  4.2097 +bool XMLPrinter::Visit( const XMLUnknown& unknown )
  4.2098 +{
  4.2099 +    PushUnknown( unknown.Value() );
  4.2100 +    return true;
  4.2101 +}
  4.2102 +
  4.2103 +}   // namespace tinyxml2
  4.2104 +
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/3rdParty/TinyXml/tinyxml2.h	Wed Jan 14 06:51:16 2015 +0200
     5.3 @@ -0,0 +1,1911 @@
     5.4 +/*
     5.5 +Original code by Lee Thomason (www.grinninglizard.com)
     5.6 +
     5.7 +This software is provided 'as-is', without any express or implied
     5.8 +warranty. In no event will the authors be held liable for any
     5.9 +damages arising from the use of this software.
    5.10 +
    5.11 +Permission is granted to anyone to use this software for any
    5.12 +purpose, including commercial applications, and to alter it and
    5.13 +redistribute it freely, subject to the following restrictions:
    5.14 +
    5.15 +1. The origin of this software must not be misrepresented; you must
    5.16 +not claim that you wrote the original software. If you use this
    5.17 +software in a product, an acknowledgment in the product documentation
    5.18 +would be appreciated but is not required.
    5.19 +
    5.20 +2. Altered source versions must be plainly marked as such, and
    5.21 +must not be misrepresented as being the original software.
    5.22 +
    5.23 +3. This notice may not be removed or altered from any source
    5.24 +distribution.
    5.25 +*/
    5.26 +
    5.27 +#ifndef TINYXML2_INCLUDED
    5.28 +#define TINYXML2_INCLUDED
    5.29 +
    5.30 +#if defined(ANDROID_NDK) || defined(__BORLANDC__)
    5.31 +#   include <ctype.h>
    5.32 +#   include <limits.h>
    5.33 +#   include <stdio.h>
    5.34 +#   include <stdlib.h>
    5.35 +#   include <string.h>
    5.36 +#   include <stdarg.h>
    5.37 +#else
    5.38 +#   include <cctype>
    5.39 +#   include <climits>
    5.40 +#   include <cstdio>
    5.41 +#   include <cstdlib>
    5.42 +#   include <cstring>
    5.43 +#   include <cstdarg>
    5.44 +#endif
    5.45 +
    5.46 +/*
    5.47 +   TODO: intern strings instead of allocation.
    5.48 +*/
    5.49 +/*
    5.50 +	gcc:
    5.51 +        g++ -Wall -DDEBUG tinyxml2.cpp xmltest.cpp -o gccxmltest.exe
    5.52 +
    5.53 +    Formatting, Artistic Style:
    5.54 +        AStyle.exe --style=1tbs --indent-switches --break-closing-brackets --indent-preprocessor tinyxml2.cpp tinyxml2.h
    5.55 +*/
    5.56 +
    5.57 +#if defined( _DEBUG ) || defined( DEBUG ) || defined (__DEBUG__)
    5.58 +#   ifndef DEBUG
    5.59 +#       define DEBUG
    5.60 +#   endif
    5.61 +#endif
    5.62 +
    5.63 +
    5.64 +#if defined(DEBUG)
    5.65 +#   if defined(_MSC_VER)
    5.66 +#       define TIXMLASSERT( x )           if ( !(x)) { __debugbreak(); } //if ( !(x)) WinDebugBreak()
    5.67 +#   elif defined (ANDROID_NDK)
    5.68 +#       include <android/log.h>
    5.69 +#       define TIXMLASSERT( x )           if ( !(x)) { __android_log_assert( "assert", "grinliz", "ASSERT in '%s' at %d.", __FILE__, __LINE__ ); }
    5.70 +#   else
    5.71 +#       include <assert.h>
    5.72 +#       define TIXMLASSERT                assert
    5.73 +#   endif
    5.74 +#   else
    5.75 +#       define TIXMLASSERT( x )           {}
    5.76 +#endif
    5.77 +
    5.78 +
    5.79 +#if defined(_MSC_VER) && (_MSC_VER >= 1400 )
    5.80 +// Microsoft visual studio, version 2005 and higher.
    5.81 +/*int _snprintf_s(
    5.82 +   char *buffer,
    5.83 +   size_t sizeOfBuffer,
    5.84 +   size_t count,
    5.85 +   const char *format [,
    5.86 +	  argument] ...
    5.87 +);*/
    5.88 +inline int TIXML_SNPRINTF( char* buffer, size_t size, const char* format, ... )
    5.89 +{
    5.90 +    va_list va;
    5.91 +    va_start( va, format );
    5.92 +    int result = vsnprintf_s( buffer, size, _TRUNCATE, format, va );
    5.93 +    va_end( va );
    5.94 +    return result;
    5.95 +}
    5.96 +#define TIXML_SSCANF   sscanf_s
    5.97 +#else
    5.98 +// GCC version 3 and higher
    5.99 +//#warning( "Using sn* functions." )
   5.100 +#define TIXML_SNPRINTF snprintf
   5.101 +#define TIXML_SSCANF   sscanf
   5.102 +#endif
   5.103 +
   5.104 +static const int TIXML2_MAJOR_VERSION = 1;
   5.105 +static const int TIXML2_MINOR_VERSION = 0;
   5.106 +static const int TIXML2_PATCH_VERSION = 9;
   5.107 +
   5.108 +namespace tinyxml2
   5.109 +{
   5.110 +class XMLDocument;
   5.111 +class XMLElement;
   5.112 +class XMLAttribute;
   5.113 +class XMLComment;
   5.114 +class XMLNode;
   5.115 +class XMLText;
   5.116 +class XMLDeclaration;
   5.117 +class XMLUnknown;
   5.118 +
   5.119 +class XMLPrinter;
   5.120 +
   5.121 +/*
   5.122 +	A class that wraps strings. Normally stores the start and end
   5.123 +	pointers into the XML file itself, and will apply normalization
   5.124 +	and entity translation if actually read. Can also store (and memory
   5.125 +	manage) a traditional char[]
   5.126 +*/
   5.127 +class StrPair
   5.128 +{
   5.129 +public:
   5.130 +    enum {
   5.131 +        NEEDS_ENTITY_PROCESSING			= 0x01,
   5.132 +        NEEDS_NEWLINE_NORMALIZATION		= 0x02,
   5.133 +        COLLAPSE_WHITESPACE				= 0x04,
   5.134 +
   5.135 +        TEXT_ELEMENT		            = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
   5.136 +        TEXT_ELEMENT_LEAVE_ENTITIES		= NEEDS_NEWLINE_NORMALIZATION,
   5.137 +        ATTRIBUTE_NAME		            = 0,
   5.138 +        ATTRIBUTE_VALUE		            = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
   5.139 +        ATTRIBUTE_VALUE_LEAVE_ENTITIES  = NEEDS_NEWLINE_NORMALIZATION,
   5.140 +        COMMENT				            = NEEDS_NEWLINE_NORMALIZATION
   5.141 +    };
   5.142 +
   5.143 +    StrPair() : _flags( 0 ), _start( 0 ), _end( 0 ) {}
   5.144 +    ~StrPair();
   5.145 +
   5.146 +    void Set( char* start, char* end, int flags ) {
   5.147 +        Reset();
   5.148 +        _start  = start;
   5.149 +        _end    = end;
   5.150 +        _flags  = flags | NEEDS_FLUSH;
   5.151 +    }
   5.152 +
   5.153 +    const char* GetStr();
   5.154 +
   5.155 +    bool Empty() const {
   5.156 +        return _start == _end;
   5.157 +    }
   5.158 +
   5.159 +    void SetInternedStr( const char* str ) {
   5.160 +        Reset();
   5.161 +        _start = const_cast<char*>(str);
   5.162 +    }
   5.163 +
   5.164 +    void SetStr( const char* str, int flags=0 );
   5.165 +
   5.166 +    char* ParseText( char* in, const char* endTag, int strFlags );
   5.167 +    char* ParseName( char* in );
   5.168 +
   5.169 +private:
   5.170 +    void Reset();
   5.171 +    void CollapseWhitespace();
   5.172 +
   5.173 +    enum {
   5.174 +        NEEDS_FLUSH = 0x100,
   5.175 +        NEEDS_DELETE = 0x200
   5.176 +    };
   5.177 +
   5.178 +    // After parsing, if *end != 0, it can be set to zero.
   5.179 +    int     _flags;
   5.180 +    char*   _start;
   5.181 +    char*   _end;
   5.182 +};
   5.183 +
   5.184 +
   5.185 +/*
   5.186 +	A dynamic array of Plain Old Data. Doesn't support constructors, etc.
   5.187 +	Has a small initial memory pool, so that low or no usage will not
   5.188 +	cause a call to new/delete
   5.189 +*/
   5.190 +template <class T, int INIT>
   5.191 +class DynArray
   5.192 +{
   5.193 +public:
   5.194 +    DynArray< T, INIT >() {
   5.195 +        _mem = _pool;
   5.196 +        _allocated = INIT;
   5.197 +        _size = 0;
   5.198 +    }
   5.199 +
   5.200 +    ~DynArray() {
   5.201 +        if ( _mem != _pool ) {
   5.202 +            delete [] _mem;
   5.203 +        }
   5.204 +    }
   5.205 +
   5.206 +    void Push( T t ) {
   5.207 +        EnsureCapacity( _size+1 );
   5.208 +        _mem[_size++] = t;
   5.209 +    }
   5.210 +
   5.211 +    T* PushArr( int count ) {
   5.212 +        EnsureCapacity( _size+count );
   5.213 +        T* ret = &_mem[_size];
   5.214 +        _size += count;
   5.215 +        return ret;
   5.216 +    }
   5.217 +
   5.218 +    T Pop() {
   5.219 +        return _mem[--_size];
   5.220 +    }
   5.221 +
   5.222 +    void PopArr( int count ) {
   5.223 +        TIXMLASSERT( _size >= count );
   5.224 +        _size -= count;
   5.225 +    }
   5.226 +
   5.227 +    bool Empty() const					{
   5.228 +        return _size == 0;
   5.229 +    }
   5.230 +
   5.231 +    T& operator[](int i)				{
   5.232 +        TIXMLASSERT( i>= 0 && i < _size );
   5.233 +        return _mem[i];
   5.234 +    }
   5.235 +
   5.236 +    const T& operator[](int i) const	{
   5.237 +        TIXMLASSERT( i>= 0 && i < _size );
   5.238 +        return _mem[i];
   5.239 +    }
   5.240 +
   5.241 +    int Size() const					{
   5.242 +        return _size;
   5.243 +    }
   5.244 +
   5.245 +    int Capacity() const				{
   5.246 +        return _allocated;
   5.247 +    }
   5.248 +
   5.249 +    const T* Mem() const				{
   5.250 +        return _mem;
   5.251 +    }
   5.252 +
   5.253 +    T* Mem()							{
   5.254 +        return _mem;
   5.255 +    }
   5.256 +
   5.257 +private:
   5.258 +    void EnsureCapacity( int cap ) {
   5.259 +        if ( cap > _allocated ) {
   5.260 +            int newAllocated = cap * 2;
   5.261 +            T* newMem = new T[newAllocated];
   5.262 +            memcpy( newMem, _mem, sizeof(T)*_size );	// warning: not using constructors, only works for PODs
   5.263 +            if ( _mem != _pool ) {
   5.264 +                delete [] _mem;
   5.265 +            }
   5.266 +            _mem = newMem;
   5.267 +            _allocated = newAllocated;
   5.268 +        }
   5.269 +    }
   5.270 +
   5.271 +    T*  _mem;
   5.272 +    T   _pool[INIT];
   5.273 +    int _allocated;		// objects allocated
   5.274 +    int _size;			// number objects in use
   5.275 +};
   5.276 +
   5.277 +
   5.278 +/*
   5.279 +	Parent virtual class of a pool for fast allocation
   5.280 +	and deallocation of objects.
   5.281 +*/
   5.282 +class MemPool
   5.283 +{
   5.284 +public:
   5.285 +    MemPool() {}
   5.286 +    virtual ~MemPool() {}
   5.287 +
   5.288 +    virtual int ItemSize() const = 0;
   5.289 +    virtual void* Alloc() = 0;
   5.290 +    virtual void Free( void* ) = 0;
   5.291 +    virtual void SetTracked() = 0;
   5.292 +};
   5.293 +
   5.294 +
   5.295 +/*
   5.296 +	Template child class to create pools of the correct type.
   5.297 +*/
   5.298 +template< int SIZE >
   5.299 +class MemPoolT : public MemPool
   5.300 +{
   5.301 +public:
   5.302 +    MemPoolT() : _root(0), _currentAllocs(0), _nAllocs(0), _maxAllocs(0), _nUntracked(0)	{}
   5.303 +    ~MemPoolT() {
   5.304 +        // Delete the blocks.
   5.305 +        for( int i=0; i<_blockPtrs.Size(); ++i ) {
   5.306 +            delete _blockPtrs[i];
   5.307 +        }
   5.308 +    }
   5.309 +
   5.310 +    virtual int ItemSize() const	{
   5.311 +        return SIZE;
   5.312 +    }
   5.313 +    int CurrentAllocs() const		{
   5.314 +        return _currentAllocs;
   5.315 +    }
   5.316 +
   5.317 +    virtual void* Alloc() {
   5.318 +        if ( !_root ) {
   5.319 +            // Need a new block.
   5.320 +            Block* block = new Block();
   5.321 +            _blockPtrs.Push( block );
   5.322 +
   5.323 +            for( int i=0; i<COUNT-1; ++i ) {
   5.324 +                block->chunk[i].next = &block->chunk[i+1];
   5.325 +            }
   5.326 +            block->chunk[COUNT-1].next = 0;
   5.327 +            _root = block->chunk;
   5.328 +        }
   5.329 +        void* result = _root;
   5.330 +        _root = _root->next;
   5.331 +
   5.332 +        ++_currentAllocs;
   5.333 +        if ( _currentAllocs > _maxAllocs ) {
   5.334 +            _maxAllocs = _currentAllocs;
   5.335 +        }
   5.336 +        _nAllocs++;
   5.337 +        _nUntracked++;
   5.338 +        return result;
   5.339 +    }
   5.340 +    virtual void Free( void* mem ) {
   5.341 +        if ( !mem ) {
   5.342 +            return;
   5.343 +        }
   5.344 +        --_currentAllocs;
   5.345 +        Chunk* chunk = (Chunk*)mem;
   5.346 +#ifdef DEBUG
   5.347 +        memset( chunk, 0xfe, sizeof(Chunk) );
   5.348 +#endif
   5.349 +        chunk->next = _root;
   5.350 +        _root = chunk;
   5.351 +    }
   5.352 +    void Trace( const char* name ) {
   5.353 +        printf( "Mempool %s watermark=%d [%dk] current=%d size=%d nAlloc=%d blocks=%d\n",
   5.354 +                name, _maxAllocs, _maxAllocs*SIZE/1024, _currentAllocs, SIZE, _nAllocs, _blockPtrs.Size() );
   5.355 +    }
   5.356 +
   5.357 +    void SetTracked() {
   5.358 +        _nUntracked--;
   5.359 +    }
   5.360 +
   5.361 +    int Untracked() const {
   5.362 +        return _nUntracked;
   5.363 +    }
   5.364 +
   5.365 +    enum { COUNT = 1024/SIZE }; // Some compilers do not accept to use COUNT in private part if COUNT is private
   5.366 +
   5.367 +private:
   5.368 +    union Chunk {
   5.369 +        Chunk*  next;
   5.370 +        char    mem[SIZE];
   5.371 +    };
   5.372 +    struct Block {
   5.373 +        Chunk chunk[COUNT];
   5.374 +    };
   5.375 +    DynArray< Block*, 10 > _blockPtrs;
   5.376 +    Chunk* _root;
   5.377 +
   5.378 +    int _currentAllocs;
   5.379 +    int _nAllocs;
   5.380 +    int _maxAllocs;
   5.381 +    int _nUntracked;
   5.382 +};
   5.383 +
   5.384 +
   5.385 +
   5.386 +/**
   5.387 +	Implements the interface to the "Visitor pattern" (see the Accept() method.)
   5.388 +	If you call the Accept() method, it requires being passed a XMLVisitor
   5.389 +	class to handle callbacks. For nodes that contain other nodes (Document, Element)
   5.390 +	you will get called with a VisitEnter/VisitExit pair. Nodes that are always leafs
   5.391 +	are simply called with Visit().
   5.392 +
   5.393 +	If you return 'true' from a Visit method, recursive parsing will continue. If you return
   5.394 +	false, <b>no children of this node or its sibilings</b> will be visited.
   5.395 +
   5.396 +	All flavors of Visit methods have a default implementation that returns 'true' (continue
   5.397 +	visiting). You need to only override methods that are interesting to you.
   5.398 +
   5.399 +	Generally Accept() is called on the TiXmlDocument, although all nodes support visiting.
   5.400 +
   5.401 +	You should never change the document from a callback.
   5.402 +
   5.403 +	@sa XMLNode::Accept()
   5.404 +*/
   5.405 +class XMLVisitor
   5.406 +{
   5.407 +public:
   5.408 +    virtual ~XMLVisitor() {}
   5.409 +
   5.410 +    /// Visit a document.
   5.411 +    virtual bool VisitEnter( const XMLDocument& /*doc*/ )			{
   5.412 +        return true;
   5.413 +    }
   5.414 +    /// Visit a document.
   5.415 +    virtual bool VisitExit( const XMLDocument& /*doc*/ )			{
   5.416 +        return true;
   5.417 +    }
   5.418 +
   5.419 +    /// Visit an element.
   5.420 +    virtual bool VisitEnter( const XMLElement& /*element*/, const XMLAttribute* /*firstAttribute*/ )	{
   5.421 +        return true;
   5.422 +    }
   5.423 +    /// Visit an element.
   5.424 +    virtual bool VisitExit( const XMLElement& /*element*/ )			{
   5.425 +        return true;
   5.426 +    }
   5.427 +
   5.428 +    /// Visit a declaration.
   5.429 +    virtual bool Visit( const XMLDeclaration& /*declaration*/ )		{
   5.430 +        return true;
   5.431 +    }
   5.432 +    /// Visit a text node.
   5.433 +    virtual bool Visit( const XMLText& /*text*/ )					{
   5.434 +        return true;
   5.435 +    }
   5.436 +    /// Visit a comment node.
   5.437 +    virtual bool Visit( const XMLComment& /*comment*/ )				{
   5.438 +        return true;
   5.439 +    }
   5.440 +    /// Visit an unknown node.
   5.441 +    virtual bool Visit( const XMLUnknown& /*unknown*/ )				{
   5.442 +        return true;
   5.443 +    }
   5.444 +};
   5.445 +
   5.446 +
   5.447 +/*
   5.448 +	Utility functionality.
   5.449 +*/
   5.450 +class XMLUtil
   5.451 +{
   5.452 +public:
   5.453 +    // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't
   5.454 +    // correct, but simple, and usually works.
   5.455 +    static const char* SkipWhiteSpace( const char* p )	{
   5.456 +        while( !IsUTF8Continuation(*p) && isspace( *reinterpret_cast<const unsigned char*>(p) ) ) {
   5.457 +            ++p;
   5.458 +        }
   5.459 +        return p;
   5.460 +    }
   5.461 +    static char* SkipWhiteSpace( char* p )				{
   5.462 +        while( !IsUTF8Continuation(*p) && isspace( *reinterpret_cast<unsigned char*>(p) ) )		{
   5.463 +            ++p;
   5.464 +        }
   5.465 +        return p;
   5.466 +    }
   5.467 +    static bool IsWhiteSpace( char p )					{
   5.468 +        return !IsUTF8Continuation(p) && isspace( static_cast<unsigned char>(p) );
   5.469 +    }
   5.470 +
   5.471 +    inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX )  {
   5.472 +        int n = 0;
   5.473 +        if ( p == q ) {
   5.474 +            return true;
   5.475 +        }
   5.476 +        while( *p && *q && *p == *q && n<nChar ) {
   5.477 +            ++p;
   5.478 +            ++q;
   5.479 +            ++n;
   5.480 +        }
   5.481 +        if ( (n == nChar) || ( *p == 0 && *q == 0 ) ) {
   5.482 +            return true;
   5.483 +        }
   5.484 +        return false;
   5.485 +    }
   5.486 +    inline static int IsUTF8Continuation( const char p ) {
   5.487 +        return p & 0x80;
   5.488 +    }
   5.489 +    inline static int IsAlphaNum( unsigned char anyByte )	{
   5.490 +        return ( anyByte < 128 ) ? isalnum( anyByte ) : 1;
   5.491 +    }
   5.492 +    inline static int IsAlpha( unsigned char anyByte )		{
   5.493 +        return ( anyByte < 128 ) ? isalpha( anyByte ) : 1;
   5.494 +    }
   5.495 +
   5.496 +    static const char* ReadBOM( const char* p, bool* hasBOM );
   5.497 +    // p is the starting location,
   5.498 +    // the UTF-8 value of the entity will be placed in value, and length filled in.
   5.499 +    static const char* GetCharacterRef( const char* p, char* value, int* length );
   5.500 +    static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length );
   5.501 +
   5.502 +    // converts primitive types to strings
   5.503 +    static void ToStr( int v, char* buffer, int bufferSize );
   5.504 +    static void ToStr( unsigned v, char* buffer, int bufferSize );
   5.505 +    static void ToStr( bool v, char* buffer, int bufferSize );
   5.506 +    static void ToStr( float v, char* buffer, int bufferSize );
   5.507 +    static void ToStr( double v, char* buffer, int bufferSize );
   5.508 +
   5.509 +    // converts strings to primitive types
   5.510 +    static bool	ToInt( const char* str, int* value );
   5.511 +    static bool ToUnsigned( const char* str, unsigned* value );
   5.512 +    static bool	ToBool( const char* str, bool* value );
   5.513 +    static bool	ToFloat( const char* str, float* value );
   5.514 +    static bool ToDouble( const char* str, double* value );
   5.515 +};
   5.516 +
   5.517 +
   5.518 +/** XMLNode is a base class for every object that is in the
   5.519 +	XML Document Object Model (DOM), except XMLAttributes.
   5.520 +	Nodes have siblings, a parent, and children which can
   5.521 +	be navigated. A node is always in a XMLDocument.
   5.522 +	The type of a XMLNode can be queried, and it can
   5.523 +	be cast to its more defined type.
   5.524 +
   5.525 +	A XMLDocument allocates memory for all its Nodes.
   5.526 +	When the XMLDocument gets deleted, all its Nodes
   5.527 +	will also be deleted.
   5.528 +
   5.529 +	@verbatim
   5.530 +	A Document can contain:	Element	(container or leaf)
   5.531 +							Comment (leaf)
   5.532 +							Unknown (leaf)
   5.533 +							Declaration( leaf )
   5.534 +
   5.535 +	An Element can contain:	Element (container or leaf)
   5.536 +							Text	(leaf)
   5.537 +							Attributes (not on tree)
   5.538 +							Comment (leaf)
   5.539 +							Unknown (leaf)
   5.540 +
   5.541 +	@endverbatim
   5.542 +*/
   5.543 +class XMLNode
   5.544 +{
   5.545 +    friend class XMLDocument;
   5.546 +    friend class XMLElement;
   5.547 +public:
   5.548 +
   5.549 +    /// Get the XMLDocument that owns this XMLNode.
   5.550 +    const XMLDocument* GetDocument() const	{
   5.551 +        return _document;
   5.552 +    }
   5.553 +    /// Get the XMLDocument that owns this XMLNode.
   5.554 +    XMLDocument* GetDocument()				{
   5.555 +        return _document;
   5.556 +    }
   5.557 +
   5.558 +    /// Safely cast to an Element, or null.
   5.559 +    virtual XMLElement*		ToElement()		{
   5.560 +        return 0;
   5.561 +    }
   5.562 +    /// Safely cast to Text, or null.
   5.563 +    virtual XMLText*		ToText()		{
   5.564 +        return 0;
   5.565 +    }
   5.566 +    /// Safely cast to a Comment, or null.
   5.567 +    virtual XMLComment*		ToComment()		{
   5.568 +        return 0;
   5.569 +    }
   5.570 +    /// Safely cast to a Document, or null.
   5.571 +    virtual XMLDocument*	ToDocument()	{
   5.572 +        return 0;
   5.573 +    }
   5.574 +    /// Safely cast to a Declaration, or null.
   5.575 +    virtual XMLDeclaration*	ToDeclaration()	{
   5.576 +        return 0;
   5.577 +    }
   5.578 +    /// Safely cast to an Unknown, or null.
   5.579 +    virtual XMLUnknown*		ToUnknown()		{
   5.580 +        return 0;
   5.581 +    }
   5.582 +
   5.583 +    virtual const XMLElement*		ToElement() const		{
   5.584 +        return 0;
   5.585 +    }
   5.586 +    virtual const XMLText*			ToText() const			{
   5.587 +        return 0;
   5.588 +    }
   5.589 +    virtual const XMLComment*		ToComment() const		{
   5.590 +        return 0;
   5.591 +    }
   5.592 +    virtual const XMLDocument*		ToDocument() const		{
   5.593 +        return 0;
   5.594 +    }
   5.595 +    virtual const XMLDeclaration*	ToDeclaration() const	{
   5.596 +        return 0;
   5.597 +    }
   5.598 +    virtual const XMLUnknown*		ToUnknown() const		{
   5.599 +        return 0;
   5.600 +    }
   5.601 +
   5.602 +    /** The meaning of 'value' changes for the specific type.
   5.603 +    	@verbatim
   5.604 +    	Document:	empty
   5.605 +    	Element:	name of the element
   5.606 +    	Comment:	the comment text
   5.607 +    	Unknown:	the tag contents
   5.608 +    	Text:		the text string
   5.609 +    	@endverbatim
   5.610 +    */
   5.611 +    const char* Value() const			{
   5.612 +        return _value.GetStr();
   5.613 +    }
   5.614 +
   5.615 +    /** Set the Value of an XML node.
   5.616 +    	@sa Value()
   5.617 +    */
   5.618 +    void SetValue( const char* val, bool staticMem=false );
   5.619 +
   5.620 +    /// Get the parent of this node on the DOM.
   5.621 +    const XMLNode*	Parent() const			{
   5.622 +        return _parent;
   5.623 +    }
   5.624 +
   5.625 +    XMLNode* Parent()						{
   5.626 +        return _parent;
   5.627 +    }
   5.628 +
   5.629 +    /// Returns true if this node has no children.
   5.630 +    bool NoChildren() const					{
   5.631 +        return !_firstChild;
   5.632 +    }
   5.633 +
   5.634 +    /// Get the first child node, or null if none exists.
   5.635 +    const XMLNode*  FirstChild() const		{
   5.636 +        return _firstChild;
   5.637 +    }
   5.638 +
   5.639 +    XMLNode*		FirstChild()			{
   5.640 +        return _firstChild;
   5.641 +    }
   5.642 +
   5.643 +    /** Get the first child element, or optionally the first child
   5.644 +        element with the specified name.
   5.645 +    */
   5.646 +    const XMLElement* FirstChildElement( const char* value=0 ) const;
   5.647 +
   5.648 +    XMLElement* FirstChildElement( const char* value=0 )	{
   5.649 +        return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->FirstChildElement( value ));
   5.650 +    }
   5.651 +
   5.652 +    /// Get the last child node, or null if none exists.
   5.653 +    const XMLNode*	LastChild() const						{
   5.654 +        return _lastChild;
   5.655 +    }
   5.656 +
   5.657 +    XMLNode*		LastChild()								{
   5.658 +        return const_cast<XMLNode*>(const_cast<const XMLNode*>(this)->LastChild() );
   5.659 +    }
   5.660 +
   5.661 +    /** Get the last child element or optionally the last child
   5.662 +        element with the specified name.
   5.663 +    */
   5.664 +    const XMLElement* LastChildElement( const char* value=0 ) const;
   5.665 +
   5.666 +    XMLElement* LastChildElement( const char* value=0 )	{
   5.667 +        return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->LastChildElement(value) );
   5.668 +    }
   5.669 +
   5.670 +    /// Get the previous (left) sibling node of this node.
   5.671 +    const XMLNode*	PreviousSibling() const					{
   5.672 +        return _prev;
   5.673 +    }
   5.674 +
   5.675 +    XMLNode*	PreviousSibling()							{
   5.676 +        return _prev;
   5.677 +    }
   5.678 +
   5.679 +    /// Get the previous (left) sibling element of this node, with an opitionally supplied name.
   5.680 +    const XMLElement*	PreviousSiblingElement( const char* value=0 ) const ;
   5.681 +
   5.682 +    XMLElement*	PreviousSiblingElement( const char* value=0 ) {
   5.683 +        return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->PreviousSiblingElement( value ) );
   5.684 +    }
   5.685 +
   5.686 +    /// Get the next (right) sibling node of this node.
   5.687 +    const XMLNode*	NextSibling() const						{
   5.688 +        return _next;
   5.689 +    }
   5.690 +
   5.691 +    XMLNode*	NextSibling()								{
   5.692 +        return _next;
   5.693 +    }
   5.694 +
   5.695 +    /// Get the next (right) sibling element of this node, with an opitionally supplied name.
   5.696 +    const XMLElement*	NextSiblingElement( const char* value=0 ) const;
   5.697 +
   5.698 +    XMLElement*	NextSiblingElement( const char* value=0 )	{
   5.699 +        return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->NextSiblingElement( value ) );
   5.700 +    }
   5.701 +
   5.702 +    /**
   5.703 +    	Add a child node as the last (right) child.
   5.704 +    */
   5.705 +    XMLNode* InsertEndChild( XMLNode* addThis );
   5.706 +
   5.707 +    XMLNode* LinkEndChild( XMLNode* addThis )	{
   5.708 +        return InsertEndChild( addThis );
   5.709 +    }
   5.710 +    /**
   5.711 +    	Add a child node as the first (left) child.
   5.712 +    */
   5.713 +    XMLNode* InsertFirstChild( XMLNode* addThis );
   5.714 +    /**
   5.715 +    	Add a node after the specified child node.
   5.716 +    */
   5.717 +    XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis );
   5.718 +
   5.719 +    /**
   5.720 +    	Delete all the children of this node.
   5.721 +    */
   5.722 +    void DeleteChildren();
   5.723 +
   5.724 +    /**
   5.725 +    	Delete a child of this node.
   5.726 +    */
   5.727 +    void DeleteChild( XMLNode* node );
   5.728 +
   5.729 +    /**
   5.730 +    	Make a copy of this node, but not its children.
   5.731 +    	You may pass in a Document pointer that will be
   5.732 +    	the owner of the new Node. If the 'document' is
   5.733 +    	null, then the node returned will be allocated
   5.734 +    	from the current Document. (this->GetDocument())
   5.735 +
   5.736 +    	Note: if called on a XMLDocument, this will return null.
   5.737 +    */
   5.738 +    virtual XMLNode* ShallowClone( XMLDocument* document ) const = 0;
   5.739 +
   5.740 +    /**
   5.741 +    	Test if 2 nodes are the same, but don't test children.
   5.742 +    	The 2 nodes do not need to be in the same Document.
   5.743 +
   5.744 +    	Note: if called on a XMLDocument, this will return false.
   5.745 +    */
   5.746 +    virtual bool ShallowEqual( const XMLNode* compare ) const = 0;
   5.747 +
   5.748 +    /** Accept a hierarchical visit of the nodes in the TinyXML DOM. Every node in the
   5.749 +    	XML tree will be conditionally visited and the host will be called back
   5.750 +    	via the TiXmlVisitor interface.
   5.751 +
   5.752 +    	This is essentially a SAX interface for TinyXML. (Note however it doesn't re-parse
   5.753 +    	the XML for the callbacks, so the performance of TinyXML is unchanged by using this
   5.754 +    	interface versus any other.)
   5.755 +
   5.756 +    	The interface has been based on ideas from:
   5.757 +
   5.758 +    	- http://www.saxproject.org/
   5.759 +    	- http://c2.com/cgi/wiki?HierarchicalVisitorPattern
   5.760 +
   5.761 +    	Which are both good references for "visiting".
   5.762 +
   5.763 +    	An example of using Accept():
   5.764 +    	@verbatim
   5.765 +    	TiXmlPrinter printer;
   5.766 +    	tinyxmlDoc.Accept( &printer );
   5.767 +    	const char* xmlcstr = printer.CStr();
   5.768 +    	@endverbatim
   5.769 +    */
   5.770 +    virtual bool Accept( XMLVisitor* visitor ) const = 0;
   5.771 +
   5.772 +    // internal
   5.773 +    virtual char* ParseDeep( char*, StrPair* );
   5.774 +
   5.775 +protected:
   5.776 +    XMLNode( XMLDocument* );
   5.777 +    virtual ~XMLNode();
   5.778 +    XMLNode( const XMLNode& );	// not supported
   5.779 +    XMLNode& operator=( const XMLNode& );	// not supported
   5.780 +
   5.781 +    XMLDocument*	_document;
   5.782 +    XMLNode*		_parent;
   5.783 +    mutable StrPair	_value;
   5.784 +
   5.785 +    XMLNode*		_firstChild;
   5.786 +    XMLNode*		_lastChild;
   5.787 +
   5.788 +    XMLNode*		_prev;
   5.789 +    XMLNode*		_next;
   5.790 +
   5.791 +private:
   5.792 +    MemPool*		_memPool;
   5.793 +    void Unlink( XMLNode* child );
   5.794 +};
   5.795 +
   5.796 +
   5.797 +/** XML text.
   5.798 +
   5.799 +	Note that a text node can have child element nodes, for example:
   5.800 +	@verbatim
   5.801 +	<root>This is <b>bold</b></root>
   5.802 +	@endverbatim
   5.803 +
   5.804 +	A text node can have 2 ways to output the next. "normal" output
   5.805 +	and CDATA. It will default to the mode it was parsed from the XML file and
   5.806 +	you generally want to leave it alone, but you can change the output mode with
   5.807 +	SetCDATA() and query it with CDATA().
   5.808 +*/
   5.809 +class XMLText : public XMLNode
   5.810 +{
   5.811 +    friend class XMLBase;
   5.812 +    friend class XMLDocument;
   5.813 +public:
   5.814 +    virtual bool Accept( XMLVisitor* visitor ) const;
   5.815 +
   5.816 +    virtual XMLText* ToText()			{
   5.817 +        return this;
   5.818 +    }
   5.819 +    virtual const XMLText* ToText() const	{
   5.820 +        return this;
   5.821 +    }
   5.822 +
   5.823 +    /// Declare whether this should be CDATA or standard text.
   5.824 +    void SetCData( bool isCData )			{
   5.825 +        _isCData = isCData;
   5.826 +    }
   5.827 +    /// Returns true if this is a CDATA text element.
   5.828 +    bool CData() const						{
   5.829 +        return _isCData;
   5.830 +    }
   5.831 +
   5.832 +    char* ParseDeep( char*, StrPair* endTag );
   5.833 +    virtual XMLNode* ShallowClone( XMLDocument* document ) const;
   5.834 +    virtual bool ShallowEqual( const XMLNode* compare ) const;
   5.835 +
   5.836 +protected:
   5.837 +    XMLText( XMLDocument* doc )	: XMLNode( doc ), _isCData( false )	{}
   5.838 +    virtual ~XMLText()												{}
   5.839 +    XMLText( const XMLText& );	// not supported
   5.840 +    XMLText& operator=( const XMLText& );	// not supported
   5.841 +
   5.842 +private:
   5.843 +    bool _isCData;
   5.844 +};
   5.845 +
   5.846 +
   5.847 +/** An XML Comment. */
   5.848 +class XMLComment : public XMLNode
   5.849 +{
   5.850 +    friend class XMLDocument;
   5.851 +public:
   5.852 +    virtual XMLComment*	ToComment()					{
   5.853 +        return this;
   5.854 +    }
   5.855 +    virtual const XMLComment* ToComment() const		{
   5.856 +        return this;
   5.857 +    }
   5.858 +
   5.859 +    virtual bool Accept( XMLVisitor* visitor ) const;
   5.860 +
   5.861 +    char* ParseDeep( char*, StrPair* endTag );
   5.862 +    virtual XMLNode* ShallowClone( XMLDocument* document ) const;
   5.863 +    virtual bool ShallowEqual( const XMLNode* compare ) const;
   5.864 +
   5.865 +protected:
   5.866 +    XMLComment( XMLDocument* doc );
   5.867 +    virtual ~XMLComment();
   5.868 +    XMLComment( const XMLComment& );	// not supported
   5.869 +    XMLComment& operator=( const XMLComment& );	// not supported
   5.870 +
   5.871 +private:
   5.872 +};
   5.873 +
   5.874 +
   5.875 +/** In correct XML the declaration is the first entry in the file.
   5.876 +	@verbatim
   5.877 +		<?xml version="1.0" standalone="yes"?>
   5.878 +	@endverbatim
   5.879 +
   5.880 +	TinyXML2 will happily read or write files without a declaration,
   5.881 +	however.
   5.882 +
   5.883 +	The text of the declaration isn't interpreted. It is parsed
   5.884 +	and written as a string.
   5.885 +*/
   5.886 +class XMLDeclaration : public XMLNode
   5.887 +{
   5.888 +    friend class XMLDocument;
   5.889 +public:
   5.890 +    virtual XMLDeclaration*	ToDeclaration()					{
   5.891 +        return this;
   5.892 +    }
   5.893 +    virtual const XMLDeclaration* ToDeclaration() const		{
   5.894 +        return this;
   5.895 +    }
   5.896 +
   5.897 +    virtual bool Accept( XMLVisitor* visitor ) const;
   5.898 +
   5.899 +    char* ParseDeep( char*, StrPair* endTag );
   5.900 +    virtual XMLNode* ShallowClone( XMLDocument* document ) const;
   5.901 +    virtual bool ShallowEqual( const XMLNode* compare ) const;
   5.902 +
   5.903 +protected:
   5.904 +    XMLDeclaration( XMLDocument* doc );
   5.905 +    virtual ~XMLDeclaration();
   5.906 +    XMLDeclaration( const XMLDeclaration& );	// not supported
   5.907 +    XMLDeclaration& operator=( const XMLDeclaration& );	// not supported
   5.908 +};
   5.909 +
   5.910 +
   5.911 +/** Any tag that tinyXml doesn't recognize is saved as an
   5.912 +	unknown. It is a tag of text, but should not be modified.
   5.913 +	It will be written back to the XML, unchanged, when the file
   5.914 +	is saved.
   5.915 +
   5.916 +	DTD tags get thrown into TiXmlUnknowns.
   5.917 +*/
   5.918 +class XMLUnknown : public XMLNode
   5.919 +{
   5.920 +    friend class XMLDocument;
   5.921 +public:
   5.922 +    virtual XMLUnknown*	ToUnknown()					{
   5.923 +        return this;
   5.924 +    }
   5.925 +    virtual const XMLUnknown* ToUnknown() const		{
   5.926 +        return this;
   5.927 +    }
   5.928 +
   5.929 +    virtual bool Accept( XMLVisitor* visitor ) const;
   5.930 +
   5.931 +    char* ParseDeep( char*, StrPair* endTag );
   5.932 +    virtual XMLNode* ShallowClone( XMLDocument* document ) const;
   5.933 +    virtual bool ShallowEqual( const XMLNode* compare ) const;
   5.934 +
   5.935 +protected:
   5.936 +    XMLUnknown( XMLDocument* doc );
   5.937 +    virtual ~XMLUnknown();
   5.938 +    XMLUnknown( const XMLUnknown& );	// not supported
   5.939 +    XMLUnknown& operator=( const XMLUnknown& );	// not supported
   5.940 +};
   5.941 +
   5.942 +
   5.943 +enum XMLError {
   5.944 +    XML_NO_ERROR = 0,
   5.945 +    XML_SUCCESS = 0,
   5.946 +
   5.947 +    XML_NO_ATTRIBUTE,
   5.948 +    XML_WRONG_ATTRIBUTE_TYPE,
   5.949 +
   5.950 +    XML_ERROR_FILE_NOT_FOUND,
   5.951 +    XML_ERROR_FILE_COULD_NOT_BE_OPENED,
   5.952 +    XML_ERROR_FILE_READ_ERROR,
   5.953 +    XML_ERROR_ELEMENT_MISMATCH,
   5.954 +    XML_ERROR_PARSING_ELEMENT,
   5.955 +    XML_ERROR_PARSING_ATTRIBUTE,
   5.956 +    XML_ERROR_IDENTIFYING_TAG,
   5.957 +    XML_ERROR_PARSING_TEXT,
   5.958 +    XML_ERROR_PARSING_CDATA,
   5.959 +    XML_ERROR_PARSING_COMMENT,
   5.960 +    XML_ERROR_PARSING_DECLARATION,
   5.961 +    XML_ERROR_PARSING_UNKNOWN,
   5.962 +    XML_ERROR_EMPTY_DOCUMENT,
   5.963 +    XML_ERROR_MISMATCHED_ELEMENT,
   5.964 +    XML_ERROR_PARSING,
   5.965 +
   5.966 +    XML_CAN_NOT_CONVERT_TEXT,
   5.967 +    XML_NO_TEXT_NODE
   5.968 +};
   5.969 +
   5.970 +
   5.971 +/** An attribute is a name-value pair. Elements have an arbitrary
   5.972 +	number of attributes, each with a unique name.
   5.973 +
   5.974 +	@note The attributes are not XMLNodes. You may only query the
   5.975 +	Next() attribute in a list.
   5.976 +*/
   5.977 +class XMLAttribute
   5.978 +{
   5.979 +    friend class XMLElement;
   5.980 +public:
   5.981 +    /// The name of the attribute.
   5.982 +    const char* Name() const {
   5.983 +        return _name.GetStr();
   5.984 +    }
   5.985 +    /// The value of the attribute.
   5.986 +    const char* Value() const {
   5.987 +        return _value.GetStr();
   5.988 +    }
   5.989 +    /// The next attribute in the list.
   5.990 +    const XMLAttribute* Next() const {
   5.991 +        return _next;
   5.992 +    }
   5.993 +
   5.994 +    /** IntAttribute interprets the attribute as an integer, and returns the value.
   5.995 +        If the value isn't an integer, 0 will be returned. There is no error checking;
   5.996 +    	use QueryIntAttribute() if you need error checking.
   5.997 +    */
   5.998 +    int		 IntValue() const				{
   5.999 +        int i=0;
  5.1000 +        QueryIntValue( &i );
  5.1001 +        return i;
  5.1002 +    }
  5.1003 +    /// Query as an unsigned integer. See IntAttribute()
  5.1004 +    unsigned UnsignedValue() const			{
  5.1005 +        unsigned i=0;
  5.1006 +        QueryUnsignedValue( &i );
  5.1007 +        return i;
  5.1008 +    }
  5.1009 +    /// Query as a boolean. See IntAttribute()
  5.1010 +    bool	 BoolValue() const				{
  5.1011 +        bool b=false;
  5.1012 +        QueryBoolValue( &b );
  5.1013 +        return b;
  5.1014 +    }
  5.1015 +    /// Query as a double. See IntAttribute()
  5.1016 +    double 	 DoubleValue() const			{
  5.1017 +        double d=0;
  5.1018 +        QueryDoubleValue( &d );
  5.1019 +        return d;
  5.1020 +    }
  5.1021 +    /// Query as a float. See IntAttribute()
  5.1022 +    float	 FloatValue() const				{
  5.1023 +        float f=0;
  5.1024 +        QueryFloatValue( &f );
  5.1025 +        return f;
  5.1026 +    }
  5.1027 +
  5.1028 +    /** QueryIntAttribute interprets the attribute as an integer, and returns the value
  5.1029 +    	in the provided paremeter. The function will return XML_NO_ERROR on success,
  5.1030 +    	and XML_WRONG_ATTRIBUTE_TYPE if the conversion is not successful.
  5.1031 +    */
  5.1032 +    XMLError QueryIntValue( int* value ) const;
  5.1033 +    /// See QueryIntAttribute
  5.1034 +    XMLError QueryUnsignedValue( unsigned int* value ) const;
  5.1035 +    /// See QueryIntAttribute
  5.1036 +    XMLError QueryBoolValue( bool* value ) const;
  5.1037 +    /// See QueryIntAttribute
  5.1038 +    XMLError QueryDoubleValue( double* value ) const;
  5.1039 +    /// See QueryIntAttribute
  5.1040 +    XMLError QueryFloatValue( float* value ) const;
  5.1041 +
  5.1042 +    /// Set the attribute to a string value.
  5.1043 +    void SetAttribute( const char* value );
  5.1044 +    /// Set the attribute to value.
  5.1045 +    void SetAttribute( int value );
  5.1046 +    /// Set the attribute to value.
  5.1047 +    void SetAttribute( unsigned value );
  5.1048 +    /// Set the attribute to value.
  5.1049 +    void SetAttribute( bool value );
  5.1050 +    /// Set the attribute to value.
  5.1051 +    void SetAttribute( double value );
  5.1052 +    /// Set the attribute to value.
  5.1053 +    void SetAttribute( float value );
  5.1054 +
  5.1055 +private:
  5.1056 +    enum { BUF_SIZE = 200 };
  5.1057 +
  5.1058 +    XMLAttribute() : _next( 0 ) {}
  5.1059 +    virtual ~XMLAttribute()	{}
  5.1060 +
  5.1061 +    XMLAttribute( const XMLAttribute& );	// not supported
  5.1062 +    void operator=( const XMLAttribute& );	// not supported
  5.1063 +    void SetName( const char* name );
  5.1064 +
  5.1065 +    char* ParseDeep( char* p, bool processEntities );
  5.1066 +
  5.1067 +    mutable StrPair _name;
  5.1068 +    mutable StrPair _value;
  5.1069 +    XMLAttribute*   _next;
  5.1070 +    MemPool*        _memPool;
  5.1071 +};
  5.1072 +
  5.1073 +
  5.1074 +/** The element is a container class. It has a value, the element name,
  5.1075 +	and can contain other elements, text, comments, and unknowns.
  5.1076 +	Elements also contain an arbitrary number of attributes.
  5.1077 +*/
  5.1078 +class XMLElement : public XMLNode
  5.1079 +{
  5.1080 +    friend class XMLBase;
  5.1081 +    friend class XMLDocument;
  5.1082 +public:
  5.1083 +    /// Get the name of an element (which is the Value() of the node.)
  5.1084 +    const char* Name() const		{
  5.1085 +        return Value();
  5.1086 +    }
  5.1087 +    /// Set the name of the element.
  5.1088 +    void SetName( const char* str, bool staticMem=false )	{
  5.1089 +        SetValue( str, staticMem );
  5.1090 +    }
  5.1091 +
  5.1092 +    virtual XMLElement* ToElement()				{
  5.1093 +        return this;
  5.1094 +    }
  5.1095 +    virtual const XMLElement* ToElement() const {
  5.1096 +        return this;
  5.1097 +    }
  5.1098 +    virtual bool Accept( XMLVisitor* visitor ) const;
  5.1099 +
  5.1100 +    /** Given an attribute name, Attribute() returns the value
  5.1101 +    	for the attribute of that name, or null if none
  5.1102 +    	exists. For example:
  5.1103 +
  5.1104 +    	@verbatim
  5.1105 +    	const char* value = ele->Attribute( "foo" );
  5.1106 +    	@endverbatim
  5.1107 +
  5.1108 +    	The 'value' parameter is normally null. However, if specified,
  5.1109 +    	the attribute will only be returned if the 'name' and 'value'
  5.1110 +    	match. This allow you to write code:
  5.1111 +
  5.1112 +    	@verbatim
  5.1113 +    	if ( ele->Attribute( "foo", "bar" ) ) callFooIsBar();
  5.1114 +    	@endverbatim
  5.1115 +
  5.1116 +    	rather than:
  5.1117 +    	@verbatim
  5.1118 +    	if ( ele->Attribute( "foo" ) ) {
  5.1119 +    		if ( strcmp( ele->Attribute( "foo" ), "bar" ) == 0 ) callFooIsBar();
  5.1120 +    	}
  5.1121 +    	@endverbatim
  5.1122 +    */
  5.1123 +    const char* Attribute( const char* name, const char* value=0 ) const;
  5.1124 +
  5.1125 +    /** Given an attribute name, IntAttribute() returns the value
  5.1126 +    	of the attribute interpreted as an integer. 0 will be
  5.1127 +    	returned if there is an error. For a method with error
  5.1128 +    	checking, see QueryIntAttribute()
  5.1129 +    */
  5.1130 +    int		 IntAttribute( const char* name ) const		{
  5.1131 +        int i=0;
  5.1132 +        QueryIntAttribute( name, &i );
  5.1133 +        return i;
  5.1134 +    }
  5.1135 +    /// See IntAttribute()
  5.1136 +    unsigned UnsignedAttribute( const char* name ) const {
  5.1137 +        unsigned i=0;
  5.1138 +        QueryUnsignedAttribute( name, &i );
  5.1139 +        return i;
  5.1140 +    }
  5.1141 +    /// See IntAttribute()
  5.1142 +    bool	 BoolAttribute( const char* name ) const	{
  5.1143 +        bool b=false;
  5.1144 +        QueryBoolAttribute( name, &b );
  5.1145 +        return b;
  5.1146 +    }
  5.1147 +    /// See IntAttribute()
  5.1148 +    double 	 DoubleAttribute( const char* name ) const	{
  5.1149 +        double d=0;
  5.1150 +        QueryDoubleAttribute( name, &d );
  5.1151 +        return d;
  5.1152 +    }
  5.1153 +    /// See IntAttribute()
  5.1154 +    float	 FloatAttribute( const char* name ) const	{
  5.1155 +        float f=0;
  5.1156 +        QueryFloatAttribute( name, &f );
  5.1157 +        return f;
  5.1158 +    }
  5.1159 +
  5.1160 +    /** Given an attribute name, QueryIntAttribute() returns
  5.1161 +    	XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion
  5.1162 +    	can't be performed, or XML_NO_ATTRIBUTE if the attribute
  5.1163 +    	doesn't exist. If successful, the result of the conversion
  5.1164 +    	will be written to 'value'. If not successful, nothing will
  5.1165 +    	be written to 'value'. This allows you to provide default
  5.1166 +    	value:
  5.1167 +
  5.1168 +    	@verbatim
  5.1169 +    	int value = 10;
  5.1170 +    	QueryIntAttribute( "foo", &value );		// if "foo" isn't found, value will still be 10
  5.1171 +    	@endverbatim
  5.1172 +    */
  5.1173 +    XMLError QueryIntAttribute( const char* name, int* value ) const				{
  5.1174 +        const XMLAttribute* a = FindAttribute( name );
  5.1175 +        if ( !a ) {
  5.1176 +            return XML_NO_ATTRIBUTE;
  5.1177 +        }
  5.1178 +        return a->QueryIntValue( value );
  5.1179 +    }
  5.1180 +    /// See QueryIntAttribute()
  5.1181 +    XMLError QueryUnsignedAttribute( const char* name, unsigned int* value ) const	{
  5.1182 +        const XMLAttribute* a = FindAttribute( name );
  5.1183 +        if ( !a ) {
  5.1184 +            return XML_NO_ATTRIBUTE;
  5.1185 +        }
  5.1186 +        return a->QueryUnsignedValue( value );
  5.1187 +    }
  5.1188 +    /// See QueryIntAttribute()
  5.1189 +    XMLError QueryBoolAttribute( const char* name, bool* value ) const				{
  5.1190 +        const XMLAttribute* a = FindAttribute( name );
  5.1191 +        if ( !a ) {
  5.1192 +            return XML_NO_ATTRIBUTE;
  5.1193 +        }
  5.1194 +        return a->QueryBoolValue( value );
  5.1195 +    }
  5.1196 +    /// See QueryIntAttribute()
  5.1197 +    XMLError QueryDoubleAttribute( const char* name, double* value ) const			{
  5.1198 +        const XMLAttribute* a = FindAttribute( name );
  5.1199 +        if ( !a ) {
  5.1200 +            return XML_NO_ATTRIBUTE;
  5.1201 +        }
  5.1202 +        return a->QueryDoubleValue( value );
  5.1203 +    }
  5.1204 +    /// See QueryIntAttribute()
  5.1205 +    XMLError QueryFloatAttribute( const char* name, float* value ) const			{
  5.1206 +        const XMLAttribute* a = FindAttribute( name );
  5.1207 +        if ( !a ) {
  5.1208 +            return XML_NO_ATTRIBUTE;
  5.1209 +        }
  5.1210 +        return a->QueryFloatValue( value );
  5.1211 +    }
  5.1212 +
  5.1213 +    /// Sets the named attribute to value.
  5.1214 +    void SetAttribute( const char* name, const char* value )	{
  5.1215 +        XMLAttribute* a = FindOrCreateAttribute( name );
  5.1216 +        a->SetAttribute( value );
  5.1217 +    }
  5.1218 +    /// Sets the named attribute to value.
  5.1219 +    void SetAttribute( const char* name, int value )			{
  5.1220 +        XMLAttribute* a = FindOrCreateAttribute( name );
  5.1221 +        a->SetAttribute( value );
  5.1222 +    }
  5.1223 +    /// Sets the named attribute to value.
  5.1224 +    void SetAttribute( const char* name, unsigned value )		{
  5.1225 +        XMLAttribute* a = FindOrCreateAttribute( name );
  5.1226 +        a->SetAttribute( value );
  5.1227 +    }
  5.1228 +    /// Sets the named attribute to value.
  5.1229 +    void SetAttribute( const char* name, bool value )			{
  5.1230 +        XMLAttribute* a = FindOrCreateAttribute( name );
  5.1231 +        a->SetAttribute( value );
  5.1232 +    }
  5.1233 +    /// Sets the named attribute to value.
  5.1234 +    void SetAttribute( const char* name, double value )		{
  5.1235 +        XMLAttribute* a = FindOrCreateAttribute( name );
  5.1236 +        a->SetAttribute( value );
  5.1237 +    }
  5.1238 +
  5.1239 +    /**
  5.1240 +    	Delete an attribute.
  5.1241 +    */
  5.1242 +    void DeleteAttribute( const char* name );
  5.1243 +
  5.1244 +    /// Return the first attribute in the list.
  5.1245 +    const XMLAttribute* FirstAttribute() const {
  5.1246 +        return _rootAttribute;
  5.1247 +    }
  5.1248 +    /// Query a specific attribute in the list.
  5.1249 +    const XMLAttribute* FindAttribute( const char* name ) const;
  5.1250 +
  5.1251 +    /** Convenience function for easy access to the text inside an element. Although easy
  5.1252 +    	and concise, GetText() is limited compared to getting the TiXmlText child
  5.1253 +    	and accessing it directly.
  5.1254 +
  5.1255 +    	If the first child of 'this' is a TiXmlText, the GetText()
  5.1256 +    	returns the character string of the Text node, else null is returned.
  5.1257 +
  5.1258 +    	This is a convenient method for getting the text of simple contained text:
  5.1259 +    	@verbatim
  5.1260 +    	<foo>This is text</foo>
  5.1261 +    		const char* str = fooElement->GetText();
  5.1262 +    	@endverbatim
  5.1263 +
  5.1264 +    	'str' will be a pointer to "This is text".
  5.1265 +
  5.1266 +    	Note that this function can be misleading. If the element foo was created from
  5.1267 +    	this XML:
  5.1268 +    	@verbatim
  5.1269 +    		<foo><b>This is text</b></foo>
  5.1270 +    	@endverbatim
  5.1271 +
  5.1272 +    	then the value of str would be null. The first child node isn't a text node, it is
  5.1273 +    	another element. From this XML:
  5.1274 +    	@verbatim
  5.1275 +    		<foo>This is <b>text</b></foo>
  5.1276 +    	@endverbatim
  5.1277 +    	GetText() will return "This is ".
  5.1278 +    */
  5.1279 +    const char* GetText() const;
  5.1280 +
  5.1281 +    /**
  5.1282 +    	Convenience method to query the value of a child text node. This is probably best
  5.1283 +    	shown by example. Given you have a document is this form:
  5.1284 +    	@verbatim
  5.1285 +    		<point>
  5.1286 +    			<x>1</x>
  5.1287 +    			<y>1.4</y>
  5.1288 +    		</point>
  5.1289 +    	@endverbatim
  5.1290 +
  5.1291 +    	The QueryIntText() and similar functions provide a safe and easier way to get to the
  5.1292 +    	"value" of x and y.
  5.1293 +
  5.1294 +    	@verbatim
  5.1295 +    		int x = 0;
  5.1296 +    		float y = 0;	// types of x and y are contrived for example
  5.1297 +    		const XMLElement* xElement = pointElement->FirstChildElement( "x" );
  5.1298 +    		const XMLElement* yElement = pointElement->FirstChildElement( "y" );
  5.1299 +    		xElement->QueryIntText( &x );
  5.1300 +    		yElement->QueryFloatText( &y );
  5.1301 +    	@endverbatim
  5.1302 +
  5.1303 +    	@returns XML_SUCCESS (0) on success, XML_CAN_NOT_CONVERT_TEXT if the text cannot be converted
  5.1304 +    			 to the requested type, and XML_NO_TEXT_NODE if there is no child text to query.
  5.1305 +
  5.1306 +    */
  5.1307 +    XMLError QueryIntText( int* ival ) const;
  5.1308 +    /// See QueryIntText()
  5.1309 +    XMLError QueryUnsignedText( unsigned* uval ) const;
  5.1310 +    /// See QueryIntText()
  5.1311 +    XMLError QueryBoolText( bool* bval ) const;
  5.1312 +    /// See QueryIntText()
  5.1313 +    XMLError QueryDoubleText( double* dval ) const;
  5.1314 +    /// See QueryIntText()
  5.1315 +    XMLError QueryFloatText( float* fval ) const;
  5.1316 +
  5.1317 +    // internal:
  5.1318 +    enum {
  5.1319 +        OPEN,		// <foo>
  5.1320 +        CLOSED,		// <foo/>
  5.1321 +        CLOSING		// </foo>
  5.1322 +    };
  5.1323 +    int ClosingType() const {
  5.1324 +        return _closingType;
  5.1325 +    }
  5.1326 +    char* ParseDeep( char* p, StrPair* endTag );
  5.1327 +    virtual XMLNode* ShallowClone( XMLDocument* document ) const;
  5.1328 +    virtual bool ShallowEqual( const XMLNode* compare ) const;
  5.1329 +
  5.1330 +private:
  5.1331 +    XMLElement( XMLDocument* doc );
  5.1332 +    virtual ~XMLElement();
  5.1333 +    XMLElement( const XMLElement& );	// not supported
  5.1334 +    void operator=( const XMLElement& );	// not supported
  5.1335 +
  5.1336 +    XMLAttribute* FindAttribute( const char* name );
  5.1337 +    XMLAttribute* FindOrCreateAttribute( const char* name );
  5.1338 +    //void LinkAttribute( XMLAttribute* attrib );
  5.1339 +    char* ParseAttributes( char* p );
  5.1340 +
  5.1341 +    int _closingType;
  5.1342 +    // The attribute list is ordered; there is no 'lastAttribute'
  5.1343 +    // because the list needs to be scanned for dupes before adding
  5.1344 +    // a new attribute.
  5.1345 +    XMLAttribute* _rootAttribute;
  5.1346 +};
  5.1347 +
  5.1348 +
  5.1349 +enum Whitespace {
  5.1350 +    PRESERVE_WHITESPACE,
  5.1351 +    COLLAPSE_WHITESPACE
  5.1352 +};
  5.1353 +
  5.1354 +
  5.1355 +/** A Document binds together all the functionality.
  5.1356 +	It can be saved, loaded, and printed to the screen.
  5.1357 +	All Nodes are connected and allocated to a Document.
  5.1358 +	If the Document is deleted, all its Nodes are also deleted.
  5.1359 +*/
  5.1360 +class XMLDocument : public XMLNode
  5.1361 +{
  5.1362 +    friend class XMLElement;
  5.1363 +public:
  5.1364 +    /// constructor
  5.1365 +    XMLDocument( bool processEntities = true, Whitespace = PRESERVE_WHITESPACE );
  5.1366 +    ~XMLDocument();
  5.1367 +
  5.1368 +    virtual XMLDocument* ToDocument()				{
  5.1369 +        return this;
  5.1370 +    }
  5.1371 +    virtual const XMLDocument* ToDocument() const	{
  5.1372 +        return this;
  5.1373 +    }
  5.1374 +
  5.1375 +    /**
  5.1376 +    	Parse an XML file from a character string.
  5.1377 +    	Returns XML_NO_ERROR (0) on success, or
  5.1378 +    	an errorID.
  5.1379 +
  5.1380 +    	You may optionally pass in the 'nBytes', which is
  5.1381 +    	the number of bytes which will be parsed. If not
  5.1382 +    	specified, TinyXML will assume 'xml' points to a
  5.1383 +    	null terminated string.
  5.1384 +    */
  5.1385 +    XMLError Parse( const char* xml, size_t nBytes=(size_t)(-1) );
  5.1386 +
  5.1387 +    /**
  5.1388 +    	Load an XML file from disk.
  5.1389 +    	Returns XML_NO_ERROR (0) on success, or
  5.1390 +    	an errorID.
  5.1391 +    */
  5.1392 +    XMLError LoadFile( const char* filename );
  5.1393 +
  5.1394 +    /**
  5.1395 +    	Load an XML file from disk. You are responsible
  5.1396 +    	for providing and closing the FILE*.
  5.1397 +
  5.1398 +    	Returns XML_NO_ERROR (0) on success, or
  5.1399 +    	an errorID.
  5.1400 +    */
  5.1401 +    XMLError LoadFile( FILE* );
  5.1402 +
  5.1403 +    /**
  5.1404 +    	Save the XML file to disk.
  5.1405 +    	Returns XML_NO_ERROR (0) on success, or
  5.1406 +    	an errorID.
  5.1407 +    */
  5.1408 +    XMLError SaveFile( const char* filename, bool compact = false );
  5.1409 +
  5.1410 +    /**
  5.1411 +    	Save the XML file to disk. You are responsible
  5.1412 +    	for providing and closing the FILE*.
  5.1413 +
  5.1414 +    	Returns XML_NO_ERROR (0) on success, or
  5.1415 +    	an errorID.
  5.1416 +    */
  5.1417 +    XMLError SaveFile( FILE* fp, bool compact = false );
  5.1418 +
  5.1419 +    bool ProcessEntities() const		{
  5.1420 +        return _processEntities;
  5.1421 +    }
  5.1422 +    Whitespace WhitespaceMode() const	{
  5.1423 +        return _whitespace;
  5.1424 +    }
  5.1425 +
  5.1426 +    /**
  5.1427 +    	Returns true if this document has a leading Byte Order Mark of UTF8.
  5.1428 +    */
  5.1429 +    bool HasBOM() const {
  5.1430 +        return _writeBOM;
  5.1431 +    }
  5.1432 +    /** Sets whether to write the BOM when writing the file.
  5.1433 +    */
  5.1434 +    void SetBOM( bool useBOM ) {
  5.1435 +        _writeBOM = useBOM;
  5.1436 +    }
  5.1437 +
  5.1438 +    /** Return the root element of DOM. Equivalent to FirstChildElement().
  5.1439 +        To get the first node, use FirstChild().
  5.1440 +    */
  5.1441 +    XMLElement* RootElement()				{
  5.1442 +        return FirstChildElement();
  5.1443 +    }
  5.1444 +    const XMLElement* RootElement() const	{
  5.1445 +        return FirstChildElement();
  5.1446 +    }
  5.1447 +
  5.1448 +    /** Print the Document. If the Printer is not provided, it will
  5.1449 +        print to stdout. If you provide Printer, this can print to a file:
  5.1450 +    	@verbatim
  5.1451 +    	XMLPrinter printer( fp );
  5.1452 +    	doc.Print( &printer );
  5.1453 +    	@endverbatim
  5.1454 +
  5.1455 +    	Or you can use a printer to print to memory:
  5.1456 +    	@verbatim
  5.1457 +    	XMLPrinter printer;
  5.1458 +    	doc->Print( &printer );
  5.1459 +    	// printer.CStr() has a const char* to the XML
  5.1460 +    	@endverbatim
  5.1461 +    */
  5.1462 +    void Print( XMLPrinter* streamer=0 );
  5.1463 +    virtual bool Accept( XMLVisitor* visitor ) const;
  5.1464 +
  5.1465 +    /**
  5.1466 +    	Create a new Element associated with
  5.1467 +    	this Document. The memory for the Element
  5.1468 +    	is managed by the Document.
  5.1469 +    */
  5.1470 +    XMLElement* NewElement( const char* name );
  5.1471 +    /**
  5.1472 +    	Create a new Comment associated with
  5.1473 +    	this Document. The memory for the Comment
  5.1474 +    	is managed by the Document.
  5.1475 +    */
  5.1476 +    XMLComment* NewComment( const char* comment );
  5.1477 +    /**
  5.1478 +    	Create a new Text associated with
  5.1479 +    	this Document. The memory for the Text
  5.1480 +    	is managed by the Document.
  5.1481 +    */
  5.1482 +    XMLText* NewText( const char* text );
  5.1483 +    /**
  5.1484 +    	Create a new Declaration associated with
  5.1485 +    	this Document. The memory for the object
  5.1486 +    	is managed by the Document.
  5.1487 +
  5.1488 +    	If the 'text' param is null, the standard
  5.1489 +    	declaration is used.:
  5.1490 +    	@verbatim
  5.1491 +    		<?xml version="1.0" encoding="UTF-8"?>
  5.1492 +    	@endverbatim
  5.1493 +    */
  5.1494 +    XMLDeclaration* NewDeclaration( const char* text=0 );
  5.1495 +    /**
  5.1496 +    	Create a new Unknown associated with
  5.1497 +    	this Document. The memory forthe object
  5.1498 +    	is managed by the Document.
  5.1499 +    */
  5.1500 +    XMLUnknown* NewUnknown( const char* text );
  5.1501 +
  5.1502 +    /**
  5.1503 +    	Delete a node associated with this document.
  5.1504 +    	It will be unlinked from the DOM.
  5.1505 +    */
  5.1506 +    void DeleteNode( XMLNode* node )	{
  5.1507 +        node->_parent->DeleteChild( node );
  5.1508 +    }
  5.1509 +
  5.1510 +    void SetError( XMLError error, const char* str1, const char* str2 );
  5.1511 +
  5.1512 +    /// Return true if there was an error parsing the document.
  5.1513 +    bool Error() const {
  5.1514 +        return _errorID != XML_NO_ERROR;
  5.1515 +    }
  5.1516 +    /// Return the errorID.
  5.1517 +    XMLError  ErrorID() const {
  5.1518 +        return _errorID;
  5.1519 +    }
  5.1520 +    /// Return a possibly helpful diagnostic location or string.
  5.1521 +    const char* GetErrorStr1() const {
  5.1522 +        return _errorStr1;
  5.1523 +    }
  5.1524 +    /// Return a possibly helpful secondary diagnostic location or string.
  5.1525 +    const char* GetErrorStr2() const {
  5.1526 +        return _errorStr2;
  5.1527 +    }
  5.1528 +    /// If there is an error, print it to stdout.
  5.1529 +    void PrintError() const;
  5.1530 +
  5.1531 +    // internal
  5.1532 +    char* Identify( char* p, XMLNode** node );
  5.1533 +
  5.1534 +    virtual XMLNode* ShallowClone( XMLDocument* /*document*/ ) const	{
  5.1535 +        return 0;
  5.1536 +    }
  5.1537 +    virtual bool ShallowEqual( const XMLNode* /*compare*/ ) const	{
  5.1538 +        return false;
  5.1539 +    }
  5.1540 +
  5.1541 +private:
  5.1542 +    XMLDocument( const XMLDocument& );	// not supported
  5.1543 +    void operator=( const XMLDocument& );	// not supported
  5.1544 +    void InitDocument();
  5.1545 +
  5.1546 +    bool        _writeBOM;
  5.1547 +    bool        _processEntities;
  5.1548 +    XMLError    _errorID;
  5.1549 +    Whitespace  _whitespace;
  5.1550 +    const char* _errorStr1;
  5.1551 +    const char* _errorStr2;
  5.1552 +    char*       _charBuffer;
  5.1553 +
  5.1554 +    MemPoolT< sizeof(XMLElement) >	 _elementPool;
  5.1555 +    MemPoolT< sizeof(XMLAttribute) > _attributePool;
  5.1556 +    MemPoolT< sizeof(XMLText) >		 _textPool;
  5.1557 +    MemPoolT< sizeof(XMLComment) >	 _commentPool;
  5.1558 +};
  5.1559 +
  5.1560 +
  5.1561 +/**
  5.1562 +	A XMLHandle is a class that wraps a node pointer with null checks; this is
  5.1563 +	an incredibly useful thing. Note that XMLHandle is not part of the TinyXML
  5.1564 +	DOM structure. It is a separate utility class.
  5.1565 +
  5.1566 +	Take an example:
  5.1567 +	@verbatim
  5.1568 +	<Document>
  5.1569 +		<Element attributeA = "valueA">
  5.1570 +			<Child attributeB = "value1" />
  5.1571 +			<Child attributeB = "value2" />
  5.1572 +		</Element>
  5.1573 +	</Document>
  5.1574 +	@endverbatim
  5.1575 +
  5.1576 +	Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very
  5.1577 +	easy to write a *lot* of code that looks like:
  5.1578 +
  5.1579 +	@verbatim
  5.1580 +	XMLElement* root = document.FirstChildElement( "Document" );
  5.1581 +	if ( root )
  5.1582 +	{
  5.1583 +		XMLElement* element = root->FirstChildElement( "Element" );
  5.1584 +		if ( element )
  5.1585 +		{
  5.1586 +			XMLElement* child = element->FirstChildElement( "Child" );
  5.1587 +			if ( child )
  5.1588 +			{
  5.1589 +				XMLElement* child2 = child->NextSiblingElement( "Child" );
  5.1590 +				if ( child2 )
  5.1591 +				{
  5.1592 +					// Finally do something useful.
  5.1593 +	@endverbatim
  5.1594 +
  5.1595 +	And that doesn't even cover "else" cases. XMLHandle addresses the verbosity
  5.1596 +	of such code. A XMLHandle checks for null pointers so it is perfectly safe
  5.1597 +	and correct to use:
  5.1598 +
  5.1599 +	@verbatim
  5.1600 +	XMLHandle docHandle( &document );
  5.1601 +	XMLElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild().NextSibling().ToElement();
  5.1602 +	if ( child2 )
  5.1603 +	{
  5.1604 +		// do something useful
  5.1605 +	@endverbatim
  5.1606 +
  5.1607 +	Which is MUCH more concise and useful.
  5.1608 +
  5.1609 +	It is also safe to copy handles - internally they are nothing more than node pointers.
  5.1610 +	@verbatim
  5.1611 +	XMLHandle handleCopy = handle;
  5.1612 +	@endverbatim
  5.1613 +
  5.1614 +	See also XMLConstHandle, which is the same as XMLHandle, but operates on const objects.
  5.1615 +*/
  5.1616 +class XMLHandle
  5.1617 +{
  5.1618 +public:
  5.1619 +    /// Create a handle from any node (at any depth of the tree.) This can be a null pointer.
  5.1620 +    XMLHandle( XMLNode* node )												{
  5.1621 +        _node = node;
  5.1622 +    }
  5.1623 +    /// Create a handle from a node.
  5.1624 +    XMLHandle( XMLNode& node )												{
  5.1625 +        _node = &node;
  5.1626 +    }
  5.1627 +    /// Copy constructor
  5.1628 +    XMLHandle( const XMLHandle& ref )										{
  5.1629 +        _node = ref._node;
  5.1630 +    }
  5.1631 +    /// Assignment
  5.1632 +    XMLHandle& operator=( const XMLHandle& ref )							{
  5.1633 +        _node = ref._node;
  5.1634 +        return *this;
  5.1635 +    }
  5.1636 +
  5.1637 +    /// Get the first child of this handle.
  5.1638 +    XMLHandle FirstChild() 													{
  5.1639 +        return XMLHandle( _node ? _node->FirstChild() : 0 );
  5.1640 +    }
  5.1641 +    /// Get the first child element of this handle.
  5.1642 +    XMLHandle FirstChildElement( const char* value=0 )						{
  5.1643 +        return XMLHandle( _node ? _node->FirstChildElement( value ) : 0 );
  5.1644 +    }
  5.1645 +    /// Get the last child of this handle.
  5.1646 +    XMLHandle LastChild()													{
  5.1647 +        return XMLHandle( _node ? _node->LastChild() : 0 );
  5.1648 +    }
  5.1649 +    /// Get the last child element of this handle.
  5.1650 +    XMLHandle LastChildElement( const char* _value=0 )						{
  5.1651 +        return XMLHandle( _node ? _node->LastChildElement( _value ) : 0 );
  5.1652 +    }
  5.1653 +    /// Get the previous sibling of this handle.
  5.1654 +    XMLHandle PreviousSibling()												{
  5.1655 +        return XMLHandle( _node ? _node->PreviousSibling() : 0 );
  5.1656 +    }
  5.1657 +    /// Get the previous sibling element of this handle.
  5.1658 +    XMLHandle PreviousSiblingElement( const char* _value=0 )				{
  5.1659 +        return XMLHandle( _node ? _node->PreviousSiblingElement( _value ) : 0 );
  5.1660 +    }
  5.1661 +    /// Get the next sibling of this handle.
  5.1662 +    XMLHandle NextSibling()													{
  5.1663 +        return XMLHandle( _node ? _node->NextSibling() : 0 );
  5.1664 +    }
  5.1665 +    /// Get the next sibling element of this handle.
  5.1666 +    XMLHandle NextSiblingElement( const char* _value=0 )					{
  5.1667 +        return XMLHandle( _node ? _node->NextSiblingElement( _value ) : 0 );
  5.1668 +    }
  5.1669 +
  5.1670 +    /// Safe cast to XMLNode. This can return null.
  5.1671 +    XMLNode* ToNode()							{
  5.1672 +        return _node;
  5.1673 +    }
  5.1674 +    /// Safe cast to XMLElement. This can return null.
  5.1675 +    XMLElement* ToElement() 					{
  5.1676 +        return ( ( _node && _node->ToElement() ) ? _node->ToElement() : 0 );
  5.1677 +    }
  5.1678 +    /// Safe cast to XMLText. This can return null.
  5.1679 +    XMLText* ToText() 							{
  5.1680 +        return ( ( _node && _node->ToText() ) ? _node->ToText() : 0 );
  5.1681 +    }
  5.1682 +    /// Safe cast to XMLUnknown. This can return null.
  5.1683 +    XMLUnknown* ToUnknown() 					{
  5.1684 +        return ( ( _node && _node->ToUnknown() ) ? _node->ToUnknown() : 0 );
  5.1685 +    }
  5.1686 +    /// Safe cast to XMLDeclaration. This can return null.
  5.1687 +    XMLDeclaration* ToDeclaration() 			{
  5.1688 +        return ( ( _node && _node->ToDeclaration() ) ? _node->ToDeclaration() : 0 );
  5.1689 +    }
  5.1690 +
  5.1691 +private:
  5.1692 +    XMLNode* _node;
  5.1693 +};
  5.1694 +
  5.1695 +
  5.1696 +/**
  5.1697 +	A variant of the XMLHandle class for working with const XMLNodes and Documents. It is the
  5.1698 +	same in all regards, except for the 'const' qualifiers. See XMLHandle for API.
  5.1699 +*/
  5.1700 +class XMLConstHandle
  5.1701 +{
  5.1702 +public:
  5.1703 +    XMLConstHandle( const XMLNode* node )											{
  5.1704 +        _node = node;
  5.1705 +    }
  5.1706 +    XMLConstHandle( const XMLNode& node )											{
  5.1707 +        _node = &node;
  5.1708 +    }
  5.1709 +    XMLConstHandle( const XMLConstHandle& ref )										{
  5.1710 +        _node = ref._node;
  5.1711 +    }
  5.1712 +
  5.1713 +    XMLConstHandle& operator=( const XMLConstHandle& ref )							{
  5.1714 +        _node = ref._node;
  5.1715 +        return *this;
  5.1716 +    }
  5.1717 +
  5.1718 +    const XMLConstHandle FirstChild() const											{
  5.1719 +        return XMLConstHandle( _node ? _node->FirstChild() : 0 );
  5.1720 +    }
  5.1721 +    const XMLConstHandle FirstChildElement( const char* value=0 ) const				{
  5.1722 +        return XMLConstHandle( _node ? _node->FirstChildElement( value ) : 0 );
  5.1723 +    }
  5.1724 +    const XMLConstHandle LastChild()	const										{
  5.1725 +        return XMLConstHandle( _node ? _node->LastChild() : 0 );
  5.1726 +    }
  5.1727 +    const XMLConstHandle LastChildElement( const char* _value=0 ) const				{
  5.1728 +        return XMLConstHandle( _node ? _node->LastChildElement( _value ) : 0 );
  5.1729 +    }
  5.1730 +    const XMLConstHandle PreviousSibling() const									{
  5.1731 +        return XMLConstHandle( _node ? _node->PreviousSibling() : 0 );
  5.1732 +    }
  5.1733 +    const XMLConstHandle PreviousSiblingElement( const char* _value=0 ) const		{
  5.1734 +        return XMLConstHandle( _node ? _node->PreviousSiblingElement( _value ) : 0 );
  5.1735 +    }
  5.1736 +    const XMLConstHandle NextSibling() const										{
  5.1737 +        return XMLConstHandle( _node ? _node->NextSibling() : 0 );
  5.1738 +    }
  5.1739 +    const XMLConstHandle NextSiblingElement( const char* _value=0 ) const			{
  5.1740 +        return XMLConstHandle( _node ? _node->NextSiblingElement( _value ) : 0 );
  5.1741 +    }
  5.1742 +
  5.1743 +
  5.1744 +    const XMLNode* ToNode() const				{
  5.1745 +        return _node;
  5.1746 +    }
  5.1747 +    const XMLElement* ToElement() const			{
  5.1748 +        return ( ( _node && _node->ToElement() ) ? _node->ToElement() : 0 );
  5.1749 +    }
  5.1750 +    const XMLText* ToText() const				{
  5.1751 +        return ( ( _node && _node->ToText() ) ? _node->ToText() : 0 );
  5.1752 +    }
  5.1753 +    const XMLUnknown* ToUnknown() const			{
  5.1754 +        return ( ( _node && _node->ToUnknown() ) ? _node->ToUnknown() : 0 );
  5.1755 +    }
  5.1756 +    const XMLDeclaration* ToDeclaration() const	{
  5.1757 +        return ( ( _node && _node->ToDeclaration() ) ? _node->ToDeclaration() : 0 );
  5.1758 +    }
  5.1759 +
  5.1760 +private:
  5.1761 +    const XMLNode* _node;
  5.1762 +};
  5.1763 +
  5.1764 +
  5.1765 +/**
  5.1766 +	Printing functionality. The XMLPrinter gives you more
  5.1767 +	options than the XMLDocument::Print() method.
  5.1768 +
  5.1769 +	It can:
  5.1770 +	-# Print to memory.
  5.1771 +	-# Print to a file you provide.
  5.1772 +	-# Print XML without a XMLDocument.
  5.1773 +
  5.1774 +	Print to Memory
  5.1775 +
  5.1776 +	@verbatim
  5.1777 +	XMLPrinter printer;
  5.1778 +	doc->Print( &printer );
  5.1779 +	SomeFunction( printer.CStr() );
  5.1780 +	@endverbatim
  5.1781 +
  5.1782 +	Print to a File
  5.1783 +
  5.1784 +	You provide the file pointer.
  5.1785 +	@verbatim
  5.1786 +	XMLPrinter printer( fp );
  5.1787 +	doc.Print( &printer );
  5.1788 +	@endverbatim
  5.1789 +
  5.1790 +	Print without a XMLDocument
  5.1791 +
  5.1792 +	When loading, an XML parser is very useful. However, sometimes
  5.1793 +	when saving, it just gets in the way. The code is often set up
  5.1794 +	for streaming, and constructing the DOM is just overhead.
  5.1795 +
  5.1796 +	The Printer supports the streaming case. The following code
  5.1797 +	prints out a trivially simple XML file without ever creating
  5.1798 +	an XML document.
  5.1799 +
  5.1800 +	@verbatim
  5.1801 +	XMLPrinter printer( fp );
  5.1802 +	printer.OpenElement( "foo" );
  5.1803 +	printer.PushAttribute( "foo", "bar" );
  5.1804 +	printer.CloseElement();
  5.1805 +	@endverbatim
  5.1806 +*/
  5.1807 +class XMLPrinter : public XMLVisitor
  5.1808 +{
  5.1809 +public:
  5.1810 +    /** Construct the printer. If the FILE* is specified,
  5.1811 +    	this will print to the FILE. Else it will print
  5.1812 +    	to memory, and the result is available in CStr().
  5.1813 +    	If 'compact' is set to true, then output is created
  5.1814 +    	with only required whitespace and newlines.
  5.1815 +    */
  5.1816 +    XMLPrinter( FILE* file=0, bool compact = false );
  5.1817 +    ~XMLPrinter()	{}
  5.1818 +
  5.1819 +    /** If streaming, write the BOM and declaration. */
  5.1820 +    void PushHeader( bool writeBOM, bool writeDeclaration );
  5.1821 +    /** If streaming, start writing an element.
  5.1822 +        The element must be closed with CloseElement()
  5.1823 +    */
  5.1824 +    void OpenElement( const char* name );
  5.1825 +    /// If streaming, add an attribute to an open element.
  5.1826 +    void PushAttribute( const char* name, const char* value );
  5.1827 +    void PushAttribute( const char* name, int value );
  5.1828 +    void PushAttribute( const char* name, unsigned value );
  5.1829 +    void PushAttribute( const char* name, bool value );
  5.1830 +    void PushAttribute( const char* name, double value );
  5.1831 +    /// If streaming, close the Element.
  5.1832 +    void CloseElement();
  5.1833 +
  5.1834 +    /// Add a text node.
  5.1835 +    void PushText( const char* text, bool cdata=false );
  5.1836 +    /// Add a text node from an integer.
  5.1837 +    void PushText( int value );
  5.1838 +    /// Add a text node from an unsigned.
  5.1839 +    void PushText( unsigned value );
  5.1840 +    /// Add a text node from a bool.
  5.1841 +    void PushText( bool value );
  5.1842 +    /// Add a text node from a float.
  5.1843 +    void PushText( float value );
  5.1844 +    /// Add a text node from a double.
  5.1845 +    void PushText( double value );
  5.1846 +
  5.1847 +    /// Add a comment
  5.1848 +    void PushComment( const char* comment );
  5.1849 +
  5.1850 +    void PushDeclaration( const char* value );
  5.1851 +    void PushUnknown( const char* value );
  5.1852 +
  5.1853 +    virtual bool VisitEnter( const XMLDocument& /*doc*/ );
  5.1854 +    virtual bool VisitExit( const XMLDocument& /*doc*/ )			{
  5.1855 +        return true;
  5.1856 +    }
  5.1857 +
  5.1858 +    virtual bool VisitEnter( const XMLElement& element, const XMLAttribute* attribute );
  5.1859 +    virtual bool VisitExit( const XMLElement& element );
  5.1860 +
  5.1861 +    virtual bool Visit( const XMLText& text );
  5.1862 +    virtual bool Visit( const XMLComment& comment );
  5.1863 +    virtual bool Visit( const XMLDeclaration& declaration );
  5.1864 +    virtual bool Visit( const XMLUnknown& unknown );
  5.1865 +
  5.1866 +    /**
  5.1867 +    	If in print to memory mode, return a pointer to
  5.1868 +    	the XML file in memory.
  5.1869 +    */
  5.1870 +    const char* CStr() const {
  5.1871 +        return _buffer.Mem();
  5.1872 +    }
  5.1873 +    /**
  5.1874 +    	If in print to memory mode, return the size
  5.1875 +    	of the XML file in memory. (Note the size returned
  5.1876 +    	includes the terminating null.)
  5.1877 +    */
  5.1878 +    int CStrSize() const {
  5.1879 +        return _buffer.Size();
  5.1880 +    }
  5.1881 +
  5.1882 +private:
  5.1883 +    void SealElement();
  5.1884 +    void PrintSpace( int depth );
  5.1885 +    void PrintString( const char*, bool restrictedEntitySet );	// prints out, after detecting entities.
  5.1886 +    void Print( const char* format, ... );
  5.1887 +
  5.1888 +    bool _elementJustOpened;
  5.1889 +    bool _firstElement;
  5.1890 +    FILE* _fp;
  5.1891 +    int _depth;
  5.1892 +    int _textDepth;
  5.1893 +    bool _processEntities;
  5.1894 +    bool _compactMode;
  5.1895 +
  5.1896 +    enum {
  5.1897 +        ENTITY_RANGE = 64,
  5.1898 +        BUF_SIZE = 200
  5.1899 +    };
  5.1900 +    bool _entityFlag[ENTITY_RANGE];
  5.1901 +    bool _restrictedEntityFlag[ENTITY_RANGE];
  5.1902 +
  5.1903 +    DynArray< const char*, 10 > _stack;
  5.1904 +    DynArray< char, 20 > _buffer;
  5.1905 +#ifdef _MSC_VER
  5.1906 +    DynArray< char, 20 > _accumulator;
  5.1907 +#endif
  5.1908 +};
  5.1909 +
  5.1910 +
  5.1911 +}	// tinyxml2
  5.1912 +
  5.1913 +
  5.1914 +#endif // TINYXML2_INCLUDED
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/ConfigureDebian.sh	Wed Jan 14 06:51:16 2015 +0200
     6.3 @@ -0,0 +1,49 @@
     6.4 +#!/bin/bash
     6.5 +
     6.6 +#############################################################################
     6.7 +#
     6.8 +# Filename    : ConfigurePermissionsAndPackages.sh
     6.9 +# Content     : Linux file for installing prerequisite libraries and the 
    6.10 +#               permissions file for the USB HID device
    6.11 +# Created     : 2013
    6.12 +# Authors     : Simon Hallam and Brant Lewis
    6.13 +# Copyright   : Copyright 2013 OculusVR, Inc. All Rights Reserved
    6.14 +# Instruction : Ensure that the install.sh has execute permissions.
    6.15 +#               Navigate to a command shell, enter:
    6.16 +#               
    6.17 +#                   ./install.sh
    6.18 +#
    6.19 +#		Enter the administrator password for sudo access.
    6.20 +#
    6.21 +# Notes       : UBUNTU 13 USERS
    6.22 +#               ---------------
    6.23 +#                 The OculusConfigUtil does not currently support Ubuntu 13
    6.24 +#                 out of the box.  If you see an error similar to this upon
    6.25 +#                 launching OculusConfigUtil:
    6.26 +#
    6.27 +#                     "error while loading shared libraries: libudev.so.0"
    6.28 +#
    6.29 +#                 Then please try the following solution, until we officially 
    6.30 +#                 support Ubuntu 13:
    6.31 +#
    6.32 +#                     cd /lib/x86_64-linux-gnu/
    6.33 +#                     sudo ln -sf libudev.so.1 libudev.so.0
    6.34 +#
    6.35 +#############################################################################
    6.36 +
    6.37 +echo "Installing OculusVR Rift udev rules file..."
    6.38 +sudo cp ./LibOVR/90-oculus.rules /lib/udev/rules.d
    6.39 +echo "Installing libudev..."
    6.40 +sudo apt-get install libudev-dev
    6.41 +echo "Installing libxext..."
    6.42 +sudo apt-get install libxext-dev
    6.43 +echo "Installing mesa-common..."
    6.44 +sudo apt-get install mesa-common-dev
    6.45 +echo "Installing freeglut3..."
    6.46 +sudo apt-get install freeglut3-dev
    6.47 +echo "Installing Xrandr..."
    6.48 +sudo apt-get install libxrandr-dev
    6.49 +echo "Installing uuid"
    6.50 +sudo apt-get install uuid-dev
    6.51 +echo "Installation complete"
    6.52 +
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/LINUX_README	Wed Jan 14 06:51:16 2015 +0200
     7.3 @@ -0,0 +1,57 @@
     7.4 +WHAT SETUP IS REQUIRED?
     7.5 +
     7.6 +  * Appropriate permissions for Oculus hidraw devices. See
     7.7 +    LibOVR/90-oculus.rules and ConfigureDebian.sh.
     7.8 +  * Use a multihead setup with one X screen spanning both displays (such as
     7.9 +    NVidia TwinView) or place the rift on an independent X screen.
    7.10 +  * Ensure oculusd is running when using the rift.
    7.11 +
    7.12 +BUILD INSTRUCTIONS
    7.13 +
    7.14 +  After installing the appropriate packages issue 'make' in the root of
    7.15 +  the SDK directory. This will build a release version of Oculus World Demo
    7.16 +  (OWD). To generate debug symbols use 'make DEBUG=1'.
    7.17 +
    7.18 +HOW DO I RUN OCULUS WORLD DEMO (OWD)?
    7.19 +
    7.20 +  Either run the binary directly from the output directory, or use 'make run'.
    7.21 +
    7.22 +SHOULD I ROTATE MY DEVICE'S SCREEN?
    7.23 +
    7.24 +  Manual screen rotation is not recommended. If your window is fullscreen on a
    7.25 +  rift device, set the ovrDistortionCap_LinuxDevFullscreen distortion cap to
    7.26 +  have the SDK automatically rotate the distortion mesh on appropriate devices.
    7.27 +  Be aware you will have to account for window size. You can use
    7.28 +  OVR::SDKWindow::findDevScreenForHMD (Displays/OVR_Linux_SDKWindow.h) to
    7.29 +  return the screen offset and dimensions necessary to size your Linux window.
    7.30 +  See Samples/CommonSrc/Platform/Linux_Platform.cpp for an example.
    7.31 +
    7.32 +TWINVIEW
    7.33 +
    7.34 +  You must sync to the Rift's display device for a smooth experience when using
    7.35 +  TwinView. To consistently sync to the rift with TwinView setups, set the
    7.36 +  __GL_SYNC_DISPLAY_DEVICE environment variable to the appropriate display
    7.37 +  device before X starts. For example in your /etc/profile you could place the
    7.38 +  following:
    7.39 +
    7.40 +    export __GL_SYNC_DISPLAY_DEVICE="DFP-1"
    7.41 +
    7.42 +  if your rift corresponds to DFP-1.
    7.43 +
    7.44 +STARTING THE TRACKING SERVICE AUTOMATICALLY
    7.45 +
    7.46 +  Start the tracking service when a user is logged in using Xsession files.
    7.47 +
    7.48 +UBUNTU USERS
    7.49 +
    7.50 +  There was a ubuntu-specific kernel bug which affected HID devices in 14.04.
    7.51 +  If you are receiving feature report failures try upgrading your distro
    7.52 +  (dist-upgrade).
    7.53 +
    7.54 +KNOWN ISSUES
    7.55 +
    7.56 +  * OWD vsync initially disabled on Radeon proprietary.
    7.57 +  * Frame loss on NVidia TwinView setups. Use an independent X screen for an
    7.58 +    optimal experience.
    7.59 +  * Mesa DK2 latency tester does not function properly in OWD.
    7.60 +
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/LibOVR/90-oculus.rules	Wed Jan 14 06:51:16 2015 +0200
     8.3 @@ -0,0 +1,2 @@
     8.4 +# Oculus HID Sensor naming and permissioning
     8.5 +KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="2833", MODE="0666"
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/LibOVR/Include/OVR.h	Wed Jan 14 06:51:16 2015 +0200
     9.3 @@ -0,0 +1,36 @@
     9.4 +/************************************************************************************
     9.5 +
     9.6 +Filename    :   OVR.h
     9.7 +Content     :   The main public interface to Oculus for C++ Developers.
     9.8 +                Includes C API and helper classes.
     9.9 +
    9.10 +Copyright   :   Copyright 2014 Oculus VR, LLC. All Rights reserved.
    9.11 +
    9.12 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
    9.13 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
    9.14 +which is provided at the time of installation or download, or which 
    9.15 +otherwise accompanies this software in either electronic or hard copy form.
    9.16 +
    9.17 +You may obtain a copy of the License at
    9.18 +
    9.19 +http://www.oculusvr.com/licenses/LICENSE-3.2 
    9.20 +
    9.21 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
    9.22 +distributed under the License is distributed on an "AS IS" BASIS,
    9.23 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    9.24 +See the License for the specific language governing permissions and
    9.25 +limitations under the License.
    9.26 +
    9.27 +*************************************************************************************/
    9.28 +
    9.29 +#ifndef OVR_h
    9.30 +#define OVR_h
    9.31 +
    9.32 +#include "OVR_Version.h"
    9.33 +
    9.34 +#include "../Src/Kernel/OVR_Math.h"
    9.35 +
    9.36 +#include "../Src/OVR_CAPI.h"
    9.37 +
    9.38 +#endif
    9.39 +
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/LibOVR/Include/OVR_Kernel.h	Wed Jan 14 06:51:16 2015 +0200
    10.3 @@ -0,0 +1,42 @@
    10.4 +/************************************************************************************
    10.5 +
    10.6 +Filename    :   OVRKernel.h
    10.7 +Content     :   This contains references to all OVR Kernel headers in Src folder.
    10.8 +                Should be generated automatically based on PublicHeader tags.
    10.9 +
   10.10 +Copyright   :   Copyright 2014 Oculus VR, LLC. All Rights reserved.
   10.11 +
   10.12 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
   10.13 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
   10.14 +which is provided at the time of installation or download, or which 
   10.15 +otherwise accompanies this software in either electronic or hard copy form.
   10.16 +
   10.17 +You may obtain a copy of the License at
   10.18 +
   10.19 +http://www.oculusvr.com/licenses/LICENSE-3.2 
   10.20 +
   10.21 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
   10.22 +distributed under the License is distributed on an "AS IS" BASIS,
   10.23 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   10.24 +See the License for the specific language governing permissions and
   10.25 +limitations under the License.
   10.26 +
   10.27 +*************************************************************************************/
   10.28 +
   10.29 +#ifndef OVR_h
   10.30 +#define OVR_h
   10.31 +
   10.32 +#include "../Src/Kernel/OVR_Types.h"
   10.33 +#include "../Src/Kernel/OVR_Allocator.h"
   10.34 +#include "../Src/Kernel/OVR_RefCount.h"
   10.35 +#include "../Src/Kernel/OVR_Log.h"
   10.36 +#include "../Src/Kernel/OVR_Math.h"
   10.37 +#include "../Src/Kernel/OVR_System.h"
   10.38 +#include "../Src/Kernel/OVR_Nullptr.h"
   10.39 +#include "../Src/Kernel/OVR_String.h"
   10.40 +#include "../Src/Kernel/OVR_Array.h"
   10.41 +#include "../Src/Kernel/OVR_Timer.h"
   10.42 +#include "../Src/Kernel/OVR_SysFile.h"
   10.43 +
   10.44 +#endif
   10.45 +
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/LibOVR/Include/OVR_Version.h	Wed Jan 14 06:51:16 2015 +0200
    11.3 @@ -0,0 +1,35 @@
    11.4 +/************************************************************************************
    11.5 +
    11.6 +Filename    :   OVRVersion.h
    11.7 +Content     :
    11.8 +
    11.9 +Copyright   :   Copyright 2014 Oculus VR, LLC. All Rights reserved.
   11.10 +
   11.11 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License");
   11.12 +you may not use the Oculus VR Rift SDK except in compliance with the License,
   11.13 +which is provided at the time of installation or download, or which
   11.14 +otherwise accompanies this software in either electronic or hard copy form.
   11.15 +
   11.16 +You may obtain a copy of the License at
   11.17 +
   11.18 +http://www.oculusvr.com/licenses/LICENSE-3.2
   11.19 +
   11.20 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK
   11.21 +distributed under the License is distributed on an "AS IS" BASIS,
   11.22 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   11.23 +See the License for the specific language governing permissions and
   11.24 +limitations under the License.
   11.25 +
   11.26 +*************************************************************************************/
   11.27 +
   11.28 +#ifndef _OVR_VERSION_H
   11.29 +#define _OVR_VERSION_H
   11.30 +
   11.31 +#define OVR_MAJOR_VERSION 0
   11.32 +#define OVR_MINOR_VERSION 4
   11.33 +#define OVR_BUILD_VERSION 4
   11.34 +#define OVR_VERSION_STRING "0.4.4"
   11.35 +
   11.36 +#define OVR_DK2_LATEST_FIRMWARE_MAJOR_VERSION 2
   11.37 +#define OVR_DK2_LATEST_FIRMWARE_MINOR_VERSION 12
   11.38 +#endif
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/LibOVR/Makefile	Wed Jan 14 06:51:16 2015 +0200
    12.3 @@ -0,0 +1,156 @@
    12.4 +#############################################################################
    12.5 +#
    12.6 +# Filename    : Makefile
    12.7 +# Content     : Makefile for building Linux version of: libovr
    12.8 +# Created     : 2014
    12.9 +# Authors     : Simon Hallam, Peter Giokaris, Chris Taylor
   12.10 +# Copyright   : Copyright 2014 OculusVR, Inc. All Rights Reserved
   12.11 +# Instruction : The g++ compiler and standard lib packages need to be
   12.12 +#               installed on the system.  Navigate in a shell to the
   12.13 +#               directory where this Makefile is located and enter:
   12.14 +#
   12.15 +#               make                builds the release version for the
   12.16 +#                                   current architecture
   12.17 +#               make clean          delete intermediate release object files
   12.18 +#                                   and the library file
   12.19 +#               make DEBUG=1        builds the debug version for the current
   12.20 +#                                   architecture
   12.21 +#               make clean DEBUG=1  deletes intermediate debug object files
   12.22 +#                                   and the library file
   12.23 +#
   12.24 +# Output      : Relative to the directory this Makefile lives in, libraries
   12.25 +#               are built at the following locations depending upon the
   12.26 +#               architecture of the system you are running:
   12.27 +#
   12.28 +#               ./Lib/Linux/Debug/i386/libovr.a
   12.29 +#               ./Lib/Linux/Debug/x86_64/libovr.a
   12.30 +#               ./Lib/Linux/Release/i386/libovr.a
   12.31 +#               ./Lib/Linux/Release/x86_64/libovr.a
   12.32 +#
   12.33 +#############################################################################
   12.34 +
   12.35 +####### Include auxiliary makefiles in current directory
   12.36 +-include Makefile.*[^~]
   12.37 +
   12.38 +####### Detect system architecture
   12.39 +
   12.40 +SYSARCH       = i386
   12.41 +ifeq ($(shell uname -m),x86_64)
   12.42 +SYSARCH       = x86_64
   12.43 +endif
   12.44 +
   12.45 +####### Compiler, tools and options
   12.46 +
   12.47 +CXX           = g++
   12.48 +LINK          = 
   12.49 +DELETEFILE    = rm -f
   12.50 +
   12.51 +####### Detect debug or release
   12.52 +
   12.53 +COMMONFLAGS   = -Wall -Wextra -Werror -pipe -fPIC -msse2
   12.54 +
   12.55 +DEBUG         ?= 0
   12.56 +CXXFLAGS 			?=
   12.57 +ifeq ($(DEBUG), 1)
   12.58 +	CXXFLAGS      += $(COMMONFLAGS) -DDEBUG -DOVR_BUILD_DEBUG -g
   12.59 +	RELEASETYPE   ?= Debug
   12.60 +else
   12.61 +	CXXFLAGS      += $(COMMONFLAGS) -O2 -fno-strict-aliasing
   12.62 +	RELEASETYPE   ?= Release
   12.63 +endif
   12.64 +
   12.65 +####### Paths
   12.66 +
   12.67 +LIBOVRPATH    = .
   12.68 +3RDPARTYPATH  = ../3rdParty
   12.69 +INCPATH       = -I. -I.. -I$(LIBOVRPATH)/Include -I$(LIBOVRPATH)/Src
   12.70 +OBJPATH       = ./Obj/Linux/$(RELEASETYPE)/$(SYSARCH)
   12.71 +PREFIX        = /usr/local
   12.72 +
   12.73 +####### Files
   12.74 +
   12.75 +TARGET_DIR      = ./Lib/Linux/$(RELEASETYPE)/$(SYSARCH)
   12.76 +STATIC_NAME     = libovr.a
   12.77 +STATIC_TARGET   = $(TARGET_DIR)/$(STATIC_NAME)
   12.78 +LIBOVR_INST_HDR = Src/OVR_CAPI.h Src/OVR_CAPI_Keys.h Src/OVR_CAPI_GL.h
   12.79 +
   12.80 +####### Rules
   12.81 +
   12.82 +all:    $(STATIC_TARGET)
   12.83 +
   12.84 +OTHER_SOURCE =	$(3RDPARTYPATH)/EDID/edid.cpp \
   12.85 +				$(3RDPARTYPATH)/TinyXml/tinyxml2.cpp
   12.86 +
   12.87 +OTHER_OBJECTS = $(OTHER_SOURCE:.cpp=.o)
   12.88 +
   12.89 +LIBOVR_SOURCE = 	$(LIBOVRPATH)/Src/Net/OVR_BitStream.cpp \
   12.90 +				$(LIBOVRPATH)/Src/Net/OVR_Unix_Socket.cpp \
   12.91 +				$(LIBOVRPATH)/Src/Net/OVR_NetworkPlugin.cpp \
   12.92 +				$(LIBOVRPATH)/Src/Net/OVR_PacketizedTCPSocket.cpp \
   12.93 +				$(LIBOVRPATH)/Src/Net/OVR_RPC1.cpp \
   12.94 +				$(LIBOVRPATH)/Src/Net/OVR_Session.cpp \
   12.95 +				$(LIBOVRPATH)/Src/Net/OVR_Socket.cpp \
   12.96 +				$(LIBOVRPATH)/Src/Service/Service_NetClient.cpp \
   12.97 +				$(LIBOVRPATH)/Src/Service/Service_NetSessionCommon.cpp \
   12.98 +				$(LIBOVRPATH)/Src/Tracking/Tracking_SensorStateReader.cpp \
   12.99 +				$(LIBOVRPATH)/Src/Displays/OVR_Display.cpp \
  12.100 +				$(LIBOVRPATH)/Src/Displays/OVR_Linux_Display.cpp \
  12.101 +				$(LIBOVRPATH)/Src/Displays/OVR_Linux_SDKWindow.cpp \
  12.102 +				$(LIBOVRPATH)/Src/CAPI/CAPI_DistortionRenderer.cpp \
  12.103 +				$(LIBOVRPATH)/Src/CAPI/CAPI_HSWDisplay.cpp \
  12.104 +				$(LIBOVRPATH)/Src/CAPI/CAPI_FrameTimeManager.cpp \
  12.105 +				$(LIBOVRPATH)/Src/CAPI/CAPI_HMDRenderState.cpp \
  12.106 +				$(LIBOVRPATH)/Src/CAPI/CAPI_HMDState.cpp \
  12.107 +				$(LIBOVRPATH)/Src/CAPI/CAPI_LatencyStatistics.cpp \
  12.108 +				$(LIBOVRPATH)/Src/CAPI/GL/CAPI_GL_DistortionRenderer.cpp \
  12.109 +				$(LIBOVRPATH)/Src/CAPI/GL/CAPI_GL_HSWDisplay.cpp \
  12.110 +				$(LIBOVRPATH)/Src/CAPI/GL/CAPI_GL_Util.cpp \
  12.111 +				$(LIBOVRPATH)/Src/CAPI/GL/CAPI_GLE.cpp \
  12.112 +				$(LIBOVRPATH)/Src/Kernel/OVR_Alg.cpp \
  12.113 +				$(LIBOVRPATH)/Src/Kernel/OVR_Allocator.cpp \
  12.114 +				$(LIBOVRPATH)/Src/Kernel/OVR_Atomic.cpp \
  12.115 +				$(LIBOVRPATH)/Src/Kernel/OVR_CRC32.cpp \
  12.116 +				$(LIBOVRPATH)/Src/Kernel/OVR_DebugHelp.cpp \
  12.117 +				$(LIBOVRPATH)/Src/Kernel/OVR_File.cpp \
  12.118 +				$(LIBOVRPATH)/Src/Kernel/OVR_FileFILE.cpp \
  12.119 +				$(LIBOVRPATH)/Src/Kernel/OVR_Lockless.cpp \
  12.120 +				$(LIBOVRPATH)/Src/Kernel/OVR_Log.cpp \
  12.121 +				$(LIBOVRPATH)/Src/Kernel/OVR_Math.cpp \
  12.122 +				$(LIBOVRPATH)/Src/Kernel/OVR_RefCount.cpp \
  12.123 +				$(LIBOVRPATH)/Src/Kernel/OVR_SharedMemory.cpp \
  12.124 +				$(LIBOVRPATH)/Src/Kernel/OVR_Std.cpp \
  12.125 +				$(LIBOVRPATH)/Src/Kernel/OVR_String.cpp \
  12.126 +				$(LIBOVRPATH)/Src/Kernel/OVR_String_FormatUtil.cpp \
  12.127 +				$(LIBOVRPATH)/Src/Kernel/OVR_String_PathUtil.cpp \
  12.128 +				$(LIBOVRPATH)/Src/Kernel/OVR_SysFile.cpp \
  12.129 +				$(LIBOVRPATH)/Src/Kernel/OVR_System.cpp \
  12.130 +				$(LIBOVRPATH)/Src/Kernel/OVR_ThreadsPthread.cpp \
  12.131 +				$(LIBOVRPATH)/Src/Kernel/OVR_ThreadCommandQueue.cpp \
  12.132 +				$(LIBOVRPATH)/Src/Kernel/OVR_Timer.cpp \
  12.133 +				$(LIBOVRPATH)/Src/Kernel/OVR_UTF8Util.cpp \
  12.134 +				$(LIBOVRPATH)/Src/Util/Util_Interface.cpp \
  12.135 +				$(LIBOVRPATH)/Src/Util/Util_LatencyTest2Reader.cpp \
  12.136 +				$(LIBOVRPATH)/Src/Util/Util_Render_Stereo.cpp \
  12.137 +				$(LIBOVRPATH)/Src/Util/Util_SystemInfo.cpp \
  12.138 +				$(LIBOVRPATH)/Src/Util/Util_SystemGUI.cpp \
  12.139 +				$(LIBOVRPATH)/Src/OVR_CAPI.cpp \
  12.140 +				$(LIBOVRPATH)/Src/OVR_SerialFormat.cpp \
  12.141 +				$(LIBOVRPATH)/Src/OVR_JSON.cpp \
  12.142 +				$(LIBOVRPATH)/Src/OVR_Profile.cpp \
  12.143 +				$(LIBOVRPATH)/Src/OVR_Stereo.cpp
  12.144 +
  12.145 +LIBOVR_OBJECTS = $(patsubst $(LIBOVRPATH)%.cpp,$(OBJPATH)%.o,$(LIBOVR_SOURCE))
  12.146 +
  12.147 +OBJECTS = $(OTHER_OBJECTS) $(LIBOVR_OBJECTS)
  12.148 +
  12.149 +$(OBJPATH)/%.o: %.cpp
  12.150 +	@mkdir -p $(dir $@)
  12.151 +	$(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
  12.152 +
  12.153 +$(STATIC_TARGET): $(OBJECTS)
  12.154 +	@mkdir -p $(@D)
  12.155 +	ar rvs $(STATIC_TARGET) $(OBJECTS)
  12.156 +
  12.157 +clean:
  12.158 +	-$(DELETEFILE) $(OBJECTS)
  12.159 +	-$(DELETEFILE) $(STATIC_TARGET)
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/LibOVR/Src/CAPI/CAPI_DistortionRenderer.cpp	Wed Jan 14 06:51:16 2015 +0200
    13.3 @@ -0,0 +1,157 @@
    13.4 +/************************************************************************************
    13.5 +
    13.6 +Filename    :   CAPI_DistortionRenderer.cpp
    13.7 +Content     :   Combines all of the rendering state associated with the HMD
    13.8 +Created     :   February 2, 2014
    13.9 +Authors     :   Michael Antonov
   13.10 +
   13.11 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   13.12 +
   13.13 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
   13.14 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
   13.15 +which is provided at the time of installation or download, or which 
   13.16 +otherwise accompanies this software in either electronic or hard copy form.
   13.17 +
   13.18 +You may obtain a copy of the License at
   13.19 +
   13.20 +http://www.oculusvr.com/licenses/LICENSE-3.2 
   13.21 +
   13.22 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
   13.23 +distributed under the License is distributed on an "AS IS" BASIS,
   13.24 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   13.25 +See the License for the specific language governing permissions and
   13.26 +limitations under the License.
   13.27 +
   13.28 +************************************************************************************/
   13.29 +
   13.30 +#include "CAPI_DistortionRenderer.h"
   13.31 +
   13.32 +#if defined (OVR_OS_WIN32)
   13.33 +
   13.34 +// TBD: Move to separate config file that handles back-ends.
   13.35 +#define OVR_D3D_VERSION 11
   13.36 +#include "D3D1X/CAPI_D3D1X_DistortionRenderer.h"
   13.37 +#undef OVR_D3D_VERSION
   13.38 +
   13.39 +#define OVR_D3D_VERSION 10
   13.40 +#include "D3D1X/CAPI_D3D1X_DistortionRenderer.h"
   13.41 +#undef OVR_D3D_VERSION
   13.42 +
   13.43 +#define OVR_D3D_VERSION 9
   13.44 +#include "D3D9/CAPI_D3D9_DistortionRenderer.h"
   13.45 +#undef OVR_D3D_VERSION
   13.46 +
   13.47 +#endif
   13.48 +
   13.49 +#include "GL/CAPI_GL_DistortionRenderer.h"
   13.50 +
   13.51 +namespace OVR { namespace CAPI {
   13.52 +
   13.53 +//-------------------------------------------------------------------------------------
   13.54 +// ***** DistortionRenderer
   13.55 +
   13.56 +// TBD: Move to separate config file that handles back-ends.
   13.57 +
   13.58 +DistortionRenderer::CreateFunc DistortionRenderer::APICreateRegistry[ovrRenderAPI_Count] =
   13.59 +{
   13.60 +    0, // None
   13.61 +    &GL::DistortionRenderer::Create,
   13.62 +    0, // Android_GLES
   13.63 +#if defined (OVR_OS_WIN32)
   13.64 +    &D3D9::DistortionRenderer::Create,
   13.65 +    &D3D10::DistortionRenderer::Create,
   13.66 +    &D3D11::DistortionRenderer::Create
   13.67 +#else
   13.68 +    0,
   13.69 +    0,
   13.70 +    0
   13.71 +#endif
   13.72 +};
   13.73 +
   13.74 +void DistortionRenderer::SetLatencyTestColor(unsigned char* color)
   13.75 +{
   13.76 +    if(color)
   13.77 +    {
   13.78 +        LatencyTestDrawColor[0] = color[0];
   13.79 +        LatencyTestDrawColor[1] = color[1];
   13.80 +        LatencyTestDrawColor[2] = color[2];
   13.81 +    }
   13.82 +
   13.83 +    LatencyTestActive = color != NULL;
   13.84 +}
   13.85 +
   13.86 +void DistortionRenderer::SetLatencyTest2Color(unsigned char* color)
   13.87 +{
   13.88 +    if(color)
   13.89 +    {
   13.90 +        LatencyTest2DrawColor[0] = color[0];
   13.91 +        LatencyTest2DrawColor[1] = color[1];
   13.92 +        LatencyTest2DrawColor[2] = color[2];
   13.93 +    }
   13.94 +
   13.95 +    LatencyTest2Active = color != NULL;
   13.96 +}
   13.97 +
   13.98 +void DistortionRenderer::GetOverdriveScales(float& outRiseScale, float& outFallScale)
   13.99 +{
  13.100 +    outRiseScale = 0.1f;
  13.101 +    outFallScale = 0.05f;	// falling issues are hardly visible
  13.102 +}
  13.103 +
  13.104 +double DistortionRenderer::WaitTillTime(double absTime)
  13.105 +{
  13.106 +    double initialTime = ovr_GetTimeInSeconds();
  13.107 +    if (initialTime >= absTime)
  13.108 +        return 0.0;
  13.109 +
  13.110 +    double newTime = initialTime;
  13.111 +
  13.112 +    while (newTime < absTime)
  13.113 +    {
  13.114 +// TODO: Needs further testing before enabling it on all Windows configs
  13.115 +#if 0 //def OVR_OS_WIN32
  13.116 +        double remainingWaitTime = absTime - newTime;
  13.117 +
  13.118 +        // don't yield if <2ms
  13.119 +        if(remainingWaitTime > 0.002)
  13.120 +        {
  13.121 +            // round down wait time to closest 1 ms
  13.122 +            int roundedWaitTime = (remainingWaitTime * 1000);
  13.123 +
  13.124 +            waitableTimerInterval.QuadPart = -10000LL; // 10000 * 100 ns = 1 ms
  13.125 +            waitableTimerInterval.QuadPart *= roundedWaitTime;
  13.126 +
  13.127 +            SetWaitableTimer(timer, &waitableTimerInterval, 0, NULL, NULL, TRUE);
  13.128 +            DWORD waitResult = WaitForSingleObject(timer, roundedWaitTime + 3);   // give 3 ms extra time
  13.129 +            OVR_UNUSED(waitResult);
  13.130 +
  13.131 +#ifdef OVR_BUILD_DEBUG
  13.132 +            double sleptTime = ovr_GetTimeInSeconds() - newTime;
  13.133 +            // Make sure we didn't sleep too long and it is reliable, otherwise we might miss v-sync causing a stutter
  13.134 +            if (sleptTime > (roundedWaitTime + 2) * 0.001) 
  13.135 +            {
  13.136 +                OVR_DEBUG_LOG_TEXT(
  13.137 +                    ("[DistortionRenderer::WaitTillTime] Sleep interval too long: %f\n", sleptTime));
  13.138 +            }
  13.139 +            else
  13.140 +            {
  13.141 +                OVR_ASSERT(WAIT_OBJECT_0 == waitResult);
  13.142 +            }
  13.143 +#endif
  13.144 +        }
  13.145 +        else
  13.146 +#endif
  13.147 +        {
  13.148 +            for (int j = 0; j < 5; j++)
  13.149 +                OVR_PROCESSOR_PAUSE();
  13.150 +        }
  13.151 +
  13.152 +        newTime = ovr_GetTimeInSeconds();
  13.153 +    }
  13.154 +
  13.155 +    // How long we waited
  13.156 +    return newTime - initialTime;
  13.157 +}
  13.158 +
  13.159 +}} // namespace OVR::CAPI
  13.160 +
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/LibOVR/Src/CAPI/CAPI_DistortionRenderer.h	Wed Jan 14 06:51:16 2015 +0200
    14.3 @@ -0,0 +1,167 @@
    14.4 +/************************************************************************************
    14.5 +
    14.6 +Filename    :   CAPI_DistortionRenderer.h
    14.7 +Content     :   Abstract interface for platform-specific rendering of distortion
    14.8 +Created     :   February 2, 2014
    14.9 +Authors     :   Michael Antonov
   14.10 +
   14.11 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   14.12 +
   14.13 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
   14.14 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
   14.15 +which is provided at the time of installation or download, or which 
   14.16 +otherwise accompanies this software in either electronic or hard copy form.
   14.17 +
   14.18 +You may obtain a copy of the License at
   14.19 +
   14.20 +http://www.oculusvr.com/licenses/LICENSE-3.2 
   14.21 +
   14.22 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
   14.23 +distributed under the License is distributed on an "AS IS" BASIS,
   14.24 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   14.25 +See the License for the specific language governing permissions and
   14.26 +limitations under the License.
   14.27 +
   14.28 +************************************************************************************/
   14.29 +
   14.30 +#ifndef OVR_CAPI_DistortionRenderer_h
   14.31 +#define OVR_CAPI_DistortionRenderer_h
   14.32 +
   14.33 +#include "CAPI_HMDRenderState.h"
   14.34 +#include "CAPI_FrameTimeManager.h"
   14.35 +
   14.36 +typedef void (*PostDistortionCallback)(void* pRenderContext);
   14.37 +
   14.38 +namespace OVR { namespace CAPI {
   14.39 +
   14.40 +//-------------------------------------------------------------------------------------
   14.41 +// ***** CAPI::DistortionRenderer
   14.42 +
   14.43 +// DistortionRenderer implements rendering of distortion and other overlay elements
   14.44 +// in platform-independent way.
   14.45 +// Platform-specific renderer back ends for CAPI are derived from this class.
   14.46 +
   14.47 +class  DistortionRenderer : public RefCountBase<DistortionRenderer>
   14.48 +{
   14.49 +    // Quiet assignment compiler warning.
   14.50 +    void operator = (const DistortionRenderer&) { }
   14.51 +public:
   14.52 +    
   14.53 +    DistortionRenderer(ovrRenderAPIType api, ovrHmd hmd,
   14.54 +                       FrameTimeManager& timeManager,              
   14.55 +                       const HMDRenderState& renderState) :
   14.56 +		LastUsedOverdriveTextureIndex(-1),
   14.57 +        LatencyTestActive(false),
   14.58 +        LatencyTest2Active(false),
   14.59 +        RenderAPI(api),
   14.60 +        HMD(hmd),
   14.61 +        TimeManager(timeManager),
   14.62 +        RState(renderState),
   14.63 +        GfxState(),
   14.64 +        RegisteredPostDistortionCallback(NULL)
   14.65 +    {
   14.66 +#ifdef OVR_OS_WIN32
   14.67 +        timer = CreateWaitableTimer(NULL, TRUE, NULL);
   14.68 +        OVR_ASSERT(timer != NULL);
   14.69 +#endif
   14.70 +    }
   14.71 +    virtual ~DistortionRenderer()
   14.72 +    {
   14.73 +    }
   14.74 +    
   14.75 +
   14.76 +    // Configures the Renderer based on externally passed API settings. Must be
   14.77 +    // called before use.
   14.78 +    // Under D3D, apiConfig includes D3D Device pointer, back buffer and other
   14.79 +    // needed structures.
   14.80 +    virtual bool Initialize(const ovrRenderAPIConfig* apiConfig) = 0;
   14.81 +
   14.82 +    // Submits one eye texture for rendering. This is in the separate method to
   14.83 +    // allow "submit as you render" scenarios on horizontal screens where one
   14.84 +    // eye can be scanned out before the other.
   14.85 +    virtual void SubmitEye(int eyeId, const ovrTexture* eyeTexture) = 0;
   14.86 +
   14.87 +    // Finish the frame, optionally swapping buffers.
   14.88 +    // Many implementations may actually apply the distortion here.
   14.89 +    virtual void EndFrame(bool swapBuffers) = 0;
   14.90 +    
   14.91 +    void RegisterPostDistortionCallback(PostDistortionCallback postDistortionCallback)
   14.92 +    {
   14.93 +        RegisteredPostDistortionCallback = postDistortionCallback;
   14.94 +    }
   14.95 +
   14.96 +	// Stores the current graphics pipeline state so it can be restored later.
   14.97 +	void SaveGraphicsState() { if (GfxState && !(RState.DistortionCaps & ovrDistortionCap_NoRestore)) GfxState->Save(); }
   14.98 +
   14.99 +	// Restores the saved graphics pipeline state.
  14.100 +	void RestoreGraphicsState() { if (GfxState && !(RState.DistortionCaps & ovrDistortionCap_NoRestore)) GfxState->Restore(); }
  14.101 +
  14.102 +    // *** Creation Factory logic
  14.103 +    
  14.104 +    ovrRenderAPIType GetRenderAPI() const { return RenderAPI; }
  14.105 +
  14.106 +    // Creation function for this interface, registered for API.
  14.107 +    typedef DistortionRenderer* (*CreateFunc)(ovrHmd hmd,
  14.108 +                                              FrameTimeManager &timeManager,
  14.109 +                                              const HMDRenderState& renderState);
  14.110 +
  14.111 +    static CreateFunc APICreateRegistry[ovrRenderAPI_Count];
  14.112 +
  14.113 +    // Color is expected to be 3 byte RGB
  14.114 +    void SetLatencyTestColor(unsigned char* color);
  14.115 +    void SetLatencyTest2Color(unsigned char* color);
  14.116 +    
  14.117 +protected:
  14.118 +	// Used for pixel luminance overdrive on DK2 displays
  14.119 +	// A copy of back buffer images will be ping ponged
  14.120 +	// TODO: figure out 0 dynamically based on DK2 latency?
  14.121 +	static const int	NumOverdriveTextures = 2;
  14.122 +	int					LastUsedOverdriveTextureIndex;
  14.123 +
  14.124 +    bool                LatencyTestActive;
  14.125 +    unsigned char       LatencyTestDrawColor[3];
  14.126 +    bool                LatencyTest2Active;
  14.127 +    unsigned char       LatencyTest2DrawColor[3];
  14.128 +
  14.129 +    bool IsOverdriveActive()
  14.130 +	{
  14.131 +		// doesn't make sense to use overdrive when vsync is disabled as we cannot guarantee
  14.132 +		// when the rendered frame will be displayed
  14.133 +		return LastUsedOverdriveTextureIndex >= 0 &&
  14.134 +                !((RState.EnabledHmdCaps & ovrHmdCap_NoVSync) > 0) &&
  14.135 +                (RState.DistortionCaps & ovrDistortionCap_Chromatic);
  14.136 +	}
  14.137 +
  14.138 +    void GetOverdriveScales(float& outRiseScale, float& outFallScale);
  14.139 +
  14.140 +    double WaitTillTime(double absTime);
  14.141 +
  14.142 +#ifdef OVR_OS_WIN32
  14.143 +    HANDLE timer;
  14.144 +    LARGE_INTEGER waitableTimerInterval;
  14.145 +#endif
  14.146 +
  14.147 +    class GraphicsState : public RefCountBase<GraphicsState>
  14.148 +    {
  14.149 +    public:
  14.150 +        GraphicsState() : IsValid(false) {}
  14.151 +        virtual ~GraphicsState() {}
  14.152 +        virtual void Save() = 0;
  14.153 +        virtual void Restore() = 0;
  14.154 +        
  14.155 +    protected:
  14.156 +        bool IsValid;
  14.157 +    };
  14.158 +    
  14.159 +    const ovrRenderAPIType  RenderAPI;
  14.160 +    const ovrHmd            HMD;
  14.161 +    FrameTimeManager&       TimeManager;
  14.162 +    const HMDRenderState&   RState;
  14.163 +    Ptr<GraphicsState>      GfxState;
  14.164 +    PostDistortionCallback  RegisteredPostDistortionCallback;
  14.165 +};
  14.166 +
  14.167 +}} // namespace OVR::CAPI
  14.168 +
  14.169 +
  14.170 +#endif // OVR_CAPI_DistortionRenderer_h
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/LibOVR/Src/CAPI/CAPI_FrameTimeManager.cpp	Wed Jan 14 06:51:16 2015 +0200
    15.3 @@ -0,0 +1,946 @@
    15.4 +/************************************************************************************
    15.5 +
    15.6 +Filename    :   CAPI_FrameTimeManager.cpp
    15.7 +Content     :   Manage frame timing and pose prediction for rendering
    15.8 +Created     :   November 30, 2013
    15.9 +Authors     :   Volga Aksoy, Michael Antonov
   15.10 +
   15.11 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   15.12 +
   15.13 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
   15.14 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
   15.15 +which is provided at the time of installation or download, or which 
   15.16 +otherwise accompanies this software in either electronic or hard copy form.
   15.17 +
   15.18 +You may obtain a copy of the License at
   15.19 +
   15.20 +http://www.oculusvr.com/licenses/LICENSE-3.2 
   15.21 +
   15.22 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
   15.23 +distributed under the License is distributed on an "AS IS" BASIS,
   15.24 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   15.25 +See the License for the specific language governing permissions and
   15.26 +limitations under the License.
   15.27 +
   15.28 +************************************************************************************/
   15.29 +
   15.30 +#include "CAPI_FrameTimeManager.h"
   15.31 +
   15.32 +#include "../Kernel/OVR_Log.h"
   15.33 +
   15.34 +namespace OVR { namespace CAPI {
   15.35 +
   15.36 +
   15.37 +//-------------------------------------------------------------------------------------
   15.38 +// ***** FrameLatencyTracker
   15.39 +    
   15.40 +
   15.41 +FrameLatencyTracker::FrameLatencyTracker()
   15.42 +{
   15.43 +   Reset();
   15.44 +}
   15.45 +
   15.46 +
   15.47 +void FrameLatencyTracker::Reset()
   15.48 +{
   15.49 +    TrackerEnabled         = true;
   15.50 +    WaitMode               = SampleWait_Zeroes;
   15.51 +    MatchCount             = 0;
   15.52 +    memset(FrameEndTimes, 0, sizeof(FrameEndTimes));
   15.53 +    FrameIndex             = 0;
   15.54 +  //FrameDeltas
   15.55 +    RenderLatencySeconds   = 0.0;
   15.56 +    TimewarpLatencySeconds = 0.0;
   15.57 +    LatencyRecordTime      = 0.0;
   15.58 +
   15.59 +    FrameDeltas.Clear();
   15.60 +}
   15.61 +
   15.62 +
   15.63 +unsigned char FrameLatencyTracker::GetNextDrawColor()
   15.64 +{   
   15.65 +    if (!TrackerEnabled || (WaitMode == SampleWait_Zeroes) ||
   15.66 +        (FrameIndex >= FramesTracked))
   15.67 +    {        
   15.68 +        return (unsigned char)Util::FrameTimeRecord::ReadbackIndexToColor(0);
   15.69 +    }
   15.70 +
   15.71 +    OVR_ASSERT(FrameIndex < FramesTracked);    
   15.72 +    return (unsigned char)Util::FrameTimeRecord::ReadbackIndexToColor(FrameIndex+1);
   15.73 +}
   15.74 +
   15.75 +
   15.76 +void FrameLatencyTracker::SaveDrawColor(unsigned char drawColor, double endFrameTime,
   15.77 +                                        double renderIMUTime, double timewarpIMUTime )
   15.78 +{
   15.79 +    if (!TrackerEnabled || (WaitMode == SampleWait_Zeroes))
   15.80 +        return;
   15.81 +
   15.82 +    if (FrameIndex < FramesTracked)
   15.83 +    {
   15.84 +        OVR_ASSERT(Util::FrameTimeRecord::ReadbackIndexToColor(FrameIndex+1) == drawColor);
   15.85 +        OVR_UNUSED(drawColor);
   15.86 +
   15.87 +        // saves {color, endFrame time}
   15.88 +        FrameEndTimes[FrameIndex].ReadbackIndex         = FrameIndex + 1;
   15.89 +        FrameEndTimes[FrameIndex].TimeSeconds           = endFrameTime;
   15.90 +        FrameEndTimes[FrameIndex].RenderIMUTimeSeconds  = renderIMUTime;
   15.91 +        FrameEndTimes[FrameIndex].TimewarpIMUTimeSeconds= timewarpIMUTime;
   15.92 +        FrameEndTimes[FrameIndex].MatchedRecord         = false;
   15.93 +        FrameIndex++;
   15.94 +    }
   15.95 +    else
   15.96 +    {
   15.97 +        // If the request was outstanding for too long, switch to zero mode to restart.
   15.98 +        if (endFrameTime > (FrameEndTimes[FrameIndex-1].TimeSeconds + 0.15))
   15.99 +        {
  15.100 +            if (MatchCount == 0)
  15.101 +            {
  15.102 +                // If nothing was matched, we have no latency reading.
  15.103 +                RenderLatencySeconds   = 0.0;
  15.104 +                TimewarpLatencySeconds = 0.0;
  15.105 +            }
  15.106 +
  15.107 +            WaitMode   =  SampleWait_Zeroes;
  15.108 +            MatchCount = 0;
  15.109 +            FrameIndex = 0;
  15.110 +        }
  15.111 +    }
  15.112 +}
  15.113 +
  15.114 +
  15.115 +void FrameLatencyTracker::MatchRecord(const Util::FrameTimeRecordSet &r)
  15.116 +{
  15.117 +    if (!TrackerEnabled)
  15.118 +        return;
  15.119 +
  15.120 +    if (WaitMode == SampleWait_Zeroes)
  15.121 +    {
  15.122 +        // Do we have all zeros?
  15.123 +        if (r.IsAllZeroes())
  15.124 +        {
  15.125 +            OVR_ASSERT(FrameIndex == 0);
  15.126 +            WaitMode = SampleWait_Match;
  15.127 +            MatchCount = 0;
  15.128 +        }
  15.129 +        return;
  15.130 +    }
  15.131 +
  15.132 +    // We are in Match Mode. Wait until all colors are matched or timeout,
  15.133 +    // at which point we go back to zeros.
  15.134 +
  15.135 +    for (int i = 0; i < FrameIndex; i++)
  15.136 +    {
  15.137 +        int recordIndex = 0;
  15.138 +        int consecutiveMatch  = 0;
  15.139 +
  15.140 +        OVR_ASSERT(FrameEndTimes[i].ReadbackIndex != 0);
  15.141 +
  15.142 +        if (r.FindReadbackIndex(&recordIndex, FrameEndTimes[i].ReadbackIndex))
  15.143 +        {
  15.144 +            // Advance forward to see that we have several more matches.
  15.145 +            int  ri = recordIndex + 1;
  15.146 +            int  j  = i + 1;
  15.147 +
  15.148 +            consecutiveMatch++;
  15.149 +
  15.150 +            for (; (j < FrameIndex) && (ri < Util::FrameTimeRecordSet::RecordCount); j++, ri++)
  15.151 +            {
  15.152 +                if (r[ri].ReadbackIndex != FrameEndTimes[j].ReadbackIndex)
  15.153 +                    break;
  15.154 +                consecutiveMatch++;
  15.155 +            }
  15.156 +
  15.157 +            // Match at least 2 items in the row, to avoid accidentally matching color.
  15.158 +            if (consecutiveMatch > 1)
  15.159 +            {
  15.160 +                // Record latency values for all but last samples. Keep last 2 samples
  15.161 +                // for the future to simplify matching.
  15.162 +                for (int q = 0; q < consecutiveMatch; q++)
  15.163 +                {
  15.164 +                    const Util::FrameTimeRecord &scanoutFrame = r[recordIndex+q];
  15.165 +                    FrameTimeRecordEx           &renderFrame  = FrameEndTimes[i+q];
  15.166 +                    
  15.167 +                    if (!renderFrame.MatchedRecord)
  15.168 +                    {
  15.169 +                        double deltaSeconds = scanoutFrame.TimeSeconds - renderFrame.TimeSeconds;
  15.170 +                        if (deltaSeconds > 0.0)
  15.171 +                        {
  15.172 +                            FrameDeltas.AddTimeDelta(deltaSeconds);
  15.173 +
  15.174 +                            // FIRMWARE HACK: don't take new readings if they're 10ms higher than previous reading
  15.175 +                            // but only do that for 1 second, after that accept it regardless of the timing difference
  15.176 +                            double newRenderLatency = scanoutFrame.TimeSeconds - renderFrame.RenderIMUTimeSeconds;                            
  15.177 +                            if( newRenderLatency < RenderLatencySeconds + 0.01 ||
  15.178 +                                scanoutFrame.TimeSeconds > LatencyRecordTime + 1.0)
  15.179 +                            {
  15.180 +                                LatencyRecordTime      = scanoutFrame.TimeSeconds;
  15.181 +                                RenderLatencySeconds   = scanoutFrame.TimeSeconds - renderFrame.RenderIMUTimeSeconds;
  15.182 +                                TimewarpLatencySeconds = (renderFrame.TimewarpIMUTimeSeconds == 0.0)  ?  0.0 :
  15.183 +                                                         (scanoutFrame.TimeSeconds - renderFrame.TimewarpIMUTimeSeconds);
  15.184 +                            }
  15.185 +                        }
  15.186 +
  15.187 +                        renderFrame.MatchedRecord = true;
  15.188 +                        MatchCount++;
  15.189 +                    }
  15.190 +                }
  15.191 +
  15.192 +                // Exit for.
  15.193 +                break;
  15.194 +            }
  15.195 +        }
  15.196 +    } // for ( i => FrameIndex )
  15.197 +
  15.198 +
  15.199 +    // If we matched all frames, start over.
  15.200 +    if (MatchCount == FramesTracked)
  15.201 +    {
  15.202 +        WaitMode   =  SampleWait_Zeroes;
  15.203 +        MatchCount = 0;
  15.204 +        FrameIndex = 0;
  15.205 +    }
  15.206 +}
  15.207 +
  15.208 +bool FrameLatencyTracker::IsLatencyTimingAvailable()
  15.209 +{
  15.210 +    return ovr_GetTimeInSeconds() < (LatencyRecordTime + 2.0);
  15.211 +}
  15.212 +
  15.213 +void FrameLatencyTracker::GetLatencyTimings(float& latencyRender, float& latencyTimewarp, float& latencyPostPresent)
  15.214 +{
  15.215 +    if (!IsLatencyTimingAvailable())
  15.216 +    {
  15.217 +        latencyRender = 0.0f;
  15.218 +        latencyTimewarp = 0.0f;
  15.219 +        latencyPostPresent = 0.0f;
  15.220 +    }
  15.221 +    else
  15.222 +    {
  15.223 +        latencyRender = (float)RenderLatencySeconds;
  15.224 +        latencyTimewarp = (float)TimewarpLatencySeconds;
  15.225 +        latencyPostPresent = (float)FrameDeltas.GetMedianTimeDelta();
  15.226 +    }    
  15.227 +}
  15.228 +
  15.229 +
  15.230 +//-------------------------------------------------------------------------------------
  15.231 +// ***** FrameTimeManager
  15.232 +
  15.233 +FrameTimeManager::FrameTimeManager(bool vsyncEnabled) :
  15.234 +    RenderInfo(),
  15.235 +    FrameTimeDeltas(),
  15.236 +    DistortionRenderTimes(),
  15.237 +    ScreenLatencyTracker(),
  15.238 +    VsyncEnabled(vsyncEnabled),
  15.239 +    DynamicPrediction(true),
  15.240 +    SdkRender(false),
  15.241 +  //DirectToRift(false), Initialized below.
  15.242 +  //VSyncToScanoutDelay(0.0), Initialized below.
  15.243 +  //NoVSyncToScanoutDelay(0.0), Initialized below.
  15.244 +    ScreenSwitchingDelay(0.0),
  15.245 +    FrameTiming(),
  15.246 +    LocklessTiming(),
  15.247 +    RenderIMUTimeSeconds(0.0),
  15.248 +    TimewarpIMUTimeSeconds(0.0)
  15.249 +{
  15.250 +    // If driver is in use,
  15.251 +    DirectToRift = !Display::InCompatibilityMode(false);
  15.252 +    if (DirectToRift)
  15.253 +    {
  15.254 +        // The latest driver provides a post-present vsync-to-scan-out delay
  15.255 +        // that is roughly zero.  The latency tester will provide real numbers
  15.256 +        // but when it is unavailable for some reason, we should default to
  15.257 +        // an expected value.
  15.258 +        VSyncToScanoutDelay = 0.0001f;
  15.259 +    }
  15.260 +    else
  15.261 +    {
  15.262 +        // HACK: SyncToScanoutDelay observed close to 1 frame in video cards.
  15.263 +        //       Overwritten by dynamic latency measurement on DK2.
  15.264 +        VSyncToScanoutDelay = 0.013f;
  15.265 +    }
  15.266 +    NoVSyncToScanoutDelay = 0.004f;
  15.267 +}
  15.268 +
  15.269 +void FrameTimeManager::Init(HmdRenderInfo& renderInfo)
  15.270 +{
  15.271 +    // Set up prediction distances.
  15.272 +    // With-Vsync timings.
  15.273 +    RenderInfo = renderInfo;
  15.274 +
  15.275 +    ScreenSwitchingDelay = RenderInfo.Shutter.PixelSettleTime * 0.5f + 
  15.276 +                           RenderInfo.Shutter.PixelPersistence * 0.5f;
  15.277 +}
  15.278 +
  15.279 +void FrameTimeManager::ResetFrameTiming(unsigned frameIndex,
  15.280 +                                        bool dynamicPrediction,
  15.281 +                                        bool sdkRender)
  15.282 +{    
  15.283 +    DynamicPrediction   = dynamicPrediction;
  15.284 +    SdkRender           = sdkRender;
  15.285 +
  15.286 +    FrameTimeDeltas.Clear();
  15.287 +    DistortionRenderTimes.Clear();
  15.288 +    ScreenLatencyTracker.Reset();
  15.289 +    //Revisit dynamic pre-Timewarp delay adjustment logic
  15.290 +    //TimewarpAdjuster.Reset();
  15.291 +
  15.292 +    FrameTiming.FrameIndex               = frameIndex;
  15.293 +    FrameTiming.NextFrameTime            = 0.0;
  15.294 +    FrameTiming.ThisFrameTime            = 0.0;
  15.295 +    FrameTiming.Inputs.FrameDelta        = calcFrameDelta();
  15.296 +    // This one is particularly critical, and has been missed in the past because
  15.297 +    // this init function wasn't called for app-rendered.
  15.298 +    FrameTiming.Inputs.ScreenDelay       = calcScreenDelay();
  15.299 +    FrameTiming.Inputs.TimewarpWaitDelta = 0.0f;
  15.300 +
  15.301 +    LocklessTiming.SetState(FrameTiming);
  15.302 +}
  15.303 +
  15.304 +
  15.305 +double  FrameTimeManager::calcFrameDelta() const
  15.306 +{
  15.307 +    // Timing difference between frame is tracked by FrameTimeDeltas, or
  15.308 +    // is a hard-coded value of 1/FrameRate.
  15.309 +    double  frameDelta;    
  15.310 +
  15.311 +    if (!VsyncEnabled)
  15.312 +    {
  15.313 +        frameDelta = 0.0;
  15.314 +    }
  15.315 +    else if (FrameTimeDeltas.GetCount() > 3)
  15.316 +    {
  15.317 +        frameDelta = FrameTimeDeltas.GetMedianTimeDelta();
  15.318 +        if (frameDelta > (RenderInfo.Shutter.VsyncToNextVsync + 0.001))
  15.319 +            frameDelta = RenderInfo.Shutter.VsyncToNextVsync;
  15.320 +    }
  15.321 +    else
  15.322 +    {
  15.323 +        frameDelta = RenderInfo.Shutter.VsyncToNextVsync;
  15.324 +    }
  15.325 +
  15.326 +    return frameDelta;
  15.327 +}
  15.328 +
  15.329 +
  15.330 +double  FrameTimeManager::calcScreenDelay() const
  15.331 +{
  15.332 +    double  screenDelay = ScreenSwitchingDelay;
  15.333 +    double  measuredVSyncToScanout;
  15.334 +
  15.335 +    // Use real-time DK2 latency tester HW for prediction if its is working.
  15.336 +    // Do sanity check under 60 ms
  15.337 +    if (!VsyncEnabled)
  15.338 +    {
  15.339 +        screenDelay += NoVSyncToScanoutDelay;
  15.340 +    }
  15.341 +    else if ( DynamicPrediction &&
  15.342 +              (ScreenLatencyTracker.FrameDeltas.GetCount() > 3) &&
  15.343 +              (measuredVSyncToScanout = ScreenLatencyTracker.FrameDeltas.GetMedianTimeDelta(),
  15.344 +               (measuredVSyncToScanout > -0.0001) && (measuredVSyncToScanout < 0.06)) ) 
  15.345 +    {
  15.346 +        screenDelay += measuredVSyncToScanout;
  15.347 +    }
  15.348 +    else
  15.349 +    {
  15.350 +        screenDelay += VSyncToScanoutDelay;
  15.351 +    }
  15.352 +
  15.353 +    return screenDelay;
  15.354 +}
  15.355 +
  15.356 +double FrameTimeManager::calcTimewarpWaitDelta() const
  15.357 +{
  15.358 +    // If timewarp timing hasn't been calculated, we should wait.
  15.359 +    if (!VsyncEnabled)
  15.360 +        return 0.0;
  15.361 +
  15.362 +    if (SdkRender)
  15.363 +    {
  15.364 +        if (NeedDistortionTimeMeasurement())
  15.365 +            return 0.0;
  15.366 +        return -(DistortionRenderTimes.GetMedianTimeDelta() + 0.0035);
  15.367 +
  15.368 +        //Revisit dynamic pre-Timewarp delay adjustment logic
  15.369 +        /*return -(DistortionRenderTimes.GetMedianTimeDelta() + 0.002 +
  15.370 +                 TimewarpAdjuster.GetDelayReduction());*/
  15.371 +    }
  15.372 +   
  15.373 +    // Just a hard-coded "high" value for game-drawn code.
  15.374 +    // TBD: Just return 0 and let users calculate this themselves?
  15.375 +    return -0.004;
  15.376 +
  15.377 +    //Revisit dynamic pre-Timewarp delay adjustment logic
  15.378 +    //return -(0.003 + TimewarpAdjuster.GetDelayReduction());
  15.379 +}
  15.380 +
  15.381 +//Revisit dynamic pre-Timewarp delay adjustment logic
  15.382 +/*
  15.383 +void FrameTimeManager::updateTimewarpTiming()
  15.384 +{
  15.385 +    // If timewarp timing changes based on this sample, update it.
  15.386 +    double newTimewarpWaitDelta = calcTimewarpWaitDelta();
  15.387 +    if (newTimewarpWaitDelta != FrameTiming.Inputs.TimewarpWaitDelta)
  15.388 +    {
  15.389 +        FrameTiming.Inputs.TimewarpWaitDelta = newTimewarpWaitDelta;
  15.390 +        LocklessTiming.SetState(FrameTiming);
  15.391 +    }
  15.392 +}
  15.393 +*/
  15.394 +
  15.395 +void FrameTimeManager::Timing::InitTimingFromInputs(const FrameTimeManager::TimingInputs& inputs,
  15.396 +                                                    HmdShutterTypeEnum shutterType,
  15.397 +                                                    double thisFrameTime, unsigned int frameIndex)
  15.398 +{    
  15.399 +    // ThisFrameTime comes from the end of last frame, unless it it changed.  
  15.400 +    double  nextFrameBase;
  15.401 +    double  frameDelta = inputs.FrameDelta;
  15.402 +
  15.403 +    FrameIndex        = frameIndex;
  15.404 +
  15.405 +    ThisFrameTime     = thisFrameTime;
  15.406 +    NextFrameTime     = ThisFrameTime + frameDelta;
  15.407 +    nextFrameBase     = NextFrameTime + inputs.ScreenDelay;
  15.408 +    MidpointTime      = nextFrameBase + frameDelta * 0.5;
  15.409 +    TimewarpPointTime = (inputs.TimewarpWaitDelta == 0.0) ?
  15.410 +                        0.0 : (NextFrameTime + inputs.TimewarpWaitDelta);
  15.411 +
  15.412 +    // Calculate absolute points in time when eye rendering or corresponding time-warp
  15.413 +    // screen edges will become visible.
  15.414 +    // This only matters with VSync.
  15.415 +    switch(shutterType)
  15.416 +    {            
  15.417 +    case HmdShutter_RollingTopToBottom:
  15.418 +        EyeRenderTimes[0]               = MidpointTime;
  15.419 +        EyeRenderTimes[1]               = MidpointTime;
  15.420 +        TimeWarpStartEndTimes[0][0]     = nextFrameBase;
  15.421 +        TimeWarpStartEndTimes[0][1]     = nextFrameBase + frameDelta;
  15.422 +        TimeWarpStartEndTimes[1][0]     = nextFrameBase;
  15.423 +        TimeWarpStartEndTimes[1][1]     = nextFrameBase + frameDelta;
  15.424 +        break;
  15.425 +    case HmdShutter_RollingLeftToRight:
  15.426 +        EyeRenderTimes[0]               = nextFrameBase + frameDelta * 0.25;
  15.427 +        EyeRenderTimes[1]               = nextFrameBase + frameDelta * 0.75;
  15.428 +
  15.429 +        /*
  15.430 +        // TBD: MA: It is probably better if mesh sets it up per-eye.
  15.431 +        // Would apply if screen is 0 -> 1 for each eye mesh
  15.432 +        TimeWarpStartEndTimes[0][0]     = nextFrameBase;
  15.433 +        TimeWarpStartEndTimes[0][1]     = MidpointTime;
  15.434 +        TimeWarpStartEndTimes[1][0]     = MidpointTime;
  15.435 +        TimeWarpStartEndTimes[1][1]     = nextFrameBase + frameDelta;
  15.436 +        */
  15.437 +
  15.438 +        // Mesh is set up to vary from Edge of scree 0 -> 1 across both eyes
  15.439 +        TimeWarpStartEndTimes[0][0]     = nextFrameBase;
  15.440 +        TimeWarpStartEndTimes[0][1]     = nextFrameBase + frameDelta;
  15.441 +        TimeWarpStartEndTimes[1][0]     = nextFrameBase;
  15.442 +        TimeWarpStartEndTimes[1][1]     = nextFrameBase + frameDelta;
  15.443 +
  15.444 +        break;
  15.445 +    case HmdShutter_RollingRightToLeft:
  15.446 +
  15.447 +        EyeRenderTimes[0]               = nextFrameBase + frameDelta * 0.75;
  15.448 +        EyeRenderTimes[1]               = nextFrameBase + frameDelta * 0.25;
  15.449 +        
  15.450 +        // This is *Correct* with Tom's distortion mesh organization.
  15.451 +        TimeWarpStartEndTimes[0][0]     = nextFrameBase ;
  15.452 +        TimeWarpStartEndTimes[0][1]     = nextFrameBase + frameDelta;
  15.453 +        TimeWarpStartEndTimes[1][0]     = nextFrameBase ;
  15.454 +        TimeWarpStartEndTimes[1][1]     = nextFrameBase + frameDelta;
  15.455 +        break;
  15.456 +    case HmdShutter_Global:
  15.457 +        // TBD
  15.458 +        EyeRenderTimes[0]               = MidpointTime;
  15.459 +        EyeRenderTimes[1]               = MidpointTime;
  15.460 +        TimeWarpStartEndTimes[0][0]     = MidpointTime;
  15.461 +        TimeWarpStartEndTimes[0][1]     = MidpointTime;
  15.462 +        TimeWarpStartEndTimes[1][0]     = MidpointTime;
  15.463 +        TimeWarpStartEndTimes[1][1]     = MidpointTime;
  15.464 +        break;
  15.465 +    default:
  15.466 +        break;
  15.467 +    }
  15.468 +}
  15.469 +
  15.470 +  
  15.471 +double FrameTimeManager::BeginFrame(unsigned frameIndex)
  15.472 +{    
  15.473 +    RenderIMUTimeSeconds = 0.0;
  15.474 +    TimewarpIMUTimeSeconds = 0.0;
  15.475 +
  15.476 +    // TPH - putting an assert so this doesn't remain a hidden problem.
  15.477 +    OVR_ASSERT(FrameTiming.Inputs.ScreenDelay != 0);
  15.478 +
  15.479 +    // ThisFrameTime comes from the end of last frame, unless it it changed.
  15.480 +    double thisFrameTime = (FrameTiming.NextFrameTime != 0.0) ?
  15.481 +                           FrameTiming.NextFrameTime : ovr_GetTimeInSeconds();
  15.482 +    
  15.483 +    // We are starting to process a new frame...
  15.484 +    FrameTiming.InitTimingFromInputs(FrameTiming.Inputs, RenderInfo.Shutter.Type,
  15.485 +                                     thisFrameTime, frameIndex);
  15.486 +
  15.487 +    return FrameTiming.ThisFrameTime;
  15.488 +}
  15.489 +
  15.490 +
  15.491 +void FrameTimeManager::EndFrame()
  15.492 +{
  15.493 +    // Record timing since last frame; must be called after Present & sync.
  15.494 +    FrameTiming.NextFrameTime = ovr_GetTimeInSeconds();    
  15.495 +    if (FrameTiming.ThisFrameTime > 0.0)
  15.496 +    {
  15.497 +    //Revisit dynamic pre-Timewarp delay adjustment logic
  15.498 +    /*
  15.499 +        double actualFrameDelta = FrameTiming.NextFrameTime - FrameTiming.ThisFrameTime;
  15.500 +
  15.501 +        if (VsyncEnabled)
  15.502 +            TimewarpAdjuster.UpdateTimewarpWaitIfSkippedFrames(this, actualFrameDelta,
  15.503 +                                                               FrameTiming.NextFrameTime);
  15.504 +
  15.505 +        FrameTimeDeltas.AddTimeDelta(actualFrameDelta);
  15.506 +    */
  15.507 +        FrameTimeDeltas.AddTimeDelta(FrameTiming.NextFrameTime - FrameTiming.ThisFrameTime);
  15.508 +        FrameTiming.Inputs.FrameDelta = calcFrameDelta();
  15.509 +    }
  15.510 +
  15.511 +    // Write to Lock-less
  15.512 +    LocklessTiming.SetState(FrameTiming);
  15.513 +}
  15.514 +
  15.515 +// Thread-safe function to query timing for a future frame
  15.516 +
  15.517 +FrameTimeManager::Timing FrameTimeManager::GetFrameTiming(unsigned frameIndex)
  15.518 +{
  15.519 +    Timing frameTiming = LocklessTiming.GetState();
  15.520 +
  15.521 +    if (frameTiming.ThisFrameTime == 0.0)
  15.522 +    {
  15.523 +        // If timing hasn't been initialized, starting based on "now" is the best guess.
  15.524 +        frameTiming.InitTimingFromInputs(frameTiming.Inputs, RenderInfo.Shutter.Type,
  15.525 +                                         ovr_GetTimeInSeconds(), frameIndex);
  15.526 +    }
  15.527 +    
  15.528 +    else if (frameIndex > frameTiming.FrameIndex)
  15.529 +    {
  15.530 +        unsigned frameDelta    = frameIndex - frameTiming.FrameIndex;
  15.531 +        double   thisFrameTime = frameTiming.NextFrameTime +
  15.532 +                                 double(frameDelta-1) * frameTiming.Inputs.FrameDelta;
  15.533 +        // Don't run away too far into the future beyond rendering.
  15.534 +		OVR_DEBUG_LOG_COND(frameDelta >= 6, ("GetFrameTiming is 6 or more frames in future beyond rendering!"));
  15.535 +
  15.536 +        frameTiming.InitTimingFromInputs(frameTiming.Inputs, RenderInfo.Shutter.Type,
  15.537 +                                         thisFrameTime, frameIndex);
  15.538 +    }
  15.539 +
  15.540 +    return frameTiming;
  15.541 +}
  15.542 +
  15.543 +
  15.544 +double FrameTimeManager::GetEyePredictionTime(ovrEyeType eye, unsigned int frameIndex)
  15.545 +{
  15.546 +    if (VsyncEnabled)
  15.547 +    {
  15.548 +        FrameTimeManager::Timing frameTiming = GetFrameTiming(frameIndex);
  15.549 +
  15.550 +        // Special case: ovrEye_Count predicts to midpoint
  15.551 +        return (eye == ovrEye_Count) ? frameTiming.MidpointTime : frameTiming.EyeRenderTimes[eye];
  15.552 +    }
  15.553 +
  15.554 +    // No VSync: Best guess for the near future
  15.555 +    return ovr_GetTimeInSeconds() + ScreenSwitchingDelay + NoVSyncToScanoutDelay;
  15.556 +}
  15.557 +
  15.558 +ovrTrackingState FrameTimeManager::GetEyePredictionTracking(ovrHmd hmd, ovrEyeType eye, unsigned int frameIndex)
  15.559 +{
  15.560 +    double           eyeRenderTime = GetEyePredictionTime(eye, frameIndex);
  15.561 +    ovrTrackingState eyeState      = ovrHmd_GetTrackingState(hmd, eyeRenderTime);
  15.562 +        
  15.563 +    // Record view pose sampling time for Latency reporting.
  15.564 +    if (RenderIMUTimeSeconds == 0.0)
  15.565 +    {
  15.566 +        // TODO: Figure out why this are not as accurate as ovr_GetTimeInSeconds()
  15.567 +        //RenderIMUTimeSeconds = eyeState.RawSensorData.TimeInSeconds;
  15.568 +        RenderIMUTimeSeconds = ovr_GetTimeInSeconds();
  15.569 +    }
  15.570 +
  15.571 +    return eyeState;
  15.572 +}
  15.573 +
  15.574 +Posef FrameTimeManager::GetEyePredictionPose(ovrHmd hmd, ovrEyeType eye)
  15.575 +{
  15.576 +    double           eyeRenderTime = GetEyePredictionTime(eye, 0);
  15.577 +    ovrTrackingState eyeState      = ovrHmd_GetTrackingState(hmd, eyeRenderTime);
  15.578 +
  15.579 +    // Record view pose sampling time for Latency reporting.
  15.580 +    if (RenderIMUTimeSeconds == 0.0)
  15.581 +    {
  15.582 +        // TODO: Figure out why this are not as accurate as ovr_GetTimeInSeconds()
  15.583 +        //RenderIMUTimeSeconds = eyeState.RawSensorData.TimeInSeconds;
  15.584 +        RenderIMUTimeSeconds = ovr_GetTimeInSeconds();
  15.585 +    }
  15.586 +
  15.587 +    return eyeState.HeadPose.ThePose;
  15.588 +}
  15.589 +
  15.590 +void FrameTimeManager::GetTimewarpPredictions(ovrEyeType eye, double timewarpStartEnd[2])
  15.591 +{
  15.592 +    if (VsyncEnabled)
  15.593 +    {
  15.594 +        timewarpStartEnd[0] = FrameTiming.TimeWarpStartEndTimes[eye][0];
  15.595 +        timewarpStartEnd[1] = FrameTiming.TimeWarpStartEndTimes[eye][1];
  15.596 +        return;
  15.597 +    }    
  15.598 +
  15.599 +    // Free-running, so this will be displayed immediately.
  15.600 +    // Unfortunately we have no idea which bit of the screen is actually going to be displayed.
  15.601 +    // TODO: guess which bit of the screen is being displayed!
  15.602 +    // (e.g. use DONOTWAIT on present and see when the return isn't WASSTILLWAITING?)
  15.603 +
  15.604 +    // We have no idea where scan-out is currently, so we can't usefully warp the screen spatially.
  15.605 +    timewarpStartEnd[0] = ovr_GetTimeInSeconds() + ScreenSwitchingDelay + NoVSyncToScanoutDelay;
  15.606 +    timewarpStartEnd[1] = timewarpStartEnd[0];
  15.607 +}
  15.608 +
  15.609 +
  15.610 +void FrameTimeManager::GetTimewarpMatrices(ovrHmd hmd, ovrEyeType eyeId,
  15.611 +                                           ovrPosef renderPose, ovrMatrix4f twmOut[2],
  15.612 +										   double debugTimingOffsetInSeconds)
  15.613 +{
  15.614 +    if (!hmd)
  15.615 +    {
  15.616 +        return;
  15.617 +    }
  15.618 +
  15.619 +    double timewarpStartEnd[2] = { 0.0, 0.0 };    
  15.620 +    GetTimewarpPredictions(eyeId, timewarpStartEnd);
  15.621 +
  15.622 +	//TPH, to vary timing, to allow developers to debug, to shunt the predicted time forward 
  15.623 +	//and back, and see if the SDK is truly delivering the correct time.  Also to allow
  15.624 +	//illustration of the detrimental effects when this is not done right. 
  15.625 +	timewarpStartEnd[0] += debugTimingOffsetInSeconds;
  15.626 +	timewarpStartEnd[1] += debugTimingOffsetInSeconds;
  15.627 +
  15.628 +      
  15.629 +    //HMDState* p = (HMDState*)hmd;
  15.630 +    ovrTrackingState startState = ovrHmd_GetTrackingState(hmd, timewarpStartEnd[0]);
  15.631 +    ovrTrackingState endState   = ovrHmd_GetTrackingState(hmd, timewarpStartEnd[1]);
  15.632 +
  15.633 +    if (TimewarpIMUTimeSeconds == 0.0)
  15.634 +    {
  15.635 +        // TODO: Figure out why this are not as accurate as ovr_GetTimeInSeconds()
  15.636 +        //TimewarpIMUTimeSeconds = startState.RawSensorData.TimeInSeconds;
  15.637 +        TimewarpIMUTimeSeconds = ovr_GetTimeInSeconds();
  15.638 +    }
  15.639 +
  15.640 +    Quatf quatFromStart = startState.HeadPose.ThePose.Orientation;
  15.641 +    Quatf quatFromEnd   = endState.HeadPose.ThePose.Orientation;
  15.642 +    Quatf quatFromEye   = renderPose.Orientation; //EyeRenderPoses[eyeId].Orientation;
  15.643 +    quatFromEye.Invert();   // because we need the view matrix, not the camera matrix
  15.644 +    
  15.645 +    Quatf timewarpStartQuat = quatFromEye * quatFromStart;
  15.646 +    Quatf timewarpEndQuat   = quatFromEye * quatFromEnd;
  15.647 +
  15.648 +    Matrix4f timewarpStart(timewarpStartQuat);
  15.649 +    Matrix4f timewarpEnd(timewarpEndQuat);
  15.650 +    
  15.651 +
  15.652 +    // The real-world orientations have:                                  X=right, Y=up,   Z=backwards.
  15.653 +    // The vectors inside the mesh are in NDC to keep the shader simple: X=right, Y=down, Z=forwards.
  15.654 +    // So we need to perform a similarity transform on this delta matrix.
  15.655 +    // The verbose code would look like this:
  15.656 +    /*
  15.657 +    Matrix4f matBasisChange;
  15.658 +    matBasisChange.SetIdentity();
  15.659 +    matBasisChange.M[0][0] =  1.0f;
  15.660 +    matBasisChange.M[1][1] = -1.0f;
  15.661 +    matBasisChange.M[2][2] = -1.0f;
  15.662 +    Matrix4f matBasisChangeInv = matBasisChange.Inverted();
  15.663 +    matRenderFromNow = matBasisChangeInv * matRenderFromNow * matBasisChange;
  15.664 +    */
  15.665 +    // ...but of course all the above is a constant transform and much more easily done.
  15.666 +    // We flip the signs of the Y&Z row, then flip the signs of the Y&Z column,
  15.667 +    // and of course most of the flips cancel:
  15.668 +    // +++                        +--                     +--
  15.669 +    // +++ -> flip Y&Z columns -> +-- -> flip Y&Z rows -> -++
  15.670 +    // +++                        +--                     -++
  15.671 +    timewarpStart.M[0][1] = -timewarpStart.M[0][1];
  15.672 +    timewarpStart.M[0][2] = -timewarpStart.M[0][2];
  15.673 +    timewarpStart.M[1][0] = -timewarpStart.M[1][0];
  15.674 +    timewarpStart.M[2][0] = -timewarpStart.M[2][0];
  15.675 +
  15.676 +    timewarpEnd  .M[0][1] = -timewarpEnd  .M[0][1];
  15.677 +    timewarpEnd  .M[0][2] = -timewarpEnd  .M[0][2];
  15.678 +    timewarpEnd  .M[1][0] = -timewarpEnd  .M[1][0];
  15.679 +    timewarpEnd  .M[2][0] = -timewarpEnd  .M[2][0];
  15.680 +
  15.681 +    twmOut[0] = timewarpStart;
  15.682 +    twmOut[1] = timewarpEnd;
  15.683 +}
  15.684 +
  15.685 +
  15.686 +// Used by renderer to determine if it should time distortion rendering.
  15.687 +bool  FrameTimeManager::NeedDistortionTimeMeasurement() const
  15.688 +{
  15.689 +    if (!VsyncEnabled)
  15.690 +        return false;
  15.691 +    return DistortionRenderTimes.GetCount() < DistortionRenderTimes.Capacity;
  15.692 +}
  15.693 +
  15.694 +
  15.695 +void  FrameTimeManager::AddDistortionTimeMeasurement(double distortionTimeSeconds)
  15.696 +{
  15.697 +    DistortionRenderTimes.AddTimeDelta(distortionTimeSeconds);
  15.698 +
  15.699 +    //Revisit dynamic pre-Timewarp delay adjustment logic
  15.700 +    //updateTimewarpTiming();
  15.701 +
  15.702 +    // If timewarp timing changes based on this sample, update it.
  15.703 +    double newTimewarpWaitDelta = calcTimewarpWaitDelta();
  15.704 +    if (newTimewarpWaitDelta != FrameTiming.Inputs.TimewarpWaitDelta)
  15.705 +    {
  15.706 +        FrameTiming.Inputs.TimewarpWaitDelta = newTimewarpWaitDelta;
  15.707 +        LocklessTiming.SetState(FrameTiming);
  15.708 +    }
  15.709 +}
  15.710 +
  15.711 +
  15.712 +void FrameTimeManager::UpdateFrameLatencyTrackingAfterEndFrame(
  15.713 +                                    unsigned char frameLatencyTestColor[3],
  15.714 +                                    const Util::FrameTimeRecordSet& rs)
  15.715 +{    
  15.716 +    // FrameTiming.NextFrameTime in this context (after EndFrame) is the end frame time.
  15.717 +    ScreenLatencyTracker.SaveDrawColor(frameLatencyTestColor[0],
  15.718 +                                       FrameTiming.NextFrameTime,
  15.719 +                                       RenderIMUTimeSeconds,
  15.720 +                                       TimewarpIMUTimeSeconds);
  15.721 +
  15.722 +    ScreenLatencyTracker.MatchRecord(rs);
  15.723 +
  15.724 +    // If screen delay changed, update timing.
  15.725 +    double newScreenDelay = calcScreenDelay();
  15.726 +    if (newScreenDelay != FrameTiming.Inputs.ScreenDelay)
  15.727 +    {
  15.728 +        FrameTiming.Inputs.ScreenDelay = newScreenDelay;
  15.729 +        LocklessTiming.SetState(FrameTiming);
  15.730 +    }
  15.731 +}
  15.732 +
  15.733 +
  15.734 +//-----------------------------------------------------------------------------------
  15.735 +//Revisit dynamic pre-Timewarp delay adjustment logic
  15.736 +/*
  15.737 +void FrameTimeManager::TimewarpDelayAdjuster::Reset()    
  15.738 +{
  15.739 +    State                           = State_WaitingToReduceLevel;
  15.740 +    DelayLevel                      = 0;
  15.741 +    InitialFrameCounter             = 0;
  15.742 +    TimewarpDelayReductionSeconds   = 0.0;
  15.743 +    DelayLevelFinishTime            = 0.0;
  15.744 +
  15.745 +    memset(WaitTimeIndexForLevel, 0, sizeof(WaitTimeIndexForLevel));
  15.746 +    // If we are at level 0, waits are infinite.
  15.747 +    WaitTimeIndexForLevel[0] = MaxTimeIndex;
  15.748 +}
  15.749 +
  15.750 +
  15.751 +void FrameTimeManager::TimewarpDelayAdjuster::
  15.752 +        UpdateTimewarpWaitIfSkippedFrames(FrameTimeManager* manager,
  15.753 +                                          double measuredFrameDelta, double nextFrameTime)
  15.754 +{    
  15.755 +    // Times in seconds
  15.756 +    const static double delayTimingTiers[7] = { 1.0, 5.0, 15.0, 30.0, 60.0, 120.0, 1000000.0 };
  15.757 +
  15.758 +    const double currentFrameDelta = manager->FrameTiming.Inputs.FrameDelta;
  15.759 +
  15.760 +
  15.761 +    // Once we detected frame spike, we skip several frames before testing again.    
  15.762 +    if (InitialFrameCounter > 0)
  15.763 +    {
  15.764 +        InitialFrameCounter --;
  15.765 +        return;
  15.766 +    }
  15.767 +
  15.768 +    // Skipped frame would usually take 2x longer then regular frame
  15.769 +    if (measuredFrameDelta > currentFrameDelta * 1.8)
  15.770 +    {        
  15.771 +        if (State == State_WaitingToReduceLevel)
  15.772 +        {
  15.773 +            // If we got here, escalate the level again. 
  15.774 +            if (DelayLevel < MaxDelayLevel)
  15.775 +            {
  15.776 +                DelayLevel++;
  15.777 +                InitialFrameCounter = 3;
  15.778 +            }
  15.779 +        }
  15.780 +
  15.781 +        else if (State == State_VerifyingAfterReduce)
  15.782 +        {
  15.783 +            // So we went down to this level and tried to wait to see if there was
  15.784 +            // as skipped frame and there is -> go back up a level and incrment its timing tier
  15.785 +            if (DelayLevel < MaxDelayLevel)
  15.786 +            {
  15.787 +                DelayLevel++;
  15.788 +                State = State_WaitingToReduceLevel;
  15.789 +                
  15.790 +                // For higher level delays reductions, i.e. more then half a frame,
  15.791 +                // we don't go into the infinite wait tier.
  15.792 +                int maxTimingTier = MaxTimeIndex;
  15.793 +                if (DelayLevel > MaxInfiniteTimingLevel)
  15.794 +                    maxTimingTier--;
  15.795 +
  15.796 +                if (WaitTimeIndexForLevel[DelayLevel] < maxTimingTier )
  15.797 +                    WaitTimeIndexForLevel[DelayLevel]++;
  15.798 +            }
  15.799 +        }
  15.800 +
  15.801 +        DelayLevelFinishTime          = nextFrameTime +
  15.802 +                                        delayTimingTiers[WaitTimeIndexForLevel[DelayLevel]];
  15.803 +        TimewarpDelayReductionSeconds = currentFrameDelta * 0.125 * DelayLevel;
  15.804 +        manager->updateTimewarpTiming();
  15.805 +
  15.806 +    }
  15.807 +
  15.808 +    else if (nextFrameTime > DelayLevelFinishTime)
  15.809 +    {        
  15.810 +        if (State == State_WaitingToReduceLevel)
  15.811 +        {
  15.812 +            if (DelayLevel > 0)
  15.813 +            {
  15.814 +                DelayLevel--;
  15.815 +                State = State_VerifyingAfterReduce;
  15.816 +                // Always use 1 sec to see if "down sampling mode" caused problems
  15.817 +                DelayLevelFinishTime = nextFrameTime + 1.0f; 
  15.818 +            }
  15.819 +        }
  15.820 +        else if (State == State_VerifyingAfterReduce)
  15.821 +        {
  15.822 +            // Prior display level successfully reduced,
  15.823 +            // try to see we we could go down further after wait.
  15.824 +            WaitTimeIndexForLevel[DelayLevel+1] = 0;            
  15.825 +            State                               = State_WaitingToReduceLevel;
  15.826 +            DelayLevelFinishTime                = nextFrameTime +
  15.827 +                                                  delayTimingTiers[WaitTimeIndexForLevel[DelayLevel]];
  15.828 +        }
  15.829 +
  15.830 +        // TBD: Update TimeWarpTiming
  15.831 +        TimewarpDelayReductionSeconds = currentFrameDelta * 0.125 * DelayLevel;
  15.832 +        manager->updateTimewarpTiming();
  15.833 +    }
  15.834 +
  15.835 +
  15.836 +    //static int oldDelayLevel = 0;
  15.837 +
  15.838 +    //if (oldDelayLevel != DelayLevel)
  15.839 +    //{
  15.840 +        //OVR_DEBUG_LOG(("DelayLevel:%d tReduction = %0.5f ", DelayLevel, TimewarpDelayReductionSeconds));
  15.841 +        //oldDelayLevel = DelayLevel;
  15.842 +    //}
  15.843 +    }
  15.844 +    */
  15.845 +
  15.846 +//-----------------------------------------------------------------------------------
  15.847 +// ***** TimeDeltaCollector
  15.848 +
  15.849 +void TimeDeltaCollector::AddTimeDelta(double timeSeconds)
  15.850 +{
  15.851 +    // avoid adding invalid timing values
  15.852 +    if(timeSeconds < 0.0f)
  15.853 +        return;
  15.854 +
  15.855 +    if (Count == Capacity)
  15.856 +    {
  15.857 +        for(int i=0; i< Count-1; i++)
  15.858 +            TimeBufferSeconds[i] = TimeBufferSeconds[i+1];
  15.859 +        Count--;
  15.860 +    }
  15.861 +    TimeBufferSeconds[Count++] = timeSeconds;
  15.862 +
  15.863 +    ReCalcMedian = true;
  15.864 +}
  15.865 +
  15.866 +// KevinJ: Better median function
  15.867 +double CalculateListMedianRecursive(const double inputList[TimeDeltaCollector::Capacity], int inputListLength, int lessThanSum, int greaterThanSum)
  15.868 +{
  15.869 +    double lessThanMedian[TimeDeltaCollector::Capacity], greaterThanMedian[TimeDeltaCollector::Capacity];
  15.870 +    int lessThanMedianListLength = 0, greaterThanMedianListLength = 0;
  15.871 +    double median = inputList[0];
  15.872 +    int i;
  15.873 +    for (i = 1; i < inputListLength; i++)
  15.874 +    {
  15.875 +        // If same value, spread among lists evenly
  15.876 +        if (inputList[i] < median || ((i & 1) == 0 && inputList[i] == median))
  15.877 +            lessThanMedian[lessThanMedianListLength++] = inputList[i];
  15.878 +        else
  15.879 +            greaterThanMedian[greaterThanMedianListLength++] = inputList[i];
  15.880 +    }
  15.881 +    if (lessThanMedianListLength + lessThanSum == greaterThanMedianListLength + greaterThanSum + 1 ||
  15.882 +        lessThanMedianListLength + lessThanSum == greaterThanMedianListLength + greaterThanSum - 1)
  15.883 +        return median;
  15.884 +
  15.885 +    if (lessThanMedianListLength + lessThanSum < greaterThanMedianListLength + greaterThanSum)
  15.886 +    {
  15.887 +        lessThanMedian[lessThanMedianListLength++] = median;
  15.888 +        return CalculateListMedianRecursive(greaterThanMedian, greaterThanMedianListLength, lessThanMedianListLength + lessThanSum, greaterThanSum);
  15.889 +    }
  15.890 +    else
  15.891 +    {
  15.892 +        greaterThanMedian[greaterThanMedianListLength++] = median;
  15.893 +        return CalculateListMedianRecursive(lessThanMedian, lessThanMedianListLength, lessThanSum, greaterThanMedianListLength + greaterThanSum);
  15.894 +    }
  15.895 +}
  15.896 +// KevinJ: Excludes Firmware hack
  15.897 +double TimeDeltaCollector::GetMedianTimeDeltaNoFirmwareHack() const
  15.898 +{
  15.899 +    if (ReCalcMedian)
  15.900 +    {
  15.901 +        ReCalcMedian = false;
  15.902 +        Median = CalculateListMedianRecursive(TimeBufferSeconds, Count, 0, 0);
  15.903 +    }
  15.904 +    return Median;
  15.905 +}
  15.906 +double TimeDeltaCollector::GetMedianTimeDelta() const
  15.907 +{
  15.908 +    if(ReCalcMedian)
  15.909 +    {
  15.910 +        double  SortedList[Capacity];
  15.911 +        bool    used[Capacity];
  15.912 +
  15.913 +        memset(used, 0, sizeof(used));
  15.914 +        SortedList[0] = 0.0; // In case Count was 0...
  15.915 +
  15.916 +        // Probably the slowest way to find median...
  15.917 +        for (int i=0; i<Count; i++)
  15.918 +        {
  15.919 +            double smallestDelta = 1000000.0;
  15.920 +            int    index = 0;
  15.921 +
  15.922 +            for (int j = 0; j < Count; j++)
  15.923 +            {
  15.924 +                if (!used[j])
  15.925 +                {                
  15.926 +                    if (TimeBufferSeconds[j] < smallestDelta)
  15.927 +                    {
  15.928 +                        smallestDelta = TimeBufferSeconds[j];
  15.929 +                        index = j;
  15.930 +                    }
  15.931 +                }
  15.932 +            }
  15.933 +
  15.934 +            // Mark as used
  15.935 +            used[index]   = true;
  15.936 +            SortedList[i] = smallestDelta;
  15.937 +        }
  15.938 +
  15.939 +        // FIRMWARE HACK: Don't take the actual median, but err on the low time side
  15.940 +        Median = SortedList[Count/4];
  15.941 +        ReCalcMedian = false;
  15.942 +    }
  15.943 +
  15.944 +    return Median;
  15.945 +}
  15.946 +      
  15.947 +
  15.948 +}} // namespace OVR::CAPI
  15.949 +
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/LibOVR/Src/CAPI/CAPI_FrameTimeManager.h	Wed Jan 14 06:51:16 2015 +0200
    16.3 @@ -0,0 +1,327 @@
    16.4 +/************************************************************************************
    16.5 +
    16.6 +Filename    :   CAPI_FrameTimeManager.h
    16.7 +Content     :   Manage frame timing and pose prediction for rendering
    16.8 +Created     :   November 30, 2013
    16.9 +Authors     :   Volga Aksoy, Michael Antonov
   16.10 +
   16.11 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   16.12 +
   16.13 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
   16.14 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
   16.15 +which is provided at the time of installation or download, or which 
   16.16 +otherwise accompanies this software in either electronic or hard copy form.
   16.17 +
   16.18 +You may obtain a copy of the License at
   16.19 +
   16.20 +http://www.oculusvr.com/licenses/LICENSE-3.2 
   16.21 +
   16.22 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
   16.23 +distributed under the License is distributed on an "AS IS" BASIS,
   16.24 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   16.25 +See the License for the specific language governing permissions and
   16.26 +limitations under the License.
   16.27 +
   16.28 +************************************************************************************/
   16.29 +
   16.30 +#ifndef OVR_CAPI_FrameTimeManager_h
   16.31 +#define OVR_CAPI_FrameTimeManager_h
   16.32 +
   16.33 +#include "../OVR_CAPI.h"
   16.34 +#include "../Kernel/OVR_Timer.h"
   16.35 +#include "../Kernel/OVR_Math.h"
   16.36 +#include "../Util/Util_Render_Stereo.h"
   16.37 +
   16.38 +namespace OVR { namespace CAPI {
   16.39 +
   16.40 +
   16.41 +//-------------------------------------------------------------------------------------
   16.42 +// ***** TimeDeltaCollector
   16.43 +
   16.44 +// Helper class to collect median times between frames, so that we know
   16.45 +// how long to wait. 
   16.46 +struct TimeDeltaCollector
   16.47 +{
   16.48 +    TimeDeltaCollector() : Median(-1.0), Count(0), ReCalcMedian(true) { }
   16.49 +
   16.50 +    void    AddTimeDelta(double timeSeconds);
   16.51 +    void    Clear() { Count = 0; }
   16.52 +
   16.53 +    double  GetMedianTimeDelta() const;
   16.54 +    double  GetMedianTimeDeltaNoFirmwareHack() const;
   16.55 +
   16.56 +    double  GetCount() const { return Count; }
   16.57 +
   16.58 +    enum { Capacity = 12 };
   16.59 +private:
   16.60 +    double  TimeBufferSeconds[Capacity];
   16.61 +    mutable double  Median;
   16.62 +    int     Count;
   16.63 +    mutable bool    ReCalcMedian;
   16.64 +};
   16.65 +
   16.66 +
   16.67 +//-------------------------------------------------------------------------------------
   16.68 +// ***** FrameLatencyTracker
   16.69 +
   16.70 +// FrameLatencyTracker tracks frame Present to display Scan-out timing, as reported by
   16.71 +// the DK2 internal latency tester pixel read-back. The computed value is used in
   16.72 +// FrameTimeManager for prediction. View Render and TimeWarp to scan-out latencies are
   16.73 +// also reported for debugging.
   16.74 +//
   16.75 +// The class operates by generating color values from GetNextDrawColor() that must
   16.76 +// be rendered on the back end and then looking for matching values in FrameTimeRecordSet
   16.77 +// structure as reported by HW.
   16.78 +
   16.79 +class FrameLatencyTracker
   16.80 +{
   16.81 +public:
   16.82 +
   16.83 +    enum { FramesTracked = Util::LT2_IncrementCount-1 };
   16.84 +
   16.85 +    FrameLatencyTracker();
   16.86 +
   16.87 +    // DrawColor == 0 is special in that it doesn't need saving of timestamp
   16.88 +    unsigned char GetNextDrawColor();
   16.89 +
   16.90 +    void SaveDrawColor(unsigned char drawColor, double endFrameTime,
   16.91 +                       double renderIMUTime, double timewarpIMUTime );
   16.92 +
   16.93 +    void MatchRecord(const Util::FrameTimeRecordSet &r);   
   16.94 +
   16.95 +    bool IsLatencyTimingAvailable();
   16.96 +    void GetLatencyTimings(float& latencyRender, float& latencyTimewarp, float& latencyPostPresent);
   16.97 +
   16.98 +    void Reset();
   16.99 +
  16.100 +public:
  16.101 +
  16.102 +    struct FrameTimeRecordEx : public Util::FrameTimeRecord
  16.103 +    {
  16.104 +        bool    MatchedRecord;
  16.105 +        double  RenderIMUTimeSeconds;
  16.106 +        double  TimewarpIMUTimeSeconds;
  16.107 +    };
  16.108 +
  16.109 +    // True if rendering read-back is enabled.
  16.110 +    bool                  TrackerEnabled;
  16.111 +
  16.112 +    enum SampleWaitType {
  16.113 +        SampleWait_Zeroes, // We are waiting for a record with all zeros.
  16.114 +        SampleWait_Match   // We are issuing & matching colors.
  16.115 +    };
  16.116 +    
  16.117 +    SampleWaitType        WaitMode;
  16.118 +    int                   MatchCount;
  16.119 +    // Records of frame timings that we are trying to measure.
  16.120 +    FrameTimeRecordEx     FrameEndTimes[FramesTracked];
  16.121 +    int                   FrameIndex;
  16.122 +    // Median filter for (ScanoutTimeSeconds - PostPresent frame time)
  16.123 +    TimeDeltaCollector    FrameDeltas;
  16.124 +    // Latency reporting results
  16.125 +    double                RenderLatencySeconds;
  16.126 +    double                TimewarpLatencySeconds;
  16.127 +    double                LatencyRecordTime;
  16.128 +};
  16.129 +
  16.130 +
  16.131 +
  16.132 +//-------------------------------------------------------------------------------------
  16.133 +// ***** FrameTimeManager
  16.134 +
  16.135 +// FrameTimeManager keeps track of rendered frame timing and handles predictions for
  16.136 +// orientations and time-warp.
  16.137 +
  16.138 +class FrameTimeManager
  16.139 +{
  16.140 +public:
  16.141 +    FrameTimeManager(bool vsyncEnabled);
  16.142 +
  16.143 +    // Data that affects frame timing computation.
  16.144 +    struct TimingInputs
  16.145 +    {
  16.146 +        // Hard-coded value or dynamic as reported by FrameTimeDeltas.GetMedianTimeDelta().
  16.147 +        double              FrameDelta;
  16.148 +        // Screen delay from present to scan-out, as potentially reported by ScreenLatencyTracker.
  16.149 +        double              ScreenDelay;
  16.150 +        // Negative value of how many seconds before EndFrame we start timewarp. 0.0 if not used.
  16.151 +        double              TimewarpWaitDelta;
  16.152 +        
  16.153 +        TimingInputs()
  16.154 +            : FrameDelta(0), ScreenDelay(0), TimewarpWaitDelta(0)
  16.155 +        { }
  16.156 +    };
  16.157 +
  16.158 +    // Timing values for a specific frame.
  16.159 +    struct Timing
  16.160 +    {
  16.161 +        TimingInputs        Inputs;
  16.162 +        
  16.163 +        // Index of a frame that started at ThisFrameTime.
  16.164 +        unsigned int        FrameIndex;
  16.165 +        // Predicted absolute times for when this frame will show up on screen.
  16.166 +        // Generally, all values will be >= NextFrameTime, since that's the time we expect next
  16.167 +        // vsync to succeed.
  16.168 +        double              ThisFrameTime;
  16.169 +        double              TimewarpPointTime;
  16.170 +        double              NextFrameTime;        
  16.171 +        double              MidpointTime;
  16.172 +        double              EyeRenderTimes[2];
  16.173 +        double              TimeWarpStartEndTimes[2][2];
  16.174 +
  16.175 +        Timing()
  16.176 +        {
  16.177 +            memset(this, 0, sizeof(Timing));
  16.178 +        }
  16.179 +
  16.180 +        void InitTimingFromInputs(const TimingInputs& inputs, HmdShutterTypeEnum shutterType,
  16.181 +                                  double thisFrameTime, unsigned int frameIndex);
  16.182 +    };
  16.183 +
  16.184 +   
  16.185 +    // Called on startup to provided data on HMD timing.
  16.186 +    void    Init(HmdRenderInfo& renderInfo);
  16.187 +
  16.188 +    // Called with each new ConfigureRendering.
  16.189 +    void    ResetFrameTiming(unsigned frameIndex,
  16.190 +                             bool dynamicPrediction, bool sdkRender);
  16.191 +
  16.192 +    void    SetVsync(bool enabled) { VsyncEnabled = enabled; }
  16.193 +
  16.194 +    // BeginFrame returns time of the call
  16.195 +    // TBD: Should this be a predicted time value instead ?
  16.196 +    double  BeginFrame(unsigned frameIndex);
  16.197 +    void    EndFrame();    
  16.198 +
  16.199 +    // Thread-safe function to query timing for a future frame
  16.200 +    Timing  GetFrameTiming(unsigned frameIndex);
  16.201 + 
  16.202 +    // if eye == ovrEye_Count, timing is for MidpointTime as opposed to any specific eye
  16.203 +    double           GetEyePredictionTime(ovrEyeType eye, unsigned int frameIndex);
  16.204 +    ovrTrackingState GetEyePredictionTracking(ovrHmd hmd, ovrEyeType eye, unsigned int frameIndex);
  16.205 +    Posef            GetEyePredictionPose(ovrHmd hmd, ovrEyeType eye);
  16.206 +
  16.207 +    void    GetTimewarpPredictions(ovrEyeType eye, double timewarpStartEnd[2]); 
  16.208 +    void    GetTimewarpMatrices(ovrHmd hmd, ovrEyeType eye, ovrPosef renderPose, ovrMatrix4f twmOut[2],double debugTimingOffsetInSeconds = 0.0);
  16.209 +
  16.210 +    // Used by renderer to determine if it should time distortion rendering.
  16.211 +    bool    NeedDistortionTimeMeasurement() const;
  16.212 +    void    AddDistortionTimeMeasurement(double distortionTimeSeconds);
  16.213 +
  16.214 +    
  16.215 +    // DK2 Latency test interface
  16.216 +    
  16.217 +    // Get next draw color for DK2 latency tester (3-byte RGB)
  16.218 +    void GetFrameLatencyTestDrawColor(unsigned char outColor[3])
  16.219 +    {
  16.220 +        outColor[0] = ScreenLatencyTracker.GetNextDrawColor();
  16.221 +        outColor[1] = ScreenLatencyTracker.IsLatencyTimingAvailable() ? 255 : 0;
  16.222 +        outColor[2] = ScreenLatencyTracker.IsLatencyTimingAvailable() ? 0 : 255;
  16.223 +    }
  16.224 +
  16.225 +    // Must be called after EndFrame() to update latency tester timings.
  16.226 +    // Must pass color reported by NextFrameColor for this frame.
  16.227 +    void    UpdateFrameLatencyTrackingAfterEndFrame(unsigned char frameLatencyTestColor[3],
  16.228 +                                                    const Util::FrameTimeRecordSet& rs);
  16.229 +
  16.230 +    void    GetLatencyTimings(float& latencyRender, float& latencyTimewarp, float& latencyPostPresent)
  16.231 +    {
  16.232 +        return ScreenLatencyTracker.GetLatencyTimings(latencyRender, latencyTimewarp, latencyPostPresent);
  16.233 +    }
  16.234 +
  16.235 +    const Timing& GetFrameTiming() const { return FrameTiming; }
  16.236 +
  16.237 +private:
  16.238 +    double  calcFrameDelta() const;
  16.239 +    double  calcScreenDelay() const;
  16.240 +    double  calcTimewarpWaitDelta() const;
  16.241 +
  16.242 +    //Revisit dynamic pre-Timewarp delay adjustment logic
  16.243 +    /*
  16.244 +    void    updateTimewarpTiming();
  16.245 +
  16.246 +
  16.247 +    
  16.248 +    // TimewarpDelayAdjuster implements a simple state machine that reduces the amount
  16.249 +    // of time-warp waiting based on skipped frames. 
  16.250 +    struct TimewarpDelayAdjuster
  16.251 +    {
  16.252 +        enum StateInLevel
  16.253 +        {        
  16.254 +            // We are ok at this level, and will be waiting for some time before trying to reduce.
  16.255 +            State_WaitingToReduceLevel,  
  16.256 +            // After decrementing a level, we are verifying that this won't cause skipped frames.
  16.257 +            State_VerifyingAfterReduce
  16.258 +       };
  16.259 +    
  16.260 +        enum {
  16.261 +            MaxDelayLevel          = 5,
  16.262 +            MaxInfiniteTimingLevel = 3,
  16.263 +            MaxTimeIndex           = 6
  16.264 +        };
  16.265 +
  16.266 +        StateInLevel State;   
  16.267 +        // Current level. Higher levels means larger delay reduction (smaller overall time-warp delay).
  16.268 +        int          DelayLevel;
  16.269 +        // Index for the amount of time we'd wait in this level. If attempt to decrease level fails,
  16.270 +        // with is incrementing causing the level to become "sticky". 
  16.271 +        int          WaitTimeIndexForLevel[MaxTimeIndex + 1];
  16.272 +        // We skip few frames after each escalation to avoid too rapid of a reduction.
  16.273 +        int          InitialFrameCounter;
  16.274 +        // What th currect "reduction" currently is.
  16.275 +        double       TimewarpDelayReductionSeconds;
  16.276 +        // When we should try changing the level again.
  16.277 +        double       DelayLevelFinishTime;
  16.278 +
  16.279 +    public:
  16.280 +        TimewarpDelayAdjuster() { Reset(); }
  16.281 +
  16.282 +        void    Reset();
  16.283 +
  16.284 +        void    UpdateTimewarpWaitIfSkippedFrames(FrameTimeManager* manager,
  16.285 +                                                  double measuredFrameDelta,
  16.286 +                                                  double nextFrameTime);
  16.287 +
  16.288 +        double  GetDelayReduction() const { return TimewarpDelayReductionSeconds; }
  16.289 +    };
  16.290 +    */
  16.291 +
  16.292 +    
  16.293 +    HmdRenderInfo       RenderInfo;
  16.294 +    // Timings are collected through a median filter, to avoid outliers.
  16.295 +    TimeDeltaCollector  FrameTimeDeltas;
  16.296 +    TimeDeltaCollector  DistortionRenderTimes;
  16.297 +    FrameLatencyTracker ScreenLatencyTracker;
  16.298 +
  16.299 +    // Timing changes if we have no Vsync (all prediction is reduced to fixed interval).
  16.300 +    bool                VsyncEnabled;
  16.301 +    // Set if we are rendering via the SDK, so DistortionRenderTimes is valid.
  16.302 +    bool                DynamicPrediction;
  16.303 +    // Set if SDk is doing the rendering.
  16.304 +    bool                SdkRender;
  16.305 +    // Direct to rift.
  16.306 +    bool                DirectToRift;
  16.307 +
  16.308 +    // Total frame delay due to VsyncToFirstScanline, persistence and settle time.
  16.309 +    // Computed from RenderInfor.Shutter.
  16.310 +    double              VSyncToScanoutDelay;
  16.311 +    double              NoVSyncToScanoutDelay;
  16.312 +    double              ScreenSwitchingDelay;
  16.313 +
  16.314 +    //Revisit dynamic pre-Timewarp delay adjustment logic
  16.315 +    //TimewarpDelayAdjuster  TimewarpAdjuster;
  16.316 +
  16.317 +    // Current (or last) frame timing info. Used as a source for LocklessTiming.
  16.318 +    Timing                  FrameTiming;
  16.319 +    // TBD: Don't we need NextFrame here as well?
  16.320 +    LocklessUpdater<Timing, Timing> LocklessTiming;
  16.321 +
  16.322 +    // IMU Read timings
  16.323 +    double              RenderIMUTimeSeconds;
  16.324 +    double              TimewarpIMUTimeSeconds;
  16.325 +};
  16.326 +
  16.327 +
  16.328 +}} // namespace OVR::CAPI
  16.329 +
  16.330 +#endif // OVR_CAPI_FrameTimeManager_h
    17.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.2 +++ b/LibOVR/Src/CAPI/CAPI_HMDRenderState.cpp	Wed Jan 14 06:51:16 2015 +0200
    17.3 @@ -0,0 +1,143 @@
    17.4 +/************************************************************************************
    17.5 +
    17.6 +Filename    :   OVR_CAPI_HMDRenderState.cpp
    17.7 +Content     :   Combines all of the rendering state associated with the HMD
    17.8 +Created     :   February 2, 2014
    17.9 +Authors     :   Michael Antonov
   17.10 +
   17.11 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   17.12 +
   17.13 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
   17.14 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
   17.15 +which is provided at the time of installation or download, or which 
   17.16 +otherwise accompanies this software in either electronic or hard copy form.
   17.17 +
   17.18 +You may obtain a copy of the License at
   17.19 +
   17.20 +http://www.oculusvr.com/licenses/LICENSE-3.2 
   17.21 +
   17.22 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
   17.23 +distributed under the License is distributed on an "AS IS" BASIS,
   17.24 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   17.25 +See the License for the specific language governing permissions and
   17.26 +limitations under the License.
   17.27 +
   17.28 +************************************************************************************/
   17.29 +
   17.30 +#include "CAPI_HMDRenderState.h"
   17.31 +
   17.32 +namespace OVR { namespace CAPI {
   17.33 +
   17.34 +
   17.35 +//-------------------------------------------------------------------------------------
   17.36 +// ***** HMDRenderState
   17.37 +
   17.38 +ovrHmdDesc HMDRenderState::GetDesc() const
   17.39 +{
   17.40 +    ovrHmdDesc d;
   17.41 +    memset(&d, 0, sizeof(d));
   17.42 +    
   17.43 +    d.Type = ovrHmd_Other;
   17.44 +     
   17.45 +    d.ProductName       = OurHMDInfo.ProductName;    
   17.46 +    d.Manufacturer      = OurHMDInfo.Manufacturer;
   17.47 +    d.Resolution.w      = OurHMDInfo.ResolutionInPixels.w;
   17.48 +    d.Resolution.h      = OurHMDInfo.ResolutionInPixels.h;
   17.49 +    d.WindowsPos.x      = OurHMDInfo.DesktopX;
   17.50 +    d.WindowsPos.y      = OurHMDInfo.DesktopY;
   17.51 +    d.DisplayDeviceName = OurHMDInfo.DisplayDeviceName;
   17.52 +    d.DisplayId         = OurHMDInfo.DisplayId;
   17.53 +    d.VendorId          = (short)OurHMDInfo.VendorId;
   17.54 +    d.ProductId         = (short)OurHMDInfo.ProductId;
   17.55 +    d.FirmwareMajor     = (short)OurHMDInfo.FirmwareMajor;
   17.56 +    d.FirmwareMinor     = (short)OurHMDInfo.FirmwareMinor;
   17.57 +    d.CameraFrustumFarZInMeters  = OurHMDInfo.CameraFrustumFarZInMeters;
   17.58 +    d.CameraFrustumHFovInRadians = OurHMDInfo.CameraFrustumHFovInRadians;
   17.59 +    d.CameraFrustumNearZInMeters = OurHMDInfo.CameraFrustumNearZInMeters;
   17.60 +    d.CameraFrustumVFovInRadians = OurHMDInfo.CameraFrustumVFovInRadians;
   17.61 +
   17.62 +    OVR_strcpy(d.SerialNumber, sizeof(d.SerialNumber), OurHMDInfo.PrintedSerial.ToCStr());
   17.63 +
   17.64 +    d.HmdCaps           = ovrHmdCap_Present | ovrHmdCap_NoVSync;
   17.65 +    d.TrackingCaps      = ovrTrackingCap_MagYawCorrection | ovrTrackingCap_Orientation;
   17.66 +    d.DistortionCaps    = ovrDistortionCap_Chromatic | ovrDistortionCap_TimeWarp |
   17.67 +                          ovrDistortionCap_Vignette | ovrDistortionCap_SRGB |
   17.68 +                          ovrDistortionCap_FlipInput | ovrDistortionCap_ProfileNoTimewarpSpinWaits |
   17.69 +                          ovrDistortionCap_HqDistortion | ovrDistortionCap_LinuxDevFullscreen;
   17.70 +
   17.71 +#if defined(OVR_OS_WIN32) || defined(OVR_OS_WIN64)
   17.72 +    // TODO: this gets enabled for everything, but is only applicable for DX11+
   17.73 +    d.DistortionCaps   |= ovrDistortionCap_ComputeShader;
   17.74 +#endif
   17.75 +
   17.76 +    if( OurHMDInfo.InCompatibilityMode )
   17.77 +        d.HmdCaps |= ovrHmdCap_ExtendDesktop;
   17.78 +
   17.79 +    if (strstr(OurHMDInfo.ProductName, "DK1"))
   17.80 +    {
   17.81 +        d.Type = ovrHmd_DK1;        
   17.82 +    }
   17.83 +    else if (strstr(OurHMDInfo.ProductName, "DK2"))
   17.84 +    {
   17.85 +        d.Type        = ovrHmd_DK2;
   17.86 +        d.HmdCaps    |= ovrHmdCap_LowPersistence | ovrHmdCap_DynamicPrediction;
   17.87 +        d.TrackingCaps |= ovrTrackingCap_Position;
   17.88 +		d.DistortionCaps |= ovrDistortionCap_Overdrive;
   17.89 +    }
   17.90 +        
   17.91 +    const DistortionRenderDesc& leftDistortion  = Distortion[0];
   17.92 +    const DistortionRenderDesc& rightDistortion = Distortion[1];
   17.93 +  
   17.94 +    // The suggested FOV (assuming eye rotation)
   17.95 +    d.DefaultEyeFov[0] = CalculateFovFromHmdInfo(StereoEye_Left, leftDistortion, RenderInfo, OVR_DEFAULT_EXTRA_EYE_ROTATION);
   17.96 +    d.DefaultEyeFov[1] = CalculateFovFromHmdInfo(StereoEye_Right, rightDistortion, RenderInfo, OVR_DEFAULT_EXTRA_EYE_ROTATION);
   17.97 +
   17.98 +    // FOV extended across the entire screen
   17.99 +    d.MaxEyeFov[0] = GetPhysicalScreenFov(StereoEye_Left, leftDistortion);
  17.100 +    d.MaxEyeFov[1] = GetPhysicalScreenFov(StereoEye_Right, rightDistortion);
  17.101 +    
  17.102 +    if (OurHMDInfo.Shutter.Type == HmdShutter_RollingRightToLeft)
  17.103 +    {
  17.104 +        d.EyeRenderOrder[0] = ovrEye_Right;
  17.105 +        d.EyeRenderOrder[1] = ovrEye_Left;
  17.106 +    }
  17.107 +    else
  17.108 +    {
  17.109 +        d.EyeRenderOrder[0] = ovrEye_Left;
  17.110 +        d.EyeRenderOrder[1] = ovrEye_Right;
  17.111 +    }    
  17.112 +
  17.113 +    // MA: Taking this out on purpose.
  17.114 +	// Important information for those that are required to do their own timing,
  17.115 +    // because of shortfalls in timing code.
  17.116 +	//d.VsyncToNextVsync = OurHMDInfo.Shutter.VsyncToNextVsync;
  17.117 +	//d.PixelPersistence = OurHMDInfo.Shutter.PixelPersistence;
  17.118 +
  17.119 +    return d;
  17.120 +}
  17.121 +
  17.122 +
  17.123 +ovrSizei HMDRenderState::GetFOVTextureSize(int eye, ovrFovPort fov, float pixelsPerDisplayPixel) const
  17.124 +{
  17.125 +    OVR_ASSERT((unsigned)eye < 2);
  17.126 +    StereoEye seye = (eye == ovrEye_Left) ? StereoEye_Left : StereoEye_Right;
  17.127 +    return CalculateIdealPixelSize(seye, Distortion[eye], fov, pixelsPerDisplayPixel);
  17.128 +}
  17.129 +
  17.130 +ovrEyeRenderDesc HMDRenderState::CalcRenderDesc(ovrEyeType eyeType, const ovrFovPort& fov) const
  17.131 +{    
  17.132 +    const HmdRenderInfo&   hmdri = RenderInfo;
  17.133 +    StereoEye        eye   = (eyeType == ovrEye_Left) ? StereoEye_Left : StereoEye_Right;
  17.134 +    ovrEyeRenderDesc e0;
  17.135 +    
  17.136 +    e0.Eye                       = eyeType;
  17.137 +    e0.Fov                       = fov;
  17.138 +    e0.HmdToEyeViewOffset        = CalculateEyeVirtualCameraOffset(hmdri, eye, false);
  17.139 +    e0.DistortedViewport         = GetFramebufferViewport(eye, hmdri);
  17.140 +    e0.PixelsPerTanAngleAtCenter = Distortion[0].PixelsPerTanAngleAtCenter;
  17.141 +
  17.142 +    return e0;
  17.143 +}
  17.144 +
  17.145 +}} // namespace OVR::CAPI
  17.146 +
    18.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.2 +++ b/LibOVR/Src/CAPI/CAPI_HMDRenderState.h	Wed Jan 14 06:51:16 2015 +0200
    18.3 @@ -0,0 +1,74 @@
    18.4 +/************************************************************************************
    18.5 +
    18.6 +Filename    :   CAPI_HMDRenderState.h
    18.7 +Content     :   Combines all of the rendering state associated with the HMD
    18.8 +Created     :   February 2, 2014
    18.9 +Authors     :   Michael Antonov
   18.10 +
   18.11 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   18.12 +
   18.13 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
   18.14 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
   18.15 +which is provided at the time of installation or download, or which 
   18.16 +otherwise accompanies this software in either electronic or hard copy form.
   18.17 +
   18.18 +You may obtain a copy of the License at
   18.19 +
   18.20 +http://www.oculusvr.com/licenses/LICENSE-3.2 
   18.21 +
   18.22 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
   18.23 +distributed under the License is distributed on an "AS IS" BASIS,
   18.24 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   18.25 +See the License for the specific language governing permissions and
   18.26 +limitations under the License.
   18.27 +
   18.28 +************************************************************************************/
   18.29 +
   18.30 +#ifndef OVR_CAPI_HMDRenderState_h
   18.31 +#define OVR_CAPI_HMDRenderState_h
   18.32 +
   18.33 +#include "../OVR_CAPI.h"
   18.34 +#include "../Kernel/OVR_Math.h"
   18.35 +#include "../Util/Util_Render_Stereo.h"
   18.36 +#include "../Service/Service_NetSessionCommon.h"
   18.37 +
   18.38 +namespace OVR { namespace CAPI {
   18.39 +
   18.40 +using namespace OVR::Util::Render;
   18.41 +
   18.42 +
   18.43 +//-------------------------------------------------------------------------------------
   18.44 +// ***** HMDRenderState
   18.45 +
   18.46 +// Combines all of the rendering setup information about one HMD.
   18.47 +// This structure only ever exists inside HMDState, but this 
   18.48 +// declaration is in a separate file to reduce #include dependencies.
   18.49 +// All actual lifetime and update control is done by the surrounding HMDState.
   18.50 +struct HMDRenderState
   18.51 +{
   18.52 +    // Utility query functions.
   18.53 +    ovrHmdDesc          GetDesc() const;
   18.54 +    ovrSizei            GetFOVTextureSize(int eye, ovrFovPort fov, float pixelsPerDisplayPixel) const;
   18.55 +    ovrEyeRenderDesc    CalcRenderDesc(ovrEyeType eyeType, const ovrFovPort& fov) const;
   18.56 +
   18.57 +    HMDInfo                 OurHMDInfo;
   18.58 +
   18.59 +    HmdRenderInfo           RenderInfo;
   18.60 +    DistortionRenderDesc    Distortion[2];
   18.61 +    ovrEyeRenderDesc        EyeRenderDesc[2]; 
   18.62 +
   18.63 +    // Clear color used for distortion
   18.64 +    float                   ClearColor[4];
   18.65 +
   18.66 +    // Pose at which last time the eye was rendered, as submitted by EndEyeRender.
   18.67 +    ovrPosef                EyeRenderPoses[2];
   18.68 +
   18.69 +    // Capabilities passed to Configure.
   18.70 +    unsigned                EnabledHmdCaps;
   18.71 +    unsigned                DistortionCaps;     // enum ovrDistortionCaps
   18.72 +};
   18.73 +
   18.74 +
   18.75 +}} // namespace OVR::CAPI
   18.76 +
   18.77 +#endif // OVR_CAPI_HMDState_h
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/LibOVR/Src/CAPI/CAPI_HMDState.cpp	Wed Jan 14 06:51:16 2015 +0200
    19.3 @@ -0,0 +1,816 @@
    19.4 +/************************************************************************************
    19.5 +
    19.6 +Filename    :   CAPI_HMDState.cpp
    19.7 +Content     :   State associated with a single HMD
    19.8 +Created     :   January 24, 2014
    19.9 +Authors     :   Michael Antonov
   19.10 +
   19.11 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   19.12 +
   19.13 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
   19.14 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
   19.15 +which is provided at the time of installation or download, or which 
   19.16 +otherwise accompanies this software in either electronic or hard copy form.
   19.17 +
   19.18 +You may obtain a copy of the License at
   19.19 +
   19.20 +http://www.oculusvr.com/licenses/LICENSE-3.2 
   19.21 +
   19.22 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
   19.23 +distributed under the License is distributed on an "AS IS" BASIS,
   19.24 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   19.25 +See the License for the specific language governing permissions and
   19.26 +limitations under the License.
   19.27 +
   19.28 +************************************************************************************/
   19.29 +
   19.30 +#include "CAPI_HMDState.h"
   19.31 +#include "../OVR_Profile.h"
   19.32 +#include "../Service/Service_NetClient.h"
   19.33 +#ifdef OVR_OS_WIN32
   19.34 +#include "../Displays/OVR_Win32_ShimFunctions.h"
   19.35 +#endif
   19.36 +
   19.37 +
   19.38 +namespace OVR { namespace CAPI {
   19.39 +
   19.40 +
   19.41 +// Accessed via HMDState::GetHMDStateList()
   19.42 +static OVR::List<HMDState> hmdStateList; // List of all created HMDStates.
   19.43 +
   19.44 +
   19.45 +//-------------------------------------------------------------------------------------
   19.46 +// ***** HMDState
   19.47 +
   19.48 +HMDState::HMDState(const OVR::Service::HMDNetworkInfo& netInfo,
   19.49 +				   const OVR::HMDInfo& hmdInfo,
   19.50 +				   Profile* profile,
   19.51 +				   Service::NetClient* client) :
   19.52 +    pProfile(profile),
   19.53 +    pHmdDesc(0),
   19.54 +    pWindow(0),
   19.55 +    pClient(client),
   19.56 +    NetId(netInfo.NetId),
   19.57 +    NetInfo(netInfo),
   19.58 +    OurHMDInfo(hmdInfo),
   19.59 +    pLastError(NULL),
   19.60 +    EnabledHmdCaps(0),
   19.61 +    EnabledServiceHmdCaps(0),
   19.62 +    SharedStateReader(),
   19.63 +    TheSensorStateReader(),
   19.64 +    TheLatencyTestStateReader(),
   19.65 +    LatencyTestActive(false),
   19.66 +  //LatencyTestDrawColor(),
   19.67 +    LatencyTest2Active(false),
   19.68 +  //LatencyTest2DrawColor(),
   19.69 +    TimeManager(true),
   19.70 +    RenderState(),
   19.71 +    pRenderer(),
   19.72 +    pHSWDisplay(),
   19.73 +    LastFrameTimeSeconds(0.),
   19.74 +    LastGetFrameTimeSeconds(0.),
   19.75 +  //LastGetStringValue(),
   19.76 +    RenderingConfigured(false),
   19.77 +    BeginFrameCalled(false),
   19.78 +    BeginFrameThreadId(),
   19.79 +    RenderAPIThreadChecker(),
   19.80 +    BeginFrameTimingCalled(false)
   19.81 +{
   19.82 +    sharedInit(profile);
   19.83 +    hmdStateList.PushBack(this);
   19.84 +}
   19.85 +
   19.86 +
   19.87 +HMDState::HMDState(const OVR::HMDInfo& hmdInfo, Profile* profile) :
   19.88 +    pProfile(profile),
   19.89 +    pHmdDesc(0),
   19.90 +    pWindow(0),
   19.91 +    pClient(0),
   19.92 +    NetId(InvalidVirtualHmdId),
   19.93 +    NetInfo(),
   19.94 +    OurHMDInfo(hmdInfo),
   19.95 +    pLastError(NULL),
   19.96 +    EnabledHmdCaps(0),
   19.97 +    EnabledServiceHmdCaps(0),
   19.98 +    SharedStateReader(),
   19.99 +    TheSensorStateReader(),
  19.100 +    TheLatencyTestStateReader(),
  19.101 +    LatencyTestActive(false),
  19.102 +  //LatencyTestDrawColor(),
  19.103 +    LatencyTest2Active(false),
  19.104 +  //LatencyTest2DrawColor(),
  19.105 +    TimeManager(true),
  19.106 +    RenderState(),
  19.107 +    pRenderer(),
  19.108 +    pHSWDisplay(),
  19.109 +    LastFrameTimeSeconds(0.),
  19.110 +    LastGetFrameTimeSeconds(0.),
  19.111 +  //LastGetStringValue(),
  19.112 +    RenderingConfigured(false),
  19.113 +    BeginFrameCalled(false),
  19.114 +    BeginFrameThreadId(),
  19.115 +    RenderAPIThreadChecker(),
  19.116 +    BeginFrameTimingCalled(false)
  19.117 +{
  19.118 +    sharedInit(profile);
  19.119 +    hmdStateList.PushBack(this);
  19.120 +}
  19.121 +
  19.122 +HMDState::~HMDState()
  19.123 +{
  19.124 +    hmdStateList.Remove(this);
  19.125 +
  19.126 +    if (pClient)
  19.127 +    {
  19.128 +		pClient->Hmd_Release(NetId);
  19.129 +		pClient = 0;
  19.130 +    }
  19.131 +
  19.132 +    ConfigureRendering(0,0,0,0);
  19.133 +
  19.134 +    if (pHmdDesc)
  19.135 +    {
  19.136 +        OVR_FREE(pHmdDesc);
  19.137 +        pHmdDesc = NULL;
  19.138 +    }
  19.139 +}
  19.140 +
  19.141 +void HMDState::sharedInit(Profile* profile)
  19.142 +{
  19.143 +    // TBD: We should probably be looking up the default profile for the given
  19.144 +    // device type + user if profile == 0.    
  19.145 +    pLastError = 0;
  19.146 +
  19.147 +    RenderState.OurHMDInfo = OurHMDInfo;
  19.148 +
  19.149 +    UpdateRenderProfile(profile);
  19.150 +
  19.151 +    OVR_ASSERT(!pHmdDesc);
  19.152 +    pHmdDesc         = (ovrHmdDesc*)OVR_ALLOC(sizeof(ovrHmdDesc));
  19.153 +    *pHmdDesc        = RenderState.GetDesc();
  19.154 +    pHmdDesc->Handle = this;
  19.155 +
  19.156 +    RenderState.ClearColor[0] = 0.0f;
  19.157 +    RenderState.ClearColor[1] = 0.0f;
  19.158 +    RenderState.ClearColor[2] = 0.0f;
  19.159 +    RenderState.ClearColor[3] = 0.0f;
  19.160 +
  19.161 +    RenderState.EnabledHmdCaps = 0;
  19.162 +
  19.163 +    TimeManager.Init(RenderState.RenderInfo);
  19.164 +
  19.165 +    /*
  19.166 +    LatencyTestDrawColor[0] = 0;
  19.167 +    LatencyTestDrawColor[1] = 0;
  19.168 +    LatencyTestDrawColor[2] = 0;
  19.169 +    */
  19.170 +
  19.171 +    RenderingConfigured = false;
  19.172 +    BeginFrameCalled   = false;
  19.173 +    BeginFrameThreadId = 0;
  19.174 +    BeginFrameTimingCalled = false;
  19.175 +
  19.176 +    // Construct the HSWDisplay. We will later reconstruct it with a specific ovrRenderAPI type if the application starts using SDK-based rendering.
  19.177 +    if(!pHSWDisplay)
  19.178 +    {
  19.179 +        pHSWDisplay = *OVR::CAPI::HSWDisplay::Factory(ovrRenderAPI_None, pHmdDesc, RenderState);
  19.180 +        pHSWDisplay->Enable(pProfile->GetBoolValue("HSW", true));
  19.181 +    }
  19.182 +}
  19.183 +
  19.184 +static Vector3f GetNeckModelFromProfile(Profile* profile)
  19.185 +{
  19.186 +    OVR_ASSERT(profile);
  19.187 +
  19.188 +    float neckeye[2] = { OVR_DEFAULT_NECK_TO_EYE_HORIZONTAL, OVR_DEFAULT_NECK_TO_EYE_VERTICAL };
  19.189 +    profile->GetFloatValues(OVR_KEY_NECK_TO_EYE_DISTANCE, neckeye, 2);
  19.190 +
  19.191 +    // Make sure these are vaguely sensible values.
  19.192 +    //OVR_ASSERT((neckeye[0] > 0.05f) && (neckeye[0] < 0.5f));
  19.193 +    //OVR_ASSERT((neckeye[1] > 0.05f) && (neckeye[1] < 0.5f));
  19.194 +
  19.195 +    // Named for clarity
  19.196 +    float NeckToEyeHorizontal = neckeye[0];
  19.197 +    float NeckToEyeVertical = neckeye[1];
  19.198 +
  19.199 +    // Store the neck model
  19.200 +    return Vector3f(0.0, NeckToEyeVertical, -NeckToEyeHorizontal);
  19.201 +}
  19.202 +
  19.203 +static float GetCenterPupilDepthFromRenderInfo(HmdRenderInfo* hmdRenderInfo)
  19.204 +{
  19.205 +    OVR_ASSERT(hmdRenderInfo);
  19.206 +
  19.207 +    // Find the distance from the center of the screen to the "center eye"
  19.208 +    // This center eye is used by systems like rendering & audio to represent the player,
  19.209 +    // and they will handle the offsets needed from there to each actual eye.
  19.210 +
  19.211 +    // HACK HACK HACK
  19.212 +    // We know for DK1 the screen->lens surface distance is roughly 0.049f, and that the faceplate->lens is 0.02357f.
  19.213 +    // We're going to assume(!!!!) that all HMDs have the same screen->faceplate distance.
  19.214 +    // Crystal Cove was measured to be roughly 0.025 screen->faceplate which agrees with this assumption.
  19.215 +    // TODO: do this properly!  Update:  Measured this at 0.02733 with a CC prototype, CES era (PT7), on 2/19/14 -Steve
  19.216 +    float screenCenterToMidplate = 0.02733f;
  19.217 +    float centerEyeRelief = hmdRenderInfo->GetEyeCenter().ReliefInMeters;
  19.218 +    float CenterPupilDepth = screenCenterToMidplate + hmdRenderInfo->LensSurfaceToMidplateInMeters + centerEyeRelief;
  19.219 +
  19.220 +    return CenterPupilDepth;
  19.221 +}
  19.222 +
  19.223 +void HMDState::UpdateRenderProfile(Profile* profile)
  19.224 +{
  19.225 +    // Apply the given profile to generate a render context
  19.226 +    RenderState.RenderInfo = GenerateHmdRenderInfoFromHmdInfo(RenderState.OurHMDInfo, profile);
  19.227 +    RenderState.Distortion[0] = CalculateDistortionRenderDesc(StereoEye_Left, RenderState.RenderInfo, 0);
  19.228 +    RenderState.Distortion[1] = CalculateDistortionRenderDesc(StereoEye_Right, RenderState.RenderInfo, 0);
  19.229 +
  19.230 +    if (pClient)
  19.231 +    {
  19.232 +        // Center pupil depth
  19.233 +        float centerPupilDepth = GetCenterPupilDepthFromRenderInfo(&RenderState.RenderInfo);
  19.234 +        pClient->SetNumberValue(GetNetId(), "CenterPupilDepth", centerPupilDepth);
  19.235 +
  19.236 +        // Neck model
  19.237 +        Vector3f neckModel = GetNeckModelFromProfile(profile);
  19.238 +        double neckModelArray[3] = {
  19.239 +            neckModel.x,
  19.240 +            neckModel.y,
  19.241 +            neckModel.z
  19.242 +        };
  19.243 +        pClient->SetNumberValues(GetNetId(), "NeckModelVector3f", neckModelArray, 3);
  19.244 +
  19.245 +        double camerastate[7];
  19.246 +        if (profile->GetDoubleValues(OVR_KEY_CAMERA_POSITION, camerastate, 7) == 0)
  19.247 +        {
  19.248 +            //there is no value, so we load the default
  19.249 +            for (int i = 0; i < 7; i++) camerastate[i] = 0;
  19.250 +            camerastate[3] = 1;//no offset. by default, give the quaternion w component value 1
  19.251 +        }
  19.252 +        else
  19.253 +
  19.254 +        TheSensorStateReader.setCenteredFromWorld(OVR::Posed::FromArray(camerastate));
  19.255 +    }
  19.256 +
  19.257 +
  19.258 +}
  19.259 +
  19.260 +HMDState* HMDState::CreateHMDState(NetClient* client, const HMDNetworkInfo& netInfo)
  19.261 +{
  19.262 +    // HMDState works through a handle to service HMD....
  19.263 +    HMDInfo hinfo;
  19.264 +    if (!client->Hmd_GetHmdInfo(netInfo.NetId, &hinfo))
  19.265 +    {
  19.266 +        OVR_DEBUG_LOG(("[HMDState] Unable to get HMD info"));
  19.267 +        return NULL;
  19.268 +    }
  19.269 +
  19.270 +#ifdef OVR_OS_WIN32
  19.271 +    OVR_DEBUG_LOG(("Setting up display shim"));
  19.272 +
  19.273 +    // Initialize the display shim before reporting the display to the user code
  19.274 +    // so that this will happen before the D3D display object is created.
  19.275 +    Win32::DisplayShim::GetInstance().Update(&hinfo.ShimInfo);
  19.276 +#endif
  19.277 +
  19.278 +    Ptr<Profile> pDefaultProfile = *ProfileManager::GetInstance()->GetDefaultUserProfile(&hinfo);
  19.279 +    OVR_DEBUG_LOG(("Using profile %s", pDefaultProfile->GetValue(OVR_KEY_USER)));
  19.280 +
  19.281 +    HMDState* hmds = new HMDState(netInfo, hinfo, pDefaultProfile, client);
  19.282 +
  19.283 +    if (!hmds->SharedStateReader.Open(netInfo.SharedMemoryName.ToCStr()))
  19.284 +    {
  19.285 +        delete hmds;
  19.286 +        return NULL;
  19.287 +    }
  19.288 +
  19.289 +    hmds->TheSensorStateReader.SetUpdater(hmds->SharedStateReader.Get());
  19.290 +    hmds->TheLatencyTestStateReader.SetUpdater(hmds->SharedStateReader.Get());
  19.291 +
  19.292 +    return hmds;
  19.293 +}
  19.294 +
  19.295 +HMDState* HMDState::CreateHMDState(ovrHmdType hmdType)
  19.296 +{
  19.297 +    HmdTypeEnum t = HmdType_None;
  19.298 +    if (hmdType == ovrHmd_DK1)
  19.299 +        t = HmdType_DK1;    
  19.300 +    else if (hmdType == ovrHmd_DK2)
  19.301 +        t = HmdType_DK2;
  19.302 +
  19.303 +    // FIXME: This does not actually grab the right user..
  19.304 +    Ptr<Profile> pDefaultProfile = *ProfileManager::GetInstance()->GetDefaultProfile(t);
  19.305 +
  19.306 +    return new HMDState(CreateDebugHMDInfo(t), pDefaultProfile);
  19.307 +}
  19.308 +    
  19.309 +
  19.310 +const OVR::List<HMDState>& HMDState::GetHMDStateList()
  19.311 +{
  19.312 +    return hmdStateList;
  19.313 +}
  19.314 +
  19.315 +
  19.316 +//-------------------------------------------------------------------------------------
  19.317 +// *** Sensor 
  19.318 +
  19.319 +bool HMDState::ConfigureTracking(unsigned supportedCaps, unsigned requiredCaps)
  19.320 +{
  19.321 +	return pClient ? pClient->Hmd_ConfigureTracking(NetId, supportedCaps, requiredCaps) : true;
  19.322 +}
  19.323 +
  19.324 +void HMDState::ResetTracking()
  19.325 +{
  19.326 +	if (pClient) pClient->Hmd_ResetTracking(NetId);
  19.327 +}        
  19.328 +
  19.329 +// Re-center the orientation.
  19.330 +void HMDState::RecenterPose()
  19.331 +{
  19.332 +    TheSensorStateReader.RecenterPose();
  19.333 +}
  19.334 +
  19.335 +// Returns prediction for time.
  19.336 +ovrTrackingState HMDState::PredictedTrackingState(double absTime)
  19.337 +{    
  19.338 +	Tracking::TrackingState ss;
  19.339 +    TheSensorStateReader.GetSensorStateAtTime(absTime, ss);
  19.340 +
  19.341 +    // Zero out the status flags
  19.342 +    if (!pClient || !pClient->IsConnected(false, false))
  19.343 +    {
  19.344 +        ss.StatusFlags = 0;
  19.345 +    }
  19.346 +
  19.347 +    return ss;
  19.348 +}
  19.349 +
  19.350 +void HMDState::SetEnabledHmdCaps(unsigned hmdCaps)
  19.351 +{
  19.352 +    if (OurHMDInfo.HmdType < HmdType_DK2)
  19.353 +    {
  19.354 +        // disable low persistence and pentile.
  19.355 +        hmdCaps &= ~ovrHmdCap_LowPersistence;
  19.356 +        hmdCaps &= ~ovrHmdCap_DirectPentile;
  19.357 +
  19.358 +        // disable dynamic prediction using the internal latency tester
  19.359 +        hmdCaps &= ~ovrHmdCap_DynamicPrediction;
  19.360 +    }
  19.361 +
  19.362 +    if (OurHMDInfo.HmdType >= HmdType_DK2)
  19.363 +    {
  19.364 +        if ((EnabledHmdCaps ^ hmdCaps) & ovrHmdCap_DynamicPrediction)
  19.365 +        {
  19.366 +            // DynamicPrediction change
  19.367 +            TimeManager.ResetFrameTiming(TimeManager.GetFrameTiming().FrameIndex,
  19.368 +                                         (hmdCaps & ovrHmdCap_DynamicPrediction) ? true : false,
  19.369 +                                         RenderingConfigured);
  19.370 +        }
  19.371 +    }
  19.372 +
  19.373 +    // Pentile unsupported on everything right now.
  19.374 +    hmdCaps &= ~ovrHmdCap_DirectPentile;
  19.375 +	
  19.376 +    if ((EnabledHmdCaps ^ hmdCaps) & ovrHmdCap_NoVSync)
  19.377 +    {
  19.378 +        TimeManager.SetVsync((hmdCaps & ovrHmdCap_NoVSync) ? false : true);
  19.379 +    }
  19.380 +
  19.381 +    if ((EnabledHmdCaps ^ hmdCaps) & ovrHmdCap_NoMirrorToWindow)
  19.382 +    {
  19.383 +#ifdef OVR_OS_WIN32
  19.384 +        Win32::DisplayShim::GetInstance().UseMirroring = (hmdCaps & ovrHmdCap_NoMirrorToWindow)  ?
  19.385 +                                                         false : true;
  19.386 +        if (pWindow)
  19.387 +        {   // Force window repaint so that stale mirrored image doesn't persist.
  19.388 +            ::InvalidateRect((HWND)pWindow, 0, true);
  19.389 +        }
  19.390 +#endif
  19.391 +    }
  19.392 +
  19.393 +    // TBD: Should this include be only the rendering flags? Otherwise, bits that failed
  19.394 +    //      modification in Hmd_SetEnabledCaps may mis-match...
  19.395 +    EnabledHmdCaps             = hmdCaps & ovrHmdCap_Writable_Mask;
  19.396 +    RenderState.EnabledHmdCaps = EnabledHmdCaps;
  19.397 +
  19.398 +
  19.399 +    // If any of the modifiable service caps changed, call on the service.
  19.400 +    unsigned prevServiceCaps = EnabledServiceHmdCaps & ovrHmdCap_Writable_Mask;
  19.401 +    unsigned newServiceCaps  = hmdCaps & ovrHmdCap_Writable_Mask & ovrHmdCap_Service_Mask;
  19.402 +
  19.403 +    if (prevServiceCaps ^ newServiceCaps)
  19.404 +	{
  19.405 +        EnabledServiceHmdCaps = pClient ? pClient->Hmd_SetEnabledCaps(NetId, newServiceCaps)
  19.406 +                                : newServiceCaps;
  19.407 +    }
  19.408 +}
  19.409 +
  19.410 +
  19.411 +unsigned HMDState::SetEnabledHmdCaps()
  19.412 +{
  19.413 +	unsigned serviceCaps = pClient ? pClient->Hmd_GetEnabledCaps(NetId) :
  19.414 +                                      EnabledServiceHmdCaps;
  19.415 +    
  19.416 +    return serviceCaps & ((~ovrHmdCap_Service_Mask) | EnabledHmdCaps);    
  19.417 +}
  19.418 +
  19.419 +
  19.420 +//-------------------------------------------------------------------------------------
  19.421 +// ***** Property Access
  19.422 +
  19.423 +// FIXME: Remove the EGetBoolValue stuff and do it with a "Server:" prefix, so we do not
  19.424 +// need to keep a white-list of keys.  This is also way cool because it allows us to add
  19.425 +// new settings keys from outside CAPI that can modify internal server data.
  19.426 +
  19.427 +bool HMDState::getBoolValue(const char* propertyName, bool defaultVal)
  19.428 +{
  19.429 +    if (NetSessionCommon::IsServiceProperty(NetSessionCommon::EGetBoolValue, propertyName))
  19.430 +    {
  19.431 +       return NetClient::GetInstance()->GetBoolValue(GetNetId(), propertyName, defaultVal);
  19.432 +    }
  19.433 +    else if (pProfile)
  19.434 +    {
  19.435 +        return pProfile->GetBoolValue(propertyName, defaultVal);
  19.436 +    }
  19.437 +    return defaultVal;
  19.438 +}
  19.439 +
  19.440 +bool HMDState::setBoolValue(const char* propertyName, bool value)
  19.441 +{
  19.442 +	if (NetSessionCommon::IsServiceProperty(NetSessionCommon::ESetBoolValue, propertyName))
  19.443 +	{
  19.444 +		return NetClient::GetInstance()->SetBoolValue(GetNetId(), propertyName, value);
  19.445 +	}
  19.446 +
  19.447 +	return false;
  19.448 +}
  19.449 +
  19.450 +int HMDState::getIntValue(const char* propertyName, int defaultVal)
  19.451 +{
  19.452 +    if (NetSessionCommon::IsServiceProperty(NetSessionCommon::EGetIntValue, propertyName))
  19.453 +    {
  19.454 +        return NetClient::GetInstance()->GetIntValue(GetNetId(), propertyName, defaultVal);
  19.455 +    }
  19.456 +    else if (pProfile)
  19.457 +    {
  19.458 +        return pProfile->GetIntValue(propertyName, defaultVal);
  19.459 +    }
  19.460 +    return defaultVal;
  19.461 +}
  19.462 +
  19.463 +bool HMDState::setIntValue(const char* propertyName, int value)
  19.464 +{
  19.465 +	if (NetSessionCommon::IsServiceProperty(NetSessionCommon::ESetIntValue, propertyName))
  19.466 +	{
  19.467 +		return NetClient::GetInstance()->SetIntValue(GetNetId(), propertyName, value);
  19.468 +	}
  19.469 +
  19.470 +	return false;
  19.471 +}
  19.472 +
  19.473 +float HMDState::getFloatValue(const char* propertyName, float defaultVal)
  19.474 +{
  19.475 +    if (OVR_strcmp(propertyName, "LensSeparation") == 0)
  19.476 +    {
  19.477 +        return OurHMDInfo.LensSeparationInMeters;
  19.478 +    }
  19.479 +    else if (OVR_strcmp(propertyName, "VsyncToNextVsync") == 0) 
  19.480 +    {
  19.481 +        return OurHMDInfo.Shutter.VsyncToNextVsync;
  19.482 +    }
  19.483 +    else if (OVR_strcmp(propertyName, "PixelPersistence") == 0) 
  19.484 +    {
  19.485 +        return OurHMDInfo.Shutter.PixelPersistence;
  19.486 +    }
  19.487 +    else if (NetSessionCommon::IsServiceProperty(NetSessionCommon::EGetNumberValue, propertyName))
  19.488 +    {
  19.489 +       return (float)NetClient::GetInstance()->GetNumberValue(GetNetId(), propertyName, defaultVal);
  19.490 +    }
  19.491 +    else if (pProfile)
  19.492 +    {
  19.493 +        return pProfile->GetFloatValue(propertyName, defaultVal);
  19.494 +    }
  19.495 +
  19.496 +    return defaultVal;
  19.497 +}
  19.498 +
  19.499 +bool HMDState::setFloatValue(const char* propertyName, float value)
  19.500 +{
  19.501 +	if (NetSessionCommon::IsServiceProperty(NetSessionCommon::ESetNumberValue, propertyName))
  19.502 +	{
  19.503 +		return NetClient::GetInstance()->SetNumberValue(GetNetId(), propertyName, value);
  19.504 +	}
  19.505 +
  19.506 +	return false;
  19.507 +}
  19.508 +
  19.509 +static unsigned CopyFloatArrayWithLimit(float dest[], unsigned destSize,
  19.510 +                                        float source[], unsigned sourceSize)
  19.511 +{
  19.512 +    unsigned count = Alg::Min(destSize, sourceSize);
  19.513 +    for (unsigned i = 0; i < count; i++)
  19.514 +        dest[i] = source[i];
  19.515 +    return count;
  19.516 +}
  19.517 +
  19.518 +unsigned HMDState::getFloatArray(const char* propertyName, float values[], unsigned arraySize)
  19.519 +{
  19.520 +	if (arraySize)
  19.521 +	{
  19.522 +		if (OVR_strcmp(propertyName, "ScreenSize") == 0)
  19.523 +		{
  19.524 +			float data[2] = { OurHMDInfo.ScreenSizeInMeters.w, OurHMDInfo.ScreenSizeInMeters.h };
  19.525 +
  19.526 +            return CopyFloatArrayWithLimit(values, arraySize, data, 2);
  19.527 +		}
  19.528 +        else if (OVR_strcmp(propertyName, "DistortionClearColor") == 0)
  19.529 +        {
  19.530 +            return CopyFloatArrayWithLimit(values, arraySize, RenderState.ClearColor, 4);
  19.531 +        }
  19.532 +        else if (OVR_strcmp(propertyName, "DK2Latency") == 0)
  19.533 +        {
  19.534 +            if (OurHMDInfo.HmdType != HmdType_DK2)
  19.535 +            {
  19.536 +                return 0;
  19.537 +            }
  19.538 +
  19.539 +            union {
  19.540 +                struct X {
  19.541 +                    float latencyRender, latencyTimewarp, latencyPostPresent;
  19.542 +                } x;
  19.543 +                float data[3];
  19.544 +            } m;
  19.545 +
  19.546 +            static_assert(sizeof(m.x)==sizeof(m.data), "sizeof(struct X) failure");
  19.547 +
  19.548 +            TimeManager.GetLatencyTimings(m.x.latencyRender, m.x.latencyTimewarp, m.x.latencyPostPresent);
  19.549 +
  19.550 +            return CopyFloatArrayWithLimit(values, arraySize, m.data, 3);
  19.551 +        }
  19.552 +        else if (NetSessionCommon::IsServiceProperty(NetSessionCommon::EGetNumberValues, propertyName))
  19.553 +        {
  19.554 +            // Convert floats to doubles
  19.555 +            double* da = new double[arraySize];
  19.556 +            for (int i = 0; i < (int)arraySize; ++i)
  19.557 +            {
  19.558 +                da[i] = values[i];
  19.559 +            }
  19.560 +
  19.561 +            int count = NetClient::GetInstance()->GetNumberValues(GetNetId(), propertyName, da, (int)arraySize);
  19.562 +
  19.563 +            for (int i = 0; i < count; ++i)
  19.564 +            {
  19.565 +                values[i] = (float)da[i];
  19.566 +            }
  19.567 +
  19.568 +            delete[] da;
  19.569 +
  19.570 +            return count;
  19.571 +        }
  19.572 +		else if (pProfile)
  19.573 +		{        
  19.574 +			// TBD: Not quite right. Should update profile interface, so that
  19.575 +			//      we can return 0 in all conditions if property doesn't exist.
  19.576 +		
  19.577 +            return pProfile->GetFloatValues(propertyName, values, arraySize);
  19.578 +		}
  19.579 +	}
  19.580 +
  19.581 +	return 0;
  19.582 +}
  19.583 +
  19.584 +bool HMDState::setFloatArray(const char* propertyName, float values[], unsigned arraySize)
  19.585 +{
  19.586 +    if (!arraySize)
  19.587 +    {
  19.588 +        return false;
  19.589 +    }
  19.590 +    
  19.591 +    if (OVR_strcmp(propertyName, "DistortionClearColor") == 0)
  19.592 +    {
  19.593 +        CopyFloatArrayWithLimit(RenderState.ClearColor, 4, values, arraySize);
  19.594 +        return true;
  19.595 +    }
  19.596 +
  19.597 +	if (NetSessionCommon::IsServiceProperty(NetSessionCommon::ESetNumberValues, propertyName))
  19.598 +	{
  19.599 +		double* da = new double[arraySize];
  19.600 +		for (int i = 0; i < (int)arraySize; ++i)
  19.601 +		{
  19.602 +			da[i] = values[i];
  19.603 +		}
  19.604 +
  19.605 +		bool result = NetClient::GetInstance()->SetNumberValues(GetNetId(), propertyName, da, arraySize);
  19.606 +
  19.607 +		delete[] da;
  19.608 +
  19.609 +		return result;
  19.610 +	}
  19.611 +
  19.612 +	return false;
  19.613 +}
  19.614 +
  19.615 +const char* HMDState::getString(const char* propertyName, const char* defaultVal)
  19.616 +{
  19.617 +    if (NetSessionCommon::IsServiceProperty(NetSessionCommon::EGetStringValue, propertyName))
  19.618 +    {
  19.619 +        return NetClient::GetInstance()->GetStringValue(GetNetId(), propertyName, defaultVal);
  19.620 +    }
  19.621 +
  19.622 +	if (pProfile)
  19.623 +	{
  19.624 +		LastGetStringValue[0] = 0;
  19.625 +		if (pProfile->GetValue(propertyName, LastGetStringValue, sizeof(LastGetStringValue)))
  19.626 +		{
  19.627 +			return LastGetStringValue;
  19.628 +		}
  19.629 +	}
  19.630 +
  19.631 +	return defaultVal;
  19.632 +}
  19.633 +
  19.634 +bool HMDState::setString(const char* propertyName, const char* value)
  19.635 +{
  19.636 +	if (NetSessionCommon::IsServiceProperty(NetSessionCommon::ESetStringValue, propertyName))
  19.637 +	{
  19.638 +		return NetClient::GetInstance()->SetStringValue(GetNetId(), propertyName, value);
  19.639 +	}
  19.640 +
  19.641 +	return false;
  19.642 +}
  19.643 +
  19.644 +
  19.645 +//-------------------------------------------------------------------------------------
  19.646 +// *** Latency Test
  19.647 +
  19.648 +bool HMDState::ProcessLatencyTest(unsigned char rgbColorOut[3])
  19.649 +{    
  19.650 +    return NetClient::GetInstance()->LatencyUtil_ProcessInputs(Timer::GetSeconds(), rgbColorOut);
  19.651 +}
  19.652 +
  19.653 +//-------------------------------------------------------------------------------------
  19.654 +// *** Rendering
  19.655 +
  19.656 +bool HMDState::ConfigureRendering(ovrEyeRenderDesc eyeRenderDescOut[2],
  19.657 +                                  const ovrFovPort eyeFovIn[2],
  19.658 +                                  const ovrRenderAPIConfig* apiConfig,                                  
  19.659 +                                  unsigned distortionCaps)
  19.660 +{
  19.661 +    ThreadChecker::Scope checkScope(&RenderAPIThreadChecker, "ovrHmd_ConfigureRendering");
  19.662 +
  19.663 +    // null -> shut down.
  19.664 +    if (!apiConfig)
  19.665 +    {
  19.666 +        if (pHSWDisplay)
  19.667 +        {
  19.668 +            pHSWDisplay->Shutdown();
  19.669 +            pHSWDisplay.Clear();
  19.670 +        }
  19.671 +
  19.672 +        if (pRenderer)
  19.673 +            pRenderer.Clear();        
  19.674 +        RenderingConfigured = false; 
  19.675 +        return true;
  19.676 +    }
  19.677 +
  19.678 +    if (pRenderer &&
  19.679 +        (apiConfig->Header.API != pRenderer->GetRenderAPI()))
  19.680 +    {
  19.681 +        // Shutdown old renderer.
  19.682 +        if (pHSWDisplay)
  19.683 +        {
  19.684 +            pHSWDisplay->Shutdown();
  19.685 +            pHSWDisplay.Clear();
  19.686 +        }
  19.687 +
  19.688 +        if (pRenderer)
  19.689 +            pRenderer.Clear();
  19.690 +    }
  19.691 +
  19.692 +	distortionCaps = distortionCaps & pHmdDesc->DistortionCaps;
  19.693 +
  19.694 +    // Step 1: do basic setup configuration
  19.695 +    RenderState.EnabledHmdCaps = EnabledHmdCaps;     // This is a copy... Any cleaner way?
  19.696 +    RenderState.DistortionCaps = distortionCaps;
  19.697 +    RenderState.EyeRenderDesc[0] = RenderState.CalcRenderDesc(ovrEye_Left,  eyeFovIn[0]);
  19.698 +    RenderState.EyeRenderDesc[1] = RenderState.CalcRenderDesc(ovrEye_Right, eyeFovIn[1]);
  19.699 +    eyeRenderDescOut[0] = RenderState.EyeRenderDesc[0];
  19.700 +    eyeRenderDescOut[1] = RenderState.EyeRenderDesc[1];
  19.701 +
  19.702 +    TimeManager.ResetFrameTiming(0,
  19.703 +                                 (EnabledHmdCaps & ovrHmdCap_DynamicPrediction) ? true : false,
  19.704 +                                 true);
  19.705 +
  19.706 +    LastFrameTimeSeconds = 0.0f;
  19.707 +
  19.708 +    // Set RenderingConfigured early to avoid ASSERTs in renderer initialization.
  19.709 +    RenderingConfigured = true;
  19.710 +
  19.711 +    if (!pRenderer)
  19.712 +    {
  19.713 +        pRenderer = *DistortionRenderer::APICreateRegistry
  19.714 +                        [apiConfig->Header.API](pHmdDesc, TimeManager, RenderState);
  19.715 +    }
  19.716 +
  19.717 +    if (!pRenderer ||
  19.718 +        !pRenderer->Initialize(apiConfig))
  19.719 +    {
  19.720 +        RenderingConfigured = false;
  19.721 +        return false;
  19.722 +    }    
  19.723 +
  19.724 +    // Setup the Health and Safety Warning display system.
  19.725 +    if(pHSWDisplay && (pHSWDisplay->GetRenderAPIType() != apiConfig->Header.API)) // If we need to reconstruct the HSWDisplay for a different graphics API type, delete the existing display.
  19.726 +    {
  19.727 +        pHSWDisplay->Shutdown();
  19.728 +        pHSWDisplay.Clear();
  19.729 +    }
  19.730 +
  19.731 +    if(!pHSWDisplay) // Use * below because that for of operator= causes it to inherit the refcount the factory gave the object.
  19.732 +    {
  19.733 +        pHSWDisplay = *OVR::CAPI::HSWDisplay::Factory(apiConfig->Header.API, pHmdDesc, RenderState);
  19.734 +        pHSWDisplay->Enable(pProfile->GetBoolValue("HSW", true));
  19.735 +    }
  19.736 +
  19.737 +    if (pHSWDisplay)
  19.738 +        pHSWDisplay->Initialize(apiConfig); // This is potentially re-initializing it with a new config.
  19.739 +
  19.740 +    return true;
  19.741 +}
  19.742 +
  19.743 +
  19.744 +void  HMDState::SubmitEyeTextures(const ovrPosef renderPose[2],
  19.745 +                                  const ovrTexture eyeTexture[2])
  19.746 +{
  19.747 +    RenderState.EyeRenderPoses[0] = renderPose[0];
  19.748 +    RenderState.EyeRenderPoses[1] = renderPose[1];
  19.749 +
  19.750 +    if (pRenderer)
  19.751 +    {
  19.752 +        pRenderer->SubmitEye(0, &eyeTexture[0]);
  19.753 +        pRenderer->SubmitEye(1, &eyeTexture[1]);
  19.754 +    }
  19.755 +}
  19.756 +
  19.757 +
  19.758 +// I appreciate this is not an idea place for this function, but it didn't seem to be
  19.759 +// being linked properly when in OVR_CAPI.cpp. 
  19.760 +// Please relocate if you know of a better place
  19.761 +ovrBool ovrHmd_CreateDistortionMeshInternal( ovrHmdStruct *  hmd,
  19.762 +                                             ovrEyeType eyeType, ovrFovPort fov,
  19.763 +                                             unsigned int distortionCaps,
  19.764 +                                             ovrDistortionMesh *meshData,
  19.765 +											 float overrideEyeReliefIfNonZero )
  19.766 +{
  19.767 +    if (!meshData)
  19.768 +        return 0;
  19.769 +    HMDState* hmds = (HMDState*)hmd;
  19.770 +
  19.771 +    // Not used now, but Chromatic flag or others could possibly be checked for in the future.
  19.772 +    OVR_UNUSED1(distortionCaps); 
  19.773 +   
  19.774 +#if defined (OVR_CC_MSVC)
  19.775 +    static_assert(sizeof(DistortionMeshVertexData) == sizeof(ovrDistortionVertex), "DistortionMeshVertexData size mismatch");
  19.776 +#endif
  19.777 +	
  19.778 +    // *** Calculate a part of "StereoParams" needed for mesh generation
  19.779 +
  19.780 +    // Note that mesh distortion generation is invariant of RenderTarget UVs, allowing
  19.781 +    // render target size and location to be changed after the fact dynamically. 
  19.782 +    // eyeToSourceUV is computed here for convenience, so that users don't need
  19.783 +    // to call ovrHmd_GetRenderScaleAndOffset unless changing RT dynamically.
  19.784 +
  19.785 +    const HmdRenderInfo&  hmdri          = hmds->RenderState.RenderInfo;    
  19.786 +    StereoEye             stereoEye      = (eyeType == ovrEye_Left) ? StereoEye_Left : StereoEye_Right;
  19.787 +
  19.788 +    DistortionRenderDesc& distortion = hmds->RenderState.Distortion[eyeType];
  19.789 +	if (overrideEyeReliefIfNonZero)
  19.790 +	{
  19.791 +		distortion.Lens = GenerateLensConfigFromEyeRelief(overrideEyeReliefIfNonZero,hmdri);
  19.792 +	}
  19.793 +
  19.794 +    // Find the mapping from TanAngle space to target NDC space.
  19.795 +    ScaleAndOffset2D      eyeToSourceNDC = CreateNDCScaleAndOffsetFromFov(fov);
  19.796 +
  19.797 +    int triangleCount = 0;
  19.798 +    int vertexCount = 0;
  19.799 +
  19.800 +    DistortionMeshCreate((DistortionMeshVertexData**)&meshData->pVertexData,
  19.801 +                         (uint16_t**)&meshData->pIndexData,
  19.802 +                          &vertexCount, &triangleCount,
  19.803 +                          (stereoEye == StereoEye_Right),
  19.804 +                          hmdri, distortion, eyeToSourceNDC);
  19.805 +
  19.806 +    if (meshData->pVertexData)
  19.807 +    {
  19.808 +        // Convert to index
  19.809 +        meshData->IndexCount = triangleCount * 3;
  19.810 +        meshData->VertexCount = vertexCount;
  19.811 +        return 1;
  19.812 +    }
  19.813 +
  19.814 +    return 0;
  19.815 +}
  19.816 +
  19.817 +
  19.818 +
  19.819 +}} // namespace OVR::CAPI
    20.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.2 +++ b/LibOVR/Src/CAPI/CAPI_HMDState.h	Wed Jan 14 06:51:16 2015 +0200
    20.3 @@ -0,0 +1,304 @@
    20.4 +/************************************************************************************
    20.5 +
    20.6 +Filename    :   CAPI_HMDState.h
    20.7 +Content     :   State associated with a single HMD
    20.8 +Created     :   January 24, 2014
    20.9 +Authors     :   Michael Antonov
   20.10 +
   20.11 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   20.12 +
   20.13 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
   20.14 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
   20.15 +which is provided at the time of installation or download, or which 
   20.16 +otherwise accompanies this software in either electronic or hard copy form.
   20.17 +
   20.18 +You may obtain a copy of the License at
   20.19 +
   20.20 +http://www.oculusvr.com/licenses/LICENSE-3.2 
   20.21 +
   20.22 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
   20.23 +distributed under the License is distributed on an "AS IS" BASIS,
   20.24 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   20.25 +See the License for the specific language governing permissions and
   20.26 +limitations under the License.
   20.27 +
   20.28 +************************************************************************************/
   20.29 +
   20.30 +#ifndef OVR_CAPI_HMDState_h
   20.31 +#define OVR_CAPI_HMDState_h
   20.32 +
   20.33 +#include "../Kernel/OVR_Math.h"
   20.34 +#include "../Kernel/OVR_List.h"
   20.35 +#include "../Kernel/OVR_Log.h"
   20.36 +#include "../OVR_CAPI.h"
   20.37 +
   20.38 +#include "CAPI_FrameTimeManager.h"
   20.39 +#include "CAPI_LatencyStatistics.h"
   20.40 +#include "CAPI_HMDRenderState.h"
   20.41 +#include "CAPI_DistortionRenderer.h"
   20.42 +#include "CAPI_HSWDisplay.h"
   20.43 +
   20.44 +#include "../Service/Service_NetClient.h"
   20.45 +#include "../Net/OVR_NetworkTypes.h"
   20.46 +#include "../Util/Util_LatencyTest2Reader.h"
   20.47 +
   20.48 +struct ovrHmdStruct { };
   20.49 +
   20.50 +namespace OVR { namespace CAPI {
   20.51 +
   20.52 +
   20.53 +using namespace OVR::Util::Render;
   20.54 +using namespace OVR::Service;
   20.55 +using namespace OVR::Net;
   20.56 +
   20.57 +
   20.58 +//-------------------------------------------------------------------------------------
   20.59 +// ***** ThreadChecker
   20.60 +
   20.61 +// This helper class is used to verify that the API is used according to supported
   20.62 +// thread safety constraints (is not re-entrant for this and related functions).
   20.63 +class ThreadChecker
   20.64 +{
   20.65 +public:
   20.66 +
   20.67 +#ifndef OVR_BUILD_DEBUG
   20.68 +
   20.69 +    // In release build, thread checks are disabled.
   20.70 +    ThreadChecker() { }
   20.71 +    void Begin(const char* functionName)    { OVR_UNUSED1(functionName); }
   20.72 +    void End()                              {  }
   20.73 +
   20.74 +    // Add thread-re-entrancy check for function scope
   20.75 +    struct Scope
   20.76 +    {
   20.77 +        Scope(ThreadChecker*, const char *) { }
   20.78 +        ~Scope() { }
   20.79 +    };
   20.80 +
   20.81 +
   20.82 +#else // OVR_BUILD_DEBUG
   20.83 +    ThreadChecker() : pFunctionName(0), FirstThread(0)
   20.84 +    { }
   20.85 +
   20.86 +    void Begin(const char* functionName)
   20.87 +    {        
   20.88 +        if (!pFunctionName)
   20.89 +        {
   20.90 +            pFunctionName = functionName;
   20.91 +            FirstThread   = GetCurrentThreadId();
   20.92 +        }
   20.93 +        else
   20.94 +        {
   20.95 +            // pFunctionName may be not null here if function is called internally on the same thread.
   20.96 +            OVR_ASSERT_LOG((FirstThread == GetCurrentThreadId()),
   20.97 +                ("%s (threadId=%p) called at the same times as %s (threadId=%p)\n",
   20.98 +                functionName, GetCurrentThreadId(), pFunctionName, FirstThread) );
   20.99 +        }        
  20.100 +    }
  20.101 +    void End()
  20.102 +    {
  20.103 +        pFunctionName = 0;
  20.104 +        FirstThread   = 0;
  20.105 +    }
  20.106 +
  20.107 +    // Add thread-reentrancy check for function scope.
  20.108 +    struct Scope
  20.109 +    {
  20.110 +        Scope(ThreadChecker* threadChecker, const char *functionName) : pChecker(threadChecker)
  20.111 +        { pChecker->Begin(functionName); }
  20.112 +        ~Scope()
  20.113 +        { pChecker->End(); }
  20.114 +    private:
  20.115 +        ThreadChecker* pChecker;
  20.116 +    };
  20.117 +
  20.118 +private:
  20.119 +    // If not 0, contains the name of the function that first entered the scope.
  20.120 +    const char * pFunctionName;
  20.121 +    ThreadId     FirstThread;
  20.122 +
  20.123 +#endif // OVR_BUILD_DEBUG
  20.124 +};
  20.125 +
  20.126 +
  20.127 +//-------------------------------------------------------------------------------------
  20.128 +// ***** HMDState
  20.129 +
  20.130 +// Describes a single HMD.
  20.131 +class HMDState : public ListNode<HMDState>,
  20.132 +                 public ovrHmdStruct, public NewOverrideBase 
  20.133 +{
  20.134 +    void operator=(const HMDState&) { } // Quiet warning.
  20.135 +
  20.136 +protected:   
  20.137 +	HMDState(const OVR::Service::HMDNetworkInfo& netInfo,
  20.138 +			 const OVR::HMDInfo& hmdInfo,
  20.139 +			 Profile* profile,
  20.140 +			 Service::NetClient* client);
  20.141 +    HMDState(const HMDInfo& src, Profile* profile);
  20.142 +
  20.143 +public:   
  20.144 +    virtual ~HMDState();
  20.145 +
  20.146 +    static HMDState* CreateHMDState(Service::NetClient* client, const HMDNetworkInfo& netInfo);
  20.147 +    static HMDState* CreateHMDState(ovrHmdType hmdType); // Used for debug mode
  20.148 +    static const OVR::List<HMDState>& GetHMDStateList();
  20.149 +
  20.150 +    // *** Sensor Setup
  20.151 +
  20.152 +    bool            ConfigureTracking(unsigned supportedCaps, unsigned requiredCaps);    
  20.153 +    void            ResetTracking();
  20.154 +	void			RecenterPose();
  20.155 +    ovrTrackingState PredictedTrackingState(double absTime);
  20.156 +
  20.157 +    // Changes HMD Caps.
  20.158 +    // Capability bits that are not directly or logically tied to one system (such as sensor)
  20.159 +    // are grouped here. ovrHmdCap_VSync, for example, affects rendering and timing.
  20.160 +    void            SetEnabledHmdCaps(unsigned caps);
  20.161 +    unsigned        SetEnabledHmdCaps();
  20.162 +
  20.163 +    bool            ProcessLatencyTest(unsigned char rgbColorOut[3]);
  20.164 +
  20.165 +    // *** Rendering Setup
  20.166 +    bool        ConfigureRendering(ovrEyeRenderDesc eyeRenderDescOut[2],
  20.167 +                                   const ovrFovPort eyeFovIn[2],
  20.168 +                                   const ovrRenderAPIConfig* apiConfig,                                  
  20.169 +                                   unsigned distortionCaps);  
  20.170 +    
  20.171 +    void        UpdateRenderProfile(Profile* profile);
  20.172 +
  20.173 +
  20.174 +    void        SubmitEyeTextures(const ovrPosef renderPose[2],
  20.175 +                                  const ovrTexture eyeTexture[2]);
  20.176 +
  20.177 +
  20.178 +    void sharedInit ( Profile *profile );
  20.179 +
  20.180 +    void applyProfileToSensorFusion();
  20.181 +
  20.182 +    // INlines so that they can be easily compiled out.    
  20.183 +    // Does debug ASSERT checks for functions that require BeginFrame.
  20.184 +    // Also verifies that we are on the right thread.
  20.185 +    void checkBeginFrameScope(const char* functionName)
  20.186 +    {
  20.187 +        OVR_UNUSED1(functionName); // for Release build.
  20.188 +        OVR_ASSERT_LOG(BeginFrameCalled == true,
  20.189 +                       ("%s called outside ovrHmd_BeginFrame.", functionName));
  20.190 +		OVR_DEBUG_LOG_COND(BeginFrameThreadId != OVR::GetCurrentThreadId(),
  20.191 +                       ("%s called on a different thread then ovrHmd_BeginFrame.", functionName));
  20.192 +    }
  20.193 +
  20.194 +    void checkRenderingConfigured(const char* functionName)
  20.195 +    {
  20.196 +        OVR_UNUSED1(functionName); // for Release build.
  20.197 +        OVR_ASSERT_LOG(RenderingConfigured == true,
  20.198 +                       ("%s called without ovrHmd_ConfigureRendering.", functionName));
  20.199 +    }
  20.200 +
  20.201 +    void checkBeginFrameTimingScope(const char* functionName)
  20.202 +    {
  20.203 +        OVR_UNUSED1(functionName); // for Release build.
  20.204 +        OVR_ASSERT_LOG(BeginFrameTimingCalled == true,
  20.205 +                       ("%s called outside ovrHmd_BeginFrameTiming.", functionName));
  20.206 +    }
  20.207 +
  20.208 +	// Get properties by name.
  20.209 +    bool     getBoolValue(const char* propertyName, bool defaultVal);
  20.210 +    bool     setBoolValue(const char* propertyName, bool value);
  20.211 +    int      getIntValue(const char* propertyName, int defaultVal);
  20.212 +    bool     setIntValue(const char* propertyName, int value);
  20.213 +    float    getFloatValue(const char* propertyName, float defaultVal);
  20.214 +    bool     setFloatValue(const char* propertyName, float value);
  20.215 +	unsigned getFloatArray(const char* propertyName, float values[], unsigned arraySize);
  20.216 +    bool     setFloatArray(const char* propertyName, float values[], unsigned arraySize);
  20.217 +    const char* getString(const char* propertyName, const char* defaultVal);
  20.218 +    bool        setString(const char* propertyName, const char* value);
  20.219 +
  20.220 +	VirtualHmdId GetNetId() { return NetId; }
  20.221 +
  20.222 +public:
  20.223 +	Ptr<Profile>            pProfile;
  20.224 +    // Descriptor that gets allocated and returned to the user as ovrHmd.
  20.225 +    ovrHmdDesc*             pHmdDesc;
  20.226 +    // Window handle passed in AttachWindow.
  20.227 +    void*                   pWindow;
  20.228 +
  20.229 +	// Network
  20.230 +	Service::NetClient*     pClient;
  20.231 +	VirtualHmdId            NetId;
  20.232 +	HMDNetworkInfo          NetInfo;
  20.233 +
  20.234 +    // HMDInfo shouldn't change, as its string pointers are passed out.    
  20.235 +    HMDInfo                 OurHMDInfo;
  20.236 +
  20.237 +    const char*             pLastError;
  20.238 +
  20.239 +    // Caps enabled for the HMD.
  20.240 +    unsigned                EnabledHmdCaps;
  20.241 +    
  20.242 +    // Caps actually sent to the Sensor Service
  20.243 +    unsigned                EnabledServiceHmdCaps;
  20.244 +    
  20.245 +    // These are the flags actually applied to the Sensor device,
  20.246 +    // used to track whether SetDisplayReport calls are necessary.
  20.247 +    //unsigned                HmdCapsAppliedToSensor;
  20.248 +    
  20.249 +    // *** Sensor
  20.250 +    Tracking::CombinedSharedStateReader SharedStateReader;
  20.251 +    Tracking::SensorStateReader         TheSensorStateReader;
  20.252 +    Util::RecordStateReader             TheLatencyTestStateReader;
  20.253 +
  20.254 +    bool                    LatencyTestActive;
  20.255 +    unsigned char           LatencyTestDrawColor[3];
  20.256 +
  20.257 +    bool                    LatencyTest2Active;
  20.258 +    unsigned char           LatencyTest2DrawColor[3];
  20.259 +
  20.260 +    // Rendering part
  20.261 +    FrameTimeManager        TimeManager;
  20.262 +    LagStatsCalculator      LagStats;
  20.263 +    LatencyStatisticsCSV    LagStatsCSV;
  20.264 +    HMDRenderState          RenderState;
  20.265 +    Ptr<DistortionRenderer> pRenderer;
  20.266 +
  20.267 +    // Health and Safety Warning display.
  20.268 +    Ptr<HSWDisplay>         pHSWDisplay;
  20.269 +
  20.270 +    // Last timing value reported by BeginFrame.
  20.271 +    double                  LastFrameTimeSeconds;    
  20.272 +    // Last timing value reported by GetFrameTime. These are separate since the intended
  20.273 +    // use is from different threads. TBD: Move to FrameTimeManager? Make atomic?
  20.274 +    double                  LastGetFrameTimeSeconds;
  20.275 +
  20.276 +    // Last cached value returned by ovrHmd_GetString/ovrHmd_GetStringArray.
  20.277 +    char                    LastGetStringValue[256];
  20.278 +   
  20.279 +    // Debug flag set after ovrHmd_ConfigureRendering succeeds.
  20.280 +    bool                    RenderingConfigured;
  20.281 +    // Set after BeginFrame succeeds, and its corresponding thread id for debug checks.
  20.282 +    bool                    BeginFrameCalled;
  20.283 +    ThreadId                BeginFrameThreadId;    
  20.284 +    // Graphics functions are not re-entrant from other threads.
  20.285 +    ThreadChecker           RenderAPIThreadChecker;
  20.286 +    // 
  20.287 +    bool                    BeginFrameTimingCalled;
  20.288 +};
  20.289 +
  20.290 +
  20.291 +
  20.292 +
  20.293 +//I appreciate this isn't an idea place for this function prototype, but needed
  20.294 +//to be seen by OVR_CAPI.cpp and the various SDK renderers of CAPI,
  20.295 +//and have everything defined.  Please move to a better place if you know of one.
  20.296 +ovrBool ovrHmd_CreateDistortionMeshInternal( ovrHmdStruct *  hmd,
  20.297 +                                             ovrEyeType eyeType, ovrFovPort fov,
  20.298 +                                             unsigned int distortionCaps,
  20.299 +                                             ovrDistortionMesh *meshData,
  20.300 +											 float overrideEyeReliefIfNonZero=0 );
  20.301 +
  20.302 +
  20.303 +
  20.304 +
  20.305 +}} // namespace OVR::CAPI
  20.306 +
  20.307 +#endif // OVR_CAPI_HMDState_h
    21.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.2 +++ b/LibOVR/Src/CAPI/CAPI_HSWDisplay.cpp	Wed Jan 14 06:51:16 2015 +0200
    21.3 @@ -0,0 +1,482 @@
    21.4 +/************************************************************************************
    21.5 +
    21.6 +Filename    :   CAPI_HSWDisplay.cpp
    21.7 +Content     :   Implements Health and Safety Warning system.
    21.8 +Created     :   July 3, 2014
    21.9 +Authors     :   Paul Pedriana
   21.10 +
   21.11 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   21.12 +
   21.13 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
   21.14 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
   21.15 +which is provided at the time of installation or download, or which 
   21.16 +otherwise accompanies this software in either electronic or hard copy form.
   21.17 +
   21.18 +You may obtain a copy of the License at
   21.19 +
   21.20 +http://www.oculusvr.com/licenses/LICENSE-3.2 
   21.21 +
   21.22 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
   21.23 +distributed under the License is distributed on an "AS IS" BASIS,
   21.24 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   21.25 +See the License for the specific language governing permissions and
   21.26 +limitations under the License.
   21.27 +
   21.28 +************************************************************************************/
   21.29 +
   21.30 +#include "CAPI_HSWDisplay.h"
   21.31 +#include "CAPI_HMDState.h"
   21.32 +#include "../Kernel/OVR_Log.h"
   21.33 +#include "../Kernel/OVR_String.h"
   21.34 +#include "Textures/healthAndSafety.tga.h" // TGA file as a C array declaration.
   21.35 +#include <stdlib.h>
   21.36 +
   21.37 +//-------------------------------------------------------------------------------------
   21.38 +// ***** HSWDISPLAY_DEBUGGING
   21.39 +//
   21.40 +// Defined as 0 or 1. Enables debugging features of this module.
   21.41 +
   21.42 +#if !defined(HSWDISPLAY_DEBUGGING)
   21.43 +    #if defined(AUTHOR_PPEDRIANA)
   21.44 +        #define HSWDISPLAY_DEBUGGING 1
   21.45 +    #else
   21.46 +        #define HSWDISPLAY_DEBUGGING 0
   21.47 +    #endif
   21.48 +#endif
   21.49 +
   21.50 +#if HSWDISPLAY_DEBUGGING
   21.51 +    OVR_DISABLE_ALL_MSVC_WARNINGS()
   21.52 +    #include <winsock2.h>
   21.53 +    #include <Windows.h>
   21.54 +    OVR_RESTORE_ALL_MSVC_WARNINGS()
   21.55 +#endif
   21.56 +
   21.57 +OVR_DISABLE_MSVC_WARNING(4996) // "This function or variable may be unsafe..."
   21.58 +
   21.59 +
   21.60 +//-------------------------------------------------------------------------------------
   21.61 +// ***** HSWDISPLAY_DEFAULT_ENABLED
   21.62 +//
   21.63 +// Defined as 0 or 1. 1 is default. If 0 then by default HSWDisplay is disabled.
   21.64 +// Developers can set it to 0 to disable HSW display.
   21.65 +//
   21.66 +#if !defined(HSWDISPLAY_DEFAULT_ENABLED)
   21.67 +    #define HSWDISPLAY_DEFAULT_ENABLED 1
   21.68 +#endif
   21.69 +
   21.70 +
   21.71 +
   21.72 +//-------------------------------------------------------------------------------------
   21.73 +// ***** Experimental C API functions
   21.74 +//
   21.75 +
   21.76 +extern "C"
   21.77 +{
   21.78 +    OVR_EXPORT void ovrhmd_EnableHSWDisplaySDKRender(ovrHmd hmd, ovrBool enabled)
   21.79 +    {
   21.80 +        OVR::CAPI::HMDState* pHMDState = (OVR::CAPI::HMDState*)hmd->Handle;
   21.81 +
   21.82 +	    if (pHMDState)
   21.83 +	    {
   21.84 +            OVR::CAPI::HSWDisplay* pHSWDisplay = pHMDState->pHSWDisplay;
   21.85 +
   21.86 +            if(pHSWDisplay)
   21.87 +                pHSWDisplay->EnableRender((enabled == 0) ? false : true);
   21.88 +        }
   21.89 +    }
   21.90 +}
   21.91 +
   21.92 +
   21.93 +
   21.94 +
   21.95 +//-------------------------------------------------------------------------------------
   21.96 +// ***** HSWDisplay implementation
   21.97 +//
   21.98 +
   21.99 +namespace OVR { namespace CAPI {
  21.100 +
  21.101 +
  21.102 +static const time_t HSWDisplayTimeNever = (time_t)0; // Constant which denotes the time of "never", as in the display has never been shown yet.
  21.103 +
  21.104 +#define HSWDISPLAY_POLL_INTERVAL            0.400 // Seconds between polling for whether the display should be shown.
  21.105 +#define OVR_KEY_HSWDISPLAYLASTDISPLAYEDTIME "HASWLastDisplayedTime"
  21.106 +
  21.107 +
  21.108 +#if defined(OVR_BUILD_DEBUG)
  21.109 +    #define HSWDISPLAY_FIRST_DISMISSAL_TIME    4     // Earliest time in seconds until the user can dismiss the display.
  21.110 +    #define HSWDISPLAY_REGULAR_DISMISSAL_TIME  2
  21.111 +#else
  21.112 +    #define HSWDISPLAY_FIRST_DISMISSAL_TIME   15
  21.113 +    #define HSWDISPLAY_REGULAR_DISMISSAL_TIME  6
  21.114 +#endif
  21.115 +
  21.116 +
  21.117 +HSWDisplay::HSWDisplay(ovrRenderAPIType renderAPIType, ovrHmd hmd, const HMDRenderState& hmdRenderState)
  21.118 +  : Enabled(HSWDISPLAY_DEFAULT_ENABLED ? true : false),
  21.119 +    Displayed(false),
  21.120 +    SDKRendered(false),
  21.121 +    DismissRequested(false),
  21.122 +    RenderEnabled(true),
  21.123 +    UnloadGraphicsRequested(false),
  21.124 +    StartTime(0.0),
  21.125 +    DismissibleTime(0.0),
  21.126 +    LastPollTime(0.0),
  21.127 +    HMD(hmd), 
  21.128 +    HMDMounted(false),
  21.129 +    HMDNewlyMounted(false),
  21.130 +    RenderAPIType(renderAPIType), 
  21.131 +    RenderState(hmdRenderState),
  21.132 +    LastProfileName(),
  21.133 +    LastHSWTime(0)
  21.134 +{
  21.135 +}
  21.136 +
  21.137 +
  21.138 +HSWDisplay::~HSWDisplay()
  21.139 +{
  21.140 +    // To consider: assert that we are already shut down.
  21.141 +    HSWDisplay::Shutdown();
  21.142 +}
  21.143 +
  21.144 +
  21.145 +void HSWDisplay::Enable(bool enable)
  21.146 +{
  21.147 +    Enabled = enable;
  21.148 +
  21.149 +    if(!enable && Displayed) // If it's visible but should not be...
  21.150 +        Dismiss();
  21.151 +}
  21.152 +
  21.153 +
  21.154 +void HSWDisplay::EnableRender(bool enable)
  21.155 +{
  21.156 +    RenderEnabled = enable;
  21.157 +}
  21.158 +
  21.159 +
  21.160 +void HSWDisplay::Display()
  21.161 +{
  21.162 +    HSWDISPLAY_LOG(("[HSWDisplay] Display()"));
  21.163 +
  21.164 +    DisplayInternal();
  21.165 +
  21.166 +    HMDNewlyMounted = false;
  21.167 +    Displayed = true;
  21.168 +    SDKRendered = RenderEnabled;
  21.169 +    StartTime = ovr_GetTimeInSeconds();
  21.170 +
  21.171 +    const time_t lastDisplayedTime = HSWDisplay::GetCurrentProfileLastHSWTime();
  21.172 +    DismissibleTime = StartTime + ((lastDisplayedTime == HSWDisplayTimeNever) ? HSWDISPLAY_FIRST_DISMISSAL_TIME : HSWDISPLAY_REGULAR_DISMISSAL_TIME);
  21.173 +
  21.174 +    SetCurrentProfileLastHSWTime(time(NULL));
  21.175 +}
  21.176 +
  21.177 +
  21.178 +bool HSWDisplay::IsDisplayViewable() const
  21.179 +{
  21.180 +    // This function is called IsDisplayViewable, but currently it refers only to whether the 
  21.181 +    // HMD is mounted on the user's head.
  21.182 +
  21.183 +    return HMDMounted;
  21.184 +}
  21.185 +
  21.186 +
  21.187 +bool HSWDisplay::Dismiss()
  21.188 +{
  21.189 +    #if HSWDISPLAY_DEBUGGING && defined(OVR_OS_WIN32)
  21.190 +        if(GetKeyState(VK_SCROLL) & 0x0001) // If the scroll lock key is toggled on...
  21.191 +            return false;                   // Make it so that the display doesn't dismiss, so we can debug this.
  21.192 +    #endif
  21.193 +
  21.194 +    // If dismissal is not requested yet, mark it as such.
  21.195 +    bool newlyRequested = false;
  21.196 +
  21.197 +    if(!DismissRequested)
  21.198 +    {
  21.199 +        DismissRequested = true;
  21.200 +        newlyRequested = true;
  21.201 +    }
  21.202 +
  21.203 +    // If displayed and time has elapsed, do the dismissal.
  21.204 +    OVR_ASSERT(DismissibleTime <= (ovr_GetTimeInSeconds() + HSWDISPLAY_FIRST_DISMISSAL_TIME)); // Make sure the dismissal time is sane.
  21.205 +    if (Displayed && (ovr_GetTimeInSeconds() >= DismissibleTime))
  21.206 +    {
  21.207 +        DismissInternal();
  21.208 +        Displayed = false;
  21.209 +        DismissRequested = false;
  21.210 +        SDKRendered = false;
  21.211 +        return true;
  21.212 +    }
  21.213 +
  21.214 +    if(newlyRequested)
  21.215 +        { HSWDISPLAY_LOG(("[HSWDisplay] Dismiss(): Not permitted yet. Queued for timeout in %.1f seconds.", DismissibleTime - ovr_GetTimeInSeconds())); }
  21.216 +
  21.217 +    return false; // Cannot dismiss yet.
  21.218 +}
  21.219 +
  21.220 +
  21.221 +bool HSWDisplay::TickState(ovrHSWDisplayState *hswDisplayState, bool graphicsContext)
  21.222 +{
  21.223 +    bool newlyDisplayed = false;
  21.224 +    const double currentTime = ovr_GetTimeInSeconds();
  21.225 +
  21.226 +    // See if we need to be currently displayed. By design we automatically display but don't automatically dismiss.
  21.227 +    if (Displayed)
  21.228 +    {
  21.229 +        if (DismissRequested) // If dismiss was previously requested, see if it can be executed.
  21.230 +            Dismiss();
  21.231 +
  21.232 +        if (Displayed) // If not already dismissed above...
  21.233 +        {
  21.234 +            // We currently have the debug behavior that we permit dismiss very soon after launch.
  21.235 +            #if defined(OVR_BUILD_DEBUG)
  21.236 +                if(currentTime >= (StartTime + 2))
  21.237 +                {
  21.238 +                    DismissibleTime = StartTime;
  21.239 +                    //Dismiss();
  21.240 +                }
  21.241 +            #endif
  21.242 +        }
  21.243 +
  21.244 +        if (Displayed) // If not already dismissed above...
  21.245 +        {
  21.246 +            const ovrTrackingState ts = ((OVR::CAPI::HMDState*)HMD->Handle)->PredictedTrackingState(currentTime);
  21.247 +
  21.248 +            if (ts.StatusFlags & ovrStatus_OrientationTracked) // If the Accelerometer data is valid...
  21.249 +            {
  21.250 +				const OVR::Vector3f v(ts.HeadPose.LinearAcceleration.x, ts.HeadPose.LinearAcceleration.y, ts.HeadPose.LinearAcceleration.z);
  21.251 +
  21.252 +                const float minTapMagnitude = 350.0f; // Empirically determined by some testing.
  21.253 +
  21.254 +                if (v.LengthSq() > minTapMagnitude)
  21.255 +                    Dismiss(); // This will do nothing if the display is not present.
  21.256 +            }
  21.257 +        }
  21.258 +    }
  21.259 +    else if (Enabled && (currentTime >= (LastPollTime + HSWDISPLAY_POLL_INTERVAL)))
  21.260 +    {
  21.261 +        LastPollTime = currentTime;
  21.262 +
  21.263 +        // We need to display if any of the following are true:
  21.264 +        //     - The application is just started in Event Mode while the HMD is mounted (warning display would be viewable) and this app was not spawned from a launcher.
  21.265 +        //     - The current user has never seen the display yet while the HMD is mounted (warning display would be viewable).
  21.266 +        //     - The HMD is newly mounted (or the warning display is otherwise newly viewable).
  21.267 +        //     - The warning display hasn't shown in 24 hours (need to verify this as a requirement).
  21.268 +        // Event Mode refers to when the app is being run in a public demo event such as a trade show.
  21.269 +
  21.270 +        OVR::CAPI::HMDState* pHMDState = (OVR::CAPI::HMDState*)HMD->Handle;
  21.271 +
  21.272 +        if(pHMDState)
  21.273 +        {
  21.274 +            const time_t lastDisplayedTime = HSWDisplay::GetCurrentProfileLastHSWTime();
  21.275 +
  21.276 +            // We currently unilaterally set HMDMounted to true because we don't yet have the ability to detect this. To do: Implement this when possible.
  21.277 +            const bool previouslyMounted = HMDMounted;
  21.278 +            HMDMounted = true;
  21.279 +            HMDNewlyMounted = (!previouslyMounted && HMDMounted); // We set this back to false in the Display function or if the HMD is unmounted before then.
  21.280 +
  21.281 +            if((lastDisplayedTime == HSWDisplayTimeNever) || HMDNewlyMounted)
  21.282 +            {
  21.283 +                if(IsDisplayViewable()) // If the HMD is mounted and otherwise being viewed by the user...
  21.284 +                {
  21.285 +                    Display();
  21.286 +                    newlyDisplayed = true;
  21.287 +                }
  21.288 +            }
  21.289 +        }
  21.290 +    }
  21.291 +    else if(graphicsContext && UnloadGraphicsRequested)
  21.292 +    {
  21.293 +        UnloadGraphics();
  21.294 +        UnloadGraphicsRequested = false;
  21.295 +    }
  21.296 +
  21.297 +    if(hswDisplayState)
  21.298 +        GetState(hswDisplayState);
  21.299 +
  21.300 +    return newlyDisplayed;
  21.301 +}
  21.302 +
  21.303 +
  21.304 +void HSWDisplay::GetState(ovrHSWDisplayState *hswDisplayState) const
  21.305 +{
  21.306 +    // Return the state to the caller.
  21.307 +    OVR_ASSERT(hswDisplayState != NULL);
  21.308 +    if(hswDisplayState)
  21.309 +    {
  21.310 +        hswDisplayState->Displayed = Displayed;
  21.311 +        hswDisplayState->StartTime = StartTime;
  21.312 +        hswDisplayState->DismissibleTime = DismissibleTime;
  21.313 +    }
  21.314 +}
  21.315 +
  21.316 +
  21.317 +void HSWDisplay::Render(ovrEyeType eye, const ovrTexture* eyeTexture)
  21.318 +{
  21.319 +    SDKRendered = true;
  21.320 +    RenderInternal(eye, eyeTexture);
  21.321 +}
  21.322 +
  21.323 +// Persist the HSW settings on the server, since it needs to be synchronized across all applications.
  21.324 +// Note that the profile manager singleton cannot be used for this task because it overwrites the global
  21.325 +// settings for which the rift config tool is supposed to be authoritative.  That also would step on the
  21.326 +// settings generated by other rift apps.  The server settings, however, are synchronized for all apps
  21.327 +// and so are appropriate for this task.
  21.328 +static String getHSWTimeKey(const char* userName)
  21.329 +{
  21.330 +    String keyName = "server:";
  21.331 +    keyName += OVR_KEY_HSWDISPLAYLASTDISPLAYEDTIME;
  21.332 +    keyName += ":";
  21.333 +    if (userName)
  21.334 +    {
  21.335 +        keyName += userName;
  21.336 +    }
  21.337 +    return keyName;
  21.338 +}
  21.339 +
  21.340 +// Returns HSWDisplayTimeNever (0) if there is no profile or this is the first time we are seeing this profile.
  21.341 +time_t HSWDisplay::GetCurrentProfileLastHSWTime() const
  21.342 +{
  21.343 +    // We store the timeout value in HMDState's pProfile.
  21.344 +    HMDState* pHMDState = (HMDState*)HMD->Handle;
  21.345 +
  21.346 +    if (pHMDState)
  21.347 +    {
  21.348 +        const char* profileName = pHMDState->pProfile ? pHMDState->pProfile->GetValue(OVR_KEY_USER) : NULL;
  21.349 +
  21.350 +        if (profileName)
  21.351 +        {
  21.352 +            if (LastProfileName == profileName)
  21.353 +            {
  21.354 +                return LastHSWTime;
  21.355 +            }
  21.356 +
  21.357 +            LastProfileName = profileName;
  21.358 +            String timeKey = getHSWTimeKey(profileName);
  21.359 +            int lastTime = pHMDState->getIntValue(timeKey.ToCStr(), (int)HSWDisplayTimeNever);
  21.360 +
  21.361 +            LastHSWTime = lastTime;
  21.362 +            return lastTime;
  21.363 +        }
  21.364 +    }
  21.365 +
  21.366 +    return HSWDisplayTimeNever;
  21.367 +}
  21.368 +
  21.369 +void HSWDisplay::SetCurrentProfileLastHSWTime(time_t t)
  21.370 +{
  21.371 +    // The timeout value is stored in HMDState's pProfile.
  21.372 +    HMDState* pHMDState = (HMDState*)HMD->Handle;
  21.373 +
  21.374 +    if (pHMDState)
  21.375 +    {
  21.376 +        const char* profileName = pHMDState->pProfile ? pHMDState->pProfile->GetValue(OVR_KEY_USER) : NULL;
  21.377 +
  21.378 +        if (profileName)
  21.379 +        {
  21.380 +            LastProfileName = profileName;
  21.381 +            LastHSWTime = (int)t;
  21.382 +
  21.383 +            String timeKey = getHSWTimeKey(profileName);
  21.384 +            pHMDState->setIntValue(timeKey.ToCStr(), (int)t);
  21.385 +        }
  21.386 +    }
  21.387 +}
  21.388 +
  21.389 +
  21.390 +// Generates an appropriate stereo ortho projection matrix.
  21.391 +void HSWDisplay::GetOrthoProjection(const HMDRenderState& RenderState, Matrix4f OrthoProjection[2])
  21.392 +{
  21.393 +    Matrix4f perspectiveProjection[2];
  21.394 +    perspectiveProjection[0] = ovrMatrix4f_Projection(RenderState.EyeRenderDesc[0].Fov, 0.01f, 10000.f, true);
  21.395 +    perspectiveProjection[1] = ovrMatrix4f_Projection(RenderState.EyeRenderDesc[1].Fov, 0.01f, 10000.f, true);
  21.396 +
  21.397 +    const float    orthoDistance = HSWDISPLAY_DISTANCE; // This is meters from the camera (viewer) that we place the ortho plane.
  21.398 +    const Vector2f orthoScale0   = Vector2f(1.f) / Vector2f(RenderState.EyeRenderDesc[0].PixelsPerTanAngleAtCenter);
  21.399 +    const Vector2f orthoScale1   = Vector2f(1.f) / Vector2f(RenderState.EyeRenderDesc[1].PixelsPerTanAngleAtCenter);
  21.400 +    
  21.401 +    OrthoProjection[0] = ovrMatrix4f_OrthoSubProjection(perspectiveProjection[0], orthoScale0, orthoDistance, RenderState.EyeRenderDesc[0].HmdToEyeViewOffset.x);
  21.402 +    OrthoProjection[1] = ovrMatrix4f_OrthoSubProjection(perspectiveProjection[1], orthoScale1, orthoDistance, RenderState.EyeRenderDesc[1].HmdToEyeViewOffset.x);
  21.403 +}
  21.404 +
  21.405 +
  21.406 +const uint8_t* HSWDisplay::GetDefaultTexture(size_t& TextureSize)
  21.407 +{
  21.408 +    TextureSize = sizeof(healthAndSafety_tga);
  21.409 +    return healthAndSafety_tga;
  21.410 +}
  21.411 +
  21.412 +
  21.413 +
  21.414 +}} // namespace OVR::CAPI
  21.415 +
  21.416 +
  21.417 +
  21.418 +
  21.419 +//-------------------------------------------------------------------------------------
  21.420 +// ***** HSWDisplay factory
  21.421 +//
  21.422 +
  21.423 +#if defined (OVR_OS_WIN32)
  21.424 +    #define OVR_D3D_VERSION 9
  21.425 +    #include "D3D9/CAPI_D3D9_HSWDisplay.h"
  21.426 +    #undef  OVR_D3D_VERSION
  21.427 +
  21.428 +    #define OVR_D3D_VERSION 10
  21.429 +    #include "D3D1X/CAPI_D3D10_HSWDisplay.h"
  21.430 +    #undef  OVR_D3D_VERSION
  21.431 +
  21.432 +    #define OVR_D3D_VERSION 11
  21.433 +    #include "D3D1X/CAPI_D3D11_HSWDisplay.h"
  21.434 +    #undef  OVR_D3D_VERSION
  21.435 +#endif
  21.436 +
  21.437 +#include "GL/CAPI_GL_HSWDisplay.h"
  21.438 +
  21.439 +
  21.440 +OVR::CAPI::HSWDisplay* OVR::CAPI::HSWDisplay::Factory(ovrRenderAPIType apiType, ovrHmd hmd, const OVR::CAPI::HMDRenderState& renderState)
  21.441 +{
  21.442 +    OVR::CAPI::HSWDisplay* pHSWDisplay = NULL;
  21.443 +
  21.444 +    switch (apiType)
  21.445 +    {
  21.446 +        case ovrRenderAPI_None:
  21.447 +            pHSWDisplay = new OVR::CAPI::HSWDisplay(apiType, hmd, renderState);
  21.448 +            break;
  21.449 +
  21.450 +        case ovrRenderAPI_OpenGL:
  21.451 +            pHSWDisplay = new OVR::CAPI::GL::HSWDisplay(apiType, hmd, renderState);
  21.452 +            break;
  21.453 +
  21.454 +    #if defined(OVR_OS_WIN32)
  21.455 +        case ovrRenderAPI_D3D9:
  21.456 +            pHSWDisplay = new OVR::CAPI::D3D9::HSWDisplay(apiType, hmd, renderState);
  21.457 +            break;
  21.458 +
  21.459 +        case ovrRenderAPI_D3D10:
  21.460 +            pHSWDisplay = new OVR::CAPI::D3D10::HSWDisplay(apiType, hmd, renderState);
  21.461 +            break;
  21.462 +
  21.463 +        case ovrRenderAPI_D3D11:
  21.464 +            pHSWDisplay = new OVR::CAPI::D3D11::HSWDisplay(apiType, hmd, renderState);
  21.465 +            break;
  21.466 +    #else
  21.467 +        case ovrRenderAPI_D3D9:
  21.468 +        case ovrRenderAPI_D3D10:
  21.469 +        case ovrRenderAPI_D3D11: // Fall through
  21.470 +    #endif
  21.471 +
  21.472 +        // Handle unsupported cases.
  21.473 +        case ovrRenderAPI_Android_GLES:
  21.474 +        case ovrRenderAPI_Count: // This is not actually a type.
  21.475 +        default:
  21.476 +            break;
  21.477 +    }
  21.478 +
  21.479 +    return pHSWDisplay;
  21.480 +}
  21.481 +
  21.482 +
  21.483 +
  21.484 +
  21.485 +
    22.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    22.2 +++ b/LibOVR/Src/CAPI/CAPI_HSWDisplay.h	Wed Jan 14 06:51:16 2015 +0200
    22.3 @@ -0,0 +1,249 @@
    22.4 +/************************************************************************************
    22.5 +
    22.6 +Filename    :   CAPI_HSWDisplay.h
    22.7 +Content     :   Implements Health and Safety Warning system.
    22.8 +Created     :   July 3, 2014
    22.9 +Authors     :   Paul Pedriana
   22.10 +
   22.11 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   22.12 +
   22.13 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
   22.14 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
   22.15 +which is provided at the time of installation or download, or which 
   22.16 +otherwise accompanies this software in either electronic or hard copy form.
   22.17 +
   22.18 +You may obtain a copy of the License at
   22.19 +
   22.20 +http://www.oculusvr.com/licenses/LICENSE-3.2 
   22.21 +
   22.22 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
   22.23 +distributed under the License is distributed on an "AS IS" BASIS,
   22.24 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   22.25 +See the License for the specific language governing permissions and
   22.26 +limitations under the License.
   22.27 +
   22.28 +************************************************************************************/
   22.29 +
   22.30 +#ifndef OVR_CAPI_HSWDisplay_h
   22.31 +#define OVR_CAPI_HSWDisplay_h
   22.32 +
   22.33 +#include "../OVR_CAPI.h"
   22.34 +#include "CAPI_HMDRenderState.h"
   22.35 +#include <time.h>
   22.36 +
   22.37 +
   22.38 +
   22.39 +//-------------------------------------------------------------------------------------
   22.40 +// ***** HSWDISPLAY_LOG
   22.41 +//
   22.42 +// Debug log wrapper.
   22.43 +
   22.44 +#if !defined(HSWDISPLAY_LOG_ENABLED)
   22.45 +    #ifdef OVR_BUILD_DEBUG
   22.46 +        #define HSWDISPLAY_LOG_ENABLED 1
   22.47 +    #else
   22.48 +        #define HSWDISPLAY_LOG_ENABLED 0
   22.49 +    #endif
   22.50 +#endif
   22.51 +
   22.52 +#if HSWDISPLAY_LOG_ENABLED
   22.53 +    #define HSWDISPLAY_LOG(...) OVR_DEBUG_LOG(__VA_ARGS__)
   22.54 +#else
   22.55 +    #define HSWDISPLAY_LOG(...)
   22.56 +#endif
   22.57 +
   22.58 +
   22.59 +//-------------------------------------------------------------------------------------
   22.60 +// ***** HSWDISPLAY_DISTANCE
   22.61 +//
   22.62 +// Floating point value in the range of ~0.75 to ~3.0 which controls the distance 
   22.63 +// (in meters) of the display from the viewer.
   22.64 +
   22.65 +#ifndef HSWDISPLAY_DISTANCE
   22.66 +    #define HSWDISPLAY_DISTANCE 1.5f
   22.67 +#endif
   22.68 +
   22.69 +
   22.70 +//-------------------------------------------------------------------------------------
   22.71 +// ***** HSWDISPLAY_SCALE
   22.72 +//
   22.73 +// Floating point value in the range of ~0.1 to ~2.0 which controls the size scale of the 
   22.74 +// SDK-rendered HSW display. The value is an arbitrary relative value, though this may 
   22.75 +// change in future SDK versions.
   22.76 +
   22.77 +#ifndef HSWDISPLAY_SCALE
   22.78 +    #define HSWDISPLAY_SCALE 0.92f
   22.79 +#endif
   22.80 +
   22.81 +
   22.82 +
   22.83 +
   22.84 +//-------------------------------------------------------------------------------------
   22.85 +// ***** Experimental C API functions
   22.86 +//
   22.87 +// These are currently not formally supported and may be promoted to the formal C API
   22.88 +// or may be removed in the future.
   22.89 +
   22.90 +extern "C"
   22.91 +{
   22.92 +    // Normally if an application uses SDK-based distortion rendering 
   22.93 +    // (ovrHmd_BeginFrame / ovrHmd_EndFrame) then the SDK also takes care of 
   22.94 +    // drawing the health and safety warning. If an application is using 
   22.95 +    // SDK-based rendering but wants to draw the warning display itself, 
   22.96 +    // it call this function with enabled set to false.
   22.97 +    OVR_EXPORT void ovrhmd_EnableHSWDisplaySDKRender(ovrHmd hmd, ovrBool enabled);
   22.98 +}
   22.99 +
  22.100 +
  22.101 +namespace OVR { namespace CAPI {
  22.102 +
  22.103 +
  22.104 +//-------------------------------------------------------------------------------------
  22.105 +// ***** CAPI::HSWDisplay
  22.106 +//
  22.107 +// Note: This will be renamed to HSWDisplay in the future.
  22.108 +//
  22.109 +// Implements the logic for the Health and Safety (HAS) warning display. Primarily this
  22.110 +// is two things: providing information about whether the warning needs to be currently
  22.111 +// displayed, and implementing the display itself. 
  22.112 +//
  22.113 +// An HSWDisplay is associated 1:1 with an HMD. There can be at most one HSWDisplay 
  22.114 +// being displayed on an HMD at a time. If a warning needs to be displayed while an  
  22.115 +// existing one is present, it replaces the existing one. 
  22.116 +//
  22.117 +// Notes
  22.118 +//    Warnings are displayed per HMD (head mounted display).
  22.119 +//    The app can have multiple HMDs.
  22.120 +//    There can be multiple users of a given HMD over time, with each identified by a different user profile.
  22.121 +//    There can be multiple apps using HMDs.
  22.122 +//
  22.123 +//    Shows upon first entering a VR application (or VR mode in an application) when in Event Mode (e.g. trade show).
  22.124 +//    Shows upon each wearing of the HMD.
  22.125 +//    If the user profile is switched while display is active, the display must restart.
  22.126 +//    Doesn't show in app when app was started by a launcher app.
  22.127 +//
  22.128 +//    First display ever (per profile): 15 seconds until the display can be dismissed.
  22.129 +//    Subsequent displays: 6 seconds until the display can be dismissed. Per profile.
  22.130 +//    Dismissing occurs via HMD tap, designated keypress, gaze detection on OK button for N seconds, 
  22.131 +//        and possibly via an input gesture in the future.
  22.132 +//
  22.133 +//    If the warning fades out upon completion, the fade out should begin after the full display time has elapsed, 
  22.134 +//        but it needs to avoid interfering (e.g. obscuring) with the application. This likely means the application 
  22.135 +//        would need to put in a couple seconds delay to allow the fade to complete.
  22.136 +//    Ideally we'd handle the case of a user switching HMDs and not needing to see the warning again.
  22.137 +
  22.138 +class HSWDisplay : public RefCountBase<HSWDisplay>
  22.139 +{
  22.140 +public:
  22.141 +    HSWDisplay(ovrRenderAPIType api, ovrHmd hmd, const HMDRenderState& renderState);
  22.142 +
  22.143 +    virtual ~HSWDisplay();
  22.144 +
  22.145 +    // Must be called after construction and before use.
  22.146 +    virtual bool Initialize(const ovrRenderAPIConfig*)
  22.147 +        { return true; }
  22.148 +
  22.149 +    // Must be called before destruction.
  22.150 +    virtual void Shutdown() {}
  22.151 +
  22.152 +    // Enables or disables the HSW display system. It may be disabled only for development uses.
  22.153 +    // It is enabled by default. 
  22.154 +    void Enable(bool enable);
  22.155 +
  22.156 +    // Enables or disables our internal rendering when Render is called. If set to false then the 
  22.157 +    // application is expected to implement drawing of the display when Displayed is true.
  22.158 +    // It is enabled by default. 
  22.159 +    void EnableRender(bool enable);
  22.160 +
  22.161 +    // Triggers a display of the HSW display for the associated HMD. Restarts the display if 
  22.162 +    // the warning is already being displayed. 
  22.163 +    void Display();
  22.164 +
  22.165 +    // This function should be called per HMD every frame in order to give this class processing time. 
  22.166 +    // Writes the new state to newHSWDisplayState if it's non-NULL.
  22.167 +    // The graphicsContext argument indicates if the Tick is occurring within a graphics context and
  22.168 +    // thus if graphics operations are allowed during the TickState call.
  22.169 +    // Returns true if the new state results in a required warning display (ovrHSWDisplayState::Displayed became true).
  22.170 +    bool TickState(ovrHSWDisplayState *newHSWDisplayState = NULL, bool graphicsContext = false);
  22.171 +
  22.172 +    // Gets the current state of the HSW display. 
  22.173 +    // Corresponds to ovrhmd_GetHSWDisplayState.
  22.174 +    void GetState(ovrHSWDisplayState *hasWarningState) const;
  22.175 +
  22.176 +    // Removes the HSW display display if the minimum dismissal time has occurred. 
  22.177 +    // Returns true if the warning display could be dissmissed or was not displayed at the time of the call.
  22.178 +    // Corresponds to ovrhmd_DismissHSWDisplay.
  22.179 +    bool Dismiss();
  22.180 +
  22.181 +    // Returns true if the HMD appears to be currently mounted and in a state that a 
  22.182 +    // warning display would be viewable.
  22.183 +    bool IsDisplayViewable() const;
  22.184 +
  22.185 +    // Draws the warning to the eye texture(s). This must be done at the end of a 
  22.186 +    // frame but prior to executing the distortion rendering of the eye textures. 
  22.187 +    virtual void Render(ovrEyeType, const ovrTexture*);
  22.188 +
  22.189 +    // Resets the current profile's HAS settings (e.g. to act as if the user has never seen the HSW display before).
  22.190 +    void ResetProfileData();
  22.191 +
  22.192 +    // Returns the ovrRenderAPIType. This is essentially the same as RTTI, as it's indicating what subclass
  22.193 +    // is being used for this.
  22.194 +    ovrRenderAPIType GetRenderAPIType() const // e.g. ovrRenderAPI_D3D11
  22.195 +        { return RenderAPIType; }
  22.196 +
  22.197 +    // Returns the required HSW display text for the current profile's locale. 
  22.198 +    // Useful for implementing custom warning displays. Returns the required strlen 
  22.199 +    // of the text, and thus success is indicated by a return value < strCapacity.
  22.200 +    // size_t GetText(char *str, size_t strCapacity);
  22.201 +
  22.202 +    // Creates and constructs an instance of an HSWDisplay subclass based on the API type.
  22.203 +    static HSWDisplay* Factory(ovrRenderAPIType apiType, ovrHmd hmd, const HMDRenderState& renderState);
  22.204 +
  22.205 +private:
  22.206 +    OVR_NON_COPYABLE(HSWDisplay)
  22.207 +
  22.208 +protected:
  22.209 +    virtual void DisplayInternal() {}
  22.210 +    virtual void DismissInternal() {}
  22.211 +    virtual void RenderInternal(ovrEyeType, const ovrTexture*) {}
  22.212 +    virtual void UnloadGraphics() {}
  22.213 +    virtual void LoadGraphics() {}
  22.214 +
  22.215 +    // Profile functionality
  22.216 +    time_t GetCurrentProfileLastHSWTime() const;
  22.217 +    void   SetCurrentProfileLastHSWTime(time_t t);
  22.218 +
  22.219 +    // Generates an appropriate stereo ortho projection matrix.
  22.220 +    static void GetOrthoProjection(const HMDRenderState& RenderState, Matrix4f OrthoProjection[2]);
  22.221 +
  22.222 +    // Returns the default HSW display texture data.
  22.223 +    static const uint8_t* GetDefaultTexture(size_t& TextureSize);
  22.224 +
  22.225 +protected:
  22.226 +    bool                   Enabled;                 // If true then the HSW display system is enabled. True by default.
  22.227 +    bool                   Displayed;               // If true then the warning is currently visible and the following variables have meaning. Else there is no warning being displayed for this application on the given HMD.
  22.228 +    bool                   SDKRendered;             // If true then the display is being rendered by the SDK as opposed to the application.
  22.229 +    bool                   DismissRequested;        // If true then the warning has been requested to be hidden.
  22.230 +    bool                   RenderEnabled;           // If true then we handle rendering when Render is called. Else we skip it and assume the application is otherwise handling it itself.
  22.231 +    bool                   UnloadGraphicsRequested; // If true then an unload of graphics was requested. This acts as a message from the main thread to the drawing thread so that the unload happens in the expected thread.
  22.232 +    double                 StartTime;               // Absolute time when the warning was first displayed. See ovr_GetTimeInSeconds().
  22.233 +    double                 DismissibleTime;         // Absolute time when the warning can be dismissed.
  22.234 +    double                 LastPollTime;            // Used to prevent us from polling the required display state every frame but rather more like every 200 milliseconds.
  22.235 +    const ovrHmd           HMD;                     // The HMDState this HSWDisplay instance corresponds to.
  22.236 +    mutable bool           HMDMounted;              // True if the HMD was most recently found to be mounted. We need this in order to maintain HMDNewlyMounted.
  22.237 +    mutable bool           HMDNewlyMounted;         // True if HMDMounted has transitioned from false to true. We need this in order to tell if the HMD was recently mounted so we can display the HSW display.
  22.238 +    const ovrRenderAPIType RenderAPIType;           // e.g. ovrRenderAPI_D3D11
  22.239 +    const HMDRenderState&  RenderState;             // Information about the rendering setup.
  22.240 +
  22.241 +    // Settings cache
  22.242 +    mutable String         LastProfileName;
  22.243 +    mutable int            LastHSWTime;
  22.244 +
  22.245 +}; // class HSWDisplay
  22.246 +
  22.247 +
  22.248 +
  22.249 +}} // namespace OVR::CAPI
  22.250 +
  22.251 +
  22.252 +#endif // OVR_CAPI_HSWDisplay_h
    23.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    23.2 +++ b/LibOVR/Src/CAPI/CAPI_LatencyStatistics.cpp	Wed Jan 14 06:51:16 2015 +0200
    23.3 @@ -0,0 +1,316 @@
    23.4 +/************************************************************************************
    23.5 +
    23.6 +Filename    :   CAPI_LatencyStatistics.cpp
    23.7 +Content     :   Record latency statistics during rendering
    23.8 +Created     :   Sept 23, 2014
    23.9 +Authors     :   Chris Taylor, Kevin Jenkins
   23.10 +
   23.11 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   23.12 +
   23.13 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
   23.14 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
   23.15 +which is provided at the time of installation or download, or which 
   23.16 +otherwise accompanies this software in either electronic or hard copy form.
   23.17 +
   23.18 +You may obtain a copy of the License at
   23.19 +
   23.20 +http://www.oculusvr.com/licenses/LICENSE-3.2 
   23.21 +
   23.22 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
   23.23 +distributed under the License is distributed on an "AS IS" BASIS,
   23.24 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   23.25 +See the License for the specific language governing permissions and
   23.26 +limitations under the License.
   23.27 +
   23.28 +************************************************************************************/
   23.29 +
   23.30 +#include "CAPI_LatencyStatistics.h"
   23.31 +
   23.32 +#include "../Kernel/OVR_Log.h"
   23.33 +#include "../Kernel/OVR_Threads.h"
   23.34 +#include "../Util/Util_SystemInfo.h"
   23.35 +
   23.36 +namespace OVR { namespace CAPI {
   23.37 +
   23.38 +//-----------------------------------------------------------------------------
   23.39 +// ***** LatencyStatisticsObserver
   23.40 +
   23.41 +LatencyStatisticsCSV::LatencyStatisticsCSV()
   23.42 +{
   23.43 +}
   23.44 +
   23.45 +LatencyStatisticsCSV::~LatencyStatisticsCSV()
   23.46 +{
   23.47 +    Stop();
   23.48 +}
   23.49 +
   23.50 +bool LatencyStatisticsCSV::Start(String fileName, String userData1)
   23.51 +{
   23.52 +    if (_File.IsValid())
   23.53 +    {
   23.54 +        if (fileName == FileName)
   23.55 +        {
   23.56 +            UserData1 = userData1;
   23.57 +            return true;
   23.58 +        }
   23.59 +        else
   23.60 +        {
   23.61 +            Stop();
   23.62 +        }
   23.63 +    }
   23.64 +
   23.65 +    OVR::String basePath = OVR::GetBaseOVRPath(true);
   23.66 +    OVR::String path = basePath;
   23.67 +    path.AppendString("\\");
   23.68 +    path.AppendString(fileName);
   23.69 +    OS = OVR::Util::OSAsString();
   23.70 +    OSVersion = OVR::Util::OSVersionAsString();
   23.71 +#if defined (OVR_OS_WIN64) || defined (OVR_OS_WIN32)
   23.72 +    ProcessInfo = OVR::Util::GetProcessInfo();
   23.73 +    DisplayDriverVersion = OVR::Util::GetDisplayDriverVersion();
   23.74 +    CameraDriverVersion = OVR::Util::GetCameraDriverVersion();
   23.75 +    OVR::Array< OVR::String > gpus;
   23.76 +    OVR::Util::GetGraphicsCardList(gpus);
   23.77 +    StringBuffer sb;
   23.78 +    size_t gpuIdx;
   23.79 +    for (gpuIdx = 0; gpuIdx < gpus.GetSize(); gpuIdx++)
   23.80 +    {
   23.81 +        sb.AppendString(gpus[gpuIdx]);
   23.82 +        if (gpuIdx + 1 < gpus.GetSize())
   23.83 +            sb.AppendString("; ");
   23.84 +    }
   23.85 +    GPUVersion = sb;
   23.86 +#endif
   23.87 +    Guid = OVR::Util::GetGuidString();
   23.88 +
   23.89 +    if (!_File.Open(path, OVR::File::Open_Write, OVR::File::Mode_Write))
   23.90 +    {
   23.91 +        _File.Create(path, OVR::File::Mode_Write);
   23.92 +        WriteHeaderV1();
   23.93 +    }
   23.94 +    else
   23.95 +    {
   23.96 +        _File.Seek(0, FileConstants::Seek_End);
   23.97 +    }
   23.98 +
   23.99 +    if (_File.IsValid())
  23.100 +    {
  23.101 +        UserData1 = userData1;
  23.102 +        FileName = fileName;
  23.103 +        _Observer.SetHandler(LatencyStatisticsSlot::FromMember<LatencyStatisticsCSV, &LatencyStatisticsCSV::OnResults>(this));
  23.104 +
  23.105 +        return true;
  23.106 +    }
  23.107 +
  23.108 +    return false;
  23.109 +}
  23.110 +bool LatencyStatisticsCSV::Stop()
  23.111 +{
  23.112 +    if (_File.IsValid())
  23.113 +    {
  23.114 +        _File.Flush();
  23.115 +        _File.Close();
  23.116 +        _Observer.ReleaseAll();
  23.117 +
  23.118 +        Guid.Clear();
  23.119 +        FileName.Clear();
  23.120 +        return true;
  23.121 +    }
  23.122 +    return false;
  23.123 +}
  23.124 +void LatencyStatisticsCSV::WriteHeaderV1()
  23.125 +{
  23.126 +    if (_File.IsValid())
  23.127 +    {
  23.128 +        // Write header if creating the file
  23.129 +        const char *str = "GUID,OS,OSVersion,Process,DisplayDriver,CameraDriver,GPU,Time,Interval,FPS,EndFrameExecutionTime,LatencyRender,LatencyTimewarp,LatencyPostPresent,LatencyVisionProc,LatencyVisionFrame,UserData1\n";
  23.130 +        _File.Write((const uint8_t *) str, (int)OVR_strlen(str));
  23.131 +    }
  23.132 +}
  23.133 +
  23.134 +void LatencyStatisticsCSV::WriteResultsV1(LatencyStatisticsResults *results)
  23.135 +{
  23.136 +    if (_File.IsValid())
  23.137 +    {
  23.138 +        char str[512];
  23.139 +        OVR_sprintf(str, sizeof(str),
  23.140 +            "%s,%s,%s,%s,%s,%s,%s,%f,%f,%f,%f,%f,%f,%f,%f,%f,%s\n",
  23.141 +            Guid.ToCStr(),
  23.142 +            OS.ToCStr(),
  23.143 +            OSVersion.ToCStr(),
  23.144 +            ProcessInfo.ToCStr(),
  23.145 +            DisplayDriverVersion.ToCStr(),
  23.146 +            CameraDriverVersion.ToCStr(),
  23.147 +            GPUVersion.ToCStr(),
  23.148 +            ovr_GetTimeInSeconds(),
  23.149 +            results->IntervalSeconds,
  23.150 +            results->FPS,
  23.151 +            results->EndFrameExecutionTime,
  23.152 +            results->LatencyRender,
  23.153 +            results->LatencyTimewarp,
  23.154 +            results->LatencyPostPresent,
  23.155 +            results->LatencyVisionProc,
  23.156 +            results->LatencyVisionFrame,
  23.157 +            UserData1.ToCStr());
  23.158 +        str[sizeof(str)-1] = 0;
  23.159 +        _File.Write((const uint8_t *)str, (int)OVR_strlen(str));
  23.160 +    }
  23.161 +}
  23.162 +void LatencyStatisticsCSV::OnResults(LatencyStatisticsResults *results)
  23.163 +{
  23.164 +    WriteResultsV1(results);
  23.165 +}
  23.166 +//-------------------------------------------------------------------------------------
  23.167 +// ***** LatencyStatisticsCalculator
  23.168 +    
  23.169 +LagStatsCalculator::LagStatsCalculator()
  23.170 +{
  23.171 +    resetPerfStats();
  23.172 +}
  23.173 +
  23.174 +void LagStatsCalculator::resetPerfStats(double resetTime)
  23.175 +{
  23.176 +    EndFrameStartTime = 0.;
  23.177 +    EndFrameEndTime = 0.;
  23.178 +
  23.179 +    LastCameraFrameCounter = ~(uint32_t)0;
  23.180 +
  23.181 +    EpochBegin = resetTime; // Set epoch start to now
  23.182 +
  23.183 +    FrameCount = 0;
  23.184 +    //EndFrameSum = 0.;
  23.185 +
  23.186 +    //VisionProcSum = 0.;
  23.187 +    //VisionLagSum = 0.;
  23.188 +    VisionFrames = 0;
  23.189 +
  23.190 +    //for (int i = 0; i < 3; ++i)
  23.191 +    //{
  23.192 +    //    LatencyData[i] = 0.f;
  23.193 +    //    LatencySum[i] = 0.;
  23.194 +    //}
  23.195 +
  23.196 +    latencyStatisticsData.EndFrameExecutionTime = 0;
  23.197 +    latencyStatisticsData.LatencyRender = 0;
  23.198 +    latencyStatisticsData.LatencyTimewarp = 0;
  23.199 +    latencyStatisticsData.LatencyPostPresent = 0;
  23.200 +    latencyStatisticsData.LatencyVisionProc = 0;
  23.201 +    latencyStatisticsData.LatencyVisionFrame = 0;
  23.202 +}
  23.203 +
  23.204 +void LagStatsCalculator::GetLatestResults(LatencyStatisticsResults* results)
  23.205 +{
  23.206 +    *results = Results.GetState();
  23.207 +}
  23.208 +void LagStatsCalculator::AddResultsObserver(ObserverScope<LatencyStatisticsSlot> *calculateResultsObserver)
  23.209 +{
  23.210 +    Lock::Locker locker(&calculateResultsLock);
  23.211 +    calculateResultsObserver->GetPtr()->Observe(calculateResultsSubject);
  23.212 +}
  23.213 +void LagStatsCalculator::InstrumentEndFrameStart(double timestamp)
  23.214 +{
  23.215 +    EndFrameStartTime = timestamp;
  23.216 +}
  23.217 +
  23.218 +void LagStatsCalculator::InstrumentLatencyTimings(FrameTimeManager& ftm)
  23.219 +{
  23.220 +    //latencies[0] = (float)RenderLatencySeconds;
  23.221 +    //latencies[1] = (float)TimewarpLatencySeconds;
  23.222 +    //latencies[2] = (float)FrameDeltas.GetMedianTimeDelta();
  23.223 +
  23.224 +    // Note: This assumes that it is called right before InstrumentEndFrameEnd()
  23.225 +	float latencyRender, latencyTimewarp, latencyPostPresent;
  23.226 +    ftm.GetLatencyTimings(latencyRender, latencyTimewarp, latencyPostPresent);
  23.227 +	latencyStatisticsData.LatencyRender += latencyRender;
  23.228 +	latencyStatisticsData.LatencyTimewarp += latencyTimewarp;
  23.229 +	latencyStatisticsData.LatencyPostPresent += latencyPostPresent;
  23.230 +}
  23.231 +
  23.232 +void LagStatsCalculator::InstrumentEndFrameEnd(double timestamp)
  23.233 +{
  23.234 +    EndFrameEndTime = timestamp;
  23.235 +
  23.236 +    calculateResults();
  23.237 +}
  23.238 +
  23.239 +void LagStatsCalculator::InstrumentEyePose(const ovrTrackingState& state)
  23.240 +{
  23.241 +    // If the camera frame counter has rolled,
  23.242 +    if (LastCameraFrameCounter != state.LastCameraFrameCounter)
  23.243 +    {
  23.244 +        // Accumulate eye pose data
  23.245 +        if (state.StatusFlags != 0)
  23.246 +        {
  23.247 +            latencyStatisticsData.LatencyVisionProc += state.LastVisionProcessingTime;
  23.248 +            latencyStatisticsData.LatencyVisionFrame += state.LastVisionFrameLatency;
  23.249 +        }
  23.250 +        ++VisionFrames;
  23.251 +
  23.252 +        LastCameraFrameCounter = state.LastCameraFrameCounter;
  23.253 +    }
  23.254 +}
  23.255 +
  23.256 +// Note: Currently assumes this is being called from OnEndFrameEnd() above.
  23.257 +void LagStatsCalculator::calculateResults()
  23.258 +{
  23.259 +    // Calculate time in the current epoch so far
  23.260 +    double intervalDuration = EndFrameEndTime - EpochBegin;
  23.261 +
  23.262 +    // If stats should be reset due to inactivity,
  23.263 +    if (intervalDuration >= OVR_LAG_STATS_RESET_LIMIT)
  23.264 +    {
  23.265 +        resetPerfStats(EndFrameEndTime);
  23.266 +        return;
  23.267 +    }
  23.268 +
  23.269 +    // Calculate EndFrame() duration
  23.270 +    double endFrameDuration = EndFrameEndTime - EndFrameStartTime;
  23.271 +
  23.272 +    // Incorporate EndFrame() duration into the running sum
  23.273 +    latencyStatisticsData.EndFrameExecutionTime += endFrameDuration;
  23.274 +
  23.275 +    //for (int i = 0; i < 3; ++i)
  23.276 +    //{
  23.277 +    //    LatencySum[i] += LatencyData[i];
  23.278 +    //}
  23.279 +
  23.280 +    // Increment frame counter
  23.281 +    ++FrameCount;
  23.282 +
  23.283 +    // If enough time has passed,
  23.284 +    if (intervalDuration >= OVR_LAG_STATS_EPOCH)
  23.285 +    {
  23.286 +        LatencyStatisticsResults results;
  23.287 +
  23.288 +        float invFrameCount = 1.0f / (float) FrameCount;
  23.289 +
  23.290 +        // EndFrame() instrumentation
  23.291 +        results.IntervalSeconds = intervalDuration;
  23.292 +        results.FPS = FrameCount / intervalDuration;
  23.293 +        results.EndFrameExecutionTime = latencyStatisticsData.EndFrameExecutionTime * invFrameCount;
  23.294 +
  23.295 +        // Latency data
  23.296 +        results.LatencyRender = latencyStatisticsData.LatencyRender * invFrameCount;
  23.297 +        results.LatencyTimewarp = latencyStatisticsData.LatencyTimewarp * invFrameCount;
  23.298 +        results.LatencyPostPresent = latencyStatisticsData.LatencyPostPresent * invFrameCount;
  23.299 +
  23.300 +        double invVisionFrameCount = 1. / VisionFrames;
  23.301 +
  23.302 +        // Eye pose instrumentation
  23.303 +        results.LatencyVisionProc = latencyStatisticsData.LatencyVisionProc * invVisionFrameCount;
  23.304 +        results.LatencyVisionFrame = latencyStatisticsData.LatencyVisionFrame * invVisionFrameCount;
  23.305 +
  23.306 +        Results.SetState(results);
  23.307 +
  23.308 +        {
  23.309 +            Lock::Locker locker(&calculateResultsLock);
  23.310 +            calculateResultsSubject.GetPtr()->Call(&results);
  23.311 +        }
  23.312 +
  23.313 +        // Reset for next frame
  23.314 +        resetPerfStats();
  23.315 +    }
  23.316 +}
  23.317 +
  23.318 +
  23.319 +}} // namespace OVR::CAPI
    24.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    24.2 +++ b/LibOVR/Src/CAPI/CAPI_LatencyStatistics.h	Wed Jan 14 06:51:16 2015 +0200
    24.3 @@ -0,0 +1,178 @@
    24.4 +/************************************************************************************
    24.5 +
    24.6 +Filename    :   CAPI_LatencyStatistics.h
    24.7 +Content     :   Record latency statistics during rendering
    24.8 +Created     :   Sept 23, 2014
    24.9 +Authors     :   Chris Taylor, Kevin Jenkins
   24.10 +
   24.11 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   24.12 +
   24.13 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
   24.14 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
   24.15 +which is provided at the time of installation or download, or which 
   24.16 +otherwise accompanies this software in either electronic or hard copy form.
   24.17 +
   24.18 +You may obtain a copy of the License at
   24.19 +
   24.20 +http://www.oculusvr.com/licenses/LICENSE-3.2 
   24.21 +
   24.22 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
   24.23 +distributed under the License is distributed on an "AS IS" BASIS,
   24.24 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   24.25 +See the License for the specific language governing permissions and
   24.26 +limitations under the License.
   24.27 +
   24.28 +************************************************************************************/
   24.29 +
   24.30 +#ifndef OVR_CAPI_LatencyStatistics_h
   24.31 +#define OVR_CAPI_LatencyStatistics_h
   24.32 +
   24.33 +#include "../OVR_CAPI.h"
   24.34 +#include "../Kernel/OVR_Timer.h"
   24.35 +#include "../Kernel/OVR_Lockless.h"
   24.36 +#include "../Kernel/OVR_SysFile.h"
   24.37 +#include "CAPI_FrameTimeManager.h"
   24.38 +
   24.39 +namespace OVR { namespace CAPI {
   24.40 +
   24.41 +
   24.42 +// Define epoch period for lag statistics
   24.43 +#define OVR_LAG_STATS_EPOCH 1.0 /* seconds */
   24.44 +// Define seconds without frames before resetting stats
   24.45 +#define OVR_LAG_STATS_RESET_LIMIT 2.0 /* seconds */
   24.46 +
   24.47 +
   24.48 +//-------------------------------------------------------------------------------------
   24.49 +// ***** LatencyStatisticsResults
   24.50 +
   24.51 +// Results from statistics collection
   24.52 +struct LatencyStatisticsResults
   24.53 +{
   24.54 +    // Number of seconds of data represented by these statistics.
   24.55 +    double IntervalSeconds;
   24.56 +
   24.57 +    // Frames per second during the epoch.
   24.58 +    double FPS;
   24.59 +
   24.60 +    // Measures average time for EndFrame() call over each of the frames.
   24.61 +    double EndFrameExecutionTime;
   24.62 +
   24.63 +    // Measures the time between first scanline and first pose request before app starts rendering eyes.
   24.64 +    float LatencyRender;
   24.65 +
   24.66 +    // Measures the time between first scanline and distortion/timewarp rendering.
   24.67 +    float LatencyTimewarp;
   24.68 +
   24.69 +    // Time between Present() call and photon emission from first scanline of screen
   24.70 +    float LatencyPostPresent;
   24.71 +
   24.72 +    // Measures the time from receiving the camera frame until vision CPU processing completes.
   24.73 +    double LatencyVisionProc;
   24.74 +
   24.75 +    // Measures the time from exposure until the pose is available for the frame, including processing time.
   24.76 +    double LatencyVisionFrame;
   24.77 +};
   24.78 +
   24.79 +//-----------------------------------------------------------------------------
   24.80 +typedef Delegate1<void, LatencyStatisticsResults*> LatencyStatisticsSlot;
   24.81 +
   24.82 +// ***** LatencyStatisticsObserver
   24.83 +class LatencyStatisticsCSV
   24.84 +{
   24.85 +public:
   24.86 +    LatencyStatisticsCSV();
   24.87 +    ~LatencyStatisticsCSV();
   24.88 +    bool Start(String fileName, String userData1);
   24.89 +    bool Stop();
   24.90 +    void OnResults(LatencyStatisticsResults *results);
   24.91 +
   24.92 +    // Internal
   24.93 +    void WriteHeaderV1();
   24.94 +    void WriteResultsV1(LatencyStatisticsResults *results);
   24.95 +    ObserverScope<LatencyStatisticsSlot>* GetObserver() { return &_Observer; }
   24.96 +
   24.97 +protected:
   24.98 +    ObserverScope<LatencyStatisticsSlot> _Observer;
   24.99 +    String Guid, UserData1;
  24.100 +    String FileName;
  24.101 +    OVR::SysFile _File;
  24.102 +    String OS, OSVersion, ProcessInfo, DisplayDriverVersion, CameraDriverVersion, GPUVersion;
  24.103 +};
  24.104 +
  24.105 +//-----------------------------------------------------------------------------
  24.106 +// ***** LatencyStatisticsCalculator
  24.107 +
  24.108 +// Calculator for latency statistics
  24.109 +class LagStatsCalculator
  24.110 +{
  24.111 +    // Statistics instrumentation inputs:
  24.112 +
  24.113 +    // Timestamp when the EndFrame() call started executing
  24.114 +    double              EndFrameStartTime;
  24.115 +    // Timestamp when the EndFrame() call finished executing
  24.116 +    double              EndFrameEndTime;
  24.117 +
  24.118 +    // Latency statistics for the epoch
  24.119 +    LatencyStatisticsResults latencyStatisticsData;
  24.120 +
  24.121 +    // Last latency data
  24.122 +    // float               LatencyData[3]; // render, timewarp, median post-present
  24.123 +
  24.124 +    // Last vision processing frame counter number
  24.125 +    uint32_t            LastCameraFrameCounter;
  24.126 +
  24.127 +    // Running statistics:
  24.128 +
  24.129 +    void resetPerfStats(double resetTime = 0.);
  24.130 +
  24.131 +    // Start of the current statistics epoch
  24.132 +    double              EpochBegin;
  24.133 +    // Count of frames in this stats epoch, measured at EndFrame()
  24.134 +    int                 FrameCount;
  24.135 +    // Sum of end frame durations for this stats epoch
  24.136 +    //double              EndFrameSum;
  24.137 +
  24.138 +    // Sum of latencies
  24.139 +    // double              LatencySum[3];
  24.140 +
  24.141 +    // Sum of vision processing times
  24.142 +    //double              VisionProcSum;
  24.143 +    // Sum of vision latency times
  24.144 +    //double              VisionLagSum;
  24.145 +    // Count of vision frames
  24.146 +    int                 VisionFrames;
  24.147 +
  24.148 +    // Statistics results:
  24.149 +
  24.150 +    LocklessUpdater<LatencyStatisticsResults, LatencyStatisticsResults> Results;
  24.151 +
  24.152 +    void calculateResults();
  24.153 +
  24.154 +    OVR::ObserverScope<LatencyStatisticsSlot> calculateResultsSubject;
  24.155 +    OVR::Lock calculateResultsLock;
  24.156 +
  24.157 +public:
  24.158 +    LagStatsCalculator();
  24.159 +
  24.160 +    void GetLatestResults(LatencyStatisticsResults* results);
  24.161 +    void AddResultsObserver(ObserverScope<LatencyStatisticsSlot> *calculateResultsObserver);
  24.162 +
  24.163 +public:
  24.164 +    // Internal instrumentation interface:
  24.165 +
  24.166 +    // EndFrame() instrumentation
  24.167 +    void InstrumentEndFrameStart(double timestamp);
  24.168 +    void InstrumentEndFrameEnd(double timestamp);
  24.169 +
  24.170 +    // DK2 latency tester instrumentation
  24.171 +    // Note: This assumes that it is called right before InstrumentEndFrameEnd()
  24.172 +    void InstrumentLatencyTimings(FrameTimeManager& ftm);
  24.173 +
  24.174 +    // Eye pose instrumentation
  24.175 +    void InstrumentEyePose(const ovrTrackingState& state);
  24.176 +};
  24.177 +
  24.178 +
  24.179 +}} // namespace OVR::CAPI
  24.180 +
  24.181 +#endif // OVR_CAPI_LatencyStatistics_h
    25.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    25.2 +++ b/LibOVR/Src/CAPI/GL/CAPI_GLE.cpp	Wed Jan 14 06:51:16 2015 +0200
    25.3 @@ -0,0 +1,7884 @@
    25.4 +/************************************************************************************
    25.5 +
    25.6 +Filename    :   Render_GLE.cpp
    25.7 +Content     :   OpenGL Extensions support. Implements a stripped down glew-like 
    25.8 +                interface with some additional functionality.
    25.9 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   25.10 +
   25.11 +Licensed under the Apache License, Version 2.0 (the "License");
   25.12 +you may not use this file except in compliance with the License.
   25.13 +You may obtain a copy of the License at
   25.14 +
   25.15 +http://www.apache.org/licenses/LICENSE-2.0
   25.16 +
   25.17 +Unless required by applicable law or agreed to in writing, software
   25.18 +distributed under the License is distributed on an "AS IS" BASIS,
   25.19 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   25.20 +See the License for the specific language governing permissions and
   25.21 +limitations under the License.
   25.22 +
   25.23 +************************************************************************************/
   25.24 +
   25.25 +#include "CAPI_GLE.h"
   25.26 +#include "../../Kernel/OVR_Log.h"
   25.27 +#include <string.h>
   25.28 +
   25.29 +
   25.30 +#if defined(_WIN32)
   25.31 +    #if !defined(WINAPI)
   25.32 +        #ifndef WIN32_LEAN_AND_MEAN
   25.33 +            #define WIN32_LEAN_AND_MEAN 1
   25.34 +        #endif
   25.35 +        #include <windows.h>
   25.36 +    #endif
   25.37 +
   25.38 +    #pragma comment(lib, "opengl32.lib")
   25.39 +#elif defined(__APPLE__)
   25.40 +    #include <stdlib.h>
   25.41 +    #include <string.h>
   25.42 +    #include <AvailabilityMacros.h>
   25.43 +    #include <dlfcn.h>
   25.44 +#endif
   25.45 +
   25.46 +
   25.47 +
   25.48 +//namespace OVR
   25.49 +//{
   25.50 +    // OVRTypeof
   25.51 +    // Acts the same as the C++11 decltype expression, though with reduced requirements.
   25.52 +    #if !defined(OVRTypeof)
   25.53 +        #if defined(_MSC_VER)
   25.54 +            #define OVRTypeof(x) decltype(x)    // VS2010+ unilaterally supports decltype
   25.55 +        #else
   25.56 +            #define OVRTypeof(x) __typeof__(x)  // Other compilers support decltype, but usually not unless C++11 support is present and explicitly enabled.
   25.57 +        #endif
   25.58 +    #endif
   25.59 +
   25.60 +    
   25.61 +    // GLELoadProc
   25.62 +    // Macro which implements dynamically looking up and assigning an OpenGL function.
   25.63 +    //
   25.64 +    // Example usage:
   25.65 +    //     GLELoadProc(glCopyTexSubImage3D, glCopyTexSubImage3D);
   25.66 +    // Expands to:
   25.67 +    //     gleCopyTexSubImage3D = (OVRTypeof(gleCopyTexSubImage3D)) GLEGetProcAddress("glCopyTexSubImage3D");
   25.68 +    
   25.69 +    #define GLELoadProc(var, name) var = (OVRTypeof(var))GLEGetProcAddress(#name)
   25.70 +    
   25.71 +
   25.72 +    // Disable some #defines, as we need to call these functions directly.
   25.73 +    #if defined(GLE_HOOKING_ENABLED)
   25.74 +        #if defined(_WIN32)
   25.75 +            #undef wglGetProcAddress
   25.76 +            extern "C" { GLAPI PROC GLAPIENTRY wglGetProcAddress(LPCSTR lpszProc); }
   25.77 +        #endif
   25.78 +
   25.79 +        #undef glGetString
   25.80 +        extern "C" { GLAPI const GLubyte * GLAPIENTRY glGetString(GLenum name); }
   25.81 +    #endif
   25.82 +
   25.83 +
   25.84 +    // Generic OpenGL GetProcAddress function interface. Maps to platform-specific functionality
   25.85 +    // internally. On Windows this is equivalent to wglGetProcAddress as opposed to global GetProcAddress.
   25.86 +    void* OVR::GLEGetProcAddress(const char* name)
   25.87 +    {
   25.88 +        #if defined(_WIN32)
   25.89 +            return wglGetProcAddress(name);
   25.90 +        
   25.91 +        #elif defined(__APPLE__)
   25.92 +            // Requires the OS 10.3 SDK or later.
   25.93 +            static void* dlImage = NULL;
   25.94 +            void* addr = nullptr;
   25.95 +        
   25.96 +            if(!dlImage)
   25.97 +                dlImage = dlopen("/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL", RTLD_LAZY);
   25.98 +        
   25.99 +            if(dlImage)
  25.100 +                addr = dlsym(dlImage, name);
  25.101 +        
  25.102 +            return addr;
  25.103 +        
  25.104 +        #elif defined(__ANDROID__)
  25.105 +            return eglGetProcAddress(name);
  25.106 +        
  25.107 +        #else
  25.108 +            // This was glXGetProcAddressARB in GLX versions prior to v1.4, but that was ten years ago.
  25.109 +            return (void*)glXGetProcAddress((const GLubyte*)name);
  25.110 +        #endif
  25.111 +    }
  25.112 +
  25.113 +
  25.114 +
  25.115 +    // Current context functionality
  25.116 +    static OVR::GLEContext* GLECurrentContext = NULL;
  25.117 +    
  25.118 +    OVR::GLEContext* OVR::GLEContext::GetCurrentContext()
  25.119 +    {
  25.120 +        return GLECurrentContext;
  25.121 +    }
  25.122 +
  25.123 +    void OVR::GLEContext::SetCurrentContext(OVR::GLEContext* p)
  25.124 +    {
  25.125 +        GLECurrentContext = p;
  25.126 +    }
  25.127 +        
  25.128 +
  25.129 +    
  25.130 +    OVR::GLEContext::GLEContext()
  25.131 +      : MajorVersion(0)
  25.132 +      , MinorVersion(0)
  25.133 +      , WholeVersion(0)
  25.134 +      , IsGLES(false)
  25.135 +      , IsCoreProfile(false)
  25.136 +      , EnableHookGetError(true)
  25.137 +      , PlatformMajorVersion(0)
  25.138 +      , PlatformMinorVersion(0)
  25.139 +      , PlatformWholeVersion(0)
  25.140 +    {
  25.141 +        // The following sequence is not thread-safe. Two threads could set the context to this at the same time.
  25.142 +        if(GetCurrentContext() == NULL)
  25.143 +            SetCurrentContext(this);
  25.144 +    }
  25.145 +    
  25.146 +    
  25.147 +    OVR::GLEContext::~GLEContext()
  25.148 +    {
  25.149 +        // Currently empty
  25.150 +    }
  25.151 +    
  25.152 +    
  25.153 +    void OVR::GLEContext::Init()
  25.154 +    {
  25.155 +        PlatformInit();
  25.156 +
  25.157 +        if(!IsInitialized())
  25.158 +        {
  25.159 +            InitVersion();
  25.160 +            InitExtensionLoad();
  25.161 +            InitExtensionSupport();
  25.162 +        }
  25.163 +    }
  25.164 +    
  25.165 +
  25.166 +    bool OVR::GLEContext::IsInitialized() const
  25.167 +    {
  25.168 +        return (MajorVersion != 0);
  25.169 +    }
  25.170 +
  25.171 +
  25.172 +    void OVR::GLEContext::Shutdown()
  25.173 +    {
  25.174 +        // This memset is valid only if this class has no virtual functions (similar to concept of POD).
  25.175 +        // We cannot assert this because restrictions prevent us from using C++11 type traits here.
  25.176 +        memset(this, 0, sizeof(GLEContext));
  25.177 +    }
  25.178 +
  25.179 +
  25.180 +    void OVR::GLEContext::PlatformInit()
  25.181 +    {
  25.182 +        if(!IsPlatformInitialized())
  25.183 +        {
  25.184 +            InitPlatformExtensionLoad();
  25.185 +            InitPlatformExtensionSupport();
  25.186 +            InitPlatformVersion();
  25.187 +        }
  25.188 +    }
  25.189 +
  25.190 +
  25.191 +    bool OVR::GLEContext::IsPlatformInitialized() const
  25.192 +    {
  25.193 +        return (PlatformMajorVersion != 0);
  25.194 +    }
  25.195 +
  25.196 +
  25.197 +    void OVR::GLEContext::InitVersion()
  25.198 +    {
  25.199 +        const char* version = (const char*)glGetString(GL_VERSION);
  25.200 +        int fields = 0, major = 0, minor = 0;
  25.201 +        bool isGLES = false;
  25.202 +
  25.203 +        OVR_ASSERT(version);
  25.204 +        if (version)
  25.205 +        {
  25.206 +            OVR_DEBUG_LOG(("GL_VERSION: %s", (const char*)version));
  25.207 +
  25.208 +            // Skip all leading non-digits before reading %d.
  25.209 +            // Example GL_VERSION strings:
  25.210 +            //   "1.5 ATI-1.4.18"
  25.211 +            //   "OpenGL ES-CM 3.2"
  25.212 +            OVR_DISABLE_MSVC_WARNING(4996) // "scanf may be unsafe"
  25.213 +            fields = sscanf(version, isdigit(*version) ? "%d.%d" : "%*[^0-9]%d.%d", &major, &minor);
  25.214 +            isGLES = (strstr(version, "OpenGL ES") != NULL);
  25.215 +            OVR_RESTORE_MSVC_WARNING()
  25.216 +        }
  25.217 +        else
  25.218 +        {
  25.219 +            LogText("Warning: GL_VERSION was NULL\n");
  25.220 +        }
  25.221 +
  25.222 +        // If two fields were not found,
  25.223 +        if (fields != 2)
  25.224 +        {
  25.225 +            static_assert(sizeof(major) == sizeof(GLint), "type mis-match");
  25.226 +
  25.227 +            glGetIntegerv(GL_MAJOR_VERSION, &major);
  25.228 +            glGetIntegerv(GL_MINOR_VERSION, &minor);
  25.229 +        }
  25.230 +
  25.231 +        // Write version data
  25.232 +        MajorVersion  = major;
  25.233 +        MinorVersion  = minor;
  25.234 +        WholeVersion  = (major * 100) + minor;
  25.235 +
  25.236 +        GLint profileMask = 0;
  25.237 +        if(WholeVersion >= 302)
  25.238 +        {
  25.239 +            // Older NVidia drivers have a bug with this on at least Windows.
  25.240 +            // https://www.opengl.org/discussion_boards/showthread.php/171380-NVIDIA-drivers-not-returning-the-right-profile-mas
  25.241 +            // A workaround could be to check for the GL_ARB_compatibility extension, which indicates if OpenGL is in compatibility mode,
  25.242 +            // and if not then we are in core profile mode. On Apple another solution would be to use NSOpeNGLPixelFormat
  25.243 +            // NSOpenGLView::pixelFormat to get the core profile attribute.
  25.244 +            glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &profileMask);
  25.245 +        }
  25.246 +        IsCoreProfile = (profileMask == GL_CONTEXT_CORE_PROFILE_BIT); // There's also GL_CONTEXT_COMPATIBILITY_PROFILE_BIT
  25.247 +        IsGLES        = isGLES;
  25.248 +    }
  25.249 +    
  25.250 +    
  25.251 +    void OVR::GLEContext::InitExtensionLoad()
  25.252 +    {
  25.253 +        // GL_VERSION_1_1
  25.254 +        // We don't load these but rather link to them directly.
  25.255 +        
  25.256 +        // GL_VERSION_1_2
  25.257 +        GLELoadProc(glCopyTexSubImage3D_Impl, glCopyTexSubImage3D);  // This expands to a get proc address call (e.g. wglGetProcAddress on Windows).
  25.258 +        GLELoadProc(glDrawRangeElements_Impl, glDrawRangeElements);
  25.259 +        GLELoadProc(glTexImage3D_Impl, glTexImage3D);
  25.260 +        GLELoadProc(glTexSubImage3D_Impl, glTexSubImage3D);
  25.261 +
  25.262 +        // GL_VERSION_1_3
  25.263 +        GLELoadProc(glActiveTexture_Impl, glActiveTexture);
  25.264 +        GLELoadProc(glClientActiveTexture_Impl, glClientActiveTexture);
  25.265 +        GLELoadProc(glCompressedTexImage1D_Impl, glCompressedTexImage1D);
  25.266 +        GLELoadProc(glCompressedTexImage2D_Impl, glCompressedTexImage2D);
  25.267 +        GLELoadProc(glCompressedTexImage3D_Impl, glCompressedTexImage3D);
  25.268 +        GLELoadProc(glCompressedTexSubImage1D_Impl, glCompressedTexSubImage1D);
  25.269 +        GLELoadProc(glCompressedTexSubImage2D_Impl, glCompressedTexSubImage2D);
  25.270 +        GLELoadProc(glCompressedTexSubImage3D_Impl, glCompressedTexSubImage3D);
  25.271 +        GLELoadProc(glGetCompressedTexImage_Impl, glGetCompressedTexImage);
  25.272 +        GLELoadProc(glLoadTransposeMatrixd_Impl, glLoadTransposeMatrixd);
  25.273 +        GLELoadProc(glLoadTransposeMatrixf_Impl, glLoadTransposeMatrixf);
  25.274 +        GLELoadProc(glMultTransposeMatrixd_Impl, glMultTransposeMatrixd);
  25.275 +        GLELoadProc(glMultTransposeMatrixf_Impl, glMultTransposeMatrixf);
  25.276 +        GLELoadProc(glMultiTexCoord1d_Impl, glMultiTexCoord1d);
  25.277 +        GLELoadProc(glMultiTexCoord1dv_Impl, glMultiTexCoord1dv);
  25.278 +        GLELoadProc(glMultiTexCoord1f_Impl, glMultiTexCoord1f);
  25.279 +        GLELoadProc(glMultiTexCoord1fv_Impl, glMultiTexCoord1fv);
  25.280 +        GLELoadProc(glMultiTexCoord1i_Impl, glMultiTexCoord1i);
  25.281 +        GLELoadProc(glMultiTexCoord1iv_Impl, glMultiTexCoord1iv);
  25.282 +        GLELoadProc(glMultiTexCoord1s_Impl, glMultiTexCoord1s);
  25.283 +        GLELoadProc(glMultiTexCoord1sv_Impl, glMultiTexCoord1sv);
  25.284 +        GLELoadProc(glMultiTexCoord2d_Impl, glMultiTexCoord2d);
  25.285 +        GLELoadProc(glMultiTexCoord2dv_Impl, glMultiTexCoord2dv);
  25.286 +        GLELoadProc(glMultiTexCoord2f_Impl, glMultiTexCoord2f);
  25.287 +        GLELoadProc(glMultiTexCoord2fv_Impl, glMultiTexCoord2fv);
  25.288 +        GLELoadProc(glMultiTexCoord2i_Impl, glMultiTexCoord2i);
  25.289 +        GLELoadProc(glMultiTexCoord2iv_Impl, glMultiTexCoord2iv);
  25.290 +        GLELoadProc(glMultiTexCoord2s_Impl, glMultiTexCoord2s);
  25.291 +        GLELoadProc(glMultiTexCoord2sv_Impl, glMultiTexCoord2sv);
  25.292 +        GLELoadProc(glMultiTexCoord3d_Impl, glMultiTexCoord3d);
  25.293 +        GLELoadProc(glMultiTexCoord3dv_Impl, glMultiTexCoord3dv);
  25.294 +        GLELoadProc(glMultiTexCoord3f_Impl, glMultiTexCoord3f);
  25.295 +        GLELoadProc(glMultiTexCoord3fv_Impl, glMultiTexCoord3fv);
  25.296 +        GLELoadProc(glMultiTexCoord3i_Impl, glMultiTexCoord3i);
  25.297 +        GLELoadProc(glMultiTexCoord3iv_Impl, glMultiTexCoord3iv);
  25.298 +        GLELoadProc(glMultiTexCoord3s_Impl, glMultiTexCoord3s);
  25.299 +        GLELoadProc(glMultiTexCoord3sv_Impl, glMultiTexCoord3sv);
  25.300 +        GLELoadProc(glMultiTexCoord4d_Impl, glMultiTexCoord4d);
  25.301 +        GLELoadProc(glMultiTexCoord4dv_Impl, glMultiTexCoord4dv);
  25.302 +        GLELoadProc(glMultiTexCoord4f_Impl, glMultiTexCoord4f);
  25.303 +        GLELoadProc(glMultiTexCoord4fv_Impl, glMultiTexCoord4fv);
  25.304 +        GLELoadProc(glMultiTexCoord4i_Impl, glMultiTexCoord4i);
  25.305 +        GLELoadProc(glMultiTexCoord4iv_Impl, glMultiTexCoord4iv);
  25.306 +        GLELoadProc(glMultiTexCoord4s_Impl, glMultiTexCoord4s);
  25.307 +        GLELoadProc(glMultiTexCoord4sv_Impl, glMultiTexCoord4sv);
  25.308 +        GLELoadProc(glSampleCoverage_Impl, glSampleCoverage);
  25.309 +
  25.310 +        // GL_VERSION_1_4
  25.311 +        GLELoadProc(glBlendColor_Impl, glBlendColor);
  25.312 +        GLELoadProc(glBlendEquation_Impl, glBlendEquation);
  25.313 +        GLELoadProc(glBlendFuncSeparate_Impl, glBlendFuncSeparate);
  25.314 +        GLELoadProc(glFogCoordPointer_Impl, glFogCoordPointer);
  25.315 +        GLELoadProc(glFogCoordd_Impl, glFogCoordd);
  25.316 +        GLELoadProc(glFogCoorddv_Impl, glFogCoorddv);
  25.317 +        GLELoadProc(glFogCoordf_Impl, glFogCoordf);
  25.318 +        GLELoadProc(glFogCoordfv_Impl, glFogCoordfv);
  25.319 +        GLELoadProc(glMultiDrawArrays_Impl, glMultiDrawArrays);
  25.320 +        GLELoadProc(glMultiDrawElements_Impl, glMultiDrawElements);
  25.321 +        GLELoadProc(glPointParameterf_Impl, glPointParameterf);
  25.322 +        GLELoadProc(glPointParameterfv_Impl, glPointParameterfv);
  25.323 +        GLELoadProc(glPointParameteri_Impl, glPointParameteri);
  25.324 +        GLELoadProc(glPointParameteriv_Impl, glPointParameteriv);
  25.325 +        GLELoadProc(glSecondaryColor3b_Impl, glSecondaryColor3b);
  25.326 +        GLELoadProc(glSecondaryColor3bv_Impl, glSecondaryColor3bv);
  25.327 +        GLELoadProc(glSecondaryColor3d_Impl, glSecondaryColor3d);
  25.328 +        GLELoadProc(glSecondaryColor3dv_Impl, glSecondaryColor3dv);
  25.329 +        GLELoadProc(glSecondaryColor3f_Impl, glSecondaryColor3f);
  25.330 +        GLELoadProc(glSecondaryColor3fv_Impl, glSecondaryColor3fv);
  25.331 +        GLELoadProc(glSecondaryColor3i_Impl, glSecondaryColor3i);
  25.332 +        GLELoadProc(glSecondaryColor3iv_Impl, glSecondaryColor3iv);
  25.333 +        GLELoadProc(glSecondaryColor3s_Impl, glSecondaryColor3s);
  25.334 +        GLELoadProc(glSecondaryColor3sv_Impl, glSecondaryColor3sv);
  25.335 +        GLELoadProc(glSecondaryColor3ub_Impl, glSecondaryColor3ub);
  25.336 +        GLELoadProc(glSecondaryColor3ubv_Impl, glSecondaryColor3ubv);
  25.337 +        GLELoadProc(glSecondaryColor3ui_Impl, glSecondaryColor3ui);
  25.338 +        GLELoadProc(glSecondaryColor3uiv_Impl, glSecondaryColor3uiv);
  25.339 +        GLELoadProc(glSecondaryColor3us_Impl, glSecondaryColor3us);
  25.340 +        GLELoadProc(glSecondaryColor3usv_Impl, glSecondaryColor3usv);
  25.341 +        GLELoadProc(glSecondaryColorPointer_Impl, glSecondaryColorPointer);
  25.342 +        GLELoadProc(glWindowPos2d_Impl, glWindowPos2d);
  25.343 +        GLELoadProc(glWindowPos2dv_Impl, glWindowPos2dv);
  25.344 +        GLELoadProc(glWindowPos2f_Impl, glWindowPos2f);
  25.345 +        GLELoadProc(glWindowPos2fv_Impl, glWindowPos2fv);
  25.346 +        GLELoadProc(glWindowPos2i_Impl, glWindowPos2i);
  25.347 +        GLELoadProc(glWindowPos2iv_Impl, glWindowPos2iv);
  25.348 +        GLELoadProc(glWindowPos2s_Impl, glWindowPos2s);
  25.349 +        GLELoadProc(glWindowPos2sv_Impl, glWindowPos2sv);
  25.350 +        GLELoadProc(glWindowPos3d_Impl, glWindowPos3d);
  25.351 +        GLELoadProc(glWindowPos3dv_Impl, glWindowPos3dv);
  25.352 +        GLELoadProc(glWindowPos3f_Impl, glWindowPos3f);
  25.353 +        GLELoadProc(glWindowPos3fv_Impl, glWindowPos3fv);
  25.354 +        GLELoadProc(glWindowPos3i_Impl, glWindowPos3i);
  25.355 +        GLELoadProc(glWindowPos3iv_Impl, glWindowPos3iv);
  25.356 +        GLELoadProc(glWindowPos3s_Impl, glWindowPos3s);
  25.357 +        GLELoadProc(glWindowPos3sv_Impl, glWindowPos3sv);
  25.358 +
  25.359 +        // GL_VERSION_1_5
  25.360 +        GLELoadProc(glBeginQuery_Impl, glBeginQuery);
  25.361 +        GLELoadProc(glBindBuffer_Impl, glBindBuffer);
  25.362 +        GLELoadProc(glBufferData_Impl, glBufferData);
  25.363 +        GLELoadProc(glBufferSubData_Impl, glBufferSubData);
  25.364 +        GLELoadProc(glDeleteBuffers_Impl, glDeleteBuffers);
  25.365 +        GLELoadProc(glDeleteQueries_Impl, glDeleteQueries);
  25.366 +        GLELoadProc(glEndQuery_Impl, glEndQuery);
  25.367 +        GLELoadProc(glGenBuffers_Impl, glGenBuffers);
  25.368 +        GLELoadProc(glGenQueries_Impl, glGenQueries);
  25.369 +        GLELoadProc(glGetBufferParameteriv_Impl, glGetBufferParameteriv);
  25.370 +        GLELoadProc(glGetBufferPointerv_Impl, glGetBufferPointerv);
  25.371 +        GLELoadProc(glGetBufferSubData_Impl, glGetBufferSubData);
  25.372 +        GLELoadProc(glGetQueryObjectiv_Impl, glGetQueryObjectiv);
  25.373 +        GLELoadProc(glGetQueryObjectuiv_Impl, glGetQueryObjectuiv);
  25.374 +        GLELoadProc(glGetQueryiv_Impl, glGetQueryiv);
  25.375 +        GLELoadProc(glIsBuffer_Impl, glIsBuffer);
  25.376 +        GLELoadProc(glIsQuery_Impl, glIsQuery);
  25.377 +        GLELoadProc(glMapBuffer_Impl, glMapBuffer);
  25.378 +        GLELoadProc(glUnmapBuffer_Impl, glUnmapBuffer);
  25.379 +
  25.380 +        // GL_VERSION_2_0
  25.381 +        GLELoadProc(glAttachShader_Impl, glAttachShader);
  25.382 +        GLELoadProc(glBindAttribLocation_Impl, glBindAttribLocation);
  25.383 +        GLELoadProc(glBlendEquationSeparate_Impl, glBlendEquationSeparate);
  25.384 +        GLELoadProc(glCompileShader_Impl, glCompileShader);
  25.385 +        GLELoadProc(glCreateProgram_Impl, glCreateProgram);
  25.386 +        GLELoadProc(glCreateShader_Impl, glCreateShader);
  25.387 +        GLELoadProc(glDeleteProgram_Impl, glDeleteProgram);
  25.388 +        GLELoadProc(glDeleteShader_Impl, glDeleteShader);
  25.389 +        GLELoadProc(glDetachShader_Impl, glDetachShader);
  25.390 +        GLELoadProc(glDisableVertexAttribArray_Impl, glDisableVertexAttribArray);
  25.391 +        GLELoadProc(glDrawBuffers_Impl, glDrawBuffers);
  25.392 +        GLELoadProc(glEnableVertexAttribArray_Impl, glEnableVertexAttribArray);
  25.393 +        GLELoadProc(glGetActiveAttrib_Impl, glGetActiveAttrib);
  25.394 +        GLELoadProc(glGetActiveUniform_Impl, glGetActiveUniform);
  25.395 +        GLELoadProc(glGetAttachedShaders_Impl, glGetAttachedShaders);
  25.396 +        GLELoadProc(glGetAttribLocation_Impl, glGetAttribLocation);
  25.397 +        GLELoadProc(glGetProgramInfoLog_Impl, glGetProgramInfoLog);
  25.398 +        GLELoadProc(glGetProgramiv_Impl, glGetProgramiv);
  25.399 +        GLELoadProc(glGetShaderInfoLog_Impl, glGetShaderInfoLog);
  25.400 +        GLELoadProc(glGetShaderSource_Impl, glGetShaderSource);
  25.401 +        GLELoadProc(glGetShaderiv_Impl, glGetShaderiv);
  25.402 +        GLELoadProc(glGetUniformLocation_Impl, glGetUniformLocation);
  25.403 +        GLELoadProc(glGetUniformfv_Impl, glGetUniformfv);
  25.404 +        GLELoadProc(glGetUniformiv_Impl, glGetUniformiv);
  25.405 +        GLELoadProc(glGetVertexAttribPointerv_Impl, glGetVertexAttribPointerv);
  25.406 +        GLELoadProc(glGetVertexAttribdv_Impl, glGetVertexAttribdv);
  25.407 +        GLELoadProc(glGetVertexAttribfv_Impl, glGetVertexAttribfv);
  25.408 +        GLELoadProc(glGetVertexAttribiv_Impl, glGetVertexAttribiv);
  25.409 +        GLELoadProc(glIsProgram_Impl, glIsProgram);
  25.410 +        GLELoadProc(glIsShader_Impl, glIsShader);
  25.411 +        GLELoadProc(glLinkProgram_Impl, glLinkProgram);
  25.412 +        GLELoadProc(glShaderSource_Impl, glShaderSource);
  25.413 +        GLELoadProc(glStencilFuncSeparate_Impl, glStencilFuncSeparate);
  25.414 +        GLELoadProc(glStencilMaskSeparate_Impl, glStencilMaskSeparate);
  25.415 +        GLELoadProc(glStencilOpSeparate_Impl, glStencilOpSeparate);
  25.416 +        GLELoadProc(glUniform1f_Impl, glUniform1f);
  25.417 +        GLELoadProc(glUniform1fv_Impl, glUniform1fv);
  25.418 +        GLELoadProc(glUniform1i_Impl, glUniform1i);
  25.419 +        GLELoadProc(glUniform1iv_Impl, glUniform1iv);
  25.420 +        GLELoadProc(glUniform2f_Impl, glUniform2f);
  25.421 +        GLELoadProc(glUniform2fv_Impl, glUniform2fv);
  25.422 +        GLELoadProc(glUniform2i_Impl, glUniform2i);
  25.423 +        GLELoadProc(glUniform2iv_Impl, glUniform2iv);
  25.424 +        GLELoadProc(glUniform3f_Impl, glUniform3f);
  25.425 +        GLELoadProc(glUniform3fv_Impl, glUniform3fv);
  25.426 +        GLELoadProc(glUniform3i_Impl, glUniform3i);
  25.427 +        GLELoadProc(glUniform3iv_Impl, glUniform3iv);
  25.428 +        GLELoadProc(glUniform4f_Impl, glUniform4f);
  25.429 +        GLELoadProc(glUniform4fv_Impl, glUniform4fv);
  25.430 +        GLELoadProc(glUniform4i_Impl, glUniform4i);
  25.431 +        GLELoadProc(glUniform4iv_Impl, glUniform4iv);
  25.432 +        GLELoadProc(glUniformMatrix2fv_Impl, glUniformMatrix2fv);
  25.433 +        GLELoadProc(glUniformMatrix3fv_Impl, glUniformMatrix3fv);
  25.434 +        GLELoadProc(glUniformMatrix4fv_Impl, glUniformMatrix4fv);
  25.435 +        GLELoadProc(glUseProgram_Impl, glUseProgram);
  25.436 +        GLELoadProc(glValidateProgram_Impl, glValidateProgram);
  25.437 +        GLELoadProc(glVertexAttrib1d_Impl, glVertexAttrib1d);
  25.438 +        GLELoadProc(glVertexAttrib1dv_Impl, glVertexAttrib1dv);
  25.439 +        GLELoadProc(glVertexAttrib1f_Impl, glVertexAttrib1f);
  25.440 +        GLELoadProc(glVertexAttrib1fv_Impl, glVertexAttrib1fv);
  25.441 +        GLELoadProc(glVertexAttrib1s_Impl, glVertexAttrib1s);
  25.442 +        GLELoadProc(glVertexAttrib1sv_Impl, glVertexAttrib1sv);
  25.443 +        GLELoadProc(glVertexAttrib2d_Impl, glVertexAttrib2d);
  25.444 +        GLELoadProc(glVertexAttrib2dv_Impl, glVertexAttrib2dv);
  25.445 +        GLELoadProc(glVertexAttrib2f_Impl, glVertexAttrib2f);
  25.446 +        GLELoadProc(glVertexAttrib2fv_Impl, glVertexAttrib2fv);
  25.447 +        GLELoadProc(glVertexAttrib2s_Impl, glVertexAttrib2s);
  25.448 +        GLELoadProc(glVertexAttrib2sv_Impl, glVertexAttrib2sv);
  25.449 +        GLELoadProc(glVertexAttrib3d_Impl, glVertexAttrib3d);
  25.450 +        GLELoadProc(glVertexAttrib3dv_Impl, glVertexAttrib3dv);
  25.451 +        GLELoadProc(glVertexAttrib3f_Impl, glVertexAttrib3f);
  25.452 +        GLELoadProc(glVertexAttrib3fv_Impl, glVertexAttrib3fv);
  25.453 +        GLELoadProc(glVertexAttrib3s_Impl, glVertexAttrib3s);
  25.454 +        GLELoadProc(glVertexAttrib3sv_Impl, glVertexAttrib3sv);
  25.455 +        GLELoadProc(glVertexAttrib4Nbv_Impl, glVertexAttrib4Nbv);
  25.456 +        GLELoadProc(glVertexAttrib4Niv_Impl, glVertexAttrib4Niv);
  25.457 +        GLELoadProc(glVertexAttrib4Nsv_Impl, glVertexAttrib4Nsv);
  25.458 +        GLELoadProc(glVertexAttrib4Nub_Impl, glVertexAttrib4Nub);
  25.459 +        GLELoadProc(glVertexAttrib4Nubv_Impl, glVertexAttrib4Nubv);
  25.460 +        GLELoadProc(glVertexAttrib4Nuiv_Impl, glVertexAttrib4Nuiv);
  25.461 +        GLELoadProc(glVertexAttrib4Nusv_Impl, glVertexAttrib4Nusv);
  25.462 +        GLELoadProc(glVertexAttrib4bv_Impl, glVertexAttrib4bv);
  25.463 +        GLELoadProc(glVertexAttrib4d_Impl, glVertexAttrib4d);
  25.464 +        GLELoadProc(glVertexAttrib4dv_Impl, glVertexAttrib4dv);
  25.465 +        GLELoadProc(glVertexAttrib4f_Impl, glVertexAttrib4f);
  25.466 +        GLELoadProc(glVertexAttrib4fv_Impl, glVertexAttrib4fv);
  25.467 +        GLELoadProc(glVertexAttrib4iv_Impl, glVertexAttrib4iv);
  25.468 +        GLELoadProc(glVertexAttrib4s_Impl, glVertexAttrib4s);
  25.469 +        GLELoadProc(glVertexAttrib4sv_Impl, glVertexAttrib4sv);
  25.470 +        GLELoadProc(glVertexAttrib4ubv_Impl, glVertexAttrib4ubv);
  25.471 +        GLELoadProc(glVertexAttrib4uiv_Impl, glVertexAttrib4uiv);
  25.472 +        GLELoadProc(glVertexAttrib4usv_Impl, glVertexAttrib4usv);
  25.473 +        GLELoadProc(glVertexAttribPointer_Impl, glVertexAttribPointer);
  25.474 +
  25.475 +        // GL_VERSION_2_1
  25.476 +        GLELoadProc(glUniformMatrix2x3fv_Impl, glUniformMatrix2x3fv);
  25.477 +        GLELoadProc(glUniformMatrix2x4fv_Impl, glUniformMatrix2x4fv);
  25.478 +        GLELoadProc(glUniformMatrix3x2fv_Impl, glUniformMatrix3x2fv);
  25.479 +        GLELoadProc(glUniformMatrix3x4fv_Impl, glUniformMatrix3x4fv);
  25.480 +        GLELoadProc(glUniformMatrix4x2fv_Impl, glUniformMatrix4x2fv);
  25.481 +        GLELoadProc(glUniformMatrix4x3fv_Impl, glUniformMatrix4x3fv);
  25.482 +
  25.483 +        // GL_VERSION_3_0
  25.484 +        GLELoadProc(glBeginConditionalRender_Impl, glBeginConditionalRender);
  25.485 +        GLELoadProc(glBeginTransformFeedback_Impl, glBeginTransformFeedback);
  25.486 +        GLELoadProc(glBindFragDataLocation_Impl, glBindFragDataLocation);
  25.487 +        GLELoadProc(glClampColor_Impl, glClampColor);
  25.488 +        GLELoadProc(glClearBufferfi_Impl, glClearBufferfi);
  25.489 +        GLELoadProc(glClearBufferfv_Impl, glClearBufferfv);
  25.490 +        GLELoadProc(glClearBufferiv_Impl, glClearBufferiv);
  25.491 +        GLELoadProc(glClearBufferuiv_Impl, glClearBufferuiv);
  25.492 +        GLELoadProc(glColorMaski_Impl, glColorMaski);
  25.493 +        GLELoadProc(glDisablei_Impl, glDisablei);
  25.494 +        GLELoadProc(glEnablei_Impl, glEnablei);
  25.495 +        GLELoadProc(glEndConditionalRender_Impl, glEndConditionalRender);
  25.496 +        GLELoadProc(glEndTransformFeedback_Impl, glEndTransformFeedback);
  25.497 +        GLELoadProc(glBindBufferRange_Impl, glBindBufferRange);
  25.498 +        GLELoadProc(glBindBufferBase_Impl, glBindBufferBase);
  25.499 +        GLELoadProc(glGetBooleani_v_Impl, glGetBooleani_v);
  25.500 +        GLELoadProc(glGetIntegeri_v_Impl, glGetIntegeri_v);
  25.501 +        GLELoadProc(glGetFragDataLocation_Impl, glGetFragDataLocation);
  25.502 +        GLELoadProc(glGetStringi_Impl, glGetStringi);
  25.503 +        GLELoadProc(glGetTexParameterIiv_Impl, glGetTexParameterIiv);
  25.504 +        GLELoadProc(glGetTexParameterIuiv_Impl, glGetTexParameterIuiv);
  25.505 +        GLELoadProc(glGetTransformFeedbackVarying_Impl, glGetTransformFeedbackVarying);
  25.506 +        GLELoadProc(glGetUniformuiv_Impl, glGetUniformuiv);
  25.507 +        GLELoadProc(glGetVertexAttribIiv_Impl, glGetVertexAttribIiv);
  25.508 +        GLELoadProc(glGetVertexAttribIuiv_Impl, glGetVertexAttribIuiv);
  25.509 +        GLELoadProc(glIsEnabledi_Impl, glIsEnabledi);
  25.510 +        GLELoadProc(glTexParameterIiv_Impl, glTexParameterIiv);
  25.511 +        GLELoadProc(glTexParameterIuiv_Impl, glTexParameterIuiv);
  25.512 +        GLELoadProc(glTransformFeedbackVaryings_Impl, glTransformFeedbackVaryings);
  25.513 +        GLELoadProc(glUniform1ui_Impl, glUniform1ui);
  25.514 +        GLELoadProc(glUniform1uiv_Impl, glUniform1uiv);
  25.515 +        GLELoadProc(glUniform2ui_Impl, glUniform2ui);
  25.516 +        GLELoadProc(glUniform2uiv_Impl, glUniform2uiv);
  25.517 +        GLELoadProc(glUniform3ui_Impl, glUniform3ui);
  25.518 +        GLELoadProc(glUniform3uiv_Impl, glUniform3uiv);
  25.519 +        GLELoadProc(glUniform4ui_Impl, glUniform4ui);
  25.520 +        GLELoadProc(glUniform4uiv_Impl, glUniform4uiv);
  25.521 +        GLELoadProc(glVertexAttribI1i_Impl, glVertexAttribI1i);
  25.522 +        GLELoadProc(glVertexAttribI1iv_Impl, glVertexAttribI1iv);
  25.523 +        GLELoadProc(glVertexAttribI1ui_Impl, glVertexAttribI1ui);
  25.524 +        GLELoadProc(glVertexAttribI1uiv_Impl, glVertexAttribI1uiv);
  25.525 +        GLELoadProc(glVertexAttribI2i_Impl, glVertexAttribI2i);
  25.526 +        GLELoadProc(glVertexAttribI2iv_Impl, glVertexAttribI2iv);
  25.527 +        GLELoadProc(glVertexAttribI2ui_Impl, glVertexAttribI2ui);
  25.528 +        GLELoadProc(glVertexAttribI2uiv_Impl, glVertexAttribI2uiv);
  25.529 +        GLELoadProc(glVertexAttribI3i_Impl, glVertexAttribI3i);
  25.530 +        GLELoadProc(glVertexAttribI3iv_Impl, glVertexAttribI3iv);
  25.531 +        GLELoadProc(glVertexAttribI3ui_Impl, glVertexAttribI3ui);
  25.532 +        GLELoadProc(glVertexAttribI3uiv_Impl, glVertexAttribI3uiv);
  25.533 +        GLELoadProc(glVertexAttribI4bv_Impl, glVertexAttribI4bv);
  25.534 +        GLELoadProc(glVertexAttribI4i_Impl, glVertexAttribI4i);
  25.535 +        GLELoadProc(glVertexAttribI4iv_Impl, glVertexAttribI4iv);
  25.536 +        GLELoadProc(glVertexAttribI4sv_Impl, glVertexAttribI4sv);
  25.537 +        GLELoadProc(glVertexAttribI4ubv_Impl, glVertexAttribI4ubv);
  25.538 +        GLELoadProc(glVertexAttribI4ui_Impl, glVertexAttribI4ui);
  25.539 +        GLELoadProc(glVertexAttribI4uiv_Impl, glVertexAttribI4uiv);
  25.540 +        GLELoadProc(glVertexAttribI4usv_Impl, glVertexAttribI4usv);
  25.541 +        GLELoadProc(glVertexAttribIPointer_Impl, glVertexAttribIPointer);
  25.542 +
  25.543 +        // GL_VERSION_3_1
  25.544 +        GLELoadProc(glDrawArraysInstanced_Impl, glDrawArraysInstanced);
  25.545 +        GLELoadProc(glDrawElementsInstanced_Impl, glDrawElementsInstanced);
  25.546 +        GLELoadProc(glPrimitiveRestartIndex_Impl, glPrimitiveRestartIndex);
  25.547 +        GLELoadProc(glTexBuffer_Impl, glTexBuffer);
  25.548 +
  25.549 +        // GL_VERSION_3_2
  25.550 +        GLELoadProc(glFramebufferTexture_Impl, glFramebufferTexture);
  25.551 +        GLELoadProc(glGetBufferParameteri64v_Impl, glGetBufferParameteri64v);
  25.552 +        GLELoadProc(glGetInteger64i_v_Impl, glGetInteger64i_v);
  25.553 +
  25.554 +        // GL_VERSION_3_3
  25.555 +        GLELoadProc(glVertexAttribDivisor_Impl, glVertexAttribDivisor);
  25.556 +
  25.557 +        // GL_VERSION_4_0
  25.558 +        GLELoadProc(glBlendEquationSeparatei_Impl, glBlendEquationSeparatei);
  25.559 +        GLELoadProc(glBlendEquationi_Impl, glBlendEquationi);
  25.560 +        GLELoadProc(glBlendFuncSeparatei_Impl, glBlendFuncSeparatei);
  25.561 +        GLELoadProc(glBlendFunci_Impl, glBlendFunci);
  25.562 +        GLELoadProc(glMinSampleShading_Impl, glMinSampleShading);
  25.563 +
  25.564 +        // GL_AMD_debug_output
  25.565 +        GLELoadProc(glDebugMessageCallbackAMD_Impl, glDebugMessageCallbackAMD);
  25.566 +        GLELoadProc(glDebugMessageEnableAMD_Impl, glDebugMessageEnableAMD);
  25.567 +        GLELoadProc(glDebugMessageInsertAMD_Impl, glDebugMessageInsertAMD);
  25.568 +        GLELoadProc(glGetDebugMessageLogAMD_Impl, glGetDebugMessageLogAMD);
  25.569 +
  25.570 +      #if defined(GLE_CGL_ENABLED)
  25.571 +        // GL_APPLE_element_array
  25.572 +        GLELoadProc(glDrawElementArrayAPPLE_Impl, glDrawElementArrayAPPLE);
  25.573 +        GLELoadProc(glDrawRangeElementArrayAPPLE_Impl, glDrawRangeElementArrayAPPLE);
  25.574 +        GLELoadProc(glElementPointerAPPLE_Impl, glElementPointerAPPLE);
  25.575 +        GLELoadProc(glMultiDrawElementArrayAPPLE_Impl, glMultiDrawElementArrayAPPLE);
  25.576 +        GLELoadProc(glMultiDrawRangeElementArrayAPPLE_Impl, glMultiDrawRangeElementArrayAPPLE);
  25.577 +
  25.578 +        // GL_APPLE_fence
  25.579 +        GLELoadProc(glDeleteFencesAPPLE_Impl, glDeleteFencesAPPLE);
  25.580 +        GLELoadProc(glFinishFenceAPPLE_Impl, glFinishFenceAPPLE);
  25.581 +        GLELoadProc(glFinishObjectAPPLE_Impl, glFinishObjectAPPLE);
  25.582 +        GLELoadProc(glGenFencesAPPLE_Impl, glGenFencesAPPLE);
  25.583 +        GLELoadProc(glIsFenceAPPLE_Impl, glIsFenceAPPLE);
  25.584 +        GLELoadProc(glSetFenceAPPLE_Impl, glSetFenceAPPLE);
  25.585 +        GLELoadProc(glTestFenceAPPLE_Impl, glTestFenceAPPLE);
  25.586 +        GLELoadProc(glTestObjectAPPLE_Impl, glTestObjectAPPLE);
  25.587 +
  25.588 +        // GL_APPLE_flush_buffer_range
  25.589 +        GLELoadProc(glBufferParameteriAPPLE_Impl, glMultiDrawRangeElementArrayAPPLE);
  25.590 +        GLELoadProc(glFlushMappedBufferRangeAPPLE_Impl, glFlushMappedBufferRangeAPPLE);
  25.591 +
  25.592 +        // GL_APPLE_object_purgeable
  25.593 +        GLELoadProc(glGetObjectParameterivAPPLE_Impl, glGetObjectParameterivAPPLE);
  25.594 +        GLELoadProc(glObjectPurgeableAPPLE_Impl, glObjectPurgeableAPPLE);
  25.595 +        GLELoadProc(glObjectUnpurgeableAPPLE_Impl, glObjectUnpurgeableAPPLE);
  25.596 +
  25.597 +        // GL_APPLE_texture_range
  25.598 +        GLELoadProc(glGetTexParameterPointervAPPLE_Impl, glGetTexParameterPointervAPPLE);
  25.599 +        GLELoadProc(glTextureRangeAPPLE_Impl, glTextureRangeAPPLE);
  25.600 +
  25.601 +        // GL_APPLE_vertex_array_object
  25.602 +        GLELoadProc(glBindVertexArrayAPPLE_Impl, glBindVertexArrayAPPLE);
  25.603 +        GLELoadProc(glDeleteVertexArraysAPPLE_Impl, glDeleteVertexArraysAPPLE);
  25.604 +        GLELoadProc(glGenVertexArraysAPPLE_Impl, glGenVertexArraysAPPLE);
  25.605 +        GLELoadProc(glIsVertexArrayAPPLE_Impl, glIsVertexArrayAPPLE);
  25.606 +
  25.607 +        // GL_APPLE_vertex_array_range
  25.608 +        GLELoadProc(glFlushVertexArrayRangeAPPLE_Impl, glFlushVertexArrayRangeAPPLE);
  25.609 +        GLELoadProc(glVertexArrayParameteriAPPLE_Impl, glVertexArrayParameteriAPPLE);
  25.610 +        GLELoadProc(glVertexArrayRangeAPPLE_Impl, glVertexArrayRangeAPPLE);
  25.611 +
  25.612 +        // GL_APPLE_vertex_program_evaluators
  25.613 +        GLELoadProc(glDisableVertexAttribAPPLE_Impl, glDisableVertexAttribAPPLE);
  25.614 +        GLELoadProc(glEnableVertexAttribAPPLE_Impl, glEnableVertexAttribAPPLE);
  25.615 +        GLELoadProc(glIsVertexAttribEnabledAPPLE_Impl, glIsVertexAttribEnabledAPPLE);
  25.616 +        GLELoadProc(glMapVertexAttrib1dAPPLE_Impl, glMapVertexAttrib1dAPPLE);
  25.617 +        GLELoadProc(glMapVertexAttrib1fAPPLE_Impl, glMapVertexAttrib1fAPPLE);
  25.618 +        GLELoadProc(glMapVertexAttrib2dAPPLE_Impl, glMapVertexAttrib2dAPPLE);
  25.619 +        GLELoadProc(glMapVertexAttrib2fAPPLE_Impl, glMapVertexAttrib2fAPPLE);
  25.620 +        
  25.621 +      #endif // GLE_CGL_ENABLED
  25.622 +      
  25.623 +        // GL_ARB_debug_output
  25.624 +        GLELoadProc(glDebugMessageCallbackARB_Impl, glDebugMessageCallbackARB);
  25.625 +        GLELoadProc(glDebugMessageControlARB_Impl, glDebugMessageControlARB);
  25.626 +        GLELoadProc(glDebugMessageInsertARB_Impl, glDebugMessageInsertARB);
  25.627 +        GLELoadProc(glGetDebugMessageLogARB_Impl, glGetDebugMessageLogARB);
  25.628 +        
  25.629 +        // GL_ARB_ES2_compatibility
  25.630 +        GLELoadProc(glClearDepthf_Impl, glClearDepthf);
  25.631 +        GLELoadProc(glDepthRangef_Impl, glDepthRangef);
  25.632 +        GLELoadProc(glGetShaderPrecisionFormat_Impl, glGetShaderPrecisionFormat);
  25.633 +        GLELoadProc(glReleaseShaderCompiler_Impl, glReleaseShaderCompiler);
  25.634 +        GLELoadProc(glShaderBinary_Impl, glShaderBinary);
  25.635 +
  25.636 +        // GL_ARB_framebuffer_object
  25.637 +        GLELoadProc(glBindFramebuffer_Impl, glBindFramebuffer);
  25.638 +        GLELoadProc(glBindRenderbuffer_Impl, glBindRenderbuffer);
  25.639 +        GLELoadProc(glBlitFramebuffer_Impl, glBlitFramebuffer);
  25.640 +        GLELoadProc(glCheckFramebufferStatus_Impl, glCheckFramebufferStatus);
  25.641 +        GLELoadProc(glDeleteFramebuffers_Impl, glDeleteFramebuffers);
  25.642 +        GLELoadProc(glDeleteRenderbuffers_Impl, glDeleteRenderbuffers);
  25.643 +        GLELoadProc(glFramebufferRenderbuffer_Impl, glFramebufferRenderbuffer);
  25.644 +        GLELoadProc(glFramebufferTexture1D_Impl, glFramebufferTexture1D);
  25.645 +        GLELoadProc(glFramebufferTexture2D_Impl, glFramebufferTexture2D);
  25.646 +        GLELoadProc(glFramebufferTexture3D_Impl, glFramebufferTexture3D);
  25.647 +        GLELoadProc(glFramebufferTextureLayer_Impl, glFramebufferTextureLayer);
  25.648 +        GLELoadProc(glGenFramebuffers_Impl, glGenFramebuffers);
  25.649 +        GLELoadProc(glGenRenderbuffers_Impl, glGenRenderbuffers);
  25.650 +        GLELoadProc(glGenerateMipmap_Impl, glGenerateMipmap);
  25.651 +        GLELoadProc(glGetFramebufferAttachmentParameteriv_Impl, glGetFramebufferAttachmentParameteriv);
  25.652 +        GLELoadProc(glGetRenderbufferParameteriv_Impl, glGetRenderbufferParameteriv);
  25.653 +        GLELoadProc(glIsFramebuffer_Impl, glIsFramebuffer);
  25.654 +        GLELoadProc(glIsRenderbuffer_Impl, glIsRenderbuffer);
  25.655 +        GLELoadProc(glRenderbufferStorage_Impl, glRenderbufferStorage);
  25.656 +        GLELoadProc(glRenderbufferStorageMultisample_Impl, glRenderbufferStorageMultisample);
  25.657 +
  25.658 +        if(!glBindFramebuffer_Impl) // This will rarely if ever be the case in practice with modern computers and drivers.
  25.659 +        {
  25.660 +            // See if we can map GL_EXT_framebuffer_object to GL_ARB_framebuffer_object. The former is basically a subset of the latter, but we use only that subset.
  25.661 +            GLELoadProc(glBindFramebuffer_Impl, glBindFramebufferEXT);
  25.662 +            GLELoadProc(glBindRenderbuffer_Impl, glBindRenderbufferEXT);
  25.663 +          //GLELoadProc(glBlitFramebuffer_Impl, glBlitFramebufferEXT (nonexistent));
  25.664 +            GLELoadProc(glCheckFramebufferStatus_Impl, glCheckFramebufferStatusEXT);
  25.665 +            GLELoadProc(glDeleteFramebuffers_Impl, glDeleteFramebuffersEXT);
  25.666 +            GLELoadProc(glDeleteRenderbuffers_Impl, glDeleteRenderbuffersEXT);
  25.667 +            GLELoadProc(glFramebufferRenderbuffer_Impl, glFramebufferRenderbufferEXT);
  25.668 +            GLELoadProc(glFramebufferTexture1D_Impl, glFramebufferTexture1DEXT);
  25.669 +            GLELoadProc(glFramebufferTexture2D_Impl, glFramebufferTexture2DEXT);
  25.670 +            GLELoadProc(glFramebufferTexture3D_Impl, glFramebufferTexture3DEXT);
  25.671 +          //GLELoadProc(glFramebufferTextureLayer_Impl, glFramebufferTextureLayerEXT (nonexistent));
  25.672 +            GLELoadProc(glGenFramebuffers_Impl, glGenFramebuffersEXT);
  25.673 +            GLELoadProc(glGenRenderbuffers_Impl, glGenRenderbuffersEXT);
  25.674 +            GLELoadProc(glGenerateMipmap_Impl, glGenerateMipmapEXT);
  25.675 +            GLELoadProc(glGetFramebufferAttachmentParameteriv_Impl, glGetFramebufferAttachmentParameterivEXT);
  25.676 +            GLELoadProc(glGetRenderbufferParameteriv_Impl, glGetRenderbufferParameterivEXT);
  25.677 +            GLELoadProc(glIsFramebuffer_Impl, glIsFramebufferEXT);
  25.678 +            GLELoadProc(glIsRenderbuffer_Impl, glIsRenderbufferEXT);
  25.679 +            GLELoadProc(glRenderbufferStorage_Impl, glRenderbufferStorageEXT);
  25.680 +          //GLELoadProc(glRenderbufferStorageMultisample_Impl, glRenderbufferStorageMultisampleEXT (nonexistent));
  25.681 +        }
  25.682 +        
  25.683 +        // GL_ARB_texture_multisample
  25.684 +        GLELoadProc(glGetMultisamplefv_Impl, glGetMultisamplefv);
  25.685 +        GLELoadProc(glSampleMaski_Impl, glSampleMaski);
  25.686 +        GLELoadProc(glTexImage2DMultisample_Impl, glTexImage2DMultisample);
  25.687 +        GLELoadProc(glTexImage3DMultisample_Impl, glTexImage3DMultisample);
  25.688 +        
  25.689 +        // GL_ARB_timer_query
  25.690 +        GLELoadProc(glGetQueryObjecti64v_Impl, glGetQueryObjecti64v);
  25.691 +        GLELoadProc(glGetQueryObjectui64v_Impl, glGetQueryObjectui64v);
  25.692 +        GLELoadProc(glQueryCounter_Impl, glQueryCounter);
  25.693 +
  25.694 +        // GL_ARB_vertex_array_object
  25.695 +        GLELoadProc(glBindVertexArray_Impl, glBindVertexArray);
  25.696 +        GLELoadProc(glDeleteVertexArrays_Impl, glDeleteVertexArrays);
  25.697 +        GLELoadProc(glGenVertexArrays_Impl, glGenVertexArrays);
  25.698 +        GLELoadProc(glIsVertexArray_Impl, glIsVertexArray);
  25.699 +
  25.700 +        #if defined(GLE_CGL_ENABLED) // Apple OpenGL...
  25.701 +            if(WholeVersion < 302) // It turns out that Apple OpenGL versions prior to 3.2 have glBindVertexArray, etc. but they silently fail by default. So always use the APPLE version.
  25.702 +            {
  25.703 +                glBindVertexArray_Impl    = glBindVertexArrayAPPLE_Impl;
  25.704 +                glDeleteVertexArrays_Impl = glDeleteVertexArraysAPPLE_Impl;
  25.705 +                glGenVertexArrays_Impl    = (OVRTypeof(glGenVertexArrays_Impl)) glGenVertexArraysAPPLE_Impl; // There is a const cast of the arrays argument here due to a slight difference in the Apple behavior. For our purposes it should be OK.
  25.706 +                glIsVertexArray_Impl      = glIsVertexArrayAPPLE_Impl;
  25.707 +                
  25.708 +                if(glBindVertexArray_Impl)
  25.709 +                    gle_ARB_vertex_array_object = true; // We are routing the APPLE version through our version, with the assumption that we use the ARB version the same as we would use the APPLE version.
  25.710 +            }
  25.711 +        #endif
  25.712 +        
  25.713 +        // GL_EXT_draw_buffers2
  25.714 +        GLELoadProc(glColorMaskIndexedEXT_Impl, glColorMaskIndexedEXT);
  25.715 +        GLELoadProc(glDisableIndexedEXT_Impl, glDisableIndexedEXT);
  25.716 +        GLELoadProc(glEnableIndexedEXT_Impl, glEnableIndexedEXT);
  25.717 +        GLELoadProc(glGetBooleanIndexedvEXT_Impl, glGetBooleanIndexedvEXT);
  25.718 +        GLELoadProc(glGetIntegerIndexedvEXT_Impl, glGetIntegerIndexedvEXT);
  25.719 +        GLELoadProc(glIsEnabledIndexedEXT_Impl, glIsEnabledIndexedEXT);
  25.720 +
  25.721 +        // GL_KHR_debug
  25.722 +        GLELoadProc(glDebugMessageCallback_Impl, glDebugMessageCallback);
  25.723 +        GLELoadProc(glDebugMessageControl_Impl, glDebugMessageControl);
  25.724 +        GLELoadProc(glDebugMessageInsert_Impl, glDebugMessageInsert);
  25.725 +        GLELoadProc(glGetDebugMessageLog_Impl, glGetDebugMessageLog);
  25.726 +        GLELoadProc(glGetObjectLabel_Impl, glGetObjectLabel);
  25.727 +        GLELoadProc(glGetObjectPtrLabel_Impl, glGetObjectPtrLabel);
  25.728 +        GLELoadProc(glObjectLabel_Impl, glObjectLabel);
  25.729 +        GLELoadProc(glObjectPtrLabel_Impl, glObjectPtrLabel);
  25.730 +        GLELoadProc(glPopDebugGroup_Impl, glPopDebugGroup);
  25.731 +        GLELoadProc(glPushDebugGroup_Impl, glPushDebugGroup);
  25.732 +
  25.733 +        // GL_WIN_swap_hint
  25.734 +        GLELoadProc(glAddSwapHintRectWIN_Impl, glAddSwapHintRectWIN);
  25.735 +    }
  25.736 +    
  25.737 +
  25.738 +
  25.739 +    OVR_DISABLE_MSVC_WARNING(4510 4512 4610) // default constructor could not be generated,
  25.740 +    struct ValueStringPair
  25.741 +    {
  25.742 +        bool& IsPresent;
  25.743 +        const char* ExtensionName;
  25.744 +    };
  25.745 +
  25.746 +
  25.747 +    // Helper function for InitExtensionSupport.
  25.748 +    static void CheckExtensions(ValueStringPair* pValueStringPairArray, size_t arrayCount, const char* extensions)
  25.749 +    {
  25.750 +        // We search the extesion list string for each of the individual extensions we are interested in. 
  25.751 +        // We do this by walking over the string and comparing each entry in turn to our array of entries of interest.
  25.752 +        // Example string (with patholigical extra spaces): "   ext1 ext2   ext3  "
  25.753 +           
  25.754 +        char extension[64];
  25.755 +        const char* p = extensions; // p points to the beginning of the current word
  25.756 +        const char* pEnd;           // pEnd points to one-past the last character of the current word. It is where the trailing '\0' of the string would be.
  25.757 +           
  25.758 +        while(*p)
  25.759 +        {
  25.760 +            while(*p == ' ') // Find the next word begin.
  25.761 +                ++p;
  25.762 +                
  25.763 +            pEnd = p;
  25.764 +               
  25.765 +            while((*pEnd != '\0') && (*pEnd != ' ')) // Find the next word end.
  25.766 +                ++pEnd;
  25.767 +               
  25.768 +            if(((pEnd - p) > 0) && ((size_t)(pEnd - p) < OVR_ARRAY_COUNT(extension)))
  25.769 +            {
  25.770 +                memcpy(extension, p, pEnd - p); // To consider: Revise this code to directly read from p/pEnd instead of doing a memcpy.
  25.771 +                extension[pEnd - p] = '\0';
  25.772 +                   
  25.773 +                for(size_t i = 0; i < arrayCount; i++) // For each extension we are interested in...
  25.774 +                {
  25.775 +                    ValueStringPair& vsp = pValueStringPairArray[i];
  25.776 + 
  25.777 +                    if(strcmp(extension, vsp.ExtensionName) == 0) // case-sensitive compare
  25.778 +                        pValueStringPairArray[i].IsPresent = true;
  25.779 +                }
  25.780 +            }
  25.781 +               
  25.782 +            p = pEnd;
  25.783 +        }
  25.784 +    }
  25.785 +
  25.786 +
  25.787 +    void OVR::GLEContext::InitExtensionSupport()
  25.788 +    {
  25.789 +        // It may be better in the long run to use a member STL map<const char*, bool>.
  25.790 +        // It would make this loading code cleaner, though it would make lookups slower.
  25.791 +
  25.792 +        ValueStringPair vspArray[] =
  25.793 +        {
  25.794 +            { gle_AMD_debug_output, "GL_AMD_debug_output" },
  25.795 +          #if defined(GLE_CGL_ENABLED)
  25.796 +            { gle_APPLE_aux_depth_stencil, "GL_APPLE_aux_depth_stencil" },
  25.797 +            { gle_APPLE_client_storage, "GL_APPLE_client_storage" },
  25.798 +            { gle_APPLE_element_array, "GL_APPLE_element_array" },
  25.799 +            { gle_APPLE_fence, "GL_APPLE_fence" },
  25.800 +            { gle_APPLE_float_pixels, "GL_APPLE_float_pixels" },
  25.801 +            { gle_APPLE_flush_buffer_range, "GL_APPLE_flush_buffer_range" },
  25.802 +            { gle_APPLE_object_purgeable, "GL_APPLE_object_purgeable" },
  25.803 +            { gle_APPLE_pixel_buffer, "GL_APPLE_pixel_buffer" },
  25.804 +            { gle_APPLE_rgb_422, "GL_APPLE_rgb_422" },
  25.805 +            { gle_APPLE_row_bytes, "GL_APPLE_row_bytes" },
  25.806 +            { gle_APPLE_specular_vector, "GL_APPLE_specular_vector" },
  25.807 +            { gle_APPLE_texture_range, "GL_APPLE_texture_range" },
  25.808 +            { gle_APPLE_transform_hint, "GL_APPLE_transform_hint" },
  25.809 +            { gle_APPLE_vertex_array_object, "GL_APPLE_vertex_array_object" },
  25.810 +            { gle_APPLE_vertex_array_range, "GL_APPLE_vertex_array_range" },
  25.811 +            { gle_APPLE_vertex_program_evaluators, "GL_APPLE_vertex_program_evaluators" },
  25.812 +            { gle_APPLE_ycbcr_422, "GL_APPLE_ycbcr_422" },
  25.813 +          #endif
  25.814 +            { gle_ARB_debug_output, "GL_ARB_debug_output" },
  25.815 +            { gle_ARB_depth_buffer_float, "GL_ARB_depth_buffer_float" },
  25.816 +            { gle_ARB_ES2_compatibility, "GL_ARB_ES2_compatibility" },
  25.817 +            { gle_ARB_framebuffer_object, "GL_ARB_framebuffer_object" },
  25.818 +            { gle_ARB_framebuffer_object, "GL_EXT_framebuffer_object" },    // We map glBindFramebuffer, etc. to glBindFramebufferEXT, etc. if necessary
  25.819 +            { gle_ARB_framebuffer_sRGB, "GL_ARB_framebuffer_sRGB" },
  25.820 +            { gle_ARB_texture_multisample, "GL_ARB_texture_multisample" },
  25.821 +            { gle_ARB_texture_non_power_of_two, "GL_ARB_texture_non_power_of_two" },
  25.822 +            { gle_ARB_texture_rectangle, "GL_ARB_texture_rectangle" },
  25.823 +            { gle_ARB_texture_rectangle, "GL_EXT_texture_rectangle" },  // We also check for GL_EXT_texture_rectangle and GL_NV_texture_rectangle.
  25.824 +            { gle_ARB_texture_rectangle, "GL_NV_texture_rectangle" },
  25.825 +            { gle_ARB_timer_query, "GL_ARB_timer_query" },
  25.826 +            { gle_ARB_vertex_array_object, "GL_ARB_vertex_array_object" },
  25.827 +            { gle_EXT_draw_buffers2, "GL_EXT_draw_buffers2" },
  25.828 +            { gle_EXT_texture_compression_s3tc, "GL_EXT_texture_compression_s3tc" },
  25.829 +            { gle_EXT_texture_filter_anisotropic, "GL_EXT_texture_filter_anisotropic" },
  25.830 +            { gle_KHR_debug, "GL_KHR_debug" },
  25.831 +            { gle_WIN_swap_hint, "GL_WIN_swap_hint" }
  25.832 +            // Windows WGL, Unix GLX, and Apple CGL extensions are handled below, as they require different calls from glGetString(GL_EXTENSIONS).
  25.833 +        };
  25.834 +
  25.835 +        // We cannot use glGetString(GL_EXTENSIONS) when an OpenGL core profile is active,
  25.836 +        // as it's deprecated in favor of using OpenGL 3+ glGetStringi.
  25.837 +        const char* extensions = (MajorVersion < 3) ? (const char*)glGetString(GL_EXTENSIONS) : "";
  25.838 +       
  25.839 +        if (extensions && *extensions) // If we have a space-delimited extension string to search for individual extensions...
  25.840 +        {
  25.841 +            OVR_DEBUG_LOG(("GL_EXTENSIONS: %s", (const char*)extensions));
  25.842 +            CheckExtensions(vspArray, OVR_ARRAY_COUNT(vspArray), extensions); // Call our shared helper function for this.
  25.843 +        }
  25.844 +        else
  25.845 +        {
  25.846 +            if(MajorVersion >= 3) // If glGetIntegerv(GL_NUM_EXTENSIONS, ...) is supported...
  25.847 +            {
  25.848 +                // In this case we need to match an array of individual extensions against an array of
  25.849 +                // externsions provided by glGetStringi. This is an O(n^2) operation, but at least we
  25.850 +                // are doing this only once on startup. There are a few tricks we can employ to speed
  25.851 +                // up the logic below, but they may not be worth much.
  25.852 +               
  25.853 +                GLint extensionCount = 0;
  25.854 +                glGetIntegerv(GL_NUM_EXTENSIONS, &extensionCount);
  25.855 +                GLenum err = glGetError();
  25.856 +               
  25.857 +                if(err == 0)
  25.858 +                {
  25.859 +                    #ifdef OVR_BUILD_DEBUG
  25.860 +                    OVR::StringBuffer extensionsStr;
  25.861 +                    #endif
  25.862 + 
  25.863 +                    for(GLint e = 0; e != extensionCount; ++e) // For each extension supported...
  25.864 +                    {
  25.865 +                        const char* extension = (const char*)glGetStringi(GL_EXTENSIONS, (GLuint)e);
  25.866 + 
  25.867 +                        if(extension) // glGetStringi returns NULL upon error.
  25.868 +                        {
  25.869 +                            #ifdef OVR_BUILD_DEBUG
  25.870 +                                extensionsStr.AppendFormat(" %s", extension);
  25.871 +                            #endif
  25.872 + 
  25.873 +                            for(size_t i = 0; i < OVR_ARRAY_COUNT(vspArray); i++) // For each extension we are interested in...
  25.874 +                            {
  25.875 +                                ValueStringPair& vsp = vspArray[i];
  25.876 + 
  25.877 +                                if(strcmp(extension, vsp.ExtensionName) == 0) // case-sensitive compare
  25.878 +                                    vspArray[i].IsPresent = true;
  25.879 +                            }
  25.880 +                        }
  25.881 +                        else
  25.882 +                            break;
  25.883 +                    }
  25.884 + 
  25.885 +                    OVR_DEBUG_LOG(("GL_EXTENSIONS: %s", extensionsStr.ToCStr()));
  25.886 +                }
  25.887 +            }
  25.888 +            // Else we have a problem: no means to read the extensions was successful.
  25.889 +        }
  25.890 +
  25.891 +        #if defined(GLE_CGL_ENABLED)
  25.892 +            // The following are built into Apple OpenGL 3.2+ (declared in <OpenGL/gl3.h>) and not identified as extensions.
  25.893 +            // On other platforms (e.g. Windows) these are identified as extensions and are detected above.
  25.894 +            if(WholeVersion >= 302)
  25.895 +            {
  25.896 +                gle_ARB_depth_buffer_float       = true;
  25.897 +                gle_ARB_framebuffer_object       = true;
  25.898 +                gle_ARB_framebuffer_sRGB         = true;
  25.899 +                gle_ARB_texture_multisample      = true;
  25.900 +                gle_ARB_texture_non_power_of_two = true;
  25.901 +                gle_ARB_texture_rectangle        = true;
  25.902 +                gle_ARB_vertex_array_object      = true;
  25.903 +            }
  25.904 +        #endif
  25.905 +
  25.906 +    } // GLEContext::InitExtensionSupport()
  25.907 +        
  25.908 +
  25.909 +    void OVR::GLEContext::InitPlatformVersion()
  25.910 +    {
  25.911 +        #if defined(GLE_GLX_ENABLED)
  25.912 +            const char* pGLXVersion = glXGetClientString(glXGetCurrentDisplay(), GLX_VERSION); // To do: Use a better mechanism to get the desired display.
  25.913 +            sscanf(pGLXVersion, "%d.%d", &PlatformMajorVersion, &PlatformMinorVersion);
  25.914 +
  25.915 +        #elif defined(GLE_EGL_ENABLED)
  25.916 +            const char* pEGLVersion = eglQueryString(eglGetDisplay(EGL_DEFAULT_DISPLAY), EGL_VERSION);
  25.917 +            sscanf(pEGLVersion, "%d.%d", &PlatformMajorVersion, &PlatformMinorVersion);
  25.918 +
  25.919 +        #else
  25.920 +            PlatformMajorVersion = 1;
  25.921 +            PlatformMinorVersion = 0;
  25.922 +            PlatformWholeVersion = 100;
  25.923 +        #endif
  25.924 +    }
  25.925 +
  25.926 +
  25.927 +    void OVR::GLEContext::InitPlatformExtensionLoad()
  25.928 +    {
  25.929 +        #if defined(GLE_WGL_ENABLED)
  25.930 +            // WGL
  25.931 +            // We don't load these as function pointers but rather statically link to them.
  25.932 +            // These need to be loaded via LoadLibrary instead of wglLoadLibrary.
  25.933 +
  25.934 +            #if 0
  25.935 +        	HINSTANCE hOpenGL = LoadLibraryW(L"Opengl32.dll");
  25.936 +            if(hOpenGL)
  25.937 +            {
  25.938 +                wglCopyContext_Impl            = (OVRTypeof(wglCopyContext_Impl)) GetProcAddress(hOpenGL, "wglCopyContext");
  25.939 +                wglCreateContext_Impl          = (OVRTypeof(wglCreateContext_Impl)) GetProcAddress(hOpenGL, "wglCreateContext");
  25.940 +                wglCreateLayerContext_Impl     = (OVRTypeof(wglCreateLayerContext_Impl)) GetProcAddress(hOpenGL, "wglCreateLayerContext");
  25.941 +                wglDeleteContext_Impl          = (OVRTypeof(wglDeleteContext_Impl)) GetProcAddress(hOpenGL, "wglDeleteContext");
  25.942 +                wglGetCurrentContext_Impl      = (OVRTypeof(wglGetCurrentContext_Impl)) GetProcAddress(hOpenGL, "wglGetCurrentContext");
  25.943 +                wglGetCurrentDC_Impl           = (OVRTypeof(wglGetCurrentDC_Impl)) GetProcAddress(hOpenGL, "wglGetCurrentDC");
  25.944 +                wglGetProcAddress_Impl         = (OVRTypeof(wglGetProcAddress_Impl)) GetProcAddress(hOpenGL, "wglGetProcAddress");
  25.945 +                wglMakeCurrent_Impl            = (OVRTypeof(wglMakeCurrent_Impl)) GetProcAddress(hOpenGL, "wglMakeCurrent");
  25.946 +                wglShareLists_Impl             = (OVRTypeof(wglShareLists_Impl)) GetProcAddress(hOpenGL, "wglShareLists");
  25.947 +                wglUseFontBitmapsA_Impl        = (OVRTypeof(wglUseFontBitmapsA_Impl)) GetProcAddress(hOpenGL, "wglUseFontBitmapsA");
  25.948 +                wglUseFontBitmapsW_Impl        = (OVRTypeof(wglUseFontBitmapsW_Impl)) GetProcAddress(hOpenGL, "wglUseFontBitmapsW");
  25.949 +                wglUseFontOutlinesA_Impl       = (OVRTypeof(wglUseFontOutlinesA_Impl)) GetProcAddress(hOpenGL, "wglUseFontOutlinesA");
  25.950 +                wglUseFontOutlinesW_Impl       = (OVRTypeof(wglUseFontOutlinesW_Impl)) GetProcAddress(hOpenGL, "wglUseFontOutlinesW");
  25.951 +                wglDescribeLayerPlane_Impl     = (OVRTypeof(wglDescribeLayerPlane_Impl)) GetProcAddress(hOpenGL, "wglDescribeLayerPlane");
  25.952 +                wglSetLayerPaletteEntries_Impl = (OVRTypeof(wglSetLayerPaletteEntries_Impl)) GetProcAddress(hOpenGL, "wglSetLayerPaletteEntries");
  25.953 +                wglGetLayerPaletteEntries_Impl = (OVRTypeof(wglGetLayerPaletteEntries_Impl)) GetProcAddress(hOpenGL, "wglGetLayerPaletteEntries");
  25.954 +                wglRealizeLayerPalette_Impl    = (OVRTypeof(wglRealizeLayerPalette_Impl)) GetProcAddress(hOpenGL, "wglRealizeLayerPalette");
  25.955 +                wglSwapLayerBuffers_Impl       = (OVRTypeof(wglSwapLayerBuffers_Impl)) GetProcAddress(hOpenGL, "wglSwapLayerBuffers");
  25.956 +                wglSwapMultipleBuffers_Impl    = (OVRTypeof(wglSwapMultipleBuffers_Impl)) GetProcAddress(hOpenGL, "wglSwapMultipleBuffers");
  25.957 +                FreeLibrary(hOpenGL);
  25.958 +            }
  25.959 +            #endif
  25.960 +
  25.961 +            // WGL_ARB_buffer_region
  25.962 +            GLELoadProc(wglCreateBufferRegionARB_Impl, wglCreateBufferRegionARB);
  25.963 +            GLELoadProc(wglDeleteBufferRegionARB_Impl, wglDeleteBufferRegionARB);
  25.964 +            GLELoadProc(wglSaveBufferRegionARB_Impl, wglSaveBufferRegionARB);
  25.965 +            GLELoadProc(wglRestoreBufferRegionARB_Impl, wglRestoreBufferRegionARB);
  25.966 +
  25.967 +            // WGL_ARB_extensions_string
  25.968 +            GLELoadProc(wglGetExtensionsStringARB_Impl, wglGetExtensionsStringARB);
  25.969 +
  25.970 +            // WGL_ARB_pixel_format
  25.971 +            GLELoadProc(wglGetPixelFormatAttribivARB_Impl, wglGetPixelFormatAttribivARB);
  25.972 +            GLELoadProc(wglGetPixelFormatAttribfvARB_Impl, wglGetPixelFormatAttribfvARB);
  25.973 +            GLELoadProc(wglChoosePixelFormatARB_Impl, wglChoosePixelFormatARB);
  25.974 +
  25.975 +            // WGL_ARB_make_current_read
  25.976 +            GLELoadProc(wglMakeContextCurrentARB_Impl, wglMakeContextCurrentARB);
  25.977 +            GLELoadProc(wglGetCurrentReadDCARB_Impl, wglGetCurrentReadDCARB);
  25.978 +
  25.979 +            // WGL_ARB_pbuffer
  25.980 +            GLELoadProc(wglCreatePbufferARB_Impl, wglCreatePbufferARB);
  25.981 +            GLELoadProc(wglGetPbufferDCARB_Impl, wglGetPbufferDCARB);
  25.982 +            GLELoadProc(wglReleasePbufferDCARB_Impl, wglReleasePbufferDCARB);
  25.983 +            GLELoadProc(wglDestroyPbufferARB_Impl, wglDestroyPbufferARB);
  25.984 +            GLELoadProc(wglQueryPbufferARB_Impl, wglQueryPbufferARB);
  25.985 +
  25.986 +            // WGL_ARB_render_texture
  25.987 +            GLELoadProc(wglBindTexImageARB_Impl, wglBindTexImageARB);
  25.988 +            GLELoadProc(wglReleaseTexImageARB_Impl, wglReleaseTexImageARB);
  25.989 +            GLELoadProc(wglSetPbufferAttribARB_Impl, wglSetPbufferAttribARB);
  25.990 +
  25.991 +            // WGL_NV_present_video
  25.992 +            GLELoadProc(wglEnumerateVideoDevicesNV_Impl, wglEnumerateVideoDevicesNV);
  25.993 +            GLELoadProc(wglBindVideoDeviceNV_Impl, wglBindVideoDeviceNV);
  25.994 +            GLELoadProc(wglQueryCurrentContextNV_Impl, wglQueryCurrentContextNV);
  25.995 +
  25.996 +            // WGL_ARB_create_context
  25.997 +            GLELoadProc(wglCreateContextAttribsARB_Impl, wglCreateContextAttribsARB);
  25.998 +
  25.999 +            // WGL_EXT_extensions_string
 25.1000 +            GLELoadProc(wglGetExtensionsStringEXT_Impl, wglGetExtensionsStringEXT);
 25.1001 +
 25.1002 +            // WGL_EXT_swap_control
 25.1003 +            GLELoadProc(wglGetSwapIntervalEXT_Impl, wglGetSwapIntervalEXT);
 25.1004 +            GLELoadProc(wglSwapIntervalEXT_Impl, wglSwapIntervalEXT);
 25.1005 +        
 25.1006 +            // WGL_OML_sync_control
 25.1007 +            GLELoadProc(wglGetSyncValuesOML_Impl, wglGetSyncValuesOML);
 25.1008 +            GLELoadProc(wglGetMscRateOML_Impl, wglGetMscRateOML);
 25.1009 +            GLELoadProc(wglSwapBuffersMscOML_Impl, wglSwapBuffersMscOML);
 25.1010 +            GLELoadProc(wglSwapLayerBuffersMscOML_Impl, wglSwapLayerBuffersMscOML);
 25.1011 +            GLELoadProc(wglWaitForMscOML_Impl, wglWaitForMscOML);
 25.1012 +            GLELoadProc(wglWaitForSbcOML_Impl, wglWaitForSbcOML);
 25.1013 +
 25.1014 +            // WGL_NV_video_output
 25.1015 +            GLELoadProc(wglGetVideoDeviceNV_Impl, wglGetVideoDeviceNV);
 25.1016 +            GLELoadProc(wglReleaseVideoDeviceNV_Impl, wglReleaseVideoDeviceNV);
 25.1017 +            GLELoadProc(wglBindVideoImageNV_Impl, wglBindVideoImageNV);
 25.1018 +            GLELoadProc(wglReleaseVideoImageNV_Impl, wglReleaseVideoImageNV);
 25.1019 +            GLELoadProc(wglSendPbufferToVideoNV_Impl, wglSendPbufferToVideoNV);
 25.1020 +            GLELoadProc(wglGetVideoInfoNV_Impl, wglGetVideoInfoNV);
 25.1021 +
 25.1022 +            // WGL_NV_swap_group
 25.1023 +            GLELoadProc(wglJoinSwapGroupNV_Impl, wglJoinSwapGroupNV);
 25.1024 +            GLELoadProc(wglBindSwapBarrierNV_Impl, wglBindSwapBarrierNV);
 25.1025 +            GLELoadProc(wglQuerySwapGroupNV_Impl, wglQuerySwapGroupNV);
 25.1026 +            GLELoadProc(wglQueryMaxSwapGroupsNV_Impl, wglQueryMaxSwapGroupsNV);
 25.1027 +            GLELoadProc(wglQueryFrameCountNV_Impl, wglQueryFrameCountNV);
 25.1028 +            GLELoadProc(wglResetFrameCountNV_Impl, wglResetFrameCountNV);
 25.1029 +
 25.1030 +            // WGL_NV_video_capture
 25.1031 +            GLELoadProc(wglBindVideoCaptureDeviceNV_Impl, wglBindVideoCaptureDeviceNV);
 25.1032 +            GLELoadProc(wglEnumerateVideoCaptureDevicesNV_Impl, wglEnumerateVideoCaptureDevicesNV);
 25.1033 +            GLELoadProc(wglLockVideoCaptureDeviceNV_Impl, wglLockVideoCaptureDeviceNV);
 25.1034 +            GLELoadProc(wglQueryVideoCaptureDeviceNV_Impl, wglQueryVideoCaptureDeviceNV);
 25.1035 +            GLELoadProc(wglReleaseVideoCaptureDeviceNV_Impl, wglReleaseVideoCaptureDeviceNV);
 25.1036 +
 25.1037 +            // WGL_NV_copy_image
 25.1038 +            GLELoadProc(wglCopyImageSubDataNV_Impl, wglCopyImageSubDataNV);
 25.1039 +
 25.1040 +            // WGL_NV_DX_interop
 25.1041 +            GLELoadProc(wglDXCloseDeviceNV_Impl, wglDXCloseDeviceNV);
 25.1042 +            GLELoadProc(wglDXLockObjectsNV_Impl, wglDXLockObjectsNV);
 25.1043 +            GLELoadProc(wglDXObjectAccessNV_Impl, wglDXObjectAccessNV);
 25.1044 +            GLELoadProc(wglDXOpenDeviceNV_Impl, wglDXOpenDeviceNV);
 25.1045 +            GLELoadProc(wglDXRegisterObjectNV_Impl, wglDXRegisterObjectNV);
 25.1046 +            GLELoadProc(wglDXSetResourceShareHandleNV_Impl, wglDXSetResourceShareHandleNV);
 25.1047 +            GLELoadProc(wglDXUnlockObjectsNV_Impl, wglDXUnlockObjectsNV);
 25.1048 +            GLELoadProc(wglDXUnregisterObjectNV_Impl, wglDXUnregisterObjectNV);
 25.1049 +
 25.1050 +        #elif defined(GLE_GLX_ENABLED)
 25.1051 +            // GLX_VERSION_1_1
 25.1052 +            // We don't create any pointers_Impl, because we assume these functions are always present.
 25.1053 +        
 25.1054 +            // GLX_VERSION_1_2
 25.1055 +            GLELoadProc(glXGetCurrentDisplay_Impl, glXGetCurrentDisplay);
 25.1056 +
 25.1057 +            // GLX_VERSION_1_3
 25.1058 +            GLELoadProc(glXChooseFBConfig_Impl, glXChooseFBConfig);
 25.1059 +            GLELoadProc(glXCreateNewContext_Impl, glXCreateNewContext);
 25.1060 +            GLELoadProc(glXCreatePbuffer_Impl, glXCreatePbuffer);
 25.1061 +            GLELoadProc(glXCreatePixmap_Impl, glXCreatePixmap);
 25.1062 +            GLELoadProc(glXCreateWindow_Impl, glXCreateWindow);
 25.1063 +            GLELoadProc(glXDestroyPbuffer_Impl, glXDestroyPbuffer);
 25.1064 +            GLELoadProc(glXDestroyPixmap_Impl, glXDestroyPixmap);
 25.1065 +            GLELoadProc(glXDestroyWindow_Impl, glXDestroyWindow);
 25.1066 +            GLELoadProc(glXGetCurrentReadDrawable_Impl, glXGetCurrentReadDrawable);
 25.1067 +            GLELoadProc(glXGetFBConfigAttrib_Impl, glXGetFBConfigAttrib);
 25.1068 +            GLELoadProc(glXGetFBConfigs_Impl, glXGetFBConfigs);
 25.1069 +            GLELoadProc(glXGetSelectedEvent_Impl, glXGetSelectedEvent);
 25.1070 +            GLELoadProc(glXGetVisualFromFBConfig_Impl, glXGetVisualFromFBConfig);
 25.1071 +            GLELoadProc(glXMakeContextCurrent_Impl, glXMakeContextCurrent);
 25.1072 +            GLELoadProc(glXQueryContext_Impl, glXQueryContext);
 25.1073 +            GLELoadProc(glXQueryDrawable_Impl, glXQueryDrawable);
 25.1074 +            GLELoadProc(glXSelectEvent_Impl, glXSelectEvent);
 25.1075 +
 25.1076 +            // GLX_VERSION_1_4
 25.1077 +            // Nothing to declare
 25.1078 +        
 25.1079 +            // GLX_ARB_create_context
 25.1080 +            GLELoadProc(glXCreateContextAttribsARB_Impl, glXCreateContextAttribsARB);
 25.1081 +
 25.1082 +            // GLX_EXT_swap_control
 25.1083 +            GLELoadProc(glXSwapIntervalEXT_Impl, glXSwapIntervalEXT);
 25.1084 + 
 25.1085 +            // GLX_OML_sync_control
 25.1086 +            GLELoadProc(glXGetMscRateOML_Impl, glXGetMscRateOML);
 25.1087 +            GLELoadProc(glXGetSyncValuesOML_Impl, glXGetSyncValuesOML);
 25.1088 +            GLELoadProc(glXGetSyncValuesOML_Impl, glXSwapBuffersMscOML);
 25.1089 +            GLELoadProc(glXSwapBuffersMscOML_Impl, glXSwapBuffersMscOML);
 25.1090 +            GLELoadProc(glXWaitForSbcOML_Impl, glXWaitForSbcOML);
 25.1091 +
 25.1092 +            // GLX_MESA_swap_control
 25.1093 +            GLELoadProc(glXGetSwapIntervalMESA_Impl, glXGetSwapIntervalMESA);
 25.1094 +            GLELoadProc(glXSwapIntervalMESA_Impl, glXSwapIntervalMESA);
 25.1095 +        #endif
 25.1096 +    }
 25.1097 +
 25.1098 +
 25.1099 +    void OVR::GLEContext::InitPlatformExtensionSupport()
 25.1100 +    {
 25.1101 +        #if defined(GLE_WGL_ENABLED)
 25.1102 +            // We need to use wglGetExtensionsStringARB or wglGetExtensionsStringEXT as opposed to above with glGetString(GL_EXTENSIONS).
 25.1103 +            ValueStringPair vspWGLArray[] =
 25.1104 +            {
 25.1105 +                 { gle_WGL_ARB_buffer_region, "WGL_ARB_buffer_region" }
 25.1106 +                ,{ gle_WGL_ARB_create_context, "WGL_ARB_create_context" }
 25.1107 +                ,{ gle_WGL_ARB_create_context_profile, "WGL_ARB_create_context_profile" }
 25.1108 +                ,{ gle_WGL_ARB_create_context_robustness, "WGL_ARB_create_context_robustness" }
 25.1109 +                ,{ gle_WGL_ARB_extensions_string, "WGL_ARB_extensions_string" }
 25.1110 +                ,{ gle_WGL_ARB_framebuffer_sRGB, "WGL_ARB_framebuffer_sRGB" }
 25.1111 +                ,{ gle_WGL_ARB_framebuffer_sRGB, "WGL_EXT_framebuffer_sRGB" }    // We map the EXT to the ARB.
 25.1112 +                ,{ gle_WGL_ARB_make_current_read, "WGL_ARB_make_current_read" }
 25.1113 +                ,{ gle_WGL_ARB_pbuffer, "WGL_ARB_pbuffer" }
 25.1114 +                ,{ gle_WGL_ARB_pixel_format, "WGL_ARB_pixel_format" }
 25.1115 +                ,{ gle_WGL_ARB_pixel_format_float, "WGL_ARB_pixel_format_float" }
 25.1116 +                ,{ gle_WGL_ARB_render_texture, "WGL_ARB_render_texture" }
 25.1117 +                ,{ gle_WGL_ATI_render_texture_rectangle, "WGL_ATI_render_texture_rectangle" }
 25.1118 +                ,{ gle_WGL_EXT_extensions_string, "WGL_EXT_extensions_string" }
 25.1119 +                ,{ gle_WGL_EXT_swap_control, "WGL_EXT_swap_control" }
 25.1120 +                ,{ gle_WGL_NV_copy_image, "WGL_NV_copy_image" }
 25.1121 +                ,{ gle_WGL_NV_DX_interop, "WGL_NV_DX_interop" }
 25.1122 +                ,{ gle_WGL_NV_DX_interop2, "WGL_NV_DX_interop2" }
 25.1123 +                ,{ gle_WGL_NV_present_video, "WGL_NV_present_video" }
 25.1124 +                ,{ gle_WGL_NV_render_texture_rectangle, "WGL_NV_render_texture_rectangle" }
 25.1125 +                ,{ gle_WGL_NV_swap_group, "WGL_NV_swap_group" }
 25.1126 +                ,{ gle_WGL_NV_video_capture, "WGL_NV_video_capture" }
 25.1127 +                ,{ gle_WGL_NV_video_output, "WGL_NV_video_output" }
 25.1128 +                ,{ gle_WGL_OML_sync_control, "WGL_OML_sync_control" }
 25.1129 +            };
 25.1130 +
 25.1131 +            const char* extensions = NULL;
 25.1132 +
 25.1133 +            if(wglGetExtensionsStringARB_Impl)
 25.1134 +                extensions = wglGetExtensionsStringARB_Impl(wglGetCurrentDC()); // To do: Use a better mechanism to get the desired HDC.
 25.1135 +            else if(wglGetExtensionsStringEXT_Impl)
 25.1136 +                extensions = wglGetExtensionsStringEXT_Impl();
 25.1137 +
 25.1138 +            if (extensions && *extensions)
 25.1139 +            {
 25.1140 +                OVR_DEBUG_LOG(("WGL_EXTENSIONS: %s", (const char*)extensions));
 25.1141 +                CheckExtensions(vspWGLArray, OVR_ARRAY_COUNT(vspWGLArray), extensions);
 25.1142 +            }
 25.1143 +
 25.1144 +        #elif defined(GLE_GLX_ENABLED)
 25.1145 +            ValueStringPair vspGLXArray[] =
 25.1146 +            {
 25.1147 +                 { gle_GLX_ARB_create_context,            "GLX_ARB_create_context" }
 25.1148 +                ,{ gle_GLX_ARB_create_context_profile,    "GLX_ARB_create_context_profile" }
 25.1149 +                ,{ gle_GLX_ARB_create_context_robustness, "GLX_ARB_create_context_robustness" }
 25.1150 +                ,{ gle_GLX_EXT_swap_control,              "GLX_EXT_swap_control" }
 25.1151 +                ,{ gle_GLX_OML_sync_control,              "GLX_OML_sync_control" }
 25.1152 +                ,{ gle_MESA_swap_control,                 "GLX_MESA_swap_control" }
 25.1153 +            };
 25.1154 +
 25.1155 +            const char* extensions = glXGetClientString(glXGetCurrentDisplay(), GLX_EXTENSIONS); // To do: Use a better mechanism to get the desired display.
 25.1156 +
 25.1157 +            if (extensions && *extensions)
 25.1158 +            {
 25.1159 +                OVR_DEBUG_LOG(("GLX_EXTENSIONS: %s", (const char*)extensions));
 25.1160 +                CheckExtensions(vspGLXArray, OVR_ARRAY_COUNT(vspGLXArray), extensions);
 25.1161 +            }
 25.1162 +        #endif
 25.1163 +    }
 25.1164 +
 25.1165 +
 25.1166 +    #if defined(GLE_HOOKING_ENABLED)
 25.1167 +
 25.1168 +        #undef glGetError
 25.1169 +        extern "C" { GLAPI GLenum GLAPIENTRY glGetError(); }
 25.1170 +
 25.1171 +        // Disabled until such time as it might be useful to enable for debug purposes.
 25.1172 +        //void OVR::GLEContext::PreHook(const char* functionName)
 25.1173 +        //{
 25.1174 +        //    if(EnableHookGetError)
 25.1175 +        //    {
 25.1176 +        //        int err = glGetError();
 25.1177 +        //
 25.1178 +        //        for(int i = 0; (i < 6) && (err != GL_NO_ERROR); i++) // 6 is an arbitrary cap to prevent infinite looping which would occur if the current GL context is invalid.
 25.1179 +        //        {
 25.1180 +        //            OVR_DEBUG_LOG(("GL Error prior to hook: %d (%#x) from %s", err, err, functionName ? functionName : "OpenGL")); OVR_UNUSED(functionName);
 25.1181 +        //            err = glGetError();
 25.1182 +        //        }
 25.1183 +        //    }
 25.1184 +        //}
 25.1185 +
 25.1186 +        void OVR::GLEContext::PostHook(const char* functionName)
 25.1187 +        {
 25.1188 +            if(EnableHookGetError)
 25.1189 +            {
 25.1190 +                // OpenGL Standard regarding error state: To allow for distributed implementations, there may be several error flags. If any single error flag has recorded an error, the value of that flag 
 25.1191 +                // is returned and that flag is reset to GL_NO_ERROR when glGetError is called. If more than one flag has recorded an error, glGetError returns and 
 25.1192 +                // clears an arbitrary error flag value. Thus, glGetError should always be called in a loop, until it returns GL_NO_ERROR, if all error flags are to be reset.
 25.1193 +                int err = glGetError();
 25.1194 +
 25.1195 +                for(int i = 0; (i < 6) && (err != GL_NO_ERROR); i++) // 6 is an arbitrary cap to prevent infinite looping which would occur if the current GL context is invalid.
 25.1196 +                {
 25.1197 +                    OVR_DEBUG_LOG(("GL Error: %d (%#x) from %s", err, err, functionName ? functionName : "OpenGL")); OVR_UNUSED(functionName);
 25.1198 +                    err = glGetError();
 25.1199 +                }
 25.1200 +            }
 25.1201 +        }
 25.1202 +
 25.1203 +
 25.1204 +        // OpenGL 1.1 link-based functions
 25.1205 +        #undef glAccum // Undefine the macro from our header so that we can directly call the real version of this function.
 25.1206 +        extern "C" { GLAPI void GLAPIENTRY glAccum(GLenum op, GLfloat value); }
 25.1207 +        void OVR::GLEContext::glAccum_Hook(GLenum op, GLfloat value)
 25.1208 +        {
 25.1209 +            glAccum(op, value);
 25.1210 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1211 +        }
 25.1212 +
 25.1213 +        #undef glAlphaFunc
 25.1214 +        extern "C" { GLAPI void GLAPIENTRY glAlphaFunc(GLenum func, GLclampf ref); }
 25.1215 +        void OVR::GLEContext::glAlphaFunc_Hook(GLenum func, GLclampf ref)
 25.1216 +        {
 25.1217 +            glAlphaFunc(func, ref);
 25.1218 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1219 +        }
 25.1220 +
 25.1221 +        #undef glAreTexturesResident
 25.1222 +        extern "C" { GLAPI GLboolean GLAPIENTRY glAreTexturesResident(GLsizei n, const GLuint *textures, GLboolean *residences); }
 25.1223 +        GLboolean OVR::GLEContext::glAreTexturesResident_Hook(GLsizei n, const GLuint *textures, GLboolean *residences)
 25.1224 +        {
 25.1225 +            GLboolean b = glAreTexturesResident(n, textures, residences);
 25.1226 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1227 +            return b;
 25.1228 +        }
 25.1229 +
 25.1230 +        #undef glArrayElement
 25.1231 +        extern "C" { GLAPI void GLAPIENTRY glArrayElement(GLint i); }
 25.1232 +        void OVR::GLEContext::glArrayElement_Hook(GLint i)
 25.1233 +        {
 25.1234 +            glArrayElement(i);
 25.1235 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1236 +        }
 25.1237 +
 25.1238 +        #undef glBegin
 25.1239 +        extern "C" { GLAPI void GLAPIENTRY glBegin(GLenum mode); }
 25.1240 +        void OVR::GLEContext::glBegin_Hook(GLenum mode)
 25.1241 +        {
 25.1242 +            glBegin(mode);
 25.1243 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1244 +        }
 25.1245 +
 25.1246 +        #undef glBindTexture
 25.1247 +        extern "C" { GLAPI void GLAPIENTRY glBindTexture(GLenum target, GLuint texture); }
 25.1248 +        void OVR::GLEContext::glBindTexture_Hook(GLenum target, GLuint texture)
 25.1249 +        {
 25.1250 +            glBindTexture(target, texture);
 25.1251 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1252 +        }
 25.1253 +
 25.1254 +        #undef glBitmap
 25.1255 +        extern "C" { GLAPI void GLAPIENTRY glBitmap(GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte *bitmap); }
 25.1256 +        void OVR::GLEContext::glBitmap_Hook(GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte *bitmap)
 25.1257 +        {
 25.1258 +            glBitmap(width, height, xorig, yorig, xmove, ymove, bitmap);
 25.1259 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1260 +        }
 25.1261 +
 25.1262 +        #undef glBlendFunc
 25.1263 +        extern "C" { GLAPI void GLAPIENTRY glBlendFunc(GLenum sfactor, GLenum dfactor); }
 25.1264 +        void OVR::GLEContext::glBlendFunc_Hook(GLenum sfactor, GLenum dfactor)
 25.1265 +        {
 25.1266 +            glBlendFunc(sfactor, dfactor);
 25.1267 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1268 +        }
 25.1269 +
 25.1270 +        #undef glCallList
 25.1271 +        extern "C" { GLAPI void GLAPIENTRY glCallList(GLuint list); }
 25.1272 +        void OVR::GLEContext::glCallList_Hook(GLuint list)
 25.1273 +        {
 25.1274 +            glCallList(list);
 25.1275 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1276 +        }
 25.1277 +
 25.1278 +        #undef glCallLists
 25.1279 +        extern "C" { GLAPI void GLAPIENTRY glCallLists(GLsizei n, GLenum type, const void *lists); }
 25.1280 +        void OVR::GLEContext::glCallLists_Hook(GLsizei n, GLenum type, const void *lists)
 25.1281 +        {
 25.1282 +            glCallLists(n, type, lists);
 25.1283 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1284 +        }
 25.1285 +
 25.1286 +        #undef glClear
 25.1287 +        extern "C" { GLAPI void GLAPIENTRY glClear(GLbitfield mask); }
 25.1288 +        void OVR::GLEContext::glClear_Hook(GLbitfield mask)
 25.1289 +        {
 25.1290 +            glClear(mask);
 25.1291 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1292 +        }
 25.1293 +
 25.1294 +        #undef glClearAccum
 25.1295 +        extern "C" { GLAPI void GLAPIENTRY glClearAccum(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); }
 25.1296 +        void OVR::GLEContext::glClearAccum_Hook(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
 25.1297 +        {
 25.1298 +            glClearAccum(red, green, blue, alpha);
 25.1299 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1300 +        }
 25.1301 +
 25.1302 +        #undef glClearColor
 25.1303 +        extern "C" { GLAPI void GLAPIENTRY glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); }
 25.1304 +        void OVR::GLEContext::glClearColor_Hook(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
 25.1305 +        {
 25.1306 +            glClearColor(red, green, blue, alpha);
 25.1307 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1308 +        }
 25.1309 +
 25.1310 +        #undef glClearDepth
 25.1311 +        extern "C" { GLAPI void GLAPIENTRY glClearDepth(GLclampd depth); }
 25.1312 +        void OVR::GLEContext::glClearDepth_Hook(GLclampd depth)
 25.1313 +        {
 25.1314 +            glClearDepth(depth);
 25.1315 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1316 +        }
 25.1317 +
 25.1318 +        #undef glClearIndex
 25.1319 +        extern "C" { GLAPI void GLAPIENTRY glClearIndex(GLfloat c); }
 25.1320 +        void OVR::GLEContext::glClearIndex_Hook(GLfloat c)
 25.1321 +        {
 25.1322 +            glClearIndex(c);
 25.1323 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1324 +        }
 25.1325 +
 25.1326 +        #undef glClearStencil
 25.1327 +        extern "C" { GLAPI void GLAPIENTRY glClearStencil(GLint s); }
 25.1328 +        void OVR::GLEContext::glClearStencil_Hook(GLint s)
 25.1329 +        {
 25.1330 +            glClearStencil(s);
 25.1331 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1332 +        }
 25.1333 +
 25.1334 +        #undef glClipPlane
 25.1335 +        extern "C" { GLAPI void GLAPIENTRY glClipPlane(GLenum plane, const GLdouble *equation); }
 25.1336 +        void OVR::GLEContext::glClipPlane_Hook(GLenum plane, const GLdouble *equation)
 25.1337 +        {
 25.1338 +            glClipPlane(plane, equation);
 25.1339 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1340 +        }
 25.1341 +
 25.1342 +        #undef glColor3b
 25.1343 +        extern "C" { GLAPI void GLAPIENTRY glColor3b(GLbyte red, GLbyte green, GLbyte blue); }
 25.1344 +        void OVR::GLEContext::glColor3b_Hook(GLbyte red, GLbyte green, GLbyte blue)
 25.1345 +        {
 25.1346 +            glColor3b(red, green, blue);
 25.1347 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1348 +        }
 25.1349 +
 25.1350 +        #undef glColor3bv
 25.1351 +        extern "C" { GLAPI void GLAPIENTRY glColor3bv(const GLbyte *v); }
 25.1352 +        void OVR::GLEContext::glColor3bv_Hook(const GLbyte *v)
 25.1353 +        {
 25.1354 +            glColor3bv(v);
 25.1355 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1356 +        }
 25.1357 +
 25.1358 +        #undef glColor3d
 25.1359 +        extern "C" { GLAPI void GLAPIENTRY glColor3d(GLdouble red, GLdouble green, GLdouble blue); }
 25.1360 +        void OVR::GLEContext::glColor3d_Hook(GLdouble red, GLdouble green, GLdouble blue)
 25.1361 +        {
 25.1362 +            glColor3d(red, green, blue);
 25.1363 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1364 +        }
 25.1365 +
 25.1366 +        #undef glColor3dv
 25.1367 +        extern "C" { GLAPI void GLAPIENTRY glColor3dv(const GLdouble *v); }
 25.1368 +        void OVR::GLEContext::glColor3dv_Hook(const GLdouble *v)
 25.1369 +        {
 25.1370 +            glColor3dv(v);
 25.1371 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1372 +        }
 25.1373 +
 25.1374 +        #undef glColor3f
 25.1375 +        extern "C" { GLAPI void GLAPIENTRY glColor3f(GLfloat red, GLfloat green, GLfloat blue); }
 25.1376 +        void OVR::GLEContext::glColor3f_Hook(GLfloat red, GLfloat green, GLfloat blue)
 25.1377 +        {
 25.1378 +            glColor3f(red, green, blue);
 25.1379 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1380 +        }
 25.1381 +
 25.1382 +        #undef glColor3fv
 25.1383 +        extern "C" { GLAPI void GLAPIENTRY glColor3fv(const GLfloat *v); }
 25.1384 +        void OVR::GLEContext::glColor3fv_Hook(const GLfloat *v)
 25.1385 +        {
 25.1386 +            glColor3fv(v);
 25.1387 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1388 +        }
 25.1389 +
 25.1390 +        #undef glColor3i
 25.1391 +        extern "C" { GLAPI void GLAPIENTRY glColor3i(GLint red, GLint green, GLint blue); }
 25.1392 +        void OVR::GLEContext::glColor3i_Hook(GLint red, GLint green, GLint blue)
 25.1393 +        {
 25.1394 +            glColor3i(red, green, blue);
 25.1395 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1396 +        }
 25.1397 +
 25.1398 +        #undef glColor3iv
 25.1399 +        extern "C" { GLAPI void GLAPIENTRY glColor3iv(const GLint *v); }
 25.1400 +        void OVR::GLEContext::glColor3iv_Hook(const GLint *v)
 25.1401 +        {
 25.1402 +            glColor3iv(v);
 25.1403 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1404 +        }
 25.1405 +
 25.1406 +        #undef glColor3s
 25.1407 +        extern "C" { GLAPI void GLAPIENTRY glColor3s(GLshort red, GLshort green, GLshort blue); }
 25.1408 +        void OVR::GLEContext::glColor3s_Hook(GLshort red, GLshort green, GLshort blue)
 25.1409 +        {
 25.1410 +            glColor3s(red, green, blue);
 25.1411 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1412 +        }
 25.1413 +
 25.1414 +        #undef glColor3sv
 25.1415 +        extern "C" { GLAPI void GLAPIENTRY glColor3sv(const GLshort *v); }
 25.1416 +        void OVR::GLEContext::glColor3sv_Hook(const GLshort *v)
 25.1417 +        {
 25.1418 +            glColor3sv(v);
 25.1419 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1420 +        }
 25.1421 +
 25.1422 +        #undef glColor3ub
 25.1423 +        extern "C" { GLAPI void GLAPIENTRY glColor3ub(GLubyte red, GLubyte green, GLubyte blue); }
 25.1424 +        void OVR::GLEContext::glColor3ub_Hook(GLubyte red, GLubyte green, GLubyte blue)
 25.1425 +        {
 25.1426 +            glColor3ub(red, green, blue);
 25.1427 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1428 +        }
 25.1429 +
 25.1430 +        #undef glColor3ubv
 25.1431 +        extern "C" { GLAPI void GLAPIENTRY glColor3ubv(const GLubyte *v); }
 25.1432 +        void OVR::GLEContext::glColor3ubv_Hook(const GLubyte *v)
 25.1433 +        {
 25.1434 +            glColor3ubv(v);
 25.1435 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1436 +        }
 25.1437 +
 25.1438 +        #undef glColor3ui
 25.1439 +        extern "C" { GLAPI void GLAPIENTRY glColor3ui(GLuint red, GLuint green, GLuint blue); }
 25.1440 +        void OVR::GLEContext::glColor3ui_Hook(GLuint red, GLuint green, GLuint blue)
 25.1441 +        {
 25.1442 +            glColor3ui(red, green, blue);
 25.1443 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1444 +        }
 25.1445 +
 25.1446 +        #undef glColor3uiv
 25.1447 +        extern "C" { GLAPI void GLAPIENTRY glColor3uiv(const GLuint *v); }
 25.1448 +        void OVR::GLEContext::glColor3uiv_Hook(const GLuint *v)
 25.1449 +        {
 25.1450 +            glColor3uiv(v);
 25.1451 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1452 +        }
 25.1453 +
 25.1454 +        #undef glColor3us
 25.1455 +        extern "C" { GLAPI void GLAPIENTRY glColor3us(GLushort red, GLushort green, GLushort blue); }
 25.1456 +        void OVR::GLEContext::glColor3us_Hook(GLushort red, GLushort green, GLushort blue)
 25.1457 +        {
 25.1458 +            glColor3us(red, green, blue);
 25.1459 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1460 +        }
 25.1461 +
 25.1462 +        #undef glColor3usv
 25.1463 +        extern "C" { GLAPI void GLAPIENTRY glColor3usv(const GLushort *v); }
 25.1464 +        void OVR::GLEContext::glColor3usv_Hook(const GLushort *v)
 25.1465 +        {
 25.1466 +            glColor3usv(v);
 25.1467 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1468 +        }
 25.1469 +
 25.1470 +        #undef glColor4b
 25.1471 +        extern "C" { GLAPI void GLAPIENTRY glColor4b(GLbyte red, GLbyte green, GLbyte blue, GLbyte alpha); }
 25.1472 +        void OVR::GLEContext::glColor4b_Hook(GLbyte red, GLbyte green, GLbyte blue, GLbyte alpha)
 25.1473 +        {
 25.1474 +            glColor4b(red, green, blue, alpha);
 25.1475 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1476 +        }
 25.1477 +
 25.1478 +        #undef glColor4bv
 25.1479 +        extern "C" { GLAPI void GLAPIENTRY glColor4bv(const GLbyte *v); }
 25.1480 +        void OVR::GLEContext::glColor4bv_Hook(const GLbyte *v)
 25.1481 +        {
 25.1482 +            glColor4bv(v);
 25.1483 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1484 +        }
 25.1485 +
 25.1486 +        #undef glColor4d
 25.1487 +        extern "C" { GLAPI void GLAPIENTRY glColor4d(GLdouble red, GLdouble green, GLdouble blue, GLdouble alpha); }
 25.1488 +        void OVR::GLEContext::glColor4d_Hook(GLdouble red, GLdouble green, GLdouble blue, GLdouble alpha)
 25.1489 +        {
 25.1490 +            glColor4d(red, green, blue, alpha);
 25.1491 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1492 +        }
 25.1493 +
 25.1494 +        #undef glColor4dv
 25.1495 +        extern "C" { GLAPI void GLAPIENTRY glColor4dv(const GLdouble *v); }
 25.1496 +        void OVR::GLEContext::glColor4dv_Hook(const GLdouble *v)
 25.1497 +        {
 25.1498 +            glColor4dv(v);
 25.1499 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1500 +        }
 25.1501 +
 25.1502 +        #undef glColor4f
 25.1503 +        extern "C" { GLAPI void GLAPIENTRY glColor4f(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); }
 25.1504 +        void OVR::GLEContext::glColor4f_Hook(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
 25.1505 +        {
 25.1506 +            glColor4f(red, green, blue, alpha);
 25.1507 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1508 +        }
 25.1509 +
 25.1510 +        #undef glColor4fv
 25.1511 +        extern "C" { GLAPI void GLAPIENTRY glColor4fv(const GLfloat *v); }
 25.1512 +        void OVR::GLEContext::glColor4fv_Hook(const GLfloat *v)
 25.1513 +        {
 25.1514 +            glColor4fv(v);
 25.1515 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1516 +        }
 25.1517 +
 25.1518 +        #undef glColor4i
 25.1519 +        extern "C" { GLAPI void GLAPIENTRY glColor4i(GLint red, GLint green, GLint blue, GLint alpha); }
 25.1520 +        void OVR::GLEContext::glColor4i_Hook(GLint red, GLint green, GLint blue, GLint alpha)
 25.1521 +        {
 25.1522 +            glColor4i(red, green, blue, alpha);
 25.1523 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1524 +        }
 25.1525 +
 25.1526 +        #undef glColor4iv
 25.1527 +        extern "C" { GLAPI void GLAPIENTRY glColor4iv(const GLint *v); }
 25.1528 +        void OVR::GLEContext::glColor4iv_Hook(const GLint *v)
 25.1529 +        {
 25.1530 +            glColor4iv(v);
 25.1531 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1532 +        }
 25.1533 +
 25.1534 +        #undef glColor4s
 25.1535 +        extern "C" { GLAPI void GLAPIENTRY glColor4s(GLshort red, GLshort green, GLshort blue, GLshort alpha); }
 25.1536 +        void OVR::GLEContext::glColor4s_Hook(GLshort red, GLshort green, GLshort blue, GLshort alpha)
 25.1537 +        {
 25.1538 +            glColor4s(red, green, blue, alpha);
 25.1539 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1540 +        }
 25.1541 +
 25.1542 +        #undef glColor4sv
 25.1543 +        extern "C" { GLAPI void GLAPIENTRY glColor4sv(const GLshort *v); }
 25.1544 +        void OVR::GLEContext::glColor4sv_Hook(const GLshort *v)
 25.1545 +        {
 25.1546 +            glColor4sv(v);
 25.1547 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1548 +        }
 25.1549 +
 25.1550 +        #undef glColor4ub
 25.1551 +        extern "C" { GLAPI void GLAPIENTRY glColor4ub(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha); }
 25.1552 +        void OVR::GLEContext::glColor4ub_Hook(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha)
 25.1553 +        {
 25.1554 +            glColor4ub(red, green, blue, alpha);
 25.1555 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1556 +        }
 25.1557 +
 25.1558 +        #undef glColor4ubv
 25.1559 +        extern "C" { GLAPI void GLAPIENTRY glColor4ubv(const GLubyte *v); }
 25.1560 +        void OVR::GLEContext::glColor4ubv_Hook(const GLubyte *v)
 25.1561 +        {
 25.1562 +            glColor4ubv(v);
 25.1563 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1564 +        }
 25.1565 +
 25.1566 +        #undef glColor4ui
 25.1567 +        extern "C" { GLAPI void GLAPIENTRY glColor4ui(GLuint red, GLuint green, GLuint blue, GLuint alpha); }
 25.1568 +        void OVR::GLEContext::glColor4ui_Hook(GLuint red, GLuint green, GLuint blue, GLuint alpha)
 25.1569 +        {
 25.1570 +            glColor4ui(red, green, blue, alpha);
 25.1571 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1572 +        }
 25.1573 +
 25.1574 +        #undef glColor4uiv
 25.1575 +        extern "C" { GLAPI void GLAPIENTRY glColor4uiv(const GLuint *v); }
 25.1576 +        void OVR::GLEContext::glColor4uiv_Hook(const GLuint *v)
 25.1577 +        {
 25.1578 +            glColor4uiv(v);
 25.1579 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1580 +        }
 25.1581 +
 25.1582 +        #undef glColor4us
 25.1583 +        extern "C" { GLAPI void GLAPIENTRY glColor4us(GLushort red, GLushort green, GLushort blue, GLushort alpha); }
 25.1584 +        void OVR::GLEContext::glColor4us_Hook(GLushort red, GLushort green, GLushort blue, GLushort alpha)
 25.1585 +        {
 25.1586 +            glColor4us(red, green, blue, alpha);
 25.1587 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1588 +        }
 25.1589 +
 25.1590 +        #undef glColor4usv
 25.1591 +        extern "C" { GLAPI void GLAPIENTRY glColor4usv(const GLushort *v); }
 25.1592 +        void OVR::GLEContext::glColor4usv_Hook(const GLushort *v)
 25.1593 +        {
 25.1594 +            glColor4usv(v);
 25.1595 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1596 +        }
 25.1597 +
 25.1598 +        #undef glColorMask
 25.1599 +        extern "C" { GLAPI void GLAPIENTRY glColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); }
 25.1600 +        void OVR::GLEContext::glColorMask_Hook(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)
 25.1601 +        {
 25.1602 +            glColorMask(red, green, blue, alpha);
 25.1603 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1604 +        }
 25.1605 +
 25.1606 +        #undef glColorMaterial
 25.1607 +        extern "C" { GLAPI void GLAPIENTRY glColorMaterial(GLenum face, GLenum mode); }
 25.1608 +        void OVR::GLEContext::glColorMaterial_Hook(GLenum face, GLenum mode)
 25.1609 +        {
 25.1610 +            glColorMaterial(face, mode);
 25.1611 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1612 +        }
 25.1613 +
 25.1614 +        #undef glColorPointer
 25.1615 +        extern "C" { GLAPI void GLAPIENTRY glColorPointer(GLint size, GLenum type, GLsizei stride, const void *pointer); }
 25.1616 +        void OVR::GLEContext::glColorPointer_Hook(GLint size, GLenum type, GLsizei stride, const void *pointer)
 25.1617 +        {
 25.1618 +            glColorPointer(size, type, stride, pointer);
 25.1619 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1620 +        }
 25.1621 +
 25.1622 +        #undef glCopyPixels
 25.1623 +        extern "C" { GLAPI void GLAPIENTRY glCopyPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type); }
 25.1624 +        void OVR::GLEContext::glCopyPixels_Hook(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type)
 25.1625 +        {
 25.1626 +            glCopyPixels(x, y, width, height, type);
 25.1627 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1628 +        }
 25.1629 +
 25.1630 +        #undef glCopyTexImage1D
 25.1631 +        extern "C" { GLAPI void GLAPIENTRY glCopyTexImage1D(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLint border); }
 25.1632 +        void OVR::GLEContext::glCopyTexImage1D_Hook(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLint border)
 25.1633 +        {
 25.1634 +            glCopyTexImage1D(target, level, internalFormat, x, y, width, border);
 25.1635 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1636 +        }
 25.1637 +
 25.1638 +        #undef glCopyTexImage2D
 25.1639 +        extern "C" { GLAPI void GLAPIENTRY glCopyTexImage2D(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); }
 25.1640 +        void OVR::GLEContext::glCopyTexImage2D_Hook(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border)
 25.1641 +        {
 25.1642 +            glCopyTexImage2D(target, level, internalFormat, x, y, width, height, border);
 25.1643 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1644 +        }
 25.1645 +
 25.1646 +        #undef glCopyTexSubImage1D
 25.1647 +        extern "C" { GLAPI void GLAPIENTRY glCopyTexSubImage1D(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); }
 25.1648 +        void OVR::GLEContext::glCopyTexSubImage1D_Hook(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width)
 25.1649 +        {
 25.1650 +            glCopyTexSubImage1D(target, level, xoffset, x, y, width);
 25.1651 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1652 +        }
 25.1653 +
 25.1654 +        #undef glCopyTexSubImage2D
 25.1655 +        extern "C" { GLAPI void GLAPIENTRY glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); }
 25.1656 +        void OVR::GLEContext::glCopyTexSubImage2D_Hook(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height)
 25.1657 +        {
 25.1658 +            glCopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
 25.1659 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1660 +        }
 25.1661 +
 25.1662 +        #undef glCullFace
 25.1663 +        extern "C" { GLAPI void GLAPIENTRY glCullFace(GLenum mode); }
 25.1664 +        void OVR::GLEContext::glCullFace_Hook(GLenum mode)
 25.1665 +        {
 25.1666 +            glCullFace(mode);
 25.1667 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1668 +        }
 25.1669 +
 25.1670 +        #undef glDeleteLists
 25.1671 +        extern "C" { GLAPI void GLAPIENTRY glDeleteLists(GLuint list, GLsizei range); }
 25.1672 +        void OVR::GLEContext::glDeleteLists_Hook(GLuint list, GLsizei range)
 25.1673 +        {
 25.1674 +            glDeleteLists(list, range);
 25.1675 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1676 +        }
 25.1677 +
 25.1678 +        #undef glDeleteTextures
 25.1679 +        extern "C" { GLAPI void GLAPIENTRY glDeleteTextures(GLsizei n, const GLuint *textures); }
 25.1680 +        void OVR::GLEContext::glDeleteTextures_Hook(GLsizei n, const GLuint *textures)
 25.1681 +        {
 25.1682 +            glDeleteTextures(n, textures);
 25.1683 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1684 +        }
 25.1685 +
 25.1686 +        #undef glDepthFunc
 25.1687 +        extern "C" { GLAPI void GLAPIENTRY glDepthFunc(GLenum func); }
 25.1688 +        void OVR::GLEContext::glDepthFunc_Hook(GLenum func)
 25.1689 +        {
 25.1690 +            glDepthFunc(func);
 25.1691 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1692 +        }
 25.1693 +
 25.1694 +        #undef glDepthMask
 25.1695 +        extern "C" { GLAPI void GLAPIENTRY glDepthMask(GLboolean flag); }
 25.1696 +        void OVR::GLEContext::glDepthMask_Hook(GLboolean flag)
 25.1697 +        {
 25.1698 +            glDepthMask(flag);
 25.1699 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1700 +        }
 25.1701 +
 25.1702 +        #undef glDepthRange
 25.1703 +        extern "C" { GLAPI void GLAPIENTRY glDepthRange(GLclampd zNear, GLclampd zFar); }
 25.1704 +        void OVR::GLEContext::glDepthRange_Hook(GLclampd zNear, GLclampd zFar)
 25.1705 +        {
 25.1706 +            glDepthRange(zNear, zFar);
 25.1707 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1708 +        }
 25.1709 +
 25.1710 +        #undef glDisable
 25.1711 +        extern "C" { GLAPI void GLAPIENTRY glDisable(GLenum cap); }
 25.1712 +        void OVR::GLEContext::glDisable_Hook(GLenum cap)
 25.1713 +        {
 25.1714 +            glDisable(cap);
 25.1715 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1716 +        }
 25.1717 +
 25.1718 +        #undef glDisableClientState
 25.1719 +        extern "C" { GLAPI void GLAPIENTRY glDisableClientState(GLenum array); }
 25.1720 +        void OVR::GLEContext::glDisableClientState_Hook(GLenum array)
 25.1721 +        {
 25.1722 +            glDisableClientState(array);
 25.1723 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1724 +        }
 25.1725 +
 25.1726 +        #undef glDrawArrays
 25.1727 +        extern "C" { GLAPI void GLAPIENTRY glDrawArrays(GLenum mode, GLint first, GLsizei count); }
 25.1728 +        void OVR::GLEContext::glDrawArrays_Hook(GLenum mode, GLint first, GLsizei count)
 25.1729 +        {
 25.1730 +            glDrawArrays(mode, first, count);
 25.1731 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1732 +        }
 25.1733 +
 25.1734 +        #undef glDrawBuffer
 25.1735 +        extern "C" { GLAPI void GLAPIENTRY glDrawBuffer(GLenum mode); }
 25.1736 +        void OVR::GLEContext::glDrawBuffer_Hook(GLenum mode)
 25.1737 +        {
 25.1738 +            glDrawBuffer(mode);
 25.1739 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1740 +        }
 25.1741 +
 25.1742 +        #undef glDrawElements
 25.1743 +        extern "C" { GLAPI void GLAPIENTRY glDrawElements(GLenum mode, GLsizei count, GLenum type, const void *indices); }
 25.1744 +        void OVR::GLEContext::glDrawElements_Hook(GLenum mode, GLsizei count, GLenum type, const void *indices)
 25.1745 +        {
 25.1746 +            glDrawElements(mode, count, type, indices);
 25.1747 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1748 +        }
 25.1749 +
 25.1750 +        #undef glDrawPixels
 25.1751 +        extern "C" { GLAPI void GLAPIENTRY glDrawPixels(GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels); }
 25.1752 +        void OVR::GLEContext::glDrawPixels_Hook(GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels)
 25.1753 +        {
 25.1754 +            glDrawPixels(width, height, format, type, pixels);
 25.1755 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1756 +        }
 25.1757 +
 25.1758 +        #undef glEdgeFlag
 25.1759 +        extern "C" { GLAPI void GLAPIENTRY glEdgeFlag(GLboolean flag); }
 25.1760 +        void OVR::GLEContext::glEdgeFlag_Hook(GLboolean flag)
 25.1761 +        {
 25.1762 +            glEdgeFlag(flag);
 25.1763 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1764 +        }
 25.1765 +
 25.1766 +        #undef glEdgeFlagPointer
 25.1767 +        extern "C" { GLAPI void GLAPIENTRY glEdgeFlagPointer(GLsizei stride, const void *pointer); }
 25.1768 +        void OVR::GLEContext::glEdgeFlagPointer_Hook(GLsizei stride, const void *pointer)
 25.1769 +        {
 25.1770 +            glEdgeFlagPointer(stride, pointer);
 25.1771 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1772 +        }
 25.1773 +
 25.1774 +        #undef glEdgeFlagv
 25.1775 +        extern "C" { GLAPI void GLAPIENTRY glEdgeFlagv(const GLboolean *flag); }
 25.1776 +        void OVR::GLEContext::glEdgeFlagv_Hook(const GLboolean *flag)
 25.1777 +        {
 25.1778 +            glEdgeFlagv(flag);
 25.1779 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1780 +        }
 25.1781 +
 25.1782 +        #undef glEnable
 25.1783 +        extern "C" { GLAPI void GLAPIENTRY glEnable(GLenum cap); }
 25.1784 +        namespace OVR {
 25.1785 +        void GLEContext::glEnable_Hook(GLenum cap)
 25.1786 +        {
 25.1787 +            glEnable(cap);
 25.1788 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1789 +        }
 25.1790 +        }
 25.1791 +
 25.1792 +        #undef glEnableClientState
 25.1793 +        extern "C" { GLAPI void GLAPIENTRY glEnableClientState(GLenum array); }
 25.1794 +        void OVR::GLEContext::glEnableClientState_Hook(GLenum array)
 25.1795 +        {
 25.1796 +            glEnableClientState(array);
 25.1797 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1798 +        }
 25.1799 +
 25.1800 +        #undef glEnd
 25.1801 +        extern "C" { GLAPI void GLAPIENTRY glEnd(); }
 25.1802 +        void OVR::GLEContext::glEnd_Hook()
 25.1803 +        {
 25.1804 +            glEnd();
 25.1805 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1806 +        }
 25.1807 +
 25.1808 +        #undef glEndList
 25.1809 +        extern "C" { GLAPI void GLAPIENTRY glEndList(); }
 25.1810 +        void OVR::GLEContext::glEndList_Hook()
 25.1811 +        {
 25.1812 +            glEndList();
 25.1813 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1814 +        }
 25.1815 +
 25.1816 +        #undef glEvalCoord1d
 25.1817 +        extern "C" { GLAPI void GLAPIENTRY glEvalCoord1d(GLdouble u); }
 25.1818 +        void OVR::GLEContext::glEvalCoord1d_Hook(GLdouble u)
 25.1819 +        {
 25.1820 +            glEvalCoord1d(u);
 25.1821 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1822 +        }
 25.1823 +
 25.1824 +        #undef glEvalCoord1dv
 25.1825 +        extern "C" { GLAPI void GLAPIENTRY glEvalCoord1dv(const GLdouble *u); }
 25.1826 +        void OVR::GLEContext::glEvalCoord1dv_Hook(const GLdouble *u)
 25.1827 +        {
 25.1828 +            glEvalCoord1dv(u);
 25.1829 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1830 +        }
 25.1831 +
 25.1832 +        #undef glEvalCoord1f
 25.1833 +        extern "C" { GLAPI void GLAPIENTRY glEvalCoord1f(GLfloat u); }
 25.1834 +        void OVR::GLEContext::glEvalCoord1f_Hook(GLfloat u)
 25.1835 +        {
 25.1836 +            glEvalCoord1f(u);
 25.1837 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1838 +        }
 25.1839 +
 25.1840 +        #undef glEvalCoord1fv
 25.1841 +        extern "C" { GLAPI void GLAPIENTRY glEvalCoord1fv(const GLfloat *u); }
 25.1842 +        void OVR::GLEContext::glEvalCoord1fv_Hook(const GLfloat *u)
 25.1843 +        {
 25.1844 +            glEvalCoord1fv(u);
 25.1845 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1846 +        }
 25.1847 +
 25.1848 +        #undef glEvalCoord2d
 25.1849 +        extern "C" { GLAPI void GLAPIENTRY glEvalCoord2d(GLdouble u, GLdouble v); }
 25.1850 +        void OVR::GLEContext::glEvalCoord2d_Hook(GLdouble u, GLdouble v)
 25.1851 +        {
 25.1852 +            glEvalCoord2d(u, v);
 25.1853 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1854 +        }
 25.1855 +
 25.1856 +        #undef glEvalCoord2dv
 25.1857 +        extern "C" { GLAPI void GLAPIENTRY glEvalCoord2dv(const GLdouble *u); }
 25.1858 +        void OVR::GLEContext::glEvalCoord2dv_Hook(const GLdouble *u)
 25.1859 +        {
 25.1860 +            glEvalCoord2dv(u);
 25.1861 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1862 +        }
 25.1863 +
 25.1864 +        #undef glEvalCoord2f
 25.1865 +        extern "C" { GLAPI void GLAPIENTRY glEvalCoord2f(GLfloat u, GLfloat v); }
 25.1866 +        void OVR::GLEContext::glEvalCoord2f_Hook(GLfloat u, GLfloat v)
 25.1867 +        {
 25.1868 +            glEvalCoord2f(u, v);
 25.1869 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1870 +        }
 25.1871 +
 25.1872 +        #undef glEvalCoord2fv
 25.1873 +        extern "C" { GLAPI void GLAPIENTRY glEvalCoord2fv(const GLfloat *u); }
 25.1874 +        void OVR::GLEContext::glEvalCoord2fv_Hook(const GLfloat *u)
 25.1875 +        {
 25.1876 +            glEvalCoord2fv(u);
 25.1877 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1878 +        }
 25.1879 +
 25.1880 +        #undef glEvalMesh1
 25.1881 +        extern "C" { GLAPI void GLAPIENTRY glEvalMesh1(GLenum mode, GLint i1, GLint i2); }
 25.1882 +        void OVR::GLEContext::glEvalMesh1_Hook(GLenum mode, GLint i1, GLint i2)
 25.1883 +        {
 25.1884 +            glEvalMesh1(mode, i1, i2);
 25.1885 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1886 +        }
 25.1887 +
 25.1888 +        #undef glEvalMesh2
 25.1889 +        extern "C" { GLAPI void GLAPIENTRY glEvalMesh2(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2); }
 25.1890 +        void OVR::GLEContext::glEvalMesh2_Hook(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2)
 25.1891 +        {
 25.1892 +            glEvalMesh2(mode, i1, i2, j1, j2);
 25.1893 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1894 +        }
 25.1895 +
 25.1896 +        #undef glEvalPoint1
 25.1897 +        extern "C" { GLAPI void GLAPIENTRY glEvalPoint1(GLint i); }
 25.1898 +        void OVR::GLEContext::glEvalPoint1_Hook(GLint i)
 25.1899 +        {
 25.1900 +            glEvalPoint1(i);
 25.1901 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1902 +        }
 25.1903 +
 25.1904 +        #undef glEvalPoint2
 25.1905 +        extern "C" { GLAPI void GLAPIENTRY glEvalPoint2(GLint i, GLint j); }
 25.1906 +        void OVR::GLEContext::glEvalPoint2_Hook(GLint i, GLint j)
 25.1907 +        {
 25.1908 +            glEvalPoint2(i, j);
 25.1909 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1910 +        }
 25.1911 +
 25.1912 +        #undef glFeedbackBuffer
 25.1913 +        extern "C" { GLAPI void GLAPIENTRY glFeedbackBuffer(GLsizei size, GLenum type, GLfloat *buffer); }
 25.1914 +        void OVR::GLEContext::glFeedbackBuffer_Hook(GLsizei size, GLenum type, GLfloat *buffer)
 25.1915 +        {
 25.1916 +            glFeedbackBuffer(size, type, buffer);
 25.1917 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1918 +        }
 25.1919 +
 25.1920 +        #undef glFinish
 25.1921 +        extern "C" { GLAPI void GLAPIENTRY glFinish(); }
 25.1922 +        void OVR::GLEContext::glFinish_Hook()
 25.1923 +        {
 25.1924 +            glFinish();
 25.1925 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1926 +        }
 25.1927 +
 25.1928 +        #undef glFlush
 25.1929 +        extern "C" { GLAPI void GLAPIENTRY glFlush(); }
 25.1930 +        void OVR::GLEContext::glFlush_Hook()
 25.1931 +        {
 25.1932 +            glFlush();
 25.1933 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1934 +        }
 25.1935 +
 25.1936 +        #undef glFogf
 25.1937 +        extern "C" { GLAPI void GLAPIENTRY glFogf(GLenum pname, GLfloat param); }
 25.1938 +        void OVR::GLEContext::glFogf_Hook(GLenum pname, GLfloat param)
 25.1939 +        {
 25.1940 +            glFogf(pname, param);
 25.1941 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1942 +        }
 25.1943 +
 25.1944 +        #undef glFogfv
 25.1945 +        extern "C" { GLAPI void GLAPIENTRY glFogfv(GLenum pname, const GLfloat *params); }
 25.1946 +        void OVR::GLEContext::glFogfv_Hook(GLenum pname, const GLfloat *params)
 25.1947 +        {
 25.1948 +            glFogfv(pname, params);
 25.1949 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1950 +        }
 25.1951 +
 25.1952 +        #undef glFogi
 25.1953 +        extern "C" { GLAPI void GLAPIENTRY glFogi(GLenum pname, GLint param); }
 25.1954 +        void OVR::GLEContext::glFogi_Hook(GLenum pname, GLint param)
 25.1955 +        {
 25.1956 +            glFogi(pname, param);
 25.1957 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1958 +        }
 25.1959 +
 25.1960 +        #undef glFogiv
 25.1961 +        extern "C" { GLAPI void GLAPIENTRY glFogiv(GLenum pname, const GLint *params); }
 25.1962 +        void OVR::GLEContext::glFogiv_Hook(GLenum pname, const GLint *params)
 25.1963 +        {
 25.1964 +            glFogiv(pname, params);
 25.1965 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1966 +        }
 25.1967 +
 25.1968 +        #undef glFrontFace
 25.1969 +        extern "C" { GLAPI void GLAPIENTRY glFrontFace(GLenum mode); }
 25.1970 +        void OVR::GLEContext::glFrontFace_Hook(GLenum mode)
 25.1971 +        {
 25.1972 +            glFrontFace(mode);
 25.1973 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1974 +        }
 25.1975 +
 25.1976 +        #undef glFrustum
 25.1977 +        extern "C" { GLAPI void GLAPIENTRY glFrustum(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar); }
 25.1978 +        void OVR::GLEContext::glFrustum_Hook(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar)
 25.1979 +        {
 25.1980 +            glFrustum(left, right, bottom, top, zNear, zFar);
 25.1981 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1982 +        }
 25.1983 +
 25.1984 +        #undef glGenLists
 25.1985 +        extern "C" { GLAPI GLuint GLAPIENTRY glGenLists(GLsizei range); }
 25.1986 +        GLuint OVR::GLEContext::glGenLists_Hook(GLsizei range)
 25.1987 +        {
 25.1988 +            GLuint u = glGenLists(range);
 25.1989 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1990 +            return u;
 25.1991 +        }
 25.1992 +
 25.1993 +        #undef glGenTextures
 25.1994 +        extern "C" { GLAPI void GLAPIENTRY glGenTextures(GLsizei n, GLuint *textures); }
 25.1995 +        void OVR::GLEContext::glGenTextures_Hook(GLsizei n, GLuint *textures)
 25.1996 +        {
 25.1997 +            glGenTextures(n, textures);
 25.1998 +            PostHook(GLE_CURRENT_FUNCTION);
 25.1999 +        }
 25.2000 +
 25.2001 +        #undef glGetBooleanv
 25.2002 +        extern "C" { GLAPI void GLAPIENTRY glGetBooleanv(GLenum pname, GLboolean *params); }
 25.2003 +        void OVR::GLEContext::glGetBooleanv_Hook(GLenum pname, GLboolean *params)
 25.2004 +        {
 25.2005 +            glGetBooleanv(pname, params);
 25.2006 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2007 +        }
 25.2008 +
 25.2009 +        #undef glGetClipPlane
 25.2010 +        extern "C" { GLAPI void GLAPIENTRY glGetClipPlane(GLenum plane, GLdouble *equation); }
 25.2011 +        void OVR::GLEContext::glGetClipPlane_Hook(GLenum plane, GLdouble *equation)
 25.2012 +        {
 25.2013 +            glGetClipPlane(plane, equation);
 25.2014 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2015 +        }
 25.2016 +
 25.2017 +        #undef glGetDoublev
 25.2018 +        extern "C" { GLAPI void GLAPIENTRY glGetDoublev(GLenum pname, GLdouble *params); }
 25.2019 +        void OVR::GLEContext::glGetDoublev_Hook(GLenum pname, GLdouble *params)
 25.2020 +        {
 25.2021 +            glGetDoublev(pname, params);
 25.2022 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2023 +        }
 25.2024 +
 25.2025 +        //#undef glGetError Not needed because we happen to do this above already.
 25.2026 +        //extern "C" { GLAPI GLenum GLAPIENTRY glGetError(); }
 25.2027 +        GLenum OVR::GLEContext::glGetError_Hook()
 25.2028 +        {
 25.2029 +            GLenum e = glGetError();
 25.2030 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2031 +            return e;
 25.2032 +        }
 25.2033 +
 25.2034 +        #undef glGetFloatv
 25.2035 +        extern "C" { GLAPI void GLAPIENTRY glGetFloatv(GLenum pname, GLfloat *params); }
 25.2036 +        void OVR::GLEContext::glGetFloatv_Hook(GLenum pname, GLfloat *params)
 25.2037 +        {
 25.2038 +            glGetFloatv(pname, params);
 25.2039 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2040 +        }
 25.2041 +
 25.2042 +        #undef glGetIntegerv
 25.2043 +        extern "C" { GLAPI void GLAPIENTRY glGetIntegerv(GLenum pname, GLint *params); }
 25.2044 +        void OVR::GLEContext::glGetIntegerv_Hook(GLenum pname, GLint *params)
 25.2045 +        {
 25.2046 +            glGetIntegerv(pname, params);
 25.2047 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2048 +        }
 25.2049 +
 25.2050 +        #undef glGetLightfv
 25.2051 +        extern "C" { GLAPI void GLAPIENTRY glGetLightfv(GLenum light, GLenum pname, GLfloat *params); }
 25.2052 +        void OVR::GLEContext::glGetLightfv_Hook(GLenum light, GLenum pname, GLfloat *params)
 25.2053 +        {
 25.2054 +            glGetLightfv(light, pname, params);
 25.2055 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2056 +        }
 25.2057 +
 25.2058 +        #undef glGetLightiv
 25.2059 +        extern "C" { GLAPI void GLAPIENTRY glGetLightiv(GLenum light, GLenum pname, GLint *params); }
 25.2060 +        void OVR::GLEContext::glGetLightiv_Hook(GLenum light, GLenum pname, GLint *params)
 25.2061 +        {
 25.2062 +            glGetLightiv(light, pname, params);
 25.2063 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2064 +        }
 25.2065 +
 25.2066 +        #undef glGetMapdv
 25.2067 +        extern "C" { GLAPI void GLAPIENTRY glGetMapdv(GLenum target, GLenum query, GLdouble *v); }
 25.2068 +        void OVR::GLEContext::glGetMapdv_Hook(GLenum target, GLenum query, GLdouble *v)
 25.2069 +        {
 25.2070 +            glGetMapdv(target, query, v);
 25.2071 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2072 +        }
 25.2073 +
 25.2074 +        #undef glGetMapfv
 25.2075 +        extern "C" { GLAPI void GLAPIENTRY glGetMapfv(GLenum target, GLenum query, GLfloat *v); }
 25.2076 +        void OVR::GLEContext::glGetMapfv_Hook(GLenum target, GLenum query, GLfloat *v)
 25.2077 +        {
 25.2078 +            glGetMapfv(target, query, v);
 25.2079 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2080 +        }
 25.2081 +
 25.2082 +        #undef glGetMapiv
 25.2083 +        extern "C" { GLAPI void GLAPIENTRY glGetMapiv(GLenum target, GLenum query, GLint *v); }
 25.2084 +        void OVR::GLEContext::glGetMapiv_Hook(GLenum target, GLenum query, GLint *v)
 25.2085 +        {
 25.2086 +            glGetMapiv(target, query, v);
 25.2087 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2088 +        }
 25.2089 +
 25.2090 +        #undef glGetMaterialfv
 25.2091 +        extern "C" { GLAPI void GLAPIENTRY glGetMaterialfv(GLenum face, GLenum pname, GLfloat *params); }
 25.2092 +        void OVR::GLEContext::glGetMaterialfv_Hook(GLenum face, GLenum pname, GLfloat *params)
 25.2093 +        {
 25.2094 +            glGetMaterialfv(face, pname, params);
 25.2095 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2096 +        }
 25.2097 +
 25.2098 +        #undef glGetMaterialiv
 25.2099 +        extern "C" { GLAPI void GLAPIENTRY glGetMaterialiv(GLenum face, GLenum pname, GLint *params); }
 25.2100 +        void OVR::GLEContext::glGetMaterialiv_Hook(GLenum face, GLenum pname, GLint *params)
 25.2101 +        {
 25.2102 +            glGetMaterialiv(face, pname, params);
 25.2103 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2104 +        }
 25.2105 +
 25.2106 +        #undef glGetPixelMapfv
 25.2107 +        extern "C" { GLAPI void GLAPIENTRY glGetPixelMapfv(GLenum map, GLfloat *values); }
 25.2108 +        void OVR::GLEContext::glGetPixelMapfv_Hook(GLenum map, GLfloat *values)
 25.2109 +        {
 25.2110 +            glGetPixelMapfv(map, values);
 25.2111 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2112 +        }
 25.2113 +
 25.2114 +        #undef glGetPixelMapuiv
 25.2115 +        extern "C" { GLAPI void GLAPIENTRY glGetPixelMapuiv(GLenum map, GLuint *values); }
 25.2116 +        void OVR::GLEContext::glGetPixelMapuiv_Hook(GLenum map, GLuint *values)
 25.2117 +        {
 25.2118 +            glGetPixelMapuiv(map, values);
 25.2119 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2120 +        }
 25.2121 +
 25.2122 +        #undef glGetPixelMapusv
 25.2123 +        extern "C" { GLAPI void GLAPIENTRY glGetPixelMapusv(GLenum map, GLushort *values); }
 25.2124 +        void OVR::GLEContext::glGetPixelMapusv_Hook(GLenum map, GLushort *values)
 25.2125 +        {
 25.2126 +            glGetPixelMapusv(map, values);
 25.2127 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2128 +        }
 25.2129 +
 25.2130 +        #undef glGetPointerv
 25.2131 +        extern "C" { GLAPI void GLAPIENTRY glGetPointerv(GLenum pname, void* *params); }
 25.2132 +        void OVR::GLEContext::glGetPointerv_Hook(GLenum pname, void* *params)
 25.2133 +        {
 25.2134 +            glGetPointerv(pname, params);
 25.2135 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2136 +        }
 25.2137 +
 25.2138 +        #undef glGetPolygonStipple
 25.2139 +        extern "C" { GLAPI void GLAPIENTRY glGetPolygonStipple(GLubyte *mask); }
 25.2140 +        void OVR::GLEContext::glGetPolygonStipple_Hook(GLubyte *mask)
 25.2141 +        {
 25.2142 +            glGetPolygonStipple(mask);
 25.2143 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2144 +        }
 25.2145 +
 25.2146 +        // #undef glGetString // This was already disabled above.
 25.2147 +        // extern "C" { GLAPI const GLubyte * GLAPIENTRY glGetString(GLenum name); }
 25.2148 +        const GLubyte * OVR::GLEContext::glGetString_Hook(GLenum name)
 25.2149 +        {
 25.2150 +            const GLubyte * p = glGetString(name);
 25.2151 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2152 +            return p;
 25.2153 +        }
 25.2154 +
 25.2155 +        #undef glGetTexEnvfv
 25.2156 +        extern "C" { GLAPI void GLAPIENTRY glGetTexEnvfv(GLenum target, GLenum pname, GLfloat *params); }
 25.2157 +        void OVR::GLEContext::glGetTexEnvfv_Hook(GLenum target, GLenum pname, GLfloat *params)
 25.2158 +        {
 25.2159 +            glGetTexEnvfv(target, pname, params);
 25.2160 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2161 +        }
 25.2162 +
 25.2163 +        #undef glGetTexEnviv
 25.2164 +        extern "C" { GLAPI void GLAPIENTRY glGetTexEnviv(GLenum target, GLenum pname, GLint *params); }
 25.2165 +        void OVR::GLEContext::glGetTexEnviv_Hook(GLenum target, GLenum pname, GLint *params)
 25.2166 +        {
 25.2167 +            glGetTexEnviv(target, pname, params);
 25.2168 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2169 +        }
 25.2170 +
 25.2171 +        #undef glGetTexGendv
 25.2172 +        extern "C" { GLAPI void GLAPIENTRY glGetTexGendv(GLenum coord, GLenum pname, GLdouble *params); }
 25.2173 +        void OVR::GLEContext::glGetTexGendv_Hook(GLenum coord, GLenum pname, GLdouble *params)
 25.2174 +        {
 25.2175 +            glGetTexGendv(coord, pname, params);
 25.2176 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2177 +        }
 25.2178 +
 25.2179 +        #undef glGetTexGenfv
 25.2180 +        extern "C" { GLAPI void GLAPIENTRY glGetTexGenfv(GLenum coord, GLenum pname, GLfloat *params); }
 25.2181 +        void OVR::GLEContext::glGetTexGenfv_Hook(GLenum coord, GLenum pname, GLfloat *params)
 25.2182 +        {
 25.2183 +            glGetTexGenfv(coord, pname, params);
 25.2184 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2185 +        }
 25.2186 +
 25.2187 +        #undef glGetTexGeniv
 25.2188 +        extern "C" { GLAPI void GLAPIENTRY glGetTexGeniv(GLenum coord, GLenum pname, GLint *params); }
 25.2189 +        void OVR::GLEContext::glGetTexGeniv_Hook(GLenum coord, GLenum pname, GLint *params)
 25.2190 +        {
 25.2191 +            glGetTexGeniv(coord, pname, params);
 25.2192 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2193 +        }
 25.2194 +
 25.2195 +        #undef glGetTexImage
 25.2196 +        extern "C" { GLAPI void GLAPIENTRY glGetTexImage(GLenum target, GLint level, GLenum format, GLenum type, void *pixels); }
 25.2197 +        void OVR::GLEContext::glGetTexImage_Hook(GLenum target, GLint level, GLenum format, GLenum type, void *pixels)
 25.2198 +        {
 25.2199 +            glGetTexImage(target, level, format, type, pixels);
 25.2200 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2201 +        }
 25.2202 +
 25.2203 +        #undef glGetTexLevelParameterfv
 25.2204 +        extern "C" { GLAPI void GLAPIENTRY glGetTexLevelParameterfv(GLenum target, GLint level, GLenum pname, GLfloat *params); }
 25.2205 +        void OVR::GLEContext::glGetTexLevelParameterfv_Hook(GLenum target, GLint level, GLenum pname, GLfloat *params)
 25.2206 +        {
 25.2207 +            glGetTexLevelParameterfv(target, level, pname, params);
 25.2208 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2209 +        }
 25.2210 +
 25.2211 +        #undef glGetTexLevelParameteriv
 25.2212 +        extern "C" { GLAPI void GLAPIENTRY glGetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint *params); }
 25.2213 +        void OVR::GLEContext::glGetTexLevelParameteriv_Hook(GLenum target, GLint level, GLenum pname, GLint *params)
 25.2214 +        {
 25.2215 +            glGetTexLevelParameteriv(target, level, pname, params);
 25.2216 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2217 +        }
 25.2218 +
 25.2219 +        #undef glGetTexParameterfv
 25.2220 +        extern "C" { GLAPI void GLAPIENTRY glGetTexParameterfv(GLenum target, GLenum pname, GLfloat *params); }
 25.2221 +        void OVR::GLEContext::glGetTexParameterfv_Hook(GLenum target, GLenum pname, GLfloat *params)
 25.2222 +        {
 25.2223 +            glGetTexParameterfv(target, pname, params);
 25.2224 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2225 +        }
 25.2226 +
 25.2227 +        #undef glGetTexParameteriv
 25.2228 +        extern "C" { GLAPI void GLAPIENTRY glGetTexParameteriv(GLenum target, GLenum pname, GLint *params); }
 25.2229 +        void OVR::GLEContext::glGetTexParameteriv_Hook(GLenum target, GLenum pname, GLint *params)
 25.2230 +        {
 25.2231 +            glGetTexParameteriv(target, pname, params);
 25.2232 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2233 +        }
 25.2234 +
 25.2235 +        #undef glHint
 25.2236 +        extern "C" { GLAPI void GLAPIENTRY glHint(GLenum target, GLenum mode); }
 25.2237 +        void OVR::GLEContext::glHint_Hook(GLenum target, GLenum mode)
 25.2238 +        {
 25.2239 +            glHint(target, mode);
 25.2240 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2241 +        }
 25.2242 +
 25.2243 +        #undef glIndexMask
 25.2244 +        extern "C" { GLAPI void GLAPIENTRY glIndexMask(GLuint mask); }
 25.2245 +        void OVR::GLEContext::glIndexMask_Hook(GLuint mask)
 25.2246 +        {
 25.2247 +            glIndexMask(mask);
 25.2248 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2249 +        }
 25.2250 +
 25.2251 +        #undef glIndexPointer
 25.2252 +        extern "C" { GLAPI void GLAPIENTRY glIndexPointer(GLenum type, GLsizei stride, const void *pointer); }
 25.2253 +        void OVR::GLEContext::glIndexPointer_Hook(GLenum type, GLsizei stride, const void *pointer)
 25.2254 +        {
 25.2255 +            glIndexPointer(type, stride, pointer);
 25.2256 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2257 +        }
 25.2258 +
 25.2259 +        #undef glIndexd
 25.2260 +        extern "C" { GLAPI void GLAPIENTRY glIndexd(GLdouble c); }
 25.2261 +        void OVR::GLEContext::glIndexd_Hook(GLdouble c)
 25.2262 +        {
 25.2263 +            glIndexd(c);
 25.2264 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2265 +        }
 25.2266 +
 25.2267 +        #undef glIndexdv
 25.2268 +        extern "C" { GLAPI void GLAPIENTRY glIndexdv(const GLdouble *c); }
 25.2269 +        void OVR::GLEContext::glIndexdv_Hook(const GLdouble *c)
 25.2270 +        {
 25.2271 +            glIndexdv(c);
 25.2272 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2273 +        }
 25.2274 +
 25.2275 +        #undef glIndexf
 25.2276 +        extern "C" { GLAPI void GLAPIENTRY glIndexf(GLfloat c); }
 25.2277 +        void OVR::GLEContext::glIndexf_Hook(GLfloat c)
 25.2278 +        {
 25.2279 +            glIndexf(c);
 25.2280 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2281 +        }
 25.2282 +
 25.2283 +        #undef glIndexfv
 25.2284 +        extern "C" { GLAPI void GLAPIENTRY glIndexfv(const GLfloat *c); }
 25.2285 +        void OVR::GLEContext::glIndexfv_Hook(const GLfloat *c)
 25.2286 +        {
 25.2287 +            glIndexfv(c);
 25.2288 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2289 +        }
 25.2290 +
 25.2291 +        #undef glIndexi
 25.2292 +        extern "C" { GLAPI void GLAPIENTRY glIndexi(GLint c); }
 25.2293 +        void OVR::GLEContext::glIndexi_Hook(GLint c)
 25.2294 +        {
 25.2295 +            glIndexi(c);
 25.2296 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2297 +        }
 25.2298 +
 25.2299 +        #undef glIndexiv
 25.2300 +        extern "C" { GLAPI void GLAPIENTRY glIndexiv(const GLint *c); }
 25.2301 +        void OVR::GLEContext::glIndexiv_Hook(const GLint *c)
 25.2302 +        {
 25.2303 +            glIndexiv(c);
 25.2304 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2305 +        }
 25.2306 +
 25.2307 +        #undef glIndexs
 25.2308 +        extern "C" { GLAPI void GLAPIENTRY glIndexs(GLshort c); }
 25.2309 +        void OVR::GLEContext::glIndexs_Hook(GLshort c)
 25.2310 +        {
 25.2311 +            glIndexs(c);
 25.2312 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2313 +        }
 25.2314 +
 25.2315 +        #undef glIndexsv
 25.2316 +        extern "C" { GLAPI void GLAPIENTRY glIndexsv(const GLshort *c); }
 25.2317 +        void OVR::GLEContext::glIndexsv_Hook(const GLshort *c)
 25.2318 +        {
 25.2319 +            glIndexsv(c);
 25.2320 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2321 +        }
 25.2322 +
 25.2323 +        #undef glIndexub
 25.2324 +        extern "C" { GLAPI void GLAPIENTRY glIndexub(GLubyte c); }
 25.2325 +        void OVR::GLEContext::glIndexub_Hook(GLubyte c)
 25.2326 +        {
 25.2327 +            glIndexub(c);
 25.2328 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2329 +        }
 25.2330 +
 25.2331 +        #undef glIndexubv
 25.2332 +        extern "C" { GLAPI void GLAPIENTRY glIndexubv(const GLubyte *c); }
 25.2333 +        void OVR::GLEContext::glIndexubv_Hook(const GLubyte *c)
 25.2334 +        {
 25.2335 +            glIndexubv(c);
 25.2336 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2337 +        }
 25.2338 +
 25.2339 +        #undef glInitNames
 25.2340 +        extern "C" { GLAPI void GLAPIENTRY glInitNames(); }
 25.2341 +        void OVR::GLEContext::glInitNames_Hook()
 25.2342 +        {
 25.2343 +            glInitNames();
 25.2344 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2345 +        }
 25.2346 +
 25.2347 +        #undef glInterleavedArrays
 25.2348 +        extern "C" { GLAPI void GLAPIENTRY glInterleavedArrays(GLenum format, GLsizei stride, const void *pointer); }
 25.2349 +        void OVR::GLEContext::glInterleavedArrays_Hook(GLenum format, GLsizei stride, const void *pointer)
 25.2350 +        {
 25.2351 +            glInterleavedArrays(format, stride, pointer);
 25.2352 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2353 +        }
 25.2354 +
 25.2355 +        #undef glIsEnabled
 25.2356 +        extern "C" { GLAPI GLboolean GLAPIENTRY glIsEnabled(GLenum cap); }
 25.2357 +        GLboolean OVR::GLEContext::glIsEnabled_Hook(GLenum cap)
 25.2358 +        {
 25.2359 +            GLboolean b = glIsEnabled(cap);
 25.2360 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2361 +            return b;
 25.2362 +        }
 25.2363 +
 25.2364 +        #undef glIsList
 25.2365 +        extern "C" { GLAPI GLboolean GLAPIENTRY glIsList(GLuint list); }
 25.2366 +        GLboolean OVR::GLEContext::glIsList_Hook(GLuint list)
 25.2367 +        {
 25.2368 +            GLboolean b = glIsList(list);
 25.2369 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2370 +            return b;
 25.2371 +        }
 25.2372 +
 25.2373 +        #undef glIsTexture
 25.2374 +        extern "C" { GLAPI GLboolean GLAPIENTRY glIsTexture(GLuint texture); }
 25.2375 +        GLboolean OVR::GLEContext::glIsTexture_Hook(GLuint texture)
 25.2376 +        {
 25.2377 +            GLboolean b = glIsTexture(texture);
 25.2378 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2379 +            return b;
 25.2380 +        }
 25.2381 +
 25.2382 +        #undef glLightModelf
 25.2383 +        extern "C" { GLAPI void GLAPIENTRY glLightModelf(GLenum pname, GLfloat param); }
 25.2384 +        void OVR::GLEContext::glLightModelf_Hook(GLenum pname, GLfloat param)
 25.2385 +        {
 25.2386 +            glLightModelf(pname, param);
 25.2387 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2388 +        }
 25.2389 +
 25.2390 +        #undef glLightModelfv
 25.2391 +        extern "C" { GLAPI void GLAPIENTRY glLightModelfv(GLenum pname, const GLfloat *params); }
 25.2392 +        void OVR::GLEContext::glLightModelfv_Hook(GLenum pname, const GLfloat *params)
 25.2393 +        {
 25.2394 +            glLightModelfv(pname, params);
 25.2395 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2396 +        }
 25.2397 +
 25.2398 +        #undef glLightModeli
 25.2399 +        extern "C" { GLAPI void GLAPIENTRY glLightModeli(GLenum pname, GLint param); }
 25.2400 +        void OVR::GLEContext::glLightModeli_Hook(GLenum pname, GLint param)
 25.2401 +        {
 25.2402 +            glLightModeli(pname, param);
 25.2403 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2404 +        }
 25.2405 +
 25.2406 +        #undef glLightModeliv
 25.2407 +        extern "C" { GLAPI void GLAPIENTRY glLightModeliv(GLenum pname, const GLint *params); }
 25.2408 +        void OVR::GLEContext::glLightModeliv_Hook(GLenum pname, const GLint *params)
 25.2409 +        {
 25.2410 +            glLightModeliv(pname, params);
 25.2411 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2412 +        }
 25.2413 +
 25.2414 +        #undef glLightf
 25.2415 +        extern "C" { GLAPI void GLAPIENTRY glLightf(GLenum light, GLenum pname, GLfloat param); }
 25.2416 +        void OVR::GLEContext::glLightf_Hook(GLenum light, GLenum pname, GLfloat param)
 25.2417 +        {
 25.2418 +            glLightf(light, pname, param);
 25.2419 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2420 +        }
 25.2421 +
 25.2422 +        #undef glLightfv
 25.2423 +        extern "C" { GLAPI void GLAPIENTRY glLightfv(GLenum light, GLenum pname, const GLfloat *params); }
 25.2424 +        void OVR::GLEContext::glLightfv_Hook(GLenum light, GLenum pname, const GLfloat *params)
 25.2425 +        {
 25.2426 +            glLightfv(light, pname, params);
 25.2427 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2428 +        }
 25.2429 +
 25.2430 +        #undef glLighti
 25.2431 +        extern "C" { GLAPI void GLAPIENTRY glLighti(GLenum light, GLenum pname, GLint param); }
 25.2432 +        void OVR::GLEContext::glLighti_Hook(GLenum light, GLenum pname, GLint param)
 25.2433 +        {
 25.2434 +            glLighti(light, pname, param);
 25.2435 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2436 +        }
 25.2437 +
 25.2438 +        #undef glLightiv
 25.2439 +        extern "C" { GLAPI void GLAPIENTRY glLightiv(GLenum light, GLenum pname, const GLint *params); }
 25.2440 +        void OVR::GLEContext::glLightiv_Hook(GLenum light, GLenum pname, const GLint *params)
 25.2441 +        {
 25.2442 +            glLightiv(light, pname, params);
 25.2443 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2444 +        }
 25.2445 +
 25.2446 +        #undef glLineStipple
 25.2447 +        extern "C" { GLAPI void GLAPIENTRY glLineStipple(GLint factor, GLushort pattern); }
 25.2448 +        void OVR::GLEContext::glLineStipple_Hook(GLint factor, GLushort pattern)
 25.2449 +        {
 25.2450 +            glLineStipple(factor, pattern);
 25.2451 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2452 +        }
 25.2453 +
 25.2454 +        #undef glLineWidth
 25.2455 +        extern "C" { GLAPI void GLAPIENTRY glLineWidth(GLfloat width); }
 25.2456 +        void OVR::GLEContext::glLineWidth_Hook(GLfloat width)
 25.2457 +        {
 25.2458 +            glLineWidth(width);
 25.2459 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2460 +        }
 25.2461 +
 25.2462 +        #undef glListBase
 25.2463 +        extern "C" { GLAPI void GLAPIENTRY glListBase(GLuint base); }
 25.2464 +        void OVR::GLEContext::glListBase_Hook(GLuint base)
 25.2465 +        {
 25.2466 +            glListBase(base);
 25.2467 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2468 +        }
 25.2469 +
 25.2470 +        #undef glLoadIdentity
 25.2471 +        extern "C" { GLAPI void GLAPIENTRY glLoadIdentity(); }
 25.2472 +        void OVR::GLEContext::glLoadIdentity_Hook()
 25.2473 +        {
 25.2474 +            glLoadIdentity();
 25.2475 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2476 +        }
 25.2477 +
 25.2478 +        #undef glLoadMatrixd
 25.2479 +        extern "C" { GLAPI void GLAPIENTRY glLoadMatrixd(const GLdouble *m); }
 25.2480 +        void OVR::GLEContext::glLoadMatrixd_Hook(const GLdouble *m)
 25.2481 +        {
 25.2482 +            glLoadMatrixd(m);
 25.2483 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2484 +        }
 25.2485 +
 25.2486 +        #undef glLoadMatrixf
 25.2487 +        extern "C" { GLAPI void GLAPIENTRY glLoadMatrixf(const GLfloat *m); }
 25.2488 +        void OVR::GLEContext::glLoadMatrixf_Hook(const GLfloat *m)
 25.2489 +        {
 25.2490 +            glLoadMatrixf(m);
 25.2491 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2492 +        }
 25.2493 +
 25.2494 +        #undef glLoadName
 25.2495 +        extern "C" { GLAPI void GLAPIENTRY glLoadName(GLuint name); }
 25.2496 +        void OVR::GLEContext::glLoadName_Hook(GLuint name)
 25.2497 +        {
 25.2498 +            glLoadName(name);
 25.2499 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2500 +        }
 25.2501 +
 25.2502 +        #undef glLogicOp
 25.2503 +        extern "C" { GLAPI void GLAPIENTRY glLogicOp(GLenum opcode); }
 25.2504 +        void OVR::GLEContext::glLogicOp_Hook(GLenum opcode)
 25.2505 +        {
 25.2506 +            glLogicOp(opcode);
 25.2507 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2508 +        }
 25.2509 +
 25.2510 +        #undef glMap1d
 25.2511 +        extern "C" { GLAPI void GLAPIENTRY glMap1d(GLenum target, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points); }
 25.2512 +        void OVR::GLEContext::glMap1d_Hook(GLenum target, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points)
 25.2513 +        {
 25.2514 +            glMap1d(target, u1, u2, stride, order, points);
 25.2515 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2516 +        }
 25.2517 +
 25.2518 +        #undef glMap1f
 25.2519 +        extern "C" { GLAPI void GLAPIENTRY glMap1f(GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points); }
 25.2520 +        void OVR::GLEContext::glMap1f_Hook(GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points)
 25.2521 +        {
 25.2522 +            glMap1f(target, u1, u2, stride, order, points);
 25.2523 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2524 +        }
 25.2525 +
 25.2526 +        #undef glMap2d
 25.2527 +        extern "C" { GLAPI void GLAPIENTRY glMap2d(GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points); }
 25.2528 +        void OVR::GLEContext::glMap2d_Hook(GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points)
 25.2529 +        {
 25.2530 +            glMap2d(target, u1, u2, ustride, uorder, v1, v2, vstride, vorder, points);
 25.2531 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2532 +        }
 25.2533 +
 25.2534 +        #undef glMap2f
 25.2535 +        extern "C" { GLAPI void GLAPIENTRY glMap2f(GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points); }
 25.2536 +        void OVR::GLEContext::glMap2f_Hook(GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points)
 25.2537 +        {
 25.2538 +            glMap2f(target, u1, u2, ustride, uorder, v1, v2, vstride, vorder, points);
 25.2539 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2540 +        }
 25.2541 +
 25.2542 +        #undef glMapGrid1d
 25.2543 +        extern "C" { GLAPI void GLAPIENTRY glMapGrid1d(GLint un, GLdouble u1, GLdouble u2); }
 25.2544 +        void OVR::GLEContext::glMapGrid1d_Hook(GLint un, GLdouble u1, GLdouble u2)
 25.2545 +        {
 25.2546 +            glMapGrid1d(un, u1, u2);
 25.2547 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2548 +        }
 25.2549 +
 25.2550 +        #undef glMapGrid1f
 25.2551 +        extern "C" { GLAPI void GLAPIENTRY glMapGrid1f(GLint un, GLfloat u1, GLfloat u2); }
 25.2552 +        void OVR::GLEContext::glMapGrid1f_Hook(GLint un, GLfloat u1, GLfloat u2)
 25.2553 +        {
 25.2554 +            glMapGrid1f(un, u1, u2);
 25.2555 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2556 +        }
 25.2557 +
 25.2558 +        #undef glMapGrid2d
 25.2559 +        extern "C" { GLAPI void GLAPIENTRY glMapGrid2d(GLint un, GLdouble u1, GLdouble u2, GLint vn, GLdouble v1, GLdouble v2); }
 25.2560 +        void OVR::GLEContext::glMapGrid2d_Hook(GLint un, GLdouble u1, GLdouble u2, GLint vn, GLdouble v1, GLdouble v2)
 25.2561 +        {
 25.2562 +            glMapGrid2d(un, u1, u2, vn, v1, v2);
 25.2563 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2564 +        }
 25.2565 +
 25.2566 +        #undef glMapGrid2f
 25.2567 +        extern "C" { GLAPI void GLAPIENTRY glMapGrid2f(GLint un, GLfloat u1, GLfloat u2, GLint vn, GLfloat v1, GLfloat v2); }
 25.2568 +        void OVR::GLEContext::glMapGrid2f_Hook(GLint un, GLfloat u1, GLfloat u2, GLint vn, GLfloat v1, GLfloat v2)
 25.2569 +        {
 25.2570 +            glMapGrid2f(un, u1, u2, vn, v1, v2);
 25.2571 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2572 +        }
 25.2573 +
 25.2574 +        #undef glMaterialf
 25.2575 +        extern "C" { GLAPI void GLAPIENTRY glMaterialf(GLenum face, GLenum pname, GLfloat param); }
 25.2576 +        void OVR::GLEContext::glMaterialf_Hook(GLenum face, GLenum pname, GLfloat param)
 25.2577 +        {
 25.2578 +            glMaterialf(face, pname, param);
 25.2579 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2580 +        }
 25.2581 +
 25.2582 +        #undef glMaterialfv
 25.2583 +        extern "C" { GLAPI void GLAPIENTRY glMaterialfv(GLenum face, GLenum pname, const GLfloat *params); }
 25.2584 +        void OVR::GLEContext::glMaterialfv_Hook(GLenum face, GLenum pname, const GLfloat *params)
 25.2585 +        {
 25.2586 +            glMaterialfv(face, pname, params);
 25.2587 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2588 +        }
 25.2589 +
 25.2590 +        #undef glMateriali
 25.2591 +        extern "C" { GLAPI void GLAPIENTRY glMateriali(GLenum face, GLenum pname, GLint param); }
 25.2592 +        void OVR::GLEContext::glMateriali_Hook(GLenum face, GLenum pname, GLint param)
 25.2593 +        {
 25.2594 +            glMateriali(face, pname, param);
 25.2595 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2596 +        }
 25.2597 +
 25.2598 +        #undef glMaterialiv
 25.2599 +        extern "C" { GLAPI void GLAPIENTRY glMaterialiv(GLenum face, GLenum pname, const GLint *params); }
 25.2600 +        void OVR::GLEContext::glMaterialiv_Hook(GLenum face, GLenum pname, const GLint *params)
 25.2601 +        {
 25.2602 +            glMaterialiv(face, pname, params);
 25.2603 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2604 +        }
 25.2605 +
 25.2606 +        #undef glMatrixMode
 25.2607 +        extern "C" { GLAPI void GLAPIENTRY glMatrixMode(GLenum mode); }
 25.2608 +        void OVR::GLEContext::glMatrixMode_Hook(GLenum mode)
 25.2609 +        {
 25.2610 +            glMatrixMode(mode);
 25.2611 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2612 +        }
 25.2613 +
 25.2614 +        #undef glMultMatrixd
 25.2615 +        extern "C" { GLAPI void GLAPIENTRY glMultMatrixd(const GLdouble *m); }
 25.2616 +        void OVR::GLEContext::glMultMatrixd_Hook(const GLdouble *m)
 25.2617 +        {
 25.2618 +            glMultMatrixd(m);
 25.2619 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2620 +        }
 25.2621 +
 25.2622 +        #undef glMultMatrixf
 25.2623 +        extern "C" { GLAPI void GLAPIENTRY glMultMatrixf(const GLfloat *m); }
 25.2624 +        void OVR::GLEContext::glMultMatrixf_Hook(const GLfloat *m)
 25.2625 +        {
 25.2626 +            glMultMatrixf(m);
 25.2627 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2628 +        }
 25.2629 +
 25.2630 +        #undef glNewList
 25.2631 +        extern "C" { GLAPI void GLAPIENTRY glNewList(GLuint list, GLenum mode); }
 25.2632 +        void OVR::GLEContext::glNewList_Hook(GLuint list, GLenum mode)
 25.2633 +        {
 25.2634 +            glNewList(list, mode);
 25.2635 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2636 +        }
 25.2637 +
 25.2638 +        #undef glNormal3b
 25.2639 +        extern "C" { GLAPI void GLAPIENTRY glNormal3b(GLbyte nx, GLbyte ny, GLbyte nz); }
 25.2640 +        void OVR::GLEContext::glNormal3b_Hook(GLbyte nx, GLbyte ny, GLbyte nz)
 25.2641 +        {
 25.2642 +            glNormal3b(nx, ny, nz);
 25.2643 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2644 +        }
 25.2645 +
 25.2646 +        #undef glNormal3bv
 25.2647 +        extern "C" { GLAPI void GLAPIENTRY glNormal3bv(const GLbyte *v); }
 25.2648 +        void OVR::GLEContext::glNormal3bv_Hook(const GLbyte *v)
 25.2649 +        {
 25.2650 +            glNormal3bv(v);
 25.2651 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2652 +        }
 25.2653 +
 25.2654 +        #undef glNormal3d
 25.2655 +        extern "C" { GLAPI void GLAPIENTRY glNormal3d(GLdouble nx, GLdouble ny, GLdouble nz); }
 25.2656 +        void OVR::GLEContext::glNormal3d_Hook(GLdouble nx, GLdouble ny, GLdouble nz)
 25.2657 +        {
 25.2658 +            glNormal3d(nx, ny, nz);
 25.2659 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2660 +        }
 25.2661 +
 25.2662 +        #undef glNormal3dv
 25.2663 +        extern "C" { GLAPI void GLAPIENTRY glNormal3dv(const GLdouble *v); }
 25.2664 +        void OVR::GLEContext::glNormal3dv_Hook(const GLdouble *v)
 25.2665 +        {
 25.2666 +            glNormal3dv(v);
 25.2667 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2668 +        }
 25.2669 +
 25.2670 +        #undef glNormal3f
 25.2671 +        extern "C" { GLAPI void GLAPIENTRY glNormal3f(GLfloat nx, GLfloat ny, GLfloat nz); }
 25.2672 +        void OVR::GLEContext::glNormal3f_Hook(GLfloat nx, GLfloat ny, GLfloat nz)
 25.2673 +        {
 25.2674 +            glNormal3f(nx, ny, nz);
 25.2675 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2676 +        }
 25.2677 +
 25.2678 +        #undef glNormal3fv
 25.2679 +        extern "C" { GLAPI void GLAPIENTRY glNormal3fv(const GLfloat *v); }
 25.2680 +        void OVR::GLEContext::glNormal3fv_Hook(const GLfloat *v)
 25.2681 +        {
 25.2682 +            glNormal3fv(v);
 25.2683 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2684 +        }
 25.2685 +
 25.2686 +        #undef glNormal3i
 25.2687 +        extern "C" { GLAPI void GLAPIENTRY glNormal3i(GLint nx, GLint ny, GLint nz); }
 25.2688 +        void OVR::GLEContext::glNormal3i_Hook(GLint nx, GLint ny, GLint nz)
 25.2689 +        {
 25.2690 +            glNormal3i(nx, ny, nz);
 25.2691 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2692 +        }
 25.2693 +
 25.2694 +        #undef glNormal3iv
 25.2695 +        extern "C" { GLAPI void GLAPIENTRY glNormal3iv(const GLint *v); }
 25.2696 +        void OVR::GLEContext::glNormal3iv_Hook(const GLint *v)
 25.2697 +        {
 25.2698 +            glNormal3iv(v);
 25.2699 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2700 +        }
 25.2701 +
 25.2702 +        #undef glNormal3s
 25.2703 +        extern "C" { GLAPI void GLAPIENTRY glNormal3s(GLshort nx, GLshort ny, GLshort nz); }
 25.2704 +        void OVR::GLEContext::glNormal3s_Hook(GLshort nx, GLshort ny, GLshort nz)
 25.2705 +        {
 25.2706 +            glNormal3s(nx, ny, nz);
 25.2707 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2708 +        }
 25.2709 +
 25.2710 +        #undef glNormal3sv
 25.2711 +        extern "C" { GLAPI void GLAPIENTRY glNormal3sv(const GLshort *v); }
 25.2712 +        void OVR::GLEContext::glNormal3sv_Hook(const GLshort *v)
 25.2713 +        {
 25.2714 +            glNormal3sv(v);
 25.2715 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2716 +        }
 25.2717 +
 25.2718 +        #undef glNormalPointer
 25.2719 +        extern "C" { GLAPI void GLAPIENTRY glNormalPointer(GLenum type, GLsizei stride, const void *pointer); }
 25.2720 +        void OVR::GLEContext::glNormalPointer_Hook(GLenum type, GLsizei stride, const void *pointer)
 25.2721 +        {
 25.2722 +            glNormalPointer(type, stride, pointer);
 25.2723 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2724 +        }
 25.2725 +
 25.2726 +        #undef glOrtho
 25.2727 +        extern "C" { GLAPI void GLAPIENTRY glOrtho(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar); }
 25.2728 +        void OVR::GLEContext::glOrtho_Hook(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar)
 25.2729 +        {
 25.2730 +            glOrtho(left, right, bottom, top, zNear, zFar);
 25.2731 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2732 +        }
 25.2733 +
 25.2734 +        #undef glPassThrough
 25.2735 +        extern "C" { GLAPI void GLAPIENTRY glPassThrough(GLfloat token); }
 25.2736 +        void OVR::GLEContext::glPassThrough_Hook(GLfloat token)
 25.2737 +        {
 25.2738 +            glPassThrough(token);
 25.2739 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2740 +        }
 25.2741 +
 25.2742 +        #undef glPixelMapfv
 25.2743 +        extern "C" { GLAPI void GLAPIENTRY glPixelMapfv(GLenum map, GLsizei mapsize, const GLfloat *values); }
 25.2744 +        void OVR::GLEContext::glPixelMapfv_Hook(GLenum map, GLsizei mapsize, const GLfloat *values)
 25.2745 +        {
 25.2746 +            glPixelMapfv(map, mapsize, values);
 25.2747 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2748 +        }
 25.2749 +
 25.2750 +        #undef glPixelMapuiv
 25.2751 +        extern "C" { GLAPI void GLAPIENTRY glPixelMapuiv(GLenum map, GLsizei mapsize, const GLuint *values); }
 25.2752 +        void OVR::GLEContext::glPixelMapuiv_Hook(GLenum map, GLsizei mapsize, const GLuint *values)
 25.2753 +        {
 25.2754 +            glPixelMapuiv(map, mapsize, values);
 25.2755 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2756 +        }
 25.2757 +
 25.2758 +        #undef glPixelMapusv
 25.2759 +        extern "C" { GLAPI void GLAPIENTRY glPixelMapusv(GLenum map, GLsizei mapsize, const GLushort *values); }
 25.2760 +        void OVR::GLEContext::glPixelMapusv_Hook(GLenum map, GLsizei mapsize, const GLushort *values)
 25.2761 +        {
 25.2762 +            glPixelMapusv(map, mapsize, values);
 25.2763 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2764 +        }
 25.2765 +
 25.2766 +        #undef glPixelStoref
 25.2767 +        extern "C" { GLAPI void GLAPIENTRY glPixelStoref(GLenum pname, GLfloat param); }
 25.2768 +        void OVR::GLEContext::glPixelStoref_Hook(GLenum pname, GLfloat param)
 25.2769 +        {
 25.2770 +            glPixelStoref(pname, param);
 25.2771 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2772 +        }
 25.2773 +
 25.2774 +        #undef glPixelStorei
 25.2775 +        extern "C" { GLAPI void GLAPIENTRY glPixelStorei(GLenum pname, GLint param); }
 25.2776 +        void OVR::GLEContext::glPixelStorei_Hook(GLenum pname, GLint param)
 25.2777 +        {
 25.2778 +            glPixelStorei(pname, param);
 25.2779 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2780 +        }
 25.2781 +
 25.2782 +        #undef glPixelTransferf
 25.2783 +        extern "C" { GLAPI void GLAPIENTRY glPixelTransferf(GLenum pname, GLfloat param); }
 25.2784 +        void OVR::GLEContext::glPixelTransferf_Hook(GLenum pname, GLfloat param)
 25.2785 +        {
 25.2786 +            glPixelTransferf(pname, param);
 25.2787 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2788 +        }
 25.2789 +
 25.2790 +        #undef glPixelTransferi
 25.2791 +        extern "C" { GLAPI void GLAPIENTRY glPixelTransferi(GLenum pname, GLint param); }
 25.2792 +        void OVR::GLEContext::glPixelTransferi_Hook(GLenum pname, GLint param)
 25.2793 +        {
 25.2794 +            glPixelTransferi(pname, param);
 25.2795 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2796 +        }
 25.2797 +
 25.2798 +        #undef glPixelZoom
 25.2799 +        extern "C" { GLAPI void GLAPIENTRY glPixelZoom(GLfloat xfactor, GLfloat yfactor); }
 25.2800 +        void OVR::GLEContext::glPixelZoom_Hook(GLfloat xfactor, GLfloat yfactor)
 25.2801 +        {
 25.2802 +            glPixelZoom(xfactor, yfactor);
 25.2803 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2804 +        }
 25.2805 +
 25.2806 +        #undef glPointSize
 25.2807 +        extern "C" { GLAPI void GLAPIENTRY glPointSize(GLfloat size); }
 25.2808 +        void OVR::GLEContext::glPointSize_Hook(GLfloat size)
 25.2809 +        {
 25.2810 +            glPointSize(size);
 25.2811 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2812 +        }
 25.2813 +
 25.2814 +        #undef glPolygonMode
 25.2815 +        extern "C" { GLAPI void GLAPIENTRY glPolygonMode(GLenum face, GLenum mode); }
 25.2816 +        void OVR::GLEContext::glPolygonMode_Hook(GLenum face, GLenum mode)
 25.2817 +        {
 25.2818 +            glPolygonMode(face, mode);
 25.2819 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2820 +        }
 25.2821 +
 25.2822 +        #undef glPolygonOffset
 25.2823 +        extern "C" { GLAPI void GLAPIENTRY glPolygonOffset(GLfloat factor, GLfloat units); }
 25.2824 +        void OVR::GLEContext::glPolygonOffset_Hook(GLfloat factor, GLfloat units)
 25.2825 +        {
 25.2826 +            glPolygonOffset(factor, units);
 25.2827 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2828 +        }
 25.2829 +
 25.2830 +        #undef glPolygonStipple
 25.2831 +        extern "C" { GLAPI void GLAPIENTRY glPolygonStipple(const GLubyte *mask); }
 25.2832 +        void OVR::GLEContext::glPolygonStipple_Hook(const GLubyte *mask)
 25.2833 +        {
 25.2834 +            glPolygonStipple(mask);
 25.2835 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2836 +        }
 25.2837 +
 25.2838 +        #undef glPopAttrib
 25.2839 +        extern "C" { GLAPI void GLAPIENTRY glPopAttrib(); }
 25.2840 +        void OVR::GLEContext::glPopAttrib_Hook()
 25.2841 +        {
 25.2842 +            glPopAttrib();
 25.2843 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2844 +        }
 25.2845 +
 25.2846 +        #undef glPopClientAttrib
 25.2847 +        extern "C" { GLAPI void GLAPIENTRY glPopClientAttrib(); }
 25.2848 +        void OVR::GLEContext::glPopClientAttrib_Hook()
 25.2849 +        {
 25.2850 +            glPopClientAttrib();
 25.2851 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2852 +        }
 25.2853 +
 25.2854 +        #undef glPopMatrix
 25.2855 +        extern "C" { GLAPI void GLAPIENTRY glPopMatrix(); }
 25.2856 +        void OVR::GLEContext::glPopMatrix_Hook()
 25.2857 +        {
 25.2858 +            glPopMatrix();
 25.2859 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2860 +        }
 25.2861 +
 25.2862 +        #undef glPopName
 25.2863 +        extern "C" { GLAPI void GLAPIENTRY glPopName(); }
 25.2864 +        void OVR::GLEContext::glPopName_Hook()
 25.2865 +        {
 25.2866 +            glPopName();
 25.2867 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2868 +        }
 25.2869 +
 25.2870 +        #undef glPrioritizeTextures
 25.2871 +        extern "C" { GLAPI void GLAPIENTRY glPrioritizeTextures(GLsizei n, const GLuint *textures, const GLclampf *priorities); }
 25.2872 +        void OVR::GLEContext::glPrioritizeTextures_Hook(GLsizei n, const GLuint *textures, const GLclampf *priorities)
 25.2873 +        {
 25.2874 +            glPrioritizeTextures(n, textures, priorities);
 25.2875 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2876 +        }
 25.2877 +
 25.2878 +        #undef glPushAttrib
 25.2879 +        extern "C" { GLAPI void GLAPIENTRY glPushAttrib(GLbitfield mask); }
 25.2880 +        void OVR::GLEContext::glPushAttrib_Hook(GLbitfield mask)
 25.2881 +        {
 25.2882 +            glPushAttrib(mask);
 25.2883 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2884 +        }
 25.2885 +
 25.2886 +        #undef glPushClientAttrib
 25.2887 +        extern "C" { GLAPI void GLAPIENTRY glPushClientAttrib(GLbitfield mask); }
 25.2888 +        void OVR::GLEContext::glPushClientAttrib_Hook(GLbitfield mask)
 25.2889 +        {
 25.2890 +            glPushClientAttrib(mask);
 25.2891 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2892 +        }
 25.2893 +
 25.2894 +        #undef glPushMatrix
 25.2895 +        extern "C" { GLAPI void GLAPIENTRY glPushMatrix(); }
 25.2896 +        void OVR::GLEContext::glPushMatrix_Hook()
 25.2897 +        {
 25.2898 +            glPushMatrix();
 25.2899 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2900 +        }
 25.2901 +
 25.2902 +        #undef glPushName
 25.2903 +        extern "C" { GLAPI void GLAPIENTRY glPushName(GLuint name); }
 25.2904 +        void OVR::GLEContext::glPushName_Hook(GLuint name)
 25.2905 +        {
 25.2906 +            glPushName(name);
 25.2907 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2908 +        }
 25.2909 +
 25.2910 +        #undef glRasterPos2d
 25.2911 +        extern "C" { GLAPI void GLAPIENTRY glRasterPos2d(GLdouble x, GLdouble y); }
 25.2912 +        void OVR::GLEContext::glRasterPos2d_Hook(GLdouble x, GLdouble y)
 25.2913 +        {
 25.2914 +            glRasterPos2d(x, y);
 25.2915 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2916 +        }
 25.2917 +
 25.2918 +        #undef glRasterPos2dv
 25.2919 +        extern "C" { GLAPI void GLAPIENTRY glRasterPos2dv(const GLdouble *v); }
 25.2920 +        void OVR::GLEContext::glRasterPos2dv_Hook(const GLdouble *v)
 25.2921 +        {
 25.2922 +            glRasterPos2dv(v);
 25.2923 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2924 +        }
 25.2925 +
 25.2926 +        #undef glRasterPos2f
 25.2927 +        extern "C" { GLAPI void GLAPIENTRY glRasterPos2f(GLfloat x, GLfloat y); }
 25.2928 +        void OVR::GLEContext::glRasterPos2f_Hook(GLfloat x, GLfloat y)
 25.2929 +        {
 25.2930 +            glRasterPos2f(x, y);
 25.2931 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2932 +        }
 25.2933 +
 25.2934 +        #undef glRasterPos2fv
 25.2935 +        extern "C" { GLAPI void GLAPIENTRY glRasterPos2fv(const GLfloat *v); }
 25.2936 +        void OVR::GLEContext::glRasterPos2fv_Hook(const GLfloat *v)
 25.2937 +        {
 25.2938 +            glRasterPos2fv(v);
 25.2939 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2940 +        }
 25.2941 +
 25.2942 +        #undef glRasterPos2i
 25.2943 +        extern "C" { GLAPI void GLAPIENTRY glRasterPos2i(GLint x, GLint y); }
 25.2944 +        void OVR::GLEContext::glRasterPos2i_Hook(GLint x, GLint y)
 25.2945 +        {
 25.2946 +            glRasterPos2i(x, y);
 25.2947 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2948 +        }
 25.2949 +
 25.2950 +        #undef glRasterPos2iv
 25.2951 +        extern "C" { GLAPI void GLAPIENTRY glRasterPos2iv(const GLint *v); }
 25.2952 +        void OVR::GLEContext::glRasterPos2iv_Hook(const GLint *v)
 25.2953 +        {
 25.2954 +            glRasterPos2iv(v);
 25.2955 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2956 +        }
 25.2957 +
 25.2958 +        #undef glRasterPos2s
 25.2959 +        extern "C" { GLAPI void GLAPIENTRY glRasterPos2s(GLshort x, GLshort y); }
 25.2960 +        void OVR::GLEContext::glRasterPos2s_Hook(GLshort x, GLshort y)
 25.2961 +        {
 25.2962 +            glRasterPos2s(x, y);
 25.2963 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2964 +        }
 25.2965 +
 25.2966 +        #undef glRasterPos2sv
 25.2967 +        extern "C" { GLAPI void GLAPIENTRY glRasterPos2sv(const GLshort *v); }
 25.2968 +        void OVR::GLEContext::glRasterPos2sv_Hook(const GLshort *v)
 25.2969 +        {
 25.2970 +            glRasterPos2sv(v);
 25.2971 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2972 +        }
 25.2973 +
 25.2974 +        #undef glRasterPos3d
 25.2975 +        extern "C" { GLAPI void GLAPIENTRY glRasterPos3d(GLdouble x, GLdouble y, GLdouble z); }
 25.2976 +        void OVR::GLEContext::glRasterPos3d_Hook(GLdouble x, GLdouble y, GLdouble z)
 25.2977 +        {
 25.2978 +            glRasterPos3d(x, y, z);
 25.2979 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2980 +        }
 25.2981 +
 25.2982 +        #undef glRasterPos3dv
 25.2983 +        extern "C" { GLAPI void GLAPIENTRY glRasterPos3dv(const GLdouble *v); }
 25.2984 +        void OVR::GLEContext::glRasterPos3dv_Hook(const GLdouble *v)
 25.2985 +        {
 25.2986 +            glRasterPos3dv(v);
 25.2987 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2988 +        }
 25.2989 +
 25.2990 +        #undef glRasterPos3f
 25.2991 +        extern "C" { GLAPI void GLAPIENTRY glRasterPos3f(GLfloat x, GLfloat y, GLfloat z); }
 25.2992 +        void OVR::GLEContext::glRasterPos3f_Hook(GLfloat x, GLfloat y, GLfloat z)
 25.2993 +        {
 25.2994 +            glRasterPos3f(x, y, z);
 25.2995 +            PostHook(GLE_CURRENT_FUNCTION);
 25.2996 +        }
 25.2997 +
 25.2998 +        #undef glRasterPos3fv
 25.2999 +        extern "C" { GLAPI void GLAPIENTRY glRasterPos3fv(const GLfloat *v); }
 25.3000 +        void OVR::GLEContext::glRasterPos3fv_Hook(const GLfloat *v)
 25.3001 +        {
 25.3002 +            glRasterPos3fv(v);
 25.3003 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3004 +        }
 25.3005 +
 25.3006 +        #undef glRasterPos3i
 25.3007 +        extern "C" { GLAPI void GLAPIENTRY glRasterPos3i(GLint x, GLint y, GLint z); }
 25.3008 +        void OVR::GLEContext::glRasterPos3i_Hook(GLint x, GLint y, GLint z)
 25.3009 +        {
 25.3010 +            glRasterPos3i(x, y, z);
 25.3011 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3012 +        }
 25.3013 +
 25.3014 +        #undef glRasterPos3iv
 25.3015 +        extern "C" { GLAPI void GLAPIENTRY glRasterPos3iv(const GLint *v); }
 25.3016 +        void OVR::GLEContext::glRasterPos3iv_Hook(const GLint *v)
 25.3017 +        {
 25.3018 +            glRasterPos3iv(v);
 25.3019 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3020 +        }
 25.3021 +
 25.3022 +        #undef glRasterPos3s
 25.3023 +        extern "C" { GLAPI void GLAPIENTRY glRasterPos3s(GLshort x, GLshort y, GLshort z); }
 25.3024 +        void OVR::GLEContext::glRasterPos3s_Hook(GLshort x, GLshort y, GLshort z)
 25.3025 +        {
 25.3026 +            glRasterPos3s(x, y, z);
 25.3027 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3028 +        }
 25.3029 +
 25.3030 +        #undef glRasterPos3sv
 25.3031 +        extern "C" { GLAPI void GLAPIENTRY glRasterPos3sv(const GLshort *v); }
 25.3032 +        void OVR::GLEContext::glRasterPos3sv_Hook(const GLshort *v)
 25.3033 +        {
 25.3034 +            glRasterPos3sv(v);
 25.3035 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3036 +        }
 25.3037 +
 25.3038 +        #undef glRasterPos4d
 25.3039 +        extern "C" { GLAPI void GLAPIENTRY glRasterPos4d(GLdouble x, GLdouble y, GLdouble z, GLdouble w); }
 25.3040 +        void OVR::GLEContext::glRasterPos4d_Hook(GLdouble x, GLdouble y, GLdouble z, GLdouble w)
 25.3041 +        {
 25.3042 +            glRasterPos4d(x, y, z, w);
 25.3043 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3044 +        }
 25.3045 +
 25.3046 +        #undef glRasterPos4dv
 25.3047 +        extern "C" { GLAPI void GLAPIENTRY glRasterPos4dv(const GLdouble *v); }
 25.3048 +        void OVR::GLEContext::glRasterPos4dv_Hook(const GLdouble *v)
 25.3049 +        {
 25.3050 +            glRasterPos4dv(v);
 25.3051 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3052 +        }
 25.3053 +
 25.3054 +        #undef glRasterPos4f
 25.3055 +        extern "C" { GLAPI void GLAPIENTRY glRasterPos4f(GLfloat x, GLfloat y, GLfloat z, GLfloat w); }
 25.3056 +        void OVR::GLEContext::glRasterPos4f_Hook(GLfloat x, GLfloat y, GLfloat z, GLfloat w)
 25.3057 +        {
 25.3058 +            glRasterPos4f(x, y, z, w);
 25.3059 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3060 +        }
 25.3061 +
 25.3062 +        #undef glRasterPos4fv
 25.3063 +        extern "C" { GLAPI void GLAPIENTRY glRasterPos4fv(const GLfloat *v); }
 25.3064 +        void OVR::GLEContext::glRasterPos4fv_Hook(const GLfloat *v)
 25.3065 +        {
 25.3066 +            glRasterPos4fv(v);
 25.3067 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3068 +        }
 25.3069 +
 25.3070 +        #undef glRasterPos4i
 25.3071 +        extern "C" { GLAPI void GLAPIENTRY glRasterPos4i(GLint x, GLint y, GLint z, GLint w); }
 25.3072 +        void OVR::GLEContext::glRasterPos4i_Hook(GLint x, GLint y, GLint z, GLint w)
 25.3073 +        {
 25.3074 +            glRasterPos4i(x, y, z, w);
 25.3075 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3076 +        }
 25.3077 +
 25.3078 +        #undef glRasterPos4iv
 25.3079 +        extern "C" { GLAPI void GLAPIENTRY glRasterPos4iv(const GLint *v); }
 25.3080 +        void OVR::GLEContext::glRasterPos4iv_Hook(const GLint *v)
 25.3081 +        {
 25.3082 +            glRasterPos4iv(v);
 25.3083 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3084 +        }
 25.3085 +
 25.3086 +        #undef glRasterPos4s
 25.3087 +        extern "C" { GLAPI void GLAPIENTRY glRasterPos4s(GLshort x, GLshort y, GLshort z, GLshort w); }
 25.3088 +        void OVR::GLEContext::glRasterPos4s_Hook(GLshort x, GLshort y, GLshort z, GLshort w)
 25.3089 +        {
 25.3090 +            glRasterPos4s(x, y, z, w);
 25.3091 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3092 +        }
 25.3093 +
 25.3094 +        #undef glRasterPos4sv
 25.3095 +        extern "C" { GLAPI void GLAPIENTRY glRasterPos4sv(const GLshort *v); }
 25.3096 +        void OVR::GLEContext::glRasterPos4sv_Hook(const GLshort *v)
 25.3097 +        {
 25.3098 +            glRasterPos4sv(v);
 25.3099 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3100 +        }
 25.3101 +
 25.3102 +        #undef glReadBuffer
 25.3103 +        extern "C" { GLAPI void GLAPIENTRY glReadBuffer(GLenum mode); }
 25.3104 +        void OVR::GLEContext::glReadBuffer_Hook(GLenum mode)
 25.3105 +        {
 25.3106 +            glReadBuffer(mode);
 25.3107 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3108 +        }
 25.3109 +
 25.3110 +        #undef glReadPixels
 25.3111 +        extern "C" { GLAPI void GLAPIENTRY glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels); }
 25.3112 +        void OVR::GLEContext::glReadPixels_Hook(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels)
 25.3113 +        {
 25.3114 +            glReadPixels(x, y, width, height, format, type, pixels);
 25.3115 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3116 +        }
 25.3117 +
 25.3118 +        #undef glRectd
 25.3119 +        extern "C" { GLAPI void GLAPIENTRY glRectd(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2); }
 25.3120 +        void OVR::GLEContext::glRectd_Hook(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2)
 25.3121 +        {
 25.3122 +            glRectd(x1, y1, x2, y2);
 25.3123 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3124 +        }
 25.3125 +
 25.3126 +        #undef glRectdv
 25.3127 +        extern "C" { GLAPI void GLAPIENTRY glRectdv(const GLdouble *v1, const GLdouble *v2); }
 25.3128 +        void OVR::GLEContext::glRectdv_Hook(const GLdouble *v1, const GLdouble *v2)
 25.3129 +        {
 25.3130 +            glRectdv(v1, v2);
 25.3131 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3132 +        }
 25.3133 +
 25.3134 +        #undef glRectf
 25.3135 +        extern "C" { GLAPI void GLAPIENTRY glRectf(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2); }
 25.3136 +        void OVR::GLEContext::glRectf_Hook(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2)
 25.3137 +        {
 25.3138 +            glRectf(x1, y1, x2, y2);
 25.3139 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3140 +        }
 25.3141 +
 25.3142 +        #undef glRectfv
 25.3143 +        extern "C" { GLAPI void GLAPIENTRY glRectfv(const GLfloat *v1, const GLfloat *v2); }
 25.3144 +        void OVR::GLEContext::glRectfv_Hook(const GLfloat *v1, const GLfloat *v2)
 25.3145 +        {
 25.3146 +            glRectfv(v1, v2);
 25.3147 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3148 +        }
 25.3149 +
 25.3150 +        #undef glRecti
 25.3151 +        extern "C" { GLAPI void GLAPIENTRY glRecti(GLint x1, GLint y1, GLint x2, GLint y2); }
 25.3152 +        void OVR::GLEContext::glRecti_Hook(GLint x1, GLint y1, GLint x2, GLint y2)
 25.3153 +        {
 25.3154 +            glRecti(x1, y1, x2, y2);
 25.3155 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3156 +        }
 25.3157 +
 25.3158 +        #undef glRectiv
 25.3159 +        extern "C" { GLAPI void GLAPIENTRY glRectiv(const GLint *v1, const GLint *v2); }
 25.3160 +        void OVR::GLEContext::glRectiv_Hook(const GLint *v1, const GLint *v2)
 25.3161 +        {
 25.3162 +            glRectiv(v1, v2);
 25.3163 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3164 +        }
 25.3165 +
 25.3166 +        #undef glRects
 25.3167 +        extern "C" { GLAPI void GLAPIENTRY glRects(GLshort x1, GLshort y1, GLshort x2, GLshort y2); }
 25.3168 +        void OVR::GLEContext::glRects_Hook(GLshort x1, GLshort y1, GLshort x2, GLshort y2)
 25.3169 +        {
 25.3170 +            glRects(x1, y1, x2, y2);
 25.3171 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3172 +        }
 25.3173 +
 25.3174 +        #undef glRectsv
 25.3175 +        extern "C" { GLAPI void GLAPIENTRY glRectsv(const GLshort *v1, const GLshort *v2); }
 25.3176 +        void OVR::GLEContext::glRectsv_Hook(const GLshort *v1, const GLshort *v2)
 25.3177 +        {
 25.3178 +            glRectsv(v1, v2);
 25.3179 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3180 +        }
 25.3181 +
 25.3182 +        #undef glRenderMode
 25.3183 +        extern "C" { GLAPI GLint GLAPIENTRY glRenderMode(GLenum mode); }
 25.3184 +        GLint OVR::GLEContext::glRenderMode_Hook(GLenum mode)
 25.3185 +        {
 25.3186 +            GLint  i = glRenderMode(mode);
 25.3187 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3188 +            return i;
 25.3189 +        }
 25.3190 +
 25.3191 +        #undef glRotated
 25.3192 +        extern "C" { GLAPI void GLAPIENTRY glRotated(GLdouble angle, GLdouble x, GLdouble y, GLdouble z); }
 25.3193 +        void OVR::GLEContext::glRotated_Hook(GLdouble angle, GLdouble x, GLdouble y, GLdouble z)
 25.3194 +        {
 25.3195 +            glRotated(angle, x, y, z);
 25.3196 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3197 +        }
 25.3198 +
 25.3199 +        #undef glRotatef
 25.3200 +        extern "C" { GLAPI void GLAPIENTRY glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z); }
 25.3201 +        void OVR::GLEContext::glRotatef_Hook(GLfloat angle, GLfloat x, GLfloat y, GLfloat z)
 25.3202 +        {
 25.3203 +            glRotatef(angle, x, y, z);
 25.3204 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3205 +        }
 25.3206 +
 25.3207 +        #undef glScaled
 25.3208 +        extern "C" { GLAPI void GLAPIENTRY glScaled(GLdouble x, GLdouble y, GLdouble z); }
 25.3209 +        void OVR::GLEContext::glScaled_Hook(GLdouble x, GLdouble y, GLdouble z)
 25.3210 +        {
 25.3211 +            glScaled(x, y, z);
 25.3212 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3213 +        }
 25.3214 +
 25.3215 +        #undef glScalef
 25.3216 +        extern "C" { GLAPI void GLAPIENTRY glScalef(GLfloat x, GLfloat y, GLfloat z); }
 25.3217 +        void OVR::GLEContext::glScalef_Hook(GLfloat x, GLfloat y, GLfloat z)
 25.3218 +        {
 25.3219 +            glScalef(x, y, z);
 25.3220 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3221 +        }
 25.3222 +
 25.3223 +        #undef glScissor
 25.3224 +        extern "C" { GLAPI void GLAPIENTRY glScissor(GLint x, GLint y, GLsizei width, GLsizei height); }
 25.3225 +        void OVR::GLEContext::glScissor_Hook(GLint x, GLint y, GLsizei width, GLsizei height)
 25.3226 +        {
 25.3227 +            glScissor(x, y, width, height);
 25.3228 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3229 +        }
 25.3230 +
 25.3231 +        #undef glSelectBuffer
 25.3232 +        extern "C" { GLAPI void GLAPIENTRY glSelectBuffer(GLsizei size, GLuint *buffer); }
 25.3233 +        void OVR::GLEContext::glSelectBuffer_Hook(GLsizei size, GLuint *buffer)
 25.3234 +        {
 25.3235 +            glSelectBuffer(size, buffer);
 25.3236 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3237 +        }
 25.3238 +
 25.3239 +        #undef glShadeModel
 25.3240 +        extern "C" { GLAPI void GLAPIENTRY glShadeModel(GLenum mode); }
 25.3241 +        void OVR::GLEContext::glShadeModel_Hook(GLenum mode)
 25.3242 +        {
 25.3243 +            glShadeModel(mode);
 25.3244 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3245 +        }
 25.3246 +
 25.3247 +        #undef glStencilFunc
 25.3248 +        extern "C" { GLAPI void GLAPIENTRY glStencilFunc(GLenum func, GLint ref, GLuint mask); }
 25.3249 +        void OVR::GLEContext::glStencilFunc_Hook(GLenum func, GLint ref, GLuint mask)
 25.3250 +        {
 25.3251 +            glStencilFunc(func, ref, mask);
 25.3252 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3253 +        }
 25.3254 +
 25.3255 +        #undef glStencilMask
 25.3256 +        extern "C" { GLAPI void GLAPIENTRY glStencilMask(GLuint mask); }
 25.3257 +        void OVR::GLEContext::glStencilMask_Hook(GLuint mask)
 25.3258 +        {
 25.3259 +            glStencilMask(mask);
 25.3260 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3261 +        }
 25.3262 +
 25.3263 +        #undef glStencilOp
 25.3264 +        extern "C" { GLAPI void GLAPIENTRY glStencilOp(GLenum fail, GLenum zfail, GLenum zpass); }
 25.3265 +        void OVR::GLEContext::glStencilOp_Hook(GLenum fail, GLenum zfail, GLenum zpass)
 25.3266 +        {
 25.3267 +            glStencilOp(fail, zfail, zpass);
 25.3268 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3269 +        }
 25.3270 +
 25.3271 +        #undef glTexCoord1d
 25.3272 +        extern "C" { GLAPI void GLAPIENTRY glTexCoord1d(GLdouble s); }
 25.3273 +        void OVR::GLEContext::glTexCoord1d_Hook(GLdouble s)
 25.3274 +        {
 25.3275 +            glTexCoord1d(s);
 25.3276 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3277 +        }
 25.3278 +
 25.3279 +        #undef glTexCoord1dv
 25.3280 +        extern "C" { GLAPI void GLAPIENTRY glTexCoord1dv(const GLdouble *v); }
 25.3281 +        void OVR::GLEContext::glTexCoord1dv_Hook(const GLdouble *v)
 25.3282 +        {
 25.3283 +            glTexCoord1dv(v);
 25.3284 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3285 +        }
 25.3286 +
 25.3287 +        #undef glTexCoord1f
 25.3288 +        extern "C" { GLAPI void GLAPIENTRY glTexCoord1f(GLfloat s); }
 25.3289 +        void OVR::GLEContext::glTexCoord1f_Hook(GLfloat s)
 25.3290 +        {
 25.3291 +            glTexCoord1f(s);
 25.3292 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3293 +        }
 25.3294 +
 25.3295 +        #undef glTexCoord1fv
 25.3296 +        extern "C" { GLAPI void GLAPIENTRY glTexCoord1fv(const GLfloat *v); }
 25.3297 +        void OVR::GLEContext::glTexCoord1fv_Hook(const GLfloat *v)
 25.3298 +        {
 25.3299 +            glTexCoord1fv(v);
 25.3300 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3301 +        }
 25.3302 +
 25.3303 +        #undef glTexCoord1i
 25.3304 +        extern "C" { GLAPI void GLAPIENTRY glTexCoord1i(GLint s); }
 25.3305 +        void OVR::GLEContext::glTexCoord1i_Hook(GLint s)
 25.3306 +        {
 25.3307 +            glTexCoord1i(s);
 25.3308 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3309 +        }
 25.3310 +
 25.3311 +        #undef glTexCoord1iv
 25.3312 +        extern "C" { GLAPI void GLAPIENTRY glTexCoord1iv(const GLint *v); }
 25.3313 +        void OVR::GLEContext::glTexCoord1iv_Hook(const GLint *v)
 25.3314 +        {
 25.3315 +            glTexCoord1iv(v);
 25.3316 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3317 +        }
 25.3318 +
 25.3319 +        #undef glTexCoord1s
 25.3320 +        extern "C" { GLAPI void GLAPIENTRY glTexCoord1s(GLshort s); }
 25.3321 +        void OVR::GLEContext::glTexCoord1s_Hook(GLshort s)
 25.3322 +        {
 25.3323 +            glTexCoord1s(s);
 25.3324 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3325 +        }
 25.3326 +
 25.3327 +        #undef glTexCoord1sv
 25.3328 +        extern "C" { GLAPI void GLAPIENTRY glTexCoord1sv(const GLshort *v); }
 25.3329 +        void OVR::GLEContext::glTexCoord1sv_Hook(const GLshort *v)
 25.3330 +        {
 25.3331 +            glTexCoord1sv(v);
 25.3332 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3333 +        }
 25.3334 +
 25.3335 +        #undef glTexCoord2d
 25.3336 +        extern "C" { GLAPI void GLAPIENTRY glTexCoord2d(GLdouble s, GLdouble t); }
 25.3337 +        void OVR::GLEContext::glTexCoord2d_Hook(GLdouble s, GLdouble t)
 25.3338 +        {
 25.3339 +            glTexCoord2d(s, t);
 25.3340 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3341 +        }
 25.3342 +
 25.3343 +        #undef glTexCoord2dv
 25.3344 +        extern "C" { GLAPI void GLAPIENTRY glTexCoord2dv(const GLdouble *v); }
 25.3345 +        void OVR::GLEContext::glTexCoord2dv_Hook(const GLdouble *v)
 25.3346 +        {
 25.3347 +            glTexCoord2dv(v);
 25.3348 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3349 +        }
 25.3350 +
 25.3351 +        #undef glTexCoord2f
 25.3352 +        extern "C" { GLAPI void GLAPIENTRY glTexCoord2f(GLfloat s, GLfloat t); }
 25.3353 +        void OVR::GLEContext::glTexCoord2f_Hook(GLfloat s, GLfloat t)
 25.3354 +        {
 25.3355 +            glTexCoord2f(s, t);
 25.3356 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3357 +        }
 25.3358 +
 25.3359 +        #undef glTexCoord2fv
 25.3360 +        extern "C" { GLAPI void GLAPIENTRY glTexCoord2fv(const GLfloat *v); }
 25.3361 +        void OVR::GLEContext::glTexCoord2fv_Hook(const GLfloat *v)
 25.3362 +        {
 25.3363 +            glTexCoord2fv(v);
 25.3364 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3365 +        }
 25.3366 +
 25.3367 +        #undef glTexCoord2i
 25.3368 +        extern "C" { GLAPI void GLAPIENTRY glTexCoord2i(GLint s, GLint t); }
 25.3369 +        void OVR::GLEContext::glTexCoord2i_Hook(GLint s, GLint t)
 25.3370 +        {
 25.3371 +            glTexCoord2i(s, t);
 25.3372 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3373 +        }
 25.3374 +
 25.3375 +        #undef glTexCoord2iv
 25.3376 +        extern "C" { GLAPI void GLAPIENTRY glTexCoord2iv(const GLint *v); }
 25.3377 +        void OVR::GLEContext::glTexCoord2iv_Hook(const GLint *v)
 25.3378 +        {
 25.3379 +            glTexCoord2iv(v);
 25.3380 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3381 +        }
 25.3382 +
 25.3383 +        #undef glTexCoord2s
 25.3384 +        extern "C" { GLAPI void GLAPIENTRY glTexCoord2s(GLshort s, GLshort t); }
 25.3385 +        void OVR::GLEContext::glTexCoord2s_Hook(GLshort s, GLshort t)
 25.3386 +        {
 25.3387 +            glTexCoord2s(s, t);
 25.3388 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3389 +        }
 25.3390 +
 25.3391 +        #undef glTexCoord2sv
 25.3392 +        extern "C" { GLAPI void GLAPIENTRY glTexCoord2sv(const GLshort *v); }
 25.3393 +        void OVR::GLEContext::glTexCoord2sv_Hook(const GLshort *v)
 25.3394 +        {
 25.3395 +            glTexCoord2sv(v);
 25.3396 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3397 +        }
 25.3398 +
 25.3399 +        #undef glTexCoord3d
 25.3400 +        extern "C" { GLAPI void GLAPIENTRY glTexCoord3d(GLdouble s, GLdouble t, GLdouble r); }
 25.3401 +        void OVR::GLEContext::glTexCoord3d_Hook(GLdouble s, GLdouble t, GLdouble r)
 25.3402 +        {
 25.3403 +            glTexCoord3d(s, t, r);
 25.3404 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3405 +        }
 25.3406 +
 25.3407 +        #undef glTexCoord3dv
 25.3408 +        extern "C" { GLAPI void GLAPIENTRY glTexCoord3dv(const GLdouble *v); }
 25.3409 +        void OVR::GLEContext::glTexCoord3dv_Hook(const GLdouble *v)
 25.3410 +        {
 25.3411 +            glTexCoord3dv(v);
 25.3412 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3413 +        }
 25.3414 +
 25.3415 +        #undef glTexCoord3f
 25.3416 +        extern "C" { GLAPI void GLAPIENTRY glTexCoord3f(GLfloat s, GLfloat t, GLfloat r); }
 25.3417 +        void OVR::GLEContext::glTexCoord3f_Hook(GLfloat s, GLfloat t, GLfloat r)
 25.3418 +        {
 25.3419 +            glTexCoord3f(s, t, r);
 25.3420 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3421 +        }
 25.3422 +
 25.3423 +        #undef glTexCoord3fv
 25.3424 +        extern "C" { GLAPI void GLAPIENTRY glTexCoord3fv(const GLfloat *v); }
 25.3425 +        void OVR::GLEContext::glTexCoord3fv_Hook(const GLfloat *v)
 25.3426 +        {
 25.3427 +            glTexCoord3fv(v);
 25.3428 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3429 +        }
 25.3430 +
 25.3431 +        #undef glTexCoord3i
 25.3432 +        extern "C" { GLAPI void GLAPIENTRY glTexCoord3i(GLint s, GLint t, GLint r); }
 25.3433 +        void OVR::GLEContext::glTexCoord3i_Hook(GLint s, GLint t, GLint r)
 25.3434 +        {
 25.3435 +            glTexCoord3i(s, t, r);
 25.3436 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3437 +        }
 25.3438 +
 25.3439 +        #undef glTexCoord3iv
 25.3440 +        extern "C" { GLAPI void GLAPIENTRY glTexCoord3iv(const GLint *v); }
 25.3441 +        void OVR::GLEContext::glTexCoord3iv_Hook(const GLint *v)
 25.3442 +        {
 25.3443 +            glTexCoord3iv(v);
 25.3444 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3445 +        }
 25.3446 +
 25.3447 +        #undef glTexCoord3s
 25.3448 +        extern "C" { GLAPI void GLAPIENTRY glTexCoord3s(GLshort s, GLshort t, GLshort r); }
 25.3449 +        void OVR::GLEContext::glTexCoord3s_Hook(GLshort s, GLshort t, GLshort r)
 25.3450 +        {
 25.3451 +            glTexCoord3s(s, t, r);
 25.3452 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3453 +        }
 25.3454 +
 25.3455 +        #undef glTexCoord3sv
 25.3456 +        extern "C" { GLAPI void GLAPIENTRY glTexCoord3sv(const GLshort *v); }
 25.3457 +        void OVR::GLEContext::glTexCoord3sv_Hook(const GLshort *v)
 25.3458 +        {
 25.3459 +            glTexCoord3sv(v);
 25.3460 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3461 +        }
 25.3462 +
 25.3463 +        #undef glTexCoord4d
 25.3464 +        extern "C" { GLAPI void GLAPIENTRY glTexCoord4d(GLdouble s, GLdouble t, GLdouble r, GLdouble q); }
 25.3465 +        void OVR::GLEContext::glTexCoord4d_Hook(GLdouble s, GLdouble t, GLdouble r, GLdouble q)
 25.3466 +        {
 25.3467 +            glTexCoord4d(s, t, r, q);
 25.3468 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3469 +        }
 25.3470 +
 25.3471 +        #undef glTexCoord4dv
 25.3472 +        extern "C" { GLAPI void GLAPIENTRY glTexCoord4dv(const GLdouble *v); }
 25.3473 +        void OVR::GLEContext::glTexCoord4dv_Hook(const GLdouble *v)
 25.3474 +        {
 25.3475 +            glTexCoord4dv(v);
 25.3476 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3477 +        }
 25.3478 +
 25.3479 +        #undef glTexCoord4f
 25.3480 +        extern "C" { GLAPI void GLAPIENTRY glTexCoord4f(GLfloat s, GLfloat t, GLfloat r, GLfloat q); }
 25.3481 +        void OVR::GLEContext::glTexCoord4f_Hook(GLfloat s, GLfloat t, GLfloat r, GLfloat q)
 25.3482 +        {
 25.3483 +            glTexCoord4f(s, t, r, q);
 25.3484 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3485 +        }
 25.3486 +
 25.3487 +        #undef glTexCoord4fv
 25.3488 +        extern "C" { GLAPI void GLAPIENTRY glTexCoord4fv(const GLfloat *v); }
 25.3489 +        void OVR::GLEContext::glTexCoord4fv_Hook(const GLfloat *v)
 25.3490 +        {
 25.3491 +            glTexCoord4fv(v);
 25.3492 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3493 +        }
 25.3494 +
 25.3495 +        #undef glTexCoord4i
 25.3496 +        extern "C" { GLAPI void GLAPIENTRY glTexCoord4i(GLint s, GLint t, GLint r, GLint q); }
 25.3497 +        void OVR::GLEContext::glTexCoord4i_Hook(GLint s, GLint t, GLint r, GLint q)
 25.3498 +        {
 25.3499 +            glTexCoord4i(s, t, r, q);
 25.3500 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3501 +        }
 25.3502 +
 25.3503 +        #undef glTexCoord4iv
 25.3504 +        extern "C" { GLAPI void GLAPIENTRY glTexCoord4iv(const GLint *v); }
 25.3505 +        void OVR::GLEContext::glTexCoord4iv_Hook(const GLint *v)
 25.3506 +        {
 25.3507 +            glTexCoord4iv(v);
 25.3508 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3509 +        }
 25.3510 +
 25.3511 +        #undef glTexCoord4s
 25.3512 +        extern "C" { GLAPI void GLAPIENTRY glTexCoord4s(GLshort s, GLshort t, GLshort r, GLshort q); }
 25.3513 +        void OVR::GLEContext::glTexCoord4s_Hook(GLshort s, GLshort t, GLshort r, GLshort q)
 25.3514 +        {
 25.3515 +            glTexCoord4s(s, t, r, q);
 25.3516 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3517 +        }
 25.3518 +
 25.3519 +        #undef glTexCoord4sv
 25.3520 +        extern "C" { GLAPI void GLAPIENTRY glTexCoord4sv(const GLshort *v); }
 25.3521 +        void OVR::GLEContext::glTexCoord4sv_Hook(const GLshort *v)
 25.3522 +        {
 25.3523 +            glTexCoord4sv(v);
 25.3524 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3525 +        }
 25.3526 +
 25.3527 +        #undef glTexCoordPointer
 25.3528 +        extern "C" { GLAPI void GLAPIENTRY glTexCoordPointer(GLint size, GLenum type, GLsizei stride, const void *pointer); }
 25.3529 +        void OVR::GLEContext::glTexCoordPointer_Hook(GLint size, GLenum type, GLsizei stride, const void *pointer)
 25.3530 +        {
 25.3531 +            glTexCoordPointer(size, type, stride, pointer);
 25.3532 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3533 +        }
 25.3534 +
 25.3535 +        #undef glTexEnvf
 25.3536 +        extern "C" { GLAPI void GLAPIENTRY glTexEnvf(GLenum target, GLenum pname, GLfloat param); }
 25.3537 +        void OVR::GLEContext::glTexEnvf_Hook(GLenum target, GLenum pname, GLfloat param)
 25.3538 +        {
 25.3539 +            glTexEnvf(target, pname, param);
 25.3540 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3541 +        }
 25.3542 +
 25.3543 +        #undef glTexEnvfv
 25.3544 +        extern "C" { GLAPI void GLAPIENTRY glTexEnvfv(GLenum target, GLenum pname, const GLfloat *params); }
 25.3545 +        void OVR::GLEContext::glTexEnvfv_Hook(GLenum target, GLenum pname, const GLfloat *params)
 25.3546 +        {
 25.3547 +            glTexEnvfv(target, pname, params);
 25.3548 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3549 +        }
 25.3550 +
 25.3551 +        #undef glTexEnvi
 25.3552 +        extern "C" { GLAPI void GLAPIENTRY glTexEnvi(GLenum target, GLenum pname, GLint param); }
 25.3553 +        void OVR::GLEContext::glTexEnvi_Hook(GLenum target, GLenum pname, GLint param)
 25.3554 +        {
 25.3555 +            glTexEnvi(target, pname, param);
 25.3556 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3557 +        }
 25.3558 +
 25.3559 +        #undef glTexEnviv
 25.3560 +        extern "C" { GLAPI void GLAPIENTRY glTexEnviv(GLenum target, GLenum pname, const GLint *params); }
 25.3561 +        void OVR::GLEContext::glTexEnviv_Hook(GLenum target, GLenum pname, const GLint *params)
 25.3562 +        {
 25.3563 +            glTexEnviv(target, pname, params);
 25.3564 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3565 +        }
 25.3566 +
 25.3567 +        #undef glTexGend
 25.3568 +        extern "C" { GLAPI void GLAPIENTRY glTexGend(GLenum coord, GLenum pname, GLdouble param); }
 25.3569 +        void OVR::GLEContext::glTexGend_Hook(GLenum coord, GLenum pname, GLdouble param)
 25.3570 +        {
 25.3571 +            glTexGend(coord, pname, param);
 25.3572 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3573 +        }
 25.3574 +
 25.3575 +        #undef glTexGendv
 25.3576 +        extern "C" { GLAPI void GLAPIENTRY glTexGendv(GLenum coord, GLenum pname, const GLdouble *params); }
 25.3577 +        void OVR::GLEContext::glTexGendv_Hook(GLenum coord, GLenum pname, const GLdouble *params)
 25.3578 +        {
 25.3579 +            glTexGendv(coord, pname, params);
 25.3580 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3581 +        }
 25.3582 +
 25.3583 +        #undef glTexGenf
 25.3584 +        extern "C" { GLAPI void GLAPIENTRY glTexGenf(GLenum coord, GLenum pname, GLfloat param); }
 25.3585 +        void OVR::GLEContext::glTexGenf_Hook(GLenum coord, GLenum pname, GLfloat param)
 25.3586 +        {
 25.3587 +            glTexGenf(coord, pname, param);
 25.3588 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3589 +        }
 25.3590 +
 25.3591 +        #undef glTexGenfv
 25.3592 +        extern "C" { GLAPI void GLAPIENTRY glTexGenfv(GLenum coord, GLenum pname, const GLfloat *params); }
 25.3593 +        void OVR::GLEContext::glTexGenfv_Hook(GLenum coord, GLenum pname, const GLfloat *params)
 25.3594 +        {
 25.3595 +            glTexGenfv(coord, pname, params);
 25.3596 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3597 +        }
 25.3598 +
 25.3599 +        #undef glTexGeni
 25.3600 +        extern "C" { GLAPI void GLAPIENTRY glTexGeni(GLenum coord, GLenum pname, GLint param); }
 25.3601 +        void OVR::GLEContext::glTexGeni_Hook(GLenum coord, GLenum pname, GLint param)
 25.3602 +        {
 25.3603 +            glTexGeni(coord, pname, param);
 25.3604 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3605 +        }
 25.3606 +
 25.3607 +        #undef glTexGeniv
 25.3608 +        extern "C" { GLAPI void GLAPIENTRY glTexGeniv(GLenum coord, GLenum pname, const GLint *params); }
 25.3609 +        void OVR::GLEContext::glTexGeniv_Hook(GLenum coord, GLenum pname, const GLint *params)
 25.3610 +        {
 25.3611 +            glTexGeniv(coord, pname, params);
 25.3612 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3613 +        }
 25.3614 +
 25.3615 +        #undef glTexImage1D
 25.3616 +        extern "C" { GLAPI void GLAPIENTRY glTexImage1D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const void *pixels); }
 25.3617 +        void OVR::GLEContext::glTexImage1D_Hook(GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const void *pixels)
 25.3618 +        {
 25.3619 +            glTexImage1D(target, level, internalformat, width, border, format, type, pixels);
 25.3620 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3621 +        }
 25.3622 +
 25.3623 +        #undef glTexImage2D
 25.3624 +        extern "C" { GLAPI void GLAPIENTRY glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels); }
 25.3625 +        void OVR::GLEContext::glTexImage2D_Hook(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels)
 25.3626 +        {
 25.3627 +            glTexImage2D(target, level, internalformat, width, height, border, format, type, pixels);
 25.3628 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3629 +        }
 25.3630 +
 25.3631 +        #undef glTexParameterf
 25.3632 +        extern "C" { GLAPI void GLAPIENTRY glTexParameterf(GLenum target, GLenum pname, GLfloat param); }
 25.3633 +        void OVR::GLEContext::glTexParameterf_Hook(GLenum target, GLenum pname, GLfloat param)
 25.3634 +        {
 25.3635 +            glTexParameterf(target, pname, param);
 25.3636 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3637 +        }
 25.3638 +
 25.3639 +        #undef glTexParameterfv
 25.3640 +        extern "C" { GLAPI void GLAPIENTRY glTexParameterfv(GLenum target, GLenum pname, const GLfloat *params); }
 25.3641 +        void OVR::GLEContext::glTexParameterfv_Hook(GLenum target, GLenum pname, const GLfloat *params)
 25.3642 +        {
 25.3643 +            glTexParameterfv(target, pname, params);
 25.3644 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3645 +        }
 25.3646 +
 25.3647 +        #undef glTexParameteri
 25.3648 +        extern "C" { GLAPI void GLAPIENTRY glTexParameteri(GLenum target, GLenum pname, GLint param); }
 25.3649 +        void OVR::GLEContext::glTexParameteri_Hook(GLenum target, GLenum pname, GLint param)
 25.3650 +        {
 25.3651 +            glTexParameteri(target, pname, param);
 25.3652 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3653 +        }
 25.3654 +
 25.3655 +        #undef glTexParameteriv
 25.3656 +        extern "C" { GLAPI void GLAPIENTRY glTexParameteriv(GLenum target, GLenum pname, const GLint *params); }
 25.3657 +        void OVR::GLEContext::glTexParameteriv_Hook(GLenum target, GLenum pname, const GLint *params)
 25.3658 +        {
 25.3659 +            glTexParameteriv(target, pname, params);
 25.3660 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3661 +        }
 25.3662 +
 25.3663 +        #undef glTexSubImage1D
 25.3664 +        extern "C" { GLAPI void GLAPIENTRY glTexSubImage1D(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void *pixels); }
 25.3665 +        void OVR::GLEContext::glTexSubImage1D_Hook(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void *pixels)
 25.3666 +        {
 25.3667 +            glTexSubImage1D(target, level, xoffset, width, format, type, pixels);
 25.3668 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3669 +        }
 25.3670 +
 25.3671 +        #undef glTexSubImage2D
 25.3672 +        extern "C" { GLAPI void GLAPIENTRY glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels); }
 25.3673 +        void OVR::GLEContext::glTexSubImage2D_Hook(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels)
 25.3674 +        {
 25.3675 +            glTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels);
 25.3676 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3677 +        }
 25.3678 +
 25.3679 +        #undef glTranslated
 25.3680 +        extern "C" { GLAPI void GLAPIENTRY glTranslated(GLdouble x, GLdouble y, GLdouble z); }
 25.3681 +        void OVR::GLEContext::glTranslated_Hook(GLdouble x, GLdouble y, GLdouble z)
 25.3682 +        {
 25.3683 +            glTranslated(x, y, z);
 25.3684 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3685 +        }
 25.3686 +
 25.3687 +        #undef glTranslatef
 25.3688 +        extern "C" { GLAPI void GLAPIENTRY glTranslatef(GLfloat x, GLfloat y, GLfloat z); }
 25.3689 +        void OVR::GLEContext::glTranslatef_Hook(GLfloat x, GLfloat y, GLfloat z)
 25.3690 +        {
 25.3691 +            glTranslatef(x, y, z);
 25.3692 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3693 +        }
 25.3694 +
 25.3695 +        #undef glVertex2d
 25.3696 +        extern "C" { GLAPI void GLAPIENTRY glVertex2d(GLdouble x, GLdouble y); }
 25.3697 +        void OVR::GLEContext::glVertex2d_Hook(GLdouble x, GLdouble y)
 25.3698 +        {
 25.3699 +            glVertex2d(x, y);
 25.3700 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3701 +        }
 25.3702 +
 25.3703 +        #undef glVertex2dv
 25.3704 +        extern "C" { GLAPI void GLAPIENTRY glVertex2dv(const GLdouble *v); }
 25.3705 +        void OVR::GLEContext::glVertex2dv_Hook(const GLdouble *v)
 25.3706 +        {
 25.3707 +            glVertex2dv(v);
 25.3708 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3709 +        }
 25.3710 +
 25.3711 +        #undef glVertex2f
 25.3712 +        extern "C" { GLAPI void GLAPIENTRY glVertex2f(GLfloat x, GLfloat y); }
 25.3713 +        void OVR::GLEContext::glVertex2f_Hook(GLfloat x, GLfloat y)
 25.3714 +        {
 25.3715 +            glVertex2f(x, y);
 25.3716 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3717 +        }
 25.3718 +
 25.3719 +        #undef glVertex2fv
 25.3720 +        extern "C" { GLAPI void GLAPIENTRY glVertex2fv(const GLfloat *v); }
 25.3721 +        void OVR::GLEContext::glVertex2fv_Hook(const GLfloat *v)
 25.3722 +        {
 25.3723 +            glVertex2fv(v);
 25.3724 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3725 +        }
 25.3726 +
 25.3727 +        #undef glVertex2i
 25.3728 +        extern "C" { GLAPI void GLAPIENTRY glVertex2i(GLint x, GLint y); }
 25.3729 +        void OVR::GLEContext::glVertex2i_Hook(GLint x, GLint y)
 25.3730 +        {
 25.3731 +            glVertex2i(x, y);
 25.3732 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3733 +        }
 25.3734 +
 25.3735 +        #undef glVertex2iv
 25.3736 +        extern "C" { GLAPI void GLAPIENTRY glVertex2iv(const GLint *v); }
 25.3737 +        void OVR::GLEContext::glVertex2iv_Hook(const GLint *v)
 25.3738 +        {
 25.3739 +            glVertex2iv(v);
 25.3740 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3741 +        }
 25.3742 +
 25.3743 +        #undef glVertex2s
 25.3744 +        extern "C" { GLAPI void GLAPIENTRY glVertex2s(GLshort x, GLshort y); }
 25.3745 +        void OVR::GLEContext::glVertex2s_Hook(GLshort x, GLshort y)
 25.3746 +        {
 25.3747 +            glVertex2s(x, y);
 25.3748 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3749 +        }
 25.3750 +
 25.3751 +        #undef glVertex2sv
 25.3752 +        extern "C" { GLAPI void GLAPIENTRY glVertex2sv(const GLshort *v); }
 25.3753 +        void OVR::GLEContext::glVertex2sv_Hook(const GLshort *v)
 25.3754 +        {
 25.3755 +            glVertex2sv(v);
 25.3756 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3757 +        }
 25.3758 +
 25.3759 +        #undef glVertex3d
 25.3760 +        extern "C" { GLAPI void GLAPIENTRY glVertex3d(GLdouble x, GLdouble y, GLdouble z); }
 25.3761 +        void OVR::GLEContext::glVertex3d_Hook(GLdouble x, GLdouble y, GLdouble z)
 25.3762 +        {
 25.3763 +            glVertex3d(x, y, z);
 25.3764 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3765 +        }
 25.3766 +
 25.3767 +        #undef glVertex3dv
 25.3768 +        extern "C" { GLAPI void GLAPIENTRY glVertex3dv(const GLdouble *v); }
 25.3769 +        void OVR::GLEContext::glVertex3dv_Hook(const GLdouble *v)
 25.3770 +        {
 25.3771 +            glVertex3dv(v);
 25.3772 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3773 +        }
 25.3774 +
 25.3775 +        #undef glVertex3f
 25.3776 +        extern "C" { GLAPI void GLAPIENTRY glVertex3f(GLfloat x, GLfloat y, GLfloat z); }
 25.3777 +        void OVR::GLEContext::glVertex3f_Hook(GLfloat x, GLfloat y, GLfloat z)
 25.3778 +        {
 25.3779 +            glVertex3f(x, y, z);
 25.3780 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3781 +        }
 25.3782 +
 25.3783 +        #undef glVertex3fv
 25.3784 +        extern "C" { GLAPI void GLAPIENTRY glVertex3fv(const GLfloat *v); }
 25.3785 +        void OVR::GLEContext::glVertex3fv_Hook(const GLfloat *v)
 25.3786 +        {
 25.3787 +            glVertex3fv(v);
 25.3788 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3789 +        }
 25.3790 +
 25.3791 +        #undef glVertex3i
 25.3792 +        extern "C" { GLAPI void GLAPIENTRY glVertex3i(GLint x, GLint y, GLint z); }
 25.3793 +        void OVR::GLEContext::glVertex3i_Hook(GLint x, GLint y, GLint z)
 25.3794 +        {
 25.3795 +            glVertex3i(x, y, z);
 25.3796 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3797 +        }
 25.3798 +
 25.3799 +        #undef glVertex3iv
 25.3800 +        extern "C" { GLAPI void GLAPIENTRY glVertex3iv(const GLint *v); }
 25.3801 +        void OVR::GLEContext::glVertex3iv_Hook(const GLint *v)
 25.3802 +        {
 25.3803 +            glVertex3iv(v);
 25.3804 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3805 +        }
 25.3806 +
 25.3807 +        #undef glVertex3s
 25.3808 +        extern "C" { GLAPI void GLAPIENTRY glVertex3s(GLshort x, GLshort y, GLshort z); }
 25.3809 +        void OVR::GLEContext::glVertex3s_Hook(GLshort x, GLshort y, GLshort z)
 25.3810 +        {
 25.3811 +            glVertex3s(x, y, z);
 25.3812 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3813 +        }
 25.3814 +
 25.3815 +        #undef glVertex3sv
 25.3816 +        extern "C" { GLAPI void GLAPIENTRY glVertex3sv(const GLshort *v); }
 25.3817 +        void OVR::GLEContext::glVertex3sv_Hook(const GLshort *v)
 25.3818 +        {
 25.3819 +            glVertex3sv(v);
 25.3820 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3821 +        }
 25.3822 +
 25.3823 +        #undef glVertex4d
 25.3824 +        extern "C" { GLAPI void GLAPIENTRY glVertex4d(GLdouble x, GLdouble y, GLdouble z, GLdouble w); }
 25.3825 +        void OVR::GLEContext::glVertex4d_Hook(GLdouble x, GLdouble y, GLdouble z, GLdouble w)
 25.3826 +        {
 25.3827 +            glVertex4d(x, y, z, w);
 25.3828 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3829 +        }
 25.3830 +
 25.3831 +        #undef glVertex4dv
 25.3832 +        extern "C" { GLAPI void GLAPIENTRY glVertex4dv(const GLdouble *v); }
 25.3833 +        void OVR::GLEContext::glVertex4dv_Hook(const GLdouble *v)
 25.3834 +        {
 25.3835 +            glVertex4dv(v);
 25.3836 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3837 +        }
 25.3838 +
 25.3839 +        #undef glVertex4f
 25.3840 +        extern "C" { GLAPI void GLAPIENTRY glVertex4f(GLfloat x, GLfloat y, GLfloat z, GLfloat w); }
 25.3841 +        void OVR::GLEContext::glVertex4f_Hook(GLfloat x, GLfloat y, GLfloat z, GLfloat w)
 25.3842 +        {
 25.3843 +            glVertex4f(x, y, z, w);
 25.3844 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3845 +        }
 25.3846 +
 25.3847 +        #undef glVertex4fv
 25.3848 +        extern "C" { GLAPI void GLAPIENTRY glVertex4fv(const GLfloat *v); }
 25.3849 +        void OVR::GLEContext::glVertex4fv_Hook(const GLfloat *v)
 25.3850 +        {
 25.3851 +            glVertex4fv(v);
 25.3852 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3853 +        }
 25.3854 +
 25.3855 +        #undef glVertex4i
 25.3856 +        extern "C" { GLAPI void GLAPIENTRY glVertex4i(GLint x, GLint y, GLint z, GLint w); }
 25.3857 +        void OVR::GLEContext::glVertex4i_Hook(GLint x, GLint y, GLint z, GLint w)
 25.3858 +        {
 25.3859 +            glVertex4i(x, y, z, w);
 25.3860 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3861 +        }
 25.3862 +
 25.3863 +        #undef glVertex4iv
 25.3864 +        extern "C" { GLAPI void GLAPIENTRY glVertex4iv(const GLint *v); }
 25.3865 +        void OVR::GLEContext::glVertex4iv_Hook(const GLint *v)
 25.3866 +        {
 25.3867 +            glVertex4iv(v);
 25.3868 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3869 +        }
 25.3870 +
 25.3871 +        #undef glVertex4s
 25.3872 +        extern "C" { GLAPI void GLAPIENTRY glVertex4s(GLshort x, GLshort y, GLshort z, GLshort w); }
 25.3873 +        void OVR::GLEContext::glVertex4s_Hook(GLshort x, GLshort y, GLshort z, GLshort w)
 25.3874 +        {
 25.3875 +            glVertex4s(x, y, z, w);
 25.3876 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3877 +        }
 25.3878 +
 25.3879 +        #undef glVertex4sv
 25.3880 +        extern "C" { GLAPI void GLAPIENTRY glVertex4sv(const GLshort *v); }
 25.3881 +        void OVR::GLEContext::glVertex4sv_Hook(const GLshort *v)
 25.3882 +        {
 25.3883 +            glVertex4sv(v);
 25.3884 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3885 +        }
 25.3886 +
 25.3887 +        #undef glVertexPointer
 25.3888 +        extern "C" { GLAPI void GLAPIENTRY glVertexPointer(GLint size, GLenum type, GLsizei stride, const void *pointer); }
 25.3889 +        void OVR::GLEContext::glVertexPointer_Hook(GLint size, GLenum type, GLsizei stride, const void *pointer)
 25.3890 +        {
 25.3891 +            glVertexPointer(size, type, stride, pointer);
 25.3892 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3893 +        }
 25.3894 +
 25.3895 +        #undef glViewport
 25.3896 +        extern "C" { GLAPI void GLAPIENTRY glViewport(GLint x, GLint y, GLsizei width, GLsizei height); }
 25.3897 +        void OVR::GLEContext::glViewport_Hook(GLint x, GLint y, GLsizei width, GLsizei height)
 25.3898 +        {
 25.3899 +            glViewport(x, y, width, height);
 25.3900 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3901 +        }
 25.3902 +
 25.3903 +
 25.3904 +
 25.3905 +        // Pointer-based functions
 25.3906 +        void OVR::GLEContext::glBlendColor_Hook(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
 25.3907 +        {
 25.3908 +            if(glBlendColor_Impl)
 25.3909 +                glBlendColor_Impl(red, green, blue, alpha);
 25.3910 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3911 +        }
 25.3912 +
 25.3913 +        void OVR::GLEContext::glBlendEquation_Hook(GLenum mode)
 25.3914 +        {
 25.3915 +            if(glBlendEquation_Impl)
 25.3916 +                glBlendEquation_Impl(mode);
 25.3917 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3918 +        }
 25.3919 +
 25.3920 +        void OVR::GLEContext::glDrawRangeElements_Hook(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices)
 25.3921 +        {
 25.3922 +            if(glDrawRangeElements_Impl)
 25.3923 +                glDrawRangeElements_Impl(mode, start, end, count, type, indices);
 25.3924 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3925 +        }
 25.3926 +
 25.3927 +        void OVR::GLEContext::glTexImage3D_Hook(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels)
 25.3928 +        {
 25.3929 +            if(glTexImage3D_Impl)
 25.3930 +                glTexImage3D_Impl(target, level, internalformat, width, height, depth, border, format, type, pixels);
 25.3931 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3932 +        }
 25.3933 +
 25.3934 +        void OVR::GLEContext::glTexSubImage3D_Hook(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels)
 25.3935 +        {
 25.3936 +            if(glTexSubImage3D_Impl)
 25.3937 +                glTexSubImage3D_Impl(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels);
 25.3938 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3939 +        }
 25.3940 +
 25.3941 +
 25.3942 +        void OVR::GLEContext::glCopyTexSubImage3D_Hook(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height)
 25.3943 +        {
 25.3944 +            if(glCopyTexSubImage3D_Impl)
 25.3945 +                glCopyTexSubImage3D_Impl(target, level, xoffset, yoffset, zoffset, x, y, width, height);
 25.3946 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3947 +        }
 25.3948 +
 25.3949 +        // GL_VERSION_1_2 deprecated functions
 25.3950 +        /* Not currently supported
 25.3951 +        void OVR::GLEContext::glColorTable_Hook(GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *table)
 25.3952 +        {
 25.3953 +            if(glColorTable_Impl)
 25.3954 +                glColorTable_Impl(target, internalformat, width, format, type, table);
 25.3955 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3956 +        }
 25.3957 +
 25.3958 +        void OVR::GLEContext::glColorTableParameterfv_Hook(GLenum target, GLenum pname, const GLfloat *params)
 25.3959 +        {
 25.3960 +            if(glColorTableParameterfv_Impl)
 25.3961 +                glColorTableParameterfv_Impl(target, pname, params);
 25.3962 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3963 +        }
 25.3964 +
 25.3965 +        void OVR::GLEContext::glColorTableParameteriv_Hook(GLenum target, GLenum pname, const GLint *params)
 25.3966 +        {
 25.3967 +            if(glColorTableParameteriv_Impl)
 25.3968 +                glColorTableParameteriv_Impl(target, pname, params);
 25.3969 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3970 +        }
 25.3971 +
 25.3972 +        void OVR::GLEContext::glCopyColorTable_Hook(GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width)
 25.3973 +        {
 25.3974 +            if(glCopyColorTable_Impl)
 25.3975 +                glCopyColorTable_Impl(target, internalformat, x, y, width);
 25.3976 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3977 +        }
 25.3978 +
 25.3979 +        void OVR::GLEContext::glGetColorTable_Hook(GLenum target, GLenum format, GLenum type, GLvoid *table)
 25.3980 +        {
 25.3981 +            if(glGetColorTable_Impl)
 25.3982 +                glGetColorTable_Impl(target, format, type, table);
 25.3983 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3984 +        }
 25.3985 +
 25.3986 +        void OVR::GLEContext::glGetColorTableParameterfv_Hook(GLenum target, GLenum pname, GLfloat *params)
 25.3987 +        {
 25.3988 +            if(glGetColorTableParameterfv_Impl)
 25.3989 +                glGetColorTableParameterfv_Impl(target, pname, params);
 25.3990 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3991 +        }
 25.3992 +
 25.3993 +        void OVR::GLEContext::glGetColorTableParameteriv_Hook(GLenum target, GLenum pname, GLint *params)
 25.3994 +        {
 25.3995 +            if(glGetColorTableParameteriv_Impl)
 25.3996 +                glGetColorTableParameteriv_Impl(target, pname, params);
 25.3997 +            PostHook(GLE_CURRENT_FUNCTION);
 25.3998 +        }
 25.3999 +
 25.4000 +        void OVR::GLEContext::glColorSubTable_Hook(GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid *data)
 25.4001 +        {
 25.4002 +            if(glColorSubTable_Impl)
 25.4003 +                glColorSubTable_Impl(target, start, count, format, type, data);
 25.4004 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4005 +        }
 25.4006 +
 25.4007 +        void OVR::GLEContext::glCopyColorSubTable_Hook(GLenum target, GLsizei start, GLint x, GLint y, GLsizei width)
 25.4008 +        {
 25.4009 +            if(glCopyColorSubTable_Impl)
 25.4010 +                glCopyColorSubTable_Impl(target, start, x, y, width);
 25.4011 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4012 +        }
 25.4013 +
 25.4014 +        void OVR::GLEContext::glConvolutionFilter1D_Hook(GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *image)
 25.4015 +        {
 25.4016 +            if(glConvolutionFilter1D_Impl)
 25.4017 +                glConvolutionFilter1D_Impl(target, internalformat, width, format, type, image);
 25.4018 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4019 +        }
 25.4020 +
 25.4021 +        void OVR::GLEContext::glConvolutionFilter2D_Hook(GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *image)
 25.4022 +        {
 25.4023 +            if(glConvolutionFilter2D_Impl)
 25.4024 +                glConvolutionFilter2D_Impl(target, internalformat, width, height, format, type, image);
 25.4025 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4026 +        }
 25.4027 +
 25.4028 +        void OVR::GLEContext::glConvolutionParameterf_Hook(GLenum target, GLenum pname, GLfloat params)
 25.4029 +        {
 25.4030 +            if(glConvolutionParameterf_Impl)
 25.4031 +                glConvolutionParameterf_Impl(target, pname, params);
 25.4032 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4033 +        }
 25.4034 +
 25.4035 +        void OVR::GLEContext::glConvolutionParameterfv_Hook(GLenum target, GLenum pname, const GLfloat *params)
 25.4036 +        {
 25.4037 +            if(glConvolutionParameterfv_Impl)
 25.4038 +                glConvolutionParameterfv_Impl(target, pname, params);
 25.4039 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4040 +        }
 25.4041 +
 25.4042 +        void OVR::GLEContext::glConvolutionParameteri_Hook(GLenum target, GLenum pname, GLint params)
 25.4043 +        {
 25.4044 +            if(glConvolutionParameteri_Impl)
 25.4045 +                glConvolutionParameteri_Impl(target, pname, params);
 25.4046 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4047 +        }
 25.4048 +
 25.4049 +        void OVR::GLEContext::glConvolutionParameteriv_Hook(GLenum target, GLenum pname, const GLint *params)
 25.4050 +        {
 25.4051 +            if(glConvolutionParameteriv_Impl)
 25.4052 +                glConvolutionParameteriv_Impl(target, pname, params);
 25.4053 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4054 +        }
 25.4055 +
 25.4056 +        void OVR::GLEContext::glCopyConvolutionFilter1D_Hook(GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width)
 25.4057 +        {
 25.4058 +            if(glCopyConvolutionFilter1D_Impl)
 25.4059 +                glCopyConvolutionFilter1D_Impl(target, internalformat, x, y, width);
 25.4060 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4061 +        }
 25.4062 +
 25.4063 +        void OVR::GLEContext::glCopyConvolutionFilter2D_Hook(GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height)
 25.4064 +        {
 25.4065 +            if(glCopyConvolutionFilter2D_Impl)
 25.4066 +                glCopyConvolutionFilter2D_Impl(target, internalformat, x, y, width, height);
 25.4067 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4068 +        }
 25.4069 +
 25.4070 +        void OVR::GLEContext::glGetConvolutionFilter_Hook(GLenum target, GLenum format, GLenum type, GLvoid *image)
 25.4071 +        {
 25.4072 +            if(glGetConvolutionFilter_Impl)
 25.4073 +                glGetConvolutionFilter_Impl(target, format, type, image);
 25.4074 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4075 +        }
 25.4076 +
 25.4077 +        void OVR::GLEContext::glGetConvolutionParameterfv_Hook(GLenum target, GLenum pname, GLfloat *params)
 25.4078 +        {
 25.4079 +            if(glGetConvolutionParameterfv_Impl)
 25.4080 +                glGetConvolutionParameterfv_Impl(target, pname, params);
 25.4081 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4082 +        }
 25.4083 +
 25.4084 +        void OVR::GLEContext::glGetConvolutionParameteriv_Hook(GLenum target, GLenum pname, GLint *params)
 25.4085 +        {
 25.4086 +            if(glGetConvolutionParameteriv_Impl)
 25.4087 +                glGetConvolutionParameteriv_Impl(target, pname, params);
 25.4088 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4089 +        }
 25.4090 +
 25.4091 +        void OVR::GLEContext::glGetSeparableFilter_Hook(GLenum target, GLenum format, GLenum type, GLvoid *row, GLvoid *column, GLvoid *span)
 25.4092 +        {
 25.4093 +            if(glGetSeparableFilter_Impl)
 25.4094 +                glGetSeparableFilter_Impl(target, format, type, row, column, span);
 25.4095 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4096 +        }
 25.4097 +
 25.4098 +        void OVR::GLEContext::glSeparableFilter2D_Hook(GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *row, const GLvoid *column)
 25.4099 +        {
 25.4100 +            if(glSeparableFilter2D_Impl)
 25.4101 +                glSeparableFilter2D_Impl(target, internalformat, width, height, format, type, row, column);
 25.4102 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4103 +        }
 25.4104 +
 25.4105 +        void OVR::GLEContext::glGetHistogram_Hook(GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values)
 25.4106 +        {
 25.4107 +            if(glGetHistogram_Impl)
 25.4108 +                glGetHistogram_Impl(target, reset, format, type, values);
 25.4109 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4110 +        }
 25.4111 +
 25.4112 +        void OVR::GLEContext::glGetHistogramParameterfv_Hook(GLenum target, GLenum pname, GLfloat *params)
 25.4113 +        {
 25.4114 +            if(glGetHistogramParameterfv_Impl)
 25.4115 +                glGetHistogramParameterfv_Impl(target, pname, params);
 25.4116 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4117 +        }
 25.4118 +
 25.4119 +        void OVR::GLEContext::glGetHistogramParameteriv_Hook(GLenum target, GLenum pname, GLint *params)
 25.4120 +        {
 25.4121 +            if(glGetHistogramParameteriv_Impl)
 25.4122 +                glGetHistogramParameteriv_Impl(target, pname, params);
 25.4123 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4124 +        }
 25.4125 +
 25.4126 +        void OVR::GLEContext::glGetMinmax_Hook(GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values)
 25.4127 +        {
 25.4128 +            if(glGetMinmax_Impl)
 25.4129 +                glGetMinmax_Impl(target, reset, format, type, values);
 25.4130 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4131 +        }
 25.4132 +
 25.4133 +        void OVR::GLEContext::glGetMinmaxParameterfv_Hook(GLenum target, GLenum pname, GLfloat *params)
 25.4134 +        {
 25.4135 +            if(glGetMinmaxParameterfv_Impl)
 25.4136 +                glGetMinmaxParameterfv_Impl(target, pname, params);
 25.4137 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4138 +        }
 25.4139 +
 25.4140 +        void OVR::GLEContext::glGetMinmaxParameteriv_Hook(GLenum target, GLenum pname, GLint *params)
 25.4141 +        {
 25.4142 +            if(glGetMinmaxParameteriv_Impl)
 25.4143 +                glGetMinmaxParameteriv_Impl(target, pname, params);
 25.4144 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4145 +        }
 25.4146 +
 25.4147 +        void OVR::GLEContext::glHistogram_Hook(GLenum target, GLsizei width, GLenum internalformat, GLboolean sink)
 25.4148 +        {
 25.4149 +            if(glHistogram_Impl)
 25.4150 +                glHistogram_Impl(target, width, internalformat, sink);
 25.4151 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4152 +        }
 25.4153 +
 25.4154 +        void OVR::GLEContext::glMinmax_Hook(GLenum target, GLenum internalformat, GLboolean sink)
 25.4155 +        {
 25.4156 +            if(glMinmax_Impl)
 25.4157 +                glMinmax_Impl(target, internalformat, sink);
 25.4158 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4159 +        }
 25.4160 +
 25.4161 +        void OVR::GLEContext::glResetHistogram_Hook(GLenum target)
 25.4162 +        {
 25.4163 +            if(glResetHistogram_Impl)
 25.4164 +                glResetHistogram_Impl(target);
 25.4165 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4166 +        }
 25.4167 +
 25.4168 +        void OVR::GLEContext::glResetMinmax_Hook(GLenum target)
 25.4169 +        {
 25.4170 +            if(glResetMinmax_Impl)
 25.4171 +                glResetMinmax_Impl(target);
 25.4172 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4173 +        }
 25.4174 +        */
 25.4175 +
 25.4176 +        // GL_VERSION_1_3
 25.4177 +        void OVR::GLEContext::glActiveTexture_Hook(GLenum texture)
 25.4178 +        {
 25.4179 +            if(glActiveTexture_Impl)
 25.4180 +                glActiveTexture_Impl(texture);
 25.4181 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4182 +        }
 25.4183 +
 25.4184 +        void OVR::GLEContext::glSampleCoverage_Hook(GLclampf value, GLboolean invert)
 25.4185 +        {
 25.4186 +            if(glSampleCoverage_Impl)
 25.4187 +                glSampleCoverage_Impl(value, invert);
 25.4188 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4189 +        }
 25.4190 +
 25.4191 +        void OVR::GLEContext::glCompressedTexImage3D_Hook(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data)
 25.4192 +        {
 25.4193 +            if(glCompressedTexImage3D_Impl)
 25.4194 +                glCompressedTexImage3D_Impl(target, level, internalformat, width, height, depth, border, imageSize, data);
 25.4195 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4196 +        }
 25.4197 +
 25.4198 +        void OVR::GLEContext::glCompressedTexImage2D_Hook(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data)
 25.4199 +        {
 25.4200 +            if(glCompressedTexImage2D_Impl)
 25.4201 +                glCompressedTexImage2D_Impl(target, level, internalformat, width, height, border, imageSize, data);
 25.4202 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4203 +        }
 25.4204 +
 25.4205 +        void OVR::GLEContext::glCompressedTexImage1D_Hook(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data)
 25.4206 +        {
 25.4207 +            if(glCompressedTexImage1D_Impl)
 25.4208 +                glCompressedTexImage1D_Impl(target, level, internalformat, width, border, imageSize, data);
 25.4209 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4210 +        }
 25.4211 +
 25.4212 +        void OVR::GLEContext::glCompressedTexSubImage3D_Hook(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data)
 25.4213 +        {
 25.4214 +            if(glCompressedTexSubImage3D_Impl)
 25.4215 +                glCompressedTexSubImage3D_Impl(target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data);
 25.4216 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4217 +        }
 25.4218 +
 25.4219 +        void OVR::GLEContext::glCompressedTexSubImage2D_Hook(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data)
 25.4220 +        {
 25.4221 +            if(glCompressedTexSubImage2D_Impl)
 25.4222 +                glCompressedTexSubImage2D_Impl(target, level, xoffset, yoffset, width, height, format, imageSize, data);
 25.4223 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4224 +        }
 25.4225 +
 25.4226 +        void OVR::GLEContext::glCompressedTexSubImage1D_Hook(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data)
 25.4227 +        {
 25.4228 +            if(glCompressedTexSubImage1D_Impl)
 25.4229 +                glCompressedTexSubImage1D_Impl(target, level, xoffset, width, format, imageSize, data);
 25.4230 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4231 +        }
 25.4232 +
 25.4233 +        void OVR::GLEContext::glGetCompressedTexImage_Hook(GLenum target, GLint level, GLvoid *img)
 25.4234 +        {
 25.4235 +            if(glGetCompressedTexImage_Impl)
 25.4236 +                glGetCompressedTexImage_Impl(target, level, img);
 25.4237 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4238 +        }
 25.4239 +
 25.4240 +
 25.4241 +        // GL_VERSION_1_3 deprecated functions
 25.4242 +        void OVR::GLEContext::glClientActiveTexture_Hook(GLenum texture)
 25.4243 +        {
 25.4244 +            if(glClientActiveTexture_Impl)
 25.4245 +                glClientActiveTexture_Impl(texture);
 25.4246 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4247 +        }
 25.4248 +
 25.4249 +        void OVR::GLEContext::glMultiTexCoord1d_Hook(GLenum target, GLdouble s)
 25.4250 +        {
 25.4251 +            if(glMultiTexCoord1d_Impl)
 25.4252 +                glMultiTexCoord1d_Impl(target, s);
 25.4253 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4254 +        }
 25.4255 +
 25.4256 +        void OVR::GLEContext::glMultiTexCoord1dv_Hook(GLenum target, const GLdouble *v)
 25.4257 +        {
 25.4258 +            if(glMultiTexCoord1dv_Impl)
 25.4259 +                glMultiTexCoord1dv_Impl(target, v);
 25.4260 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4261 +        }
 25.4262 +
 25.4263 +        void OVR::GLEContext::glMultiTexCoord1f_Hook(GLenum target, GLfloat s)
 25.4264 +        {
 25.4265 +            if(glMultiTexCoord1f_Impl)
 25.4266 +                glMultiTexCoord1f_Impl(target, s);
 25.4267 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4268 +        }
 25.4269 +
 25.4270 +        void OVR::GLEContext::glMultiTexCoord1fv_Hook(GLenum target, const GLfloat *v)
 25.4271 +        {
 25.4272 +            if(glMultiTexCoord1fv_Impl)
 25.4273 +                glMultiTexCoord1fv_Impl(target, v);
 25.4274 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4275 +        }
 25.4276 +
 25.4277 +        void OVR::GLEContext::glMultiTexCoord1i_Hook(GLenum target, GLint s)
 25.4278 +        {
 25.4279 +            if(glMultiTexCoord1i_Impl)
 25.4280 +                glMultiTexCoord1i_Impl(target, s);
 25.4281 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4282 +        }
 25.4283 +
 25.4284 +        void OVR::GLEContext::glMultiTexCoord1iv_Hook(GLenum target, const GLint *v)
 25.4285 +        {
 25.4286 +            if(glMultiTexCoord1iv_Impl)
 25.4287 +                glMultiTexCoord1iv_Impl(target, v);
 25.4288 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4289 +        }
 25.4290 +
 25.4291 +        void OVR::GLEContext::glMultiTexCoord1s_Hook(GLenum target, GLshort s)
 25.4292 +        {
 25.4293 +            if(glMultiTexCoord1s_Impl)
 25.4294 +                glMultiTexCoord1s_Impl(target, s);
 25.4295 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4296 +        }
 25.4297 +
 25.4298 +        void OVR::GLEContext::glMultiTexCoord1sv_Hook(GLenum target, const GLshort *v)
 25.4299 +        {
 25.4300 +            if(glMultiTexCoord1sv_Impl)
 25.4301 +                glMultiTexCoord1sv_Impl(target, v);
 25.4302 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4303 +        }
 25.4304 +
 25.4305 +        void OVR::GLEContext::glMultiTexCoord2d_Hook(GLenum target, GLdouble s, GLdouble t)
 25.4306 +        {
 25.4307 +            if(glMultiTexCoord2d_Impl)
 25.4308 +                glMultiTexCoord2d_Impl(target, s, t);
 25.4309 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4310 +        }
 25.4311 +
 25.4312 +        void OVR::GLEContext::glMultiTexCoord2dv_Hook(GLenum target, const GLdouble *v)
 25.4313 +        {
 25.4314 +            if(glMultiTexCoord2dv_Impl)
 25.4315 +                glMultiTexCoord2dv_Impl(target, v);
 25.4316 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4317 +        }
 25.4318 +
 25.4319 +        void OVR::GLEContext::glMultiTexCoord2f_Hook(GLenum target, GLfloat s, GLfloat t)
 25.4320 +        {
 25.4321 +            if(glMultiTexCoord2f_Impl)
 25.4322 +                glMultiTexCoord2f_Impl(target, s, t);
 25.4323 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4324 +        }
 25.4325 +
 25.4326 +        void OVR::GLEContext::glMultiTexCoord2fv_Hook(GLenum target, const GLfloat *v)
 25.4327 +        {
 25.4328 +            if(glMultiTexCoord2fv_Impl)
 25.4329 +                glMultiTexCoord2fv_Impl(target, v);
 25.4330 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4331 +        }
 25.4332 +
 25.4333 +        void OVR::GLEContext::glMultiTexCoord2i_Hook(GLenum target, GLint s, GLint t)
 25.4334 +        {
 25.4335 +            if(glMultiTexCoord2i_Impl)
 25.4336 +                glMultiTexCoord2i_Impl(target, s, t);
 25.4337 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4338 +        }
 25.4339 +
 25.4340 +        void OVR::GLEContext::glMultiTexCoord2iv_Hook(GLenum target, const GLint *v)
 25.4341 +        {
 25.4342 +            if(glMultiTexCoord2iv_Impl)
 25.4343 +                glMultiTexCoord2iv_Impl(target, v);
 25.4344 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4345 +        }
 25.4346 +
 25.4347 +        void OVR::GLEContext::glMultiTexCoord2s_Hook(GLenum target, GLshort s, GLshort t)
 25.4348 +        {
 25.4349 +            if(glMultiTexCoord2s_Impl)
 25.4350 +                glMultiTexCoord2s_Impl(target, s, t);
 25.4351 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4352 +        }
 25.4353 +
 25.4354 +        void OVR::GLEContext::glMultiTexCoord2sv_Hook(GLenum target, const GLshort *v)
 25.4355 +        {
 25.4356 +            if(glMultiTexCoord2sv_Impl)
 25.4357 +                glMultiTexCoord2sv_Impl(target, v);
 25.4358 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4359 +        }
 25.4360 +
 25.4361 +        void OVR::GLEContext::glMultiTexCoord3d_Hook(GLenum target, GLdouble s, GLdouble t, GLdouble r)
 25.4362 +        {
 25.4363 +            if(glMultiTexCoord3d_Impl)
 25.4364 +                glMultiTexCoord3d_Impl(target, s, t, r);
 25.4365 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4366 +        }
 25.4367 +
 25.4368 +        void OVR::GLEContext::glMultiTexCoord3dv_Hook(GLenum target, const GLdouble *v)
 25.4369 +        {
 25.4370 +            if(glMultiTexCoord3dv_Impl)
 25.4371 +                glMultiTexCoord3dv_Impl(target, v);
 25.4372 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4373 +        }
 25.4374 +
 25.4375 +        void OVR::GLEContext::glMultiTexCoord3f_Hook(GLenum target, GLfloat s, GLfloat t, GLfloat r)
 25.4376 +        {
 25.4377 +            if(glMultiTexCoord3f_Impl)
 25.4378 +                glMultiTexCoord3f_Impl(target, s, t, r);
 25.4379 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4380 +        }
 25.4381 +
 25.4382 +        void OVR::GLEContext::glMultiTexCoord3fv_Hook(GLenum target, const GLfloat *v)
 25.4383 +        {
 25.4384 +            if(glMultiTexCoord3fv_Impl)
 25.4385 +                glMultiTexCoord3fv_Impl(target, v);
 25.4386 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4387 +        }
 25.4388 +
 25.4389 +        void OVR::GLEContext::glMultiTexCoord3i_Hook(GLenum target, GLint s, GLint t, GLint r)
 25.4390 +        {
 25.4391 +            if(glMultiTexCoord3i_Impl)
 25.4392 +                glMultiTexCoord3i_Impl(target, s, t, r);
 25.4393 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4394 +        }
 25.4395 +
 25.4396 +        void OVR::GLEContext::glMultiTexCoord3iv_Hook(GLenum target, const GLint *v)
 25.4397 +        {
 25.4398 +            if(glMultiTexCoord3iv_Impl)
 25.4399 +                glMultiTexCoord3iv_Impl(target, v);
 25.4400 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4401 +        }
 25.4402 +
 25.4403 +        void OVR::GLEContext::glMultiTexCoord3s_Hook(GLenum target, GLshort s, GLshort t, GLshort r)
 25.4404 +        {
 25.4405 +            if(glMultiTexCoord3s_Impl)
 25.4406 +                glMultiTexCoord3s_Impl(target, s, t, r);
 25.4407 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4408 +        }
 25.4409 +
 25.4410 +        void OVR::GLEContext::glMultiTexCoord3sv_Hook(GLenum target, const GLshort *v)
 25.4411 +        {
 25.4412 +            if(glMultiTexCoord3sv_Impl)
 25.4413 +                glMultiTexCoord3sv_Impl(target, v);
 25.4414 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4415 +        }
 25.4416 +
 25.4417 +        void OVR::GLEContext::glMultiTexCoord4d_Hook(GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q)
 25.4418 +        {
 25.4419 +            if(glMultiTexCoord4d_Impl)
 25.4420 +                glMultiTexCoord4d_Impl(target, s, t, r, q);
 25.4421 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4422 +        }
 25.4423 +
 25.4424 +        void OVR::GLEContext::glMultiTexCoord4dv_Hook(GLenum target, const GLdouble *v)
 25.4425 +        {
 25.4426 +            if(glMultiTexCoord4dv_Impl)
 25.4427 +                glMultiTexCoord4dv_Impl(target, v);
 25.4428 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4429 +        }
 25.4430 +
 25.4431 +        void OVR::GLEContext::glMultiTexCoord4f_Hook(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q)
 25.4432 +        {
 25.4433 +            if(glMultiTexCoord4f_Impl)
 25.4434 +                glMultiTexCoord4f_Impl(target, s, t, r, q);
 25.4435 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4436 +        }
 25.4437 +
 25.4438 +        void OVR::GLEContext::glMultiTexCoord4fv_Hook(GLenum target, const GLfloat *v)
 25.4439 +        {
 25.4440 +            if(glMultiTexCoord4fv_Impl)
 25.4441 +                glMultiTexCoord4fv_Impl(target, v);
 25.4442 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4443 +        }
 25.4444 +
 25.4445 +        void OVR::GLEContext::glMultiTexCoord4i_Hook(GLenum target, GLint s, GLint t, GLint r, GLint q)
 25.4446 +        {
 25.4447 +            if(glMultiTexCoord4i_Impl)
 25.4448 +                glMultiTexCoord4i_Impl(target, s, t, r, q);
 25.4449 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4450 +        }
 25.4451 +
 25.4452 +        void OVR::GLEContext::glMultiTexCoord4iv_Hook(GLenum target, const GLint *v)
 25.4453 +        {
 25.4454 +            if(glMultiTexCoord4iv_Impl)
 25.4455 +                glMultiTexCoord4iv_Impl(target, v);
 25.4456 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4457 +        }
 25.4458 +
 25.4459 +        void OVR::GLEContext::glMultiTexCoord4s_Hook(GLenum target, GLshort s, GLshort t, GLshort r, GLshort q)
 25.4460 +        {
 25.4461 +            if(glMultiTexCoord4s_Impl)
 25.4462 +                glMultiTexCoord4s_Impl(target, s, t, r, q);
 25.4463 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4464 +        }
 25.4465 +
 25.4466 +        void OVR::GLEContext::glMultiTexCoord4sv_Hook(GLenum target, const GLshort *v)
 25.4467 +        {
 25.4468 +            if(glMultiTexCoord4sv_Impl)
 25.4469 +                glMultiTexCoord4sv_Impl(target, v);
 25.4470 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4471 +        }
 25.4472 +
 25.4473 +        void OVR::GLEContext::glLoadTransposeMatrixf_Hook(const GLfloat *m)
 25.4474 +        {
 25.4475 +            if(glLoadTransposeMatrixf_Impl)
 25.4476 +                glLoadTransposeMatrixf_Impl(m);
 25.4477 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4478 +        }
 25.4479 +
 25.4480 +        void OVR::GLEContext::glLoadTransposeMatrixd_Hook(const GLdouble *m)
 25.4481 +        {
 25.4482 +            if(glLoadTransposeMatrixd_Impl)
 25.4483 +                glLoadTransposeMatrixd_Impl(m);
 25.4484 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4485 +        }
 25.4486 +
 25.4487 +        void OVR::GLEContext::glMultTransposeMatrixf_Hook(const GLfloat *m)
 25.4488 +        {
 25.4489 +            if(glMultTransposeMatrixf_Impl)
 25.4490 +                glMultTransposeMatrixf_Impl(m);
 25.4491 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4492 +        }
 25.4493 +
 25.4494 +        void OVR::GLEContext::glMultTransposeMatrixd_Hook(const GLdouble *m)
 25.4495 +        {
 25.4496 +            if(glMultTransposeMatrixd_Impl)
 25.4497 +                glMultTransposeMatrixd_Impl(m);
 25.4498 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4499 +        }
 25.4500 +
 25.4501 +
 25.4502 +        // GL_VERSION_1_4
 25.4503 +        void OVR::GLEContext::glBlendFuncSeparate_Hook(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha)
 25.4504 +        {
 25.4505 +            if(glBlendFuncSeparate_Impl)
 25.4506 +                glBlendFuncSeparate_Impl(sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha);
 25.4507 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4508 +        }
 25.4509 +
 25.4510 +        void OVR::GLEContext::glMultiDrawArrays_Hook(GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount)
 25.4511 +        {
 25.4512 +            if(glMultiDrawArrays_Impl)
 25.4513 +                glMultiDrawArrays_Impl(mode, first, count, primcount);
 25.4514 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4515 +        }
 25.4516 +
 25.4517 +        void OVR::GLEContext::glMultiDrawElements_Hook(GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount)
 25.4518 +        {
 25.4519 +            if(glMultiDrawElements_Impl)
 25.4520 +                glMultiDrawElements_Impl(mode, count, type, indices, primcount);
 25.4521 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4522 +        }
 25.4523 +
 25.4524 +        void OVR::GLEContext::glPointParameterf_Hook(GLenum pname, GLfloat param)
 25.4525 +        {
 25.4526 +            if(glPointParameterf_Impl)
 25.4527 +                glPointParameterf_Impl(pname, param);
 25.4528 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4529 +        }
 25.4530 +
 25.4531 +        void OVR::GLEContext::glPointParameterfv_Hook(GLenum pname, const GLfloat *params)
 25.4532 +        {
 25.4533 +            if(glPointParameterfv_Impl)
 25.4534 +                glPointParameterfv_Impl(pname, params);
 25.4535 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4536 +        }
 25.4537 +
 25.4538 +        void OVR::GLEContext::glPointParameteri_Hook(GLenum pname, GLint param)
 25.4539 +        {
 25.4540 +            if(glPointParameteri_Impl)
 25.4541 +                glPointParameteri_Impl(pname, param);
 25.4542 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4543 +        }
 25.4544 +
 25.4545 +        void OVR::GLEContext::glPointParameteriv_Hook(GLenum pname, const GLint *params)
 25.4546 +        {
 25.4547 +            if(glPointParameteriv_Impl)
 25.4548 +                glPointParameteriv_Impl(pname, params);
 25.4549 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4550 +        }
 25.4551 +
 25.4552 +
 25.4553 +        // GL_VERSION_1_4 deprecated functions
 25.4554 +        void OVR::GLEContext::glFogCoordf_Hook(GLfloat coord)
 25.4555 +        {
 25.4556 +            if(glFogCoordf_Impl)
 25.4557 +                glFogCoordf_Impl(coord);
 25.4558 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4559 +        }
 25.4560 +
 25.4561 +        void OVR::GLEContext::glFogCoordfv_Hook(const GLfloat *coord)
 25.4562 +        {
 25.4563 +            if(glFogCoordfv_Impl)
 25.4564 +                glFogCoordfv_Impl(coord);
 25.4565 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4566 +        }
 25.4567 +
 25.4568 +        void OVR::GLEContext::glFogCoordd_Hook(GLdouble coord)
 25.4569 +        {
 25.4570 +            if(glFogCoordd_Impl)
 25.4571 +                glFogCoordd_Impl(coord);
 25.4572 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4573 +        }
 25.4574 +
 25.4575 +        void OVR::GLEContext::glFogCoorddv_Hook(const GLdouble *coord)
 25.4576 +        {
 25.4577 +            if(glFogCoorddv_Impl)
 25.4578 +                glFogCoorddv_Impl(coord);
 25.4579 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4580 +        }
 25.4581 +
 25.4582 +        void OVR::GLEContext::glFogCoordPointer_Hook(GLenum type, GLsizei stride, const GLvoid *pointer)
 25.4583 +        {
 25.4584 +            if(glFogCoordPointer_Impl)
 25.4585 +                glFogCoordPointer_Impl(type, stride, pointer);
 25.4586 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4587 +        }
 25.4588 +
 25.4589 +        void OVR::GLEContext::glSecondaryColor3b_Hook(GLbyte red, GLbyte green, GLbyte blue)
 25.4590 +        {
 25.4591 +            if(glSecondaryColor3b_Impl)
 25.4592 +                glSecondaryColor3b_Impl(red, green, blue);
 25.4593 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4594 +        }
 25.4595 +
 25.4596 +        void OVR::GLEContext::glSecondaryColor3bv_Hook(const GLbyte *v)
 25.4597 +        {
 25.4598 +            if(glSecondaryColor3bv_Impl)
 25.4599 +                glSecondaryColor3bv_Impl(v);
 25.4600 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4601 +        }
 25.4602 +
 25.4603 +        void OVR::GLEContext::glSecondaryColor3d_Hook(GLdouble red, GLdouble green, GLdouble blue)
 25.4604 +        {
 25.4605 +            if(glSecondaryColor3d_Impl)
 25.4606 +                glSecondaryColor3d_Impl(red, green, blue);
 25.4607 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4608 +        }
 25.4609 +
 25.4610 +        void OVR::GLEContext::glSecondaryColor3dv_Hook(const GLdouble *v)
 25.4611 +        {
 25.4612 +            if(glSecondaryColor3dv_Impl)
 25.4613 +                glSecondaryColor3dv_Impl(v);
 25.4614 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4615 +        }
 25.4616 +
 25.4617 +        void OVR::GLEContext::glSecondaryColor3f_Hook(GLfloat red, GLfloat green, GLfloat blue)
 25.4618 +        {
 25.4619 +            if(glSecondaryColor3f_Impl)
 25.4620 +                glSecondaryColor3f_Impl(red, green, blue);
 25.4621 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4622 +        }
 25.4623 +
 25.4624 +        void OVR::GLEContext::glSecondaryColor3fv_Hook(const GLfloat *v)
 25.4625 +        {
 25.4626 +            if(glSecondaryColor3fv_Impl)
 25.4627 +                glSecondaryColor3fv_Impl(v);
 25.4628 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4629 +        }
 25.4630 +
 25.4631 +        void OVR::GLEContext::glSecondaryColor3i_Hook(GLint red, GLint green, GLint blue)
 25.4632 +        {
 25.4633 +            if(glSecondaryColor3i_Impl)
 25.4634 +                glSecondaryColor3i_Impl(red, green, blue);
 25.4635 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4636 +        }
 25.4637 +
 25.4638 +        void OVR::GLEContext::glSecondaryColor3iv_Hook(const GLint *v)
 25.4639 +        {
 25.4640 +            if(glSecondaryColor3iv_Impl)
 25.4641 +                glSecondaryColor3iv_Impl(v);
 25.4642 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4643 +        }
 25.4644 +
 25.4645 +        void OVR::GLEContext::glSecondaryColor3s_Hook(GLshort red, GLshort green, GLshort blue)
 25.4646 +        {
 25.4647 +            if(glSecondaryColor3s_Impl)
 25.4648 +                glSecondaryColor3s_Impl(red, green, blue);
 25.4649 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4650 +        }
 25.4651 +
 25.4652 +        void OVR::GLEContext::glSecondaryColor3sv_Hook(const GLshort *v)
 25.4653 +        {
 25.4654 +            if(glSecondaryColor3sv_Impl)
 25.4655 +                glSecondaryColor3sv_Impl(v);
 25.4656 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4657 +        }
 25.4658 +
 25.4659 +        void OVR::GLEContext::glSecondaryColor3ub_Hook(GLubyte red, GLubyte green, GLubyte blue)
 25.4660 +        {
 25.4661 +            if(glSecondaryColor3ub_Impl)
 25.4662 +                glSecondaryColor3ub_Impl(red, green, blue);
 25.4663 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4664 +        }
 25.4665 +
 25.4666 +        void OVR::GLEContext::glSecondaryColor3ubv_Hook(const GLubyte *v)
 25.4667 +        {
 25.4668 +            if(glSecondaryColor3ubv_Impl)
 25.4669 +                glSecondaryColor3ubv_Impl(v);
 25.4670 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4671 +        }
 25.4672 +
 25.4673 +        void OVR::GLEContext::glSecondaryColor3ui_Hook(GLuint red, GLuint green, GLuint blue)
 25.4674 +        {
 25.4675 +            if(glSecondaryColor3ui_Impl)
 25.4676 +                glSecondaryColor3ui_Impl(red, green, blue);
 25.4677 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4678 +        }
 25.4679 +
 25.4680 +        void OVR::GLEContext::glSecondaryColor3uiv_Hook(const GLuint *v)
 25.4681 +        {
 25.4682 +            if(glSecondaryColor3uiv_Impl)
 25.4683 +                glSecondaryColor3uiv_Impl(v);
 25.4684 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4685 +        }
 25.4686 +
 25.4687 +        void OVR::GLEContext::glSecondaryColor3us_Hook(GLushort red, GLushort green, GLushort blue)
 25.4688 +        {
 25.4689 +            if(glSecondaryColor3us_Impl)
 25.4690 +                glSecondaryColor3us_Impl(red, green, blue);
 25.4691 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4692 +        }
 25.4693 +
 25.4694 +        void OVR::GLEContext::glSecondaryColor3usv_Hook(const GLushort *v)
 25.4695 +        {
 25.4696 +            if(glSecondaryColor3usv_Impl)
 25.4697 +                glSecondaryColor3usv_Impl(v);
 25.4698 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4699 +        }
 25.4700 +
 25.4701 +        void OVR::GLEContext::glSecondaryColorPointer_Hook(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
 25.4702 +        {
 25.4703 +            if(glSecondaryColorPointer_Impl)
 25.4704 +                glSecondaryColorPointer_Impl(size, type, stride, pointer);
 25.4705 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4706 +        }
 25.4707 +
 25.4708 +        void OVR::GLEContext::glWindowPos2d_Hook(GLdouble x, GLdouble y)
 25.4709 +        {
 25.4710 +            if(glWindowPos2d_Impl)
 25.4711 +                glWindowPos2d_Impl(x, y);
 25.4712 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4713 +        }
 25.4714 +
 25.4715 +        void OVR::GLEContext::glWindowPos2dv_Hook(const GLdouble *v)
 25.4716 +        {
 25.4717 +            if(glWindowPos2dv_Impl)
 25.4718 +                glWindowPos2dv_Impl(v);
 25.4719 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4720 +        }
 25.4721 +
 25.4722 +        void OVR::GLEContext::glWindowPos2f_Hook(GLfloat x, GLfloat y)
 25.4723 +        {
 25.4724 +            if(glWindowPos2f_Impl)
 25.4725 +                glWindowPos2f_Impl(x, y);
 25.4726 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4727 +        }
 25.4728 +
 25.4729 +        void OVR::GLEContext::glWindowPos2fv_Hook(const GLfloat *v)
 25.4730 +        {
 25.4731 +            if(glWindowPos2fv_Impl)
 25.4732 +                glWindowPos2fv_Impl(v);
 25.4733 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4734 +        }
 25.4735 +
 25.4736 +        void OVR::GLEContext::glWindowPos2i_Hook(GLint x, GLint y)
 25.4737 +        {
 25.4738 +            if(glWindowPos2i_Impl)
 25.4739 +                glWindowPos2i_Impl(x, y);
 25.4740 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4741 +        }
 25.4742 +
 25.4743 +        void OVR::GLEContext::glWindowPos2iv_Hook(const GLint *v)
 25.4744 +        {
 25.4745 +            if(glWindowPos2iv_Impl)
 25.4746 +                glWindowPos2iv_Impl(v);
 25.4747 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4748 +        }
 25.4749 +
 25.4750 +        void OVR::GLEContext::glWindowPos2s_Hook(GLshort x, GLshort y)
 25.4751 +        {
 25.4752 +            if(glWindowPos2s_Impl)
 25.4753 +                glWindowPos2s_Impl(x, y);
 25.4754 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4755 +        }
 25.4756 +
 25.4757 +        void OVR::GLEContext::glWindowPos2sv_Hook(const GLshort *v)
 25.4758 +        {
 25.4759 +            if(glWindowPos2sv_Impl)
 25.4760 +                glWindowPos2sv_Impl(v);
 25.4761 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4762 +        }
 25.4763 +
 25.4764 +        void OVR::GLEContext::glWindowPos3d_Hook(GLdouble x, GLdouble y, GLdouble z)
 25.4765 +        {
 25.4766 +            if(glWindowPos3d_Impl)
 25.4767 +                glWindowPos3d_Impl(x, y, z);
 25.4768 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4769 +        }
 25.4770 +
 25.4771 +        void OVR::GLEContext::glWindowPos3dv_Hook(const GLdouble *v)
 25.4772 +        {
 25.4773 +            if(glWindowPos3dv_Impl)
 25.4774 +                glWindowPos3dv_Impl(v);
 25.4775 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4776 +        }
 25.4777 +
 25.4778 +        void OVR::GLEContext::glWindowPos3f_Hook(GLfloat x, GLfloat y, GLfloat z)
 25.4779 +        {
 25.4780 +            if(glWindowPos3f_Impl)
 25.4781 +                glWindowPos3f_Impl(x, y, z);
 25.4782 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4783 +        }
 25.4784 +
 25.4785 +        void OVR::GLEContext::glWindowPos3fv_Hook(const GLfloat *v)
 25.4786 +        {
 25.4787 +            if(glWindowPos3fv_Impl)
 25.4788 +                glWindowPos3fv_Impl(v);
 25.4789 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4790 +        }
 25.4791 +
 25.4792 +        void OVR::GLEContext::glWindowPos3i_Hook(GLint x, GLint y, GLint z)
 25.4793 +        {
 25.4794 +            if(glWindowPos3i_Impl)
 25.4795 +                glWindowPos3i_Impl(x, y, z);
 25.4796 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4797 +        }
 25.4798 +
 25.4799 +        void OVR::GLEContext::glWindowPos3iv_Hook(const GLint *v)
 25.4800 +        {
 25.4801 +            if(glWindowPos3iv_Impl)
 25.4802 +                glWindowPos3iv_Impl(v);
 25.4803 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4804 +        }
 25.4805 +
 25.4806 +        void OVR::GLEContext::glWindowPos3s_Hook(GLshort x, GLshort y, GLshort z)
 25.4807 +        {
 25.4808 +            if(glWindowPos3s_Impl)
 25.4809 +                glWindowPos3s_Impl(x, y, z);
 25.4810 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4811 +        }
 25.4812 +
 25.4813 +        void OVR::GLEContext::glWindowPos3sv_Hook(const GLshort *v)
 25.4814 +        {
 25.4815 +            if(glWindowPos3sv_Impl)
 25.4816 +                glWindowPos3sv_Impl(v);
 25.4817 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4818 +        }
 25.4819 +
 25.4820 +
 25.4821 +        // GL_VERSION_1_5
 25.4822 +        void OVR::GLEContext::glGenQueries_Hook(GLsizei n, GLuint *ids)
 25.4823 +        {
 25.4824 +            if(glGenQueries_Impl)
 25.4825 +                glGenQueries_Impl(n, ids);
 25.4826 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4827 +        }
 25.4828 +
 25.4829 +        void OVR::GLEContext::glDeleteQueries_Hook(GLsizei n, const GLuint *ids)
 25.4830 +        {
 25.4831 +            if(glDeleteQueries_Impl)
 25.4832 +                glDeleteQueries_Impl(n, ids);
 25.4833 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4834 +        }
 25.4835 +
 25.4836 +        GLboolean OVR::GLEContext::glIsQuery_Hook(GLuint id)
 25.4837 +        {
 25.4838 +            GLboolean b = GL_FALSE;
 25.4839 +            if(glIsQuery_Impl)
 25.4840 +                b = glIsQuery_Impl(id);
 25.4841 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4842 +            return b;
 25.4843 +        }
 25.4844 +
 25.4845 +        void OVR::GLEContext::glBeginQuery_Hook(GLenum target, GLuint id)
 25.4846 +        {
 25.4847 +            if(glBeginQuery_Impl)
 25.4848 +                glBeginQuery_Impl(target, id);
 25.4849 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4850 +        }
 25.4851 +
 25.4852 +        void OVR::GLEContext::glEndQuery_Hook(GLenum target)
 25.4853 +        {
 25.4854 +            if(glEndQuery_Impl)
 25.4855 +                glEndQuery_Impl(target);
 25.4856 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4857 +        }
 25.4858 +
 25.4859 +        void OVR::GLEContext::glGetQueryiv_Hook(GLenum target, GLenum pname, GLint *params)
 25.4860 +        {
 25.4861 +            if(glGetQueryiv_Impl)
 25.4862 +                glGetQueryiv_Impl(target, pname, params);
 25.4863 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4864 +        }
 25.4865 +
 25.4866 +        void OVR::GLEContext::glGetQueryObjectiv_Hook(GLuint id, GLenum pname, GLint *params)
 25.4867 +        {
 25.4868 +            if(glGetQueryObjectiv_Impl)
 25.4869 +                glGetQueryObjectiv_Impl(id, pname, params);
 25.4870 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4871 +        }
 25.4872 +
 25.4873 +        void OVR::GLEContext::glGetQueryObjectuiv_Hook(GLuint id, GLenum pname, GLuint *params)
 25.4874 +        {
 25.4875 +            if(glGetQueryObjectuiv_Impl)
 25.4876 +                glGetQueryObjectuiv_Impl(id, pname, params);
 25.4877 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4878 +        }
 25.4879 +
 25.4880 +        void OVR::GLEContext::glBindBuffer_Hook(GLenum target, GLuint buffer)
 25.4881 +        {
 25.4882 +            if(glBindBuffer_Impl)
 25.4883 +                glBindBuffer_Impl(target, buffer);
 25.4884 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4885 +        }
 25.4886 +
 25.4887 +        void OVR::GLEContext::glDeleteBuffers_Hook(GLsizei n, const GLuint *buffers)
 25.4888 +        {
 25.4889 +            if(glDeleteBuffers_Impl)
 25.4890 +                glDeleteBuffers_Impl(n, buffers);
 25.4891 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4892 +        }
 25.4893 +
 25.4894 +        void OVR::GLEContext::glGenBuffers_Hook(GLsizei n, GLuint *buffers)
 25.4895 +        {
 25.4896 +            if(glGenBuffers_Impl)
 25.4897 +                glGenBuffers_Impl(n, buffers);
 25.4898 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4899 +        }
 25.4900 +
 25.4901 +        GLboolean OVR::GLEContext::glIsBuffer_Hook(GLuint buffer)
 25.4902 +        {
 25.4903 +            GLboolean b = GL_FALSE;
 25.4904 +            if(glIsBuffer_Impl)
 25.4905 +                b = glIsBuffer_Impl(buffer);
 25.4906 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4907 +            return b;
 25.4908 +        }
 25.4909 +
 25.4910 +        void OVR::GLEContext::glBufferData_Hook(GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage)
 25.4911 +        {
 25.4912 +            if(glBufferData_Impl)
 25.4913 +                glBufferData_Impl(target, size, data, usage);
 25.4914 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4915 +        }
 25.4916 +
 25.4917 +        void OVR::GLEContext::glBufferSubData_Hook(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data)
 25.4918 +        {
 25.4919 +            if(glBufferSubData_Impl)
 25.4920 +                glBufferSubData_Impl(target, offset, size, data);
 25.4921 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4922 +        }
 25.4923 +
 25.4924 +        void OVR::GLEContext::glGetBufferSubData_Hook(GLenum target, GLintptr offset, GLsizeiptr size, GLvoid *data)
 25.4925 +        {
 25.4926 +            if(glGetBufferSubData_Impl)
 25.4927 +                glGetBufferSubData_Impl(target, offset, size, data);
 25.4928 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4929 +        }
 25.4930 +
 25.4931 +        GLvoid* OVR::GLEContext::glMapBuffer_Hook(GLenum target, GLenum access)
 25.4932 +        {
 25.4933 +            GLvoid* p = NULL;
 25.4934 +            if(glMapBuffer_Impl)
 25.4935 +                p = glMapBuffer_Impl(target, access);
 25.4936 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4937 +            return p;
 25.4938 +        }
 25.4939 +
 25.4940 +        GLboolean OVR::GLEContext::glUnmapBuffer_Hook(GLenum target)
 25.4941 +        {
 25.4942 +            GLboolean b = GL_FALSE;
 25.4943 +            if(glUnmapBuffer_Impl)
 25.4944 +                b = glUnmapBuffer_Impl(target);
 25.4945 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4946 +            return b;
 25.4947 +        }
 25.4948 +
 25.4949 +        void OVR::GLEContext::glGetBufferParameteriv_Hook(GLenum target, GLenum pname, GLint *params)
 25.4950 +        {
 25.4951 +            if(glGetBufferParameteriv_Impl)
 25.4952 +                glGetBufferParameteriv_Impl(target, pname, params);
 25.4953 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4954 +        }
 25.4955 +
 25.4956 +        void OVR::GLEContext::glGetBufferPointerv_Hook(GLenum target, GLenum pname, GLvoid* *params)
 25.4957 +        {
 25.4958 +            if(glGetBufferPointerv_Impl)
 25.4959 +                glGetBufferPointerv_Impl(target, pname, params);
 25.4960 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4961 +        }
 25.4962 +
 25.4963 +
 25.4964 +        // GL_VERSION_2_0
 25.4965 +        void OVR::GLEContext::glBlendEquationSeparate_Hook(GLenum modeRGB, GLenum modeAlpha)
 25.4966 +        {
 25.4967 +            if(glBlendEquationSeparate_Impl)
 25.4968 +                glBlendEquationSeparate_Impl(modeRGB, modeAlpha);
 25.4969 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4970 +        }
 25.4971 +
 25.4972 +        void OVR::GLEContext::glDrawBuffers_Hook(GLsizei n, const GLenum *bufs)
 25.4973 +        {
 25.4974 +            if(glDrawBuffers_Impl)
 25.4975 +                glDrawBuffers_Impl(n, bufs);
 25.4976 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4977 +        }
 25.4978 +
 25.4979 +        void OVR::GLEContext::glStencilOpSeparate_Hook(GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass)
 25.4980 +        {
 25.4981 +            if(glStencilOpSeparate_Impl)
 25.4982 +                glStencilOpSeparate_Impl(face, sfail, dpfail, dppass);
 25.4983 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4984 +        }
 25.4985 +
 25.4986 +        void OVR::GLEContext::glStencilFuncSeparate_Hook(GLenum face, GLenum func, GLint ref, GLuint mask)
 25.4987 +        {
 25.4988 +            if(glStencilFuncSeparate_Impl)
 25.4989 +                glStencilFuncSeparate_Impl(face, func, ref, mask);
 25.4990 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4991 +        }
 25.4992 +
 25.4993 +        void OVR::GLEContext::glStencilMaskSeparate_Hook(GLenum face, GLuint mask)
 25.4994 +        {
 25.4995 +            if(glStencilMaskSeparate_Impl)
 25.4996 +                glStencilMaskSeparate_Impl(face, mask);
 25.4997 +            PostHook(GLE_CURRENT_FUNCTION);
 25.4998 +        }
 25.4999 +
 25.5000 +        void OVR::GLEContext::glAttachShader_Hook(GLuint program, GLuint shader)
 25.5001 +        {
 25.5002 +            if(glAttachShader_Impl)
 25.5003 +                glAttachShader_Impl(program, shader);
 25.5004 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5005 +        }
 25.5006 +
 25.5007 +        void OVR::GLEContext::glBindAttribLocation_Hook(GLuint program, GLuint index, const GLchar *name)
 25.5008 +        {
 25.5009 +            if(glBindAttribLocation_Impl)
 25.5010 +                glBindAttribLocation_Impl(program, index, name);
 25.5011 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5012 +        }
 25.5013 +
 25.5014 +        void OVR::GLEContext::glCompileShader_Hook(GLuint shader)
 25.5015 +        {
 25.5016 +            if(glCompileShader_Impl)
 25.5017 +                glCompileShader_Impl(shader);
 25.5018 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5019 +        }
 25.5020 +
 25.5021 +        GLuint OVR::GLEContext::glCreateProgram_Hook()
 25.5022 +        {
 25.5023 +            GLuint u = 0;
 25.5024 +            if(glCreateProgram_Impl)
 25.5025 +                u = glCreateProgram_Impl();
 25.5026 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5027 +            return u;
 25.5028 +        }
 25.5029 +
 25.5030 +        GLuint OVR::GLEContext::glCreateShader_Hook(GLenum type)
 25.5031 +        {
 25.5032 +            GLuint u = 0;
 25.5033 +            if(glCreateShader_Impl)
 25.5034 +                u = glCreateShader_Impl(type);
 25.5035 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5036 +            return u;
 25.5037 +        }
 25.5038 +
 25.5039 +        void OVR::GLEContext::glDeleteProgram_Hook(GLuint program)
 25.5040 +        {
 25.5041 +            if(glDeleteProgram_Impl)
 25.5042 +                glDeleteProgram_Impl(program);
 25.5043 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5044 +        }
 25.5045 +
 25.5046 +        void OVR::GLEContext::glDeleteShader_Hook(GLuint shader)
 25.5047 +        {
 25.5048 +            if(glDeleteShader_Impl)
 25.5049 +                glDeleteShader_Impl(shader);
 25.5050 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5051 +        }
 25.5052 +
 25.5053 +        void OVR::GLEContext::glDetachShader_Hook(GLuint program, GLuint shader)
 25.5054 +        {
 25.5055 +            if(glDetachShader_Impl)
 25.5056 +                glDetachShader_Impl(program, shader);
 25.5057 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5058 +        }
 25.5059 +
 25.5060 +        void OVR::GLEContext::glDisableVertexAttribArray_Hook(GLuint index)
 25.5061 +        {
 25.5062 +            if(glDisableVertexAttribArray_Impl)
 25.5063 +                glDisableVertexAttribArray_Impl(index);
 25.5064 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5065 +        }
 25.5066 +
 25.5067 +        void OVR::GLEContext::glEnableVertexAttribArray_Hook(GLuint index)
 25.5068 +        {
 25.5069 +            if(glEnableVertexAttribArray_Impl)
 25.5070 +                glEnableVertexAttribArray_Impl(index);
 25.5071 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5072 +        }
 25.5073 +
 25.5074 +        void OVR::GLEContext::glGetActiveAttrib_Hook(GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
 25.5075 +        {
 25.5076 +            if(glGetActiveAttrib_Impl)
 25.5077 +                glGetActiveAttrib_Impl(program, index, bufSize, length, size, type, name);
 25.5078 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5079 +        }
 25.5080 +
 25.5081 +        void OVR::GLEContext::glGetActiveUniform_Hook(GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
 25.5082 +        {
 25.5083 +            if(glGetActiveUniform_Impl)
 25.5084 +                glGetActiveUniform_Impl(program, index, bufSize, length, size, type, name);
 25.5085 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5086 +        }
 25.5087 +
 25.5088 +        void OVR::GLEContext::glGetAttachedShaders_Hook(GLuint program, GLsizei maxCount, GLsizei *count, GLuint *obj)
 25.5089 +        {
 25.5090 +            if(glGetAttachedShaders_Impl)
 25.5091 +                glGetAttachedShaders_Impl(program, maxCount, count, obj);
 25.5092 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5093 +        }
 25.5094 +
 25.5095 +        GLint OVR::GLEContext::glGetAttribLocation_Hook(GLuint program, const GLchar *name)
 25.5096 +        {
 25.5097 +            GLint i = 0;
 25.5098 +            if(glGetAttribLocation_Impl)
 25.5099 +                i = glGetAttribLocation_Impl(program, name);
 25.5100 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5101 +            return i;
 25.5102 +        }
 25.5103 +
 25.5104 +        void OVR::GLEContext::glGetProgramiv_Hook(GLuint program, GLenum pname, GLint *params)
 25.5105 +        {
 25.5106 +            if(glGetProgramiv_Impl)
 25.5107 +                glGetProgramiv_Impl(program, pname, params);
 25.5108 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5109 +        }
 25.5110 +
 25.5111 +        void OVR::GLEContext::glGetProgramInfoLog_Hook(GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog)
 25.5112 +        {
 25.5113 +            if(glGetProgramInfoLog_Impl)
 25.5114 +                glGetProgramInfoLog_Impl(program, bufSize, length, infoLog);
 25.5115 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5116 +        }
 25.5117 +
 25.5118 +        void OVR::GLEContext::glGetShaderiv_Hook(GLuint shader, GLenum pname, GLint *params)
 25.5119 +        {
 25.5120 +            if(glGetShaderiv_Impl)
 25.5121 +                glGetShaderiv_Impl(shader, pname, params);
 25.5122 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5123 +        }
 25.5124 +
 25.5125 +        void OVR::GLEContext::glGetShaderInfoLog_Hook(GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog)
 25.5126 +        {
 25.5127 +            if(glGetShaderInfoLog_Impl)
 25.5128 +                glGetShaderInfoLog_Impl(shader, bufSize, length, infoLog);
 25.5129 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5130 +        }
 25.5131 +
 25.5132 +        void OVR::GLEContext::glGetShaderSource_Hook(GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source)
 25.5133 +        {
 25.5134 +            if(glGetShaderSource_Impl)
 25.5135 +                glGetShaderSource_Impl(shader, bufSize, length, source);
 25.5136 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5137 +        }
 25.5138 +
 25.5139 +        GLint OVR::GLEContext::glGetUniformLocation_Hook(GLuint program, const GLchar *name)
 25.5140 +        {
 25.5141 +            GLint i = 0;
 25.5142 +            if(glGetUniformLocation_Impl)
 25.5143 +                i = glGetUniformLocation_Impl(program, name);
 25.5144 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5145 +            return i;
 25.5146 +        }
 25.5147 +
 25.5148 +        void OVR::GLEContext::glGetUniformfv_Hook(GLuint program, GLint location, GLfloat *params)
 25.5149 +        {
 25.5150 +            if(glGetUniformfv_Impl)
 25.5151 +                glGetUniformfv_Impl(program, location, params);
 25.5152 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5153 +        }
 25.5154 +
 25.5155 +        void OVR::GLEContext::glGetUniformiv_Hook(GLuint program, GLint location, GLint *params)
 25.5156 +        {
 25.5157 +            if(glGetUniformiv_Impl)
 25.5158 +                glGetUniformiv_Impl(program, location, params);
 25.5159 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5160 +        }
 25.5161 +
 25.5162 +        void OVR::GLEContext::glGetVertexAttribdv_Hook(GLuint index, GLenum pname, GLdouble *params)
 25.5163 +        {
 25.5164 +            if(glGetVertexAttribdv_Impl)
 25.5165 +                glGetVertexAttribdv_Impl(index, pname, params);
 25.5166 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5167 +        }
 25.5168 +
 25.5169 +        void OVR::GLEContext::glGetVertexAttribfv_Hook(GLuint index, GLenum pname, GLfloat *params)
 25.5170 +        {
 25.5171 +            if(glGetVertexAttribfv_Impl)
 25.5172 +                glGetVertexAttribfv_Impl(index, pname, params);
 25.5173 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5174 +        }
 25.5175 +
 25.5176 +        void OVR::GLEContext::glGetVertexAttribiv_Hook(GLuint index, GLenum pname, GLint *params)
 25.5177 +        {
 25.5178 +            if(glGetVertexAttribiv_Impl)
 25.5179 +                glGetVertexAttribiv_Impl(index, pname, params);
 25.5180 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5181 +        }
 25.5182 +
 25.5183 +        void OVR::GLEContext::glGetVertexAttribPointerv_Hook(GLuint index, GLenum pname, GLvoid* *pointer)
 25.5184 +        {
 25.5185 +            if(glGetVertexAttribPointerv_Impl)
 25.5186 +                glGetVertexAttribPointerv_Impl(index, pname, pointer);
 25.5187 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5188 +        }
 25.5189 +
 25.5190 +        GLboolean OVR::GLEContext::glIsProgram_Hook(GLuint program)
 25.5191 +        {
 25.5192 +            GLboolean b = GL_FALSE;
 25.5193 +            if(glIsProgram_Impl)
 25.5194 +                b = glIsProgram_Impl(program);
 25.5195 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5196 +            return b;
 25.5197 +        }
 25.5198 +
 25.5199 +        GLboolean OVR::GLEContext::glIsShader_Hook(GLuint shader)
 25.5200 +        {
 25.5201 +            GLboolean b = GL_FALSE;
 25.5202 +            if(glIsShader_Impl)
 25.5203 +                b = glIsShader_Impl(shader);
 25.5204 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5205 +            return b;
 25.5206 +        }
 25.5207 +
 25.5208 +        void OVR::GLEContext::glLinkProgram_Hook(GLuint program)
 25.5209 +        {
 25.5210 +            if(glLinkProgram_Impl)
 25.5211 +                glLinkProgram_Impl(program);
 25.5212 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5213 +        }
 25.5214 +
 25.5215 +        void OVR::GLEContext::glShaderSource_Hook(GLuint shader, GLsizei count, const GLchar* *string, const GLint *length)
 25.5216 +        {
 25.5217 +            if(glShaderSource_Impl)
 25.5218 +                glShaderSource_Impl(shader, count, string, length);
 25.5219 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5220 +        }
 25.5221 +
 25.5222 +        void OVR::GLEContext::glUseProgram_Hook(GLuint program)
 25.5223 +        {
 25.5224 +            if(glUseProgram_Impl)
 25.5225 +                glUseProgram_Impl(program);
 25.5226 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5227 +        }
 25.5228 +
 25.5229 +        void OVR::GLEContext::glUniform1f_Hook(GLint location, GLfloat v0)
 25.5230 +        {
 25.5231 +            if(glUniform1f_Impl)
 25.5232 +                glUniform1f_Impl(location, v0);
 25.5233 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5234 +        }
 25.5235 +
 25.5236 +        void OVR::GLEContext::glUniform2f_Hook(GLint location, GLfloat v0, GLfloat v1)
 25.5237 +        {
 25.5238 +            if(glUniform2f_Impl)
 25.5239 +                glUniform2f_Impl(location, v0, v1);
 25.5240 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5241 +        }
 25.5242 +
 25.5243 +        void OVR::GLEContext::glUniform3f_Hook(GLint location, GLfloat v0, GLfloat v1, GLfloat v2)
 25.5244 +        {
 25.5245 +            if(glUniform3f_Impl)
 25.5246 +                glUniform3f_Impl(location, v0, v1, v2);
 25.5247 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5248 +        }
 25.5249 +
 25.5250 +        void OVR::GLEContext::glUniform4f_Hook(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3)
 25.5251 +        {
 25.5252 +            if(glUniform4f_Impl)
 25.5253 +                glUniform4f_Impl(location, v0, v1, v2, v3);
 25.5254 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5255 +        }
 25.5256 +
 25.5257 +        void OVR::GLEContext::glUniform1i_Hook(GLint location, GLint v0)
 25.5258 +        {
 25.5259 +            if(glUniform1i_Impl)
 25.5260 +                glUniform1i_Impl(location, v0);
 25.5261 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5262 +        }
 25.5263 +
 25.5264 +        void OVR::GLEContext::glUniform2i_Hook(GLint location, GLint v0, GLint v1)
 25.5265 +        {
 25.5266 +            if(glUniform2i_Impl)
 25.5267 +                glUniform2i_Impl(location, v0, v1);
 25.5268 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5269 +        }
 25.5270 +
 25.5271 +        void OVR::GLEContext::glUniform3i_Hook(GLint location, GLint v0, GLint v1, GLint v2)
 25.5272 +        {
 25.5273 +            if(glUniform3i_Impl)
 25.5274 +                glUniform3i_Impl(location, v0, v1, v2);
 25.5275 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5276 +        }
 25.5277 +
 25.5278 +        void OVR::GLEContext::glUniform4i_Hook(GLint location, GLint v0, GLint v1, GLint v2, GLint v3)
 25.5279 +        {
 25.5280 +            if(glUniform4i_Impl)
 25.5281 +                glUniform4i_Impl(location, v0, v1, v2, v3);
 25.5282 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5283 +        }
 25.5284 +
 25.5285 +        void OVR::GLEContext::glUniform1fv_Hook(GLint location, GLsizei count, const GLfloat *value)
 25.5286 +        {
 25.5287 +            if(glUniform1fv_Impl)
 25.5288 +                glUniform1fv_Impl(location, count, value);
 25.5289 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5290 +        }
 25.5291 +
 25.5292 +        void OVR::GLEContext::glUniform2fv_Hook(GLint location, GLsizei count, const GLfloat *value)
 25.5293 +        {
 25.5294 +            if(glUniform2fv_Impl)
 25.5295 +                glUniform2fv_Impl(location, count, value);
 25.5296 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5297 +        }
 25.5298 +
 25.5299 +        void OVR::GLEContext::glUniform3fv_Hook(GLint location, GLsizei count, const GLfloat *value)
 25.5300 +        {
 25.5301 +            if(glUniform3fv_Impl)
 25.5302 +                glUniform3fv_Impl(location, count, value);
 25.5303 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5304 +        }
 25.5305 +
 25.5306 +        void OVR::GLEContext::glUniform4fv_Hook(GLint location, GLsizei count, const GLfloat *value)
 25.5307 +        {
 25.5308 +            if(glUniform4fv_Impl)
 25.5309 +                glUniform4fv_Impl(location, count, value);
 25.5310 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5311 +        }
 25.5312 +
 25.5313 +        void OVR::GLEContext::glUniform1iv_Hook(GLint location, GLsizei count, const GLint *value)
 25.5314 +        {
 25.5315 +            if(glUniform1iv_Impl)
 25.5316 +                glUniform1iv_Impl(location, count, value);
 25.5317 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5318 +        }
 25.5319 +
 25.5320 +        void OVR::GLEContext::glUniform2iv_Hook(GLint location, GLsizei count, const GLint *value)
 25.5321 +        {
 25.5322 +            if(glUniform2iv_Impl)
 25.5323 +                glUniform2iv_Impl(location, count, value);
 25.5324 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5325 +        }
 25.5326 +
 25.5327 +        void OVR::GLEContext::glUniform3iv_Hook(GLint location, GLsizei count, const GLint *value)
 25.5328 +        {
 25.5329 +            if(glUniform3iv_Impl)
 25.5330 +                glUniform3iv_Impl(location, count, value);
 25.5331 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5332 +        }
 25.5333 +
 25.5334 +        void OVR::GLEContext::glUniform4iv_Hook(GLint location, GLsizei count, const GLint *value)
 25.5335 +        {
 25.5336 +            if(glUniform4iv_Impl)
 25.5337 +                glUniform4iv_Impl(location, count, value);
 25.5338 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5339 +        }
 25.5340 +
 25.5341 +        void OVR::GLEContext::glUniformMatrix2fv_Hook(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
 25.5342 +        {
 25.5343 +            if(glUniformMatrix2fv_Impl)
 25.5344 +                glUniformMatrix2fv_Impl(location, count, transpose, value);
 25.5345 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5346 +        }
 25.5347 +
 25.5348 +        void OVR::GLEContext::glUniformMatrix3fv_Hook(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
 25.5349 +        {
 25.5350 +            if(glUniformMatrix3fv_Impl)
 25.5351 +                glUniformMatrix3fv_Impl(location, count, transpose, value);
 25.5352 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5353 +        }
 25.5354 +
 25.5355 +        void OVR::GLEContext::glUniformMatrix4fv_Hook(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
 25.5356 +        {
 25.5357 +            if(glUniformMatrix4fv_Impl)
 25.5358 +                glUniformMatrix4fv_Impl(location, count, transpose, value);
 25.5359 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5360 +        }
 25.5361 +
 25.5362 +        void OVR::GLEContext::glValidateProgram_Hook(GLuint program)
 25.5363 +        {
 25.5364 +            if(glValidateProgram_Impl)
 25.5365 +                glValidateProgram_Impl(program);
 25.5366 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5367 +        }
 25.5368 +
 25.5369 +        void OVR::GLEContext::glVertexAttrib1d_Hook(GLuint index, GLdouble x)
 25.5370 +        {
 25.5371 +            if(glVertexAttrib1d_Impl)
 25.5372 +                glVertexAttrib1d_Impl(index, x);
 25.5373 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5374 +        }
 25.5375 +
 25.5376 +        void OVR::GLEContext::glVertexAttrib1dv_Hook(GLuint index, const GLdouble *v)
 25.5377 +        {
 25.5378 +            if(glVertexAttrib1dv_Impl)
 25.5379 +                glVertexAttrib1dv_Impl(index, v);
 25.5380 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5381 +        }
 25.5382 +
 25.5383 +        void OVR::GLEContext::glVertexAttrib1f_Hook(GLuint index, GLfloat x)
 25.5384 +        {
 25.5385 +            if(glVertexAttrib1f_Impl)
 25.5386 +                glVertexAttrib1f_Impl(index, x);
 25.5387 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5388 +        }
 25.5389 +
 25.5390 +        void OVR::GLEContext::glVertexAttrib1fv_Hook(GLuint index, const GLfloat *v)
 25.5391 +        {
 25.5392 +            if(glVertexAttrib1fv_Impl)
 25.5393 +                glVertexAttrib1fv_Impl(index, v);
 25.5394 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5395 +        }
 25.5396 +
 25.5397 +        void OVR::GLEContext::glVertexAttrib1s_Hook(GLuint index, GLshort x)
 25.5398 +        {
 25.5399 +            if(glVertexAttrib1s_Impl)
 25.5400 +                glVertexAttrib1s_Impl(index, x);
 25.5401 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5402 +        }
 25.5403 +
 25.5404 +        void OVR::GLEContext::glVertexAttrib1sv_Hook(GLuint index, const GLshort *v)
 25.5405 +        {
 25.5406 +            if(glVertexAttrib1sv_Impl)
 25.5407 +                glVertexAttrib1sv_Impl(index, v);
 25.5408 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5409 +        }
 25.5410 +
 25.5411 +        void OVR::GLEContext::glVertexAttrib2d_Hook(GLuint index, GLdouble x, GLdouble y)
 25.5412 +        {
 25.5413 +            if(glVertexAttrib2d_Impl)
 25.5414 +                glVertexAttrib2d_Impl(index, x, y);
 25.5415 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5416 +        }
 25.5417 +
 25.5418 +        void OVR::GLEContext::glVertexAttrib2dv_Hook(GLuint index, const GLdouble *v)
 25.5419 +        {
 25.5420 +            if(glVertexAttrib2dv_Impl)
 25.5421 +                glVertexAttrib2dv_Impl(index, v);
 25.5422 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5423 +        }
 25.5424 +
 25.5425 +        void OVR::GLEContext::glVertexAttrib2f_Hook(GLuint index, GLfloat x, GLfloat y)
 25.5426 +        {
 25.5427 +            if(glVertexAttrib2f_Impl)
 25.5428 +                glVertexAttrib2f_Impl(index, x, y);
 25.5429 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5430 +        }
 25.5431 +
 25.5432 +        void OVR::GLEContext::glVertexAttrib2fv_Hook(GLuint index, const GLfloat *v)
 25.5433 +        {
 25.5434 +            if(glVertexAttrib2fv_Impl)
 25.5435 +                glVertexAttrib2fv_Impl(index, v);
 25.5436 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5437 +        }
 25.5438 +
 25.5439 +        void OVR::GLEContext::glVertexAttrib2s_Hook(GLuint index, GLshort x, GLshort y)
 25.5440 +        {
 25.5441 +            if(glVertexAttrib2s_Impl)
 25.5442 +                glVertexAttrib2s_Impl(index, x, y);
 25.5443 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5444 +        }
 25.5445 +
 25.5446 +        void OVR::GLEContext::glVertexAttrib2sv_Hook(GLuint index, const GLshort *v)
 25.5447 +        {
 25.5448 +            if(glVertexAttrib2sv_Impl)
 25.5449 +                glVertexAttrib2sv_Impl(index, v);
 25.5450 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5451 +        }
 25.5452 +
 25.5453 +        void OVR::GLEContext::glVertexAttrib3d_Hook(GLuint index, GLdouble x, GLdouble y, GLdouble z)
 25.5454 +        {
 25.5455 +            if(glVertexAttrib3d_Impl)
 25.5456 +                glVertexAttrib3d_Impl(index, x, y, z);
 25.5457 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5458 +        }
 25.5459 +
 25.5460 +        void OVR::GLEContext::glVertexAttrib3dv_Hook(GLuint index, const GLdouble *v)
 25.5461 +        {
 25.5462 +            if(glVertexAttrib3dv_Impl)
 25.5463 +                glVertexAttrib3dv_Impl(index, v);
 25.5464 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5465 +        }
 25.5466 +
 25.5467 +        void OVR::GLEContext::glVertexAttrib3f_Hook(GLuint index, GLfloat x, GLfloat y, GLfloat z)
 25.5468 +        {
 25.5469 +            if(glVertexAttrib3f_Impl)
 25.5470 +                glVertexAttrib3f_Impl(index, x, y, z);
 25.5471 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5472 +        }
 25.5473 +
 25.5474 +        void OVR::GLEContext::glVertexAttrib3fv_Hook(GLuint index, const GLfloat *v)
 25.5475 +        {
 25.5476 +            if(glVertexAttrib3fv_Impl)
 25.5477 +                glVertexAttrib3fv_Impl(index, v);
 25.5478 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5479 +        }
 25.5480 +
 25.5481 +        void OVR::GLEContext::glVertexAttrib3s_Hook(GLuint index, GLshort x, GLshort y, GLshort z)
 25.5482 +        {
 25.5483 +            if(glVertexAttrib3s_Impl)
 25.5484 +                glVertexAttrib3s_Impl(index, x, y, z);
 25.5485 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5486 +        }
 25.5487 +
 25.5488 +        void OVR::GLEContext::glVertexAttrib3sv_Hook(GLuint index, const GLshort *v)
 25.5489 +        {
 25.5490 +            if(glVertexAttrib3sv_Impl)
 25.5491 +                glVertexAttrib3sv_Impl(index, v);
 25.5492 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5493 +        }
 25.5494 +
 25.5495 +        void OVR::GLEContext::glVertexAttrib4Nbv_Hook(GLuint index, const GLbyte *v)
 25.5496 +        {
 25.5497 +            if(glVertexAttrib4Nbv_Impl)
 25.5498 +                glVertexAttrib4Nbv_Impl(index, v);
 25.5499 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5500 +        }
 25.5501 +
 25.5502 +        void OVR::GLEContext::glVertexAttrib4Niv_Hook(GLuint index, const GLint *v)
 25.5503 +        {
 25.5504 +            if(glVertexAttrib4Niv_Impl)
 25.5505 +                glVertexAttrib4Niv_Impl(index, v);
 25.5506 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5507 +        }
 25.5508 +
 25.5509 +        void OVR::GLEContext::glVertexAttrib4Nsv_Hook(GLuint index, const GLshort *v)
 25.5510 +        {
 25.5511 +            if(glVertexAttrib4Nsv_Impl)
 25.5512 +                glVertexAttrib4Nsv_Impl(index, v);
 25.5513 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5514 +        }
 25.5515 +
 25.5516 +        void OVR::GLEContext::glVertexAttrib4Nub_Hook(GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w)
 25.5517 +        {
 25.5518 +            if(glVertexAttrib4Nub_Impl)
 25.5519 +                glVertexAttrib4Nub_Impl(index, x, y, z, w);
 25.5520 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5521 +        }
 25.5522 +
 25.5523 +        void OVR::GLEContext::glVertexAttrib4Nubv_Hook(GLuint index, const GLubyte *v)
 25.5524 +        {
 25.5525 +            if(glVertexAttrib4Nubv_Impl)
 25.5526 +                glVertexAttrib4Nubv_Impl(index, v);
 25.5527 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5528 +        }
 25.5529 +
 25.5530 +        void OVR::GLEContext::glVertexAttrib4Nuiv_Hook(GLuint index, const GLuint *v)
 25.5531 +        {
 25.5532 +            if(glVertexAttrib4Nuiv_Impl)
 25.5533 +                glVertexAttrib4Nuiv_Impl(index, v);
 25.5534 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5535 +        }
 25.5536 +
 25.5537 +        void OVR::GLEContext::glVertexAttrib4Nusv_Hook(GLuint index, const GLushort *v)
 25.5538 +        {
 25.5539 +            if(glVertexAttrib4Nusv_Impl)
 25.5540 +                glVertexAttrib4Nusv_Impl(index, v);
 25.5541 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5542 +        }
 25.5543 +
 25.5544 +        void OVR::GLEContext::glVertexAttrib4bv_Hook(GLuint index, const GLbyte *v)
 25.5545 +        {
 25.5546 +            if(glVertexAttrib4bv_Impl)
 25.5547 +                glVertexAttrib4bv_Impl(index, v);
 25.5548 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5549 +        }
 25.5550 +
 25.5551 +        void OVR::GLEContext::glVertexAttrib4d_Hook(GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w)
 25.5552 +        {
 25.5553 +            if(glVertexAttrib4d_Impl)
 25.5554 +                glVertexAttrib4d_Impl(index, x, y, z, w);
 25.5555 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5556 +        }
 25.5557 +
 25.5558 +        void OVR::GLEContext::glVertexAttrib4dv_Hook(GLuint index, const GLdouble *v)
 25.5559 +        {
 25.5560 +            if(glVertexAttrib4dv_Impl)
 25.5561 +                glVertexAttrib4dv_Impl(index, v);
 25.5562 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5563 +        }
 25.5564 +
 25.5565 +        void OVR::GLEContext::glVertexAttrib4f_Hook(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
 25.5566 +        {
 25.5567 +            if(glVertexAttrib4f_Impl)
 25.5568 +                glVertexAttrib4f_Impl(index, x, y, z, w);
 25.5569 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5570 +        }
 25.5571 +
 25.5572 +        void OVR::GLEContext::glVertexAttrib4fv_Hook(GLuint index, const GLfloat *v)
 25.5573 +        {
 25.5574 +            if(glVertexAttrib4fv_Impl)
 25.5575 +                glVertexAttrib4fv_Impl(index, v);
 25.5576 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5577 +        }
 25.5578 +
 25.5579 +        void OVR::GLEContext::glVertexAttrib4iv_Hook(GLuint index, const GLint *v)
 25.5580 +        {
 25.5581 +            if(glVertexAttrib4iv_Impl)
 25.5582 +                glVertexAttrib4iv_Impl(index, v);
 25.5583 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5584 +        }
 25.5585 +
 25.5586 +        void OVR::GLEContext::glVertexAttrib4s_Hook(GLuint index, GLshort x, GLshort y, GLshort z, GLshort w)
 25.5587 +        {
 25.5588 +            if(glVertexAttrib4s_Impl)
 25.5589 +                glVertexAttrib4s_Impl(index, x, y, z, w);
 25.5590 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5591 +        }
 25.5592 +
 25.5593 +        void OVR::GLEContext::glVertexAttrib4sv_Hook(GLuint index, const GLshort *v)
 25.5594 +        {
 25.5595 +            if(glVertexAttrib4sv_Impl)
 25.5596 +                glVertexAttrib4sv_Impl(index, v);
 25.5597 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5598 +        }
 25.5599 +
 25.5600 +        void OVR::GLEContext::glVertexAttrib4ubv_Hook(GLuint index, const GLubyte *v)
 25.5601 +        {
 25.5602 +            if(glVertexAttrib4ubv_Impl)
 25.5603 +                glVertexAttrib4ubv_Impl(index, v);
 25.5604 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5605 +        }
 25.5606 +
 25.5607 +        void OVR::GLEContext::glVertexAttrib4uiv_Hook(GLuint index, const GLuint *v)
 25.5608 +        {
 25.5609 +            if(glVertexAttrib4uiv_Impl)
 25.5610 +                glVertexAttrib4uiv_Impl(index, v);
 25.5611 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5612 +        }
 25.5613 +
 25.5614 +        void OVR::GLEContext::glVertexAttrib4usv_Hook(GLuint index, const GLushort *v)
 25.5615 +        {
 25.5616 +            if(glVertexAttrib4usv_Impl)
 25.5617 +                glVertexAttrib4usv_Impl(index, v);
 25.5618 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5619 +        }
 25.5620 +
 25.5621 +        void OVR::GLEContext::glVertexAttribPointer_Hook(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer)
 25.5622 +        {
 25.5623 +            if(glVertexAttribPointer_Impl)
 25.5624 +                glVertexAttribPointer_Impl(index, size, type, normalized, stride, pointer);
 25.5625 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5626 +        }
 25.5627 +
 25.5628 +
 25.5629 +        // GL_VERSION_2_1
 25.5630 +        void OVR::GLEContext::glUniformMatrix2x3fv_Hook(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
 25.5631 +        {
 25.5632 +            if(glUniformMatrix2x3fv_Impl)
 25.5633 +                glUniformMatrix2x3fv_Impl(location, count, transpose, value);
 25.5634 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5635 +        }
 25.5636 +
 25.5637 +        void OVR::GLEContext::glUniformMatrix3x2fv_Hook(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
 25.5638 +        {
 25.5639 +            if(glUniformMatrix3x2fv_Impl)
 25.5640 +                glUniformMatrix3x2fv_Impl(location, count, transpose, value);
 25.5641 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5642 +        }
 25.5643 +
 25.5644 +        void OVR::GLEContext::glUniformMatrix2x4fv_Hook(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
 25.5645 +        {
 25.5646 +            if(glUniformMatrix2x4fv_Impl)
 25.5647 +                glUniformMatrix2x4fv_Impl(location, count, transpose, value);
 25.5648 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5649 +        }
 25.5650 +
 25.5651 +        void OVR::GLEContext::glUniformMatrix4x2fv_Hook(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
 25.5652 +        {
 25.5653 +            if(glUniformMatrix4x2fv_Impl)
 25.5654 +                glUniformMatrix4x2fv_Impl(location, count, transpose, value);
 25.5655 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5656 +        }
 25.5657 +
 25.5658 +        void OVR::GLEContext::glUniformMatrix3x4fv_Hook(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
 25.5659 +        {
 25.5660 +            if(glUniformMatrix3x4fv_Impl)
 25.5661 +                glUniformMatrix3x4fv_Impl(location, count, transpose, value);
 25.5662 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5663 +        }
 25.5664 +
 25.5665 +        void OVR::GLEContext::glUniformMatrix4x3fv_Hook(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
 25.5666 +        {
 25.5667 +            if(glUniformMatrix4x3fv_Impl)
 25.5668 +                glUniformMatrix4x3fv_Impl(location, count, transpose, value);
 25.5669 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5670 +        }
 25.5671 +
 25.5672 +
 25.5673 +        // GL_VERSION_3_0
 25.5674 +        void OVR::GLEContext::glColorMaski_Hook(GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a)
 25.5675 +        {
 25.5676 +            if(glColorMaski_Impl)
 25.5677 +                glColorMaski_Impl(index, r, g, b, a);
 25.5678 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5679 +        }
 25.5680 +
 25.5681 +        void OVR::GLEContext::glGetBooleani_v_Hook(GLenum target, GLuint index, GLboolean *data)
 25.5682 +        {
 25.5683 +            if(glGetBooleani_v_Impl)
 25.5684 +                glGetBooleani_v_Impl(target, index, data);
 25.5685 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5686 +        }
 25.5687 +
 25.5688 +        void OVR::GLEContext::glGetIntegeri_v_Hook(GLenum target, GLuint index, GLint *data)
 25.5689 +        {
 25.5690 +            if(glGetIntegeri_v_Impl)
 25.5691 +                glGetIntegeri_v_Impl(target, index, data);
 25.5692 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5693 +        }
 25.5694 +
 25.5695 +        void OVR::GLEContext::glEnablei_Hook(GLenum target, GLuint index)
 25.5696 +        {
 25.5697 +            if(glEnablei_Impl)
 25.5698 +                glEnablei_Impl(target, index);
 25.5699 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5700 +        }
 25.5701 +
 25.5702 +        void OVR::GLEContext::glDisablei_Hook(GLenum target, GLuint index)
 25.5703 +        {
 25.5704 +            if(glDisablei_Impl)
 25.5705 +                glDisablei_Impl(target, index);
 25.5706 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5707 +        }
 25.5708 +
 25.5709 +        GLboolean OVR::GLEContext::glIsEnabledi_Hook(GLenum target, GLuint index)
 25.5710 +        {
 25.5711 +            GLboolean b = GL_FALSE;
 25.5712 +            if(glIsEnabledi_Impl)
 25.5713 +                b = glIsEnabledi_Impl(target, index);
 25.5714 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5715 +            return b;
 25.5716 +        }
 25.5717 +
 25.5718 +        void OVR::GLEContext::glBeginTransformFeedback_Hook(GLenum primitiveMode)
 25.5719 +        {
 25.5720 +            if(glBeginTransformFeedback_Impl)
 25.5721 +                glBeginTransformFeedback_Impl(primitiveMode);
 25.5722 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5723 +        }
 25.5724 +
 25.5725 +        void OVR::GLEContext::glEndTransformFeedback_Hook()
 25.5726 +        {
 25.5727 +            if(glEndTransformFeedback_Impl)
 25.5728 +                glEndTransformFeedback_Impl();
 25.5729 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5730 +        }
 25.5731 +
 25.5732 +        void OVR::GLEContext::glBindBufferRange_Hook(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size)
 25.5733 +        {
 25.5734 +            if(glBindBufferRange_Impl)
 25.5735 +                glBindBufferRange_Impl(target, index, buffer, offset, size);
 25.5736 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5737 +        }
 25.5738 +
 25.5739 +        void OVR::GLEContext::glBindBufferBase_Hook(GLenum target, GLuint index, GLuint buffer)
 25.5740 +        {
 25.5741 +            if(glBindBufferBase_Impl)
 25.5742 +                glBindBufferBase_Impl(target, index, buffer);
 25.5743 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5744 +        }
 25.5745 +
 25.5746 +        void OVR::GLEContext::glTransformFeedbackVaryings_Hook(GLuint program, GLsizei count, const GLchar* *varyings, GLenum bufferMode)
 25.5747 +        {
 25.5748 +            if(glTransformFeedbackVaryings_Impl)
 25.5749 +                glTransformFeedbackVaryings_Impl(program, count, varyings, bufferMode);
 25.5750 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5751 +        }
 25.5752 +
 25.5753 +        void OVR::GLEContext::glGetTransformFeedbackVarying_Hook(GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name)
 25.5754 +        {
 25.5755 +            if(glGetTransformFeedbackVarying_Impl)
 25.5756 +                glGetTransformFeedbackVarying_Impl(program, index, bufSize, length, size, type, name);
 25.5757 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5758 +        }
 25.5759 +
 25.5760 +        void OVR::GLEContext::glClampColor_Hook(GLenum target, GLenum clamp)
 25.5761 +        {
 25.5762 +            if(glClampColor_Impl)
 25.5763 +                glClampColor_Impl(target, clamp);
 25.5764 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5765 +        }
 25.5766 +
 25.5767 +        void OVR::GLEContext::glBeginConditionalRender_Hook(GLuint id, GLenum mode)
 25.5768 +        {
 25.5769 +            if(glBeginConditionalRender_Impl)
 25.5770 +                glBeginConditionalRender_Impl(id, mode);
 25.5771 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5772 +        }
 25.5773 +
 25.5774 +        void OVR::GLEContext::glEndConditionalRender_Hook()
 25.5775 +        {
 25.5776 +            if(glEndConditionalRender_Impl)
 25.5777 +                glEndConditionalRender_Impl();
 25.5778 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5779 +        }
 25.5780 +
 25.5781 +        void OVR::GLEContext::glVertexAttribIPointer_Hook(GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
 25.5782 +        {
 25.5783 +            if(glVertexAttribIPointer_Impl)
 25.5784 +                glVertexAttribIPointer_Impl(index, size, type,  stride, pointer);
 25.5785 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5786 +        }
 25.5787 +
 25.5788 +        void OVR::GLEContext::glGetVertexAttribIiv_Hook(GLuint index, GLenum pname, GLint *params)
 25.5789 +        {
 25.5790 +            if(glGetVertexAttribIiv_Impl)
 25.5791 +                glGetVertexAttribIiv_Impl(index, pname, params);
 25.5792 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5793 +        }
 25.5794 +
 25.5795 +        void OVR::GLEContext::glGetVertexAttribIuiv_Hook(GLuint index, GLenum pname, GLuint *params)
 25.5796 +        {
 25.5797 +            if(glGetVertexAttribIuiv_Impl)
 25.5798 +                glGetVertexAttribIuiv_Impl(index, pname, params);
 25.5799 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5800 +        }
 25.5801 +
 25.5802 +        void OVR::GLEContext::glVertexAttribI1i_Hook(GLuint index, GLint x)
 25.5803 +        {
 25.5804 +            if(glVertexAttribI1i_Impl)
 25.5805 +                glVertexAttribI1i_Impl(index, x);
 25.5806 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5807 +        }
 25.5808 +
 25.5809 +        void OVR::GLEContext::glVertexAttribI2i_Hook(GLuint index, GLint x, GLint y)
 25.5810 +        {
 25.5811 +            if(glVertexAttribI2i_Impl)
 25.5812 +                glVertexAttribI2i_Impl(index, x, y);
 25.5813 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5814 +        }
 25.5815 +
 25.5816 +        void OVR::GLEContext::glVertexAttribI3i_Hook(GLuint index, GLint x, GLint y, GLint z)
 25.5817 +        {
 25.5818 +            if(glVertexAttribI3i_Impl)
 25.5819 +                glVertexAttribI3i_Impl(index, x, y, z);
 25.5820 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5821 +        }
 25.5822 +
 25.5823 +        void OVR::GLEContext::glVertexAttribI4i_Hook(GLuint index, GLint x, GLint y, GLint z, GLint w)
 25.5824 +        {
 25.5825 +            if(glVertexAttribI4i_Impl)
 25.5826 +                glVertexAttribI4i_Impl(index, x, y, z, w);
 25.5827 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5828 +        }
 25.5829 +
 25.5830 +        void OVR::GLEContext::glVertexAttribI1ui_Hook(GLuint index, GLuint x)
 25.5831 +        {
 25.5832 +            if(glVertexAttribI1ui_Impl)
 25.5833 +                glVertexAttribI1ui_Impl(index, x);
 25.5834 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5835 +        }
 25.5836 +
 25.5837 +        void OVR::GLEContext::glVertexAttribI2ui_Hook(GLuint index, GLuint x, GLuint y)
 25.5838 +        {
 25.5839 +            if(glVertexAttribI2ui_Impl)
 25.5840 +                glVertexAttribI2ui_Impl(index, x, y);
 25.5841 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5842 +        }
 25.5843 +
 25.5844 +        void OVR::GLEContext::glVertexAttribI3ui_Hook(GLuint index, GLuint x, GLuint y, GLuint z)
 25.5845 +        {
 25.5846 +            if(glVertexAttribI3ui_Impl)
 25.5847 +                glVertexAttribI3ui_Impl(index, x, y, z);
 25.5848 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5849 +        }
 25.5850 +
 25.5851 +        void OVR::GLEContext::glVertexAttribI4ui_Hook(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w)
 25.5852 +        {
 25.5853 +            if(glVertexAttribI4ui_Impl)
 25.5854 +                glVertexAttribI4ui_Impl(index, x, y, z, w);
 25.5855 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5856 +        }
 25.5857 +
 25.5858 +        void OVR::GLEContext::glVertexAttribI1iv_Hook(GLuint index, const GLint *v)
 25.5859 +        {
 25.5860 +            if(glVertexAttribI1iv_Impl)
 25.5861 +                glVertexAttribI1iv_Impl(index, v);
 25.5862 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5863 +        }
 25.5864 +
 25.5865 +        void OVR::GLEContext::glVertexAttribI2iv_Hook(GLuint index, const GLint *v)
 25.5866 +        {
 25.5867 +            if(glVertexAttribI2iv_Impl)
 25.5868 +                glVertexAttribI2iv_Impl(index, v);
 25.5869 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5870 +        }
 25.5871 +
 25.5872 +        void OVR::GLEContext::glVertexAttribI3iv_Hook(GLuint index, const GLint *v)
 25.5873 +        {
 25.5874 +            if(glVertexAttribI3iv_Impl)
 25.5875 +                glVertexAttribI3iv_Impl(index, v);
 25.5876 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5877 +        }
 25.5878 +
 25.5879 +        void OVR::GLEContext::glVertexAttribI4iv_Hook(GLuint index, const GLint *v)
 25.5880 +        {
 25.5881 +            if(glVertexAttribI4iv_Impl)
 25.5882 +                glVertexAttribI4iv_Impl(index, v);
 25.5883 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5884 +        }
 25.5885 +
 25.5886 +        void OVR::GLEContext::glVertexAttribI1uiv_Hook(GLuint index, const GLuint *v)
 25.5887 +        {
 25.5888 +            if(glVertexAttribI1uiv_Impl)
 25.5889 +                glVertexAttribI1uiv_Impl(index, v);
 25.5890 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5891 +        }
 25.5892 +
 25.5893 +        void OVR::GLEContext::glVertexAttribI2uiv_Hook(GLuint index, const GLuint *v)
 25.5894 +        {
 25.5895 +            if(glVertexAttribI2uiv_Impl)
 25.5896 +                glVertexAttribI2uiv_Impl(index, v);
 25.5897 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5898 +        }
 25.5899 +
 25.5900 +        void OVR::GLEContext::glVertexAttribI3uiv_Hook(GLuint index, const GLuint *v)
 25.5901 +        {
 25.5902 +            if(glVertexAttribI3uiv_Impl)
 25.5903 +                glVertexAttribI3uiv_Impl(index, v);
 25.5904 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5905 +        }
 25.5906 +
 25.5907 +        void OVR::GLEContext::glVertexAttribI4uiv_Hook(GLuint index, const GLuint *v)
 25.5908 +        {
 25.5909 +            if(glVertexAttribI4uiv_Impl)
 25.5910 +                glVertexAttribI4uiv_Impl(index, v);
 25.5911 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5912 +        }
 25.5913 +
 25.5914 +        void OVR::GLEContext::glVertexAttribI4bv_Hook(GLuint index, const GLbyte *v)
 25.5915 +        {
 25.5916 +            if(glVertexAttribI4bv_Impl)
 25.5917 +                glVertexAttribI4bv_Impl(index, v);
 25.5918 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5919 +        }
 25.5920 +
 25.5921 +        void OVR::GLEContext::glVertexAttribI4sv_Hook(GLuint index, const GLshort *v)
 25.5922 +        {
 25.5923 +            if(glVertexAttribI4sv_Impl)
 25.5924 +                glVertexAttribI4sv_Impl(index, v);
 25.5925 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5926 +        }
 25.5927 +
 25.5928 +        void OVR::GLEContext::glVertexAttribI4ubv_Hook(GLuint index, const GLubyte *v)
 25.5929 +        {
 25.5930 +            if(glVertexAttribI4ubv_Impl)
 25.5931 +                glVertexAttribI4ubv_Impl(index, v);
 25.5932 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5933 +        }
 25.5934 +
 25.5935 +        void OVR::GLEContext::glVertexAttribI4usv_Hook(GLuint index, const GLushort *v)
 25.5936 +        {
 25.5937 +            if(glVertexAttribI4usv_Impl)
 25.5938 +                glVertexAttribI4usv_Impl(index, v);
 25.5939 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5940 +        }
 25.5941 +
 25.5942 +        void OVR::GLEContext::glGetUniformuiv_Hook(GLuint program, GLint location, GLuint *params)
 25.5943 +        {
 25.5944 +            if(glGetUniformuiv_Impl)
 25.5945 +                glGetUniformuiv_Impl(program, location, params);
 25.5946 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5947 +        }
 25.5948 +
 25.5949 +        void OVR::GLEContext::glBindFragDataLocation_Hook(GLuint program, GLuint color, const GLchar *name)
 25.5950 +        {
 25.5951 +            if(glBindFragDataLocation_Impl)
 25.5952 +                glBindFragDataLocation_Impl(program, color, name);
 25.5953 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5954 +        }
 25.5955 +
 25.5956 +        GLint OVR::GLEContext::glGetFragDataLocation_Hook(GLuint program, const GLchar *name)
 25.5957 +        {
 25.5958 +            GLint i = 0;
 25.5959 +            if(glGetFragDataLocation_Impl)
 25.5960 +                i = glGetFragDataLocation_Impl(program, name);
 25.5961 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5962 +            return i;
 25.5963 +        }
 25.5964 +
 25.5965 +        void OVR::GLEContext::glUniform1ui_Hook(GLint location, GLuint v0)
 25.5966 +        {
 25.5967 +            if(glUniform1ui_Impl)
 25.5968 +                glUniform1ui_Impl(location, v0);
 25.5969 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5970 +        }
 25.5971 +
 25.5972 +        void OVR::GLEContext::glUniform2ui_Hook(GLint location, GLuint v0, GLuint v1)
 25.5973 +        {
 25.5974 +            if(glUniform2ui_Impl)
 25.5975 +                glUniform2ui_Impl(location, v0, v1);
 25.5976 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5977 +        }
 25.5978 +
 25.5979 +        void OVR::GLEContext::glUniform3ui_Hook(GLint location, GLuint v0, GLuint v1, GLuint v2)
 25.5980 +        {
 25.5981 +            if(glUniform3ui_Impl)
 25.5982 +                glUniform3ui_Impl(location, v0, v1, v2);
 25.5983 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5984 +        }
 25.5985 +
 25.5986 +        void OVR::GLEContext::glUniform4ui_Hook(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3)
 25.5987 +        {
 25.5988 +            if(glUniform4ui_Impl)
 25.5989 +                glUniform4ui_Impl(location, v0, v1, v2, v3);
 25.5990 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5991 +        }
 25.5992 +
 25.5993 +        void OVR::GLEContext::glUniform1uiv_Hook(GLint location, GLsizei count, const GLuint *value)
 25.5994 +        {
 25.5995 +            if(glUniform1uiv_Impl)
 25.5996 +                glUniform1uiv_Impl(location, count, value);
 25.5997 +            PostHook(GLE_CURRENT_FUNCTION);
 25.5998 +        }
 25.5999 +
 25.6000 +        void OVR::GLEContext::glUniform2uiv_Hook(GLint location, GLsizei count, const GLuint *value)
 25.6001 +        {
 25.6002 +            if(glUniform2uiv_Impl)
 25.6003 +                glUniform2uiv_Impl(location, count, value);
 25.6004 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6005 +        }
 25.6006 +
 25.6007 +        void OVR::GLEContext::glUniform3uiv_Hook(GLint location, GLsizei count, const GLuint *value)
 25.6008 +        {
 25.6009 +            if(glUniform3uiv_Impl)
 25.6010 +                glUniform3uiv_Impl(location, count, value);
 25.6011 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6012 +        }
 25.6013 +
 25.6014 +        void OVR::GLEContext::glUniform4uiv_Hook(GLint location, GLsizei count, const GLuint *value)
 25.6015 +        {
 25.6016 +            if(glUniform4uiv_Impl)
 25.6017 +                glUniform4uiv_Impl(location, count, value);
 25.6018 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6019 +        }
 25.6020 +
 25.6021 +        void OVR::GLEContext::glTexParameterIiv_Hook(GLenum target, GLenum pname, const GLint *params)
 25.6022 +        {
 25.6023 +            if(glTexParameterIiv_Impl)
 25.6024 +                glTexParameterIiv_Impl(target, pname, params);
 25.6025 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6026 +        }
 25.6027 +
 25.6028 +        void OVR::GLEContext::glTexParameterIuiv_Hook(GLenum target, GLenum pname, const GLuint *params)
 25.6029 +        {
 25.6030 +            if(glTexParameterIuiv_Impl)
 25.6031 +                glTexParameterIuiv_Impl(target, pname, params);
 25.6032 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6033 +        }
 25.6034 +
 25.6035 +        void OVR::GLEContext::glGetTexParameterIiv_Hook(GLenum target, GLenum pname, GLint *params)
 25.6036 +        {
 25.6037 +            if(glGetTexParameterIiv_Impl)
 25.6038 +                glGetTexParameterIiv_Impl(target, pname, params);
 25.6039 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6040 +        }
 25.6041 +
 25.6042 +        void OVR::GLEContext::glGetTexParameterIuiv_Hook(GLenum target, GLenum pname, GLuint *params)
 25.6043 +        {
 25.6044 +            if(glGetTexParameterIuiv_Impl)
 25.6045 +                glGetTexParameterIuiv_Impl(target, pname, params);
 25.6046 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6047 +        }
 25.6048 +
 25.6049 +        void OVR::GLEContext::glClearBufferiv_Hook(GLenum buffer, GLint drawbuffer, const GLint *value)
 25.6050 +        {
 25.6051 +            if(glClearBufferiv_Impl)
 25.6052 +                glClearBufferiv_Impl(buffer, drawbuffer, value);
 25.6053 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6054 +        }
 25.6055 +
 25.6056 +        void OVR::GLEContext::glClearBufferuiv_Hook(GLenum buffer, GLint drawbuffer, const GLuint *value)
 25.6057 +        {
 25.6058 +            if(glClearBufferuiv_Impl)
 25.6059 +                glClearBufferuiv_Impl(buffer, drawbuffer, value);
 25.6060 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6061 +        }
 25.6062 +
 25.6063 +        void OVR::GLEContext::glClearBufferfv_Hook(GLenum buffer, GLint drawbuffer, const GLfloat *value)
 25.6064 +        {
 25.6065 +            if(glClearBufferfv_Impl)
 25.6066 +                glClearBufferfv_Impl(buffer, drawbuffer, value);
 25.6067 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6068 +        }
 25.6069 +
 25.6070 +        void OVR::GLEContext::glClearBufferfi_Hook(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil)
 25.6071 +        {
 25.6072 +            if(glClearBufferfi_Impl)
 25.6073 +                glClearBufferfi_Impl(buffer, drawbuffer, depth, stencil);
 25.6074 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6075 +        }
 25.6076 +
 25.6077 +        const GLubyte* OVR::GLEContext::glGetStringi_Hook(GLenum name, GLuint index)
 25.6078 +        {
 25.6079 +            const GLubyte* p = NULL;
 25.6080 +            if(glGetStringi_Impl)
 25.6081 +                p = glGetStringi_Impl(name, index);
 25.6082 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6083 +            return p;
 25.6084 +        }
 25.6085 +
 25.6086 +
 25.6087 +        // GL_VERSION_3_1
 25.6088 +        void OVR::GLEContext::glDrawArraysInstanced_Hook(GLenum mode, GLint first, GLsizei count, GLsizei primcount)
 25.6089 +        {
 25.6090 +            if(glDrawArraysInstanced_Impl)
 25.6091 +                glDrawArraysInstanced_Impl(mode, first, count, primcount);
 25.6092 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6093 +        }
 25.6094 +
 25.6095 +        void OVR::GLEContext::glDrawElementsInstanced_Hook(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount)
 25.6096 +        {
 25.6097 +            if(glDrawElementsInstanced_Impl)
 25.6098 +                glDrawElementsInstanced_Impl(mode, count, type, indices, primcount);
 25.6099 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6100 +        }
 25.6101 +
 25.6102 +        void OVR::GLEContext::glTexBuffer_Hook(GLenum target, GLenum internalformat, GLuint buffer)
 25.6103 +        {
 25.6104 +            if(glTexBuffer_Impl)
 25.6105 +                glTexBuffer_Impl(target, internalformat, buffer);
 25.6106 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6107 +        }
 25.6108 +
 25.6109 +        void OVR::GLEContext::glPrimitiveRestartIndex_Hook(GLuint index)
 25.6110 +        {
 25.6111 +            if(glPrimitiveRestartIndex_Impl)
 25.6112 +                glPrimitiveRestartIndex_Impl(index);
 25.6113 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6114 +        }
 25.6115 +
 25.6116 +
 25.6117 +        // GL_VERSION_3_2
 25.6118 +        void OVR::GLEContext::glGetInteger64i_v_Hook(GLenum target, GLuint index, GLint64 *data)
 25.6119 +        {
 25.6120 +            if(glGetInteger64i_v_Impl)
 25.6121 +                glGetInteger64i_v_Impl(target, index, data);
 25.6122 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6123 +        }
 25.6124 +
 25.6125 +        void OVR::GLEContext::glGetBufferParameteri64v_Hook(GLenum target, GLenum pname, GLint64 *params)
 25.6126 +        {
 25.6127 +            if(glGetBufferParameteri64v_Impl)
 25.6128 +                glGetBufferParameteri64v_Impl(target, pname, params);
 25.6129 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6130 +        }
 25.6131 +
 25.6132 +        void OVR::GLEContext::glFramebufferTexture_Hook(GLenum target, GLenum attachment, GLuint texture, GLint level)
 25.6133 +        {
 25.6134 +            if(glFramebufferTexture_Impl)
 25.6135 +                glFramebufferTexture_Impl(target, attachment, texture, level);
 25.6136 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6137 +        }
 25.6138 +
 25.6139 +
 25.6140 +        // GL_VERSION_3_3
 25.6141 +        void OVR::GLEContext::glVertexAttribDivisor_Hook(GLuint index, GLuint divisor)
 25.6142 +        {
 25.6143 +            if(glVertexAttribDivisor_Impl)
 25.6144 +                glVertexAttribDivisor_Impl(index, divisor);
 25.6145 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6146 +        }
 25.6147 +
 25.6148 +
 25.6149 +        // GL_VERSION_4_0
 25.6150 +        void OVR::GLEContext::glMinSampleShading_Hook(GLclampf value)
 25.6151 +        {
 25.6152 +            if(glMinSampleShading_Impl)
 25.6153 +                glMinSampleShading_Impl(value);
 25.6154 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6155 +        }
 25.6156 +
 25.6157 +        void OVR::GLEContext::glBlendEquationi_Hook(GLuint buf, GLenum mode)
 25.6158 +        {
 25.6159 +            if(glBlendEquationi_Impl)
 25.6160 +                glBlendEquationi_Impl(buf, mode);
 25.6161 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6162 +        }
 25.6163 +
 25.6164 +        void OVR::GLEContext::glBlendEquationSeparatei_Hook(GLuint buf, GLenum modeRGB, GLenum modeAlpha)
 25.6165 +        {
 25.6166 +            if(glBlendEquationSeparatei_Impl)
 25.6167 +                glBlendEquationSeparatei_Impl(buf, modeRGB, modeAlpha);
 25.6168 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6169 +        }
 25.6170 +
 25.6171 +        void OVR::GLEContext::glBlendFunci_Hook(GLuint buf, GLenum src, GLenum dst)
 25.6172 +        {
 25.6173 +            if(glBlendFunci_Impl)
 25.6174 +                glBlendFunci_Impl(buf, src, dst);
 25.6175 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6176 +        }
 25.6177 +
 25.6178 +        void OVR::GLEContext::glBlendFuncSeparatei_Hook(GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha)
 25.6179 +        {
 25.6180 +            if(glBlendFuncSeparatei_Impl)
 25.6181 +                glBlendFuncSeparatei_Impl(buf, srcRGB, dstRGB, srcAlpha, dstAlpha);
 25.6182 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6183 +        }
 25.6184 +
 25.6185 +
 25.6186 +        // GL_AMD_debug_output
 25.6187 +        void OVR::GLEContext::glDebugMessageEnableAMD_Hook(GLenum category, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled)
 25.6188 +        {
 25.6189 +            if(glDebugMessageEnableAMD_Impl)
 25.6190 +                glDebugMessageEnableAMD_Impl(category, severity, count, ids, enabled);
 25.6191 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6192 +        }
 25.6193 +
 25.6194 +        void OVR::GLEContext::glDebugMessageInsertAMD_Hook(GLenum category, GLenum severity, GLuint id, GLsizei length, const GLchar *buf)
 25.6195 +        {
 25.6196 +            if(glDebugMessageInsertAMD_Impl)
 25.6197 +                glDebugMessageInsertAMD_Impl(category, severity, id, length, buf);
 25.6198 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6199 +        }
 25.6200 +
 25.6201 +        void OVR::GLEContext::glDebugMessageCallbackAMD_Hook(GLDEBUGPROCAMD callback, GLvoid *userParam)
 25.6202 +        {
 25.6203 +            if(glDebugMessageCallbackAMD_Impl)
 25.6204 +                glDebugMessageCallbackAMD_Impl(callback, userParam);
 25.6205 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6206 +        }
 25.6207 +
 25.6208 +        GLuint OVR::GLEContext::glGetDebugMessageLogAMD_Hook(GLuint count, GLsizei bufsize, GLenum *categories, GLuint *severities, GLuint *ids, GLsizei *lengths, GLchar *message)
 25.6209 +        {
 25.6210 +            GLuint u = 0;
 25.6211 +            if(glGetDebugMessageLogAMD_Impl)
 25.6212 +                u = glGetDebugMessageLogAMD_Impl(count, bufsize, categories, severities, ids, lengths, message);
 25.6213 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6214 +            return u;
 25.6215 +        }
 25.6216 +
 25.6217 +
 25.6218 +    #if defined(GLE_CGL_ENABLED)
 25.6219 +        // GL_APPLE_element_array
 25.6220 +        void OVR::GLEContext::glElementPointerAPPLE_Hook(GLenum type, const GLvoid *pointer)
 25.6221 +        {
 25.6222 +            if(glElementPointerAPPLE_Impl)
 25.6223 +                glElementPointerAPPLE_Impl(type, pointer);
 25.6224 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6225 +        }
 25.6226 +
 25.6227 +        void OVR::GLEContext::glDrawElementArrayAPPLE_Hook(GLenum mode, GLint first, GLsizei count)
 25.6228 +        {
 25.6229 +            if(glDrawElementArrayAPPLE_Impl)
 25.6230 +                glDrawElementArrayAPPLE_Impl(mode, first, count);
 25.6231 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6232 +        }
 25.6233 +
 25.6234 +        void OVR::GLEContext::glDrawRangeElementArrayAPPLE_Hook(GLenum mode, GLuint start, GLuint end, GLint first, GLsizei count)
 25.6235 +        {
 25.6236 +            if(glDrawRangeElementArrayAPPLE_Impl)
 25.6237 +                glDrawRangeElementArrayAPPLE_Impl(mode, start, end, first, count);
 25.6238 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6239 +        }
 25.6240 +
 25.6241 +        void OVR::GLEContext::glMultiDrawElementArrayAPPLE_Hook(GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount)
 25.6242 +        {
 25.6243 +            if(glMultiDrawElementArrayAPPLE_Impl)
 25.6244 +                glMultiDrawElementArrayAPPLE_Impl(mode, first, count, primcount);
 25.6245 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6246 +        }
 25.6247 +
 25.6248 +        void OVR::GLEContext::glMultiDrawRangeElementArrayAPPLE_Hook(GLenum mode, GLuint start, GLuint end, const GLint *first, const GLsizei *count, GLsizei primcount)
 25.6249 +        {
 25.6250 +            if(glMultiDrawRangeElementArrayAPPLE_Impl)
 25.6251 +                glMultiDrawRangeElementArrayAPPLE_Impl(mode, start, end, first, count, primcount);
 25.6252 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6253 +        }
 25.6254 +
 25.6255 +
 25.6256 +        // GL_APPLE_fence
 25.6257 +        void OVR::GLEContext::glGenFencesAPPLE_Hook(GLsizei n, GLuint *fences)
 25.6258 +        {
 25.6259 +            if(glGenFencesAPPLE_Impl)
 25.6260 +                glGenFencesAPPLE_Impl(n, fences);
 25.6261 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6262 +        }
 25.6263 +
 25.6264 +        void OVR::GLEContext::glDeleteFencesAPPLE_Hook(GLsizei n, const GLuint *fences)
 25.6265 +        {
 25.6266 +            if(glDeleteFencesAPPLE_Impl)
 25.6267 +                glDeleteFencesAPPLE_Impl(n, fences);
 25.6268 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6269 +        }
 25.6270 +
 25.6271 +        void OVR::GLEContext::glSetFenceAPPLE_Hook(GLuint fence)
 25.6272 +        {
 25.6273 +            if(glSetFenceAPPLE_Impl)
 25.6274 +                glSetFenceAPPLE_Impl(fence);
 25.6275 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6276 +        }
 25.6277 +
 25.6278 +        GLboolean OVR::GLEContext::glIsFenceAPPLE_Hook(GLuint fence)
 25.6279 +        {
 25.6280 +            GLboolean b = GL_FALSE;
 25.6281 +            if(glIsFenceAPPLE_Impl)
 25.6282 +                b = glIsFenceAPPLE_Impl(fence);
 25.6283 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6284 +            return b;
 25.6285 +        }
 25.6286 +
 25.6287 +        GLboolean OVR::GLEContext::glTestFenceAPPLE_Hook(GLuint fence)
 25.6288 +        {
 25.6289 +            GLboolean b = GL_FALSE;
 25.6290 +            if(glTestFenceAPPLE_Impl)
 25.6291 +                b = glTestFenceAPPLE_Impl(fence);
 25.6292 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6293 +            return b;
 25.6294 +        }
 25.6295 +
 25.6296 +        void OVR::GLEContext::glFinishFenceAPPLE_Hook(GLuint fence)
 25.6297 +        {
 25.6298 +            if(glFinishFenceAPPLE_Impl)
 25.6299 +                glFinishFenceAPPLE_Impl(fence);
 25.6300 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6301 +        }
 25.6302 +
 25.6303 +        GLboolean OVR::GLEContext::glTestObjectAPPLE_Hook(GLenum object, GLuint name)
 25.6304 +        {
 25.6305 +            GLboolean b = GL_FALSE;
 25.6306 +            if(glTestObjectAPPLE_Impl)
 25.6307 +                b = glTestObjectAPPLE_Impl(object, name);
 25.6308 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6309 +            return b;
 25.6310 +        }
 25.6311 +
 25.6312 +        void OVR::GLEContext::glFinishObjectAPPLE_Hook(GLenum object, GLint name)
 25.6313 +        {
 25.6314 +            if(glFinishObjectAPPLE_Impl)
 25.6315 +                glFinishObjectAPPLE_Impl(object, name);
 25.6316 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6317 +        }
 25.6318 +
 25.6319 +
 25.6320 +        // GL_APPLE_flush_buffer_range
 25.6321 +        void OVR::GLEContext::glBufferParameteriAPPLE_Hook(GLenum target, GLenum pname, GLint param)
 25.6322 +        {
 25.6323 +            if(glBufferParameteriAPPLE_Impl)
 25.6324 +                glBufferParameteriAPPLE_Impl(target, pname, param);
 25.6325 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6326 +        }
 25.6327 +
 25.6328 +        void OVR::GLEContext::glFlushMappedBufferRangeAPPLE_Hook(GLenum target, GLintptr offset, GLsizeiptr size)
 25.6329 +        {
 25.6330 +            if(glFlushMappedBufferRangeAPPLE_Impl)
 25.6331 +                glFlushMappedBufferRangeAPPLE_Impl(target, offset, size);
 25.6332 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6333 +        }
 25.6334 +
 25.6335 +
 25.6336 +        // GL_APPLE_object_purgeable
 25.6337 +        GLenum OVR::GLEContext::glObjectPurgeableAPPLE_Hook(GLenum objectType, GLuint name, GLenum option)
 25.6338 +        {
 25.6339 +            GLenum e = 0;
 25.6340 +            if(glObjectPurgeableAPPLE_Impl)
 25.6341 +                e = glObjectPurgeableAPPLE_Impl(objectType, name, option);
 25.6342 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6343 +            return e;
 25.6344 +        }
 25.6345 +
 25.6346 +        GLenum OVR::GLEContext::glObjectUnpurgeableAPPLE_Hook(GLenum objectType, GLuint name, GLenum option)
 25.6347 +        {
 25.6348 +            GLenum e = 0;
 25.6349 +            if(glObjectUnpurgeableAPPLE_Impl)
 25.6350 +                e =glObjectUnpurgeableAPPLE_Impl(objectType, name, option);
 25.6351 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6352 +            return e;
 25.6353 +        }
 25.6354 +
 25.6355 +        void OVR::GLEContext::glGetObjectParameterivAPPLE_Hook(GLenum objectType, GLuint name, GLenum pname, GLint *params)
 25.6356 +        {
 25.6357 +            if(glGetObjectParameterivAPPLE_Impl)
 25.6358 +                glGetObjectParameterivAPPLE_Impl(objectType, name, pname, params);
 25.6359 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6360 +        }
 25.6361 +
 25.6362 +
 25.6363 +        // GL_APPLE_texture_range
 25.6364 +        void OVR::GLEContext::glTextureRangeAPPLE_Hook(GLenum target, GLsizei length, const GLvoid *pointer)
 25.6365 +        {
 25.6366 +            if(glTextureRangeAPPLE_Impl)
 25.6367 +                glTextureRangeAPPLE_Impl(target, length, pointer);
 25.6368 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6369 +        }
 25.6370 +
 25.6371 +        void OVR::GLEContext::glGetTexParameterPointervAPPLE_Hook(GLenum target, GLenum pname, GLvoid **params)
 25.6372 +        {
 25.6373 +            if(glGetTexParameterPointervAPPLE_Impl)
 25.6374 +                glGetTexParameterPointervAPPLE_Impl(target, pname, params);
 25.6375 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6376 +        }
 25.6377 +
 25.6378 +
 25.6379 +        // GL_APPLE_vertex_array_object
 25.6380 +        void OVR::GLEContext::glBindVertexArrayAPPLE_Hook(GLuint array)
 25.6381 +        {
 25.6382 +            if(glBindVertexArrayAPPLE_Impl)
 25.6383 +                glBindVertexArrayAPPLE_Impl(array);
 25.6384 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6385 +        }
 25.6386 +
 25.6387 +        void OVR::GLEContext::glDeleteVertexArraysAPPLE_Hook(GLsizei n, const GLuint *arrays)
 25.6388 +        {
 25.6389 +            if(glDeleteVertexArraysAPPLE_Impl)
 25.6390 +                glDeleteVertexArraysAPPLE_Impl(n, arrays);
 25.6391 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6392 +        }
 25.6393 +
 25.6394 +        void OVR::GLEContext::glGenVertexArraysAPPLE_Hook(GLsizei n, GLuint *arrays)
 25.6395 +        {
 25.6396 +            if(glGenVertexArraysAPPLE_Impl)
 25.6397 +                glGenVertexArraysAPPLE_Impl(n, arrays);
 25.6398 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6399 +        }
 25.6400 +
 25.6401 +        GLboolean OVR::GLEContext::glIsVertexArrayAPPLE_Hook(GLuint array)
 25.6402 +        {
 25.6403 +            GLboolean b = GL_FALSE;
 25.6404 +            if(glIsVertexArrayAPPLE_Impl)
 25.6405 +                b = glIsVertexArrayAPPLE_Impl(array);
 25.6406 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6407 +            return b;
 25.6408 +        }
 25.6409 +
 25.6410 +
 25.6411 +        // GL_APPLE_vertex_array_range
 25.6412 +        void OVR::GLEContext::glVertexArrayRangeAPPLE_Hook(GLsizei length, GLvoid *pointer)
 25.6413 +        {
 25.6414 +            if(glVertexArrayRangeAPPLE_Impl)
 25.6415 +                glVertexArrayRangeAPPLE_Impl(length, pointer);
 25.6416 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6417 +        }
 25.6418 +
 25.6419 +        void OVR::GLEContext::glFlushVertexArrayRangeAPPLE_Hook(GLsizei length, GLvoid *pointer)
 25.6420 +        {
 25.6421 +            if(glFlushVertexArrayRangeAPPLE_Impl)
 25.6422 +                glFlushVertexArrayRangeAPPLE_Impl(length, pointer);
 25.6423 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6424 +        }
 25.6425 +
 25.6426 +        void OVR::GLEContext::glVertexArrayParameteriAPPLE_Hook(GLenum pname, GLint param)
 25.6427 +        {
 25.6428 +            if(glVertexArrayParameteriAPPLE_Impl)
 25.6429 +                glVertexArrayParameteriAPPLE_Impl(pname, param);
 25.6430 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6431 +        }
 25.6432 +
 25.6433 +
 25.6434 +        // GL_APPLE_vertex_program_evaluators
 25.6435 +        void OVR::GLEContext::glEnableVertexAttribAPPLE_Hook(GLuint index, GLenum pname)
 25.6436 +        {
 25.6437 +            if(glEnableVertexAttribAPPLE_Impl)
 25.6438 +                glEnableVertexAttribAPPLE_Impl(index, pname);
 25.6439 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6440 +        }
 25.6441 +
 25.6442 +        void OVR::GLEContext::glDisableVertexAttribAPPLE_Hook(GLuint index, GLenum pname)
 25.6443 +        {
 25.6444 +            if(glDisableVertexAttribAPPLE_Impl)
 25.6445 +                glDisableVertexAttribAPPLE_Impl(index, pname);
 25.6446 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6447 +        }
 25.6448 +
 25.6449 +        GLboolean OVR::GLEContext::glIsVertexAttribEnabledAPPLE_Hook(GLuint index, GLenum pname)
 25.6450 +        {
 25.6451 +            GLboolean b = GL_FALSE;
 25.6452 +            if(glIsVertexAttribEnabledAPPLE_Impl)
 25.6453 +                b = glIsVertexAttribEnabledAPPLE_Impl(index, pname);
 25.6454 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6455 +            return b;
 25.6456 +        }
 25.6457 +
 25.6458 +        void OVR::GLEContext::glMapVertexAttrib1dAPPLE_Hook(GLuint index, GLuint size, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points)
 25.6459 +        {
 25.6460 +            if(glMapVertexAttrib1dAPPLE_Impl)
 25.6461 +                glMapVertexAttrib1dAPPLE_Impl(index, size, u1, u2, stride, order, points);
 25.6462 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6463 +        }
 25.6464 +
 25.6465 +        void OVR::GLEContext::glMapVertexAttrib1fAPPLE_Hook(GLuint index, GLuint size, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points)
 25.6466 +        {
 25.6467 +            if(glMapVertexAttrib1fAPPLE_Impl)
 25.6468 +                glMapVertexAttrib1fAPPLE_Impl(index, size, u1, u2, stride, order, points);
 25.6469 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6470 +        }
 25.6471 +
 25.6472 +        void OVR::GLEContext::glMapVertexAttrib2dAPPLE_Hook(GLuint index, GLuint size, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points)
 25.6473 +        {
 25.6474 +            if(glMapVertexAttrib2dAPPLE_Impl)
 25.6475 +                glMapVertexAttrib2dAPPLE_Impl(index, size, u1, u2, ustride, uorder, v1, v2, vstride, vorder, points);
 25.6476 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6477 +        }
 25.6478 +
 25.6479 +        void OVR::GLEContext::glMapVertexAttrib2fAPPLE_Hook(GLuint index, GLuint size, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points)
 25.6480 +        {
 25.6481 +            if(glMapVertexAttrib2fAPPLE_Impl)
 25.6482 +                glMapVertexAttrib2fAPPLE_Impl(index, size, u1, u2, ustride, uorder, v1, v2, vstride, vorder, points);
 25.6483 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6484 +        }
 25.6485 +    #endif // GLE_CGL_ENABLED
 25.6486 +
 25.6487 +
 25.6488 +        // GL_ARB_debug_output
 25.6489 +        void OVR::GLEContext::glDebugMessageControlARB_Hook(GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled)
 25.6490 +        {
 25.6491 +            if(glDebugMessageControlARB_Impl)
 25.6492 +                glDebugMessageControlARB_Impl(source, type, severity, count, ids, enabled);
 25.6493 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6494 +        }
 25.6495 +
 25.6496 +        void OVR::GLEContext::glDebugMessageInsertARB_Hook(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf)
 25.6497 +        {
 25.6498 +            if(glDebugMessageInsertARB_Impl)
 25.6499 +                glDebugMessageInsertARB_Impl(source, type, id, severity, length, buf);
 25.6500 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6501 +        }
 25.6502 +
 25.6503 +        void OVR::GLEContext::glDebugMessageCallbackARB_Hook(GLDEBUGPROCARB callback, const GLvoid *userParam)
 25.6504 +        {
 25.6505 +            if(glDebugMessageCallbackARB_Impl)
 25.6506 +                glDebugMessageCallbackARB_Impl(callback, userParam);
 25.6507 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6508 +        }
 25.6509 +
 25.6510 +        GLuint OVR::GLEContext::glGetDebugMessageLogARB_Hook(GLuint count, GLsizei bufsize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog)
 25.6511 +        {
 25.6512 +            GLuint u = 0;
 25.6513 +            if(glGetDebugMessageLogARB_Impl)
 25.6514 +                u = glGetDebugMessageLogARB_Impl(count, bufsize, sources, types, ids, severities, lengths, messageLog);
 25.6515 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6516 +            return u;
 25.6517 +        }
 25.6518 +
 25.6519 +
 25.6520 +        // GL_ARB_ES2_compatibility
 25.6521 +        void OVR::GLEContext::glReleaseShaderCompiler_Hook()
 25.6522 +        {
 25.6523 +            if(glReleaseShaderCompiler_Impl)
 25.6524 +                glReleaseShaderCompiler_Impl();
 25.6525 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6526 +        }
 25.6527 +
 25.6528 +        void OVR::GLEContext::glShaderBinary_Hook(GLsizei count, const GLuint *shaders, GLenum binaryformat, const GLvoid *binary, GLsizei length)
 25.6529 +        {
 25.6530 +            if(glShaderBinary_Impl)
 25.6531 +                glShaderBinary_Impl(count, shaders, binaryformat, binary, length);
 25.6532 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6533 +        }
 25.6534 +
 25.6535 +        void OVR::GLEContext::glGetShaderPrecisionFormat_Hook(GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision)
 25.6536 +        {
 25.6537 +            if(glGetShaderPrecisionFormat_Impl)
 25.6538 +                glGetShaderPrecisionFormat_Impl(shadertype, precisiontype, range, precision);
 25.6539 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6540 +        }
 25.6541 +
 25.6542 +        void OVR::GLEContext::glDepthRangef_Hook(GLclampf n, GLclampf f)
 25.6543 +        {
 25.6544 +            if(glDepthRangef_Impl)
 25.6545 +                glDepthRangef_Impl(n, f);
 25.6546 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6547 +        }
 25.6548 +
 25.6549 +        void OVR::GLEContext::glClearDepthf_Hook(GLclampf d)
 25.6550 +        {
 25.6551 +            if(glClearDepthf_Impl)
 25.6552 +                glClearDepthf_Impl(d);
 25.6553 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6554 +        }
 25.6555 +
 25.6556 +
 25.6557 +        // GL_ARB_framebuffer_object
 25.6558 +        GLboolean OVR::GLEContext::glIsRenderbuffer_Hook(GLuint renderbuffer)
 25.6559 +        {
 25.6560 +            GLboolean b = GL_FALSE;
 25.6561 +            if(glIsRenderbuffer_Impl)
 25.6562 +                b = glIsRenderbuffer_Impl(renderbuffer);
 25.6563 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6564 +            return b;
 25.6565 +        }
 25.6566 +
 25.6567 +        void OVR::GLEContext::glBindRenderbuffer_Hook(GLenum target, GLuint renderbuffer)
 25.6568 +        {
 25.6569 +            if(glBindRenderbuffer_Impl)
 25.6570 +                glBindRenderbuffer_Impl(target, renderbuffer);
 25.6571 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6572 +        }
 25.6573 +
 25.6574 +        void OVR::GLEContext::glDeleteRenderbuffers_Hook(GLsizei n, const GLuint *renderbuffers)
 25.6575 +        {
 25.6576 +            if(glDeleteRenderbuffers_Impl)
 25.6577 +                glDeleteRenderbuffers_Impl(n, renderbuffers);
 25.6578 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6579 +        }
 25.6580 +
 25.6581 +        void OVR::GLEContext::glGenRenderbuffers_Hook(GLsizei n, GLuint *renderbuffers)
 25.6582 +        {
 25.6583 +            if(glGenRenderbuffers_Impl)
 25.6584 +                glGenRenderbuffers_Impl(n, renderbuffers);
 25.6585 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6586 +        }
 25.6587 +
 25.6588 +        void OVR::GLEContext::glRenderbufferStorage_Hook(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
 25.6589 +        {
 25.6590 +            if(glRenderbufferStorage_Impl)
 25.6591 +                glRenderbufferStorage_Impl(target, internalformat, width, height);
 25.6592 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6593 +        }
 25.6594 +
 25.6595 +        void OVR::GLEContext::glGetRenderbufferParameteriv_Hook(GLenum target, GLenum pname, GLint *params)
 25.6596 +        {
 25.6597 +            if(glGetRenderbufferParameteriv_Impl)
 25.6598 +                glGetRenderbufferParameteriv_Impl(target, pname, params);
 25.6599 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6600 +        }
 25.6601 +
 25.6602 +        GLboolean OVR::GLEContext::glIsFramebuffer_Hook(GLuint framebuffer)
 25.6603 +        {
 25.6604 +            GLboolean b = GL_FALSE;
 25.6605 +            if(glIsFramebuffer_Impl)
 25.6606 +                b = glIsFramebuffer_Impl(framebuffer);
 25.6607 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6608 +            return b;
 25.6609 +        }
 25.6610 +
 25.6611 +        void OVR::GLEContext::glBindFramebuffer_Hook(GLenum target, GLuint framebuffer)
 25.6612 +        {
 25.6613 +            if(glBindFramebuffer_Impl)
 25.6614 +                glBindFramebuffer_Impl(target, framebuffer);
 25.6615 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6616 +        }
 25.6617 +
 25.6618 +        void OVR::GLEContext::glDeleteFramebuffers_Hook(GLsizei n, const GLuint *framebuffers)
 25.6619 +        {
 25.6620 +            if(glDeleteFramebuffers_Impl)
 25.6621 +                glDeleteFramebuffers_Impl(n, framebuffers);
 25.6622 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6623 +        }
 25.6624 +
 25.6625 +        void OVR::GLEContext::glGenFramebuffers_Hook(GLsizei n, GLuint *framebuffers)
 25.6626 +        {
 25.6627 +            if(glGenFramebuffers_Impl)
 25.6628 +                glGenFramebuffers_Impl(n, framebuffers);
 25.6629 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6630 +        }
 25.6631 +
 25.6632 +        GLenum OVR::GLEContext::glCheckFramebufferStatus_Hook(GLenum target)
 25.6633 +        {
 25.6634 +            GLenum e = 0;
 25.6635 +            if(glCheckFramebufferStatus_Impl)
 25.6636 +                e = glCheckFramebufferStatus_Impl(target);
 25.6637 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6638 +            return e;
 25.6639 +        }
 25.6640 +
 25.6641 +        void OVR::GLEContext::glFramebufferTexture1D_Hook(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
 25.6642 +        {
 25.6643 +            if(glFramebufferTexture1D_Impl)
 25.6644 +                glFramebufferTexture1D_Impl(target, attachment, textarget, texture, level);
 25.6645 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6646 +        }
 25.6647 +
 25.6648 +        void OVR::GLEContext::glFramebufferTexture2D_Hook(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
 25.6649 +        {
 25.6650 +            if(glFramebufferTexture2D_Impl)
 25.6651 +                glFramebufferTexture2D_Impl(target, attachment, textarget, texture, level);
 25.6652 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6653 +        }
 25.6654 +
 25.6655 +        void OVR::GLEContext::glFramebufferTexture3D_Hook(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset)
 25.6656 +        {
 25.6657 +            if(glFramebufferTexture3D_Impl)
 25.6658 +                glFramebufferTexture3D_Impl(target, attachment, textarget, texture, level, zoffset);
 25.6659 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6660 +        }
 25.6661 +
 25.6662 +        void OVR::GLEContext::glFramebufferRenderbuffer_Hook(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
 25.6663 +        {
 25.6664 +            if(glFramebufferRenderbuffer_Impl)
 25.6665 +                glFramebufferRenderbuffer_Impl(target, attachment, renderbuffertarget, renderbuffer);
 25.6666 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6667 +        }
 25.6668 +
 25.6669 +        void OVR::GLEContext::glGetFramebufferAttachmentParameteriv_Hook(GLenum target, GLenum attachment, GLenum pname, GLint *params)
 25.6670 +        {
 25.6671 +            if(glGetFramebufferAttachmentParameteriv_Impl)
 25.6672 +                glGetFramebufferAttachmentParameteriv_Impl(target, attachment, pname, params);
 25.6673 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6674 +        }
 25.6675 +
 25.6676 +        void OVR::GLEContext::glGenerateMipmap_Hook(GLenum target)
 25.6677 +        {
 25.6678 +            if(glGenerateMipmap_Impl)
 25.6679 +                glGenerateMipmap_Impl(target);
 25.6680 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6681 +        }
 25.6682 +
 25.6683 +        void OVR::GLEContext::glBlitFramebuffer_Hook(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter)
 25.6684 +        {
 25.6685 +            if(glBlitFramebuffer_Impl)
 25.6686 +                glBlitFramebuffer_Impl(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
 25.6687 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6688 +        }
 25.6689 +
 25.6690 +        void OVR::GLEContext::glRenderbufferStorageMultisample_Hook(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
 25.6691 +        {
 25.6692 +            if(glRenderbufferStorageMultisample_Impl)
 25.6693 +                glRenderbufferStorageMultisample_Impl(target, samples, internalformat, width, height);
 25.6694 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6695 +        }
 25.6696 +
 25.6697 +        void OVR::GLEContext::glFramebufferTextureLayer_Hook(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer)
 25.6698 +        {
 25.6699 +            if(glFramebufferTextureLayer_Impl)
 25.6700 +                glFramebufferTextureLayer_Impl(target, attachment, texture, level, layer);
 25.6701 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6702 +        }
 25.6703 +
 25.6704 +
 25.6705 +        // GL_ARB_texture_multisample
 25.6706 +        void OVR::GLEContext::glTexImage2DMultisample_Hook(GLenum target, GLsizei samples, GLint internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations)
 25.6707 +        {
 25.6708 +            if(glTexImage2DMultisample_Impl)
 25.6709 +                glTexImage2DMultisample_Impl(target, samples, internalformat, width, height, fixedsamplelocations);
 25.6710 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6711 +        }
 25.6712 +
 25.6713 +        void OVR::GLEContext::glTexImage3DMultisample_Hook(GLenum target, GLsizei samples, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations)
 25.6714 +        {
 25.6715 +            if(glTexImage3DMultisample_Impl)
 25.6716 +                glTexImage3DMultisample_Impl(target, samples, internalformat, width, height, depth, fixedsamplelocations);
 25.6717 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6718 +        }
 25.6719 +
 25.6720 +        void OVR::GLEContext::glGetMultisamplefv_Hook(GLenum pname, GLuint index, GLfloat *val)
 25.6721 +        {
 25.6722 +            if(glGetMultisamplefv_Impl)
 25.6723 +                glGetMultisamplefv_Impl(pname, index, val);
 25.6724 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6725 +        }
 25.6726 +
 25.6727 +        void OVR::GLEContext::glSampleMaski_Hook(GLuint index, GLbitfield mask)
 25.6728 +        {
 25.6729 +            if(glSampleMaski_Impl)
 25.6730 +                glSampleMaski_Impl(index, mask);
 25.6731 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6732 +        }
 25.6733 +
 25.6734 +
 25.6735 +        // GL_ARB_timer_query
 25.6736 +        void OVR::GLEContext::glQueryCounter_Hook(GLuint id, GLenum target)
 25.6737 +        {
 25.6738 +            if(glQueryCounter_Impl)
 25.6739 +                glQueryCounter_Impl(id, target);
 25.6740 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6741 +        }
 25.6742 +
 25.6743 +        void OVR::GLEContext::glGetQueryObjecti64v_Hook(GLuint id, GLenum pname, GLint64 *params)
 25.6744 +        {
 25.6745 +            if(glGetQueryObjecti64v_Impl)
 25.6746 +                glGetQueryObjecti64v_Impl(id, pname, params);
 25.6747 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6748 +        }
 25.6749 +
 25.6750 +        void OVR::GLEContext::glGetQueryObjectui64v_Hook(GLuint id, GLenum pname, GLuint64 *params)
 25.6751 +        {
 25.6752 +            if(glGetQueryObjectui64v_Impl)
 25.6753 +                glGetQueryObjectui64v_Impl(id, pname, params);
 25.6754 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6755 +        }
 25.6756 +
 25.6757 +
 25.6758 +        // GL_ARB_vertex_array_object
 25.6759 +        void OVR::GLEContext::glBindVertexArray_Hook(GLuint array)
 25.6760 +        {
 25.6761 +            if(glBindVertexArray_Impl)
 25.6762 +                glBindVertexArray_Impl(array);
 25.6763 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6764 +        }
 25.6765 +
 25.6766 +        void OVR::GLEContext::glDeleteVertexArrays_Hook(GLsizei n, const GLuint *arrays)
 25.6767 +        {
 25.6768 +            if(glDeleteVertexArrays_Impl)
 25.6769 +                glDeleteVertexArrays_Impl(n, arrays);
 25.6770 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6771 +        }
 25.6772 +
 25.6773 +        void OVR::GLEContext::glGenVertexArrays_Hook(GLsizei n, GLuint *arrays)
 25.6774 +        {
 25.6775 +            if(glGenVertexArrays_Impl)
 25.6776 +                glGenVertexArrays_Impl(n, arrays);
 25.6777 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6778 +        }
 25.6779 +
 25.6780 +        GLboolean OVR::GLEContext::glIsVertexArray_Hook(GLuint array)
 25.6781 +        {
 25.6782 +            GLboolean b = GL_FALSE;
 25.6783 +            if(glIsVertexArray_Impl)
 25.6784 +                b = glIsVertexArray_Impl(array);
 25.6785 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6786 +            return b;
 25.6787 +        }
 25.6788 +
 25.6789 +
 25.6790 +        // GL_EXT_draw_buffers2
 25.6791 +        void OVR::GLEContext::glColorMaskIndexedEXT_Hook(GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a)
 25.6792 +        {
 25.6793 +            if(glColorMaskIndexedEXT_Impl)
 25.6794 +                glColorMaskIndexedEXT_Impl(index, r, g, b, a);
 25.6795 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6796 +        }
 25.6797 +
 25.6798 +        void OVR::GLEContext::glGetBooleanIndexedvEXT_Hook(GLenum target, GLuint index, GLboolean *data)
 25.6799 +        {
 25.6800 +            if(glGetBooleanIndexedvEXT_Impl)
 25.6801 +                glGetBooleanIndexedvEXT_Impl(target, index, data);
 25.6802 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6803 +        }
 25.6804 +
 25.6805 +        void OVR::GLEContext::glGetIntegerIndexedvEXT_Hook(GLenum target, GLuint index, GLint *data)
 25.6806 +        {
 25.6807 +            if(glGetIntegerIndexedvEXT_Impl)
 25.6808 +                glGetIntegerIndexedvEXT_Impl(target, index, data);
 25.6809 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6810 +        }
 25.6811 +
 25.6812 +        void OVR::GLEContext::glEnableIndexedEXT_Hook(GLenum target, GLuint index)
 25.6813 +        {
 25.6814 +            if(glEnableIndexedEXT_Impl)
 25.6815 +                glEnableIndexedEXT_Impl(target, index);
 25.6816 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6817 +        }
 25.6818 +
 25.6819 +        void OVR::GLEContext::glDisableIndexedEXT_Hook(GLenum target, GLuint index)
 25.6820 +        {
 25.6821 +            if(glDisableIndexedEXT_Impl)
 25.6822 +                glDisableIndexedEXT_Impl(target, index);
 25.6823 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6824 +        }
 25.6825 +
 25.6826 +        GLboolean OVR::GLEContext::glIsEnabledIndexedEXT_Hook(GLenum target, GLuint index)
 25.6827 +        {
 25.6828 +            GLboolean b = GL_FALSE;
 25.6829 +            if(glIsEnabledIndexedEXT_Impl)
 25.6830 +                b = glIsEnabledIndexedEXT_Impl(target, index);
 25.6831 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6832 +            return b;
 25.6833 +        }
 25.6834 +
 25.6835 +
 25.6836 +        // GL_KHR_debug
 25.6837 +        void OVR::GLEContext::glDebugMessageControl_Hook(GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint* ids, GLboolean enabled)
 25.6838 +        {
 25.6839 +            if(glDebugMessageControl_Impl)
 25.6840 +                glDebugMessageControl_Impl(source, type, severity, count, ids, enabled);
 25.6841 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6842 +        }
 25.6843 +
 25.6844 +        void OVR::GLEContext::glDebugMessageInsert_Hook(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const char* buf)
 25.6845 +        {
 25.6846 +            if(glDebugMessageInsert_Impl)
 25.6847 +                glDebugMessageInsert_Impl(source, type, id, severity, length, buf);
 25.6848 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6849 +        }
 25.6850 +
 25.6851 +        void OVR::GLEContext::glDebugMessageCallback_Hook(GLDEBUGPROC callback, const void* userParam)
 25.6852 +        {
 25.6853 +            if(glDebugMessageCallback_Impl)
 25.6854 +                glDebugMessageCallback_Impl(callback, userParam);
 25.6855 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6856 +        }
 25.6857 +
 25.6858 +        GLuint OVR::GLEContext::glGetDebugMessageLog_Hook(GLuint count, GLsizei bufSize, GLenum* sources, GLenum* types, GLuint* ids, GLenum* severities, GLsizei* lengths,  char* messageLog)
 25.6859 +        {
 25.6860 +            GLuint u = 0;
 25.6861 +            if(glGetDebugMessageLog_Impl)
 25.6862 +                u = glGetDebugMessageLog_Impl(count, bufSize, sources, types, ids, severities, lengths, messageLog);
 25.6863 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6864 +            return u;
 25.6865 +        }
 25.6866 +
 25.6867 +        void OVR::GLEContext::glPushDebugGroup_Hook(GLenum source, GLuint id, GLsizei length, const char * message)
 25.6868 +        {
 25.6869 +            if(glPushDebugGroup_Impl)
 25.6870 +                glPushDebugGroup_Impl(source, id, length,  message);
 25.6871 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6872 +        }
 25.6873 +
 25.6874 +        void OVR::GLEContext::glPopDebugGroup_Hook()
 25.6875 +        {
 25.6876 +            if(glPopDebugGroup_Impl)
 25.6877 +                glPopDebugGroup_Impl();
 25.6878 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6879 +        }
 25.6880 +
 25.6881 +        void OVR::GLEContext::glObjectLabel_Hook(GLenum identifier, GLuint name, GLsizei length, const char *label)
 25.6882 +        {
 25.6883 +            if(glObjectLabel_Impl)
 25.6884 +                glObjectLabel_Impl(identifier, name, length, label);
 25.6885 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6886 +        }
 25.6887 +
 25.6888 +        void OVR::GLEContext::glGetObjectLabel_Hook(GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *length, char *label)
 25.6889 +        {
 25.6890 +            if(glGetObjectLabel_Impl)
 25.6891 +                glGetObjectLabel_Impl(identifier, name, bufSize, length, label);
 25.6892 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6893 +        }
 25.6894 +
 25.6895 +        void OVR::GLEContext::glObjectPtrLabel_Hook(void* ptr, GLsizei length, const char *label)
 25.6896 +        {
 25.6897 +            if(glObjectPtrLabel_Impl)
 25.6898 +                glObjectPtrLabel_Impl(ptr, length, label);
 25.6899 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6900 +        }
 25.6901 +
 25.6902 +        void OVR::GLEContext::glGetObjectPtrLabel_Hook(void* ptr, GLsizei bufSize, GLsizei *length, char *label)
 25.6903 +        {
 25.6904 +            if(glGetObjectPtrLabel_Impl)
 25.6905 +                glGetObjectPtrLabel_Impl(ptr, bufSize, length, label);
 25.6906 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6907 +        }
 25.6908 +
 25.6909 +
 25.6910 +        // GL_WIN_swap_hint
 25.6911 +        void OVR::GLEContext::glAddSwapHintRectWIN_Hook(GLint x, GLint y, GLsizei width, GLsizei height)
 25.6912 +        {
 25.6913 +            if(glAddSwapHintRectWIN_Impl)
 25.6914 +                glAddSwapHintRectWIN_Impl(x, y, width, height);
 25.6915 +            PostHook(GLE_CURRENT_FUNCTION);
 25.6916 +        }
 25.6917 +
 25.6918 +
 25.6919 +        #if defined(GLE_WGL_ENABLED)
 25.6920 +			// WGL
 25.6921 +			void OVR::GLEContext::PostWGLHook(const char* /*function*/)
 25.6922 +			{
 25.6923 +				// Empty for now. WGL functions don't have a function like glGetError().
 25.6924 +			}
 25.6925 +
 25.6926 +            /* We currently don't hook these
 25.6927 +			#undef wglCopyContext
 25.6928 +			extern "C" { GLAPI BOOL GLAPIENTRY wglCopyContext(HGLRC hglrcSrc, HGLRC hglrcDst, UINT mask); }
 25.6929 +			BOOL OVR::GLEContext::wglCopyContext_Hook(HGLRC hglrcSrc, HGLRC hglrcDst, UINT mask)
 25.6930 +			{
 25.6931 +				BOOL b = wglCopyContext(hglrcSrc, hglrcDst, mask);
 25.6932 +				PostWGLHook(GLE_CURRENT_FUNCTION);
 25.6933 +				return b;
 25.6934 +			}
 25.6935 +
 25.6936 +			#undef wglCreateContext
 25.6937 +			extern "C" { GLAPI HGLRC GLAPIENTRY wglCreateContext(HDC hdc); }
 25.6938 +			HGLRC OVR::GLEContext::wglCreateContext_Hook(HDC hdc)
 25.6939 +			{
 25.6940 +				HGLRC h = wglCreateContext(hdc);
 25.6941 +				PostWGLHook(GLE_CURRENT_FUNCTION);
 25.6942 +				return h;
 25.6943 +			}
 25.6944 +
 25.6945 +			#undef wglCreateLayerContext
 25.6946 +			extern "C" { GLAPI HGLRC GLAPIENTRY wglCreateLayerContext(HDC hdc, int iLayerPlane); }
 25.6947 +			HGLRC OVR::GLEContext::wglCreateLayerContext_Hook(HDC hdc, int iLayerPlane)
 25.6948 +			{
 25.6949 +				HGLRC h = wglCreateLayerContext(hdc, iLayerPlane);
 25.6950 +				PostWGLHook(GLE_CURRENT_FUNCTION);
 25.6951 +				return h;
 25.6952 +			}
 25.6953 +
 25.6954 +			#undef wglDeleteContext
 25.6955 +			extern "C" { GLAPI BOOL GLAPIENTRY wglDeleteContext(HGLRC hglrc); }
 25.6956 +			BOOL OVR::GLEContext::wglDeleteContext_Hook(HGLRC hglrc)
 25.6957 +			{
 25.6958 +				BOOL b = wglDeleteContext(hglrc);
 25.6959 +				PostWGLHook(GLE_CURRENT_FUNCTION);
 25.6960 +				return b;
 25.6961 +			}
 25.6962 +
 25.6963 +			#undef wglGetCurrentContext
 25.6964 +			extern "C" { GLAPI HGLRC GLAPIENTRY wglGetCurrentContext(); }
 25.6965 +			HGLRC OVR::GLEContext::wglGetCurrentContext_Hook()
 25.6966 +			{
 25.6967 +				HGLRC h = wglGetCurrentContext();
 25.6968 +				PostWGLHook(GLE_CURRENT_FUNCTION);
 25.6969 +				return h;
 25.6970 +			}
 25.6971 +
 25.6972 +			#undef wglGetCurrentDC
 25.6973 +			extern "C" { GLAPI HDC GLAPIENTRY wglGetCurrentDC(); }
 25.6974 +			HDC OVR::GLEContext::wglGetCurrentDC_Hook()
 25.6975 +			{
 25.6976 +				HDC h = wglGetCurrentDC();
 25.6977 +				PostWGLHook(GLE_CURRENT_FUNCTION);
 25.6978 +				return h;
 25.6979 +			}
 25.6980 +
 25.6981 +			//#undef wglGetProcAddress Not needed because we happen to do it above already.
 25.6982 +			//extern "C" { GLAPI PROC GLAPIENTRY wglGetProcAddress(LPCSTR lpszProc); }
 25.6983 +			PROC OVR::GLEContext::wglGetProcAddress_Hook(LPCSTR lpszProc)
 25.6984 +			{
 25.6985 +				PROC p = wglGetProcAddress(lpszProc);
 25.6986 +				PostWGLHook(GLE_CURRENT_FUNCTION);
 25.6987 +				return p;
 25.6988 +			}
 25.6989 +
 25.6990 +			#undef wglMakeCurrent
 25.6991 +			extern "C" { GLAPI BOOL GLAPIENTRY wglMakeCurrent(HDC hdc, HGLRC hglrc); }
 25.6992 +			BOOL OVR::GLEContext::wglMakeCurrent_Hook(HDC hdc, HGLRC hglrc)
 25.6993 +			{
 25.6994 +				BOOL b = wglMakeCurrent(hdc, hglrc);
 25.6995 +				PostWGLHook(GLE_CURRENT_FUNCTION);
 25.6996 +				return b;
 25.6997 +			}
 25.6998 +
 25.6999 +			#undef wglShareLists
 25.7000 +			extern "C" { GLAPI BOOL GLAPIENTRY wglShareLists(HGLRC hglrc1, HGLRC hglrc2); }
 25.7001 +			BOOL OVR::GLEContext::wglShareLists_Hook(HGLRC hglrc1, HGLRC hglrc2)
 25.7002 +			{
 25.7003 +				BOOL b = wglShareLists(hglrc1, hglrc2);
 25.7004 +				PostWGLHook(GLE_CURRENT_FUNCTION);
 25.7005 +				return b;
 25.7006 +			}
 25.7007 +
 25.7008 +			#undef wglUseFontBitmapsA
 25.7009 +			extern "C" { GLAPI BOOL GLAPIENTRY wglUseFontBitmapsA(HDC hdc, DWORD first, DWORD count, DWORD listBase); }
 25.7010 +			BOOL OVR::GLEContext::wglUseFontBitmapsA_Hook(HDC hdc, DWORD first, DWORD count, DWORD listBase)
 25.7011 +			{
 25.7012 +				BOOL b = wglUseFontBitmapsA(hdc, first, count, listBase);
 25.7013 +				PostWGLHook(GLE_CURRENT_FUNCTION);
 25.7014 +				return b;
 25.7015 +			}
 25.7016 +
 25.7017 +			#undef wglUseFontBitmapsW
 25.7018 +			extern "C" { GLAPI BOOL GLAPIENTRY wglUseFontBitmapsW(HDC hdc, DWORD first, DWORD count, DWORD listBase); }
 25.7019 +			BOOL OVR::GLEContext::wglUseFontBitmapsW_Hook(HDC hdc, DWORD first, DWORD count, DWORD listBase)
 25.7020 +			{
 25.7021 +				BOOL b = wglUseFontBitmapsW(hdc, first, count, listBase);
 25.7022 +				PostWGLHook(GLE_CURRENT_FUNCTION);
 25.7023 +				return b;
 25.7024 +			}
 25.7025 +
 25.7026 +			#undef wglUseFontOutlinesA
 25.7027 +			extern "C" { GLAPI BOOL GLAPIENTRY wglUseFontOutlinesA(HDC hdc, DWORD first, DWORD count, DWORD listBase, FLOAT deviation, FLOAT extrusion, int format, LPGLYPHMETRICSFLOAT lpgmf); }
 25.7028 +			BOOL OVR::GLEContext::wglUseFontOutlinesA_Hook(HDC hdc, DWORD first, DWORD count, DWORD listBase, FLOAT deviation, FLOAT extrusion, int format, LPGLYPHMETRICSFLOAT lpgmf)
 25.7029 +			{
 25.7030 +				BOOL b = wglUseFontOutlinesA(hdc, first, count, listBase, deviation, extrusion, format, lpgmf);
 25.7031 +				PostWGLHook(GLE_CURRENT_FUNCTION);
 25.7032 +				return b;
 25.7033 +			}
 25.7034 +
 25.7035 +			#undef wglUseFontOutlinesW
 25.7036 +			extern "C" { GLAPI BOOL GLAPIENTRY wglUseFontOutlinesW(HDC hdc, DWORD first, DWORD count, DWORD listBase, FLOAT deviation, FLOAT extrusion, int format, LPGLYPHMETRICSFLOAT lpgmf); }
 25.7037 +			BOOL OVR::GLEContext::wglUseFontOutlinesW_Hook(HDC hdc, DWORD first, DWORD count, DWORD listBase, FLOAT deviation, FLOAT extrusion, int format, LPGLYPHMETRICSFLOAT lpgmf)
 25.7038 +			{
 25.7039 +				BOOL b = wglUseFontOutlinesW(hdc, first, count, listBase, deviation, extrusion, format, lpgmf);
 25.7040 +				PostWGLHook(GLE_CURRENT_FUNCTION);
 25.7041 +				return b;
 25.7042 +			}
 25.7043 +
 25.7044 +			#undef wglDescribeLayerPlane
 25.7045 +			extern "C" { GLAPI BOOL GLAPIENTRY wglDescribeLayerPlane(HDC hdc, int iPixelFormat, int iLayerPlane, UINT nBytes, LPLAYERPLANEDESCRIPTOR plpd); }
 25.7046 +			BOOL OVR::GLEContext::wglDescribeLayerPlane_Hook(HDC hdc, int iPixelFormat, int iLayerPlane, UINT nBytes, LPLAYERPLANEDESCRIPTOR plpd)
 25.7047 +			{
 25.7048 +				BOOL b = wglDescribeLayerPlane(hdc, iPixelFormat, iLayerPlane, nBytes, plpd);
 25.7049 +				PostWGLHook(GLE_CURRENT_FUNCTION);
 25.7050 +				return b;
 25.7051 +			}
 25.7052 +
 25.7053 +			#undef wglSetLayerPaletteEntries
 25.7054 +			extern "C" { GLAPI int GLAPIENTRY wglSetLayerPaletteEntries(HDC hdc, int iLayerPlane, int iStart, int cEntries, const COLORREF *pcr); }
 25.7055 +			int OVR::GLEContext::wglSetLayerPaletteEntries_Hook(HDC hdc, int iLayerPlane, int iStart, int cEntries, const COLORREF *pcr)
 25.7056 +			{
 25.7057 +				int i = wglSetLayerPaletteEntries(hdc, iLayerPlane, iStart, cEntries, pcr);
 25.7058 +				PostWGLHook(GLE_CURRENT_FUNCTION);
 25.7059 +				return i;
 25.7060 +			}
 25.7061 +
 25.7062 +			#undef wglGetLayerPaletteEntries
 25.7063 +			extern "C" { GLAPI int GLAPIENTRY wglGetLayerPaletteEntries(HDC hdc, int iLayerPlane, int iStart, int cEntries, COLORREF *pcr); }
 25.7064 +			int OVR::GLEContext::wglGetLayerPaletteEntries_Hook(HDC hdc, int iLayerPlane, int iStart, int cEntries, COLORREF *pcr)
 25.7065 +			{
 25.7066 +				int i = wglGetLayerPaletteEntries(hdc, iLayerPlane, iStart, cEntries, pcr);
 25.7067 +				PostWGLHook(GLE_CURRENT_FUNCTION);
 25.7068 +				return i;
 25.7069 +			}
 25.7070 +
 25.7071 +			#undef wglRealizeLayerPalette
 25.7072 +			extern "C" { GLAPI BOOL GLAPIENTRY wglRealizeLayerPalette(HDC hdc, int iLayerPlane, BOOL bRealize); }
 25.7073 +			BOOL OVR::GLEContext::wglRealizeLayerPalette_Hook(HDC hdc, int iLayerPlane, BOOL bRealize)
 25.7074 +			{
 25.7075 +				BOOL b = wglRealizeLayerPalette(hdc, iLayerPlane, bRealize);
 25.7076 +				PostWGLHook(GLE_CURRENT_FUNCTION);
 25.7077 +				return b;
 25.7078 +			}
 25.7079 +
 25.7080 +			#undef wglSwapLayerBuffers
 25.7081 +			extern "C" { GLAPI BOOL GLAPIENTRY wglSwapLayerBuffers(HDC hdc, UINT fuPlanes); }
 25.7082 +			BOOL OVR::GLEContext::wglSwapLayerBuffers_Hook(HDC hdc, UINT fuPlanes)
 25.7083 +			{
 25.7084 +				BOOL b = wglSwapLayerBuffers(hdc, fuPlanes);
 25.7085 +				PostWGLHook(GLE_CURRENT_FUNCTION);
 25.7086 +				return b;
 25.7087 +			}
 25.7088 +
 25.7089 +			#undef wglSwapMultipleBuffers
 25.7090 +			extern "C" { GLAPI DWORD GLAPIENTRY wglSwapMultipleBuffers(UINT i, CONST WGLSWAP* p); }
 25.7091 +			DWORD OVR::GLEContext::wglSwapMultipleBuffers_Hook(UINT i, CONST WGLSWAP* p)
 25.7092 +			{
 25.7093 +				DWORD dw = wglSwapMultipleBuffers(i, p);
 25.7094 +				PostWGLHook(GLE_CURRENT_FUNCTION);
 25.7095 +				return dw;
 25.7096 +			}
 25.7097 +            */
 25.7098 +
 25.7099 +			// The rest of the functions are pointer-based.
 25.7100 +
 25.7101 +			// WGL_ARB_buffer_region
 25.7102 +			HANDLE OVR::GLEContext::wglCreateBufferRegionARB_Hook(HDC hDC, int iLayerPlane, UINT uType)
 25.7103 +			{
 25.7104 +				HANDLE h = NULL;
 25.7105 +				if(wglCreateBufferRegionARB_Impl)
 25.7106 +					h = wglCreateBufferRegionARB_Impl(hDC, iLayerPlane, uType);
 25.7107 +				PostWGLHook(GLE_CURRENT_FUNCTION);
 25.7108 +				return h;
 25.7109 +			}
 25.7110 +
 25.7111 +			VOID OVR::GLEContext::wglDeleteBufferRegionARB_Hook(HANDLE hRegion)
 25.7112 +			{
 25.7113 +				if(wglDeleteBufferRegionARB_Impl)
 25.7114 +					wglDeleteBufferRegionARB_Impl(hRegion);
 25.7115 +				PostWGLHook(GLE_CURRENT_FUNCTION);
 25.7116 +			}
 25.7117 +
 25.7118 +			BOOL OVR::GLEContext::wglSaveBufferRegionARB_Hook(HANDLE hRegion, int x, int y, int width, int height)
 25.7119 +			{
 25.7120 +				BOOL b = FALSE;
 25.7121 +				if(wglSaveBufferRegionARB_Impl)
 25.7122 +					b = wglSaveBufferRegionARB_Impl(hRegion, x, y, width, height);
 25.7123 +				PostWGLHook(GLE_CURRENT_FUNCTION);
 25.7124 +				return b;
 25.7125 +			}
 25.7126 +
 25.7127 +			BOOL OVR::GLEContext::wglRestoreBufferRegionARB_Hook(HANDLE hRegion, int x, int y, int width, int height, int xSrc, int ySrc)
 25.7128 +			{
 25.7129 +				BOOL b = FALSE;
 25.7130 +				if(wglRestoreBufferRegionARB_Impl)
 25.7131 +					b = wglRestoreBufferRegionARB_Impl(hRegion, x, y, width, height, xSrc, ySrc);
 25.7132 +				PostWGLHook(GLE_CURRENT_FUNCTION);
 25.7133 +				return b;
 25.7134 +			}
 25.7135 +
 25.7136 +			// WGL_ARB_extensions_string
 25.7137 +			const char * OVR::GLEContext::wglGetExtensionsStringARB_Hook(HDC hdc)
 25.7138 +			{
 25.7139 +				const char * p = NULL;
 25.7140 +				if(wglGetExtensionsStringARB_Impl)
 25.7141 +					p = wglGetExtensionsStringARB_Impl(hdc);
 25.7142 +				PostWGLHook(GLE_CURRENT_FUNCTION);
 25.7143 +				return p;
 25.7144 +			}
 25.7145 +
 25.7146 +			// WGL_ARB_pixel_format
 25.7147 +			BOOL OVR::GLEContext::wglGetPixelFormatAttribivARB_Hook(HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, int *piValues)
 25.7148 +			{
 25.7149 +				BOOL b = FALSE;
 25.7150 +				if(wglGetPixelFormatAttribivARB_Impl)
 25.7151 +					b = wglGetPixelFormatAttribivARB_Impl(hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, piValues);
 25.7152 +				PostWGLHook(GLE_CURRENT_FUNCTION);
 25.7153 +				return b;
 25.7154 +			}
 25.7155 +
 25.7156 +			BOOL OVR::GLEContext::wglGetPixelFormatAttribfvARB_Hook(HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, FLOAT *pfValues)
 25.7157 +			{
 25.7158 +				BOOL b = FALSE;
 25.7159 +				if(wglGetPixelFormatAttribfvARB_Impl)
 25.7160 +					b = wglGetPixelFormatAttribfvARB_Impl(hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, pfValues);
 25.7161 +				PostWGLHook(GLE_CURRENT_FUNCTION);
 25.7162 +				return b;
 25.7163 +			}
 25.7164 +
 25.7165 +			BOOL OVR::GLEContext::wglChoosePixelFormatARB_Hook(HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats)
 25.7166 +			{
 25.7167 +				BOOL b = FALSE;
 25.7168 +				if(wglChoosePixelFormatARB_Impl)
 25.7169 +					b = wglChoosePixelFormatARB_Impl(hdc, piAttribIList, pfAttribFList, nMaxFormats, piFormats, nNumFormats);
 25.7170 +				PostWGLHook(GLE_CURRENT_FUNCTION);
 25.7171 +				return b;
 25.7172 +			}
 25.7173 +
 25.7174 +			// WGL_ARB_make_current_read
 25.7175 +			BOOL OVR::GLEContext::wglMakeContextCurrentARB_Hook(HDC hDrawDC, HDC hReadDC, HGLRC hglrc)
 25.7176 +			{
 25.7177 +				BOOL b = FALSE;
 25.7178 +				if(wglMakeContextCurrentARB_Impl)
 25.7179 +					b = wglMakeContextCurrentARB_Impl(hDrawDC, hReadDC, hglrc);
 25.7180 +				PostWGLHook(GLE_CURRENT_FUNCTION);
 25.7181 +				return b;
 25.7182 +			}
 25.7183 +
 25.7184 +			HDC OVR::GLEContext::wglGetCurrentReadDCARB_Hook()
 25.7185 +			{
 25.7186 +				HDC h = NULL;
 25.7187 +				if(wglGetCurrentReadDCARB_Impl)
 25.7188 +					h = wglGetCurrentReadDCARB_Impl();
 25.7189 +				PostWGLHook(GLE_CURRENT_FUNCTION);
 25.7190 +				return h;
 25.7191 +			}
 25.7192 +
 25.7193 +			// WGL_ARB_pbuffer
 25.7194 +			HPBUFFERARB OVR::GLEContext::wglCreatePbufferARB_Hook(HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int *piAttribList)
 25.7195 +			{
 25.7196 +				HPBUFFERARB h = NULL;
 25.7197 +				if(wglCreatePbufferARB_Impl)
 25.7198 +					h = wglCreatePbufferARB_Impl(hDC, iPixelFormat, iWidth, iHeight, piAttribList);
 25.7199 +				PostWGLHook(GLE_CURRENT_FUNCTION);
 25.7200 +				return h;
 25.7201 +			}
 25.7202 +
 25.7203 +			HDC OVR::GLEContext::wglGetPbufferDCARB_Hook(HPBUFFERARB hPbuffer)
 25.7204 +			{
 25.7205 +				HDC h = NULL;
 25.7206 +				if(wglGetPbufferDCARB_Impl)
 25.7207 +					h = wglGetPbufferDCARB_Impl(hPbuffer);
 25.7208 +				PostWGLHook(GLE_CURRENT_FUNCTION);
 25.7209 +				return h;
 25.7210 +			}
 25.7211 +
 25.7212 +			int OVR::GLEContext::wglReleasePbufferDCARB_Hook(HPBUFFERARB hPbuffer, HDC hDC)
 25.7213 +			{
 25.7214 +				int i = 0;
 25.7215 +				if(wglReleasePbufferDCARB_Impl)
 25.7216 +					i = wglReleasePbufferDCARB_Impl(hPbuffer, hDC);
 25.7217 +				PostWGLHook(GLE_CURRENT_FUNCTION);
 25.7218 +				return i;
 25.7219 +			}
 25.7220 +
 25.7221 +			BOOL OVR::GLEContext::wglDestroyPbufferARB_Hook(HPBUFFERARB hPbuffer)
 25.7222 +			{
 25.7223 +				BOOL b = FALSE;
 25.7224 +				if(wglDestroyPbufferARB_Impl)
 25.7225 +					b = wglDestroyPbufferARB_Impl(hPbuffer);
 25.7226 +				PostWGLHook(GLE_CURRENT_FUNCTION);
 25.7227 +				return b;
 25.7228 +			}
 25.7229 +
 25.7230 +			BOOL OVR::GLEContext::wglQueryPbufferARB_Hook(HPBUFFERARB hPbuffer, int iAttribute, int *piValue)
 25.7231 +			{
 25.7232 +				BOOL b = FALSE;
 25.7233 +				if(wglQueryPbufferARB_Impl)
 25.7234 +					b = wglQueryPbufferARB_Impl(hPbuffer, iAttribute, piValue);
 25.7235 +				PostWGLHook(GLE_CURRENT_FUNCTION);
 25.7236 +				return b;
 25.7237 +			}
 25.7238 +
 25.7239 +			// WGL_ARB_render_texture
 25.7240 +			BOOL OVR::GLEContext::wglBindTexImageARB_Hook(HPBUFFERARB hPbuffer, int iBuffer)
 25.7241 +			{
 25.7242 +				BOOL b = FALSE;
 25.7243 +				if(wglBindTexImageARB_Impl)
 25.7244 +					b = wglBindTexImageARB_Impl(hPbuffer, iBuffer);
 25.7245 +				PostWGLHook(GLE_CURRENT_FUNCTION);
 25.7246 +				return b;
 25.7247 +			}
 25.7248 +
 25.7249 +			BOOL OVR::GLEContext::wglReleaseTexImageARB_Hook(HPBUFFERARB hPbuffer, int iBuffer)
 25.7250 +			{
 25.7251 +				BOOL b = FALSE;
 25.7252 +				if(wglReleaseTexImageARB_Impl)
 25.7253 +					b = wglReleaseTexImageARB_Impl(hPbuffer, iBuffer);
 25.7254 +				PostWGLHook(GLE_CURRENT_FUNCTION);
 25.7255 +				return b;
 25.7256 +			}
 25.7257 +
 25.7258 +			BOOL OVR::GLEContext::wglSetPbufferAttribARB_Hook(HPBUFFERARB hPbuffer, const int *piAttribList)
 25.7259 +			{
 25.7260 +				BOOL b = FALSE;
 25.7261 +				if(wglSetPbufferAttribARB_Impl)
 25.7262 +					b = wglSetPbufferAttribARB_Impl(hPbuffer, piAttribList);
 25.7263 +				PostWGLHook(GLE_CURRENT_FUNCTION);
 25.7264 +				return b;
 25.7265 +			}
 25.7266 +
 25.7267 +			// WGL_NV_present_video
 25.7268 +			int OVR::GLEContext::wglEnumerateVideoDevicesNV_Hook(HDC hDC, HVIDEOOUTPUTDEVICENV *phDeviceList)
 25.7269 +			{
 25.7270 +				int i = 0;
 25.7271 +				if(wglEnumerateVideoDevicesNV_Impl)
 25.7272 +					i = wglEnumerateVideoDevicesNV_Impl(hDC, phDeviceList);
 25.7273 +				PostWGLHook(GLE_CURRENT_FUNCTION);
 25.7274 +				return i;
 25.7275 +			}
 25.7276 +
 25.7277 +			BOOL OVR::GLEContext::wglBindVideoDeviceNV_Hook(HDC hDC, unsigned int uVideoSlot, HVIDEOOUTPUTDEVICENV hVideoDevice, const int *piAttribList)
 25.7278 +			{
 25.7279 +				BOOL b = FALSE;
 25.7280 +				if(wglBindVideoDeviceNV_Impl)
 25.7281 +					b = wglBindVideoDeviceNV_Impl(hDC, uVideoSlot, hVideoDevice, piAttribList);
 25.7282 +				PostWGLHook(GLE_CURRENT_FUNCTION);
 25.7283 +				return b;
 25.7284 +			}
 25.7285 +
 25.7286 +			BOOL OVR::GLEContext::wglQueryCurrentContextNV_Hook(int iAttribute, int *piValue)
 25.7287 +			{
 25.7288 +				BOOL b = FALSE;
 25.7289 +				if(wglQueryCurrentContextNV_Impl)
 25.7290 +					b = wglQueryCurrentContextNV_Impl(iAttribute, piValue);
 25.7291 +				PostWGLHook(GLE_CURRENT_FUNCTION);
 25.7292 +				return b;
 25.7293 +			}
 25.7294 +
 25.7295 +			// WGL_ARB_create_context
 25.7296 +			HGLRC OVR::GLEContext::wglCreateContextAttribsARB_Hook(HDC hDC, HGLRC hShareContext, const int *attribList)
 25.7297 +			{
 25.7298 +				HGLRC h = NULL;
 25.7299 +				if(wglCreateContextAttribsARB_Impl)
 25.7300 +					h = wglCreateContextAttribsARB_Impl(hDC, hShareContext, attribList);
 25.7301 +				PostWGLHook(GLE_CURRENT_FUNCTION);
 25.7302 +				return h;
 25.7303 +			}
 25.7304 +
 25.7305 +			// WGL_EXT_extensions_string
 25.7306 +			const char * OVR::GLEContext::wglGetExtensionsStringEXT_Hook()
 25.7307 +			{
 25.7308 +				const char * p = NULL;
 25.7309 +				if(wglGetExtensionsStringEXT_Impl)
 25.7310 +					p = wglGetExtensionsStringEXT_Impl();
 25.7311 +				PostWGLHook(GLE_CURRENT_FUNCTION);
 25.7312 +				return p;
 25.7313 +			}
 25.7314 +
 25.7315 +			// WGL_EXT_swap_control
 25.7316 +			BOOL OVR::GLEContext::wglSwapIntervalEXT_Hook(int interval)
 25.7317 +			{
 25.7318 +				BOOL b = FALSE;
 25.7319 +				if(wglSwapIntervalEXT_Impl)
 25.7320 +					b = wglSwapIntervalEXT_Impl(interval);
 25.7321 +				PostWGLHook(GLE_CURRENT_FUNCTION);
 25.7322 +				return b;
 25.7323 +			}
 25.7324 +
 25.7325 +			int OVR::GLEContext::wglGetSwapIntervalEXT_Hook()
 25.7326 +			{
 25.7327 +				int i = 0;
 25.7328 +				if(wglGetSwapIntervalEXT_Impl)
 25.7329 +					i = wglGetSwapIntervalEXT_Impl();
 25.7330 +				PostWGLHook(GLE_CURRENT_FUNCTION);
 25.7331 +				return i;
 25.7332 +			}
 25.7333 +
 25.7334 +			// WGL_OML_sync_control
 25.7335 +			BOOL  OVR::GLEContext::wglGetSyncValuesOML_Hook(HDC hdc, INT64 *ust, INT64 *msc, INT64 *sbc)
 25.7336 +			{
 25.7337 +				BOOL b = FALSE;
 25.7338 +				if(wglGetSyncValuesOML_Impl)
 25.7339 +					b = wglGetSyncValuesOML_Impl(hdc, ust, msc, sbc);
 25.7340 +				PostWGLHook(GLE_CURRENT_FUNCTION);
 25.7341 +				return b;
 25.7342 +			}
 25.7343 +
 25.7344 +			BOOL  OVR::GLEContext::wglGetMscRateOML_Hook(HDC hdc, INT32 *numerator, INT32 *denominator)
 25.7345 +			{
 25.7346 +				BOOL b = FALSE;
 25.7347 +				if(wglGetMscRateOML_Impl)
 25.7348 +					b = wglGetMscRateOML_Impl(hdc, numerator, denominator);
 25.7349 +				PostWGLHook(GLE_CURRENT_FUNCTION);
 25.7350 +				return b;
 25.7351 +			}
 25.7352 +
 25.7353 +			INT64 OVR::GLEContext::wglSwapBuffersMscOML_Hook(HDC hdc, INT64 target_msc, INT64 divisor, INT64 remainder)
 25.7354 +			{
 25.7355 +				INT64 i = 0;
 25.7356 +				if(wglSwapBuffersMscOML_Impl)
 25.7357 +					i = wglSwapBuffersMscOML_Impl(hdc, target_msc, divisor, remainder);
 25.7358 +				PostWGLHook(GLE_CURRENT_FUNCTION);
 25.7359 +				return i;
 25.7360 +			}
 25.7361 +
 25.7362 +			INT64 OVR::GLEContext::wglSwapLayerBuffersMscOML_Hook(HDC hdc, int fuPlanes, INT64 target_msc, INT64 divisor, INT64 remainder)
 25.7363 +			{
 25.7364 +				INT64 i = 0;
 25.7365 +				if(wglSwapLayerBuffersMscOML_Impl)
 25.7366 +					i = wglSwapLayerBuffersMscOML_Impl(hdc, fuPlanes, target_msc, divisor, remainder);
 25.7367 +				PostWGLHook(GLE_CURRENT_FUNCTION);
 25.7368 +				return i;
 25.7369 +			}
 25.7370 +
 25.7371 +			BOOL  OVR::GLEContext::wglWaitForMscOML_Hook(HDC hdc, INT64 target_msc, INT64 divisor, INT64 remainder, INT64 *ust, INT64 *msc, INT64 *sbc)
 25.7372 +			{
 25.7373 +				BOOL b = FALSE;
 25.7374 +				if(wglWaitForMscOML_Impl)
 25.7375 +					b = wglWaitForMscOML_Impl(hdc, target_msc, divisor, remainder, ust, msc, sbc);
 25.7376 +				PostWGLHook(GLE_CURRENT_FUNCTION);
 25.7377 +				return b;
 25.7378 +			}
 25.7379 +
 25.7380 +			BOOL  OVR::GLEContext::wglWaitForSbcOML_Hook(HDC hdc, INT64 target_sbc, INT64 *ust, INT64 *msc, INT64 *sbc)
 25.7381 +			{
 25.7382 +				BOOL b = FALSE;
 25.7383 +				if(wglWaitForSbcOML_Impl)
 25.7384 +					b = wglWaitForSbcOML_Impl(hdc, target_sbc, ust, msc, sbc);
 25.7385 +				PostWGLHook(GLE_CURRENT_FUNCTION);
 25.7386 +				return b;
 25.7387 +			}
 25.7388 +
 25.7389 +			// WGL_NV_video_output
 25.7390 +			BOOL OVR::GLEContext::wglGetVideoDeviceNV_Hook(HDC hDC, int numDevices, HPVIDEODEV *hVideoDevice)
 25.7391 +			{
 25.7392 +				BOOL b = FALSE;
 25.7393 +				if(wglGetVideoDeviceNV_Impl)
 25.7394 +					b = wglGetVideoDeviceNV_Impl(hDC, numDevices, hVideoDevice);
 25.7395 +				PostWGLHook(GLE_CURRENT_FUNCTION);
 25.7396 +				return b;
 25.7397 +			}
 25.7398 +
 25.7399 +			BOOL OVR::GLEContext::wglReleaseVideoDeviceNV_Hook(HPVIDEODEV hVideoDevice)
 25.7400 +			{
 25.7401 +				BOOL b = FALSE;
 25.7402 +				if(wglReleaseVideoDeviceNV_Impl)
 25.7403 +					b = wglReleaseVideoDeviceNV_Impl(hVideoDevice);
 25.7404 +				PostWGLHook(GLE_CURRENT_FUNCTION);
 25.7405 +				return b;
 25.7406 +			}
 25.7407 +
 25.7408 +			BOOL OVR::GLEContext::wglBindVideoImageNV_Hook(HPVIDEODEV hVideoDevice, HPBUFFERARB hPbuffer, int iVideoBuffer)
 25.7409 +			{
 25.7410 +				BOOL b = FALSE;
 25.7411 +				if(wglBindVideoImageNV_Impl)
 25.7412 +					b = wglBindVideoImageNV_Impl(hVideoDevice, hPbuffer, iVideoBuffer);
 25.7413 +				PostWGLHook(GLE_CURRENT_FUNCTION);
 25.7414 +				return b;
 25.7415 +			}
 25.7416 +
 25.7417 +			BOOL OVR::GLEContext::wglReleaseVideoImageNV_Hook(HPBUFFERARB hPbuffer, int iVideoBuffer)
 25.7418 +			{
 25.7419 +				BOOL b = FALSE;
 25.7420 +				if(wglReleaseVideoImageNV_Impl)
 25.7421 +					b = wglReleaseVideoImageNV_Impl(hPbuffer, iVideoBuffer);
 25.7422 +				PostWGLHook(GLE_CURRENT_FUNCTION);
 25.7423 +				return b;
 25.7424 +			}
 25.7425 +
 25.7426 +			BOOL OVR::GLEContext::wglSendPbufferToVideoNV_Hook(HPBUFFERARB hPbuffer, int iBufferType, unsigned long *pulCounterPbuffer, BOOL bBlock)
 25.7427 +			{
 25.7428 +				BOOL b = FALSE;
 25.7429 +				if(wglSendPbufferToVideoNV_Impl)
 25.7430 +					b = wglSendPbufferToVideoNV_Impl(hPbuffer, iBufferType, pulCounterPbuffer, bBlock);
 25.7431 +				PostWGLHook(GLE_CURRENT_FUNCTION);
 25.7432 +				return b;
 25.7433 +			}
 25.7434 +
 25.7435 +			BOOL OVR::GLEContext::wglGetVideoInfoNV_Hook(HPVIDEODEV hpVideoDevice, unsigned long *pulCounterOutputPbuffer, unsigned long *pulCounterOutputVideo)
 25.7436 +			{
 25.7437 +				BOOL b = FALSE;
 25.7438 +				if(wglGetVideoInfoNV_Impl)
 25.7439 +					b = wglGetVideoInfoNV_Impl(hpVideoDevice, pulCounterOutputPbuffer, pulCounterOutputVideo);
 25.7440 +				PostWGLHook(GLE_CURRENT_FUNCTION);
 25.7441 +				return b;
 25.7442 +			}
 25.7443 +
 25.7444 +			// WGL_NV_swap_group
 25.7445 +			BOOL OVR::GLEContext::wglJoinSwapGroupNV_Hook(HDC hDC, GLuint group)
 25.7446 +			{
 25.7447 +				BOOL b = FALSE;
 25.7448 +				if(wglJoinSwapGroupNV_Impl)
 25.7449 +					b = wglJoinSwapGroupNV_Impl(hDC, group);
 25.7450 +				PostWGLHook(GLE_CURRENT_FUNCTION);
 25.7451 +				return b;
 25.7452 +			}
 25.7453 +
 25.7454 +			BOOL OVR::GLEContext::wglBindSwapBarrierNV_Hook(GLuint group, GLuint barrier)
 25.7455 +			{
 25.7456 +				BOOL b = FALSE;
 25.7457 +				if(wglBindSwapBarrierNV_Impl)
 25.7458 +					b = wglBindSwapBarrierNV_Impl(group, barrier);
 25.7459 +				PostWGLHook(GLE_CURRENT_FUNCTION);
 25.7460 +				return b;
 25.7461 +			}
 25.7462 +
 25.7463 +			BOOL OVR::GLEContext::wglQuerySwapGroupNV_Hook(HDC hDC, GLuint *group, GLuint *barrier)
 25.7464 +			{
 25.7465 +				BOOL b = FALSE;
 25.7466 +				if(wglQuerySwapGroupNV_Impl)
 25.7467 +					b = wglQuerySwapGroupNV_Impl(hDC, group, barrier);
 25.7468 +				PostWGLHook(GLE_CURRENT_FUNCTION);
 25.7469 +				return b;
 25.7470 +		   }
 25.7471 +
 25.7472 +			BOOL OVR::GLEContext::wglQueryMaxSwapGroupsNV_Hook(HDC hDC, GLuint *maxGroups, GLuint *maxBarriers)
 25.7473 +			{
 25.7474 +				BOOL b = FALSE;
 25.7475 +				if(wglQueryMaxSwapGroupsNV_Impl)
 25.7476 +					b = wglQueryMaxSwapGroupsNV_Impl(hDC, maxGroups, maxBarriers);
 25.7477 +				PostWGLHook(GLE_CURRENT_FUNCTION);
 25.7478 +				return b;
 25.7479 +			}
 25.7480 +
 25.7481 +			BOOL OVR::GLEContext::wglQueryFrameCountNV_Hook(HDC hDC, GLuint *count)
 25.7482 +			{
 25.7483 +				BOOL b = FALSE;
 25.7484 +				if(wglQueryFrameCountNV_Impl)
 25.7485 +					b = wglQueryFrameCountNV_Impl(hDC, count);
 25.7486 +				PostWGLHook(GLE_CURRENT_FUNCTION);
 25.7487 +				return b;
 25.7488 +			}
 25.7489 +
 25.7490 +			BOOL OVR::GLEContext::wglResetFrameCountNV_Hook(HDC hDC)
 25.7491 +			{
 25.7492 +				BOOL b = FALSE;
 25.7493 +				if(wglResetFrameCountNV_Impl)
 25.7494 +					b = wglResetFrameCountNV_Impl(hDC);
 25.7495 +				PostHook(GLE_CURRENT_FUNCTION);
 25.7496 +				return b;
 25.7497 +		   }
 25.7498 +
 25.7499 +			// WGL_NV_video_capture
 25.7500 +			BOOL OVR::GLEContext::wglBindVideoCaptureDeviceNV_Hook(UINT uVideoSlot, HVIDEOINPUTDEVICENV hDevice)
 25.7501 +			{
 25.7502 +				BOOL b = FALSE;
 25.7503 +				if(wglBindVideoCaptureDeviceNV_Impl)
 25.7504 +					b = wglBindVideoCaptureDeviceNV_Impl(uVideoSlot, hDevice);
 25.7505 +				PostWGLHook(GLE_CURRENT_FUNCTION);
 25.7506 +				return b;
 25.7507 +			}
 25.7508 +
 25.7509 +			UINT OVR::GLEContext::wglEnumerateVideoCaptureDevicesNV_Hook(HDC hDc, HVIDEOINPUTDEVICENV *phDeviceList)
 25.7510 +			{
 25.7511 +				UINT u = 0;
 25.7512 +				if(wglEnumerateVideoCaptureDevicesNV_Impl)
 25.7513 +					u = wglEnumerateVideoCaptureDevicesNV_Impl(hDc, phDeviceList);
 25.7514 +				PostWGLHook(GLE_CURRENT_FUNCTION);
 25.7515 +				return u;
 25.7516 +			}
 25.7517 +
 25.7518 +			BOOL OVR::GLEContext::wglLockVideoCaptureDeviceNV_Hook(HDC hDc, HVIDEOINPUTDEVICENV hDevice)
 25.7519 +			{
 25.7520 +				BOOL b = FALSE;
 25.7521 +				if(wglLockVideoCaptureDeviceNV_Impl)
 25.7522 +					b = wglLockVideoCaptureDeviceNV_Impl(hDc, hDevice);
 25.7523 +				PostWGLHook(GLE_CURRENT_FUNCTION);
 25.7524 +				return b;
 25.7525 +			}
 25.7526 +
 25.7527 +			BOOL OVR::GLEContext::wglQueryVideoCaptureDeviceNV_Hook(HDC hDc, HVIDEOINPUTDEVICENV hDevice, int iAttribute, int *piValue)
 25.7528 +			{
 25.7529 +				BOOL b = FALSE;
 25.7530 +				if(wglQueryVideoCaptureDeviceNV_Impl)
 25.7531 +					b = wglQueryVideoCaptureDeviceNV_Impl(hDc, hDevice, iAttribute, piValue);
 25.7532 +				PostWGLHook(GLE_CURRENT_FUNCTION);
 25.7533 +				return b;
 25.7534 +			}
 25.7535 +
 25.7536 +			BOOL OVR::GLEContext::wglReleaseVideoCaptureDeviceNV_Hook(HDC hDc, HVIDEOINPUTDEVICENV hDevice)
 25.7537 +			{
 25.7538 +				BOOL b = FALSE;
 25.7539 +				if(wglReleaseVideoCaptureDeviceNV_Impl)
 25.7540 +					b = wglReleaseVideoCaptureDeviceNV_Impl(hDc, hDevice);
 25.7541 +				PostWGLHook(GLE_CURRENT_FUNCTION);
 25.7542 +				return b;
 25.7543 +			}
 25.7544 +
 25.7545 +			// WGL_NV_copy_image
 25.7546 +			BOOL OVR::GLEContext::wglCopyImageSubDataNV_Hook(HGLRC hSrcRC, GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, HGLRC hDstRC,
 25.7547 +															 GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei width, GLsizei height, GLsizei depth)
 25.7548 +			{
 25.7549 +				BOOL b = FALSE;
 25.7550 +				if(wglCopyImageSubDataNV_Impl)
 25.7551 +					b = wglCopyImageSubDataNV_Impl(hSrcRC, srcName, srcTarget, srcLevel, srcX, srcY, srcZ, hDstRC, dstName, dstTarget, dstLevel, dstX, dstY, dstZ, width, height, depth);
 25.7552 +				PostWGLHook(GLE_CURRENT_FUNCTION);
 25.7553 +				return b;
 25.7554 +			}
 25.7555 +
 25.7556 +			// WGL_NV_DX_interop
 25.7557 +			BOOL OVR::GLEContext::wglDXSetResourceShareHandleNV_Hook(void *dxObject, HANDLE shareHandle)
 25.7558 +			{
 25.7559 +				BOOL b = FALSE;
 25.7560 +				if(wglDXSetResourceShareHandleNV_Impl)
 25.7561 +					b = wglDXSetResourceShareHandleNV_Impl(dxObject, shareHandle);
 25.7562 +				PostWGLHook(GLE_CURRENT_FUNCTION);
 25.7563 +				return b;
 25.7564 +			}
 25.7565 +
 25.7566 +			HANDLE OVR::GLEContext::wglDXOpenDeviceNV_Hook(void *dxDevice)
 25.7567 +			{
 25.7568 +				HANDLE h = NULL;
 25.7569 +				if(wglDXOpenDeviceNV_Impl)
 25.7570 +					h = wglDXOpenDeviceNV_Impl(dxDevice);
 25.7571 +				PostWGLHook(GLE_CURRENT_FUNCTION);
 25.7572 +				return h;
 25.7573 +			}
 25.7574 +
 25.7575 +			BOOL OVR::GLEContext::wglDXCloseDeviceNV_Hook(HANDLE hDevice)
 25.7576 +			{
 25.7577 +				BOOL b = FALSE;
 25.7578 +				if(wglDXCloseDeviceNV_Impl)
 25.7579 +					b = wglDXCloseDeviceNV_Impl(hDevice);
 25.7580 +				PostWGLHook(GLE_CURRENT_FUNCTION);
 25.7581 +				return b;
 25.7582 +			}
 25.7583 +
 25.7584 +			HANDLE OVR::GLEContext::wglDXRegisterObjectNV_Hook(HANDLE hDevice, void *dxObject, GLuint name, GLenum type, GLenum access)
 25.7585 +			{
 25.7586 +				HANDLE h = NULL;
 25.7587 +				if(wglDXRegisterObjectNV_Impl)
 25.7588 +					h = wglDXRegisterObjectNV_Impl(hDevice, dxObject, name, type, access);
 25.7589 +				PostWGLHook(GLE_CURRENT_FUNCTION);
 25.7590 +				return h;
 25.7591 +			}
 25.7592 +
 25.7593 +			BOOL OVR::GLEContext::wglDXUnregisterObjectNV_Hook(HANDLE hDevice, HANDLE hObject)
 25.7594 +			{
 25.7595 +				BOOL b = FALSE;
 25.7596 +				if(wglDXUnregisterObjectNV_Impl)
 25.7597 +					b = wglDXUnregisterObjectNV_Impl(hDevice, hObject);
 25.7598 +				PostWGLHook(GLE_CURRENT_FUNCTION);
 25.7599 +				return b;
 25.7600 +			}
 25.7601 +
 25.7602 +			BOOL OVR::GLEContext::wglDXObjectAccessNV_Hook(HANDLE hObject, GLenum access)
 25.7603 +			{
 25.7604 +				BOOL b = FALSE;
 25.7605 +				if(wglDXObjectAccessNV_Impl)
 25.7606 +					b = wglDXObjectAccessNV_Impl(hObject, access);
 25.7607 +				PostWGLHook(GLE_CURRENT_FUNCTION);
 25.7608 +				return b;
 25.7609 +			}
 25.7610 +
 25.7611 +			BOOL OVR::GLEContext::wglDXLockObjectsNV_Hook(HANDLE hDevice, GLint count, HANDLE *hObjects)
 25.7612 +			{
 25.7613 +				BOOL b = FALSE;
 25.7614 +				if(wglDXLockObjectsNV_Impl)
 25.7615 +					b = wglDXLockObjectsNV_Impl(hDevice, count, hObjects);
 25.7616 +				PostWGLHook(GLE_CURRENT_FUNCTION);
 25.7617 +				return b;
 25.7618 +			}
 25.7619 +
 25.7620 +			BOOL OVR::GLEContext::wglDXUnlockObjectsNV_Hook(HANDLE hDevice, GLint count, HANDLE *hObjects)
 25.7621 +			{
 25.7622 +				BOOL b = FALSE;
 25.7623 +				if(wglDXUnlockObjectsNV_Impl)
 25.7624 +					b = wglDXUnlockObjectsNV_Impl(hDevice, count, hObjects);
 25.7625 +				PostWGLHook(GLE_CURRENT_FUNCTION);
 25.7626 +				return b;
 25.7627 +			}
 25.7628 +
 25.7629 +        #endif // defined(GLE_WGL_ENABLED)
 25.7630 +
 25.7631 +        #if defined(GLE_GLX_ENABLED)
 25.7632 +			void OVR::GLEContext::PostGLXHook(const char* /*function*/)
 25.7633 +			{
 25.7634 +				// Empty for now. GLX functions don't have a function like glGetError().
 25.7635 +			}
 25.7636 +
 25.7637 +			// GLX_VERSION_1_0
 25.7638 +			// GLX_VERSION_1_1
 25.7639 +			// We don't currently implement hooking of these.
 25.7640 +
 25.7641 +			// GLX_VERSION_1_2
 25.7642 +			::Display* OVR::GLEContext::glXGetCurrentDisplay_Hook(void)
 25.7643 +			{
 25.7644 +				::Display* p = NULL;
 25.7645 +				if(glXGetCurrentDisplay_Impl)
 25.7646 +	                p = glXGetCurrentDisplay_Impl();
 25.7647 +	            PostGLXHook(GLE_CURRENT_FUNCTION);
 25.7648 +	            return p;
 25.7649 +			}
 25.7650 +
 25.7651 +			// GLX_VERSION_1_3
 25.7652 +		    GLXFBConfig* OVR::GLEContext::glXChooseFBConfig_Hook(Display *dpy, int screen, const int *attrib_list, int *nelements)
 25.7653 +			{
 25.7654 +				GLXFBConfig* p = NULL;
 25.7655 +				if(glXChooseFBConfig_Impl)
 25.7656 +	                p = glXChooseFBConfig_Impl(dpy, screen, attrib_list, nelements);
 25.7657 +	            PostGLXHook(GLE_CURRENT_FUNCTION);
 25.7658 +	            return p;
 25.7659 +			}
 25.7660 +
 25.7661 +		    GLXContext OVR::GLEContext::glXCreateNewContext_Hook(Display *dpy, GLXFBConfig config, int render_type, GLXContext share_list, Bool direct)
 25.7662 +			{
 25.7663 +		    	GLXContext c = 0;
 25.7664 +				if(glXCreateNewContext_Impl)
 25.7665 +	                c = glXCreateNewContext_Impl(dpy, config, render_type, share_list, direct);
 25.7666 +	            PostGLXHook(GLE_CURRENT_FUNCTION);
 25.7667 +	            return c;
 25.7668 +			}
 25.7669 +
 25.7670 +		    GLXPbuffer OVR::GLEContext::glXCreatePbuffer_Hook(Display *dpy, GLXFBConfig config, const int *attrib_list)
 25.7671 +			{
 25.7672 +		    	GLXPbuffer b = 0;
 25.7673 +	            if(glXCreatePbuffer_Impl)
 25.7674 +	            	b = glXCreatePbuffer_Impl(dpy, config, attrib_list);
 25.7675 +	            PostGLXHook(GLE_CURRENT_FUNCTION);
 25.7676 +	            return b;
 25.7677 +			}
 25.7678 +
 25.7679 +		    GLXPixmap OVR::GLEContext::glXCreatePixmap_Hook(Display *dpy, GLXFBConfig config, Pixmap pixmap, const int *attrib_list)
 25.7680 +			{
 25.7681 +		    	GLXPixmap m = 0;
 25.7682 +	            if(glXCreatePixmap_Impl)
 25.7683 +	            	m = glXCreatePixmap_Impl(dpy, config, pixmap, attrib_list);
 25.7684 +	            PostGLXHook(GLE_CURRENT_FUNCTION);
 25.7685 +	            return m;
 25.7686 +			}
 25.7687 +
 25.7688 +		    GLXWindow OVR::GLEContext::glXCreateWindow_Hook(Display *dpy, GLXFBConfig config, Window win, const int *attrib_list)
 25.7689 +			{
 25.7690 +		    	GLXWindow w = 0;
 25.7691 +	            if(glXCreateWindow_Impl)
 25.7692 +	            	w = glXCreateWindow_Impl(dpy, config, win, attrib_list);
 25.7693 +	            PostGLXHook(GLE_CURRENT_FUNCTION);
 25.7694 +	            return w;
 25.7695 +			}
 25.7696 +
 25.7697 +		    void OVR::GLEContext::glXDestroyPbuffer_Hook(Display *dpy, GLXPbuffer pbuf)
 25.7698 +		    {
 25.7699 +	            if(glXDestroyPbuffer_Impl)
 25.7700 +	                glXDestroyPbuffer_Impl(dpy, pbuf);
 25.7701 +	            PostGLXHook(GLE_CURRENT_FUNCTION);
 25.7702 +		    }
 25.7703 +
 25.7704 +		    void OVR::GLEContext::glXDestroyPixmap_Hook(Display *dpy, GLXPixmap pixmap)
 25.7705 +			{
 25.7706 +	            if(glXDestroyPixmap_Impl)
 25.7707 +	            	glXDestroyPixmap_Impl(dpy, pixmap);
 25.7708 +	            PostGLXHook(GLE_CURRENT_FUNCTION);
 25.7709 +			}
 25.7710 +
 25.7711 +		    void OVR::GLEContext::glXDestroyWindow_Hook(Display *dpy, GLXWindow win)
 25.7712 +			{
 25.7713 +	            if(glXDestroyWindow_Impl)
 25.7714 +	            	glXDestroyWindow_Impl(dpy, win);
 25.7715 +	            PostGLXHook(GLE_CURRENT_FUNCTION);
 25.7716 +			}
 25.7717 +
 25.7718 +		    GLXDrawable OVR::GLEContext::glXGetCurrentReadDrawable_Hook(void)
 25.7719 +			{
 25.7720 +		    	GLXDrawable d;
 25.7721 +	            if(glXGetCurrentReadDrawable_Impl)
 25.7722 +	            	d = glXGetCurrentReadDrawable_Impl();
 25.7723 +	            PostGLXHook(GLE_CURRENT_FUNCTION);
 25.7724 +	            return d;
 25.7725 +			}
 25.7726 +
 25.7727 +		    int OVR::GLEContext::glXGetFBConfigAttrib_Hook(Display *dpy, GLXFBConfig config, int attribute, int *value)
 25.7728 +			{
 25.7729 +	            int i = -1;
 25.7730 +	            if(glXGetFBConfigAttrib_Impl)
 25.7731 +	            	i = glXGetFBConfigAttrib_Impl(dpy, config, attribute, value);
 25.7732 +	            PostGLXHook(GLE_CURRENT_FUNCTION);
 25.7733 +	            return i;
 25.7734 +			}
 25.7735 +
 25.7736 +		    GLXFBConfig* OVR::GLEContext::glXGetFBConfigs_Hook(Display *dpy, int screen, int *nelements)
 25.7737 +		    {
 25.7738 +		    	GLXFBConfig* p = NULL;
 25.7739 +	            if(glXGetFBConfigs_Impl)
 25.7740 +	            	p = glXGetFBConfigs_Impl(dpy, screen, nelements);
 25.7741 +	            PostGLXHook(GLE_CURRENT_FUNCTION);
 25.7742 +	            return p;
 25.7743 +		    }
 25.7744 +
 25.7745 +		    void OVR::GLEContext::glXGetSelectedEvent_Hook(Display *dpy, GLXDrawable draw, unsigned long *event_mask)
 25.7746 +			{
 25.7747 +	            if(glXGetSelectedEvent_Impl)
 25.7748 +	            	glXGetSelectedEvent_Impl(dpy, draw, event_mask);
 25.7749 +	            PostGLXHook(GLE_CURRENT_FUNCTION);
 25.7750 +			}
 25.7751 +
 25.7752 +		    XVisualInfo* OVR::GLEContext::glXGetVisualFromFBConfig_Hook(Display *dpy, GLXFBConfig config)
 25.7753 +			{
 25.7754 +		    	XVisualInfo* p = NULL;
 25.7755 +	            if(glXGetVisualFromFBConfig_Impl)
 25.7756 +	            	p = glXGetVisualFromFBConfig_Impl(dpy, config);
 25.7757 +	            PostGLXHook(GLE_CURRENT_FUNCTION);
 25.7758 +	            return p;
 25.7759 +			}
 25.7760 +
 25.7761 +		    Bool OVR::GLEContext::glXMakeContextCurrent_Hook(Display *dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx)
 25.7762 +			{
 25.7763 +	            Bool b = False;
 25.7764 +	            if(glXMakeContextCurrent_Impl)
 25.7765 +	            	b = glXMakeContextCurrent_Impl(dpy, draw, read, ctx);
 25.7766 +	            PostGLXHook(GLE_CURRENT_FUNCTION);
 25.7767 +	            return b;
 25.7768 +			}
 25.7769 +
 25.7770 +		    int OVR::GLEContext::glXQueryContext_Hook(Display *dpy, GLXContext ctx, int attribute, int *value)
 25.7771 +		    {
 25.7772 +	            int i = GLX_BAD_ATTRIBUTE;
 25.7773 +	            if(glXQueryContext_Impl)
 25.7774 +	            	i = glXQueryContext_Impl(dpy, ctx, attribute, value);
 25.7775 +	            PostGLXHook(GLE_CURRENT_FUNCTION);
 25.7776 +	            return i;
 25.7777 +		    }
 25.7778 +
 25.7779 +		    void OVR::GLEContext::glXQueryDrawable_Hook(Display *dpy, GLXDrawable draw, int attribute, unsigned int *value)
 25.7780 +			{
 25.7781 +	            if(glXQueryDrawable_Impl)
 25.7782 +	            	glXQueryDrawable_Impl(dpy, draw, attribute, value);
 25.7783 +	            PostGLXHook(GLE_CURRENT_FUNCTION);
 25.7784 +			}
 25.7785 +
 25.7786 +		    void OVR::GLEContext::glXSelectEvent_Hook(Display *dpy, GLXDrawable draw, unsigned long event_mask)
 25.7787 +			{
 25.7788 +	            if(glXSelectEvent_Impl)
 25.7789 +	            	glXSelectEvent_Impl(dpy, draw, event_mask);
 25.7790 +	            PostGLXHook(GLE_CURRENT_FUNCTION);
 25.7791 +			}
 25.7792 +
 25.7793 +		    // GLX_VERSION_1_4
 25.7794 +		    // We don't do hooking of this.
 25.7795 +
 25.7796 +		    // GLX_ARB_create_context
 25.7797 +	        GLXContext OVR::GLEContext::glXCreateContextAttribsARB_Hook(Display* dpy, GLXFBConfig config, GLXContext share_context, Bool direct, const int *attrib_list)
 25.7798 +			{
 25.7799 +	        	GLXContext c = 0;
 25.7800 +	            if(glXCreateContextAttribsARB_Impl)
 25.7801 +	            	c = glXCreateContextAttribsARB_Impl(dpy,  config, share_context, direct, attrib_list);
 25.7802 +	            PostGLXHook(GLE_CURRENT_FUNCTION);
 25.7803 +	            return c;
 25.7804 +			}
 25.7805 +
 25.7806 +		    // GLX_EXT_swap_control
 25.7807 +		    void OVR::GLEContext::glXSwapIntervalEXT_Hook(Display* dpy, GLXDrawable drawable, int interval)
 25.7808 +		    {
 25.7809 +	            if(glXSwapIntervalEXT_Impl)
 25.7810 +	            	glXSwapIntervalEXT_Impl(dpy, drawable, interval);
 25.7811 +	            PostGLXHook(GLE_CURRENT_FUNCTION);
 25.7812 +		    }
 25.7813 +
 25.7814 +            // GLX_OML_sync_control
 25.7815 +   			Bool OVR::GLEContext::glXGetMscRateOML_Hook(Display* dpy, GLXDrawable drawable, int32_t* numerator, int32_t* denominator)
 25.7816 +			{
 25.7817 +	            Bool b = False;
 25.7818 +	            if(glXGetMscRateOML_Impl)
 25.7819 +	            	b = glXGetMscRateOML_Impl(dpy, drawable, numerator, denominator);
 25.7820 +	            PostGLXHook(GLE_CURRENT_FUNCTION);
 25.7821 +	            return b;
 25.7822 +			}
 25.7823 +
 25.7824 +   			Bool OVR::GLEContext::glXGetSyncValuesOML_Hook(Display* dpy, GLXDrawable drawable, int64_t* ust, int64_t* msc, int64_t* sbc)
 25.7825 +			{
 25.7826 +	            Bool b = False;
 25.7827 +	            if(glXGetSyncValuesOML_Impl)
 25.7828 +	            	b = glXGetSyncValuesOML_Impl(dpy, drawable, ust, msc, sbc);
 25.7829 +	            PostGLXHook(GLE_CURRENT_FUNCTION);
 25.7830 +	            return b;
 25.7831 +			}
 25.7832 +
 25.7833 +   			int64_t OVR::GLEContext::glXSwapBuffersMscOML_Hook(Display* dpy, GLXDrawable drawable, int64_t target_msc, int64_t divisor, int64_t remainder)
 25.7834 +			{
 25.7835 +   				int64_t i = 0;
 25.7836 +	            if(glXSwapBuffersMscOML_Impl)
 25.7837 +	            	i = glXSwapBuffersMscOML_Impl(dpy, drawable, target_msc, divisor, remainder);
 25.7838 +	            PostGLXHook(GLE_CURRENT_FUNCTION);
 25.7839 +	            return i;
 25.7840 +			}
 25.7841 +
 25.7842 +   			Bool OVR::GLEContext::glXWaitForMscOML_Hook(Display* dpy, GLXDrawable drawable, int64_t target_msc, int64_t divisor, int64_t remainder, int64_t* ust, int64_t* msc, int64_t* sbc)
 25.7843 +			{
 25.7844 +	            Bool b = False;
 25.7845 +	            if(glXWaitForMscOML_Impl)
 25.7846 +	            	b = glXWaitForMscOML_Impl(dpy, drawable, target_msc, divisor, remainder, ust, msc, sbc);
 25.7847 +	            PostGLXHook(GLE_CURRENT_FUNCTION);
 25.7848 +	            return b;
 25.7849 +			}
 25.7850 +
 25.7851 +   			Bool OVR::GLEContext::glXWaitForSbcOML_Hook(Display* dpy, GLXDrawable drawable, int64_t target_sbc, int64_t* ust, int64_t* msc, int64_t* sbc)
 25.7852 +			{
 25.7853 +	            Bool b = False;
 25.7854 +	            if(glXWaitForSbcOML_Impl)
 25.7855 +	            	b = glXWaitForSbcOML_Impl(dpy, drawable, target_sbc, ust, msc, sbc);
 25.7856 +	            PostGLXHook(GLE_CURRENT_FUNCTION);
 25.7857 +	            return b;
 25.7858 +			}
 25.7859 +
 25.7860 +            // GLX_MESA_swap_control
 25.7861 +            int OVR::GLEContext::glXGetSwapIntervalMESA_Hook()
 25.7862 +		    {
 25.7863 +	            int i = 0;
 25.7864 +                if(glXGetSwapIntervalMESA_Impl)
 25.7865 +	            	i = glXGetSwapIntervalMESA_Impl();
 25.7866 +	            PostGLXHook(GLE_CURRENT_FUNCTION);
 25.7867 +                return i;
 25.7868 +		    }
 25.7869 +
 25.7870 +
 25.7871 +            int OVR::GLEContext::glXSwapIntervalMESA_Hook(unsigned int interval)
 25.7872 +		    {
 25.7873 +	            int i = 0;
 25.7874 +                if(glXSwapIntervalMESA_Impl)
 25.7875 +	            	i = glXSwapIntervalMESA_Impl(interval);
 25.7876 +	            PostGLXHook(GLE_CURRENT_FUNCTION);
 25.7877 +                return i;
 25.7878 +		    }
 25.7879 +
 25.7880 +        #endif // defined(GLE_GLX_ENABLED)
 25.7881 +
 25.7882 +    #endif // GLE_HOOKING_ENABLED
 25.7883 +
 25.7884 +//} // namespace OVR
 25.7885 +
 25.7886 +
 25.7887 +
    26.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    26.2 +++ b/LibOVR/Src/CAPI/GL/CAPI_GLE.h	Wed Jan 14 06:51:16 2015 +0200
    26.3 @@ -0,0 +1,2003 @@
    26.4 +/************************************************************************************
    26.5 +
    26.6 +Filename    :   CAPI_GLE.h
    26.7 +Content     :   OpenGL extensions support. Implements a stripped down glew-like 
    26.8 +                interface with some additional functionality.
    26.9 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   26.10 +
   26.11 +Licensed under the Apache License, Version 2.0 (the "License");
   26.12 +you may not use this file except in compliance with the License.
   26.13 +You may obtain a copy of the License at
   26.14 +
   26.15 +http://www.apache.org/licenses/LICENSE-2.0
   26.16 +
   26.17 +Unless required by applicable law or agreed to in writing, software
   26.18 +distributed under the License is distributed on an "AS IS" BASIS,
   26.19 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   26.20 +See the License for the specific language governing permissions and
   26.21 +limitations under the License.
   26.22 +
   26.23 +************************************************************************************/
   26.24 +
   26.25 +// This file provides functionality similar to a reduced version of GLEW, plus some
   26.26 +// additional functionality that's useful to us, such as function hooking.
   26.27 +
   26.28 +#ifndef INC_OVR_CAPI_GLE_h
   26.29 +#define INC_OVR_CAPI_GLE_h
   26.30 +
   26.31 +
   26.32 +#include "../../Kernel/OVR_Types.h"
   26.33 +#include "CAPI_GLE_GL.h"
   26.34 +
   26.35 +
   26.36 +///////////////////////////////////////////////////////////////////////////////
   26.37 +// How to use this functionality
   26.38 +//
   26.39 +// - You #include this header instead of gl.h, glext.h, wglext.h (Windows), gl3.h (Apple), gl3ext.h (Apple), glx.h (Unix), and glxext.h (Unix).
   26.40 +//   Currently you still would #include <Windows.h> for the base wgl functions on Windows and OpenGL.h or NSOpenGL for the 
   26.41 +//   base Apple cgl functions.
   26.42 +// 
   26.43 +// - You call OpenGL functions just like you would if you were directly using OpenGL 
   26.44 +//   headers and declarations. The difference is that this module automatically loads
   26.45 +//   extensions on init and so you should never need to use GetProcAddress, wglGetProcAddress, etc.
   26.46 +//
   26.47 +// - OpenGL 1.1 functions can be called unilaterally without checking if they are present,
   26.48 +//   as it's assumed they are always present.
   26.49 +//
   26.50 +// - In order to use an OpenGL 1.2 or later function you can check the GLEContext::WholeVersion
   26.51 +//   variable to tell what version of OpenGL is present and active. Example usage:
   26.52 +//       if(GLEContext::GetCurrentContext()->WholeVersion >= 302) // If OpenGL 3.2 or later...
   26.53 +//
   26.54 +// - In order to use an OpenGL extension, you can check the GLE_ helper macro that exists for each
   26.55 +//   extension. For example, in order to check of the KHR_debug is present you could do this:
   26.56 +//        if(GLE_KHR_debug) ... 
   26.57 +//   You cannot check for the presence of extensions by testing the function pointer, because
   26.58 +//   when hooking is enabled then we aren't using function pointers and thus all functions will
   26.59 +//   look like they are present. 
   26.60 +//
   26.61 +// - You can test if the OpenGL implementation is OpenGL ES by checking the GLEContext IsGLES
   26.62 +//   member variable. For example: if(GLEContext::GetCurrentContext()->IsGLES) ...
   26.63 +//
   26.64 +// - You can test if the OpenGL implementation is a core profile ES by checking the GLEContext IsCoreProfile
   26.65 +//   member variable. For example: if(GLEContext::GetCurrentContext()->IsCoreProfile) ...
   26.66 +//
   26.67 +///////////////////////////////////////////////////////////////////////////////
   26.68 +
   26.69 +
   26.70 +///////////////////////////////////////////////////////////////////////////////
   26.71 +// How to add support for additional functions to this module.
   26.72 +//
   26.73 +// For an example of how to do this, search the source files for all cases of KHR_Debug and just copy
   26.74 +// the things that it does but for your new extension.
   26.75 +//
   26.76 +//     1) Add the appropriate extension declaration to CAPI_GLE_GL.h, preferably by
   26.77 +//        copying it from the standard header file it normally comes from. If it's
   26.78 +//        platform-specific (e.g. a Windows wgl function) then make sure it's declared
   26.79 +//        within the given platform section. Note that there are potentially #defines, typedefs, 
   26.80 +//        function typedefs, and function #defines. There is always a GLE_ macro declared which
   26.81 +//        lets the user know at runtime whether the extension is present.
   26.82 +//        e.g.  #ifndef GL_KHR_debug
   26.83 +//                  #define GL_KHR_debug 1
   26.84 +//                  #define GL_CONTEXT_FLAG_DEBUG_BIT 0x00000002 etc.
   26.85 +//                  typedef void (GLAPIENTRY * PFNGLPOPDEBUGGROUPPROC) ();
   26.86 +//                  #define glPopDebugGroup GLEGetCurrentFunction(glPopDebugGroup)
   26.87 +//                  #define GLE_KHR_debug GLEGetCurrentVariable(gl_KHR_debug)
   26.88 +//              #endif etc.
   26.89 +//
   26.90 +//     2) Add a hook function for in the hook section of the GLEContext class in this header, 
   26.91 +//        ideally in the same order it's declared in the CAPI_GLE_GL.h so it's easily readable.
   26.92 +//        e.g. void glDebugMessageControl_Hook(GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint* ids, GLboolean enabled); etc.
   26.93 +//
   26.94 +//     3) Add a declaration for each interface function to the GLEContext class in this header.
   26.95 +//        e.g. PFNGLDEBUGMESSAGECALLBACKPROC glDebugMessageCallback_Impl; etc.
   26.96 +//
   26.97 +//     4) Add code to GLEContext::InitExtensionLoad to load the function pointer.
   26.98 +//        e.g. GLELoadProc(glDebugMessageCallback_Impl, glDebugMessageCallback); etc.
   26.99 +//
  26.100 +//     5) Add code to GLEContext::InitExtensionSupport to detect the extension support.
  26.101 +//        e.g. { gl_KHR_debug, "GL_KHR_debug" }, etc.
  26.102 +//
  26.103 +//     6) Implement the GLEContext hook function(s) you declared.
  26.104 +//        e.g.  void OVR::GLEContext::glDebugMessageControl_Hook(GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint* ids, GLboolean enabled)
  26.105 +//              {
  26.106 +//                 if(glDebugMessageControl_Impl)
  26.107 +//                    glDebugMessageControl_Impl(source, type, severity, count, ids, enabled);
  26.108 +//                 PostHook();
  26.109 +//              }
  26.110 +//
  26.111 +// Note that if the extension is a WGL-, GLX-, or CGL-specific extension, they are handled like above 
  26.112 +// but are in their own section below the section for regular OpenGL extensions.
  26.113 +// 
  26.114 +// In some cases the given interface may already be present by currently commented out,
  26.115 +// in which case you can simply un-comment it to enable it.
  26.116 +///////////////////////////////////////////////////////////////////////////////
  26.117 +
  26.118 +
  26.119 +namespace OVR
  26.120 +{
  26.121 +    // Generic OpenGL GetProcAddress function interface. Maps to platform-specific functionality
  26.122 +    // internally. On Windows this is equivalent to wglGetProcAddress as opposed to global GetProcAddress.
  26.123 +    void* GLEGetProcAddress(const char* name);
  26.124 +
  26.125 +
  26.126 +    // GLEContext
  26.127 +    //
  26.128 +    // Manages a collection of OpenGL extension interfaces.
  26.129 +    // If the application has multiple OpenGL unrelated contexts then you will want to create a
  26.130 +    // different instance of this class for each one you intend to use it with. 
  26.131 +    //
  26.132 +    // Example usage:
  26.133 +    //     GLEContext gGLEContext;
  26.134 +    //
  26.135 +    //     GLEContext::SetCurrentContext(&gGLEContext);
  26.136 +    //     gGLEContext.PlatformInit(); // Initializes WGL/GLX/etc. platform-specific OpenGL functionality
  26.137 +    //
  26.138 +    //     if(GLE_WGL_ARB_create_context) // If wglCreateContextAttribsARB is available...
  26.139 +    //     {
  26.140 +    //         int attribList[] = { WGL_CONTEXT_MAJOR_VERSION_ARB, 3, WGL_CONTEXT_MINOR_VERSION_ARB, 2, WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_DEBUG_BIT_ARB, None };
  26.141 +    //         HGLRC h = wglCreateContextAttribsARB(hDC, 0, attribList);
  26.142 +    //         [...]
  26.143 +    //     }
  26.144 +    //
  26.145 +    //     gGLEContext.Init(); // Must be called after an OpenGL context has been created.
  26.146 +    //
  26.147 +    //     if(GLE_WHOLE_VERSION() >= 302) // If OpenGL 3.2 or later
  26.148 +    //     {
  26.149 +    //         glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, someTexture, 0); // This is an OpenGL 3.2 function.
  26.150 +    //         [...]
  26.151 +    //     }
  26.152 +    //
  26.153 +    //     if(GLE_GL_ARB_texture_multisample) // If the GL_ARB_texture_multisample extension is available...
  26.154 +    //     {
  26.155 +    //         glEnable(GL_SAMPLE_MASK);
  26.156 +    //         glSampleMaski(0, 0x1);
  26.157 +    //         [...]
  26.158 +    //     }
  26.159 +    //
  26.160 +    //     [...]
  26.161 +    //
  26.162 +    //     gGLEContext.Shutdown();
  26.163 +    //
  26.164 +    GLE_CLASS_EXPORT class GLEContext
  26.165 +    {
  26.166 +    public:
  26.167 +        GLEContext();
  26.168 +       ~GLEContext();
  26.169 +      
  26.170 +        // Initializes platform-specific functionality (e.g. Windows WGL, Unix GLX, Android EGL, Apple CGL).
  26.171 +        // You would typically call this before creating an OpenGL context and using platform-specific functions.
  26.172 +        void PlatformInit();
  26.173 +        bool IsPlatformInitialized() const;
  26.174 +
  26.175 +        // Loads all the extensions from the current OpenGL context. This must be called after an OpenGL context 
  26.176 +        // has been created and made current.
  26.177 +        void Init();
  26.178 +        bool IsInitialized() const;
  26.179 +        
  26.180 +        // Clears all the extensions initialized by PlatformInit and Init. 
  26.181 +        void Shutdown();
  26.182 +
  26.183 +        void SetEnableHookGetError(bool enabled)
  26.184 +            { EnableHookGetError = enabled; }
  26.185 +
  26.186 +        // Returns the default instance of this class.
  26.187 +        static GLEContext* GetCurrentContext();
  26.188 +        
  26.189 +        // Sets the default instance of this class. This should be called after enabling a new OpenGL context.
  26.190 +        // This sets the current GLEContext; it does not set the underlying OpenGL context itself.
  26.191 +        static void SetCurrentContext(GLEContext*);
  26.192 +        
  26.193 +    public:
  26.194 +        // OpenGL version information
  26.195 +        int   MajorVersion;             // Best guess at major version
  26.196 +        int   MinorVersion;             // Best guess at minor version
  26.197 +        int   WholeVersion;             // Equals ((MajorVersion * 100) + MinorVersion). Example usage: if(glv.WholeVersion >= 302) // If OpenGL v3.02+ ...
  26.198 +        bool  IsGLES;                   // Open GL ES?
  26.199 +        bool  IsCoreProfile;            // Is the current OpenGL context a core profile context? Its trueness may be a false positive but will never be a false negative.
  26.200 +        bool  EnableHookGetError;       // If enabled then hook functions call glGetError after making the call.
  26.201 +
  26.202 +        int   PlatformMajorVersion;     // GLX/WGL/EGL/CGL version. Not the same as OpenGL version.
  26.203 +        int   PlatformMinorVersion;
  26.204 +        int   PlatformWholeVersion;
  26.205 +
  26.206 +        void InitVersion();             // Initializes the version information (e.g. MajorVersion). Called by the public Init function.
  26.207 +        void InitExtensionLoad();       // Loads the function addresses into the function pointers.
  26.208 +        void InitExtensionSupport();    // Loads the boolean extension support booleans.
  26.209 +        
  26.210 +        void InitPlatformVersion();
  26.211 +        void InitPlatformExtensionLoad();
  26.212 +        void InitPlatformExtensionSupport();
  26.213 +
  26.214 +    public:
  26.215 +        // GL_VERSION_1_1
  26.216 +        // Not normally included because all OpenGL 1.1 functionality is always present. But if we have 
  26.217 +        // hooking enabled then we implement our own version of each function.
  26.218 +        #if defined(GLE_HOOKING_ENABLED)
  26.219 +          //void PreHook(const char* functionName);             // Called at the beginning of a hook function.
  26.220 +            void PostHook(const char* functionName);            // Called at the end of a hook function.
  26.221 +
  26.222 +            void            glAccum_Hook(GLenum op, GLfloat value);
  26.223 +            void            glAlphaFunc_Hook(GLenum func, GLclampf ref);
  26.224 +            GLboolean       glAreTexturesResident_Hook(GLsizei n, const GLuint *textures, GLboolean *residences);
  26.225 +            void            glArrayElement_Hook(GLint i);
  26.226 +            void            glBegin_Hook(GLenum mode);
  26.227 +            void            glBindTexture_Hook(GLenum target, GLuint texture);
  26.228 +            void            glBitmap_Hook(GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte *bitmap);
  26.229 +            void            glBlendFunc_Hook(GLenum sfactor, GLenum dfactor);
  26.230 +            void            glCallList_Hook(GLuint list);
  26.231 +            void            glCallLists_Hook(GLsizei n, GLenum type, const void *lists);
  26.232 +            void            glClear_Hook(GLbitfield mask);
  26.233 +            void            glClearAccum_Hook(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
  26.234 +            void            glClearColor_Hook(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
  26.235 +            void            glClearDepth_Hook(GLclampd depth);
  26.236 +            void            glClearIndex_Hook(GLfloat c);
  26.237 +            void            glClearStencil_Hook(GLint s);
  26.238 +            void            glClipPlane_Hook(GLenum plane, const GLdouble *equation);
  26.239 +            void            glColor3b_Hook(GLbyte red, GLbyte green, GLbyte blue);
  26.240 +            void            glColor3bv_Hook(const GLbyte *v);
  26.241 +            void            glColor3d_Hook(GLdouble red, GLdouble green, GLdouble blue);
  26.242 +            void            glColor3dv_Hook(const GLdouble *v);
  26.243 +            void            glColor3f_Hook(GLfloat red, GLfloat green, GLfloat blue);
  26.244 +            void            glColor3fv_Hook(const GLfloat *v);
  26.245 +            void            glColor3i_Hook(GLint red, GLint green, GLint blue);
  26.246 +            void            glColor3iv_Hook(const GLint *v);
  26.247 +            void            glColor3s_Hook(GLshort red, GLshort green, GLshort blue);
  26.248 +            void            glColor3sv_Hook(const GLshort *v);
  26.249 +            void            glColor3ub_Hook(GLubyte red, GLubyte green, GLubyte blue);
  26.250 +            void            glColor3ubv_Hook(const GLubyte *v);
  26.251 +            void            glColor3ui_Hook(GLuint red, GLuint green, GLuint blue);
  26.252 +            void            glColor3uiv_Hook(const GLuint *v);
  26.253 +            void            glColor3us_Hook(GLushort red, GLushort green, GLushort blue);
  26.254 +            void            glColor3usv_Hook(const GLushort *v);
  26.255 +            void            glColor4b_Hook(GLbyte red, GLbyte green, GLbyte blue, GLbyte alpha);
  26.256 +            void            glColor4bv_Hook(const GLbyte *v);
  26.257 +            void            glColor4d_Hook(GLdouble red, GLdouble green, GLdouble blue, GLdouble alpha);
  26.258 +            void            glColor4dv_Hook(const GLdouble *v);
  26.259 +            void            glColor4f_Hook(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
  26.260 +            void            glColor4fv_Hook(const GLfloat *v);
  26.261 +            void            glColor4i_Hook(GLint red, GLint green, GLint blue, GLint alpha);
  26.262 +            void            glColor4iv_Hook(const GLint *v);
  26.263 +            void            glColor4s_Hook(GLshort red, GLshort green, GLshort blue, GLshort alpha);
  26.264 +            void            glColor4sv_Hook(const GLshort *v);
  26.265 +            void            glColor4ub_Hook(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha);
  26.266 +            void            glColor4ubv_Hook(const GLubyte *v);
  26.267 +            void            glColor4ui_Hook(GLuint red, GLuint green, GLuint blue, GLuint alpha);
  26.268 +            void            glColor4uiv_Hook(const GLuint *v);
  26.269 +            void            glColor4us_Hook(GLushort red, GLushort green, GLushort blue, GLushort alpha);
  26.270 +            void            glColor4usv_Hook(const GLushort *v);
  26.271 +            void            glColorMask_Hook(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
  26.272 +            void            glColorMaterial_Hook(GLenum face, GLenum mode);
  26.273 +            void            glColorPointer_Hook(GLint size, GLenum type, GLsizei stride, const void *pointer);
  26.274 +            void            glCopyPixels_Hook(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type);
  26.275 +            void            glCopyTexImage1D_Hook(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLint border);
  26.276 +            void            glCopyTexImage2D_Hook(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
  26.277 +            void            glCopyTexSubImage1D_Hook(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);
  26.278 +            void            glCopyTexSubImage2D_Hook(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
  26.279 +            void            glCullFace_Hook(GLenum mode);
  26.280 +            void            glDeleteLists_Hook(GLuint list, GLsizei range);
  26.281 +            void            glDeleteTextures_Hook(GLsizei n, const GLuint *textures);
  26.282 +            void            glDepthFunc_Hook(GLenum func);
  26.283 +            void            glDepthMask_Hook(GLboolean flag);
  26.284 +            void            glDepthRange_Hook(GLclampd zNear, GLclampd zFar);
  26.285 +            void            glDisable_Hook(GLenum cap);
  26.286 +            void            glDisableClientState_Hook(GLenum array);
  26.287 +            void            glDrawArrays_Hook(GLenum mode, GLint first, GLsizei count);
  26.288 +            void            glDrawBuffer_Hook(GLenum mode);
  26.289 +            void            glDrawElements_Hook(GLenum mode, GLsizei count, GLenum type, const void *indices);
  26.290 +            void            glDrawPixels_Hook(GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
  26.291 +            void            glEdgeFlag_Hook(GLboolean flag);
  26.292 +            void            glEdgeFlagPointer_Hook(GLsizei stride, const void *pointer);
  26.293 +            void            glEdgeFlagv_Hook(const GLboolean *flag);
  26.294 +            void            glEnable_Hook(GLenum cap);
  26.295 +            void            glEnableClientState_Hook(GLenum array);
  26.296 +            void            glEnd_Hook(void);
  26.297 +            void            glEndList_Hook(void);
  26.298 +            void            glEvalCoord1d_Hook(GLdouble u);
  26.299 +            void            glEvalCoord1dv_Hook(const GLdouble *u);
  26.300 +            void            glEvalCoord1f_Hook(GLfloat u);
  26.301 +            void            glEvalCoord1fv_Hook(const GLfloat *u);
  26.302 +            void            glEvalCoord2d_Hook(GLdouble u, GLdouble v);
  26.303 +            void            glEvalCoord2dv_Hook(const GLdouble *u);
  26.304 +            void            glEvalCoord2f_Hook(GLfloat u, GLfloat v);
  26.305 +            void            glEvalCoord2fv_Hook(const GLfloat *u);
  26.306 +            void            glEvalMesh1_Hook(GLenum mode, GLint i1, GLint i2);
  26.307 +            void            glEvalMesh2_Hook(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2);
  26.308 +            void            glEvalPoint1_Hook(GLint i);
  26.309 +            void            glEvalPoint2_Hook(GLint i, GLint j);
  26.310 +            void            glFeedbackBuffer_Hook(GLsizei size, GLenum type, GLfloat *buffer);
  26.311 +            void            glFinish_Hook(void);
  26.312 +            void            glFlush_Hook(void);
  26.313 +            void            glFogf_Hook(GLenum pname, GLfloat param);
  26.314 +            void            glFogfv_Hook(GLenum pname, const GLfloat *params);
  26.315 +            void            glFogi_Hook(GLenum pname, GLint param);
  26.316 +            void            glFogiv_Hook(GLenum pname, const GLint *params);
  26.317 +            void            glFrontFace_Hook(GLenum mode);
  26.318 +            void            glFrustum_Hook(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
  26.319 +            GLuint          glGenLists_Hook(GLsizei range);
  26.320 +            void            glGenTextures_Hook(GLsizei n, GLuint *textures);
  26.321 +            void            glGetBooleanv_Hook(GLenum pname, GLboolean *params);
  26.322 +            void            glGetClipPlane_Hook(GLenum plane, GLdouble *equation);
  26.323 +            void            glGetDoublev_Hook(GLenum pname, GLdouble *params);
  26.324 +            GLenum          glGetError_Hook(void);
  26.325 +            void            glGetFloatv_Hook(GLenum pname, GLfloat *params);
  26.326 +            void            glGetIntegerv_Hook(GLenum pname, GLint *params);
  26.327 +            void            glGetLightfv_Hook(GLenum light, GLenum pname, GLfloat *params);
  26.328 +            void            glGetLightiv_Hook(GLenum light, GLenum pname, GLint *params);
  26.329 +            void            glGetMapdv_Hook(GLenum target, GLenum query, GLdouble *v);
  26.330 +            void            glGetMapfv_Hook(GLenum target, GLenum query, GLfloat *v);
  26.331 +            void            glGetMapiv_Hook(GLenum target, GLenum query, GLint *v);
  26.332 +            void            glGetMaterialfv_Hook(GLenum face, GLenum pname, GLfloat *params);
  26.333 +            void            glGetMaterialiv_Hook(GLenum face, GLenum pname, GLint *params);
  26.334 +            void            glGetPixelMapfv_Hook(GLenum map, GLfloat *values);
  26.335 +            void            glGetPixelMapuiv_Hook(GLenum map, GLuint *values);
  26.336 +            void            glGetPixelMapusv_Hook(GLenum map, GLushort *values);
  26.337 +            void            glGetPointerv_Hook(GLenum pname, void* *params);
  26.338 +            void            glGetPolygonStipple_Hook(GLubyte *mask);
  26.339 +            const GLubyte * glGetString_Hook(GLenum name);
  26.340 +            void            glGetTexEnvfv_Hook(GLenum target, GLenum pname, GLfloat *params);
  26.341 +            void            glGetTexEnviv_Hook(GLenum target, GLenum pname, GLint *params);
  26.342 +            void            glGetTexGendv_Hook(GLenum coord, GLenum pname, GLdouble *params);
  26.343 +            void            glGetTexGenfv_Hook(GLenum coord, GLenum pname, GLfloat *params);
  26.344 +            void            glGetTexGeniv_Hook(GLenum coord, GLenum pname, GLint *params);
  26.345 +            void            glGetTexImage_Hook(GLenum target, GLint level, GLenum format, GLenum type, void *pixels);
  26.346 +            void            glGetTexLevelParameterfv_Hook(GLenum target, GLint level, GLenum pname, GLfloat *params);
  26.347 +            void            glGetTexLevelParameteriv_Hook(GLenum target, GLint level, GLenum pname, GLint *params);
  26.348 +            void            glGetTexParameterfv_Hook(GLenum target, GLenum pname, GLfloat *params);
  26.349 +            void            glGetTexParameteriv_Hook(GLenum target, GLenum pname, GLint *params);
  26.350 +            void            glHint_Hook(GLenum target, GLenum mode);
  26.351 +            void            glIndexMask_Hook(GLuint mask);
  26.352 +            void            glIndexPointer_Hook(GLenum type, GLsizei stride, const void *pointer);
  26.353 +            void            glIndexd_Hook(GLdouble c);
  26.354 +            void            glIndexdv_Hook(const GLdouble *c);
  26.355 +            void            glIndexf_Hook(GLfloat c);
  26.356 +            void            glIndexfv_Hook(const GLfloat *c);
  26.357 +            void            glIndexi_Hook(GLint c);
  26.358 +            void            glIndexiv_Hook(const GLint *c);
  26.359 +            void            glIndexs_Hook(GLshort c);
  26.360 +            void            glIndexsv_Hook(const GLshort *c);
  26.361 +            void            glIndexub_Hook(GLubyte c);
  26.362 +            void            glIndexubv_Hook(const GLubyte *c);
  26.363 +            void            glInitNames_Hook(void);
  26.364 +            void            glInterleavedArrays_Hook(GLenum format, GLsizei stride, const void *pointer);
  26.365 +            GLboolean       glIsEnabled_Hook(GLenum cap);
  26.366 +            GLboolean       glIsList_Hook(GLuint list);
  26.367 +            GLboolean       glIsTexture_Hook(GLuint texture);
  26.368 +            void            glLightModelf_Hook(GLenum pname, GLfloat param);
  26.369 +            void            glLightModelfv_Hook(GLenum pname, const GLfloat *params);
  26.370 +            void            glLightModeli_Hook(GLenum pname, GLint param);
  26.371 +            void            glLightModeliv_Hook(GLenum pname, const GLint *params);
  26.372 +            void            glLightf_Hook(GLenum light, GLenum pname, GLfloat param);
  26.373 +            void            glLightfv_Hook(GLenum light, GLenum pname, const GLfloat *params);
  26.374 +            void            glLighti_Hook(GLenum light, GLenum pname, GLint param);
  26.375 +            void            glLightiv_Hook(GLenum light, GLenum pname, const GLint *params);
  26.376 +            void            glLineStipple_Hook(GLint factor, GLushort pattern);
  26.377 +            void            glLineWidth_Hook(GLfloat width);
  26.378 +            void            glListBase_Hook(GLuint base);
  26.379 +            void            glLoadIdentity_Hook(void);
  26.380 +            void            glLoadMatrixd_Hook(const GLdouble *m);
  26.381 +            void            glLoadMatrixf_Hook(const GLfloat *m);
  26.382 +            void            glLoadName_Hook(GLuint name);
  26.383 +            void            glLogicOp_Hook(GLenum opcode);
  26.384 +            void            glMap1d_Hook(GLenum target, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points);
  26.385 +            void            glMap1f_Hook(GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points);
  26.386 +            void            glMap2d_Hook(GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points);
  26.387 +            void            glMap2f_Hook(GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points);
  26.388 +            void            glMapGrid1d_Hook(GLint un, GLdouble u1, GLdouble u2);
  26.389 +            void            glMapGrid1f_Hook(GLint un, GLfloat u1, GLfloat u2);
  26.390 +            void            glMapGrid2d_Hook(GLint un, GLdouble u1, GLdouble u2, GLint vn, GLdouble v1, GLdouble v2);
  26.391 +            void            glMapGrid2f_Hook(GLint un, GLfloat u1, GLfloat u2, GLint vn, GLfloat v1, GLfloat v2);
  26.392 +            void            glMaterialf_Hook(GLenum face, GLenum pname, GLfloat param);
  26.393 +            void            glMaterialfv_Hook(GLenum face, GLenum pname, const GLfloat *params);
  26.394 +            void            glMateriali_Hook(GLenum face, GLenum pname, GLint param);
  26.395 +            void            glMaterialiv_Hook(GLenum face, GLenum pname, const GLint *params);
  26.396 +            void            glMatrixMode_Hook(GLenum mode);
  26.397 +            void            glMultMatrixd_Hook(const GLdouble *m);
  26.398 +            void            glMultMatrixf_Hook(const GLfloat *m);
  26.399 +            void            glNewList_Hook(GLuint list, GLenum mode);
  26.400 +            void            glNormal3b_Hook(GLbyte nx, GLbyte ny, GLbyte nz);
  26.401 +            void            glNormal3bv_Hook(const GLbyte *v);
  26.402 +            void            glNormal3d_Hook(GLdouble nx, GLdouble ny, GLdouble nz);
  26.403 +            void            glNormal3dv_Hook(const GLdouble *v);
  26.404 +            void            glNormal3f_Hook(GLfloat nx, GLfloat ny, GLfloat nz);
  26.405 +            void            glNormal3fv_Hook(const GLfloat *v);
  26.406 +            void            glNormal3i_Hook(GLint nx, GLint ny, GLint nz);
  26.407 +            void            glNormal3iv_Hook(const GLint *v);
  26.408 +            void            glNormal3s_Hook(GLshort nx, GLshort ny, GLshort nz);
  26.409 +            void            glNormal3sv_Hook(const GLshort *v);
  26.410 +            void            glNormalPointer_Hook(GLenum type, GLsizei stride, const void *pointer);
  26.411 +            void            glOrtho_Hook(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
  26.412 +            void            glPassThrough_Hook(GLfloat token);
  26.413 +            void            glPixelMapfv_Hook(GLenum map, GLsizei mapsize, const GLfloat *values);
  26.414 +            void            glPixelMapuiv_Hook(GLenum map, GLsizei mapsize, const GLuint *values);
  26.415 +            void            glPixelMapusv_Hook(GLenum map, GLsizei mapsize, const GLushort *values);
  26.416 +            void            glPixelStoref_Hook(GLenum pname, GLfloat param);
  26.417 +            void            glPixelStorei_Hook(GLenum pname, GLint param);
  26.418 +            void            glPixelTransferf_Hook(GLenum pname, GLfloat param);
  26.419 +            void            glPixelTransferi_Hook(GLenum pname, GLint param);
  26.420 +            void            glPixelZoom_Hook(GLfloat xfactor, GLfloat yfactor);
  26.421 +            void            glPointSize_Hook(GLfloat size);
  26.422 +            void            glPolygonMode_Hook(GLenum face, GLenum mode);
  26.423 +            void            glPolygonOffset_Hook(GLfloat factor, GLfloat units);
  26.424 +            void            glPolygonStipple_Hook(const GLubyte *mask);
  26.425 +            void            glPopAttrib_Hook(void);
  26.426 +            void            glPopClientAttrib_Hook(void);
  26.427 +            void            glPopMatrix_Hook(void);
  26.428 +            void            glPopName_Hook(void);
  26.429 +            void            glPrioritizeTextures_Hook(GLsizei n, const GLuint *textures, const GLclampf *priorities);
  26.430 +            void            glPushAttrib_Hook(GLbitfield mask);
  26.431 +            void            glPushClientAttrib_Hook(GLbitfield mask);
  26.432 +            void            glPushMatrix_Hook(void);
  26.433 +            void            glPushName_Hook(GLuint name);
  26.434 +            void            glRasterPos2d_Hook(GLdouble x, GLdouble y);
  26.435 +            void            glRasterPos2dv_Hook(const GLdouble *v);
  26.436 +            void            glRasterPos2f_Hook(GLfloat x, GLfloat y);
  26.437 +            void            glRasterPos2fv_Hook(const GLfloat *v);
  26.438 +            void            glRasterPos2i_Hook(GLint x, GLint y);
  26.439 +            void            glRasterPos2iv_Hook(const GLint *v);
  26.440 +            void            glRasterPos2s_Hook(GLshort x, GLshort y);
  26.441 +            void            glRasterPos2sv_Hook(const GLshort *v);
  26.442 +            void            glRasterPos3d_Hook(GLdouble x, GLdouble y, GLdouble z);
  26.443 +            void            glRasterPos3dv_Hook(const GLdouble *v);
  26.444 +            void            glRasterPos3f_Hook(GLfloat x, GLfloat y, GLfloat z);
  26.445 +            void            glRasterPos3fv_Hook(const GLfloat *v);
  26.446 +            void            glRasterPos3i_Hook(GLint x, GLint y, GLint z);
  26.447 +            void            glRasterPos3iv_Hook(const GLint *v);
  26.448 +            void            glRasterPos3s_Hook(GLshort x, GLshort y, GLshort z);
  26.449 +            void            glRasterPos3sv_Hook(const GLshort *v);
  26.450 +            void            glRasterPos4d_Hook(GLdouble x, GLdouble y, GLdouble z, GLdouble w);
  26.451 +            void            glRasterPos4dv_Hook(const GLdouble *v);
  26.452 +            void            glRasterPos4f_Hook(GLfloat x, GLfloat y, GLfloat z, GLfloat w);
  26.453 +            void            glRasterPos4fv_Hook(const GLfloat *v);
  26.454 +            void            glRasterPos4i_Hook(GLint x, GLint y, GLint z, GLint w);
  26.455 +            void            glRasterPos4iv_Hook(const GLint *v);
  26.456 +            void            glRasterPos4s_Hook(GLshort x, GLshort y, GLshort z, GLshort w);
  26.457 +            void            glRasterPos4sv_Hook(const GLshort *v);
  26.458 +            void            glReadBuffer_Hook(GLenum mode);
  26.459 +            void            glReadPixels_Hook(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels);
  26.460 +            void            glRectd_Hook(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2);
  26.461 +            void            glRectdv_Hook(const GLdouble *v1, const GLdouble *v2);
  26.462 +            void            glRectf_Hook(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2);
  26.463 +            void            glRectfv_Hook(const GLfloat *v1, const GLfloat *v2);
  26.464 +            void            glRecti_Hook(GLint x1, GLint y1, GLint x2, GLint y2);
  26.465 +            void            glRectiv_Hook(const GLint *v1, const GLint *v2);
  26.466 +            void            glRects_Hook(GLshort x1, GLshort y1, GLshort x2, GLshort y2);
  26.467 +            void            glRectsv_Hook(const GLshort *v1, const GLshort *v2);
  26.468 +            GLint           glRenderMode_Hook(GLenum mode);
  26.469 +            void            glRotated_Hook(GLdouble angle, GLdouble x, GLdouble y, GLdouble z);
  26.470 +            void            glRotatef_Hook(GLfloat angle, GLfloat x, GLfloat y, GLfloat z);
  26.471 +            void            glScaled_Hook(GLdouble x, GLdouble y, GLdouble z);
  26.472 +            void            glScalef_Hook(GLfloat x, GLfloat y, GLfloat z);
  26.473 +            void            glScissor_Hook(GLint x, GLint y, GLsizei width, GLsizei height);
  26.474 +            void            glSelectBuffer_Hook(GLsizei size, GLuint *buffer);
  26.475 +            void            glShadeModel_Hook(GLenum mode);
  26.476 +            void            glStencilFunc_Hook(GLenum func, GLint ref, GLuint mask);
  26.477 +            void            glStencilMask_Hook(GLuint mask);
  26.478 +            void            glStencilOp_Hook(GLenum fail, GLenum zfail, GLenum zpass);
  26.479 +            void            glTexCoord1d_Hook(GLdouble s);
  26.480 +            void            glTexCoord1dv_Hook(const GLdouble *v);
  26.481 +            void            glTexCoord1f_Hook(GLfloat s);
  26.482 +            void            glTexCoord1fv_Hook(const GLfloat *v);
  26.483 +            void            glTexCoord1i_Hook(GLint s);
  26.484 +            void            glTexCoord1iv_Hook(const GLint *v);
  26.485 +            void            glTexCoord1s_Hook(GLshort s);
  26.486 +            void            glTexCoord1sv_Hook(const GLshort *v);
  26.487 +            void            glTexCoord2d_Hook(GLdouble s, GLdouble t);
  26.488 +            void            glTexCoord2dv_Hook(const GLdouble *v);
  26.489 +            void            glTexCoord2f_Hook(GLfloat s, GLfloat t);
  26.490 +            void            glTexCoord2fv_Hook(const GLfloat *v);
  26.491 +            void            glTexCoord2i_Hook(GLint s, GLint t);
  26.492 +            void            glTexCoord2iv_Hook(const GLint *v);
  26.493 +            void            glTexCoord2s_Hook(GLshort s, GLshort t);
  26.494 +            void            glTexCoord2sv_Hook(const GLshort *v);
  26.495 +            void            glTexCoord3d_Hook(GLdouble s, GLdouble t, GLdouble r);
  26.496 +            void            glTexCoord3dv_Hook(const GLdouble *v);
  26.497 +            void            glTexCoord3f_Hook(GLfloat s, GLfloat t, GLfloat r);
  26.498 +            void            glTexCoord3fv_Hook(const GLfloat *v);
  26.499 +            void            glTexCoord3i_Hook(GLint s, GLint t, GLint r);
  26.500 +            void            glTexCoord3iv_Hook(const GLint *v);
  26.501 +            void            glTexCoord3s_Hook(GLshort s, GLshort t, GLshort r);
  26.502 +            void            glTexCoord3sv_Hook(const GLshort *v);
  26.503 +            void            glTexCoord4d_Hook(GLdouble s, GLdouble t, GLdouble r, GLdouble q);
  26.504 +            void            glTexCoord4dv_Hook(const GLdouble *v);
  26.505 +            void            glTexCoord4f_Hook(GLfloat s, GLfloat t, GLfloat r, GLfloat q);
  26.506 +            void            glTexCoord4fv_Hook(const GLfloat *v);
  26.507 +            void            glTexCoord4i_Hook(GLint s, GLint t, GLint r, GLint q);
  26.508 +            void            glTexCoord4iv_Hook(const GLint *v);
  26.509 +            void            glTexCoord4s_Hook(GLshort s, GLshort t, GLshort r, GLshort q);
  26.510 +            void            glTexCoord4sv_Hook(const GLshort *v);
  26.511 +            void            glTexCoordPointer_Hook(GLint size, GLenum type, GLsizei stride, const void *pointer);
  26.512 +            void            glTexEnvf_Hook(GLenum target, GLenum pname, GLfloat param);
  26.513 +            void            glTexEnvfv_Hook(GLenum target, GLenum pname, const GLfloat *params);
  26.514 +            void            glTexEnvi_Hook(GLenum target, GLenum pname, GLint param);
  26.515 +            void            glTexEnviv_Hook(GLenum target, GLenum pname, const GLint *params);
  26.516 +            void            glTexGend_Hook(GLenum coord, GLenum pname, GLdouble param);
  26.517 +            void            glTexGendv_Hook(GLenum coord, GLenum pname, const GLdouble *params);
  26.518 +            void            glTexGenf_Hook(GLenum coord, GLenum pname, GLfloat param);
  26.519 +            void            glTexGenfv_Hook(GLenum coord, GLenum pname, const GLfloat *params);
  26.520 +            void            glTexGeni_Hook(GLenum coord, GLenum pname, GLint param);
  26.521 +            void            glTexGeniv_Hook(GLenum coord, GLenum pname, const GLint *params);
  26.522 +            void            glTexImage1D_Hook(GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const void *pixels);
  26.523 +            void            glTexImage2D_Hook(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels);
  26.524 +            void            glTexParameterf_Hook(GLenum target, GLenum pname, GLfloat param);
  26.525 +            void            glTexParameterfv_Hook(GLenum target, GLenum pname, const GLfloat *params);
  26.526 +            void            glTexParameteri_Hook(GLenum target, GLenum pname, GLint param);
  26.527 +            void            glTexParameteriv_Hook(GLenum target, GLenum pname, const GLint *params);
  26.528 +            void            glTexSubImage1D_Hook(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void *pixels);
  26.529 +            void            glTexSubImage2D_Hook(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
  26.530 +            void            glTranslated_Hook(GLdouble x, GLdouble y, GLdouble z);
  26.531 +            void            glTranslatef_Hook(GLfloat x, GLfloat y, GLfloat z);
  26.532 +            void            glVertex2d_Hook(GLdouble x, GLdouble y);
  26.533 +            void            glVertex2dv_Hook(const GLdouble *v);
  26.534 +            void            glVertex2f_Hook(GLfloat x, GLfloat y);
  26.535 +            void            glVertex2fv_Hook(const GLfloat *v);
  26.536 +            void            glVertex2i_Hook(GLint x, GLint y);
  26.537 +            void            glVertex2iv_Hook(const GLint *v);
  26.538 +            void            glVertex2s_Hook(GLshort x, GLshort y);
  26.539 +            void            glVertex2sv_Hook(const GLshort *v);
  26.540 +            void            glVertex3d_Hook(GLdouble x, GLdouble y, GLdouble z);
  26.541 +            void            glVertex3dv_Hook(const GLdouble *v);
  26.542 +            void            glVertex3f_Hook(GLfloat x, GLfloat y, GLfloat z);
  26.543 +            void            glVertex3fv_Hook(const GLfloat *v);
  26.544 +            void            glVertex3i_Hook(GLint x, GLint y, GLint z);
  26.545 +            void            glVertex3iv_Hook(const GLint *v);
  26.546 +            void            glVertex3s_Hook(GLshort x, GLshort y, GLshort z);
  26.547 +            void            glVertex3sv_Hook(const GLshort *v);
  26.548 +            void            glVertex4d_Hook(GLdouble x, GLdouble y, GLdouble z, GLdouble w);
  26.549 +            void            glVertex4dv_Hook(const GLdouble *v);
  26.550 +            void            glVertex4f_Hook(GLfloat x, GLfloat y, GLfloat z, GLfloat w);
  26.551 +            void            glVertex4fv_Hook(const GLfloat *v);
  26.552 +            void            glVertex4i_Hook(GLint x, GLint y, GLint z, GLint w);
  26.553 +            void            glVertex4iv_Hook(const GLint *v);
  26.554 +            void            glVertex4s_Hook(GLshort x, GLshort y, GLshort z, GLshort w);
  26.555 +            void            glVertex4sv_Hook(const GLshort *v);
  26.556 +            void            glVertexPointer_Hook(GLint size, GLenum type, GLsizei stride, const void *pointer);
  26.557 +            void            glViewport_Hook(GLint x, GLint y, GLsizei width, GLsizei height);
  26.558 +
  26.559 +            // GL_VERSION_1_2
  26.560 +            void glBlendColor_Hook(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
  26.561 +            void glBlendEquation_Hook(GLenum mode);
  26.562 +            void glDrawRangeElements_Hook(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices);
  26.563 +            void glTexImage3D_Hook(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
  26.564 +            void glTexSubImage3D_Hook(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels);
  26.565 +            void glCopyTexSubImage3D_Hook(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
  26.566 +
  26.567 +            // GL_VERSION_1_2 deprecated functions
  26.568 +            /* Not currently supported
  26.569 +            void glColorTable_Hook(GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *table);
  26.570 +            void glColorTableParameterfv_Hook(GLenum target, GLenum pname, const GLfloat *params);
  26.571 +            void glColorTableParameteriv_Hook(GLenum target, GLenum pname, const GLint *params);
  26.572 +            void glCopyColorTable_Hook(GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width);
  26.573 +            void glGetColorTable_Hook(GLenum target, GLenum format, GLenum type, GLvoid *table);
  26.574 +            void glGetColorTableParameterfv_Hook(GLenum target, GLenum pname, GLfloat *params);
  26.575 +            void glGetColorTableParameteriv_Hook(GLenum target, GLenum pname, GLint *params);
  26.576 +            void glColorSubTable_Hook(GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid *data);
  26.577 +            void glCopyColorSubTable_Hook(GLenum target, GLsizei start, GLint x, GLint y, GLsizei width);
  26.578 +            void glConvolutionFilter1D_Hook(GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *image);
  26.579 +            void glConvolutionFilter2D_Hook(GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *image);
  26.580 +            void glConvolutionParameterf_Hook(GLenum target, GLenum pname, GLfloat params);
  26.581 +            void glConvolutionParameterfv_Hook(GLenum target, GLenum pname, const GLfloat *params);
  26.582 +            void glConvolutionParameteri_Hook(GLenum target, GLenum pname, GLint params);
  26.583 +            void glConvolutionParameteriv_Hook(GLenum target, GLenum pname, const GLint *params);
  26.584 +            void glCopyConvolutionFilter1D_Hook(GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width);
  26.585 +            void glCopyConvolutionFilter2D_Hook(GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height);
  26.586 +            void glGetConvolutionFilter_Hook(GLenum target, GLenum format, GLenum type, GLvoid *image);
  26.587 +            void glGetConvolutionParameterfv_Hook(GLenum target, GLenum pname, GLfloat *params);
  26.588 +            void glGetConvolutionParameteriv_Hook(GLenum target, GLenum pname, GLint *params);
  26.589 +            void glGetSeparableFilter_Hook(GLenum target, GLenum format, GLenum type, GLvoid *row, GLvoid *column, GLvoid *span);
  26.590 +            void glSeparableFilter2D_Hook(GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *row, const GLvoid *column);
  26.591 +            void glGetHistogram_Hook(GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values);
  26.592 +            void glGetHistogramParameterfv_Hook(GLenum target, GLenum pname, GLfloat *params);
  26.593 +            void glGetHistogramParameteriv_Hook(GLenum target, GLenum pname, GLint *params);
  26.594 +            void glGetMinmax_Hook(GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values);
  26.595 +            void glGetMinmaxParameterfv_Hook(GLenum target, GLenum pname, GLfloat *params);
  26.596 +            void glGetMinmaxParameteriv_Hook(GLenum target, GLenum pname, GLint *params);
  26.597 +            void glHistogram_Hook(GLenum target, GLsizei width, GLenum internalformat, GLboolean sink);
  26.598 +            void glMinmax_Hook(GLenum target, GLenum internalformat, GLboolean sink);
  26.599 +            void glResetHistogram_Hook(GLenum target);
  26.600 +            void glResetMinmax_Hook(GLenum target);
  26.601 +            */
  26.602 +        
  26.603 +            // GL_VERSION_1_3
  26.604 +            void glActiveTexture_Hook(GLenum texture);
  26.605 +            void glSampleCoverage_Hook(GLclampf value, GLboolean invert);
  26.606 +            void glCompressedTexImage3D_Hook(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data);
  26.607 +            void glCompressedTexImage2D_Hook(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data);
  26.608 +            void glCompressedTexImage1D_Hook(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data);
  26.609 +            void glCompressedTexSubImage3D_Hook(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data);
  26.610 +            void glCompressedTexSubImage2D_Hook(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data);
  26.611 +            void glCompressedTexSubImage1D_Hook(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data);
  26.612 +            void glGetCompressedTexImage_Hook(GLenum target, GLint level, GLvoid *img);
  26.613 +
  26.614 +            // GL_VERSION_1_3 deprecated functions
  26.615 +            void glClientActiveTexture_Hook(GLenum texture);
  26.616 +            void glMultiTexCoord1d_Hook(GLenum target, GLdouble s);
  26.617 +            void glMultiTexCoord1dv_Hook(GLenum target, const GLdouble *v);
  26.618 +            void glMultiTexCoord1f_Hook(GLenum target, GLfloat s);
  26.619 +            void glMultiTexCoord1fv_Hook(GLenum target, const GLfloat *v);
  26.620 +            void glMultiTexCoord1i_Hook(GLenum target, GLint s);
  26.621 +            void glMultiTexCoord1iv_Hook(GLenum target, const GLint *v);
  26.622 +            void glMultiTexCoord1s_Hook(GLenum target, GLshort s);
  26.623 +            void glMultiTexCoord1sv_Hook(GLenum target, const GLshort *v);
  26.624 +            void glMultiTexCoord2d_Hook(GLenum target, GLdouble s, GLdouble t);
  26.625 +            void glMultiTexCoord2dv_Hook(GLenum target, const GLdouble *v);
  26.626 +            void glMultiTexCoord2f_Hook(GLenum target, GLfloat s, GLfloat t);
  26.627 +            void glMultiTexCoord2fv_Hook(GLenum target, const GLfloat *v);
  26.628 +            void glMultiTexCoord2i_Hook(GLenum target, GLint s, GLint t);
  26.629 +            void glMultiTexCoord2iv_Hook(GLenum target, const GLint *v);
  26.630 +            void glMultiTexCoord2s_Hook(GLenum target, GLshort s, GLshort t);
  26.631 +            void glMultiTexCoord2sv_Hook(GLenum target, const GLshort *v);
  26.632 +            void glMultiTexCoord3d_Hook(GLenum target, GLdouble s, GLdouble t, GLdouble r);
  26.633 +            void glMultiTexCoord3dv_Hook(GLenum target, const GLdouble *v);
  26.634 +            void glMultiTexCoord3f_Hook(GLenum target, GLfloat s, GLfloat t, GLfloat r);
  26.635 +            void glMultiTexCoord3fv_Hook(GLenum target, const GLfloat *v);
  26.636 +            void glMultiTexCoord3i_Hook(GLenum target, GLint s, GLint t, GLint r);
  26.637 +            void glMultiTexCoord3iv_Hook(GLenum target, const GLint *v);
  26.638 +            void glMultiTexCoord3s_Hook(GLenum target, GLshort s, GLshort t, GLshort r);
  26.639 +            void glMultiTexCoord3sv_Hook(GLenum target, const GLshort *v);
  26.640 +            void glMultiTexCoord4d_Hook(GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q);
  26.641 +            void glMultiTexCoord4dv_Hook(GLenum target, const GLdouble *v);
  26.642 +            void glMultiTexCoord4f_Hook(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q);
  26.643 +            void glMultiTexCoord4fv_Hook(GLenum target, const GLfloat *v);
  26.644 +            void glMultiTexCoord4i_Hook(GLenum target, GLint s, GLint t, GLint r, GLint q);
  26.645 +            void glMultiTexCoord4iv_Hook(GLenum target, const GLint *v);
  26.646 +            void glMultiTexCoord4s_Hook(GLenum target, GLshort s, GLshort t, GLshort r, GLshort q);
  26.647 +            void glMultiTexCoord4sv_Hook(GLenum target, const GLshort *v);
  26.648 +            void glLoadTransposeMatrixf_Hook(const GLfloat *m);
  26.649 +            void glLoadTransposeMatrixd_Hook(const GLdouble *m);
  26.650 +            void glMultTransposeMatrixf_Hook(const GLfloat *m);
  26.651 +            void glMultTransposeMatrixd_Hook(const GLdouble *m);
  26.652 +
  26.653 +            // GL_VERSION_1_4
  26.654 +            void glBlendFuncSeparate_Hook(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
  26.655 +            void glMultiDrawArrays_Hook(GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount);
  26.656 +            void glMultiDrawElements_Hook(GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount);
  26.657 +            void glPointParameterf_Hook(GLenum pname, GLfloat param);
  26.658 +            void glPointParameterfv_Hook(GLenum pname, const GLfloat *params);
  26.659 +            void glPointParameteri_Hook(GLenum pname, GLint param);
  26.660 +            void glPointParameteriv_Hook(GLenum pname, const GLint *params);
  26.661 +
  26.662 +            // GL_VERSION_1_4 deprecated functions
  26.663 +            void glFogCoordf_Hook(GLfloat coord);
  26.664 +            void glFogCoordfv_Hook(const GLfloat *coord);
  26.665 +            void glFogCoordd_Hook(GLdouble coord);
  26.666 +            void glFogCoorddv_Hook(const GLdouble *coord);
  26.667 +            void glFogCoordPointer_Hook(GLenum type, GLsizei stride, const GLvoid *pointer);
  26.668 +            void glSecondaryColor3b_Hook(GLbyte red, GLbyte green, GLbyte blue);
  26.669 +            void glSecondaryColor3bv_Hook(const GLbyte *v);
  26.670 +            void glSecondaryColor3d_Hook(GLdouble red, GLdouble green, GLdouble blue);
  26.671 +            void glSecondaryColor3dv_Hook(const GLdouble *v);
  26.672 +            void glSecondaryColor3f_Hook(GLfloat red, GLfloat green, GLfloat blue);
  26.673 +            void glSecondaryColor3fv_Hook(const GLfloat *v);
  26.674 +            void glSecondaryColor3i_Hook(GLint red, GLint green, GLint blue);
  26.675 +            void glSecondaryColor3iv_Hook(const GLint *v);
  26.676 +            void glSecondaryColor3s_Hook(GLshort red, GLshort green, GLshort blue);
  26.677 +            void glSecondaryColor3sv_Hook(const GLshort *v);
  26.678 +            void glSecondaryColor3ub_Hook(GLubyte red, GLubyte green, GLubyte blue);
  26.679 +            void glSecondaryColor3ubv_Hook(const GLubyte *v);
  26.680 +            void glSecondaryColor3ui_Hook(GLuint red, GLuint green, GLuint blue);
  26.681 +            void glSecondaryColor3uiv_Hook(const GLuint *v);
  26.682 +            void glSecondaryColor3us_Hook(GLushort red, GLushort green, GLushort blue);
  26.683 +            void glSecondaryColor3usv_Hook(const GLushort *v);
  26.684 +            void glSecondaryColorPointer_Hook(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
  26.685 +            void glWindowPos2d_Hook(GLdouble x, GLdouble y);
  26.686 +            void glWindowPos2dv_Hook(const GLdouble *v);
  26.687 +            void glWindowPos2f_Hook(GLfloat x, GLfloat y);
  26.688 +            void glWindowPos2fv_Hook(const GLfloat *v);
  26.689 +            void glWindowPos2i_Hook(GLint x, GLint y);
  26.690 +            void glWindowPos2iv_Hook(const GLint *v);
  26.691 +            void glWindowPos2s_Hook(GLshort x, GLshort y);
  26.692 +            void glWindowPos2sv_Hook(const GLshort *v);
  26.693 +            void glWindowPos3d_Hook(GLdouble x, GLdouble y, GLdouble z);
  26.694 +            void glWindowPos3dv_Hook(const GLdouble *v);
  26.695 +            void glWindowPos3f_Hook(GLfloat x, GLfloat y, GLfloat z);
  26.696 +            void glWindowPos3fv_Hook(const GLfloat *v);
  26.697 +            void glWindowPos3i_Hook(GLint x, GLint y, GLint z);
  26.698 +            void glWindowPos3iv_Hook(const GLint *v);
  26.699 +            void glWindowPos3s_Hook(GLshort x, GLshort y, GLshort z);
  26.700 +            void glWindowPos3sv_Hook(const GLshort *v);
  26.701 +
  26.702 +            // GL_VERSION_1_5
  26.703 +            void glGenQueries_Hook(GLsizei n, GLuint *ids);
  26.704 +            void glDeleteQueries_Hook(GLsizei n, const GLuint *ids);
  26.705 +            GLboolean glIsQuery_Hook(GLuint id);
  26.706 +            void glBeginQuery_Hook(GLenum target, GLuint id);
  26.707 +            void glEndQuery_Hook(GLenum target);
  26.708 +            void glGetQueryiv_Hook(GLenum target, GLenum pname, GLint *params);
  26.709 +            void glGetQueryObjectiv_Hook(GLuint id, GLenum pname, GLint *params);
  26.710 +            void glGetQueryObjectuiv_Hook(GLuint id, GLenum pname, GLuint *params);
  26.711 +            void glBindBuffer_Hook(GLenum target, GLuint buffer);
  26.712 +            void glDeleteBuffers_Hook(GLsizei n, const GLuint *buffers);
  26.713 +            void glGenBuffers_Hook(GLsizei n, GLuint *buffers);
  26.714 +            GLboolean glIsBuffer_Hook(GLuint buffer);
  26.715 +            void glBufferData_Hook(GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage);
  26.716 +            void glBufferSubData_Hook(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data);
  26.717 +            void glGetBufferSubData_Hook(GLenum target, GLintptr offset, GLsizeiptr size, GLvoid *data);
  26.718 +            GLvoid* glMapBuffer_Hook(GLenum target, GLenum access);
  26.719 +            GLboolean glUnmapBuffer_Hook(GLenum target);
  26.720 +            void glGetBufferParameteriv_Hook(GLenum target, GLenum pname, GLint *params);
  26.721 +            void glGetBufferPointerv_Hook(GLenum target, GLenum pname, GLvoid* *params);
  26.722 +
  26.723 +            // GL_VERSION_2_0
  26.724 +            void glBlendEquationSeparate_Hook(GLenum modeRGB, GLenum modeAlpha);
  26.725 +            void glDrawBuffers_Hook(GLsizei n, const GLenum *bufs);
  26.726 +            void glStencilOpSeparate_Hook(GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
  26.727 +            void glStencilFuncSeparate_Hook(GLenum face, GLenum func, GLint ref, GLuint mask);
  26.728 +            void glStencilMaskSeparate_Hook(GLenum face, GLuint mask);
  26.729 +            void glAttachShader_Hook(GLuint program, GLuint shader);
  26.730 +            void glBindAttribLocation_Hook(GLuint program, GLuint index, const GLchar *name);
  26.731 +            void glCompileShader_Hook(GLuint shader);
  26.732 +            GLuint glCreateProgram_Hook(void);
  26.733 +            GLuint glCreateShader_Hook(GLenum type);
  26.734 +            void glDeleteProgram_Hook(GLuint program);
  26.735 +            void glDeleteShader_Hook(GLuint shader);
  26.736 +            void glDetachShader_Hook(GLuint program, GLuint shader);
  26.737 +            void glDisableVertexAttribArray_Hook(GLuint index);
  26.738 +            void glEnableVertexAttribArray_Hook(GLuint index);
  26.739 +            void glGetActiveAttrib_Hook(GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
  26.740 +            void glGetActiveUniform_Hook(GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
  26.741 +            void glGetAttachedShaders_Hook(GLuint program, GLsizei maxCount, GLsizei *count, GLuint *obj);
  26.742 +            GLint glGetAttribLocation_Hook(GLuint program, const GLchar *name);
  26.743 +            void glGetProgramiv_Hook(GLuint program, GLenum pname, GLint *params);
  26.744 +            void glGetProgramInfoLog_Hook(GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
  26.745 +            void glGetShaderiv_Hook(GLuint shader, GLenum pname, GLint *params);
  26.746 +            void glGetShaderInfoLog_Hook(GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
  26.747 +            void glGetShaderSource_Hook(GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source);
  26.748 +            GLint glGetUniformLocation_Hook(GLuint program, const GLchar *name);
  26.749 +            void glGetUniformfv_Hook(GLuint program, GLint location, GLfloat *params);
  26.750 +            void glGetUniformiv_Hook(GLuint program, GLint location, GLint *params);
  26.751 +            void glGetVertexAttribdv_Hook(GLuint index, GLenum pname, GLdouble *params);
  26.752 +            void glGetVertexAttribfv_Hook(GLuint index, GLenum pname, GLfloat *params);
  26.753 +            void glGetVertexAttribiv_Hook(GLuint index, GLenum pname, GLint *params);
  26.754 +            void glGetVertexAttribPointerv_Hook(GLuint index, GLenum pname, GLvoid* *pointer);
  26.755 +            GLboolean glIsProgram_Hook(GLuint program);
  26.756 +            GLboolean glIsShader_Hook(GLuint shader);
  26.757 +            void glLinkProgram_Hook(GLuint program);
  26.758 +            void glShaderSource_Hook(GLuint shader, GLsizei count, const GLchar* *string, const GLint *length);
  26.759 +            void glUseProgram_Hook(GLuint program);
  26.760 +            void glUniform1f_Hook(GLint location, GLfloat v0);
  26.761 +            void glUniform2f_Hook(GLint location, GLfloat v0, GLfloat v1);
  26.762 +            void glUniform3f_Hook(GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
  26.763 +            void glUniform4f_Hook(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
  26.764 +            void glUniform1i_Hook(GLint location, GLint v0);
  26.765 +            void glUniform2i_Hook(GLint location, GLint v0, GLint v1);
  26.766 +            void glUniform3i_Hook(GLint location, GLint v0, GLint v1, GLint v2);
  26.767 +            void glUniform4i_Hook(GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
  26.768 +            void glUniform1fv_Hook(GLint location, GLsizei count, const GLfloat *value);
  26.769 +            void glUniform2fv_Hook(GLint location, GLsizei count, const GLfloat *value);
  26.770 +            void glUniform3fv_Hook(GLint location, GLsizei count, const GLfloat *value);
  26.771 +            void glUniform4fv_Hook(GLint location, GLsizei count, const GLfloat *value);
  26.772 +            void glUniform1iv_Hook(GLint location, GLsizei count, const GLint *value);
  26.773 +            void glUniform2iv_Hook(GLint location, GLsizei count, const GLint *value);
  26.774 +            void glUniform3iv_Hook(GLint location, GLsizei count, const GLint *value);
  26.775 +            void glUniform4iv_Hook(GLint location, GLsizei count, const GLint *value);
  26.776 +            void glUniformMatrix2fv_Hook(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
  26.777 +            void glUniformMatrix3fv_Hook(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
  26.778 +            void glUniformMatrix4fv_Hook(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
  26.779 +            void glValidateProgram_Hook(GLuint program);
  26.780 +            void glVertexAttrib1d_Hook(GLuint index, GLdouble x);
  26.781 +            void glVertexAttrib1dv_Hook(GLuint index, const GLdouble *v);
  26.782 +            void glVertexAttrib1f_Hook(GLuint index, GLfloat x);
  26.783 +            void glVertexAttrib1fv_Hook(GLuint index, const GLfloat *v);
  26.784 +            void glVertexAttrib1s_Hook(GLuint index, GLshort x);
  26.785 +            void glVertexAttrib1sv_Hook(GLuint index, const GLshort *v);
  26.786 +            void glVertexAttrib2d_Hook(GLuint index, GLdouble x, GLdouble y);
  26.787 +            void glVertexAttrib2dv_Hook(GLuint index, const GLdouble *v);
  26.788 +            void glVertexAttrib2f_Hook(GLuint index, GLfloat x, GLfloat y);
  26.789 +            void glVertexAttrib2fv_Hook(GLuint index, const GLfloat *v);
  26.790 +            void glVertexAttrib2s_Hook(GLuint index, GLshort x, GLshort y);
  26.791 +            void glVertexAttrib2sv_Hook(GLuint index, const GLshort *v);
  26.792 +            void glVertexAttrib3d_Hook(GLuint index, GLdouble x, GLdouble y, GLdouble z);
  26.793 +            void glVertexAttrib3dv_Hook(GLuint index, const GLdouble *v);
  26.794 +            void glVertexAttrib3f_Hook(GLuint index, GLfloat x, GLfloat y, GLfloat z);
  26.795 +            void glVertexAttrib3fv_Hook(GLuint index, const GLfloat *v);
  26.796 +            void glVertexAttrib3s_Hook(GLuint index, GLshort x, GLshort y, GLshort z);
  26.797 +            void glVertexAttrib3sv_Hook(GLuint index, const GLshort *v);
  26.798 +            void glVertexAttrib4Nbv_Hook(GLuint index, const GLbyte *v);
  26.799 +            void glVertexAttrib4Niv_Hook(GLuint index, const GLint *v);
  26.800 +            void glVertexAttrib4Nsv_Hook(GLuint index, const GLshort *v);
  26.801 +            void glVertexAttrib4Nub_Hook(GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w);
  26.802 +            void glVertexAttrib4Nubv_Hook(GLuint index, const GLubyte *v);
  26.803 +            void glVertexAttrib4Nuiv_Hook(GLuint index, const GLuint *v);
  26.804 +            void glVertexAttrib4Nusv_Hook(GLuint index, const GLushort *v);
  26.805 +            void glVertexAttrib4bv_Hook(GLuint index, const GLbyte *v);
  26.806 +            void glVertexAttrib4d_Hook(GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
  26.807 +            void glVertexAttrib4dv_Hook(GLuint index, const GLdouble *v);
  26.808 +            void glVertexAttrib4f_Hook(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
  26.809 +            void glVertexAttrib4fv_Hook(GLuint index, const GLfloat *v);
  26.810 +            void glVertexAttrib4iv_Hook(GLuint index, const GLint *v);
  26.811 +            void glVertexAttrib4s_Hook(GLuint index, GLshort x, GLshort y, GLshort z, GLshort w);
  26.812 +            void glVertexAttrib4sv_Hook(GLuint index, const GLshort *v);
  26.813 +            void glVertexAttrib4ubv_Hook(GLuint index, const GLubyte *v);
  26.814 +            void glVertexAttrib4uiv_Hook(GLuint index, const GLuint *v);
  26.815 +            void glVertexAttrib4usv_Hook(GLuint index, const GLushort *v);
  26.816 +            void glVertexAttribPointer_Hook(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer);
  26.817 +
  26.818 +            // GL_VERSION_2_1
  26.819 +            void glUniformMatrix2x3fv_Hook(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
  26.820 +            void glUniformMatrix3x2fv_Hook(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
  26.821 +            void glUniformMatrix2x4fv_Hook(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
  26.822 +            void glUniformMatrix4x2fv_Hook(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
  26.823 +            void glUniformMatrix3x4fv_Hook(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
  26.824 +            void glUniformMatrix4x3fv_Hook(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
  26.825 +
  26.826 +            // GL_VERSION_3_0
  26.827 +            void glColorMaski_Hook(GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a);
  26.828 +            void glGetBooleani_v_Hook(GLenum target, GLuint index, GLboolean *data);
  26.829 +            void  glGetIntegeri_v_Hook(GLenum target, GLuint index, GLint *data);
  26.830 +            void   glEnablei_Hook(GLenum target, GLuint index);
  26.831 +            void     glDisablei_Hook(GLenum target, GLuint index);
  26.832 +            GLboolean glIsEnabledi_Hook(GLenum target, GLuint index);
  26.833 +            void     glBeginTransformFeedback_Hook(GLenum primitiveMode);
  26.834 +            void    glEndTransformFeedback_Hook(void);
  26.835 +            void  glBindBufferRange_Hook(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
  26.836 +            void glBindBufferBase_Hook(GLenum target, GLuint index, GLuint buffer);
  26.837 +            void glTransformFeedbackVaryings_Hook(GLuint program, GLsizei count, const GLchar* *varyings, GLenum bufferMode);
  26.838 +            void glGetTransformFeedbackVarying_Hook(GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name);
  26.839 +            void glClampColor_Hook(GLenum target, GLenum clamp);
  26.840 +            void glBeginConditionalRender_Hook(GLuint id, GLenum mode);
  26.841 +            void glEndConditionalRender_Hook(void);
  26.842 +            void glVertexAttribIPointer_Hook(GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
  26.843 +            void glGetVertexAttribIiv_Hook(GLuint index, GLenum pname, GLint *params);
  26.844 +            void glGetVertexAttribIuiv_Hook(GLuint index, GLenum pname, GLuint *params);
  26.845 +            void glVertexAttribI1i_Hook(GLuint index, GLint x);
  26.846 +            void glVertexAttribI2i_Hook(GLuint index, GLint x, GLint y);
  26.847 +            void glVertexAttribI3i_Hook(GLuint index, GLint x, GLint y, GLint z);
  26.848 +            void glVertexAttribI4i_Hook(GLuint index, GLint x, GLint y, GLint z, GLint w);
  26.849 +            void glVertexAttribI1ui_Hook(GLuint index, GLuint x);
  26.850 +            void glVertexAttribI2ui_Hook(GLuint index, GLuint x, GLuint y);
  26.851 +            void glVertexAttribI3ui_Hook(GLuint index, GLuint x, GLuint y, GLuint z);
  26.852 +            void glVertexAttribI4ui_Hook(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
  26.853 +            void glVertexAttribI1iv_Hook(GLuint index, const GLint *v);
  26.854 +            void glVertexAttribI2iv_Hook(GLuint index, const GLint *v);
  26.855 +            void glVertexAttribI3iv_Hook(GLuint index, const GLint *v);
  26.856 +            void glVertexAttribI4iv_Hook(GLuint index, const GLint *v);
  26.857 +            void glVertexAttribI1uiv_Hook(GLuint index, const GLuint *v);
  26.858 +            void glVertexAttribI2uiv_Hook(GLuint index, const GLuint *v);
  26.859 +            void glVertexAttribI3uiv_Hook(GLuint index, const GLuint *v);
  26.860 +            void glVertexAttribI4uiv_Hook(GLuint index, const GLuint *v);
  26.861 +            void glVertexAttribI4bv_Hook(GLuint index, const GLbyte *v);
  26.862 +            void glVertexAttribI4sv_Hook(GLuint index, const GLshort *v);
  26.863 +            void glVertexAttribI4ubv_Hook(GLuint index, const GLubyte *v);
  26.864 +            void glVertexAttribI4usv_Hook(GLuint index, const GLushort *v);
  26.865 +            void glGetUniformuiv_Hook(GLuint program, GLint location, GLuint *params);
  26.866 +            void  glBindFragDataLocation_Hook(GLuint program, GLuint color, const GLchar *name);
  26.867 +            GLint glGetFragDataLocation_Hook(GLuint program, const GLchar *name);
  26.868 +            void  glUniform1ui_Hook(GLint location, GLuint v0);
  26.869 +            void glUniform2ui_Hook(GLint location, GLuint v0, GLuint v1);
  26.870 +            void glUniform3ui_Hook(GLint location, GLuint v0, GLuint v1, GLuint v2);
  26.871 +            void glUniform4ui_Hook(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
  26.872 +            void glUniform1uiv_Hook(GLint location, GLsizei count, const GLuint *value);
  26.873 +            void glUniform2uiv_Hook(GLint location, GLsizei count, const GLuint *value);
  26.874 +            void glUniform3uiv_Hook(GLint location, GLsizei count, const GLuint *value);
  26.875 +            void glUniform4uiv_Hook(GLint location, GLsizei count, const GLuint *value);
  26.876 +            void glTexParameterIiv_Hook(GLenum target, GLenum pname, const GLint *params);
  26.877 +            void glTexParameterIuiv_Hook(GLenum target, GLenum pname, const GLuint *params);
  26.878 +            void glGetTexParameterIiv_Hook(GLenum target, GLenum pname, GLint *params);
  26.879 +            void   glGetTexParameterIuiv_Hook(GLenum target, GLenum pname, GLuint *params);
  26.880 +            void     glClearBufferiv_Hook(GLenum buffer, GLint drawbuffer, const GLint *value);
  26.881 +            void      glClearBufferuiv_Hook(GLenum buffer, GLint drawbuffer, const GLuint *value);
  26.882 +            void        glClearBufferfv_Hook(GLenum buffer, GLint drawbuffer, const GLfloat *value);
  26.883 +            void          glClearBufferfi_Hook(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
  26.884 +            const GLubyte* glGetStringi_Hook(GLenum name, GLuint index);
  26.885 +
  26.886 +            // GL_VERSION_3_1
  26.887 +            void glDrawArraysInstanced_Hook(GLenum mode, GLint first, GLsizei count, GLsizei primcount);
  26.888 +            void glDrawElementsInstanced_Hook(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount);
  26.889 +            void glTexBuffer_Hook(GLenum target, GLenum internalformat, GLuint buffer);
  26.890 +            void glPrimitiveRestartIndex_Hook(GLuint index);
  26.891 +
  26.892 +            // GL_VERSION_3_2
  26.893 +            void glGetInteger64i_v_Hook(GLenum target, GLuint index, GLint64 *data);
  26.894 +            void glGetBufferParameteri64v_Hook(GLenum target, GLenum pname, GLint64 *params);
  26.895 +            void glFramebufferTexture_Hook(GLenum target, GLenum attachment, GLuint texture, GLint level);
  26.896 +
  26.897 +            // GL_VERSION_3_3
  26.898 +            void glVertexAttribDivisor_Hook(GLuint index, GLuint divisor);
  26.899 +
  26.900 +            // GL_VERSION_4_0
  26.901 +            void glMinSampleShading_Hook(GLclampf value);
  26.902 +            void glBlendEquationi_Hook(GLuint buf, GLenum mode);
  26.903 +            void glBlendEquationSeparatei_Hook(GLuint buf, GLenum modeRGB, GLenum modeAlpha);
  26.904 +            void glBlendFunci_Hook(GLuint buf, GLenum src, GLenum dst);
  26.905 +            void glBlendFuncSeparatei_Hook(GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
  26.906 +
  26.907 +            // GL_AMD_debug_output
  26.908 +            void   glDebugMessageEnableAMD_Hook(GLenum category, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled);
  26.909 +            void   glDebugMessageInsertAMD_Hook(GLenum category, GLenum severity, GLuint id, GLsizei length, const GLchar *buf);
  26.910 +            void   glDebugMessageCallbackAMD_Hook(GLDEBUGPROCAMD callback, GLvoid *userParam);
  26.911 +            GLuint glGetDebugMessageLogAMD_Hook(GLuint count, GLsizei bufsize, GLenum *categories, GLuint *severities, GLuint *ids, GLsizei *lengths, GLchar *message);
  26.912 +
  26.913 +        #if defined(GLE_CGL_ENABLED)
  26.914 +            // GL_APPLE_element_array
  26.915 +            void glElementPointerAPPLE_Hook(GLenum type, const GLvoid *pointer);
  26.916 +            void glDrawElementArrayAPPLE_Hook(GLenum mode, GLint first, GLsizei count);
  26.917 +            void glDrawRangeElementArrayAPPLE_Hook(GLenum mode, GLuint start, GLuint end, GLint first, GLsizei count);
  26.918 +            void glMultiDrawElementArrayAPPLE_Hook(GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount);
  26.919 +            void glMultiDrawRangeElementArrayAPPLE_Hook(GLenum mode, GLuint start, GLuint end, const GLint *first, const GLsizei *count, GLsizei primcount);
  26.920 +
  26.921 +            // GL_APPLE_fence
  26.922 +            void glGenFencesAPPLE_Hook(GLsizei n, GLuint *fences);
  26.923 +            void glDeleteFencesAPPLE_Hook(GLsizei n, const GLuint *fences);
  26.924 +            void glSetFenceAPPLE_Hook(GLuint fence);
  26.925 +            GLboolean glIsFenceAPPLE_Hook(GLuint fence);
  26.926 +            GLboolean glTestFenceAPPLE_Hook(GLuint fence);
  26.927 +            void glFinishFenceAPPLE_Hook(GLuint fence);
  26.928 +            GLboolean glTestObjectAPPLE_Hook(GLenum object, GLuint name);
  26.929 +            void glFinishObjectAPPLE_Hook(GLenum object, GLint name);
  26.930 +
  26.931 +            // GL_APPLE_flush_buffer_range
  26.932 +            void glBufferParameteriAPPLE_Hook(GLenum target, GLenum pname, GLint param);
  26.933 +            void glFlushMappedBufferRangeAPPLE_Hook(GLenum target, GLintptr offset, GLsizeiptr size);
  26.934 +
  26.935 +            // GL_APPLE_object_purgeable
  26.936 +            GLenum glObjectPurgeableAPPLE_Hook(GLenum objectType, GLuint name, GLenum option);
  26.937 +            GLenum glObjectUnpurgeableAPPLE_Hook(GLenum objectType, GLuint name, GLenum option);
  26.938 +            void glGetObjectParameterivAPPLE_Hook(GLenum objectType, GLuint name, GLenum pname, GLint *params);
  26.939 +
  26.940 +            // GL_APPLE_texture_range
  26.941 +            void glTextureRangeAPPLE_Hook(GLenum target, GLsizei length, const GLvoid *pointer);
  26.942 +            void glGetTexParameterPointervAPPLE_Hook(GLenum target, GLenum pname, GLvoid **params);
  26.943 +
  26.944 +            // GL_APPLE_vertex_array_object
  26.945 +            void glBindVertexArrayAPPLE_Hook(GLuint array);
  26.946 +            void glDeleteVertexArraysAPPLE_Hook(GLsizei n, const GLuint *arrays);
  26.947 +            void glGenVertexArraysAPPLE_Hook(GLsizei n, GLuint *arrays);
  26.948 +            GLboolean glIsVertexArrayAPPLE_Hook(GLuint array);
  26.949 +
  26.950 +            // GL_APPLE_vertex_array_range
  26.951 +            void glVertexArrayRangeAPPLE_Hook(GLsizei length, GLvoid *pointer);
  26.952 +            void glFlushVertexArrayRangeAPPLE_Hook(GLsizei length, GLvoid *pointer);
  26.953 +            void glVertexArrayParameteriAPPLE_Hook(GLenum pname, GLint param);
  26.954 +
  26.955 +            // GL_APPLE_vertex_program_evaluators
  26.956 +            void glEnableVertexAttribAPPLE_Hook(GLuint index, GLenum pname);
  26.957 +            void glDisableVertexAttribAPPLE_Hook(GLuint index, GLenum pname);
  26.958 +            GLboolean glIsVertexAttribEnabledAPPLE_Hook(GLuint index, GLenum pname);
  26.959 +            void glMapVertexAttrib1dAPPLE_Hook(GLuint index, GLuint size, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points);
  26.960 +            void glMapVertexAttrib1fAPPLE_Hook(GLuint index, GLuint size, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points);
  26.961 +            void glMapVertexAttrib2dAPPLE_Hook(GLuint index, GLuint size, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points);
  26.962 +            void glMapVertexAttrib2fAPPLE_Hook(GLuint index, GLuint size, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points);
  26.963 +        #endif // GLE_CGL_ENABLED
  26.964 +
  26.965 +            // GL_ARB_debug_output
  26.966 +            void   glDebugMessageControlARB_Hook(GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled);
  26.967 +            void   glDebugMessageInsertARB_Hook(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf);
  26.968 +            void   glDebugMessageCallbackARB_Hook(GLDEBUGPROCARB callback, const GLvoid *userParam);
  26.969 +            GLuint glGetDebugMessageLogARB_Hook(GLuint count, GLsizei bufsize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog);
  26.970 +
  26.971 +            // GL_ARB_ES2_compatibility
  26.972 +            void glReleaseShaderCompiler_Hook();
  26.973 +            void glShaderBinary_Hook(GLsizei count, const GLuint *shaders, GLenum binaryformat, const GLvoid *binary, GLsizei length);
  26.974 +            void glGetShaderPrecisionFormat_Hook(GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision);
  26.975 +            void glDepthRangef_Hook(GLclampf n, GLclampf f);
  26.976 +            void glClearDepthf_Hook(GLclampf d);
  26.977 +
  26.978 +            // GL_ARB_framebuffer_object
  26.979 +            GLboolean glIsRenderbuffer_Hook(GLuint renderbuffer);
  26.980 +            void glBindRenderbuffer_Hook(GLenum target, GLuint renderbuffer);
  26.981 +            void glDeleteRenderbuffers_Hook(GLsizei n, const GLuint *renderbuffers);
  26.982 +            void glGenRenderbuffers_Hook(GLsizei n, GLuint *renderbuffers);
  26.983 +            void glRenderbufferStorage_Hook(GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
  26.984 +            void glGetRenderbufferParameteriv_Hook(GLenum target, GLenum pname, GLint *params);
  26.985 +            GLboolean glIsFramebuffer_Hook(GLuint framebuffer);
  26.986 +            void glBindFramebuffer_Hook(GLenum target, GLuint framebuffer);
  26.987 +            void glDeleteFramebuffers_Hook(GLsizei n, const GLuint *framebuffers);
  26.988 +            void glGenFramebuffers_Hook(GLsizei n, GLuint *framebuffers);
  26.989 +            GLenum glCheckFramebufferStatus_Hook(GLenum target);
  26.990 +            void glFramebufferTexture1D_Hook(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
  26.991 +            void glFramebufferTexture2D_Hook(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
  26.992 +            void glFramebufferTexture3D_Hook(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
  26.993 +            void glFramebufferRenderbuffer_Hook(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
  26.994 +            void glGetFramebufferAttachmentParameteriv_Hook(GLenum target, GLenum attachment, GLenum pname, GLint *params);
  26.995 +            void glGenerateMipmap_Hook(GLenum target);
  26.996 +            void glBlitFramebuffer_Hook(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
  26.997 +            void glRenderbufferStorageMultisample_Hook(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
  26.998 +            void glFramebufferTextureLayer_Hook(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
  26.999 +
 26.1000 +            // GL_ARB_texture_multisample
 26.1001 +            void glTexImage2DMultisample_Hook(GLenum target, GLsizei samples, GLint internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations);
 26.1002 +            void glTexImage3DMultisample_Hook(GLenum target, GLsizei samples, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations);
 26.1003 +            void glGetMultisamplefv_Hook(GLenum pname, GLuint index, GLfloat *val);
 26.1004 +            void glSampleMaski_Hook(GLuint index, GLbitfield mask);
 26.1005 +
 26.1006 +            // GL_ARB_timer_query
 26.1007 +            void glQueryCounter_Hook(GLuint id, GLenum target);
 26.1008 +            void glGetQueryObjecti64v_Hook(GLuint id, GLenum pname, GLint64 *params);
 26.1009 +            void glGetQueryObjectui64v_Hook(GLuint id, GLenum pname, GLuint64 *params);
 26.1010 +
 26.1011 +            // GL_ARB_vertex_array_object
 26.1012 +            void      glBindVertexArray_Hook(GLuint array);
 26.1013 +            void      glDeleteVertexArrays_Hook(GLsizei n, const GLuint *arrays);
 26.1014 +            void      glGenVertexArrays_Hook(GLsizei n, GLuint *arrays);
 26.1015 +            GLboolean glIsVertexArray_Hook(GLuint array);
 26.1016 +
 26.1017 +            // GL_EXT_draw_buffers2
 26.1018 +            void      glColorMaskIndexedEXT_Hook(GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a);
 26.1019 +            void      glGetBooleanIndexedvEXT_Hook(GLenum target, GLuint index, GLboolean *data);
 26.1020 +            void      glGetIntegerIndexedvEXT_Hook(GLenum target, GLuint index, GLint *data);
 26.1021 +            void      glEnableIndexedEXT_Hook(GLenum target, GLuint index);
 26.1022 +            void      glDisableIndexedEXT_Hook(GLenum target, GLuint index);
 26.1023 +            GLboolean glIsEnabledIndexedEXT_Hook(GLenum target, GLuint index);
 26.1024 +
 26.1025 +            // GL_KHR_debug
 26.1026 +            void   glDebugMessageControl_Hook(GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint* ids, GLboolean enabled);
 26.1027 +            void   glDebugMessageInsert_Hook(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const char* buf);
 26.1028 +            void   glDebugMessageCallback_Hook(GLDEBUGPROC callback, const void* userParam);
 26.1029 +            GLuint glGetDebugMessageLog_Hook(GLuint count, GLsizei bufSize, GLenum* sources, GLenum* types, GLuint* ids, GLenum* severities, GLsizei* lengths,  char* messageLog);
 26.1030 +            void   glPushDebugGroup_Hook(GLenum source, GLuint id, GLsizei length, const char * message);
 26.1031 +            void   glPopDebugGroup_Hook(void);
 26.1032 +            void   glObjectLabel_Hook(GLenum identifier, GLuint name, GLsizei length, const char *label);
 26.1033 +            void   glGetObjectLabel_Hook(GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *length, char *label);
 26.1034 +            void   glObjectPtrLabel_Hook(void* ptr, GLsizei length, const char *label);
 26.1035 +            void   glGetObjectPtrLabel_Hook(void* ptr, GLsizei bufSize, GLsizei *length, char *label);
 26.1036 +
 26.1037 +            // GL_WIN_swap_hint
 26.1038 +            void glAddSwapHintRectWIN_Hook(GLint x, GLint y, GLsizei width, GLsizei height);
 26.1039 +
 26.1040 +          #if defined(GLE_WGL_ENABLED)
 26.1041 +            void PostWGLHook(const char* functionName);
 26.1042 +
 26.1043 +            // WGL
 26.1044 +            /* Hooking of these is currently disabled.
 26.1045 +            BOOL  wglCopyContext_Hook(HGLRC, HGLRC, UINT);
 26.1046 +            HGLRC wglCreateContext_Hook(HDC);
 26.1047 +            HGLRC wglCreateLayerContext_Hook(HDC, int);
 26.1048 +            BOOL  wglDeleteContext_Hook(HGLRC);
 26.1049 +            HGLRC wglGetCurrentContext_Hook(VOID);
 26.1050 +            HDC   wglGetCurrentDC_Hook(VOID);
 26.1051 +            PROC  wglGetProcAddress_Hook(LPCSTR);
 26.1052 +            BOOL  wglMakeCurrent_Hook(HDC, HGLRC);
 26.1053 +            BOOL  wglShareLists_Hook(HGLRC, HGLRC);
 26.1054 +            BOOL  wglUseFontBitmapsA_Hook(HDC, DWORD, DWORD, DWORD);
 26.1055 +            BOOL  wglUseFontBitmapsW_Hook(HDC, DWORD, DWORD, DWORD);
 26.1056 +            BOOL  wglUseFontOutlinesA_Hook(HDC, DWORD, DWORD, DWORD, FLOAT, FLOAT, int, LPGLYPHMETRICSFLOAT);
 26.1057 +            BOOL  wglUseFontOutlinesW_Hook(HDC, DWORD, DWORD, DWORD, FLOAT, FLOAT, int, LPGLYPHMETRICSFLOAT);
 26.1058 +            BOOL  wglDescribeLayerPlane_Hook(HDC, int, int, UINT, LPLAYERPLANEDESCRIPTOR);
 26.1059 +            int   wglSetLayerPaletteEntries_Hook(HDC, int, int, int, CONST COLORREF *);
 26.1060 +            int   wglGetLayerPaletteEntries_Hook(HDC, int, int, int, COLORREF *);
 26.1061 +            BOOL  wglRealizeLayerPalette_Hook(HDC, int, BOOL);
 26.1062 +            BOOL  wglSwapLayerBuffers_Hook(HDC, UINT);
 26.1063 +            DWORD wglSwapMultipleBuffers_Hook(UINT, CONST WGLSWAP *);
 26.1064 +            */
 26.1065 +
 26.1066 +            // WGL_ARB_buffer_region
 26.1067 +            HANDLE wglCreateBufferRegionARB_Hook (HDC hDC, int iLayerPlane, UINT uType);
 26.1068 +            VOID wglDeleteBufferRegionARB_Hook (HANDLE hRegion);
 26.1069 +            BOOL wglSaveBufferRegionARB_Hook (HANDLE hRegion, int x, int y, int width, int height);
 26.1070 +            BOOL wglRestoreBufferRegionARB_Hook (HANDLE hRegion, int x, int y, int width, int height, int xSrc, int ySrc);
 26.1071 +
 26.1072 +            // WGL_ARB_extensions_string
 26.1073 +            const char * wglGetExtensionsStringARB_Hook (HDC hdc);
 26.1074 +
 26.1075 +            // WGL_ARB_pixel_format
 26.1076 +            BOOL wglGetPixelFormatAttribivARB_Hook (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, int *piValues);
 26.1077 +            BOOL wglGetPixelFormatAttribfvARB_Hook (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, FLOAT *pfValues);
 26.1078 +            BOOL wglChoosePixelFormatARB_Hook (HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats);
 26.1079 +
 26.1080 +            // WGL_ARB_make_current_read
 26.1081 +            BOOL wglMakeContextCurrentARB_Hook (HDC hDrawDC, HDC hReadDC, HGLRC hglrc);
 26.1082 +            HDC wglGetCurrentReadDCARB_Hook (void);
 26.1083 +
 26.1084 +            // WGL_ARB_pbuffer
 26.1085 +            HPBUFFERARB wglCreatePbufferARB_Hook (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int *piAttribList);
 26.1086 +            HDC wglGetPbufferDCARB_Hook (HPBUFFERARB hPbuffer);
 26.1087 +            int wglReleasePbufferDCARB_Hook (HPBUFFERARB hPbuffer, HDC hDC);
 26.1088 +            BOOL wglDestroyPbufferARB_Hook (HPBUFFERARB hPbuffer);
 26.1089 +            BOOL wglQueryPbufferARB_Hook (HPBUFFERARB hPbuffer, int iAttribute, int *piValue);
 26.1090 +
 26.1091 +            // WGL_ARB_render_texture
 26.1092 +            BOOL wglBindTexImageARB_Hook (HPBUFFERARB hPbuffer, int iBuffer);
 26.1093 +            BOOL wglReleaseTexImageARB_Hook (HPBUFFERARB hPbuffer, int iBuffer);
 26.1094 +            BOOL wglSetPbufferAttribARB_Hook (HPBUFFERARB hPbuffer, const int *piAttribList);
 26.1095 +
 26.1096 +            // WGL_NV_present_video
 26.1097 +            int wglEnumerateVideoDevicesNV_Hook (HDC hDC, HVIDEOOUTPUTDEVICENV *phDeviceList);
 26.1098 +            BOOL wglBindVideoDeviceNV_Hook (HDC hDC, unsigned int uVideoSlot, HVIDEOOUTPUTDEVICENV hVideoDevice, const int *piAttribList);
 26.1099 +            BOOL wglQueryCurrentContextNV_Hook (int iAttribute, int *piValue);
 26.1100 +
 26.1101 +            // WGL_ARB_create_context
 26.1102 +            HGLRC wglCreateContextAttribsARB_Hook (HDC hDC, HGLRC hShareContext, const int *attribList);
 26.1103 +
 26.1104 +            // WGL_EXT_extensions_string
 26.1105 +            const char * wglGetExtensionsStringEXT_Hook ();
 26.1106 +
 26.1107 +            // WGL_EXT_swap_control
 26.1108 +            BOOL wglSwapIntervalEXT_Hook(int interval);
 26.1109 +            int  wglGetSwapIntervalEXT_Hook();
 26.1110 +
 26.1111 +            // WGL_OML_sync_control
 26.1112 +            BOOL  wglGetSyncValuesOML_Hook (HDC hdc, INT64 *ust, INT64 *msc, INT64 *sbc);
 26.1113 +            BOOL  wglGetMscRateOML_Hook (HDC hdc, INT32 *numerator, INT32 *denominator);
 26.1114 +            INT64 wglSwapBuffersMscOML_Hook (HDC hdc, INT64 target_msc, INT64 divisor, INT64 remainder);
 26.1115 +            INT64 wglSwapLayerBuffersMscOML_Hook (HDC hdc, int fuPlanes, INT64 target_msc, INT64 divisor, INT64 remainder);
 26.1116 +            BOOL  wglWaitForMscOML_Hook (HDC hdc, INT64 target_msc, INT64 divisor, INT64 remainder, INT64 *ust, INT64 *msc, INT64 *sbc);
 26.1117 +            BOOL  wglWaitForSbcOML_Hook (HDC hdc, INT64 target_sbc, INT64 *ust, INT64 *msc, INT64 *sbc);
 26.1118 +
 26.1119 +             // WGL_NV_video_output
 26.1120 +            BOOL wglGetVideoDeviceNV_Hook (HDC hDC, int numDevices, HPVIDEODEV *hVideoDevice);
 26.1121 +            BOOL wglReleaseVideoDeviceNV_Hook (HPVIDEODEV hVideoDevice);
 26.1122 +            BOOL wglBindVideoImageNV_Hook (HPVIDEODEV hVideoDevice, HPBUFFERARB hPbuffer, int iVideoBuffer);
 26.1123 +            BOOL wglReleaseVideoImageNV_Hook (HPBUFFERARB hPbuffer, int iVideoBuffer);
 26.1124 +            BOOL wglSendPbufferToVideoNV_Hook (HPBUFFERARB hPbuffer, int iBufferType, unsigned long *pulCounterPbuffer, BOOL bBlock);
 26.1125 +            BOOL wglGetVideoInfoNV_Hook (HPVIDEODEV hpVideoDevice, unsigned long *pulCounterOutputPbuffer, unsigned long *pulCounterOutputVideo);
 26.1126 +
 26.1127 +             // WGL_NV_swap_group
 26.1128 +            BOOL wglJoinSwapGroupNV_Hook (HDC hDC, GLuint group);
 26.1129 +            BOOL wglBindSwapBarrierNV_Hook (GLuint group, GLuint barrier);
 26.1130 +            BOOL wglQuerySwapGroupNV_Hook (HDC hDC, GLuint *group, GLuint *barrier);
 26.1131 +            BOOL wglQueryMaxSwapGroupsNV_Hook (HDC hDC, GLuint *maxGroups, GLuint *maxBarriers);
 26.1132 +            BOOL wglQueryFrameCountNV_Hook (HDC hDC, GLuint *count);
 26.1133 +            BOOL wglResetFrameCountNV_Hook (HDC hDC);
 26.1134 +
 26.1135 +             // WGL_NV_video_capture
 26.1136 +            BOOL wglBindVideoCaptureDeviceNV_Hook (UINT uVideoSlot, HVIDEOINPUTDEVICENV hDevice);
 26.1137 +            UINT wglEnumerateVideoCaptureDevicesNV_Hook (HDC hDc, HVIDEOINPUTDEVICENV *phDeviceList);
 26.1138 +            BOOL wglLockVideoCaptureDeviceNV_Hook (HDC hDc, HVIDEOINPUTDEVICENV hDevice);
 26.1139 +            BOOL wglQueryVideoCaptureDeviceNV_Hook (HDC hDc, HVIDEOINPUTDEVICENV hDevice, int iAttribute, int *piValue);
 26.1140 +            BOOL wglReleaseVideoCaptureDeviceNV_Hook (HDC hDc, HVIDEOINPUTDEVICENV hDevice);
 26.1141 +
 26.1142 +            // WGL_NV_copy_image
 26.1143 +            BOOL wglCopyImageSubDataNV_Hook (HGLRC hSrcRC, GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, HGLRC hDstRC, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei width, GLsizei height, GLsizei depth);
 26.1144 +
 26.1145 +            // WGL_NV_DX_interop
 26.1146 +            BOOL   wglDXSetResourceShareHandleNV_Hook(void *dxObject, HANDLE shareHandle);
 26.1147 +            HANDLE wglDXOpenDeviceNV_Hook(void *dxDevice);
 26.1148 +            BOOL   wglDXCloseDeviceNV_Hook(HANDLE hDevice);
 26.1149 +            HANDLE wglDXRegisterObjectNV_Hook(HANDLE hDevice, void *dxObject, GLuint name, GLenum type, GLenum access);
 26.1150 +            BOOL   wglDXUnregisterObjectNV_Hook(HANDLE hDevice, HANDLE hObject);
 26.1151 +            BOOL   wglDXObjectAccessNV_Hook(HANDLE hObject, GLenum access);
 26.1152 +            BOOL   wglDXLockObjectsNV_Hook(HANDLE hDevice, GLint count, HANDLE *hObjects);
 26.1153 +            BOOL   wglDXUnlockObjectsNV_Hook(HANDLE hDevice, GLint count, HANDLE *hObjects);
 26.1154 +          #endif // GLE_WGL_ENABLED
 26.1155 +
 26.1156 +          #if defined(GLE_GLX_ENABLED)
 26.1157 +            void PostGLXHook(const char* functionName);
 26.1158 +
 26.1159 +            // GLX_VERSION_1_0
 26.1160 +            // GLX_VERSION_1_1
 26.1161 +            // We don't currently do hooking of these.
 26.1162 +
 26.1163 +            // GLX_VERSION_1_2
 26.1164 +            ::Display* glXGetCurrentDisplay_Hook(void);
 26.1165 +
 26.1166 +            // GLX_VERSION_1_3
 26.1167 +            GLXFBConfig* glXChooseFBConfig_Hook(::Display *dpy, int screen, const int *attrib_list, int *nelements);
 26.1168 +            GLXContext   glXCreateNewContext_Hook(::Display *dpy, GLXFBConfig config, int render_type, GLXContext share_list, Bool direct);
 26.1169 +            GLXPbuffer   glXCreatePbuffer_Hook(::Display *dpy, GLXFBConfig config, const int *attrib_list);
 26.1170 +            GLXPixmap    glXCreatePixmap_Hook(::Display *dpy, GLXFBConfig config, Pixmap pixmap, const int *attrib_list);
 26.1171 +            GLXWindow    glXCreateWindow_Hook(::Display *dpy, GLXFBConfig config, Window win, const int *attrib_list);
 26.1172 +            void         glXDestroyPbuffer_Hook(::Display *dpy, GLXPbuffer pbuf);
 26.1173 +            void         glXDestroyPixmap_Hook(::Display *dpy, GLXPixmap pixmap);
 26.1174 +            void         glXDestroyWindow_Hook(::Display *dpy, GLXWindow win);
 26.1175 +            GLXDrawable  glXGetCurrentReadDrawable_Hook(void);
 26.1176 +            int          glXGetFBConfigAttrib_Hook(::Display *dpy, GLXFBConfig config, int attribute, int *value);
 26.1177 +            GLXFBConfig* glXGetFBConfigs_Hook(::Display *dpy, int screen, int *nelements);
 26.1178 +            void         glXGetSelectedEvent_Hook(::Display *dpy, GLXDrawable draw, unsigned long *event_mask);
 26.1179 +            XVisualInfo* glXGetVisualFromFBConfig_Hook(::Display *dpy, GLXFBConfig config);
 26.1180 +            Bool         glXMakeContextCurrent_Hook(::Display *display, GLXDrawable draw, GLXDrawable read, GLXContext ctx);
 26.1181 +            int          glXQueryContext_Hook(::Display *dpy, GLXContext ctx, int attribute, int *value);
 26.1182 +            void         glXQueryDrawable_Hook(::Display *dpy, GLXDrawable draw, int attribute, unsigned int *value);
 26.1183 +            void         glXSelectEvent_Hook(::Display *dpy, GLXDrawable draw, unsigned long event_mask);
 26.1184 +
 26.1185 +            // GLX_VERSION_1_4
 26.1186 +            // We don't do hooking of this.
 26.1187 +
 26.1188 +            // GLX_ARB_create_context
 26.1189 +            GLXContext glXCreateContextAttribsARB_Hook(Display* dpy, GLXFBConfig config, GLXContext share_context, Bool direct, const int *attrib_list);
 26.1190 +
 26.1191 +            // GLX_EXT_swap_control
 26.1192 +            void glXSwapIntervalEXT_Hook(::Display* dpy, GLXDrawable drawable, int interval);
 26.1193 +
 26.1194 +            // GLX_OML_sync_control
 26.1195 +			Bool    glXGetMscRateOML_Hook(::Display* dpy, GLXDrawable drawable, int32_t* numerator, int32_t* denominator);
 26.1196 +			Bool    glXGetSyncValuesOML_Hook(::Display* dpy, GLXDrawable drawable, int64_t* ust, int64_t* msc, int64_t* sbc);
 26.1197 +			int64_t glXSwapBuffersMscOML_Hook(::Display* dpy, GLXDrawable drawable, int64_t target_msc, int64_t divisor, int64_t remainder);
 26.1198 +			Bool    glXWaitForMscOML_Hook(::Display* dpy, GLXDrawable drawable, int64_t target_msc, int64_t divisor, int64_t remainder, int64_t* ust, int64_t* msc, int64_t* sbc);
 26.1199 +			Bool    glXWaitForSbcOML_Hook(::Display* dpy, GLXDrawable drawable, int64_t target_sbc, int64_t* ust, int64_t* msc, int64_t* sbc);
 26.1200 +
 26.1201 +            // GLX_MESA_swap_control
 26.1202 +            int glXGetSwapIntervalMESA_Hook();
 26.1203 +            int glXSwapIntervalMESA_Hook(unsigned int interval);
 26.1204 +
 26.1205 +          #endif // GLE_GLX_ENABLED
 26.1206 +
 26.1207 +        #endif // #if defined(GLE_HOOKING_ENABLED)
 26.1208 +
 26.1209 +        // GL_VERSION_1_1
 26.1210 +        // These are not represented by function pointers.
 26.1211 +        
 26.1212 +        // GL_VERSION_1_2
 26.1213 +        PFNGLCOPYTEXSUBIMAGE3DPROC glCopyTexSubImage3D_Impl;
 26.1214 +        PFNGLDRAWRANGEELEMENTSPROC glDrawRangeElements_Impl;
 26.1215 +        PFNGLTEXIMAGE3DPROC glTexImage3D_Impl;
 26.1216 +        PFNGLTEXSUBIMAGE3DPROC glTexSubImage3D_Impl;
 26.1217 +
 26.1218 +        // GL_VERSION_1_2 deprecated functions
 26.1219 +        /* Not currently supported
 26.1220 +        PFNGLCOLORTABLEPROC glColorTable_Impl;
 26.1221 +        PFNGLCOLORTABLEPARAMETERFVPROC glColorTableParameterfv_Impl;
 26.1222 +        PFNGLCOLORTABLEPARAMETERIVPROC glColorTableParameteriv_Impl;
 26.1223 +        PFNGLCOPYCOLORTABLEPROC glCopyColorTable_Impl;
 26.1224 +        PFNGLGETCOLORTABLEPROC glGetColorTable_Impl;
 26.1225 +        PFNGLGETCOLORTABLEPARAMETERFVPROC glGetColorTableParameterfv_Impl;
 26.1226 +        PFNGLGETCOLORTABLEPARAMETERIVPROC glGetColorTableParameteriv_Impl;
 26.1227 +        PFNGLCOLORSUBTABLEPROC glColorSubTable_Impl;
 26.1228 +        PFNGLCOPYCOLORSUBTABLEPROC glCopyColorSubTable_Impl;
 26.1229 +        PFNGLCONVOLUTIONFILTER1DPROC glConvolutionFilter1D_Impl;
 26.1230 +        PFNGLCONVOLUTIONFILTER2DPROC glConvolutionFilter2D_Impl;
 26.1231 +        PFNGLCONVOLUTIONPARAMETERFPROC glConvolutionParameterf_Impl;
 26.1232 +        PFNGLCONVOLUTIONPARAMETERFVPROC glConvolutionParameterfv_Impl;
 26.1233 +        PFNGLCONVOLUTIONPARAMETERIPROC glConvolutionParameteri_Impl;
 26.1234 +        PFNGLCONVOLUTIONPARAMETERIVPROC glConvolutionParameteriv_Impl;
 26.1235 +        PFNGLCOPYCONVOLUTIONFILTER1DPROC glCopyConvolutionFilter1D_Impl;
 26.1236 +        PFNGLCOPYCONVOLUTIONFILTER2DPROC glCopyConvolutionFilter2D_Impl;
 26.1237 +        PFNGLGETCONVOLUTIONFILTERPROC glGetConvolutionFilter_Impl;
 26.1238 +        PFNGLGETCONVOLUTIONPARAMETERFVPROC glGetConvolutionParameterfv_Impl;
 26.1239 +        PFNGLGETCONVOLUTIONPARAMETERIVPROC glGetConvolutionParameteriv_Impl;
 26.1240 +        PFNGLGETSEPARABLEFILTERPROC glGetSeparableFilter_Impl;
 26.1241 +        PFNGLSEPARABLEFILTER2DPROC glSeparableFilter2D_Impl;
 26.1242 +        PFNGLGETHISTOGRAMPROC glGetHistogram_Impl;
 26.1243 +        PFNGLGETHISTOGRAMPARAMETERFVPROC glGetHistogramParameterfv_Impl;
 26.1244 +        PFNGLGETHISTOGRAMPARAMETERIVPROC glGetHistogramParameteriv_Impl;
 26.1245 +        PFNGLGETMINMAXPROC glGetMinmax_Impl;
 26.1246 +        PFNGLGETMINMAXPARAMETERFVPROC glGetMinmaxParameterfv_Impl;
 26.1247 +        PFNGLGETMINMAXPARAMETERIVPROC glGetMinmaxParameteriv_Impl;
 26.1248 +        PFNGLHISTOGRAMPROC glHistogram_Impl;
 26.1249 +        PFNGLMINMAXPROC glMinmax_Impl;
 26.1250 +        PFNGLRESETHISTOGRAMPROC glResetHistogram_Impl;
 26.1251 +        PFNGLRESETMINMAXPROC glResetMinmax_Impl;
 26.1252 +        */
 26.1253 +
 26.1254 +        // GL_VERSION_1_3
 26.1255 +        PFNGLACTIVETEXTUREPROC glActiveTexture_Impl;
 26.1256 +        PFNGLCLIENTACTIVETEXTUREPROC glClientActiveTexture_Impl;
 26.1257 +        PFNGLCOMPRESSEDTEXIMAGE1DPROC glCompressedTexImage1D_Impl;
 26.1258 +        PFNGLCOMPRESSEDTEXIMAGE2DPROC glCompressedTexImage2D_Impl;
 26.1259 +        PFNGLCOMPRESSEDTEXIMAGE3DPROC glCompressedTexImage3D_Impl;
 26.1260 +        PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC glCompressedTexSubImage1D_Impl;
 26.1261 +        PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC glCompressedTexSubImage2D_Impl;
 26.1262 +        PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC glCompressedTexSubImage3D_Impl;
 26.1263 +        PFNGLGETCOMPRESSEDTEXIMAGEPROC glGetCompressedTexImage_Impl;
 26.1264 +        PFNGLLOADTRANSPOSEMATRIXDPROC glLoadTransposeMatrixd_Impl;
 26.1265 +        PFNGLLOADTRANSPOSEMATRIXFPROC glLoadTransposeMatrixf_Impl;
 26.1266 +        PFNGLMULTTRANSPOSEMATRIXDPROC glMultTransposeMatrixd_Impl;
 26.1267 +        PFNGLMULTTRANSPOSEMATRIXFPROC glMultTransposeMatrixf_Impl;
 26.1268 +        PFNGLMULTITEXCOORD1DPROC glMultiTexCoord1d_Impl;
 26.1269 +        PFNGLMULTITEXCOORD1DVPROC glMultiTexCoord1dv_Impl;
 26.1270 +        PFNGLMULTITEXCOORD1FPROC glMultiTexCoord1f_Impl;
 26.1271 +        PFNGLMULTITEXCOORD1FVPROC glMultiTexCoord1fv_Impl;
 26.1272 +        PFNGLMULTITEXCOORD1IPROC glMultiTexCoord1i_Impl;
 26.1273 +        PFNGLMULTITEXCOORD1IVPROC glMultiTexCoord1iv_Impl;
 26.1274 +        PFNGLMULTITEXCOORD1SPROC glMultiTexCoord1s_Impl;
 26.1275 +        PFNGLMULTITEXCOORD1SVPROC glMultiTexCoord1sv_Impl;
 26.1276 +        PFNGLMULTITEXCOORD2DPROC glMultiTexCoord2d_Impl;
 26.1277 +        PFNGLMULTITEXCOORD2DVPROC glMultiTexCoord2dv_Impl;
 26.1278 +        PFNGLMULTITEXCOORD2FPROC glMultiTexCoord2f_Impl;
 26.1279 +        PFNGLMULTITEXCOORD2FVPROC glMultiTexCoord2fv_Impl;
 26.1280 +        PFNGLMULTITEXCOORD2IPROC glMultiTexCoord2i_Impl;
 26.1281 +        PFNGLMULTITEXCOORD2IVPROC glMultiTexCoord2iv_Impl;
 26.1282 +        PFNGLMULTITEXCOORD2SPROC glMultiTexCoord2s_Impl;
 26.1283 +        PFNGLMULTITEXCOORD2SVPROC glMultiTexCoord2sv_Impl;
 26.1284 +        PFNGLMULTITEXCOORD3DPROC glMultiTexCoord3d_Impl;
 26.1285 +        PFNGLMULTITEXCOORD3DVPROC glMultiTexCoord3dv_Impl;
 26.1286 +        PFNGLMULTITEXCOORD3FPROC glMultiTexCoord3f_Impl;
 26.1287 +        PFNGLMULTITEXCOORD3FVPROC glMultiTexCoord3fv_Impl;
 26.1288 +        PFNGLMULTITEXCOORD3IPROC glMultiTexCoord3i_Impl;
 26.1289 +        PFNGLMULTITEXCOORD3IVPROC glMultiTexCoord3iv_Impl;
 26.1290 +        PFNGLMULTITEXCOORD3SPROC glMultiTexCoord3s_Impl;
 26.1291 +        PFNGLMULTITEXCOORD3SVPROC glMultiTexCoord3sv_Impl;
 26.1292 +        PFNGLMULTITEXCOORD4DPROC glMultiTexCoord4d_Impl;
 26.1293 +        PFNGLMULTITEXCOORD4DVPROC glMultiTexCoord4dv_Impl;
 26.1294 +        PFNGLMULTITEXCOORD4FPROC glMultiTexCoord4f_Impl;
 26.1295 +        PFNGLMULTITEXCOORD4FVPROC glMultiTexCoord4fv_Impl;
 26.1296 +        PFNGLMULTITEXCOORD4IPROC glMultiTexCoord4i_Impl;
 26.1297 +        PFNGLMULTITEXCOORD4IVPROC glMultiTexCoord4iv_Impl;
 26.1298 +        PFNGLMULTITEXCOORD4SPROC glMultiTexCoord4s_Impl;
 26.1299 +        PFNGLMULTITEXCOORD4SVPROC glMultiTexCoord4sv_Impl;
 26.1300 +        PFNGLSAMPLECOVERAGEPROC glSampleCoverage_Impl;
 26.1301 +
 26.1302 +        // GL_VERSION_1_4
 26.1303 +        PFNGLBLENDCOLORPROC glBlendColor_Impl;
 26.1304 +        PFNGLBLENDEQUATIONPROC glBlendEquation_Impl;
 26.1305 +        PFNGLBLENDFUNCSEPARATEPROC glBlendFuncSeparate_Impl;
 26.1306 +        PFNGLFOGCOORDPOINTERPROC glFogCoordPointer_Impl;
 26.1307 +        PFNGLFOGCOORDDPROC glFogCoordd_Impl;
 26.1308 +        PFNGLFOGCOORDDVPROC glFogCoorddv_Impl;
 26.1309 +        PFNGLFOGCOORDFPROC glFogCoordf_Impl;
 26.1310 +        PFNGLFOGCOORDFVPROC glFogCoordfv_Impl;
 26.1311 +        PFNGLMULTIDRAWARRAYSPROC glMultiDrawArrays_Impl;
 26.1312 +        PFNGLMULTIDRAWELEMENTSPROC glMultiDrawElements_Impl;
 26.1313 +        PFNGLPOINTPARAMETERFPROC glPointParameterf_Impl;
 26.1314 +        PFNGLPOINTPARAMETERFVPROC glPointParameterfv_Impl;
 26.1315 +        PFNGLPOINTPARAMETERIPROC glPointParameteri_Impl;
 26.1316 +        PFNGLPOINTPARAMETERIVPROC glPointParameteriv_Impl;
 26.1317 +        PFNGLSECONDARYCOLOR3BPROC glSecondaryColor3b_Impl;
 26.1318 +        PFNGLSECONDARYCOLOR3BVPROC glSecondaryColor3bv_Impl;
 26.1319 +        PFNGLSECONDARYCOLOR3DPROC glSecondaryColor3d_Impl;
 26.1320 +        PFNGLSECONDARYCOLOR3DVPROC glSecondaryColor3dv_Impl;
 26.1321 +        PFNGLSECONDARYCOLOR3FPROC glSecondaryColor3f_Impl;
 26.1322 +        PFNGLSECONDARYCOLOR3FVPROC glSecondaryColor3fv_Impl;
 26.1323 +        PFNGLSECONDARYCOLOR3IPROC glSecondaryColor3i_Impl;
 26.1324 +        PFNGLSECONDARYCOLOR3IVPROC glSecondaryColor3iv_Impl;
 26.1325 +        PFNGLSECONDARYCOLOR3SPROC glSecondaryColor3s_Impl;
 26.1326 +        PFNGLSECONDARYCOLOR3SVPROC glSecondaryColor3sv_Impl;
 26.1327 +        PFNGLSECONDARYCOLOR3UBPROC glSecondaryColor3ub_Impl;
 26.1328 +        PFNGLSECONDARYCOLOR3UBVPROC glSecondaryColor3ubv_Impl;
 26.1329 +        PFNGLSECONDARYCOLOR3UIPROC glSecondaryColor3ui_Impl;
 26.1330 +        PFNGLSECONDARYCOLOR3UIVPROC glSecondaryColor3uiv_Impl;
 26.1331 +        PFNGLSECONDARYCOLOR3USPROC glSecondaryColor3us_Impl;
 26.1332 +        PFNGLSECONDARYCOLOR3USVPROC glSecondaryColor3usv_Impl;
 26.1333 +        PFNGLSECONDARYCOLORPOINTERPROC glSecondaryColorPointer_Impl;
 26.1334 +        PFNGLWINDOWPOS2DPROC glWindowPos2d_Impl;
 26.1335 +        PFNGLWINDOWPOS2DVPROC glWindowPos2dv_Impl;
 26.1336 +        PFNGLWINDOWPOS2FPROC glWindowPos2f_Impl;
 26.1337 +        PFNGLWINDOWPOS2FVPROC glWindowPos2fv_Impl;
 26.1338 +        PFNGLWINDOWPOS2IPROC glWindowPos2i_Impl;
 26.1339 +        PFNGLWINDOWPOS2IVPROC glWindowPos2iv_Impl;
 26.1340 +        PFNGLWINDOWPOS2SPROC glWindowPos2s_Impl;
 26.1341 +        PFNGLWINDOWPOS2SVPROC glWindowPos2sv_Impl;
 26.1342 +        PFNGLWINDOWPOS3DPROC glWindowPos3d_Impl;
 26.1343 +        PFNGLWINDOWPOS3DVPROC glWindowPos3dv_Impl;
 26.1344 +        PFNGLWINDOWPOS3FPROC glWindowPos3f_Impl;
 26.1345 +        PFNGLWINDOWPOS3FVPROC glWindowPos3fv_Impl;
 26.1346 +        PFNGLWINDOWPOS3IPROC glWindowPos3i_Impl;
 26.1347 +        PFNGLWINDOWPOS3IVPROC glWindowPos3iv_Impl;
 26.1348 +        PFNGLWINDOWPOS3SPROC glWindowPos3s_Impl;
 26.1349 +        PFNGLWINDOWPOS3SVPROC glWindowPos3sv_Impl;
 26.1350 +
 26.1351 +        // GL_VERSION_1_5
 26.1352 +        PFNGLBEGINQUERYPROC glBeginQuery_Impl;
 26.1353 +        PFNGLBINDBUFFERPROC glBindBuffer_Impl;
 26.1354 +        PFNGLBUFFERDATAPROC glBufferData_Impl;
 26.1355 +        PFNGLBUFFERSUBDATAPROC glBufferSubData_Impl;
 26.1356 +        PFNGLDELETEBUFFERSPROC glDeleteBuffers_Impl;
 26.1357 +        PFNGLDELETEQUERIESPROC glDeleteQueries_Impl;
 26.1358 +        PFNGLENDQUERYPROC glEndQuery_Impl;
 26.1359 +        PFNGLGENBUFFERSPROC glGenBuffers_Impl;
 26.1360 +        PFNGLGENQUERIESPROC glGenQueries_Impl;
 26.1361 +        PFNGLGETBUFFERPARAMETERIVPROC glGetBufferParameteriv_Impl;
 26.1362 +        PFNGLGETBUFFERPOINTERVPROC glGetBufferPointerv_Impl;
 26.1363 +        PFNGLGETBUFFERSUBDATAPROC glGetBufferSubData_Impl;
 26.1364 +        PFNGLGETQUERYOBJECTIVPROC glGetQueryObjectiv_Impl;
 26.1365 +        PFNGLGETQUERYOBJECTUIVPROC glGetQueryObjectuiv_Impl;
 26.1366 +        PFNGLGETQUERYIVPROC glGetQueryiv_Impl;
 26.1367 +        PFNGLISBUFFERPROC glIsBuffer_Impl;
 26.1368 +        PFNGLISQUERYPROC glIsQuery_Impl;
 26.1369 +        PFNGLMAPBUFFERPROC glMapBuffer_Impl;
 26.1370 +        PFNGLUNMAPBUFFERPROC glUnmapBuffer_Impl;
 26.1371 +
 26.1372 +        // GL_VERSION_2_0
 26.1373 +        PFNGLATTACHSHADERPROC glAttachShader_Impl;
 26.1374 +        PFNGLBINDATTRIBLOCATIONPROC glBindAttribLocation_Impl;
 26.1375 +        PFNGLBLENDEQUATIONSEPARATEPROC glBlendEquationSeparate_Impl;
 26.1376 +        PFNGLCOMPILESHADERPROC glCompileShader_Impl;
 26.1377 +        PFNGLCREATEPROGRAMPROC glCreateProgram_Impl;
 26.1378 +        PFNGLCREATESHADERPROC glCreateShader_Impl;
 26.1379 +        PFNGLDELETEPROGRAMPROC glDeleteProgram_Impl;
 26.1380 +        PFNGLDELETESHADERPROC glDeleteShader_Impl;
 26.1381 +        PFNGLDETACHSHADERPROC glDetachShader_Impl;
 26.1382 +        PFNGLDISABLEVERTEXATTRIBARRAYPROC glDisableVertexAttribArray_Impl;
 26.1383 +        PFNGLDRAWBUFFERSPROC glDrawBuffers_Impl;
 26.1384 +        PFNGLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray_Impl;
 26.1385 +        PFNGLGETACTIVEATTRIBPROC glGetActiveAttrib_Impl;
 26.1386 +        PFNGLGETACTIVEUNIFORMPROC glGetActiveUniform_Impl;
 26.1387 +        PFNGLGETATTACHEDSHADERSPROC glGetAttachedShaders_Impl;
 26.1388 +        PFNGLGETATTRIBLOCATIONPROC glGetAttribLocation_Impl;
 26.1389 +        PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog_Impl;
 26.1390 +        PFNGLGETPROGRAMIVPROC glGetProgramiv_Impl;
 26.1391 +        PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog_Impl;
 26.1392 +        PFNGLGETSHADERSOURCEPROC glGetShaderSource_Impl;
 26.1393 +        PFNGLGETSHADERIVPROC glGetShaderiv_Impl;
 26.1394 +        PFNGLGETUNIFORMLOCATIONPROC glGetUniformLocation_Impl;
 26.1395 +        PFNGLGETUNIFORMFVPROC glGetUniformfv_Impl;
 26.1396 +        PFNGLGETUNIFORMIVPROC glGetUniformiv_Impl;
 26.1397 +        PFNGLGETVERTEXATTRIBPOINTERVPROC glGetVertexAttribPointerv_Impl;
 26.1398 +        PFNGLGETVERTEXATTRIBDVPROC glGetVertexAttribdv_Impl;
 26.1399 +        PFNGLGETVERTEXATTRIBFVPROC glGetVertexAttribfv_Impl;
 26.1400 +        PFNGLGETVERTEXATTRIBIVPROC glGetVertexAttribiv_Impl;
 26.1401 +        PFNGLISPROGRAMPROC glIsProgram_Impl;
 26.1402 +        PFNGLISSHADERPROC glIsShader_Impl;
 26.1403 +        PFNGLLINKPROGRAMPROC glLinkProgram_Impl;
 26.1404 +        PFNGLSHADERSOURCEPROC glShaderSource_Impl;
 26.1405 +        PFNGLSTENCILFUNCSEPARATEPROC glStencilFuncSeparate_Impl;
 26.1406 +        PFNGLSTENCILMASKSEPARATEPROC glStencilMaskSeparate_Impl;
 26.1407 +        PFNGLSTENCILOPSEPARATEPROC glStencilOpSeparate_Impl;
 26.1408 +        PFNGLUNIFORM1FPROC glUniform1f_Impl;
 26.1409 +        PFNGLUNIFORM1FVPROC glUniform1fv_Impl;
 26.1410 +        PFNGLUNIFORM1IPROC glUniform1i_Impl;
 26.1411 +        PFNGLUNIFORM1IVPROC glUniform1iv_Impl;
 26.1412 +        PFNGLUNIFORM2FPROC glUniform2f_Impl;
 26.1413 +        PFNGLUNIFORM2FVPROC glUniform2fv_Impl;
 26.1414 +        PFNGLUNIFORM2IPROC glUniform2i_Impl;
 26.1415 +        PFNGLUNIFORM2IVPROC glUniform2iv_Impl;
 26.1416 +        PFNGLUNIFORM3FPROC glUniform3f_Impl;
 26.1417 +        PFNGLUNIFORM3FVPROC glUniform3fv_Impl;
 26.1418 +        PFNGLUNIFORM3IPROC glUniform3i_Impl;
 26.1419 +        PFNGLUNIFORM3IVPROC glUniform3iv_Impl;
 26.1420 +        PFNGLUNIFORM4FPROC glUniform4f_Impl;
 26.1421 +        PFNGLUNIFORM4FVPROC glUniform4fv_Impl;
 26.1422 +        PFNGLUNIFORM4IPROC glUniform4i_Impl;
 26.1423 +        PFNGLUNIFORM4IVPROC glUniform4iv_Impl;
 26.1424 +        PFNGLUNIFORMMATRIX2FVPROC glUniformMatrix2fv_Impl;
 26.1425 +        PFNGLUNIFORMMATRIX3FVPROC glUniformMatrix3fv_Impl;
 26.1426 +        PFNGLUNIFORMMATRIX4FVPROC glUniformMatrix4fv_Impl;
 26.1427 +        PFNGLUSEPROGRAMPROC glUseProgram_Impl;
 26.1428 +        PFNGLVALIDATEPROGRAMPROC glValidateProgram_Impl;
 26.1429 +        PFNGLVERTEXATTRIB1DPROC glVertexAttrib1d_Impl;
 26.1430 +        PFNGLVERTEXATTRIB1DVPROC glVertexAttrib1dv_Impl;
 26.1431 +        PFNGLVERTEXATTRIB1FPROC glVertexAttrib1f_Impl;
 26.1432 +        PFNGLVERTEXATTRIB1FVPROC glVertexAttrib1fv_Impl;
 26.1433 +        PFNGLVERTEXATTRIB1SPROC glVertexAttrib1s_Impl;
 26.1434 +        PFNGLVERTEXATTRIB1SVPROC glVertexAttrib1sv_Impl;
 26.1435 +        PFNGLVERTEXATTRIB2DPROC glVertexAttrib2d_Impl;
 26.1436 +        PFNGLVERTEXATTRIB2DVPROC glVertexAttrib2dv_Impl;
 26.1437 +        PFNGLVERTEXATTRIB2FPROC glVertexAttrib2f_Impl;
 26.1438 +        PFNGLVERTEXATTRIB2FVPROC glVertexAttrib2fv_Impl;
 26.1439 +        PFNGLVERTEXATTRIB2SPROC glVertexAttrib2s_Impl;
 26.1440 +        PFNGLVERTEXATTRIB2SVPROC glVertexAttrib2sv_Impl;
 26.1441 +        PFNGLVERTEXATTRIB3DPROC glVertexAttrib3d_Impl;
 26.1442 +        PFNGLVERTEXATTRIB3DVPROC glVertexAttrib3dv_Impl;
 26.1443 +        PFNGLVERTEXATTRIB3FPROC glVertexAttrib3f_Impl;
 26.1444 +        PFNGLVERTEXATTRIB3FVPROC glVertexAttrib3fv_Impl;
 26.1445 +        PFNGLVERTEXATTRIB3SPROC glVertexAttrib3s_Impl;
 26.1446 +        PFNGLVERTEXATTRIB3SVPROC glVertexAttrib3sv_Impl;
 26.1447 +        PFNGLVERTEXATTRIB4NBVPROC glVertexAttrib4Nbv_Impl;
 26.1448 +        PFNGLVERTEXATTRIB4NIVPROC glVertexAttrib4Niv_Impl;
 26.1449 +        PFNGLVERTEXATTRIB4NSVPROC glVertexAttrib4Nsv_Impl;
 26.1450 +        PFNGLVERTEXATTRIB4NUBPROC glVertexAttrib4Nub_Impl;
 26.1451 +        PFNGLVERTEXATTRIB4NUBVPROC glVertexAttrib4Nubv_Impl;
 26.1452 +        PFNGLVERTEXATTRIB4NUIVPROC glVertexAttrib4Nuiv_Impl;
 26.1453 +        PFNGLVERTEXATTRIB4NUSVPROC glVertexAttrib4Nusv_Impl;
 26.1454 +        PFNGLVERTEXATTRIB4BVPROC glVertexAttrib4bv_Impl;
 26.1455 +        PFNGLVERTEXATTRIB4DPROC glVertexAttrib4d_Impl;
 26.1456 +        PFNGLVERTEXATTRIB4DVPROC glVertexAttrib4dv_Impl;
 26.1457 +        PFNGLVERTEXATTRIB4FPROC glVertexAttrib4f_Impl;
 26.1458 +        PFNGLVERTEXATTRIB4FVPROC glVertexAttrib4fv_Impl;
 26.1459 +        PFNGLVERTEXATTRIB4IVPROC glVertexAttrib4iv_Impl;
 26.1460 +        PFNGLVERTEXATTRIB4SPROC glVertexAttrib4s_Impl;
 26.1461 +        PFNGLVERTEXATTRIB4SVPROC glVertexAttrib4sv_Impl;
 26.1462 +        PFNGLVERTEXATTRIB4UBVPROC glVertexAttrib4ubv_Impl;
 26.1463 +        PFNGLVERTEXATTRIB4UIVPROC glVertexAttrib4uiv_Impl;
 26.1464 +        PFNGLVERTEXATTRIB4USVPROC glVertexAttrib4usv_Impl;
 26.1465 +        PFNGLVERTEXATTRIBPOINTERPROC glVertexAttribPointer_Impl;
 26.1466 +
 26.1467 +        // GL_VERSION_2_1
 26.1468 +        PFNGLUNIFORMMATRIX2X3FVPROC glUniformMatrix2x3fv_Impl;
 26.1469 +        PFNGLUNIFORMMATRIX2X4FVPROC glUniformMatrix2x4fv_Impl;
 26.1470 +        PFNGLUNIFORMMATRIX3X2FVPROC glUniformMatrix3x2fv_Impl;
 26.1471 +        PFNGLUNIFORMMATRIX3X4FVPROC glUniformMatrix3x4fv_Impl;
 26.1472 +        PFNGLUNIFORMMATRIX4X2FVPROC glUniformMatrix4x2fv_Impl;
 26.1473 +        PFNGLUNIFORMMATRIX4X3FVPROC glUniformMatrix4x3fv_Impl;
 26.1474 +
 26.1475 +        // GL_VERSION_3_0
 26.1476 +        PFNGLBEGINCONDITIONALRENDERPROC glBeginConditionalRender_Impl;
 26.1477 +        PFNGLBEGINTRANSFORMFEEDBACKPROC glBeginTransformFeedback_Impl;
 26.1478 +        PFNGLBINDFRAGDATALOCATIONPROC glBindFragDataLocation_Impl;
 26.1479 +        PFNGLCLAMPCOLORPROC glClampColor_Impl;
 26.1480 +        PFNGLCLEARBUFFERFIPROC glClearBufferfi_Impl;
 26.1481 +        PFNGLCLEARBUFFERFVPROC glClearBufferfv_Impl;
 26.1482 +        PFNGLCLEARBUFFERIVPROC glClearBufferiv_Impl;
 26.1483 +        PFNGLCLEARBUFFERUIVPROC glClearBufferuiv_Impl;
 26.1484 +        PFNGLCOLORMASKIPROC glColorMaski_Impl;
 26.1485 +        PFNGLDISABLEIPROC glDisablei_Impl;
 26.1486 +        PFNGLENABLEIPROC glEnablei_Impl;
 26.1487 +        PFNGLENDCONDITIONALRENDERPROC glEndConditionalRender_Impl;
 26.1488 +        PFNGLENDTRANSFORMFEEDBACKPROC glEndTransformFeedback_Impl;
 26.1489 +        PFNGLBINDBUFFERRANGEPROC glBindBufferRange_Impl;
 26.1490 +        PFNGLBINDBUFFERBASEPROC glBindBufferBase_Impl;
 26.1491 +        PFNGLGETBOOLEANI_VPROC glGetBooleani_v_Impl;
 26.1492 +        PFNGLGETINTEGERI_VPROC glGetIntegeri_v_Impl;
 26.1493 +        PFNGLGETFRAGDATALOCATIONPROC glGetFragDataLocation_Impl;
 26.1494 +        PFNGLGETSTRINGIPROC glGetStringi_Impl;
 26.1495 +        PFNGLGETTEXPARAMETERIIVPROC glGetTexParameterIiv_Impl;
 26.1496 +        PFNGLGETTEXPARAMETERIUIVPROC glGetTexParameterIuiv_Impl;
 26.1497 +        PFNGLGETTRANSFORMFEEDBACKVARYINGPROC glGetTransformFeedbackVarying_Impl;
 26.1498 +        PFNGLGETUNIFORMUIVPROC glGetUniformuiv_Impl;
 26.1499 +        PFNGLGETVERTEXATTRIBIIVPROC glGetVertexAttribIiv_Impl;
 26.1500 +        PFNGLGETVERTEXATTRIBIUIVPROC glGetVertexAttribIuiv_Impl;
 26.1501 +        PFNGLISENABLEDIPROC glIsEnabledi_Impl;
 26.1502 +        PFNGLTEXPARAMETERIIVPROC glTexParameterIiv_Impl;
 26.1503 +        PFNGLTEXPARAMETERIUIVPROC glTexParameterIuiv_Impl;
 26.1504 +        PFNGLTRANSFORMFEEDBACKVARYINGSPROC glTransformFeedbackVaryings_Impl;
 26.1505 +        PFNGLUNIFORM1UIPROC glUniform1ui_Impl;
 26.1506 +        PFNGLUNIFORM1UIVPROC glUniform1uiv_Impl;
 26.1507 +        PFNGLUNIFORM2UIPROC glUniform2ui_Impl;
 26.1508 +        PFNGLUNIFORM2UIVPROC glUniform2uiv_Impl;
 26.1509 +        PFNGLUNIFORM3UIPROC glUniform3ui_Impl;
 26.1510 +        PFNGLUNIFORM3UIVPROC glUniform3uiv_Impl;
 26.1511 +        PFNGLUNIFORM4UIPROC glUniform4ui_Impl;
 26.1512 +        PFNGLUNIFORM4UIVPROC glUniform4uiv_Impl;
 26.1513 +        PFNGLVERTEXATTRIBI1IPROC glVertexAttribI1i_Impl;
 26.1514 +        PFNGLVERTEXATTRIBI1IVPROC glVertexAttribI1iv_Impl;
 26.1515 +        PFNGLVERTEXATTRIBI1UIPROC glVertexAttribI1ui_Impl;
 26.1516 +        PFNGLVERTEXATTRIBI1UIVPROC glVertexAttribI1uiv_Impl;
 26.1517 +        PFNGLVERTEXATTRIBI2IPROC glVertexAttribI2i_Impl;
 26.1518 +        PFNGLVERTEXATTRIBI2IVPROC glVertexAttribI2iv_Impl;
 26.1519 +        PFNGLVERTEXATTRIBI2UIPROC glVertexAttribI2ui_Impl;
 26.1520 +        PFNGLVERTEXATTRIBI2UIVPROC glVertexAttribI2uiv_Impl;
 26.1521 +        PFNGLVERTEXATTRIBI3IPROC glVertexAttribI3i_Impl;
 26.1522 +        PFNGLVERTEXATTRIBI3IVPROC glVertexAttribI3iv_Impl;
 26.1523 +        PFNGLVERTEXATTRIBI3UIPROC glVertexAttribI3ui_Impl;
 26.1524 +        PFNGLVERTEXATTRIBI3UIVPROC glVertexAttribI3uiv_Impl;
 26.1525 +        PFNGLVERTEXATTRIBI4BVPROC glVertexAttribI4bv_Impl;
 26.1526 +        PFNGLVERTEXATTRIBI4IPROC glVertexAttribI4i_Impl;
 26.1527 +        PFNGLVERTEXATTRIBI4IVPROC glVertexAttribI4iv_Impl;
 26.1528 +        PFNGLVERTEXATTRIBI4SVPROC glVertexAttribI4sv_Impl;
 26.1529 +        PFNGLVERTEXATTRIBI4UBVPROC glVertexAttribI4ubv_Impl;
 26.1530 +        PFNGLVERTEXATTRIBI4UIPROC glVertexAttribI4ui_Impl;
 26.1531 +        PFNGLVERTEXATTRIBI4UIVPROC glVertexAttribI4uiv_Impl;
 26.1532 +        PFNGLVERTEXATTRIBI4USVPROC glVertexAttribI4usv_Impl;
 26.1533 +        PFNGLVERTEXATTRIBIPOINTERPROC glVertexAttribIPointer_Impl;
 26.1534 +
 26.1535 +        // GL_VERSION_3_1
 26.1536 +        PFNGLDRAWARRAYSINSTANCEDPROC glDrawArraysInstanced_Impl;
 26.1537 +        PFNGLDRAWELEMENTSINSTANCEDPROC glDrawElementsInstanced_Impl;
 26.1538 +        PFNGLPRIMITIVERESTARTINDEXPROC glPrimitiveRestartIndex_Impl;
 26.1539 +        PFNGLTEXBUFFERPROC glTexBuffer_Impl;
 26.1540 +
 26.1541 +        // GL_VERSION_3_2
 26.1542 +        PFNGLFRAMEBUFFERTEXTUREPROC glFramebufferTexture_Impl;
 26.1543 +        PFNGLGETBUFFERPARAMETERI64VPROC glGetBufferParameteri64v_Impl;
 26.1544 +        PFNGLGETINTEGER64I_VPROC glGetInteger64i_v_Impl;
 26.1545 +
 26.1546 +        // GL_VERSION_3_3
 26.1547 +        PFNGLVERTEXATTRIBDIVISORPROC glVertexAttribDivisor_Impl;
 26.1548 +
 26.1549 +        // GL_VERSION_4_0
 26.1550 +        PFNGLBLENDEQUATIONSEPARATEIPROC glBlendEquationSeparatei_Impl;
 26.1551 +        PFNGLBLENDEQUATIONIPROC glBlendEquationi_Impl;
 26.1552 +        PFNGLBLENDFUNCSEPARATEIPROC glBlendFuncSeparatei_Impl;
 26.1553 +        PFNGLBLENDFUNCIPROC glBlendFunci_Impl;
 26.1554 +        PFNGLMINSAMPLESHADINGPROC glMinSampleShading_Impl;
 26.1555 +
 26.1556 +        // GL_AMD_debug_output
 26.1557 +        PFNGLDEBUGMESSAGECALLBACKAMDPROC glDebugMessageCallbackAMD_Impl;
 26.1558 +        PFNGLDEBUGMESSAGEENABLEAMDPROC glDebugMessageEnableAMD_Impl;
 26.1559 +        PFNGLDEBUGMESSAGEINSERTAMDPROC glDebugMessageInsertAMD_Impl;
 26.1560 +        PFNGLGETDEBUGMESSAGELOGAMDPROC glGetDebugMessageLogAMD_Impl;
 26.1561 +
 26.1562 +      #if defined(GLE_CGL_ENABLED)
 26.1563 +        // GL_APPLE_aux_depth_stencil
 26.1564 +        // (no functions)
 26.1565 +
 26.1566 +        // GL_APPLE_client_storage
 26.1567 +        // (no functions)
 26.1568 +
 26.1569 +        // GL_APPLE_element_array
 26.1570 +        PFNGLDRAWELEMENTARRAYAPPLEPROC glDrawElementArrayAPPLE_Impl;
 26.1571 +        PFNGLDRAWRANGEELEMENTARRAYAPPLEPROC glDrawRangeElementArrayAPPLE_Impl;
 26.1572 +        PFNGLELEMENTPOINTERAPPLEPROC glElementPointerAPPLE_Impl;
 26.1573 +        PFNGLMULTIDRAWELEMENTARRAYAPPLEPROC glMultiDrawElementArrayAPPLE_Impl;
 26.1574 +        PFNGLMULTIDRAWRANGEELEMENTARRAYAPPLEPROC glMultiDrawRangeElementArrayAPPLE_Impl;
 26.1575 +
 26.1576 +        // GL_APPLE_fence
 26.1577 +        PFNGLDELETEFENCESAPPLEPROC glDeleteFencesAPPLE_Impl;
 26.1578 +        PFNGLFINISHFENCEAPPLEPROC glFinishFenceAPPLE_Impl;
 26.1579 +        PFNGLFINISHOBJECTAPPLEPROC glFinishObjectAPPLE_Impl;
 26.1580 +        PFNGLGENFENCESAPPLEPROC glGenFencesAPPLE_Impl;
 26.1581 +        PFNGLISFENCEAPPLEPROC glIsFenceAPPLE_Impl;
 26.1582 +        PFNGLSETFENCEAPPLEPROC glSetFenceAPPLE_Impl;
 26.1583 +        PFNGLTESTFENCEAPPLEPROC glTestFenceAPPLE_Impl;
 26.1584 +        PFNGLTESTOBJECTAPPLEPROC glTestObjectAPPLE_Impl;
 26.1585 +
 26.1586 +        // GL_APPLE_float_pixels
 26.1587 +        // (no functions)
 26.1588 +
 26.1589 +        // GL_APPLE_flush_buffer_range
 26.1590 +        PFNGLBUFFERPARAMETERIAPPLEPROC glBufferParameteriAPPLE_Impl;
 26.1591 +        PFNGLFLUSHMAPPEDBUFFERRANGEAPPLEPROC glFlushMappedBufferRangeAPPLE_Impl;
 26.1592 +
 26.1593 +        // GL_APPLE_object_purgeable
 26.1594 +        PFNGLGETOBJECTPARAMETERIVAPPLEPROC glGetObjectParameterivAPPLE_Impl;
 26.1595 +        PFNGLOBJECTPURGEABLEAPPLEPROC glObjectPurgeableAPPLE_Impl;
 26.1596 +        PFNGLOBJECTUNPURGEABLEAPPLEPROC glObjectUnpurgeableAPPLE_Impl;
 26.1597 +
 26.1598 +        // GL_APPLE_pixel_buffer
 26.1599 +        // (no functions)
 26.1600 +
 26.1601 +        // GL_APPLE_rgb_422
 26.1602 +        // (no functions)
 26.1603 +
 26.1604 +        // GL_APPLE_row_bytes
 26.1605 +        // (no functions)
 26.1606 +
 26.1607 +        // GL_APPLE_specular_vector
 26.1608 +        // (no functions)
 26.1609 +
 26.1610 +        // GL_APPLE_texture_range
 26.1611 +        PFNGLGETTEXPARAMETERPOINTERVAPPLEPROC glGetTexParameterPointervAPPLE_Impl;
 26.1612 +        PFNGLTEXTURERANGEAPPLEPROC glTextureRangeAPPLE_Impl;
 26.1613 +
 26.1614 +        // GL_APPLE_transform_hint
 26.1615 +        // (no functions)
 26.1616 +
 26.1617 +        // GL_APPLE_vertex_array_object
 26.1618 +        PFNGLBINDVERTEXARRAYAPPLEPROC glBindVertexArrayAPPLE_Impl;
 26.1619 +        PFNGLDELETEVERTEXARRAYSAPPLEPROC glDeleteVertexArraysAPPLE_Impl;
 26.1620 +        PFNGLGENVERTEXARRAYSAPPLEPROC glGenVertexArraysAPPLE_Impl;
 26.1621 +        PFNGLISVERTEXARRAYAPPLEPROC glIsVertexArrayAPPLE_Impl;
 26.1622 +
 26.1623 +        // GL_APPLE_vertex_array_range
 26.1624 +        PFNGLFLUSHVERTEXARRAYRANGEAPPLEPROC glFlushVertexArrayRangeAPPLE_Impl;
 26.1625 +        PFNGLVERTEXARRAYPARAMETERIAPPLEPROC glVertexArrayParameteriAPPLE_Impl;
 26.1626 +        PFNGLVERTEXARRAYRANGEAPPLEPROC glVertexArrayRangeAPPLE_Impl;
 26.1627 +
 26.1628 +        // GL_APPLE_vertex_program_evaluators
 26.1629 +        PFNGLDISABLEVERTEXATTRIBAPPLEPROC glDisableVertexAttribAPPLE_Impl;
 26.1630 +        PFNGLENABLEVERTEXATTRIBAPPLEPROC glEnableVertexAttribAPPLE_Impl;
 26.1631 +        PFNGLISVERTEXATTRIBENABLEDAPPLEPROC glIsVertexAttribEnabledAPPLE_Impl;
 26.1632 +        PFNGLMAPVERTEXATTRIB1DAPPLEPROC glMapVertexAttrib1dAPPLE_Impl;
 26.1633 +        PFNGLMAPVERTEXATTRIB1FAPPLEPROC glMapVertexAttrib1fAPPLE_Impl;
 26.1634 +        PFNGLMAPVERTEXATTRIB2DAPPLEPROC glMapVertexAttrib2dAPPLE_Impl;
 26.1635 +        PFNGLMAPVERTEXATTRIB2FAPPLEPROC glMapVertexAttrib2fAPPLE_Impl;
 26.1636 +      #endif // GLE_CGL_ENABLED
 26.1637 +      
 26.1638 +        // GL_ARB_debug_output
 26.1639 +        PFNGLDEBUGMESSAGECALLBACKARBPROC glDebugMessageCallbackARB_Impl;
 26.1640 +        PFNGLDEBUGMESSAGECONTROLARBPROC glDebugMessageControlARB_Impl;
 26.1641 +        PFNGLDEBUGMESSAGEINSERTARBPROC glDebugMessageInsertARB_Impl;
 26.1642 +        PFNGLGETDEBUGMESSAGELOGARBPROC glGetDebugMessageLogARB_Impl;
 26.1643 +
 26.1644 +        // GL_ARB_ES2_compatibility
 26.1645 +        PFNGLCLEARDEPTHFPROC glClearDepthf_Impl;
 26.1646 +        PFNGLDEPTHRANGEFPROC glDepthRangef_Impl;
 26.1647 +        PFNGLGETSHADERPRECISIONFORMATPROC glGetShaderPrecisionFormat_Impl;
 26.1648 +        PFNGLRELEASESHADERCOMPILERPROC glReleaseShaderCompiler_Impl;
 26.1649 +        PFNGLSHADERBINARYPROC glShaderBinary_Impl;
 26.1650 +
 26.1651 +        // GL_ARB_framebuffer_object
 26.1652 +        PFNGLBINDFRAMEBUFFERPROC glBindFramebuffer_Impl;
 26.1653 +        PFNGLBINDRENDERBUFFERPROC glBindRenderbuffer_Impl;
 26.1654 +        PFNGLBLITFRAMEBUFFERPROC glBlitFramebuffer_Impl;
 26.1655 +        PFNGLCHECKFRAMEBUFFERSTATUSPROC glCheckFramebufferStatus_Impl;
 26.1656 +        PFNGLDELETEFRAMEBUFFERSPROC glDeleteFramebuffers_Impl;
 26.1657 +        PFNGLDELETERENDERBUFFERSPROC glDeleteRenderbuffers_Impl;
 26.1658 +        PFNGLFRAMEBUFFERRENDERBUFFERPROC glFramebufferRenderbuffer_Impl;
 26.1659 +        PFNGLFRAMEBUFFERTEXTURE1DPROC glFramebufferTexture1D_Impl;
 26.1660 +        PFNGLFRAMEBUFFERTEXTURE2DPROC glFramebufferTexture2D_Impl;
 26.1661 +        PFNGLFRAMEBUFFERTEXTURE3DPROC glFramebufferTexture3D_Impl;
 26.1662 +        PFNGLFRAMEBUFFERTEXTURELAYERPROC glFramebufferTextureLayer_Impl;
 26.1663 +        PFNGLGENFRAMEBUFFERSPROC glGenFramebuffers_Impl;
 26.1664 +        PFNGLGENRENDERBUFFERSPROC glGenRenderbuffers_Impl;
 26.1665 +        PFNGLGENERATEMIPMAPPROC glGenerateMipmap_Impl;
 26.1666 +        PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC glGetFramebufferAttachmentParameteriv_Impl;
 26.1667 +        PFNGLGETRENDERBUFFERPARAMETERIVPROC glGetRenderbufferParameteriv_Impl;
 26.1668 +        PFNGLISFRAMEBUFFERPROC glIsFramebuffer_Impl;
 26.1669 +        PFNGLISRENDERBUFFERPROC glIsRenderbuffer_Impl;
 26.1670 +        PFNGLRENDERBUFFERSTORAGEPROC glRenderbufferStorage_Impl;
 26.1671 +        PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC glRenderbufferStorageMultisample_Impl;
 26.1672 +    
 26.1673 +        // GL_ARB_framebuffer_sRGB
 26.1674 +        // (no functions)
 26.1675 +
 26.1676 +        // GL_ARB_texture_multisample
 26.1677 +        PFNGLGETMULTISAMPLEFVPROC glGetMultisamplefv_Impl;
 26.1678 +        PFNGLSAMPLEMASKIPROC glSampleMaski_Impl;
 26.1679 +        PFNGLTEXIMAGE2DMULTISAMPLEPROC glTexImage2DMultisample_Impl;
 26.1680 +        PFNGLTEXIMAGE3DMULTISAMPLEPROC glTexImage3DMultisample_Impl;
 26.1681 +
 26.1682 +        // GL_ARB_texture_non_power_of_two
 26.1683 +        // (no functions)
 26.1684 +
 26.1685 +        // GL_ARB_texture_rectangle
 26.1686 +        // (no functions)
 26.1687 +
 26.1688 +        // GL_ARB_timer_query
 26.1689 +        PFNGLGETQUERYOBJECTI64VPROC glGetQueryObjecti64v_Impl;
 26.1690 +        PFNGLGETQUERYOBJECTUI64VPROC glGetQueryObjectui64v_Impl;
 26.1691 +        PFNGLQUERYCOUNTERPROC glQueryCounter_Impl;
 26.1692 +
 26.1693 +        // GL_ARB_vertex_array_object
 26.1694 +        PFNGLBINDVERTEXARRAYPROC glBindVertexArray_Impl;
 26.1695 +        PFNGLDELETEVERTEXARRAYSPROC glDeleteVertexArrays_Impl;
 26.1696 +        PFNGLGENVERTEXARRAYSPROC glGenVertexArrays_Impl;
 26.1697 +        PFNGLISVERTEXARRAYPROC glIsVertexArray_Impl;
 26.1698 +
 26.1699 +        // GL_EXT_draw_buffers2
 26.1700 +        PFNGLCOLORMASKINDEXEDEXTPROC glColorMaskIndexedEXT_Impl;
 26.1701 +        PFNGLDISABLEINDEXEDEXTPROC glDisableIndexedEXT_Impl;
 26.1702 +        PFNGLENABLEINDEXEDEXTPROC glEnableIndexedEXT_Impl;
 26.1703 +        PFNGLGETBOOLEANINDEXEDVEXTPROC glGetBooleanIndexedvEXT_Impl;
 26.1704 +        PFNGLGETINTEGERINDEXEDVEXTPROC glGetIntegerIndexedvEXT_Impl;
 26.1705 +        PFNGLISENABLEDINDEXEDEXTPROC glIsEnabledIndexedEXT_Impl;
 26.1706 +
 26.1707 +        // GL_EXT_texture_filter_anisotropic
 26.1708 +        // (no functions)
 26.1709 +
 26.1710 +        // GL_KHR_debug
 26.1711 +        PFNGLDEBUGMESSAGECALLBACKPROC glDebugMessageCallback_Impl;
 26.1712 +        PFNGLDEBUGMESSAGECONTROLPROC glDebugMessageControl_Impl;
 26.1713 +        PFNGLDEBUGMESSAGEINSERTPROC glDebugMessageInsert_Impl;
 26.1714 +        PFNGLGETDEBUGMESSAGELOGPROC glGetDebugMessageLog_Impl;
 26.1715 +        PFNGLGETOBJECTLABELPROC glGetObjectLabel_Impl;
 26.1716 +        PFNGLGETOBJECTPTRLABELPROC glGetObjectPtrLabel_Impl;
 26.1717 +        PFNGLOBJECTLABELPROC glObjectLabel_Impl;
 26.1718 +        PFNGLOBJECTPTRLABELPROC glObjectPtrLabel_Impl;
 26.1719 +        PFNGLPOPDEBUGGROUPPROC glPopDebugGroup_Impl;
 26.1720 +        PFNGLPUSHDEBUGGROUPPROC glPushDebugGroup_Impl;
 26.1721 +
 26.1722 +        // GL_KHR_robust_buffer_access_behavior
 26.1723 +        
 26.1724 +        // GL_WIN_swap_hint
 26.1725 +        PFNGLADDSWAPHINTRECTWINPROC glAddSwapHintRectWIN_Impl;
 26.1726 +
 26.1727 +      #if defined(GLE_WGL_ENABLED)
 26.1728 +        // WGL
 26.1729 +        // We don't declare pointers for these because we statically link to the implementations, same as with the OpenGL 1.1 functions.
 26.1730 +        // BOOL  wglCopyContext_Hook(HGLRC, HGLRC, UINT);
 26.1731 +        // HGLRC wglCreateContext_Hook(HDC);
 26.1732 +        // HGLRC wglCreateLayerContext_Hook(HDC, int);
 26.1733 +        // BOOL  wglDeleteContext_Hook(HGLRC);
 26.1734 +        // HGLRC wglGetCurrentContext_Hook(VOID);
 26.1735 +        // HDC   wglGetCurrentDC_Hook(VOID);
 26.1736 +        // PROC  wglGetProcAddress_Hook(LPCSTR);
 26.1737 +        // BOOL  wglMakeCurrent_Hook(HDC, HGLRC);
 26.1738 +        // BOOL  wglShareLists_Hook(HGLRC, HGLRC);
 26.1739 +        // BOOL  wglUseFontBitmapsA_Hook(HDC, DWORD, DWORD, DWORD);
 26.1740 +        // BOOL  wglUseFontBitmapsW_Hook(HDC, DWORD, DWORD, DWORD);
 26.1741 +        // BOOL  wglUseFontOutlinesA_Hook(HDC, DWORD, DWORD, DWORD, FLOAT, FLOAT, int, LPGLYPHMETRICSFLOAT);
 26.1742 +        // BOOL  wglUseFontOutlinesW_Hook(HDC, DWORD, DWORD, DWORD, FLOAT, FLOAT, int, LPGLYPHMETRICSFLOAT);
 26.1743 +        // BOOL  wglDescribeLayerPlane_Hook(HDC, int, int, UINT, LPLAYERPLANEDESCRIPTOR);
 26.1744 +        // int   wglSetLayerPaletteEntries_Hook(HDC, int, int, int, CONST COLORREF *);
 26.1745 +        // int   wglGetLayerPaletteEntries_Hook(HDC, int, int, int, COLORREF *);
 26.1746 +        // BOOL  wglRealizeLayerPalette_Hook(HDC, int, BOOL);
 26.1747 +        // BOOL  wglSwapLayerBuffers_Hook(HDC, UINT);
 26.1748 +        // DWORD wglSwapMultipleBuffers_Hook(UINT, CONST WGLSWAP *);
 26.1749 +
 26.1750 +        #if 0
 26.1751 +        PFNWGLCOPYCONTEXTPROC            wglCopyContext_Impl;
 26.1752 +        PFNWGLCREATECONTEXTPROC          wglCreateContext_Impl;
 26.1753 +        PFNWGLCREATELAYERCONTEXTPROC     wglCreateLayerContext_Impl;
 26.1754 +        PFNWGLDELETECONTEXTPROC          wglDeleteContext_Impl;
 26.1755 +        PFNWGLGETCURRENTCONTEXTPROC      wglGetCurrentContext_Impl;
 26.1756 +        PFNWGLGETCURRENTDCPROC           wglGetCurrentDC_Impl;
 26.1757 +        PFNWGLGETPROCADDRESSPROC         wglGetProcAddress_Impl;
 26.1758 +        PFNWGLMAKECURRENTPROC            wglMakeCurrent_Impl;
 26.1759 +        PFNWGLSHARELISTSPROC             wglShareLists_Impl;
 26.1760 +        PFNWGLUSEFONTBITMAPSAPROC        wglUseFontBitmapsA_Impl;
 26.1761 +        PFNWGLUSEFONTBITMAPSWPROC        wglUseFontBitmapsW_Impl;
 26.1762 +        PFNWGLUSEFONTOUTLINESAPROC       wglUseFontOutlinesA_Impl;
 26.1763 +        PFNWGLUSEFONTOUTLINESWPROC       wglUseFontOutlinesW_Impl;
 26.1764 +        PFNWGLDESCRIBELAYERPLANEPROC     wglDescribeLayerPlane_Impl;
 26.1765 +        PFNWGLSETLAYERPALETTEENTRIESPROC wglSetLayerPaletteEntries_Impl;
 26.1766 +        PFNWGLGETLAYERPALETTEENTRIESPROC wglGetLayerPaletteEntries_Impl;
 26.1767 +        PFNWGLREALIZELAYERPALETTEPROC    wglRealizeLayerPalette_Impl;
 26.1768 +        PFNWGLSWAPLAYERBUFFERSPROC       wglSwapLayerBuffers_Impl;
 26.1769 +        PFNWGLSWAPMULTIPLEBUFFERSPROC    wglSwapMultipleBuffers_Impl;
 26.1770 +        #endif
 26.1771 +
 26.1772 +        // WGL_ARB_buffer_region
 26.1773 +        PFNWGLCREATEBUFFERREGIONARBPROC  wglCreateBufferRegionARB_Impl;
 26.1774 +        PFNWGLDELETEBUFFERREGIONARBPROC  wglDeleteBufferRegionARB_Impl;
 26.1775 +        PFNWGLSAVEBUFFERREGIONARBPROC    wglSaveBufferRegionARB_Impl;
 26.1776 +        PFNWGLRESTOREBUFFERREGIONARBPROC wglRestoreBufferRegionARB_Impl;
 26.1777 +
 26.1778 +        // WGL_ARB_extensions_string
 26.1779 +        PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB_Impl;
 26.1780 +
 26.1781 +        // WGL_ARB_pixel_format
 26.1782 +        PFNWGLGETPIXELFORMATATTRIBIVARBPROC wglGetPixelFormatAttribivARB_Impl;
 26.1783 +        PFNWGLGETPIXELFORMATATTRIBFVARBPROC wglGetPixelFormatAttribfvARB_Impl;
 26.1784 +        PFNWGLCHOOSEPIXELFORMATARBPROC      wglChoosePixelFormatARB_Impl;
 26.1785 +
 26.1786 +        // WGL_ARB_make_current_read
 26.1787 +        PFNWGLMAKECONTEXTCURRENTARBPROC wglMakeContextCurrentARB_Impl;
 26.1788 +        PFNWGLGETCURRENTREADDCARBPROC   wglGetCurrentReadDCARB_Impl;
 26.1789 +
 26.1790 +        // WGL_ARB_pbuffer
 26.1791 +        PFNWGLCREATEPBUFFERARBPROC    wglCreatePbufferARB_Impl;
 26.1792 +        PFNWGLGETPBUFFERDCARBPROC     wglGetPbufferDCARB_Impl;
 26.1793 +        PFNWGLRELEASEPBUFFERDCARBPROC wglReleasePbufferDCARB_Impl;
 26.1794 +        PFNWGLDESTROYPBUFFERARBPROC   wglDestroyPbufferARB_Impl;
 26.1795 +        PFNWGLQUERYPBUFFERARBPROC     wglQueryPbufferARB_Impl;
 26.1796 +
 26.1797 +        // WGL_ARB_render_texture
 26.1798 +        PFNWGLBINDTEXIMAGEARBPROC     wglBindTexImageARB_Impl;
 26.1799 +        PFNWGLRELEASETEXIMAGEARBPROC  wglReleaseTexImageARB_Impl;
 26.1800 +        PFNWGLSETPBUFFERATTRIBARBPROC wglSetPbufferAttribARB_Impl;
 26.1801 +
 26.1802 +        // WGL_ARB_pixel_format_float
 26.1803 +        // (no functions)
 26.1804 +        
 26.1805 +        // WGL_ARB_framebuffer_sRGB
 26.1806 +        // (no functions)
 26.1807 +
 26.1808 +        // WGL_NV_present_video
 26.1809 +        PFNWGLENUMERATEVIDEODEVICESNVPROC wglEnumerateVideoDevicesNV_Impl;
 26.1810 +        PFNWGLBINDVIDEODEVICENVPROC       wglBindVideoDeviceNV_Impl;
 26.1811 +        PFNWGLQUERYCURRENTCONTEXTNVPROC   wglQueryCurrentContextNV_Impl;
 26.1812 +
 26.1813 +        // WGL_ARB_create_context
 26.1814 +        PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB_Impl;
 26.1815 +
 26.1816 +        // WGL_ARB_create_context_profile
 26.1817 +        // (no functions)
 26.1818 +
 26.1819 +        // WGL_ARB_create_context_robustness
 26.1820 +        // (no functions)
 26.1821 +
 26.1822 +        // WGL_EXT_extensions_string
 26.1823 +        PFNWGLGETEXTENSIONSSTRINGEXTPROC wglGetExtensionsStringEXT_Impl;
 26.1824 +
 26.1825 +        // WGL_EXT_swap_control
 26.1826 +        PFNWGLGETSWAPINTERVALEXTPROC wglGetSwapIntervalEXT_Impl;
 26.1827 +        PFNWGLSWAPINTERVALEXTPROC    wglSwapIntervalEXT_Impl;
 26.1828 +
 26.1829 +        // WGL_OML_sync_control
 26.1830 +        PFNWGLGETSYNCVALUESOMLPROC       wglGetSyncValuesOML_Impl;
 26.1831 +        PFNWGLGETMSCRATEOMLPROC          wglGetMscRateOML_Impl;
 26.1832 +        PFNWGLSWAPBUFFERSMSCOMLPROC      wglSwapBuffersMscOML_Impl;
 26.1833 +        PFNWGLSWAPLAYERBUFFERSMSCOMLPROC wglSwapLayerBuffersMscOML_Impl;
 26.1834 +        PFNWGLWAITFORMSCOMLPROC          wglWaitForMscOML_Impl;
 26.1835 +        PFNWGLWAITFORSBCOMLPROC          wglWaitForSbcOML_Impl;
 26.1836 +
 26.1837 +        // WGL_NV_video_output
 26.1838 +        PFNWGLGETVIDEODEVICENVPROC     wglGetVideoDeviceNV_Impl;
 26.1839 +        PFNWGLRELEASEVIDEODEVICENVPROC wglReleaseVideoDeviceNV_Impl;
 26.1840 +        PFNWGLBINDVIDEOIMAGENVPROC     wglBindVideoImageNV_Impl;
 26.1841 +        PFNWGLRELEASEVIDEOIMAGENVPROC  wglReleaseVideoImageNV_Impl;
 26.1842 +        PFNWGLSENDPBUFFERTOVIDEONVPROC wglSendPbufferToVideoNV_Impl;
 26.1843 +        PFNWGLGETVIDEOINFONVPROC       wglGetVideoInfoNV_Impl;
 26.1844 +
 26.1845 +        // WGL_NV_swap_group
 26.1846 +        PFNWGLJOINSWAPGROUPNVPROC      wglJoinSwapGroupNV_Impl;
 26.1847 +        PFNWGLBINDSWAPBARRIERNVPROC    wglBindSwapBarrierNV_Impl;
 26.1848 +        PFNWGLQUERYSWAPGROUPNVPROC     wglQuerySwapGroupNV_Impl;
 26.1849 +        PFNWGLQUERYMAXSWAPGROUPSNVPROC wglQueryMaxSwapGroupsNV_Impl;
 26.1850 +        PFNWGLQUERYFRAMECOUNTNVPROC    wglQueryFrameCountNV_Impl;
 26.1851 +        PFNWGLRESETFRAMECOUNTNVPROC    wglResetFrameCountNV_Impl;
 26.1852 +
 26.1853 +        // WGL_NV_video_capture
 26.1854 +        PFNWGLBINDVIDEOCAPTUREDEVICENVPROC       wglBindVideoCaptureDeviceNV_Impl;
 26.1855 +        PFNWGLENUMERATEVIDEOCAPTUREDEVICESNVPROC wglEnumerateVideoCaptureDevicesNV_Impl;
 26.1856 +        PFNWGLLOCKVIDEOCAPTUREDEVICENVPROC       wglLockVideoCaptureDeviceNV_Impl;
 26.1857 +        PFNWGLQUERYVIDEOCAPTUREDEVICENVPROC      wglQueryVideoCaptureDeviceNV_Impl;
 26.1858 +        PFNWGLRELEASEVIDEOCAPTUREDEVICENVPROC    wglReleaseVideoCaptureDeviceNV_Impl;
 26.1859 +
 26.1860 +        // WGL_NV_copy_image
 26.1861 +        PFNWGLCOPYIMAGESUBDATANVPROC wglCopyImageSubDataNV_Impl;
 26.1862 +    
 26.1863 +        // WGL_NV_DX_interop
 26.1864 +        PFNWGLDXCLOSEDEVICENVPROC            wglDXCloseDeviceNV_Impl;
 26.1865 +        PFNWGLDXLOCKOBJECTSNVPROC            wglDXLockObjectsNV_Impl;
 26.1866 +        PFNWGLDXOBJECTACCESSNVPROC           wglDXObjectAccessNV_Impl;
 26.1867 +        PFNWGLDXOPENDEVICENVPROC             wglDXOpenDeviceNV_Impl;
 26.1868 +        PFNWGLDXREGISTEROBJECTNVPROC         wglDXRegisterObjectNV_Impl;
 26.1869 +        PFNWGLDXSETRESOURCESHAREHANDLENVPROC wglDXSetResourceShareHandleNV_Impl;
 26.1870 +        PFNWGLDXUNLOCKOBJECTSNVPROC          wglDXUnlockObjectsNV_Impl;
 26.1871 +        PFNWGLDXUNREGISTEROBJECTNVPROC       wglDXUnregisterObjectNV_Impl;
 26.1872 +
 26.1873 +      #endif // GLE_WGL_ENABLED
 26.1874 +      
 26.1875 +      #if defined(GLE_GLX_ENABLED)
 26.1876 +        // GLX_VERSION_1_1
 26.1877 +        // We don't create any pointers, because we assume these functions are always present.
 26.1878 +        
 26.1879 +        // GLX_VERSION_1_2
 26.1880 +        PFNGLXGETCURRENTDISPLAYPROC      glXGetCurrentDisplay_Impl;
 26.1881 +
 26.1882 +        // GLX_VERSION_1_3
 26.1883 +        PFNGLXCHOOSEFBCONFIGPROC         glXChooseFBConfig_Impl;
 26.1884 +        PFNGLXCREATENEWCONTEXTPROC       glXCreateNewContext_Impl;
 26.1885 +        PFNGLXCREATEPBUFFERPROC          glXCreatePbuffer_Impl;
 26.1886 +        PFNGLXCREATEPIXMAPPROC           glXCreatePixmap_Impl;
 26.1887 +        PFNGLXCREATEWINDOWPROC           glXCreateWindow_Impl;
 26.1888 +        PFNGLXDESTROYPBUFFERPROC         glXDestroyPbuffer_Impl;
 26.1889 +        PFNGLXDESTROYPIXMAPPROC          glXDestroyPixmap_Impl;
 26.1890 +        PFNGLXDESTROYWINDOWPROC          glXDestroyWindow_Impl;
 26.1891 +        PFNGLXGETCURRENTREADDRAWABLEPROC glXGetCurrentReadDrawable_Impl;
 26.1892 +        PFNGLXGETFBCONFIGATTRIBPROC      glXGetFBConfigAttrib_Impl;
 26.1893 +        PFNGLXGETFBCONFIGSPROC           glXGetFBConfigs_Impl;
 26.1894 +        PFNGLXGETSELECTEDEVENTPROC       glXGetSelectedEvent_Impl;
 26.1895 +        PFNGLXGETVISUALFROMFBCONFIGPROC  glXGetVisualFromFBConfig_Impl;
 26.1896 +        PFNGLXMAKECONTEXTCURRENTPROC     glXMakeContextCurrent_Impl;
 26.1897 +        PFNGLXQUERYCONTEXTPROC           glXQueryContext_Impl;
 26.1898 +        PFNGLXQUERYDRAWABLEPROC          glXQueryDrawable_Impl;
 26.1899 +        PFNGLXSELECTEVENTPROC            glXSelectEvent_Impl;
 26.1900 +
 26.1901 +        // GLX_VERSION_1_4
 26.1902 +        // Nothing to declare
 26.1903 +        
 26.1904 +        // GLX_ARB_create_context
 26.1905 +        PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB_Impl;
 26.1906 +
 26.1907 +        // GLX_EXT_swap_control
 26.1908 +        PFNGLXSWAPINTERVALEXTPROC glXSwapIntervalEXT_Impl;
 26.1909 +
 26.1910 +        // GLX_OML_sync_control
 26.1911 +        PFNGLXGETMSCRATEOMLPROC     glXGetMscRateOML_Impl;
 26.1912 +        PFNGLXGETSYNCVALUESOMLPROC  glXGetSyncValuesOML_Impl;
 26.1913 +        PFNGLXSWAPBUFFERSMSCOMLPROC glXSwapBuffersMscOML_Impl;
 26.1914 +        PFNGLXWAITFORMSCOMLPROC     glXWaitForMscOML_Impl;
 26.1915 +        PFNGLXWAITFORSBCOMLPROC     glXWaitForSbcOML_Impl;
 26.1916 +
 26.1917 +        // GLX_MESA_swap_control
 26.1918 +        PFNGLXGETSWAPINTERVALMESAPROC glXGetSwapIntervalMESA_Impl;
 26.1919 +        PFNGLXSWAPINTERVALMESAPROC    glXSwapIntervalMESA_Impl;
 26.1920 +
 26.1921 +      #endif // GLE_GLX_ENABLED
 26.1922 +
 26.1923 +        
 26.1924 +        // Boolean extension support indicators. Each of these identifies the
 26.1925 +        // presence or absence of the given extension. A better solution here
 26.1926 +        // might be to use an STL map<const char*, bool>.
 26.1927 +        bool gle_AMD_debug_output;
 26.1928 +      //bool gle_AMD_performance_monitor;
 26.1929 +        bool gle_APPLE_aux_depth_stencil;
 26.1930 +        bool gle_APPLE_client_storage;
 26.1931 +        bool gle_APPLE_element_array;
 26.1932 +        bool gle_APPLE_fence;
 26.1933 +        bool gle_APPLE_float_pixels;
 26.1934 +        bool gle_APPLE_flush_buffer_range;
 26.1935 +        bool gle_APPLE_object_purgeable;
 26.1936 +        bool gle_APPLE_pixel_buffer;
 26.1937 +        bool gle_APPLE_rgb_422;
 26.1938 +        bool gle_APPLE_row_bytes;
 26.1939 +        bool gle_APPLE_specular_vector;
 26.1940 +        bool gle_APPLE_texture_range;
 26.1941 +        bool gle_APPLE_transform_hint;
 26.1942 +        bool gle_APPLE_vertex_array_object;
 26.1943 +        bool gle_APPLE_vertex_array_range;
 26.1944 +        bool gle_APPLE_vertex_program_evaluators;
 26.1945 +        bool gle_APPLE_ycbcr_422;
 26.1946 +        bool gle_ARB_debug_output;
 26.1947 +        bool gle_ARB_depth_buffer_float;
 26.1948 +      //bool gle_ARB_direct_state_access;
 26.1949 +        bool gle_ARB_ES2_compatibility;
 26.1950 +        bool gle_ARB_framebuffer_object;
 26.1951 +        bool gle_ARB_framebuffer_sRGB;
 26.1952 +        bool gle_ARB_texture_multisample;
 26.1953 +        bool gle_ARB_texture_non_power_of_two;
 26.1954 +        bool gle_ARB_texture_rectangle;
 26.1955 +        bool gle_ARB_timer_query;
 26.1956 +        bool gle_ARB_vertex_array_object;
 26.1957 +      //bool gle_ARB_vertex_attrib_binding;
 26.1958 +        bool gle_EXT_draw_buffers2;
 26.1959 +        bool gle_EXT_texture_compression_s3tc;
 26.1960 +        bool gle_EXT_texture_filter_anisotropic;
 26.1961 +      //bool gle_KHR_context_flush_control;
 26.1962 +        bool gle_KHR_debug;
 26.1963 +      //bool gle_KHR_robust_buffer_access_behavior;
 26.1964 +      //bool gle_KHR_robustness;
 26.1965 +        bool gle_WIN_swap_hint;
 26.1966 +        
 26.1967 +      #if defined(GLE_WGL_ENABLED)
 26.1968 +        bool gle_WGL_ARB_buffer_region;
 26.1969 +        bool gle_WGL_ARB_create_context;
 26.1970 +        bool gle_WGL_ARB_create_context_profile;
 26.1971 +        bool gle_WGL_ARB_create_context_robustness;
 26.1972 +        bool gle_WGL_ARB_extensions_string;
 26.1973 +        bool gle_WGL_ARB_framebuffer_sRGB;
 26.1974 +        bool gle_WGL_ARB_make_current_read;
 26.1975 +        bool gle_WGL_ARB_pbuffer;
 26.1976 +        bool gle_WGL_ARB_pixel_format;
 26.1977 +        bool gle_WGL_ARB_pixel_format_float;
 26.1978 +        bool gle_WGL_ARB_render_texture;
 26.1979 +        bool gle_WGL_ATI_render_texture_rectangle;
 26.1980 +        bool gle_WGL_EXT_extensions_string;
 26.1981 +        bool gle_WGL_EXT_swap_control;
 26.1982 +        bool gle_WGL_NV_copy_image;
 26.1983 +        bool gle_WGL_NV_DX_interop;
 26.1984 +        bool gle_WGL_NV_DX_interop2;
 26.1985 +        bool gle_WGL_NV_present_video;
 26.1986 +        bool gle_WGL_NV_render_texture_rectangle;
 26.1987 +        bool gle_WGL_NV_swap_group;
 26.1988 +        bool gle_WGL_NV_video_capture;
 26.1989 +        bool gle_WGL_NV_video_output;
 26.1990 +        bool gle_WGL_OML_sync_control;
 26.1991 +      #elif defined(GLE_GLX_ENABLED)
 26.1992 +        bool gle_GLX_ARB_create_context;
 26.1993 +        bool gle_GLX_ARB_create_context_profile;
 26.1994 +		bool gle_GLX_ARB_create_context_robustness;
 26.1995 +        bool gle_GLX_EXT_swap_control;
 26.1996 +        bool gle_GLX_OML_sync_control;
 26.1997 +        bool gle_MESA_swap_control;
 26.1998 +      #endif
 26.1999 +        
 26.2000 +    }; // class GLEContext
 26.2001 +
 26.2002 +
 26.2003 +} // namespace OVR
 26.2004 +
 26.2005 +
 26.2006 +#endif // Header include guard
    27.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    27.2 +++ b/LibOVR/Src/CAPI/GL/CAPI_GLE_GL.h	Wed Jan 14 06:51:16 2015 +0200
    27.3 @@ -0,0 +1,4761 @@
    27.4 +/************************************************************************************
    27.5 +
    27.6 +Filename    :   CAPI_GLE_GL.h
    27.7 +Content     :   GL extensions declarations.
    27.8 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
    27.9 +
   27.10 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
   27.11 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
   27.12 +which is provided at the time of installation or download, or which 
   27.13 +otherwise accompanies this software in either electronic or hard copy form.
   27.14 +
   27.15 +You may obtain a copy of the License at
   27.16 +
   27.17 +http://www.oculusvr.com/licenses/LICENSE-3.2 
   27.18 +
   27.19 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
   27.20 +distributed under the License is distributed on an "AS IS" BASIS,
   27.21 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   27.22 +See the License for the specific language governing permissions and
   27.23 +limitations under the License.
   27.24 +
   27.25 +************************************************************************************/
   27.26 +
   27.27 +
   27.28 +#ifndef INC_OVR_CAPI_GLE_GL_h
   27.29 +#define INC_OVR_CAPI_GLE_GL_h
   27.30 +
   27.31 +
   27.32 +#include <stddef.h>
   27.33 +
   27.34 +
   27.35 +// Windows headers
   27.36 +//     <wingdi.h>            Windows-specific OpenGL 1.1 interfaces. Long ago this was <GL/wgl.h>.
   27.37 +//     <GL/gl.h>             OpenGL 1.1 interface.
   27.38 +//     <GL/glext.h>          OpenGL 1.2+ compatibility profile and extension interfaces. Not provided by Microsoft.
   27.39 +//     <GL/wglext.h>         Windows-specific extension interfaces. Not provided by Microsoft.
   27.40 +//     <GL/glcorearb.h>      OpenGL core profile and ARB extension interfaces. Doesn't include interfaces found only in the compatibility profile. Overlaps with gl.h and glext.h.
   27.41 +//
   27.42 +// Mac headers
   27.43 +//     <OpenGL/gl.h>         OpenGL 1.1 interface.
   27.44 +//     <OpenGL/glext.h>      OpenGL 1.2+ compatibility profile and extension interfaces.
   27.45 +//     <OpenGL/gl3.h>        Includes only interfaces supported in a core OpenGL 3.1 implementations plus a few related extensions.
   27.46 +//     <OpenGL/gl3ext.h>     Includes extensions supported in a core OpenGL 3.1 implementation.
   27.47 +//     <OpenGL/OpenGL.h>     Apple-specific OpenGL interfaces.
   27.48 +//     <OpenGL/NSOpenGL.h>   Apple-specific OpenGL interfaces.
   27.49 +//
   27.50 +// Linux headers
   27.51 +//     <GL/gl.h>             OpenGL 1.1 interface.
   27.52 +//     <GL/glext.h>          OpenGL 1.2+ compatibility profile and extension interfaces.
   27.53 +//     <GL/glx.h>            X Windows-specific OpenGL interfaces.
   27.54 +//     <GL/glxext.h>         X Windows 1.3+ API and GLX extension interfaces.
   27.55 +//     <GL/glcorearb.h>      OpenGL core profile and ARB extension interfaces. Doesn't include interfaces found only in the compatibility profile. Overlaps with gl.h and glext.h.
   27.56 +
   27.57 +#if defined(__gl_h_) || defined(__GL_H__) || defined(__X_GL_H)
   27.58 +    #error gl.h should be included after this, not before.
   27.59 +#endif
   27.60 +#if defined(__gl2_h_)
   27.61 +    #error gl2.h should be included after this, not before.
   27.62 +#endif
   27.63 +#if defined(__gltypes_h_)
   27.64 +    #error gltypes.h should be included after this, not before.
   27.65 +#endif
   27.66 +#if defined(__glext_h_) || defined(__GLEXT_H_)
   27.67 +    #error glext.h should be included after this, not before.
   27.68 +#endif
   27.69 +
   27.70 +// Prevent other GL versions from being included in the future.
   27.71 +// We do not disable Microsoft's wingdi.h and redeclare its functions. That's a big header that includes many other things.
   27.72 +// We do not currently disable Apple's OpenGL/OpenGL.h, though we could if we replicated its declarations in this header file.
   27.73 +#define __gl_h_             // Disable future #includes of Apple's <OpenGL/gl.h>
   27.74 +#define __GL_H__            // Disable future #includes of Microsoft's <GL/gl.h>
   27.75 +#define __X_GL_H            // etc.
   27.76 +#define __gl2_h_
   27.77 +#define __gltypes_h_
   27.78 +#define __glext_h_
   27.79 +#define __GLEXT_H_
   27.80 +
   27.81 +
   27.82 +// GLE platform identification
   27.83 +#if defined(_WIN32)
   27.84 +    #define GLE_WGL_ENABLED 1     // WGL interface
   27.85 +#elif defined(__ANDROID__)
   27.86 +    #define GLE_EGL_ENABLED 1     // EGL interface
   27.87 +#elif defined(__IPHONE__)
   27.88 +    #define GLE_EAGL_ENABLED 1    // EAGL interface
   27.89 +#elif defined(__APPLE__)
   27.90 +    #define GLE_CGL_ENABLED 1     // CGL interface
   27.91 +#else
   27.92 +    #define GLE_GLX_ENABLED 1     // GLX interface
   27.93 +#endif
   27.94 +
   27.95 +
   27.96 +// GLAPI / GLAPIENTRY
   27.97 +//
   27.98 +// GLAPI is a wrapper for Microsoft __declspec(dllimport).
   27.99 +// GLAPIENTRY is the calling convention (__stdcall under Microsoft).
  27.100 +//
  27.101 +#if defined(GLE_WGL_ENABLED)
  27.102 +    #if !defined(WINAPI)
  27.103 +        #ifndef WIN32_LEAN_AND_MEAN
  27.104 +            #define WIN32_LEAN_AND_MEAN 1
  27.105 +        #endif
  27.106 +        #include <windows.h>
  27.107 +        #undef WIN32_LEAN_AND_MEAN
  27.108 +    #endif
  27.109 +
  27.110 +    #ifndef WINGDIAPI // Normally defined via windows.h
  27.111 +        #define WINGDIAPI __declspec(dllimport)
  27.112 +        #define GLE_WINGDIAPI_DEFINED   // We define this so that we can know to undefine WINGDIAPI at the end of this file.
  27.113 +    #endif
  27.114 +
  27.115 +    #if !defined(GLAPI)
  27.116 +        #if defined(__MINGW32__) || defined(__CYGWIN__)
  27.117 +            #define GLAPI extern
  27.118 +        #else
  27.119 +            #define GLAPI WINGDIAPI
  27.120 +        #endif
  27.121 +    #endif
  27.122 +    #if !defined(GLAPIENTRY)
  27.123 +        #define GLAPIENTRY __stdcall
  27.124 +    #endif
  27.125 +#else
  27.126 +    #include <stdint.h>
  27.127 +
  27.128 +    #define GLAPI      extern
  27.129 +    #define GLAPIENTRY /* empty */
  27.130 +#endif
  27.131 +
  27.132 +
  27.133 +// GLE_CLASS_EXPORT 
  27.134 +// Possibly maps to Microsoft __declspec(dllexport) or nothing on other platforms.
  27.135 +#define GLE_CLASS_EXPORT // Currently defined to nothing. Could be defined to a dll export type.
  27.136 +
  27.137 +
  27.138 +
  27.139 +// GLE_HOOKING_ENABLED
  27.140 +// When enabled, we intercept all OpenGL calls and do any useful internal processing before or after the call.
  27.141 +// An example use case for this is to intercept OpenGL errors on platforms that don't support the OpenGL 
  27.142 +// debug functionality (e.g. KHR_Debug).
  27.143 +#if !defined(GLE_WGL_ENABLED) && !defined(GLE_GLX_ENABLED) && defined(OVR_BUILD_DEBUG) // Windows and Unix don't need it because they have OpenGL debug extension support (e.g. KHR_Debug).
  27.144 +    #define GLE_HOOKING_ENABLED 1
  27.145 +#endif
  27.146 +
  27.147 +// When using hooking, we map all OpenGL function usage to our member functions that end with _Hook. 
  27.148 +// These member hook functions will internally call the actual OpenGL functions after doing some internal processing.
  27.149 +#if defined(GLE_HOOKING_ENABLED)
  27.150 +    #define GLEGetCurrentFunction(x) GLEContext::GetCurrentContext()->x##_Hook
  27.151 +    #define GLEGetCurrentVariable(x) GLEContext::GetCurrentContext()->x
  27.152 +#else
  27.153 +    #define GLEGetCurrentFunction(x) GLEContext::GetCurrentContext()->x##_Impl
  27.154 +    #define GLEGetCurrentVariable(x) GLEContext::GetCurrentContext()->x
  27.155 +#endif
  27.156 +
  27.157 +// GLE_CURRENT_FUNCTION
  27.158 +// Used by hooking in debug builds.
  27.159 +#if defined(OVR_BUILD_DEBUG)
  27.160 +    #define GLE_CURRENT_FUNCTION __FUNCTION__
  27.161 +#else
  27.162 +    #define GLE_CURRENT_FUNCTION NULL
  27.163 +#endif
  27.164 +
  27.165 +
  27.166 +// GLE_WHOLE_VERSION
  27.167 +// Returns the major+minor version of the current GLEContext.
  27.168 +// Example usage:
  27.169 +//     if(GLE_WHOLE_VERSION() >= 302) // If OpenGL 3.2 or later...
  27.170 +//         ...
  27.171 +#define GLE_WHOLE_VERSION() GLEContext::GetCurrentContext()->WholeVersion()
  27.172 +
  27.173 +
  27.174 +
  27.175 +#ifdef __cplusplus
  27.176 +extern "C" {
  27.177 +#endif
  27.178 +
  27.179 +
  27.180 +// OpenGL 1.1 declarations are present in all versions of gl.h, including Microsoft's.
  27.181 +// You don't need to dynamically link to these functions on any platform and can just assume
  27.182 +// they are present. A number of these functions have been deprecated by OpenGL v3+, and
  27.183 +// if an OpenGL v3+ core profile is enabled then usage of the deprecated functions is an error.
  27.184 +
  27.185 +#ifndef GL_VERSION_1_1
  27.186 +    #define GL_VERSION_1_1 1
  27.187 +
  27.188 +    typedef unsigned int GLenum;
  27.189 +    typedef unsigned int GLbitfield;
  27.190 +    typedef unsigned int GLuint;
  27.191 +    typedef int GLint;
  27.192 +    typedef int GLsizei;
  27.193 +    typedef unsigned char GLboolean;
  27.194 +    typedef signed char GLbyte;
  27.195 +    typedef short GLshort;
  27.196 +    typedef unsigned char GLubyte;
  27.197 +    typedef unsigned short GLushort;
  27.198 +    typedef unsigned long GLulong;
  27.199 +    typedef float GLfloat;
  27.200 +    typedef float GLclampf;
  27.201 +    typedef double GLdouble;
  27.202 +    typedef double GLclampd;
  27.203 +    typedef void GLvoid;
  27.204 +    typedef int64_t GLint64EXT;
  27.205 +    typedef uint64_t GLuint64EXT;
  27.206 +    typedef GLint64EXT  GLint64;
  27.207 +    typedef GLuint64EXT GLuint64;
  27.208 +    typedef struct __GLsync *GLsync;
  27.209 +    typedef char GLchar;
  27.210 +
  27.211 +    #define GL_ZERO 0
  27.212 +    #define GL_FALSE 0
  27.213 +    #define GL_LOGIC_OP 0x0BF1
  27.214 +    #define GL_NONE 0
  27.215 +    #define GL_TEXTURE_COMPONENTS 0x1003
  27.216 +    #define GL_NO_ERROR 0
  27.217 +    #define GL_POINTS 0x0000
  27.218 +    #define GL_CURRENT_BIT 0x00000001
  27.219 +    #define GL_TRUE 1
  27.220 +    #define GL_ONE 1
  27.221 +    #define GL_CLIENT_PIXEL_STORE_BIT 0x00000001
  27.222 +    #define GL_LINES 0x0001
  27.223 +    #define GL_LINE_LOOP 0x0002
  27.224 +    #define GL_POINT_BIT 0x00000002
  27.225 +    #define GL_CLIENT_VERTEX_ARRAY_BIT 0x00000002
  27.226 +    #define GL_LINE_STRIP 0x0003
  27.227 +    #define GL_LINE_BIT 0x00000004
  27.228 +    #define GL_TRIANGLES 0x0004
  27.229 +    #define GL_TRIANGLE_STRIP 0x0005
  27.230 +    #define GL_TRIANGLE_FAN 0x0006
  27.231 +    #define GL_QUADS 0x0007
  27.232 +    #define GL_QUAD_STRIP 0x0008
  27.233 +    #define GL_POLYGON_BIT 0x00000008
  27.234 +    #define GL_POLYGON 0x0009
  27.235 +    #define GL_POLYGON_STIPPLE_BIT 0x00000010
  27.236 +    #define GL_PIXEL_MODE_BIT 0x00000020
  27.237 +    #define GL_LIGHTING_BIT 0x00000040
  27.238 +    #define GL_FOG_BIT 0x00000080
  27.239 +    #define GL_DEPTH_BUFFER_BIT 0x00000100
  27.240 +    #define GL_ACCUM 0x0100
  27.241 +    #define GL_LOAD 0x0101
  27.242 +    #define GL_RETURN 0x0102
  27.243 +    #define GL_MULT 0x0103
  27.244 +    #define GL_ADD 0x0104
  27.245 +    #define GL_NEVER 0x0200
  27.246 +    #define GL_ACCUM_BUFFER_BIT 0x00000200
  27.247 +    #define GL_LESS 0x0201
  27.248 +    #define GL_EQUAL 0x0202
  27.249 +    #define GL_LEQUAL 0x0203
  27.250 +    #define GL_GREATER 0x0204
  27.251 +    #define GL_NOTEQUAL 0x0205
  27.252 +    #define GL_GEQUAL 0x0206
  27.253 +    #define GL_ALWAYS 0x0207
  27.254 +    #define GL_SRC_COLOR 0x0300
  27.255 +    #define GL_ONE_MINUS_SRC_COLOR 0x0301
  27.256 +    #define GL_SRC_ALPHA 0x0302
  27.257 +    #define GL_ONE_MINUS_SRC_ALPHA 0x0303
  27.258 +    #define GL_DST_ALPHA 0x0304
  27.259 +    #define GL_ONE_MINUS_DST_ALPHA 0x0305
  27.260 +    #define GL_DST_COLOR 0x0306
  27.261 +    #define GL_ONE_MINUS_DST_COLOR 0x0307
  27.262 +    #define GL_SRC_ALPHA_SATURATE 0x0308
  27.263 +    #define GL_STENCIL_BUFFER_BIT 0x00000400
  27.264 +    #define GL_FRONT_LEFT 0x0400
  27.265 +    #define GL_FRONT_RIGHT 0x0401
  27.266 +    #define GL_BACK_LEFT 0x0402
  27.267 +    #define GL_BACK_RIGHT 0x0403
  27.268 +    #define GL_FRONT 0x0404
  27.269 +    #define GL_BACK 0x0405
  27.270 +    #define GL_LEFT 0x0406
  27.271 +    #define GL_RIGHT 0x0407
  27.272 +    #define GL_FRONT_AND_BACK 0x0408
  27.273 +    #define GL_AUX0 0x0409
  27.274 +    #define GL_AUX1 0x040A
  27.275 +    #define GL_AUX2 0x040B
  27.276 +    #define GL_AUX3 0x040C
  27.277 +    #define GL_INVALID_ENUM 0x0500
  27.278 +    #define GL_INVALID_VALUE 0x0501
  27.279 +    #define GL_INVALID_OPERATION 0x0502
  27.280 +    #define GL_STACK_OVERFLOW 0x0503
  27.281 +    #define GL_STACK_UNDERFLOW 0x0504
  27.282 +    #define GL_OUT_OF_MEMORY 0x0505
  27.283 +    #define GL_2D 0x0600
  27.284 +    #define GL_3D 0x0601
  27.285 +    #define GL_3D_COLOR 0x0602
  27.286 +    #define GL_3D_COLOR_TEXTURE 0x0603
  27.287 +    #define GL_4D_COLOR_TEXTURE 0x0604
  27.288 +    #define GL_PASS_THROUGH_TOKEN 0x0700
  27.289 +    #define GL_POINT_TOKEN 0x0701
  27.290 +    #define GL_LINE_TOKEN 0x0702
  27.291 +    #define GL_POLYGON_TOKEN 0x0703
  27.292 +    #define GL_BITMAP_TOKEN 0x0704
  27.293 +    #define GL_DRAW_PIXEL_TOKEN 0x0705
  27.294 +    #define GL_COPY_PIXEL_TOKEN 0x0706
  27.295 +    #define GL_LINE_RESET_TOKEN 0x0707
  27.296 +    #define GL_EXP 0x0800
  27.297 +    #define GL_VIEWPORT_BIT 0x00000800
  27.298 +    #define GL_EXP2 0x0801
  27.299 +    #define GL_CW 0x0900
  27.300 +    #define GL_CCW 0x0901
  27.301 +    #define GL_COEFF 0x0A00
  27.302 +    #define GL_ORDER 0x0A01
  27.303 +    #define GL_DOMAIN 0x0A02
  27.304 +    #define GL_CURRENT_COLOR 0x0B00
  27.305 +    #define GL_CURRENT_INDEX 0x0B01
  27.306 +    #define GL_CURRENT_NORMAL 0x0B02
  27.307 +    #define GL_CURRENT_TEXTURE_COORDS 0x0B03
  27.308 +    #define GL_CURRENT_RASTER_COLOR 0x0B04
  27.309 +    #define GL_CURRENT_RASTER_INDEX 0x0B05
  27.310 +    #define GL_CURRENT_RASTER_TEXTURE_COORDS 0x0B06
  27.311 +    #define GL_CURRENT_RASTER_POSITION 0x0B07
  27.312 +    #define GL_CURRENT_RASTER_POSITION_VALID 0x0B08
  27.313 +    #define GL_CURRENT_RASTER_DISTANCE 0x0B09
  27.314 +    #define GL_POINT_SMOOTH 0x0B10
  27.315 +    #define GL_POINT_SIZE 0x0B11
  27.316 +    #define GL_POINT_SIZE_RANGE 0x0B12
  27.317 +    #define GL_POINT_SIZE_GRANULARITY 0x0B13
  27.318 +    #define GL_LINE_SMOOTH 0x0B20
  27.319 +    #define GL_LINE_WIDTH 0x0B21
  27.320 +    #define GL_LINE_WIDTH_RANGE 0x0B22
  27.321 +    #define GL_LINE_WIDTH_GRANULARITY 0x0B23
  27.322 +    #define GL_LINE_STIPPLE 0x0B24
  27.323 +    #define GL_LINE_STIPPLE_PATTERN 0x0B25
  27.324 +    #define GL_LINE_STIPPLE_REPEAT 0x0B26
  27.325 +    #define GL_LIST_MODE 0x0B30
  27.326 +    #define GL_MAX_LIST_NESTING 0x0B31
  27.327 +    #define GL_LIST_BASE 0x0B32
  27.328 +    #define GL_LIST_INDEX 0x0B33
  27.329 +    #define GL_POLYGON_MODE 0x0B40
  27.330 +    #define GL_POLYGON_SMOOTH 0x0B41
  27.331 +    #define GL_POLYGON_STIPPLE 0x0B42
  27.332 +    #define GL_EDGE_FLAG 0x0B43
  27.333 +    #define GL_CULL_FACE 0x0B44
  27.334 +    #define GL_CULL_FACE_MODE 0x0B45
  27.335 +    #define GL_FRONT_FACE 0x0B46
  27.336 +    #define GL_LIGHTING 0x0B50
  27.337 +    #define GL_LIGHT_MODEL_LOCAL_VIEWER 0x0B51
  27.338 +    #define GL_LIGHT_MODEL_TWO_SIDE 0x0B52
  27.339 +    #define GL_LIGHT_MODEL_AMBIENT 0x0B53
  27.340 +    #define GL_SHADE_MODEL 0x0B54
  27.341 +    #define GL_COLOR_MATERIAL_FACE 0x0B55
  27.342 +    #define GL_COLOR_MATERIAL_PARAMETER 0x0B56
  27.343 +    #define GL_COLOR_MATERIAL 0x0B57
  27.344 +    #define GL_FOG 0x0B60
  27.345 +    #define GL_FOG_INDEX 0x0B61
  27.346 +    #define GL_FOG_DENSITY 0x0B62
  27.347 +    #define GL_FOG_START 0x0B63
  27.348 +    #define GL_FOG_END 0x0B64
  27.349 +    #define GL_FOG_MODE 0x0B65
  27.350 +    #define GL_FOG_COLOR 0x0B66
  27.351 +    #define GL_DEPTH_RANGE 0x0B70
  27.352 +    #define GL_DEPTH_TEST 0x0B71
  27.353 +    #define GL_DEPTH_WRITEMASK 0x0B72
  27.354 +    #define GL_DEPTH_CLEAR_VALUE 0x0B73
  27.355 +    #define GL_DEPTH_FUNC 0x0B74
  27.356 +    #define GL_ACCUM_CLEAR_VALUE 0x0B80
  27.357 +    #define GL_STENCIL_TEST 0x0B90
  27.358 +    #define GL_STENCIL_CLEAR_VALUE 0x0B91
  27.359 +    #define GL_STENCIL_FUNC 0x0B92
  27.360 +    #define GL_STENCIL_VALUE_MASK 0x0B93
  27.361 +    #define GL_STENCIL_FAIL 0x0B94
  27.362 +    #define GL_STENCIL_PASS_DEPTH_FAIL 0x0B95
  27.363 +    #define GL_STENCIL_PASS_DEPTH_PASS 0x0B96
  27.364 +    #define GL_STENCIL_REF 0x0B97
  27.365 +    #define GL_STENCIL_WRITEMASK 0x0B98
  27.366 +    #define GL_MATRIX_MODE 0x0BA0
  27.367 +    #define GL_NORMALIZE 0x0BA1
  27.368 +    #define GL_VIEWPORT 0x0BA2
  27.369 +    #define GL_MODELVIEW_STACK_DEPTH 0x0BA3
  27.370 +    #define GL_PROJECTION_STACK_DEPTH 0x0BA4
  27.371 +    #define GL_TEXTURE_STACK_DEPTH 0x0BA5
  27.372 +    #define GL_MODELVIEW_MATRIX 0x0BA6
  27.373 +    #define GL_PROJECTION_MATRIX 0x0BA7
  27.374 +    #define GL_TEXTURE_MATRIX 0x0BA8
  27.375 +    #define GL_ATTRIB_STACK_DEPTH 0x0BB0
  27.376 +    #define GL_CLIENT_ATTRIB_STACK_DEPTH 0x0BB1
  27.377 +    #define GL_ALPHA_TEST 0x0BC0
  27.378 +    #define GL_ALPHA_TEST_FUNC 0x0BC1
  27.379 +    #define GL_ALPHA_TEST_REF 0x0BC2
  27.380 +    #define GL_DITHER 0x0BD0
  27.381 +    #define GL_BLEND_DST 0x0BE0
  27.382 +    #define GL_BLEND_SRC 0x0BE1
  27.383 +    #define GL_BLEND 0x0BE2
  27.384 +    #define GL_LOGIC_OP_MODE 0x0BF0
  27.385 +    #define GL_INDEX_LOGIC_OP 0x0BF1
  27.386 +    #define GL_COLOR_LOGIC_OP 0x0BF2
  27.387 +    #define GL_AUX_BUFFERS 0x0C00
  27.388 +    #define GL_DRAW_BUFFER 0x0C01
  27.389 +    #define GL_READ_BUFFER 0x0C02
  27.390 +    #define GL_SCISSOR_BOX 0x0C10
  27.391 +    #define GL_SCISSOR_TEST 0x0C11
  27.392 +    #define GL_INDEX_CLEAR_VALUE 0x0C20
  27.393 +    #define GL_INDEX_WRITEMASK 0x0C21
  27.394 +    #define GL_COLOR_CLEAR_VALUE 0x0C22
  27.395 +    #define GL_COLOR_WRITEMASK 0x0C23
  27.396 +    #define GL_INDEX_MODE 0x0C30
  27.397 +    #define GL_RGBA_MODE 0x0C31
  27.398 +    #define GL_DOUBLEBUFFER 0x0C32
  27.399 +    #define GL_STEREO 0x0C33
  27.400 +    #define GL_RENDER_MODE 0x0C40
  27.401 +    #define GL_PERSPECTIVE_CORRECTION_HINT 0x0C50
  27.402 +    #define GL_POINT_SMOOTH_HINT 0x0C51
  27.403 +    #define GL_LINE_SMOOTH_HINT 0x0C52
  27.404 +    #define GL_POLYGON_SMOOTH_HINT 0x0C53
  27.405 +    #define GL_FOG_HINT 0x0C54
  27.406 +    #define GL_TEXTURE_GEN_S 0x0C60
  27.407 +    #define GL_TEXTURE_GEN_T 0x0C61
  27.408 +    #define GL_TEXTURE_GEN_R 0x0C62
  27.409 +    #define GL_TEXTURE_GEN_Q 0x0C63
  27.410 +    #define GL_PIXEL_MAP_I_TO_I 0x0C70
  27.411 +    #define GL_PIXEL_MAP_S_TO_S 0x0C71
  27.412 +    #define GL_PIXEL_MAP_I_TO_R 0x0C72
  27.413 +    #define GL_PIXEL_MAP_I_TO_G 0x0C73
  27.414 +    #define GL_PIXEL_MAP_I_TO_B 0x0C74
  27.415 +    #define GL_PIXEL_MAP_I_TO_A 0x0C75
  27.416 +    #define GL_PIXEL_MAP_R_TO_R 0x0C76
  27.417 +    #define GL_PIXEL_MAP_G_TO_G 0x0C77
  27.418 +    #define GL_PIXEL_MAP_B_TO_B 0x0C78
  27.419 +    #define GL_PIXEL_MAP_A_TO_A 0x0C79
  27.420 +    #define GL_PIXEL_MAP_I_TO_I_SIZE 0x0CB0
  27.421 +    #define GL_PIXEL_MAP_S_TO_S_SIZE 0x0CB1
  27.422 +    #define GL_PIXEL_MAP_I_TO_R_SIZE 0x0CB2
  27.423 +    #define GL_PIXEL_MAP_I_TO_G_SIZE 0x0CB3
  27.424 +    #define GL_PIXEL_MAP_I_TO_B_SIZE 0x0CB4
  27.425 +    #define GL_PIXEL_MAP_I_TO_A_SIZE 0x0CB5
  27.426 +    #define GL_PIXEL_MAP_R_TO_R_SIZE 0x0CB6
  27.427 +    #define GL_PIXEL_MAP_G_TO_G_SIZE 0x0CB7
  27.428 +    #define GL_PIXEL_MAP_B_TO_B_SIZE 0x0CB8
  27.429 +    #define GL_PIXEL_MAP_A_TO_A_SIZE 0x0CB9
  27.430 +    #define GL_UNPACK_SWAP_BYTES 0x0CF0
  27.431 +    #define GL_UNPACK_LSB_FIRST 0x0CF1
  27.432 +    #define GL_UNPACK_ROW_LENGTH 0x0CF2
  27.433 +    #define GL_UNPACK_SKIP_ROWS 0x0CF3
  27.434 +    #define GL_UNPACK_SKIP_PIXELS 0x0CF4
  27.435 +    #define GL_UNPACK_ALIGNMENT 0x0CF5
  27.436 +    #define GL_PACK_SWAP_BYTES 0x0D00
  27.437 +    #define GL_PACK_LSB_FIRST 0x0D01
  27.438 +    #define GL_PACK_ROW_LENGTH 0x0D02
  27.439 +    #define GL_PACK_SKIP_ROWS 0x0D03
  27.440 +    #define GL_PACK_SKIP_PIXELS 0x0D04
  27.441 +    #define GL_PACK_ALIGNMENT 0x0D05
  27.442 +    #define GL_MAP_COLOR 0x0D10
  27.443 +    #define GL_MAP_STENCIL 0x0D11
  27.444 +    #define GL_INDEX_SHIFT 0x0D12
  27.445 +    #define GL_INDEX_OFFSET 0x0D13
  27.446 +    #define GL_RED_SCALE 0x0D14
  27.447 +    #define GL_RED_BIAS 0x0D15
  27.448 +    #define GL_ZOOM_X 0x0D16
  27.449 +    #define GL_ZOOM_Y 0x0D17
  27.450 +    #define GL_GREEN_SCALE 0x0D18
  27.451 +    #define GL_GREEN_BIAS 0x0D19
  27.452 +    #define GL_BLUE_SCALE 0x0D1A
  27.453 +    #define GL_BLUE_BIAS 0x0D1B
  27.454 +    #define GL_ALPHA_SCALE 0x0D1C
  27.455 +    #define GL_ALPHA_BIAS 0x0D1D
  27.456 +    #define GL_DEPTH_SCALE 0x0D1E
  27.457 +    #define GL_DEPTH_BIAS 0x0D1F
  27.458 +    #define GL_MAX_EVAL_ORDER 0x0D30
  27.459 +    #define GL_MAX_LIGHTS 0x0D31
  27.460 +    #define GL_MAX_CLIP_PLANES 0x0D32
  27.461 +    #define GL_MAX_TEXTURE_SIZE 0x0D33
  27.462 +    #define GL_MAX_PIXEL_MAP_TABLE 0x0D34
  27.463 +    #define GL_MAX_ATTRIB_STACK_DEPTH 0x0D35
  27.464 +    #define GL_MAX_MODELVIEW_STACK_DEPTH 0x0D36
  27.465 +    #define GL_MAX_NAME_STACK_DEPTH 0x0D37
  27.466 +    #define GL_MAX_PROJECTION_STACK_DEPTH 0x0D38
  27.467 +    #define GL_MAX_TEXTURE_STACK_DEPTH 0x0D39
  27.468 +    #define GL_MAX_VIEWPORT_DIMS 0x0D3A
  27.469 +    #define GL_MAX_CLIENT_ATTRIB_STACK_DEPTH 0x0D3B
  27.470 +    #define GL_SUBPIXEL_BITS 0x0D50
  27.471 +    #define GL_INDEX_BITS 0x0D51
  27.472 +    #define GL_RED_BITS 0x0D52
  27.473 +    #define GL_GREEN_BITS 0x0D53
  27.474 +    #define GL_BLUE_BITS 0x0D54
  27.475 +    #define GL_ALPHA_BITS 0x0D55
  27.476 +    #define GL_DEPTH_BITS 0x0D56
  27.477 +    #define GL_STENCIL_BITS 0x0D57
  27.478 +    #define GL_ACCUM_RED_BITS 0x0D58
  27.479 +    #define GL_ACCUM_GREEN_BITS 0x0D59
  27.480 +    #define GL_ACCUM_BLUE_BITS 0x0D5A
  27.481 +    #define GL_ACCUM_ALPHA_BITS 0x0D5B
  27.482 +    #define GL_NAME_STACK_DEPTH 0x0D70
  27.483 +    #define GL_AUTO_NORMAL 0x0D80
  27.484 +    #define GL_MAP1_COLOR_4 0x0D90
  27.485 +    #define GL_MAP1_INDEX 0x0D91
  27.486 +    #define GL_MAP1_NORMAL 0x0D92
  27.487 +    #define GL_MAP1_TEXTURE_COORD_1 0x0D93
  27.488 +    #define GL_MAP1_TEXTURE_COORD_2 0x0D94
  27.489 +    #define GL_MAP1_TEXTURE_COORD_3 0x0D95
  27.490 +    #define GL_MAP1_TEXTURE_COORD_4 0x0D96
  27.491 +    #define GL_MAP1_VERTEX_3 0x0D97
  27.492 +    #define GL_MAP1_VERTEX_4 0x0D98
  27.493 +    #define GL_MAP2_COLOR_4 0x0DB0
  27.494 +    #define GL_MAP2_INDEX 0x0DB1
  27.495 +    #define GL_MAP2_NORMAL 0x0DB2
  27.496 +    #define GL_MAP2_TEXTURE_COORD_1 0x0DB3
  27.497 +    #define GL_MAP2_TEXTURE_COORD_2 0x0DB4
  27.498 +    #define GL_MAP2_TEXTURE_COORD_3 0x0DB5
  27.499 +    #define GL_MAP2_TEXTURE_COORD_4 0x0DB6
  27.500 +    #define GL_MAP2_VERTEX_3 0x0DB7
  27.501 +    #define GL_MAP2_VERTEX_4 0x0DB8
  27.502 +    #define GL_MAP1_GRID_DOMAIN 0x0DD0
  27.503 +    #define GL_MAP1_GRID_SEGMENTS 0x0DD1
  27.504 +    #define GL_MAP2_GRID_DOMAIN 0x0DD2
  27.505 +    #define GL_MAP2_GRID_SEGMENTS 0x0DD3
  27.506 +    #define GL_TEXTURE_1D 0x0DE0
  27.507 +    #define GL_TEXTURE_2D 0x0DE1
  27.508 +    #define GL_FEEDBACK_BUFFER_POINTER 0x0DF0
  27.509 +    #define GL_FEEDBACK_BUFFER_SIZE 0x0DF1
  27.510 +    #define GL_FEEDBACK_BUFFER_TYPE 0x0DF2
  27.511 +    #define GL_SELECTION_BUFFER_POINTER 0x0DF3
  27.512 +    #define GL_SELECTION_BUFFER_SIZE 0x0DF4
  27.513 +    #define GL_TEXTURE_WIDTH 0x1000
  27.514 +    #define GL_TRANSFORM_BIT 0x00001000
  27.515 +    #define GL_TEXTURE_HEIGHT 0x1001
  27.516 +    #define GL_TEXTURE_INTERNAL_FORMAT 0x1003
  27.517 +    #define GL_TEXTURE_BORDER_COLOR 0x1004
  27.518 +    #define GL_TEXTURE_BORDER 0x1005
  27.519 +    #define GL_DONT_CARE 0x1100
  27.520 +    #define GL_FASTEST 0x1101
  27.521 +    #define GL_NICEST 0x1102
  27.522 +    #define GL_AMBIENT 0x1200
  27.523 +    #define GL_DIFFUSE 0x1201
  27.524 +    #define GL_SPECULAR 0x1202
  27.525 +    #define GL_POSITION 0x1203
  27.526 +    #define GL_SPOT_DIRECTION 0x1204
  27.527 +    #define GL_SPOT_EXPONENT 0x1205
  27.528 +    #define GL_SPOT_CUTOFF 0x1206
  27.529 +    #define GL_CONSTANT_ATTENUATION 0x1207
  27.530 +    #define GL_LINEAR_ATTENUATION 0x1208
  27.531 +    #define GL_QUADRATIC_ATTENUATION 0x1209
  27.532 +    #define GL_COMPILE 0x1300
  27.533 +    #define GL_COMPILE_AND_EXECUTE 0x1301
  27.534 +    #define GL_BYTE 0x1400
  27.535 +    #define GL_UNSIGNED_BYTE 0x1401
  27.536 +    #define GL_SHORT 0x1402
  27.537 +    #define GL_UNSIGNED_SHORT 0x1403
  27.538 +    #define GL_INT 0x1404
  27.539 +    #define GL_UNSIGNED_INT 0x1405
  27.540 +    #define GL_FLOAT 0x1406
  27.541 +    #define GL_2_BYTES 0x1407
  27.542 +    #define GL_3_BYTES 0x1408
  27.543 +    #define GL_4_BYTES 0x1409
  27.544 +    #define GL_DOUBLE 0x140A
  27.545 +    #define GL_CLEAR 0x1500
  27.546 +    #define GL_AND 0x1501
  27.547 +    #define GL_AND_REVERSE 0x1502
  27.548 +    #define GL_COPY 0x1503
  27.549 +    #define GL_AND_INVERTED 0x1504
  27.550 +    #define GL_NOOP 0x1505
  27.551 +    #define GL_XOR 0x1506
  27.552 +    #define GL_OR 0x1507
  27.553 +    #define GL_NOR 0x1508
  27.554 +    #define GL_EQUIV 0x1509
  27.555 +    #define GL_INVERT 0x150A
  27.556 +    #define GL_OR_REVERSE 0x150B
  27.557 +    #define GL_COPY_INVERTED 0x150C
  27.558 +    #define GL_OR_INVERTED 0x150D
  27.559 +    #define GL_NAND 0x150E
  27.560 +    #define GL_SET 0x150F
  27.561 +    #define GL_EMISSION 0x1600
  27.562 +    #define GL_SHININESS 0x1601
  27.563 +    #define GL_AMBIENT_AND_DIFFUSE 0x1602
  27.564 +    #define GL_COLOR_INDEXES 0x1603
  27.565 +    #define GL_MODELVIEW 0x1700
  27.566 +    #define GL_PROJECTION 0x1701
  27.567 +    #define GL_TEXTURE 0x1702
  27.568 +    #define GL_COLOR 0x1800
  27.569 +    #define GL_DEPTH 0x1801
  27.570 +    #define GL_STENCIL 0x1802
  27.571 +    #define GL_COLOR_INDEX 0x1900
  27.572 +    #define GL_STENCIL_INDEX 0x1901
  27.573 +    #define GL_DEPTH_COMPONENT 0x1902
  27.574 +    #define GL_RED 0x1903
  27.575 +    #define GL_GREEN 0x1904
  27.576 +    #define GL_BLUE 0x1905
  27.577 +    #define GL_ALPHA 0x1906
  27.578 +    #define GL_RGB 0x1907
  27.579 +    #define GL_RGBA 0x1908
  27.580 +    #define GL_LUMINANCE 0x1909
  27.581 +    #define GL_LUMINANCE_ALPHA 0x190A
  27.582 +    #define GL_BITMAP 0x1A00
  27.583 +    #define GL_POINT 0x1B00
  27.584 +    #define GL_LINE 0x1B01
  27.585 +    #define GL_FILL 0x1B02
  27.586 +    #define GL_RENDER 0x1C00
  27.587 +    #define GL_FEEDBACK 0x1C01
  27.588 +    #define GL_SELECT 0x1C02
  27.589 +    #define GL_FLAT 0x1D00
  27.590 +    #define GL_SMOOTH 0x1D01
  27.591 +    #define GL_KEEP 0x1E00
  27.592 +    #define GL_REPLACE 0x1E01
  27.593 +    #define GL_INCR 0x1E02
  27.594 +    #define GL_DECR 0x1E03
  27.595 +    #define GL_VENDOR 0x1F00
  27.596 +    #define GL_RENDERER 0x1F01
  27.597 +    #define GL_VERSION 0x1F02
  27.598 +    #define GL_EXTENSIONS 0x1F03
  27.599 +    #define GL_S 0x2000
  27.600 +    #define GL_ENABLE_BIT 0x00002000
  27.601 +    #define GL_T 0x2001
  27.602 +    #define GL_R 0x2002
  27.603 +    #define GL_Q 0x2003
  27.604 +    #define GL_MODULATE 0x2100
  27.605 +    #define GL_DECAL 0x2101
  27.606 +    #define GL_TEXTURE_ENV_MODE 0x2200
  27.607 +    #define GL_TEXTURE_ENV_COLOR 0x2201
  27.608 +    #define GL_TEXTURE_ENV 0x2300
  27.609 +    #define GL_EYE_LINEAR 0x2400
  27.610 +    #define GL_OBJECT_LINEAR 0x2401
  27.611 +    #define GL_SPHERE_MAP 0x2402
  27.612 +    #define GL_TEXTURE_GEN_MODE 0x2500
  27.613 +    #define GL_OBJECT_PLANE 0x2501
  27.614 +    #define GL_EYE_PLANE 0x2502
  27.615 +    #define GL_NEAREST 0x2600
  27.616 +    #define GL_LINEAR 0x2601
  27.617 +    #define GL_NEAREST_MIPMAP_NEAREST 0x2700
  27.618 +    #define GL_LINEAR_MIPMAP_NEAREST 0x2701
  27.619 +    #define GL_NEAREST_MIPMAP_LINEAR 0x2702
  27.620 +    #define GL_LINEAR_MIPMAP_LINEAR 0x2703
  27.621 +    #define GL_TEXTURE_MAG_FILTER 0x2800
  27.622 +    #define GL_TEXTURE_MIN_FILTER 0x2801
  27.623 +    #define GL_TEXTURE_WRAP_S 0x2802
  27.624 +    #define GL_TEXTURE_WRAP_T 0x2803
  27.625 +    #define GL_CLAMP 0x2900
  27.626 +    #define GL_REPEAT 0x2901
  27.627 +    #define GL_POLYGON_OFFSET_UNITS 0x2A00
  27.628 +    #define GL_POLYGON_OFFSET_POINT 0x2A01
  27.629 +    #define GL_POLYGON_OFFSET_LINE 0x2A02
  27.630 +    #define GL_R3_G3_B2 0x2A10
  27.631 +    #define GL_V2F 0x2A20
  27.632 +    #define GL_V3F 0x2A21
  27.633 +    #define GL_C4UB_V2F 0x2A22
  27.634 +    #define GL_C4UB_V3F 0x2A23
  27.635 +    #define GL_C3F_V3F 0x2A24
  27.636 +    #define GL_N3F_V3F 0x2A25
  27.637 +    #define GL_C4F_N3F_V3F 0x2A26
  27.638 +    #define GL_T2F_V3F 0x2A27
  27.639 +    #define GL_T4F_V4F 0x2A28
  27.640 +    #define GL_T2F_C4UB_V3F 0x2A29
  27.641 +    #define GL_T2F_C3F_V3F 0x2A2A
  27.642 +    #define GL_T2F_N3F_V3F 0x2A2B
  27.643 +    #define GL_T2F_C4F_N3F_V3F 0x2A2C
  27.644 +    #define GL_T4F_C4F_N3F_V4F 0x2A2D
  27.645 +    #define GL_CLIP_PLANE0 0x3000
  27.646 +    #define GL_CLIP_PLANE1 0x3001
  27.647 +    #define GL_CLIP_PLANE2 0x3002
  27.648 +    #define GL_CLIP_PLANE3 0x3003
  27.649 +    #define GL_CLIP_PLANE4 0x3004
  27.650 +    #define GL_CLIP_PLANE5 0x3005
  27.651 +    #define GL_LIGHT0 0x4000
  27.652 +    #define GL_COLOR_BUFFER_BIT 0x00004000
  27.653 +    #define GL_LIGHT1 0x4001
  27.654 +    #define GL_LIGHT2 0x4002
  27.655 +    #define GL_LIGHT3 0x4003
  27.656 +    #define GL_LIGHT4 0x4004
  27.657 +    #define GL_LIGHT5 0x4005
  27.658 +    #define GL_LIGHT6 0x4006
  27.659 +    #define GL_LIGHT7 0x4007
  27.660 +    #define GL_HINT_BIT 0x00008000
  27.661 +    #define GL_POLYGON_OFFSET_FILL 0x8037
  27.662 +    #define GL_POLYGON_OFFSET_FACTOR 0x8038
  27.663 +    #define GL_ALPHA4 0x803B
  27.664 +    #define GL_ALPHA8 0x803C
  27.665 +    #define GL_ALPHA12 0x803D
  27.666 +    #define GL_ALPHA16 0x803E
  27.667 +    #define GL_LUMINANCE4 0x803F
  27.668 +    #define GL_LUMINANCE8 0x8040
  27.669 +    #define GL_LUMINANCE12 0x8041
  27.670 +    #define GL_LUMINANCE16 0x8042
  27.671 +    #define GL_LUMINANCE4_ALPHA4 0x8043
  27.672 +    #define GL_LUMINANCE6_ALPHA2 0x8044
  27.673 +    #define GL_LUMINANCE8_ALPHA8 0x8045
  27.674 +    #define GL_LUMINANCE12_ALPHA4 0x8046
  27.675 +    #define GL_LUMINANCE12_ALPHA12 0x8047
  27.676 +    #define GL_LUMINANCE16_ALPHA16 0x8048
  27.677 +    #define GL_INTENSITY 0x8049
  27.678 +    #define GL_INTENSITY4 0x804A
  27.679 +    #define GL_INTENSITY8 0x804B
  27.680 +    #define GL_INTENSITY12 0x804C
  27.681 +    #define GL_INTENSITY16 0x804D
  27.682 +    #define GL_RGB4 0x804F
  27.683 +    #define GL_RGB5 0x8050
  27.684 +    #define GL_RGB8 0x8051
  27.685 +    #define GL_RGB10 0x8052
  27.686 +    #define GL_RGB12 0x8053
  27.687 +    #define GL_RGB16 0x8054
  27.688 +    #define GL_RGBA2 0x8055
  27.689 +    #define GL_RGBA4 0x8056
  27.690 +    #define GL_RGB5_A1 0x8057
  27.691 +    #define GL_RGBA8 0x8058
  27.692 +    #define GL_RGB10_A2 0x8059
  27.693 +    #define GL_RGBA12 0x805A
  27.694 +    #define GL_RGBA16 0x805B
  27.695 +    #define GL_TEXTURE_RED_SIZE 0x805C
  27.696 +    #define GL_TEXTURE_GREEN_SIZE 0x805D
  27.697 +    #define GL_TEXTURE_BLUE_SIZE 0x805E
  27.698 +    #define GL_TEXTURE_ALPHA_SIZE 0x805F
  27.699 +    #define GL_TEXTURE_LUMINANCE_SIZE 0x8060
  27.700 +    #define GL_TEXTURE_INTENSITY_SIZE 0x8061
  27.701 +    #define GL_PROXY_TEXTURE_1D 0x8063
  27.702 +    #define GL_PROXY_TEXTURE_2D 0x8064
  27.703 +    #define GL_TEXTURE_PRIORITY 0x8066
  27.704 +    #define GL_TEXTURE_RESIDENT 0x8067
  27.705 +    #define GL_TEXTURE_BINDING_1D 0x8068
  27.706 +    #define GL_TEXTURE_BINDING_2D 0x8069
  27.707 +    #define GL_VERTEX_ARRAY 0x8074
  27.708 +    #define GL_NORMAL_ARRAY 0x8075
  27.709 +    #define GL_COLOR_ARRAY 0x8076
  27.710 +    #define GL_INDEX_ARRAY 0x8077
  27.711 +    #define GL_TEXTURE_COORD_ARRAY 0x8078
  27.712 +    #define GL_EDGE_FLAG_ARRAY 0x8079
  27.713 +    #define GL_VERTEX_ARRAY_SIZE 0x807A
  27.714 +    #define GL_VERTEX_ARRAY_TYPE 0x807B
  27.715 +    #define GL_VERTEX_ARRAY_STRIDE 0x807C
  27.716 +    #define GL_NORMAL_ARRAY_TYPE 0x807E
  27.717 +    #define GL_NORMAL_ARRAY_STRIDE 0x807F
  27.718 +    #define GL_COLOR_ARRAY_SIZE 0x8081
  27.719 +    #define GL_COLOR_ARRAY_TYPE 0x8082
  27.720 +    #define GL_COLOR_ARRAY_STRIDE 0x8083
  27.721 +    #define GL_INDEX_ARRAY_TYPE 0x8085
  27.722 +    #define GL_INDEX_ARRAY_STRIDE 0x8086
  27.723 +    #define GL_TEXTURE_COORD_ARRAY_SIZE 0x8088
  27.724 +    #define GL_TEXTURE_COORD_ARRAY_TYPE 0x8089
  27.725 +    #define GL_TEXTURE_COORD_ARRAY_STRIDE 0x808A
  27.726 +    #define GL_EDGE_FLAG_ARRAY_STRIDE 0x808C
  27.727 +    #define GL_VERTEX_ARRAY_POINTER 0x808E
  27.728 +    #define GL_NORMAL_ARRAY_POINTER 0x808F
  27.729 +    #define GL_COLOR_ARRAY_POINTER 0x8090
  27.730 +    #define GL_INDEX_ARRAY_POINTER 0x8091
  27.731 +    #define GL_TEXTURE_COORD_ARRAY_POINTER 0x8092
  27.732 +    #define GL_EDGE_FLAG_ARRAY_POINTER 0x8093
  27.733 +    #define GL_COLOR_INDEX1_EXT 0x80E2
  27.734 +    #define GL_COLOR_INDEX2_EXT 0x80E3
  27.735 +    #define GL_COLOR_INDEX4_EXT 0x80E4
  27.736 +    #define GL_COLOR_INDEX8_EXT 0x80E5
  27.737 +    #define GL_COLOR_INDEX12_EXT 0x80E6
  27.738 +    #define GL_COLOR_INDEX16_EXT 0x80E7
  27.739 +    #define GL_EVAL_BIT 0x00010000
  27.740 +    #define GL_LIST_BIT 0x00020000
  27.741 +    #define GL_TEXTURE_BIT 0x00040000
  27.742 +    #define GL_SCISSOR_BIT 0x00080000
  27.743 +    #define GL_ALL_ATTRIB_BITS 0x000fffff
  27.744 +    #define GL_CLIENT_ALL_ATTRIB_BITS 0xffffffff
  27.745 +
  27.746 +    #if defined(GLE_HOOKING_ENABLED)
  27.747 +        // In this case we map these functions to internal versions instead of the standard versions.
  27.748 +        #define glAccum(...)                   GLEGetCurrentFunction(glAccum)(__VA_ARGS__)
  27.749 +        #define glAlphaFunc(...)               GLEGetCurrentFunction(glAlphaFunc)(__VA_ARGS__)
  27.750 +        #define glAreTexturesResident(...)     GLEGetCurrentFunction(glAreTexturesResident)(__VA_ARGS__)
  27.751 +        #define glArrayElement(...)            GLEGetCurrentFunction(glArrayElement)(__VA_ARGS__)
  27.752 +        #define glBegin(...)                   GLEGetCurrentFunction(glBegin)(__VA_ARGS__)
  27.753 +        #define glBindTexture(...)             GLEGetCurrentFunction(glBindTexture)(__VA_ARGS__)
  27.754 +        #define glBitmap(...)                  GLEGetCurrentFunction(glBitmap)(__VA_ARGS__)
  27.755 +        #define glBlendFunc(...)               GLEGetCurrentFunction(glBlendFunc)(__VA_ARGS__)
  27.756 +        #define glCallList(...)                GLEGetCurrentFunction(glCallList)(__VA_ARGS__)
  27.757 +        #define glCallLists(...)               GLEGetCurrentFunction(glCallLists)(__VA_ARGS__)
  27.758 +        #define glClear(...)                   GLEGetCurrentFunction(glClear)(__VA_ARGS__)
  27.759 +        #define glClearAccum(...)              GLEGetCurrentFunction(glClearAccum)(__VA_ARGS__)
  27.760 +        #define glClearColor(...)              GLEGetCurrentFunction(glClearColor)(__VA_ARGS__)
  27.761 +        #define glClearDepth(...)              GLEGetCurrentFunction(glClearDepth)(__VA_ARGS__)
  27.762 +        #define glClearIndex(...)              GLEGetCurrentFunction(glClearIndex)(__VA_ARGS__)
  27.763 +        #define glClearStencil(...)            GLEGetCurrentFunction(glClearStencil)(__VA_ARGS__)
  27.764 +        #define glClipPlane(...)               GLEGetCurrentFunction(glClipPlane)(__VA_ARGS__)
  27.765 +        #define glColor3b(...)                 GLEGetCurrentFunction(glColor3b)(__VA_ARGS__)
  27.766 +        #define glColor3bv(...)                GLEGetCurrentFunction(glColor3bv)(__VA_ARGS__)
  27.767 +        #define glColor3d(...)                 GLEGetCurrentFunction(glColor3d)(__VA_ARGS__)
  27.768 +        #define glColor3dv(...)                GLEGetCurrentFunction(glColor3dv)(__VA_ARGS__)
  27.769 +        #define glColor3f(...)                 GLEGetCurrentFunction(glColor3f)(__VA_ARGS__)
  27.770 +        #define glColor3fv(...)                GLEGetCurrentFunction(glColor3fv)(__VA_ARGS__)
  27.771 +        #define glColor3i(...)                 GLEGetCurrentFunction(glColor3i)(__VA_ARGS__)
  27.772 +        #define glColor3iv(...)                GLEGetCurrentFunction(glColor3iv)(__VA_ARGS__)
  27.773 +        #define glColor3s(...)                 GLEGetCurrentFunction(glColor3s)(__VA_ARGS__)
  27.774 +        #define glColor3sv(...)                GLEGetCurrentFunction(glColor3sv)(__VA_ARGS__)
  27.775 +        #define glColor3ub(...)                GLEGetCurrentFunction(glColor3ub)(__VA_ARGS__)
  27.776 +        #define glColor3ubv(...)               GLEGetCurrentFunction(glColor3ubv)(__VA_ARGS__)
  27.777 +        #define glColor3ui(...)                GLEGetCurrentFunction(glColor3ui)(__VA_ARGS__)
  27.778 +        #define glColor3uiv(...)               GLEGetCurrentFunction(glColor3uiv)(__VA_ARGS__)
  27.779 +        #define glColor3us(...)                GLEGetCurrentFunction(glColor3us)(__VA_ARGS__)
  27.780 +        #define glColor3usv(...)               GLEGetCurrentFunction(glColor3usv)(__VA_ARGS__)
  27.781 +        #define glColor4b(...)                 GLEGetCurrentFunction(glColor4b)(__VA_ARGS__)
  27.782 +        #define glColor4bv(...)                GLEGetCurrentFunction(glColor4bv)(__VA_ARGS__)
  27.783 +        #define glColor4d(...)                 GLEGetCurrentFunction(glColor4d)(__VA_ARGS__)
  27.784 +        #define glColor4dv(...)                GLEGetCurrentFunction(glColor4dv)(__VA_ARGS__)
  27.785 +        #define glColor4f(...)                 GLEGetCurrentFunction(glColor4f)(__VA_ARGS__)
  27.786 +        #define glColor4fv(...)                GLEGetCurrentFunction(glColor4fv)(__VA_ARGS__)
  27.787 +        #define glColor4i(...)                 GLEGetCurrentFunction(glColor4i)(__VA_ARGS__)
  27.788 +        #define glColor4iv(...)                GLEGetCurrentFunction(glColor4iv)(__VA_ARGS__)
  27.789 +        #define glColor4s(...)                 GLEGetCurrentFunction(glColor4s)(__VA_ARGS__)
  27.790 +        #define glColor4sv(...)                GLEGetCurrentFunction(glColor4sv)(__VA_ARGS__)
  27.791 +        #define glColor4ub(...)                GLEGetCurrentFunction(glColor4ub)(__VA_ARGS__)
  27.792 +        #define glColor4ubv(...)               GLEGetCurrentFunction(glColor4ubv)(__VA_ARGS__)
  27.793 +        #define glColor4ui(...)                GLEGetCurrentFunction(glColor4ui)(__VA_ARGS__)
  27.794 +        #define glColor4uiv(...)               GLEGetCurrentFunction(glColor4uiv)(__VA_ARGS__)
  27.795 +        #define glColor4us(...)                GLEGetCurrentFunction(glColor4us)(__VA_ARGS__)
  27.796 +        #define glColor4usv(...)               GLEGetCurrentFunction(glColor4usv)(__VA_ARGS__)
  27.797 +        #define glColorMask(...)               GLEGetCurrentFunction(glColorMask)(__VA_ARGS__)
  27.798 +        #define glColorMaterial(...)           GLEGetCurrentFunction(glColorMaterial)(__VA_ARGS__)
  27.799 +        #define glColorPointer(...)            GLEGetCurrentFunction(glColorPointer)(__VA_ARGS__)
  27.800 +        #define glCopyPixels(...)              GLEGetCurrentFunction(glCopyPixels)(__VA_ARGS__)
  27.801 +        #define glCopyTexImage1D(...)          GLEGetCurrentFunction(glCopyTexImage1D)(__VA_ARGS__)
  27.802 +        #define glCopyTexImage2D(...)          GLEGetCurrentFunction(glCopyTexImage2D)(__VA_ARGS__)
  27.803 +        #define glCopyTexSubImage1D(...)       GLEGetCurrentFunction(glCopyTexSubImage1D)(__VA_ARGS__)
  27.804 +        #define glCopyTexSubImage2D(...)       GLEGetCurrentFunction(glCopyTexSubImage2D)(__VA_ARGS__)
  27.805 +        #define glCullFace(...)                GLEGetCurrentFunction(glCullFace)(__VA_ARGS__)
  27.806 +        #define glDeleteLists(...)             GLEGetCurrentFunction(glDeleteLists)(__VA_ARGS__)
  27.807 +        #define glDeleteTextures(...)          GLEGetCurrentFunction(glDeleteTextures)(__VA_ARGS__)
  27.808 +        #define glDepthFunc(...)               GLEGetCurrentFunction(glDepthFunc)(__VA_ARGS__)
  27.809 +        #define glDepthMask(...)               GLEGetCurrentFunction(glDepthMask)(__VA_ARGS__)
  27.810 +        #define glDepthRange(...)              GLEGetCurrentFunction(glDepthRange)(__VA_ARGS__)
  27.811 +        #define glDisable(...)                 GLEGetCurrentFunction(glDisable)(__VA_ARGS__)
  27.812 +        #define glDisableClientState(...)      GLEGetCurrentFunction(glDisableClientState)(__VA_ARGS__)
  27.813 +        #define glDrawArrays(...)              GLEGetCurrentFunction(glDrawArrays)(__VA_ARGS__)
  27.814 +        #define glDrawBuffer(...)              GLEGetCurrentFunction(glDrawBuffer)(__VA_ARGS__)
  27.815 +        #define glDrawElements(...)            GLEGetCurrentFunction(glDrawElements)(__VA_ARGS__)
  27.816 +        #define glDrawPixels(...)              GLEGetCurrentFunction(glDrawPixels)(__VA_ARGS__)
  27.817 +        #define glEdgeFlag(...)                GLEGetCurrentFunction(glEdgeFlag)(__VA_ARGS__)
  27.818 +        #define glEdgeFlagPointer(...)         GLEGetCurrentFunction(glEdgeFlagPointer)(__VA_ARGS__)
  27.819 +        #define glEdgeFlagv(...)               GLEGetCurrentFunction(glEdgeFlagv)(__VA_ARGS__)
  27.820 +        #define glEnable(...)                  GLEGetCurrentFunction(glEnable)(__VA_ARGS__)
  27.821 +        #define glEnableClientState(...)       GLEGetCurrentFunction(glEnableClientState)(__VA_ARGS__)
  27.822 +        #define glEnd()                        GLEGetCurrentFunction(glEnd)()
  27.823 +        #define glEndList()                    GLEGetCurrentFunction(glEndList)(_)
  27.824 +        #define glEvalCoord1d(...)             GLEGetCurrentFunction(glEvalCoord1d)(__VA_ARGS__)
  27.825 +        #define glEvalCoord1dv(...)            GLEGetCurrentFunction(glEvalCoord1dv)(__VA_ARGS__)
  27.826 +        #define glEvalCoord1f(...)             GLEGetCurrentFunction(glEvalCoord1f)(__VA_ARGS__)
  27.827 +        #define glEvalCoord1fv(...)            GLEGetCurrentFunction(glEvalCoord1fv)(__VA_ARGS__)
  27.828 +        #define glEvalCoord2d(...)             GLEGetCurrentFunction(glEvalCoord2d)(__VA_ARGS__)
  27.829 +        #define glEvalCoord2dv(...)            GLEGetCurrentFunction(glEvalCoord2dv)(__VA_ARGS__)
  27.830 +        #define glEvalCoord2f(...)             GLEGetCurrentFunction(glEvalCoord2f)(__VA_ARGS__)
  27.831 +        #define glEvalCoord2fv(...)            GLEGetCurrentFunction(glEvalCoord2fv)(__VA_ARGS__)
  27.832 +        #define glEvalMesh1(...)               GLEGetCurrentFunction(glEvalMesh1)(__VA_ARGS__)
  27.833 +        #define glEvalMesh2(...)               GLEGetCurrentFunction(glEvalMesh2)(__VA_ARGS__)
  27.834 +        #define glEvalPoint1(...)              GLEGetCurrentFunction(glEvalPoint1)(__VA_ARGS__)
  27.835 +        #define glEvalPoint2(...)              GLEGetCurrentFunction(glEvalPoint2)(__VA_ARGS__)
  27.836 +        #define glFeedbackBuffer(...)          GLEGetCurrentFunction(glFeedbackBuffer)(__VA_ARGS__)
  27.837 +        #define glFinish()                     GLEGetCurrentFunction(glFinish)()
  27.838 +        #define glFlush()                      GLEGetCurrentFunction(glFlush)()
  27.839 +        #define glFogf(...)                    GLEGetCurrentFunction(glFogf)(__VA_ARGS__)
  27.840 +        #define glFogfv(...)                   GLEGetCurrentFunction(glFogfv)(__VA_ARGS__)
  27.841 +        #define glFogi(...)                    GLEGetCurrentFunction(glFogi)(__VA_ARGS__)
  27.842 +        #define glFogiv(...)                   GLEGetCurrentFunction(glFogiv)(__VA_ARGS__)
  27.843 +        #define glFrontFace(...)               GLEGetCurrentFunction(glFrontFace)(__VA_ARGS__)
  27.844 +        #define glFrustum(...)                 GLEGetCurrentFunction(glFrustum)(__VA_ARGS__)
  27.845 +        #define glGenLists(...)                GLEGetCurrentFunction(glGenLists)(__VA_ARGS__)
  27.846 +        #define glGenTextures(...)             GLEGetCurrentFunction(glGenTextures)(__VA_ARGS__)
  27.847 +        #define glGetBooleanv(...)             GLEGetCurrentFunction(glGetBooleanv)(__VA_ARGS__)
  27.848 +        #define glGetClipPlane(...)            GLEGetCurrentFunction(glGetClipPlane)(__VA_ARGS__)
  27.849 +        #define glGetDoublev(...)              GLEGetCurrentFunction(glGetDoublev)(__VA_ARGS__)
  27.850 +        #define glGetError()                   GLEGetCurrentFunction(glGetError)()
  27.851 +        #define glGetFloatv(...)               GLEGetCurrentFunction(glGetFloatv)(__VA_ARGS__)
  27.852 +        #define glGetIntegerv(...)             GLEGetCurrentFunction(glGetIntegerv)(__VA_ARGS__)
  27.853 +        #define glGetLightfv(...)              GLEGetCurrentFunction(glGetLightfv)(__VA_ARGS__)
  27.854 +        #define glGetLightiv(...)              GLEGetCurrentFunction(glGetLightiv)(__VA_ARGS__)
  27.855 +        #define glGetMapdv(...)                GLEGetCurrentFunction(glGetMapdv)(__VA_ARGS__)
  27.856 +        #define glGetMapfv(...)                GLEGetCurrentFunction(glGetMapfv)(__VA_ARGS__)
  27.857 +        #define glGetMapiv(...)                GLEGetCurrentFunction(glGetMapiv)(__VA_ARGS__)
  27.858 +        #define glGetMaterialfv(...)           GLEGetCurrentFunction(glGetMaterialfv)(__VA_ARGS__)
  27.859 +        #define glGetMaterialiv(...)           GLEGetCurrentFunction(glGetMaterialiv)(__VA_ARGS__)
  27.860 +        #define glGetPixelMapfv(...)           GLEGetCurrentFunction(glGetPixelMapfv)(__VA_ARGS__)
  27.861 +        #define glGetPixelMapuiv(...)          GLEGetCurrentFunction(glGetPixelMapuiv)(__VA_ARGS__)
  27.862 +        #define glGetPixelMapusv(...)          GLEGetCurrentFunction(glGetPixelMapusv)(__VA_ARGS__)
  27.863 +        #define glGetPointerv(...)             GLEGetCurrentFunction(glGetPointerv)(__VA_ARGS__)
  27.864 +        #define glGetPolygonStipple(...)       GLEGetCurrentFunction(glGetPolygonStipple)(__VA_ARGS__)
  27.865 +        #define glGetString(...)               GLEGetCurrentFunction(glGetString)(__VA_ARGS__)
  27.866 +        #define glGetTexEnvfv(...)             GLEGetCurrentFunction(glGetTexEnvfv)(__VA_ARGS__)
  27.867 +        #define glGetTexEnviv(...)             GLEGetCurrentFunction(glGetTexEnviv)(__VA_ARGS__)
  27.868 +        #define glGetTexGendv(...)             GLEGetCurrentFunction(glGetTexGendv)(__VA_ARGS__)
  27.869 +        #define glGetTexGenfv(...)             GLEGetCurrentFunction(glGetTexGenfv)(__VA_ARGS__)
  27.870 +        #define glGetTexGeniv(...)             GLEGetCurrentFunction(glGetTexGeniv)(__VA_ARGS__)
  27.871 +        #define glGetTexImage(...)             GLEGetCurrentFunction(glGetTexImage)(__VA_ARGS__)
  27.872 +        #define glGetTexLevelParameterfv(...)  GLEGetCurrentFunction(glGetTexLevelParameterfv)(__VA_ARGS__)
  27.873 +        #define glGetTexLevelParameteriv(...)  GLEGetCurrentFunction(glGetTexLevelParameteriv)(__VA_ARGS__)
  27.874 +        #define glGetTexParameterfv(...)       GLEGetCurrentFunction(glGetTexParameterfv)(__VA_ARGS__)
  27.875 +        #define glGetTexParameteriv(...)       GLEGetCurrentFunction(glGetTexParameteriv)(__VA_ARGS__)
  27.876 +        #define glHint(...)                    GLEGetCurrentFunction(glHint)(__VA_ARGS__)
  27.877 +        #define glIndexMask(...)               GLEGetCurrentFunction(glIndexMask)(__VA_ARGS__)
  27.878 +        #define glIndexPointer(...)            GLEGetCurrentFunction(glIndexPointer)(__VA_ARGS__)
  27.879 +        #define glIndexd(...)                  GLEGetCurrentFunction(glIndexd)(__VA_ARGS__)
  27.880 +        #define glIndexdv(...)                 GLEGetCurrentFunction(glIndexdv)(__VA_ARGS__)
  27.881 +        #define glIndexf(...)                  GLEGetCurrentFunction(glIndexf)(__VA_ARGS__)
  27.882 +        #define glIndexfv(...)                 GLEGetCurrentFunction(glIndexfv)(__VA_ARGS__)
  27.883 +        #define glIndexi(...)                  GLEGetCurrentFunction(glIndexi)(__VA_ARGS__)
  27.884 +        #define glIndexiv(...)                 GLEGetCurrentFunction(glIndexiv)(__VA_ARGS__)
  27.885 +        #define glIndexs(...)                  GLEGetCurrentFunction(glIndexs)(__VA_ARGS__)
  27.886 +        #define glIndexsv(...)                 GLEGetCurrentFunction(glIndexsv)(__VA_ARGS__)
  27.887 +        #define glIndexub(...)                 GLEGetCurrentFunction(glIndexub)(__VA_ARGS__)
  27.888 +        #define glIndexubv(...)                GLEGetCurrentFunction(glIndexubv)(__VA_ARGS__)
  27.889 +        #define glInitNames()                  GLEGetCurrentFunction(glInitNames)()
  27.890 +        #define glInterleavedArrays(...)       GLEGetCurrentFunction(glInterleavedArrays)(__VA_ARGS__)
  27.891 +        #define glIsEnabled(...)               GLEGetCurrentFunction(glIsEnabled)(__VA_ARGS__)
  27.892 +        #define glIsList(...)                  GLEGetCurrentFunction(glIsList)(__VA_ARGS__)
  27.893 +        #define glIsTexture(...)               GLEGetCurrentFunction(glIsTexture)(__VA_ARGS__)
  27.894 +        #define glLightModelf(...)             GLEGetCurrentFunction(glLightModelf)(__VA_ARGS__)
  27.895 +        #define glLightModelfv(...)            GLEGetCurrentFunction(glLightModelfv)(__VA_ARGS__)
  27.896 +        #define glLightModeli(...)             GLEGetCurrentFunction(glLightModeli)(__VA_ARGS__)
  27.897 +        #define glLightModeliv(...)            GLEGetCurrentFunction(glLightModeliv)(__VA_ARGS__)
  27.898 +        #define glLightf(...)                  GLEGetCurrentFunction(glLightf)(__VA_ARGS__)
  27.899 +        #define glLightfv(...)                 GLEGetCurrentFunction(glLightfv)(__VA_ARGS__)
  27.900 +        #define glLighti(...)                  GLEGetCurrentFunction(glLighti)(__VA_ARGS__)
  27.901 +        #define glLightiv(...)                 GLEGetCurrentFunction(glLightiv)(__VA_ARGS__)
  27.902 +        #define glLineStipple(...)             GLEGetCurrentFunction(glLineStipple)(__VA_ARGS__)
  27.903 +        #define glLineWidth(...)               GLEGetCurrentFunction(glLineWidth)(__VA_ARGS__)
  27.904 +        #define glListBase(...)                GLEGetCurrentFunction(glListBase)(__VA_ARGS__)
  27.905 +        #define glLoadIdentity()               GLEGetCurrentFunction(glLoadIdentity)()
  27.906 +        #define glLoadMatrixd(...)             GLEGetCurrentFunction(glLoadMatrixd)(__VA_ARGS__)
  27.907 +        #define glLoadMatrixf(...)             GLEGetCurrentFunction(glLoadMatrixf)(__VA_ARGS__)
  27.908 +        #define glLoadName(...)                GLEGetCurrentFunction(glLoadName)(__VA_ARGS__)
  27.909 +        #define glLogicOp(...)                 GLEGetCurrentFunction(glLogicOp)(__VA_ARGS__)
  27.910 +        #define glMap1d(...)                   GLEGetCurrentFunction(glMap1d)(__VA_ARGS__)
  27.911 +        #define glMap1f(...)                   GLEGetCurrentFunction(glMap1f)(__VA_ARGS__)
  27.912 +        #define glMap2d(...)                   GLEGetCurrentFunction(glMap2d)(__VA_ARGS__)
  27.913 +        #define glMap2f(...)                   GLEGetCurrentFunction(glMap2f)(__VA_ARGS__)
  27.914 +        #define glMapGrid1d(...)               GLEGetCurrentFunction(glMapGrid1d)(__VA_ARGS__)
  27.915 +        #define glMapGrid1f(...)               GLEGetCurrentFunction(glMapGrid1f)(__VA_ARGS__)
  27.916 +        #define glMapGrid2d(...)               GLEGetCurrentFunction(glMapGrid2d)(__VA_ARGS__)
  27.917 +        #define glMapGrid2f(...)               GLEGetCurrentFunction(glMapGrid2f)(__VA_ARGS__)
  27.918 +        #define glMaterialf(...)               GLEGetCurrentFunction(glMaterialf)(__VA_ARGS__)
  27.919 +        #define glMaterialfv(...)              GLEGetCurrentFunction(glMaterialfv)(__VA_ARGS__)
  27.920 +        #define glMateriali(...)               GLEGetCurrentFunction(glMateriali)(__VA_ARGS__)
  27.921 +        #define glMaterialiv(...)              GLEGetCurrentFunction(glMaterialiv)(__VA_ARGS__)
  27.922 +        #define glMatrixMode(...)              GLEGetCurrentFunction(glMatrixMode)(__VA_ARGS__)
  27.923 +        #define glMultMatrixd(...)             GLEGetCurrentFunction(glMultMatrixd)(__VA_ARGS__)
  27.924 +        #define glMultMatrixf(...)             GLEGetCurrentFunction(glMultMatrixf)(__VA_ARGS__)
  27.925 +        #define glNewList(...)                 GLEGetCurrentFunction(glNewList)(__VA_ARGS__)
  27.926 +        #define glNormal3b(...)                GLEGetCurrentFunction(glNormal3b)(__VA_ARGS__)
  27.927 +        #define glNormal3bv(...)               GLEGetCurrentFunction(glNormal3bv)(__VA_ARGS__)
  27.928 +        #define glNormal3d(...)                GLEGetCurrentFunction(glNormal3d)(__VA_ARGS__)
  27.929 +        #define glNormal3dv(...)               GLEGetCurrentFunction(glNormal3dv)(__VA_ARGS__)
  27.930 +        #define glNormal3f(...)                GLEGetCurrentFunction(glNormal3f)(__VA_ARGS__)
  27.931 +        #define glNormal3fv(...)               GLEGetCurrentFunction(glNormal3fv)(__VA_ARGS__)
  27.932 +        #define glNormal3i(...)                GLEGetCurrentFunction(glNormal3i)(__VA_ARGS__)
  27.933 +        #define glNormal3iv(...)               GLEGetCurrentFunction(glNormal3iv)(__VA_ARGS__)
  27.934 +        #define glNormal3s(...)                GLEGetCurrentFunction(glNormal3s)(__VA_ARGS__)
  27.935 +        #define glNormal3sv(...)               GLEGetCurrentFunction(glNormal3sv)(__VA_ARGS__)
  27.936 +        #define glNormalPointer(...)           GLEGetCurrentFunction(glNormalPointer)(__VA_ARGS__)
  27.937 +        #define glOrtho(...)                   GLEGetCurrentFunction(glOrtho)(__VA_ARGS__)
  27.938 +        #define glPassThrough(...)             GLEGetCurrentFunction(glPassThrough)(__VA_ARGS__)
  27.939 +        #define glPixelMapfv(...)              GLEGetCurrentFunction(glPixelMapfv)(__VA_ARGS__)
  27.940 +        #define glPixelMapuiv(...)             GLEGetCurrentFunction(glPixelMapuiv)(__VA_ARGS__)
  27.941 +        #define glPixelMapusv(...)             GLEGetCurrentFunction(glPixelMapusv)(__VA_ARGS__)
  27.942 +        #define glPixelStoref(...)             GLEGetCurrentFunction(glPixelStoref)(__VA_ARGS__)
  27.943 +        #define glPixelStorei(...)             GLEGetCurrentFunction(glPixelStorei)(__VA_ARGS__)
  27.944 +        #define glPixelTransferf(...)          GLEGetCurrentFunction(glPixelTransferf)(__VA_ARGS__)
  27.945 +        #define glPixelTransferi(...)          GLEGetCurrentFunction(glPixelTransferi)(__VA_ARGS__)
  27.946 +        #define glPixelZoom(...)               GLEGetCurrentFunction(glPixelZoom)(__VA_ARGS__)
  27.947 +        #define glPointSize(...)               GLEGetCurrentFunction(glPointSize)(__VA_ARGS__)
  27.948 +        #define glPolygonMode(...)             GLEGetCurrentFunction(glPolygonMode)(__VA_ARGS__)
  27.949 +        #define glPolygonOffset(...)           GLEGetCurrentFunction(glPolygonOffset)(__VA_ARGS__)
  27.950 +        #define glPolygonStipple(...)          GLEGetCurrentFunction(glPolygonStipple)(__VA_ARGS__)
  27.951 +        #define glPopAttrib()                  GLEGetCurrentFunction(glPopAttrib)()
  27.952 +        #define glPopClientAttrib()            GLEGetCurrentFunction(glPopClientAttrib)()
  27.953 +        #define glPopMatrix()                  GLEGetCurrentFunction(glPopMatrix)()
  27.954 +        #define glPopName()                    GLEGetCurrentFunction(glPopName)()
  27.955 +        #define glPrioritizeTextures(...)      GLEGetCurrentFunction(glPrioritizeTextures)(__VA_ARGS__)
  27.956 +        #define glPushAttrib(...)              GLEGetCurrentFunction(glPushAttrib)(__VA_ARGS__)
  27.957 +        #define glPushClientAttrib(...)        GLEGetCurrentFunction(glPushClientAttrib)(__VA_ARGS__)
  27.958 +        #define glPushMatrix()                 GLEGetCurrentFunction(glPushMatrix)()
  27.959 +        #define glPushName(...)                GLEGetCurrentFunction(glPushName)(__VA_ARGS__)
  27.960 +        #define glRasterPos2d(...)             GLEGetCurrentFunction(glRasterPos2d)(__VA_ARGS__)
  27.961 +        #define glRasterPos2dv(...)            GLEGetCurrentFunction(glRasterPos2dv)(__VA_ARGS__)
  27.962 +        #define glRasterPos2f(...)             GLEGetCurrentFunction(glRasterPos2f)(__VA_ARGS__)
  27.963 +        #define glRasterPos2fv(...)            GLEGetCurrentFunction(glRasterPos2fv)(__VA_ARGS__)
  27.964 +        #define glRasterPos2i(...)             GLEGetCurrentFunction(glRasterPos2i)(__VA_ARGS__)
  27.965 +        #define glRasterPos2iv(...)            GLEGetCurrentFunction(glRasterPos2iv)(__VA_ARGS__)
  27.966 +        #define glRasterPos2s(...)             GLEGetCurrentFunction(glRasterPos2s)(__VA_ARGS__)
  27.967 +        #define glRasterPos2sv(...)            GLEGetCurrentFunction(glRasterPos2sv)(__VA_ARGS__)
  27.968 +        #define glRasterPos3d(...)             GLEGetCurrentFunction(glRasterPos3d)(__VA_ARGS__)
  27.969 +        #define glRasterPos3dv(...)            GLEGetCurrentFunction(glRasterPos3dv)(__VA_ARGS__)
  27.970 +        #define glRasterPos3f(...)             GLEGetCurrentFunction(glRasterPos3f)(__VA_ARGS__)
  27.971 +        #define glRasterPos3fv(...)            GLEGetCurrentFunction(glRasterPos3fv)(__VA_ARGS__)
  27.972 +        #define glRasterPos3i(...)             GLEGetCurrentFunction(glRasterPos3i)(__VA_ARGS__)
  27.973 +        #define glRasterPos3iv(...)            GLEGetCurrentFunction(glRasterPos3iv)(__VA_ARGS__)
  27.974 +        #define glRasterPos3s(...)             GLEGetCurrentFunction(glRasterPos3s)(__VA_ARGS__)
  27.975 +        #define glRasterPos3sv(...)            GLEGetCurrentFunction(glRasterPos3sv)(__VA_ARGS__)
  27.976 +        #define glRasterPos4d(...)             GLEGetCurrentFunction(glRasterPos4d)(__VA_ARGS__)
  27.977 +        #define glRasterPos4dv(...)            GLEGetCurrentFunction(glRasterPos4dv)(__VA_ARGS__)
  27.978 +        #define glRasterPos4f(...)             GLEGetCurrentFunction(glRasterPos4f)(__VA_ARGS__)
  27.979 +        #define glRasterPos4fv(...)            GLEGetCurrentFunction(glRasterPos4fv)(__VA_ARGS__)
  27.980 +        #define glRasterPos4i(...)             GLEGetCurrentFunction(glRasterPos4i)(__VA_ARGS__)
  27.981 +        #define glRasterPos4iv(...)            GLEGetCurrentFunction(glRasterPos4iv)(__VA_ARGS__)
  27.982 +        #define glRasterPos4s(...)             GLEGetCurrentFunction(glRasterPos4s)(__VA_ARGS__)
  27.983 +        #define glRasterPos4sv(...)            GLEGetCurrentFunction(glRasterPos4sv)(__VA_ARGS__)
  27.984 +        #define glReadBuffer(...)              GLEGetCurrentFunction(glReadBuffer)(__VA_ARGS__)
  27.985 +        #define glReadPixels(...)              GLEGetCurrentFunction(glReadPixels)(__VA_ARGS__)
  27.986 +        #define glRectd(...)                   GLEGetCurrentFunction(glRectd)(__VA_ARGS__)
  27.987 +        #define glRectdv(...)                  GLEGetCurrentFunction(glRectdv)(__VA_ARGS__)
  27.988 +        #define glRectf(...)                   GLEGetCurrentFunction(glRectf)(__VA_ARGS__)
  27.989 +        #define glRectfv(...)                  GLEGetCurrentFunction(glRectfv)(__VA_ARGS__)
  27.990 +        #define glRecti(...)                   GLEGetCurrentFunction(glRecti)(__VA_ARGS__)
  27.991 +        #define glRectiv(...)                  GLEGetCurrentFunction(glRectiv)(__VA_ARGS__)
  27.992 +        #define glRects(...)                   GLEGetCurrentFunction(glRects)(__VA_ARGS__)
  27.993 +        #define glRectsv(...)                  GLEGetCurrentFunction(glRectsv)(__VA_ARGS__)
  27.994 +        #define glRenderMode(...)              GLEGetCurrentFunction(glRenderMode)(__VA_ARGS__)
  27.995 +        #define glRotated(...)                 GLEGetCurrentFunction(glRotated)(__VA_ARGS__)
  27.996 +        #define glRotatef(...)                 GLEGetCurrentFunction(glRotatef)(__VA_ARGS__)
  27.997 +        #define glScaled(...)                  GLEGetCurrentFunction(glScaled)(__VA_ARGS__)
  27.998 +        #define glScalef(...)                  GLEGetCurrentFunction(glScalef)(__VA_ARGS__)
  27.999 +        #define glScissor(...)                 GLEGetCurrentFunction(glScissor)(__VA_ARGS__)
 27.1000 +        #define glSelectBuffer(...)            GLEGetCurrentFunction(glSelectBuffer)(__VA_ARGS__)
 27.1001 +        #define glShadeModel(...)              GLEGetCurrentFunction(glShadeModel)(__VA_ARGS__)
 27.1002 +        #define glStencilFunc(...)             GLEGetCurrentFunction(glStencilFunc)(__VA_ARGS__)
 27.1003 +        #define glStencilMask(...)             GLEGetCurrentFunction(glStencilMask)(__VA_ARGS__)
 27.1004 +        #define glStencilOp(...)               GLEGetCurrentFunction(glStencilOp)(__VA_ARGS__)
 27.1005 +        #define glTexCoord1d(...)              GLEGetCurrentFunction(glTexCoord1d)(__VA_ARGS__)
 27.1006 +        #define glTexCoord1dv(...)             GLEGetCurrentFunction(glTexCoord1dv)(__VA_ARGS__)
 27.1007 +        #define glTexCoord1f(...)              GLEGetCurrentFunction(glTexCoord1f)(__VA_ARGS__)
 27.1008 +        #define glTexCoord1fv(...)             GLEGetCurrentFunction(glTexCoord1fv)(__VA_ARGS__)
 27.1009 +        #define glTexCoord1i(...)              GLEGetCurrentFunction(glTexCoord1i)(__VA_ARGS__)
 27.1010 +        #define glTexCoord1iv(...)             GLEGetCurrentFunction(glTexCoord1iv)(__VA_ARGS__)
 27.1011 +        #define glTexCoord1s(...)              GLEGetCurrentFunction(glTexCoord1s)(__VA_ARGS__)
 27.1012 +        #define glTexCoord1sv(...)             GLEGetCurrentFunction(glTexCoord1sv)(__VA_ARGS__)
 27.1013 +        #define glTexCoord2d(...)              GLEGetCurrentFunction(glTexCoord2d)(__VA_ARGS__)
 27.1014 +        #define glTexCoord2dv(...)             GLEGetCurrentFunction(glTexCoord2dv)(__VA_ARGS__)
 27.1015 +        #define glTexCoord2f(...)              GLEGetCurrentFunction(glTexCoord2f)(__VA_ARGS__)
 27.1016 +        #define glTexCoord2fv(...)             GLEGetCurrentFunction(glTexCoord2fv)(__VA_ARGS__)
 27.1017 +        #define glTexCoord2i(...)              GLEGetCurrentFunction(glTexCoord2i)(__VA_ARGS__)
 27.1018 +        #define glTexCoord2iv(...)             GLEGetCurrentFunction(glTexCoord2iv)(__VA_ARGS__)
 27.1019 +        #define glTexCoord2s(...)              GLEGetCurrentFunction(glTexCoord2s)(__VA_ARGS__)
 27.1020 +        #define glTexCoord2sv(...)             GLEGetCurrentFunction(glTexCoord2sv)(__VA_ARGS__)
 27.1021 +        #define glTexCoord3d(...)              GLEGetCurrentFunction(glTexCoord3d)(__VA_ARGS__)
 27.1022 +        #define glTexCoord3dv(...)             GLEGetCurrentFunction(glTexCoord3dv)(__VA_ARGS__)
 27.1023 +        #define glTexCoord3f(...)              GLEGetCurrentFunction(glTexCoord3f)(__VA_ARGS__)
 27.1024 +        #define glTexCoord3fv(...)             GLEGetCurrentFunction(glTexCoord3fv)(__VA_ARGS__)
 27.1025 +        #define glTexCoord3i(...)              GLEGetCurrentFunction(glTexCoord3i)(__VA_ARGS__)
 27.1026 +        #define glTexCoord3iv(...)             GLEGetCurrentFunction(glTexCoord3iv)(__VA_ARGS__)
 27.1027 +        #define glTexCoord3s(...)              GLEGetCurrentFunction(glTexCoord3s)(__VA_ARGS__)
 27.1028 +        #define glTexCoord3sv(...)             GLEGetCurrentFunction(glTexCoord3sv)(__VA_ARGS__)
 27.1029 +        #define glTexCoord4d(...)              GLEGetCurrentFunction(glTexCoord4d)(__VA_ARGS__)
 27.1030 +        #define glTexCoord4dv(...)             GLEGetCurrentFunction(glTexCoord4dv)(__VA_ARGS__)
 27.1031 +        #define glTexCoord4f(...)              GLEGetCurrentFunction(glTexCoord4f)(__VA_ARGS__)
 27.1032 +        #define glTexCoord4fv(...)             GLEGetCurrentFunction(glTexCoord4fv)(__VA_ARGS__)
 27.1033 +        #define glTexCoord4i(...)              GLEGetCurrentFunction(glTexCoord4i)(__VA_ARGS__)
 27.1034 +        #define glTexCoord4iv(...)             GLEGetCurrentFunction(glTexCoord4iv)(__VA_ARGS__)
 27.1035 +        #define glTexCoord4s(...)              GLEGetCurrentFunction(glTexCoord4s)(__VA_ARGS__)
 27.1036 +        #define glTexCoord4sv(...)             GLEGetCurrentFunction(glTexCoord4sv)(__VA_ARGS__)
 27.1037 +        #define glTexCoordPointer(...)         GLEGetCurrentFunction(glTexCoordPointer)(__VA_ARGS__)
 27.1038 +        #define glTexEnvf(...)                 GLEGetCurrentFunction(glTexEnvf)(__VA_ARGS__)
 27.1039 +        #define glTexEnvfv(...)                GLEGetCurrentFunction(glTexEnvfv)(__VA_ARGS__)
 27.1040 +        #define glTexEnvi(...)                 GLEGetCurrentFunction(glTexEnvi)(__VA_ARGS__)
 27.1041 +        #define glTexEnviv(...)                GLEGetCurrentFunction(glTexEnviv)(__VA_ARGS__)
 27.1042 +        #define glTexGend(...)                 GLEGetCurrentFunction(glTexGend)(__VA_ARGS__)
 27.1043 +        #define glTexGendv(...)                GLEGetCurrentFunction(glTexGendv)(__VA_ARGS__)
 27.1044 +        #define glTexGenf(...)                 GLEGetCurrentFunction(glTexGenf)(__VA_ARGS__)
 27.1045 +        #define glTexGenfv(...)                GLEGetCurrentFunction(glTexGenfv)(__VA_ARGS__)
 27.1046 +        #define glTexGeni(...)                 GLEGetCurrentFunction(glTexGeni)(__VA_ARGS__)
 27.1047 +        #define glTexGeniv(...)                GLEGetCurrentFunction(glTexGeniv)(__VA_ARGS__)
 27.1048 +        #define glTexImage1D(...)              GLEGetCurrentFunction(glTexImage1D)(__VA_ARGS__)
 27.1049 +        #define glTexImage2D(...)              GLEGetCurrentFunction(glTexImage2D)(__VA_ARGS__)
 27.1050 +        #define glTexParameterf(...)           GLEGetCurrentFunction(glTexParameterf)(__VA_ARGS__)
 27.1051 +        #define glTexParameterfv(...)          GLEGetCurrentFunction(glTexParameterfv)(__VA_ARGS__)
 27.1052 +        #define glTexParameteri(...)           GLEGetCurrentFunction(glTexParameteri)(__VA_ARGS__)
 27.1053 +        #define glTexParameteriv(...)          GLEGetCurrentFunction(glTexParameteriv)(__VA_ARGS__)
 27.1054 +        #define glTexSubImage1D(...)           GLEGetCurrentFunction(glTexSubImage1D)(__VA_ARGS__)
 27.1055 +        #define glTexSubImage2D(...)           GLEGetCurrentFunction(glTexSubImage2D)(__VA_ARGS__)
 27.1056 +        #define glTranslated(...)              GLEGetCurrentFunction(glTranslated)(__VA_ARGS__)
 27.1057 +        #define glTranslatef(...)              GLEGetCurrentFunction(glTranslatef)(__VA_ARGS__)
 27.1058 +        #define glVertex2d(...)                GLEGetCurrentFunction(glVertex2d)(__VA_ARGS__)
 27.1059 +        #define glVertex2dv(...)               GLEGetCurrentFunction(glVertex2dv)(__VA_ARGS__)
 27.1060 +        #define glVertex2f(...)                GLEGetCurrentFunction(glVertex2f)(__VA_ARGS__)
 27.1061 +        #define glVertex2fv(...)               GLEGetCurrentFunction(glVertex2fv)(__VA_ARGS__)
 27.1062 +        #define glVertex2i(...)                GLEGetCurrentFunction(glVertex2i)(__VA_ARGS__)
 27.1063 +        #define glVertex2iv(...)               GLEGetCurrentFunction(glVertex2iv)(__VA_ARGS__)
 27.1064 +        #define glVertex2s(...)                GLEGetCurrentFunction(glVertex2s)(__VA_ARGS__)
 27.1065 +        #define glVertex2sv(...)               GLEGetCurrentFunction(glVertex2sv)(__VA_ARGS__)
 27.1066 +        #define glVertex3d(...)                GLEGetCurrentFunction(glVertex3d)(__VA_ARGS__)
 27.1067 +        #define glVertex3dv(...)               GLEGetCurrentFunction(glVertex3dv)(__VA_ARGS__)
 27.1068 +        #define glVertex3f(...)                GLEGetCurrentFunction(glVertex3f)(__VA_ARGS__)
 27.1069 +        #define glVertex3fv(...)               GLEGetCurrentFunction(glVertex3fv)(__VA_ARGS__)
 27.1070 +        #define glVertex3i(...)                GLEGetCurrentFunction(glVertex3i)(__VA_ARGS__)
 27.1071 +        #define glVertex3iv(...)               GLEGetCurrentFunction(glVertex3iv)(__VA_ARGS__)
 27.1072 +        #define glVertex3s(...)                GLEGetCurrentFunction(glVertex3s)(__VA_ARGS__)
 27.1073 +        #define glVertex3sv(...)               GLEGetCurrentFunction(glVertex3sv)(__VA_ARGS__)
 27.1074 +        #define glVertex4d(...)                GLEGetCurrentFunction(glVertex4d)(__VA_ARGS__)
 27.1075 +        #define glVertex4dv(...)               GLEGetCurrentFunction(glVertex4dv)(__VA_ARGS__)
 27.1076 +        #define glVertex4f(...)                GLEGetCurrentFunction(glVertex4f)(__VA_ARGS__)
 27.1077 +        #define glVertex4fv(...)               GLEGetCurrentFunction(glVertex4fv)(__VA_ARGS__)
 27.1078 +        #define glVertex4i(...)                GLEGetCurrentFunction(glVertex4i)(__VA_ARGS__)
 27.1079 +        #define glVertex4iv(...)               GLEGetCurrentFunction(glVertex4iv)(__VA_ARGS__)
 27.1080 +        #define glVertex4s(...)                GLEGetCurrentFunction(glVertex4s)(__VA_ARGS__)
 27.1081 +        #define glVertex4sv(...)               GLEGetCurrentFunction(glVertex4sv)(__VA_ARGS__)
 27.1082 +        #define glVertexPointer(...)           GLEGetCurrentFunction(glVertexPointer)(__VA_ARGS__)
 27.1083 +        #define glViewport(...)                GLEGetCurrentFunction(glViewport)(__VA_ARGS__)
 27.1084 +    #else
 27.1085 +        // There is no need to typedef OpenGL 1.1 function types because they are present in all
 27.1086 +        // OpenGL implementations and don't need to be treated dynamically like extensions.
 27.1087 +        GLAPI void            GLAPIENTRY glAccum (GLenum op, GLfloat value);
 27.1088 +        GLAPI void            GLAPIENTRY glAlphaFunc (GLenum func, GLclampf ref);
 27.1089 +        GLAPI GLboolean       GLAPIENTRY glAreTexturesResident (GLsizei n, const GLuint *textures, GLboolean *residences);
 27.1090 +        GLAPI void            GLAPIENTRY glArrayElement (GLint i);
 27.1091 +        GLAPI void            GLAPIENTRY glBegin (GLenum mode);
 27.1092 +        GLAPI void            GLAPIENTRY glBindTexture (GLenum target, GLuint texture);
 27.1093 +        GLAPI void            GLAPIENTRY glBitmap (GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte *bitmap);
 27.1094 +        GLAPI void            GLAPIENTRY glBlendFunc (GLenum sfactor, GLenum dfactor);
 27.1095 +        GLAPI void            GLAPIENTRY glCallList (GLuint list);
 27.1096 +        GLAPI void            GLAPIENTRY glCallLists (GLsizei n, GLenum type, const void *lists);
 27.1097 +        GLAPI void            GLAPIENTRY glClear (GLbitfield mask);
 27.1098 +        GLAPI void            GLAPIENTRY glClearAccum (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
 27.1099 +        GLAPI void            GLAPIENTRY glClearColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
 27.1100 +        GLAPI void            GLAPIENTRY glClearDepth (GLclampd depth);
 27.1101 +        GLAPI void            GLAPIENTRY glClearIndex (GLfloat c);
 27.1102 +        GLAPI void            GLAPIENTRY glClearStencil (GLint s);
 27.1103 +        GLAPI void            GLAPIENTRY glClipPlane (GLenum plane, const GLdouble *equation);
 27.1104 +        GLAPI void            GLAPIENTRY glColor3b (GLbyte red, GLbyte green, GLbyte blue);
 27.1105 +        GLAPI void            GLAPIENTRY glColor3bv (const GLbyte *v);
 27.1106 +        GLAPI void            GLAPIENTRY glColor3d (GLdouble red, GLdouble green, GLdouble blue);
 27.1107 +        GLAPI void            GLAPIENTRY glColor3dv (const GLdouble *v);
 27.1108 +        GLAPI void            GLAPIENTRY glColor3f (GLfloat red, GLfloat green, GLfloat blue);
 27.1109 +        GLAPI void            GLAPIENTRY glColor3fv (const GLfloat *v);
 27.1110 +        GLAPI void            GLAPIENTRY glColor3i (GLint red, GLint green, GLint blue);
 27.1111 +        GLAPI void            GLAPIENTRY glColor3iv (const GLint *v);
 27.1112 +        GLAPI void            GLAPIENTRY glColor3s (GLshort red, GLshort green, GLshort blue);
 27.1113 +        GLAPI void            GLAPIENTRY glColor3sv (const GLshort *v);
 27.1114 +        GLAPI void            GLAPIENTRY glColor3ub (GLubyte red, GLubyte green, GLubyte blue);
 27.1115 +        GLAPI void            GLAPIENTRY glColor3ubv (const GLubyte *v);
 27.1116 +        GLAPI void            GLAPIENTRY glColor3ui (GLuint red, GLuint green, GLuint blue);
 27.1117 +        GLAPI void            GLAPIENTRY glColor3uiv (const GLuint *v);
 27.1118 +        GLAPI void            GLAPIENTRY glColor3us (GLushort red, GLushort green, GLushort blue);
 27.1119 +        GLAPI void            GLAPIENTRY glColor3usv (const GLushort *v);
 27.1120 +        GLAPI void            GLAPIENTRY glColor4b (GLbyte red, GLbyte green, GLbyte blue, GLbyte alpha);
 27.1121 +        GLAPI void            GLAPIENTRY glColor4bv (const GLbyte *v);
 27.1122 +        GLAPI void            GLAPIENTRY glColor4d (GLdouble red, GLdouble green, GLdouble blue, GLdouble alpha);
 27.1123 +        GLAPI void            GLAPIENTRY glColor4dv (const GLdouble *v);
 27.1124 +        GLAPI void            GLAPIENTRY glColor4f (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
 27.1125 +        GLAPI void            GLAPIENTRY glColor4fv (const GLfloat *v);
 27.1126 +        GLAPI void            GLAPIENTRY glColor4i (GLint red, GLint green, GLint blue, GLint alpha);
 27.1127 +        GLAPI void            GLAPIENTRY glColor4iv (const GLint *v);
 27.1128 +        GLAPI void            GLAPIENTRY glColor4s (GLshort red, GLshort green, GLshort blue, GLshort alpha);
 27.1129 +        GLAPI void            GLAPIENTRY glColor4sv (const GLshort *v);
 27.1130 +        GLAPI void            GLAPIENTRY glColor4ub (GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha);
 27.1131 +        GLAPI void            GLAPIENTRY glColor4ubv (const GLubyte *v);
 27.1132 +        GLAPI void            GLAPIENTRY glColor4ui (GLuint red, GLuint green, GLuint blue, GLuint alpha);
 27.1133 +        GLAPI void            GLAPIENTRY glColor4uiv (const GLuint *v);
 27.1134 +        GLAPI void            GLAPIENTRY glColor4us (GLushort red, GLushort green, GLushort blue, GLushort alpha);
 27.1135 +        GLAPI void            GLAPIENTRY glColor4usv (const GLushort *v);
 27.1136 +        GLAPI void            GLAPIENTRY glColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
 27.1137 +        GLAPI void            GLAPIENTRY glColorMaterial (GLenum face, GLenum mode);
 27.1138 +        GLAPI void            GLAPIENTRY glColorPointer (GLint size, GLenum type, GLsizei stride, const void *pointer);
 27.1139 +        GLAPI void            GLAPIENTRY glCopyPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum type);
 27.1140 +        GLAPI void            GLAPIENTRY glCopyTexImage1D (GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLint border);
 27.1141 +        GLAPI void            GLAPIENTRY glCopyTexImage2D (GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
 27.1142 +        GLAPI void            GLAPIENTRY glCopyTexSubImage1D (GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);
 27.1143 +        GLAPI void            GLAPIENTRY glCopyTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
 27.1144 +        GLAPI void            GLAPIENTRY glCullFace (GLenum mode);
 27.1145 +        GLAPI void            GLAPIENTRY glDeleteLists (GLuint list, GLsizei range);
 27.1146 +        GLAPI void            GLAPIENTRY glDeleteTextures (GLsizei n, const GLuint *textures);
 27.1147 +        GLAPI void            GLAPIENTRY glDepthFunc (GLenum func);
 27.1148 +        GLAPI void            GLAPIENTRY glDepthMask (GLboolean flag);
 27.1149 +        GLAPI void            GLAPIENTRY glDepthRange (GLclampd zNear, GLclampd zFar);
 27.1150 +        GLAPI void            GLAPIENTRY glDisable (GLenum cap);
 27.1151 +        GLAPI void            GLAPIENTRY glDisableClientState (GLenum array);
 27.1152 +        GLAPI void            GLAPIENTRY glDrawArrays (GLenum mode, GLint first, GLsizei count);
 27.1153 +        GLAPI void            GLAPIENTRY glDrawBuffer (GLenum mode);
 27.1154 +        GLAPI void            GLAPIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const void *indices);
 27.1155 +        GLAPI void            GLAPIENTRY glDrawPixels (GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
 27.1156 +        GLAPI void            GLAPIENTRY glEdgeFlag (GLboolean flag);
 27.1157 +        GLAPI void            GLAPIENTRY glEdgeFlagPointer (GLsizei stride, const void *pointer);
 27.1158 +        GLAPI void            GLAPIENTRY glEdgeFlagv (const GLboolean *flag);
 27.1159 +        GLAPI void            GLAPIENTRY glEnable (GLenum cap);
 27.1160 +        GLAPI void            GLAPIENTRY glEnableClientState (GLenum array);
 27.1161 +        GLAPI void            GLAPIENTRY glEnd (void);
 27.1162 +        GLAPI void            GLAPIENTRY glEndList (void);
 27.1163 +        GLAPI void            GLAPIENTRY glEvalCoord1d (GLdouble u);
 27.1164 +        GLAPI void            GLAPIENTRY glEvalCoord1dv (const GLdouble *u);
 27.1165 +        GLAPI void            GLAPIENTRY glEvalCoord1f (GLfloat u);
 27.1166 +        GLAPI void            GLAPIENTRY glEvalCoord1fv (const GLfloat *u);
 27.1167 +        GLAPI void            GLAPIENTRY glEvalCoord2d (GLdouble u, GLdouble v);
 27.1168 +        GLAPI void            GLAPIENTRY glEvalCoord2dv (const GLdouble *u);
 27.1169 +        GLAPI void            GLAPIENTRY glEvalCoord2f (GLfloat u, GLfloat v);
 27.1170 +        GLAPI void            GLAPIENTRY glEvalCoord2fv (const GLfloat *u);
 27.1171 +        GLAPI void            GLAPIENTRY glEvalMesh1 (GLenum mode, GLint i1, GLint i2);
 27.1172 +        GLAPI void            GLAPIENTRY glEvalMesh2 (GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2);
 27.1173 +        GLAPI void            GLAPIENTRY glEvalPoint1 (GLint i);
 27.1174 +        GLAPI void            GLAPIENTRY glEvalPoint2 (GLint i, GLint j);
 27.1175 +        GLAPI void            GLAPIENTRY glFeedbackBuffer (GLsizei size, GLenum type, GLfloat *buffer);
 27.1176 +        GLAPI void            GLAPIENTRY glFinish (void);
 27.1177 +        GLAPI void            GLAPIENTRY glFlush (void);
 27.1178 +        GLAPI void            GLAPIENTRY glFogf (GLenum pname, GLfloat param);
 27.1179 +        GLAPI void            GLAPIENTRY glFogfv (GLenum pname, const GLfloat *params);
 27.1180 +        GLAPI void            GLAPIENTRY glFogi (GLenum pname, GLint param);
 27.1181 +        GLAPI void            GLAPIENTRY glFogiv (GLenum pname, const GLint *params);
 27.1182 +        GLAPI void            GLAPIENTRY glFrontFace (GLenum mode);
 27.1183 +        GLAPI void            GLAPIENTRY glFrustum (GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
 27.1184 +        GLAPI GLuint          GLAPIENTRY glGenLists (GLsizei range);
 27.1185 +        GLAPI void            GLAPIENTRY glGenTextures (GLsizei n, GLuint *textures);
 27.1186 +        GLAPI void            GLAPIENTRY glGetBooleanv (GLenum pname, GLboolean *params);
 27.1187 +        GLAPI void            GLAPIENTRY glGetClipPlane (GLenum plane, GLdouble *equation);
 27.1188 +        GLAPI void            GLAPIENTRY glGetDoublev (GLenum pname, GLdouble *params);
 27.1189 +        GLAPI GLenum          GLAPIENTRY glGetError (void);
 27.1190 +        GLAPI void            GLAPIENTRY glGetFloatv (GLenum pname, GLfloat *params);
 27.1191 +        GLAPI void            GLAPIENTRY glGetIntegerv (GLenum pname, GLint *params);
 27.1192 +        GLAPI void            GLAPIENTRY glGetLightfv (GLenum light, GLenum pname, GLfloat *params);
 27.1193 +        GLAPI void            GLAPIENTRY glGetLightiv (GLenum light, GLenum pname, GLint *params);
 27.1194 +        GLAPI void            GLAPIENTRY glGetMapdv (GLenum target, GLenum query, GLdouble *v);
 27.1195 +        GLAPI void            GLAPIENTRY glGetMapfv (GLenum target, GLenum query, GLfloat *v);
 27.1196 +        GLAPI void            GLAPIENTRY glGetMapiv (GLenum target, GLenum query, GLint *v);
 27.1197 +        GLAPI void            GLAPIENTRY glGetMaterialfv (GLenum face, GLenum pname, GLfloat *params);
 27.1198 +        GLAPI void            GLAPIENTRY glGetMaterialiv (GLenum face, GLenum pname, GLint *params);
 27.1199 +        GLAPI void            GLAPIENTRY glGetPixelMapfv (GLenum map, GLfloat *values);
 27.1200 +        GLAPI void            GLAPIENTRY glGetPixelMapuiv (GLenum map, GLuint *values);
 27.1201 +        GLAPI void            GLAPIENTRY glGetPixelMapusv (GLenum map, GLushort *values);
 27.1202 +        GLAPI void            GLAPIENTRY glGetPointerv (GLenum pname, void* *params);
 27.1203 +        GLAPI void            GLAPIENTRY glGetPolygonStipple (GLubyte *mask);
 27.1204 +        GLAPI const GLubyte * GLAPIENTRY glGetString (GLenum name);
 27.1205 +        GLAPI void            GLAPIENTRY glGetTexEnvfv (GLenum target, GLenum pname, GLfloat *params);
 27.1206 +        GLAPI void            GLAPIENTRY glGetTexEnviv (GLenum target, GLenum pname, GLint *params);
 27.1207 +        GLAPI void            GLAPIENTRY glGetTexGendv (GLenum coord, GLenum pname, GLdouble *params);
 27.1208 +        GLAPI void            GLAPIENTRY glGetTexGenfv (GLenum coord, GLenum pname, GLfloat *params);
 27.1209 +        GLAPI void            GLAPIENTRY glGetTexGeniv (GLenum coord, GLenum pname, GLint *params);
 27.1210 +        GLAPI void            GLAPIENTRY glGetTexImage (GLenum target, GLint level, GLenum format, GLenum type, void *pixels);
 27.1211 +        GLAPI void            GLAPIENTRY glGetTexLevelParameterfv (GLenum target, GLint level, GLenum pname, GLfloat *params);
 27.1212 +        GLAPI void            GLAPIENTRY glGetTexLevelParameteriv (GLenum target, GLint level, GLenum pname, GLint *params);
 27.1213 +        GLAPI void            GLAPIENTRY glGetTexParameterfv (GLenum target, GLenum pname, GLfloat *params);
 27.1214 +        GLAPI void            GLAPIENTRY glGetTexParameteriv (GLenum target, GLenum pname, GLint *params);
 27.1215 +        GLAPI void            GLAPIENTRY glHint (GLenum target, GLenum mode);
 27.1216 +        GLAPI void            GLAPIENTRY glIndexMask (GLuint mask);
 27.1217 +        GLAPI void            GLAPIENTRY glIndexPointer (GLenum type, GLsizei stride, const void *pointer);
 27.1218 +        GLAPI void            GLAPIENTRY glIndexd (GLdouble c);
 27.1219 +        GLAPI void            GLAPIENTRY glIndexdv (const GLdouble *c);
 27.1220 +        GLAPI void            GLAPIENTRY glIndexf (GLfloat c);
 27.1221 +        GLAPI void            GLAPIENTRY glIndexfv (const GLfloat *c);
 27.1222 +        GLAPI void            GLAPIENTRY glIndexi (GLint c);
 27.1223 +        GLAPI void            GLAPIENTRY glIndexiv (const GLint *c);
 27.1224 +        GLAPI void            GLAPIENTRY glIndexs (GLshort c);
 27.1225 +        GLAPI void            GLAPIENTRY glIndexsv (const GLshort *c);
 27.1226 +        GLAPI void            GLAPIENTRY glIndexub (GLubyte c);
 27.1227 +        GLAPI void            GLAPIENTRY glIndexubv (const GLubyte *c);
 27.1228 +        GLAPI void            GLAPIENTRY glInitNames (void);
 27.1229 +        GLAPI void            GLAPIENTRY glInterleavedArrays (GLenum format, GLsizei stride, const void *pointer);
 27.1230 +        GLAPI GLboolean       GLAPIENTRY glIsEnabled (GLenum cap);
 27.1231 +        GLAPI GLboolean       GLAPIENTRY glIsList (GLuint list);
 27.1232 +        GLAPI GLboolean       GLAPIENTRY glIsTexture (GLuint texture);
 27.1233 +        GLAPI void            GLAPIENTRY glLightModelf (GLenum pname, GLfloat param);
 27.1234 +        GLAPI void            GLAPIENTRY glLightModelfv (GLenum pname, const GLfloat *params);
 27.1235 +        GLAPI void            GLAPIENTRY glLightModeli (GLenum pname, GLint param);
 27.1236 +        GLAPI void            GLAPIENTRY glLightModeliv (GLenum pname, const GLint *params);
 27.1237 +        GLAPI void            GLAPIENTRY glLightf (GLenum light, GLenum pname, GLfloat param);
 27.1238 +        GLAPI void            GLAPIENTRY glLightfv (GLenum light, GLenum pname, const GLfloat *params);
 27.1239 +        GLAPI void            GLAPIENTRY glLighti (GLenum light, GLenum pname, GLint param);
 27.1240 +        GLAPI void            GLAPIENTRY glLightiv (GLenum light, GLenum pname, const GLint *params);
 27.1241 +        GLAPI void            GLAPIENTRY glLineStipple (GLint factor, GLushort pattern);
 27.1242 +        GLAPI void            GLAPIENTRY glLineWidth (GLfloat width);
 27.1243 +        GLAPI void            GLAPIENTRY glListBase (GLuint base);
 27.1244 +        GLAPI void            GLAPIENTRY glLoadIdentity (void);
 27.1245 +        GLAPI void            GLAPIENTRY glLoadMatrixd (const GLdouble *m);
 27.1246 +        GLAPI void            GLAPIENTRY glLoadMatrixf (const GLfloat *m);
 27.1247 +        GLAPI void            GLAPIENTRY glLoadName (GLuint name);
 27.1248 +        GLAPI void            GLAPIENTRY glLogicOp (GLenum opcode);
 27.1249 +        GLAPI void            GLAPIENTRY glMap1d (GLenum target, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points);
 27.1250 +        GLAPI void            GLAPIENTRY glMap1f (GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points);
 27.1251 +        GLAPI void            GLAPIENTRY glMap2d (GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points);
 27.1252 +        GLAPI void            GLAPIENTRY glMap2f (GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points);
 27.1253 +        GLAPI void            GLAPIENTRY glMapGrid1d (GLint un, GLdouble u1, GLdouble u2);
 27.1254 +        GLAPI void            GLAPIENTRY glMapGrid1f (GLint un, GLfloat u1, GLfloat u2);
 27.1255 +        GLAPI void            GLAPIENTRY glMapGrid2d (GLint un, GLdouble u1, GLdouble u2, GLint vn, GLdouble v1, GLdouble v2);
 27.1256 +        GLAPI void            GLAPIENTRY glMapGrid2f (GLint un, GLfloat u1, GLfloat u2, GLint vn, GLfloat v1, GLfloat v2);
 27.1257 +        GLAPI void            GLAPIENTRY glMaterialf (GLenum face, GLenum pname, GLfloat param);
 27.1258 +        GLAPI void            GLAPIENTRY glMaterialfv (GLenum face, GLenum pname, const GLfloat *params);
 27.1259 +        GLAPI void            GLAPIENTRY glMateriali (GLenum face, GLenum pname, GLint param);
 27.1260 +        GLAPI void            GLAPIENTRY glMaterialiv (GLenum face, GLenum pname, const GLint *params);
 27.1261 +        GLAPI void            GLAPIENTRY glMatrixMode (GLenum mode);
 27.1262 +        GLAPI void            GLAPIENTRY glMultMatrixd (const GLdouble *m);
 27.1263 +        GLAPI void            GLAPIENTRY glMultMatrixf (const GLfloat *m);
 27.1264 +        GLAPI void            GLAPIENTRY glNewList (GLuint list, GLenum mode);
 27.1265 +        GLAPI void            GLAPIENTRY glNormal3b (GLbyte nx, GLbyte ny, GLbyte nz);
 27.1266 +        GLAPI void            GLAPIENTRY glNormal3bv (const GLbyte *v);
 27.1267 +        GLAPI void            GLAPIENTRY glNormal3d (GLdouble nx, GLdouble ny, GLdouble nz);
 27.1268 +        GLAPI void            GLAPIENTRY glNormal3dv (const GLdouble *v);
 27.1269 +        GLAPI void            GLAPIENTRY glNormal3f (GLfloat nx, GLfloat ny, GLfloat nz);
 27.1270 +        GLAPI void            GLAPIENTRY glNormal3fv (const GLfloat *v);
 27.1271 +        GLAPI void            GLAPIENTRY glNormal3i (GLint nx, GLint ny, GLint nz);
 27.1272 +        GLAPI void            GLAPIENTRY glNormal3iv (const GLint *v);
 27.1273 +        GLAPI void            GLAPIENTRY glNormal3s (GLshort nx, GLshort ny, GLshort nz);
 27.1274 +        GLAPI void            GLAPIENTRY glNormal3sv (const GLshort *v);
 27.1275 +        GLAPI void            GLAPIENTRY glNormalPointer (GLenum type, GLsizei stride, const void *pointer);
 27.1276 +        GLAPI void            GLAPIENTRY glOrtho (GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
 27.1277 +        GLAPI void            GLAPIENTRY glPassThrough (GLfloat token);
 27.1278 +        GLAPI void            GLAPIENTRY glPixelMapfv (GLenum map, GLsizei mapsize, const GLfloat *values);
 27.1279 +        GLAPI void            GLAPIENTRY glPixelMapuiv (GLenum map, GLsizei mapsize, const GLuint *values);
 27.1280 +        GLAPI void            GLAPIENTRY glPixelMapusv (GLenum map, GLsizei mapsize, const GLushort *values);
 27.1281 +        GLAPI void            GLAPIENTRY glPixelStoref (GLenum pname, GLfloat param);
 27.1282 +        GLAPI void            GLAPIENTRY glPixelStorei (GLenum pname, GLint param);
 27.1283 +        GLAPI void            GLAPIENTRY glPixelTransferf (GLenum pname, GLfloat param);
 27.1284 +        GLAPI void            GLAPIENTRY glPixelTransferi (GLenum pname, GLint param);
 27.1285 +        GLAPI void            GLAPIENTRY glPixelZoom (GLfloat xfactor, GLfloat yfactor);
 27.1286 +        GLAPI void            GLAPIENTRY glPointSize (GLfloat size);
 27.1287 +        GLAPI void            GLAPIENTRY glPolygonMode (GLenum face, GLenum mode);
 27.1288 +        GLAPI void            GLAPIENTRY glPolygonOffset (GLfloat factor, GLfloat units);
 27.1289 +        GLAPI void            GLAPIENTRY glPolygonStipple (const GLubyte *mask);
 27.1290 +        GLAPI void            GLAPIENTRY glPopAttrib (void);
 27.1291 +        GLAPI void            GLAPIENTRY glPopClientAttrib (void);
 27.1292 +        GLAPI void            GLAPIENTRY glPopMatrix (void);
 27.1293 +        GLAPI void            GLAPIENTRY glPopName (void);
 27.1294 +        GLAPI void            GLAPIENTRY glPrioritizeTextures (GLsizei n, const GLuint *textures, const GLclampf *priorities);
 27.1295 +        GLAPI void            GLAPIENTRY glPushAttrib (GLbitfield mask);
 27.1296 +        GLAPI void            GLAPIENTRY glPushClientAttrib (GLbitfield mask);
 27.1297 +        GLAPI void            GLAPIENTRY glPushMatrix (void);
 27.1298 +        GLAPI void            GLAPIENTRY glPushName (GLuint name);
 27.1299 +        GLAPI void            GLAPIENTRY glRasterPos2d (GLdouble x, GLdouble y);
 27.1300 +        GLAPI void            GLAPIENTRY glRasterPos2dv (const GLdouble *v);
 27.1301 +        GLAPI void            GLAPIENTRY glRasterPos2f (GLfloat x, GLfloat y);
 27.1302 +        GLAPI void            GLAPIENTRY glRasterPos2fv (const GLfloat *v);
 27.1303 +        GLAPI void            GLAPIENTRY glRasterPos2i (GLint x, GLint y);
 27.1304 +        GLAPI void            GLAPIENTRY glRasterPos2iv (const GLint *v);
 27.1305 +        GLAPI void            GLAPIENTRY glRasterPos2s (GLshort x, GLshort y);
 27.1306 +        GLAPI void            GLAPIENTRY glRasterPos2sv (const GLshort *v);
 27.1307 +        GLAPI void            GLAPIENTRY glRasterPos3d (GLdouble x, GLdouble y, GLdouble z);
 27.1308 +        GLAPI void            GLAPIENTRY glRasterPos3dv (const GLdouble *v);
 27.1309 +        GLAPI void            GLAPIENTRY glRasterPos3f (GLfloat x, GLfloat y, GLfloat z);
 27.1310 +        GLAPI void            GLAPIENTRY glRasterPos3fv (const GLfloat *v);
 27.1311 +        GLAPI void            GLAPIENTRY glRasterPos3i (GLint x, GLint y, GLint z);
 27.1312 +        GLAPI void            GLAPIENTRY glRasterPos3iv (const GLint *v);
 27.1313 +        GLAPI void            GLAPIENTRY glRasterPos3s (GLshort x, GLshort y, GLshort z);
 27.1314 +        GLAPI void            GLAPIENTRY glRasterPos3sv (const GLshort *v);
 27.1315 +        GLAPI void            GLAPIENTRY glRasterPos4d (GLdouble x, GLdouble y, GLdouble z, GLdouble w);
 27.1316 +        GLAPI void            GLAPIENTRY glRasterPos4dv (const GLdouble *v);
 27.1317 +        GLAPI void            GLAPIENTRY glRasterPos4f (GLfloat x, GLfloat y, GLfloat z, GLfloat w);
 27.1318 +        GLAPI void            GLAPIENTRY glRasterPos4fv (const GLfloat *v);
 27.1319 +        GLAPI void            GLAPIENTRY glRasterPos4i (GLint x, GLint y, GLint z, GLint w);
 27.1320 +        GLAPI void            GLAPIENTRY glRasterPos4iv (const GLint *v);
 27.1321 +        GLAPI void            GLAPIENTRY glRasterPos4s (GLshort x, GLshort y, GLshort z, GLshort w);
 27.1322 +        GLAPI void            GLAPIENTRY glRasterPos4sv (const GLshort *v);
 27.1323 +        GLAPI void            GLAPIENTRY glReadBuffer (GLenum mode);
 27.1324 +        GLAPI void            GLAPIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels);
 27.1325 +        GLAPI void            GLAPIENTRY glRectd (GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2);
 27.1326 +        GLAPI void            GLAPIENTRY glRectdv (const GLdouble *v1, const GLdouble *v2);
 27.1327 +        GLAPI void            GLAPIENTRY glRectf (GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2);
 27.1328 +        GLAPI void            GLAPIENTRY glRectfv (const GLfloat *v1, const GLfloat *v2);
 27.1329 +        GLAPI void            GLAPIENTRY glRecti (GLint x1, GLint y1, GLint x2, GLint y2);
 27.1330 +        GLAPI void            GLAPIENTRY glRectiv (const GLint *v1, const GLint *v2);
 27.1331 +        GLAPI void            GLAPIENTRY glRects (GLshort x1, GLshort y1, GLshort x2, GLshort y2);
 27.1332 +        GLAPI void            GLAPIENTRY glRectsv (const GLshort *v1, const GLshort *v2);
 27.1333 +        GLAPI GLint           GLAPIENTRY glRenderMode (GLenum mode);
 27.1334 +        GLAPI void            GLAPIENTRY glRotated (GLdouble angle, GLdouble x, GLdouble y, GLdouble z);
 27.1335 +        GLAPI void            GLAPIENTRY glRotatef (GLfloat angle, GLfloat x, GLfloat y, GLfloat z);
 27.1336 +        GLAPI void            GLAPIENTRY glScaled (GLdouble x, GLdouble y, GLdouble z);
 27.1337 +        GLAPI void            GLAPIENTRY glScalef (GLfloat x, GLfloat y, GLfloat z);
 27.1338 +        GLAPI void            GLAPIENTRY glScissor (GLint x, GLint y, GLsizei width, GLsizei height);
 27.1339 +        GLAPI void            GLAPIENTRY glSelectBuffer (GLsizei size, GLuint *buffer);
 27.1340 +        GLAPI void            GLAPIENTRY glShadeModel (GLenum mode);
 27.1341 +        GLAPI void            GLAPIENTRY glStencilFunc (GLenum func, GLint ref, GLuint mask);
 27.1342 +        GLAPI void            GLAPIENTRY glStencilMask (GLuint mask);
 27.1343 +        GLAPI void            GLAPIENTRY glStencilOp (GLenum fail, GLenum zfail, GLenum zpass);
 27.1344 +        GLAPI void            GLAPIENTRY glTexCoord1d (GLdouble s);
 27.1345 +        GLAPI void            GLAPIENTRY glTexCoord1dv (const GLdouble *v);
 27.1346 +        GLAPI void            GLAPIENTRY glTexCoord1f (GLfloat s);
 27.1347 +        GLAPI void            GLAPIENTRY glTexCoord1fv (const GLfloat *v);
 27.1348 +        GLAPI void            GLAPIENTRY glTexCoord1i (GLint s);
 27.1349 +        GLAPI void            GLAPIENTRY glTexCoord1iv (const GLint *v);
 27.1350 +        GLAPI void            GLAPIENTRY glTexCoord1s (GLshort s);
 27.1351 +        GLAPI void            GLAPIENTRY glTexCoord1sv (const GLshort *v);
 27.1352 +        GLAPI void            GLAPIENTRY glTexCoord2d (GLdouble s, GLdouble t);
 27.1353 +        GLAPI void            GLAPIENTRY glTexCoord2dv (const GLdouble *v);
 27.1354 +        GLAPI void            GLAPIENTRY glTexCoord2f (GLfloat s, GLfloat t);
 27.1355 +        GLAPI void            GLAPIENTRY glTexCoord2fv (const GLfloat *v);
 27.1356 +        GLAPI void            GLAPIENTRY glTexCoord2i (GLint s, GLint t);
 27.1357 +        GLAPI void            GLAPIENTRY glTexCoord2iv (const GLint *v);
 27.1358 +        GLAPI void            GLAPIENTRY glTexCoord2s (GLshort s, GLshort t);
 27.1359 +        GLAPI void            GLAPIENTRY glTexCoord2sv (const GLshort *v);
 27.1360 +        GLAPI void            GLAPIENTRY glTexCoord3d (GLdouble s, GLdouble t, GLdouble r);
 27.1361 +        GLAPI void            GLAPIENTRY glTexCoord3dv (const GLdouble *v);
 27.1362 +        GLAPI void            GLAPIENTRY glTexCoord3f (GLfloat s, GLfloat t, GLfloat r);
 27.1363 +        GLAPI void            GLAPIENTRY glTexCoord3fv (const GLfloat *v);
 27.1364 +        GLAPI void            GLAPIENTRY glTexCoord3i (GLint s, GLint t, GLint r);
 27.1365 +        GLAPI void            GLAPIENTRY glTexCoord3iv (const GLint *v);
 27.1366 +        GLAPI void            GLAPIENTRY glTexCoord3s (GLshort s, GLshort t, GLshort r);
 27.1367 +        GLAPI void            GLAPIENTRY glTexCoord3sv (const GLshort *v);
 27.1368 +        GLAPI void            GLAPIENTRY glTexCoord4d (GLdouble s, GLdouble t, GLdouble r, GLdouble q);
 27.1369 +        GLAPI void            GLAPIENTRY glTexCoord4dv (const GLdouble *v);
 27.1370 +        GLAPI void            GLAPIENTRY glTexCoord4f (GLfloat s, GLfloat t, GLfloat r, GLfloat q);
 27.1371 +        GLAPI void            GLAPIENTRY glTexCoord4fv (const GLfloat *v);
 27.1372 +        GLAPI void            GLAPIENTRY glTexCoord4i (GLint s, GLint t, GLint r, GLint q);
 27.1373 +        GLAPI void            GLAPIENTRY glTexCoord4iv (const GLint *v);
 27.1374 +        GLAPI void            GLAPIENTRY glTexCoord4s (GLshort s, GLshort t, GLshort r, GLshort q);
 27.1375 +        GLAPI void            GLAPIENTRY glTexCoord4sv (const GLshort *v);
 27.1376 +        GLAPI void            GLAPIENTRY glTexCoordPointer (GLint size, GLenum type, GLsizei stride, const void *pointer);
 27.1377 +        GLAPI void            GLAPIENTRY glTexEnvf (GLenum target, GLenum pname, GLfloat param);
 27.1378 +        GLAPI void            GLAPIENTRY glTexEnvfv (GLenum target, GLenum pname, const GLfloat *params);
 27.1379 +        GLAPI void            GLAPIENTRY glTexEnvi (GLenum target, GLenum pname, GLint param);
 27.1380 +        GLAPI void            GLAPIENTRY glTexEnviv (GLenum target, GLenum pname, const GLint *params);
 27.1381 +        GLAPI void            GLAPIENTRY glTexGend (GLenum coord, GLenum pname, GLdouble param);
 27.1382 +        GLAPI void            GLAPIENTRY glTexGendv (GLenum coord, GLenum pname, const GLdouble *params);
 27.1383 +        GLAPI void            GLAPIENTRY glTexGenf (GLenum coord, GLenum pname, GLfloat param);
 27.1384 +        GLAPI void            GLAPIENTRY glTexGenfv (GLenum coord, GLenum pname, const GLfloat *params);
 27.1385 +        GLAPI void            GLAPIENTRY glTexGeni (GLenum coord, GLenum pname, GLint param);
 27.1386 +        GLAPI void            GLAPIENTRY glTexGeniv (GLenum coord, GLenum pname, const GLint *params);
 27.1387 +        GLAPI void            GLAPIENTRY glTexImage1D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const void *pixels);
 27.1388 +        GLAPI void            GLAPIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels);
 27.1389 +        GLAPI void            GLAPIENTRY glTexParameterf (GLenum target, GLenum pname, GLfloat param);
 27.1390 +        GLAPI void            GLAPIENTRY glTexParameterfv (GLenum target, GLenum pname, const GLfloat *params);
 27.1391 +        GLAPI void            GLAPIENTRY glTexParameteri (GLenum target, GLenum pname, GLint param);
 27.1392 +        GLAPI void            GLAPIENTRY glTexParameteriv (GLenum target, GLenum pname, const GLint *params);
 27.1393 +        GLAPI void            GLAPIENTRY glTexSubImage1D (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void *pixels);
 27.1394 +        GLAPI void            GLAPIENTRY glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
 27.1395 +        GLAPI void            GLAPIENTRY glTranslated (GLdouble x, GLdouble y, GLdouble z);
 27.1396 +        GLAPI void            GLAPIENTRY glTranslatef (GLfloat x, GLfloat y, GLfloat z);
 27.1397 +        GLAPI void            GLAPIENTRY glVertex2d (GLdouble x, GLdouble y);
 27.1398 +        GLAPI void            GLAPIENTRY glVertex2dv (const GLdouble *v);
 27.1399 +        GLAPI void            GLAPIENTRY glVertex2f (GLfloat x, GLfloat y);
 27.1400 +        GLAPI void            GLAPIENTRY glVertex2fv (const GLfloat *v);
 27.1401 +        GLAPI void            GLAPIENTRY glVertex2i (GLint x, GLint y);
 27.1402 +        GLAPI void            GLAPIENTRY glVertex2iv (const GLint *v);
 27.1403 +        GLAPI void            GLAPIENTRY glVertex2s (GLshort x, GLshort y);
 27.1404 +        GLAPI void            GLAPIENTRY glVertex2sv (const GLshort *v);
 27.1405 +        GLAPI void            GLAPIENTRY glVertex3d (GLdouble x, GLdouble y, GLdouble z);
 27.1406 +        GLAPI void            GLAPIENTRY glVertex3dv (const GLdouble *v);
 27.1407 +        GLAPI void            GLAPIENTRY glVertex3f (GLfloat x, GLfloat y, GLfloat z);
 27.1408 +        GLAPI void            GLAPIENTRY glVertex3fv (const GLfloat *v);
 27.1409 +        GLAPI void            GLAPIENTRY glVertex3i (GLint x, GLint y, GLint z);
 27.1410 +        GLAPI void            GLAPIENTRY glVertex3iv (const GLint *v);
 27.1411 +        GLAPI void            GLAPIENTRY glVertex3s (GLshort x, GLshort y, GLshort z);
 27.1412 +        GLAPI void            GLAPIENTRY glVertex3sv (const GLshort *v);
 27.1413 +        GLAPI void            GLAPIENTRY glVertex4d (GLdouble x, GLdouble y, GLdouble z, GLdouble w);
 27.1414 +        GLAPI void            GLAPIENTRY glVertex4dv (const GLdouble *v);
 27.1415 +        GLAPI void            GLAPIENTRY glVertex4f (GLfloat x, GLfloat y, GLfloat z, GLfloat w);
 27.1416 +        GLAPI void            GLAPIENTRY glVertex4fv (const GLfloat *v);
 27.1417 +        GLAPI void            GLAPIENTRY glVertex4i (GLint x, GLint y, GLint z, GLint w);
 27.1418 +        GLAPI void            GLAPIENTRY glVertex4iv (const GLint *v);
 27.1419 +        GLAPI void            GLAPIENTRY glVertex4s (GLshort x, GLshort y, GLshort z, GLshort w);
 27.1420 +        GLAPI void            GLAPIENTRY glVertex4sv (const GLshort *v);
 27.1421 +        GLAPI void            GLAPIENTRY glVertexPointer (GLint size, GLenum type, GLsizei stride, const void *pointer);
 27.1422 +        GLAPI void            GLAPIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height);
 27.1423 +    
 27.1424 +  #endif // GLE_HOOKING_ENABLED
 27.1425 +
 27.1426 +#endif // GL_VERSION_1_1
 27.1427 +
 27.1428 +
 27.1429 +
 27.1430 +
 27.1431 +// OpenGL 1.2+ functions are not declared in Microsoft's gl.h
 27.1432 +
 27.1433 +#ifndef GL_VERSION_1_2
 27.1434 +    #define GL_VERSION_1_2 1
 27.1435 +
 27.1436 +    #define GL_SMOOTH_POINT_SIZE_RANGE 0x0B12
 27.1437 +    #define GL_SMOOTH_POINT_SIZE_GRANULARITY 0x0B13
 27.1438 +    #define GL_SMOOTH_LINE_WIDTH_RANGE 0x0B22
 27.1439 +    #define GL_SMOOTH_LINE_WIDTH_GRANULARITY 0x0B23
 27.1440 +    #define GL_UNSIGNED_BYTE_3_3_2 0x8032
 27.1441 +    #define GL_UNSIGNED_SHORT_4_4_4_4 0x8033
 27.1442 +    #define GL_UNSIGNED_SHORT_5_5_5_1 0x8034
 27.1443 +    #define GL_UNSIGNED_INT_8_8_8_8 0x8035
 27.1444 +    #define GL_UNSIGNED_INT_10_10_10_2 0x8036
 27.1445 +    #define GL_RESCALE_NORMAL 0x803A
 27.1446 +    #define GL_TEXTURE_BINDING_3D 0x806A
 27.1447 +    #define GL_PACK_SKIP_IMAGES 0x806B
 27.1448 +    #define GL_PACK_IMAGE_HEIGHT 0x806C
 27.1449 +    #define GL_UNPACK_SKIP_IMAGES 0x806D
 27.1450 +    #define GL_UNPACK_IMAGE_HEIGHT 0x806E
 27.1451 +    #define GL_TEXTURE_3D 0x806F
 27.1452 +    #define GL_PROXY_TEXTURE_3D 0x8070
 27.1453 +    #define GL_TEXTURE_DEPTH 0x8071
 27.1454 +    #define GL_TEXTURE_WRAP_R 0x8072
 27.1455 +    #define GL_MAX_3D_TEXTURE_SIZE 0x8073
 27.1456 +    #define GL_BGR 0x80E0
 27.1457 +    #define GL_BGRA 0x80E1
 27.1458 +    #define GL_MAX_ELEMENTS_VERTICES 0x80E8
 27.1459 +    #define GL_MAX_ELEMENTS_INDICES 0x80E9
 27.1460 +    #define GL_CLAMP_TO_EDGE 0x812F
 27.1461 +    #define GL_TEXTURE_MIN_LOD 0x813A
 27.1462 +    #define GL_TEXTURE_MAX_LOD 0x813B
 27.1463 +    #define GL_TEXTURE_BASE_LEVEL 0x813C
 27.1464 +    #define GL_TEXTURE_MAX_LEVEL 0x813D
 27.1465 +    #define GL_LIGHT_MODEL_COLOR_CONTROL 0x81F8
 27.1466 +    #define GL_SINGLE_COLOR 0x81F9
 27.1467 +    #define GL_SEPARATE_SPECULAR_COLOR 0x81FA
 27.1468 +    #define GL_UNSIGNED_BYTE_2_3_3_REV 0x8362
 27.1469 +    #define GL_UNSIGNED_SHORT_5_6_5 0x8363
 27.1470 +    #define GL_UNSIGNED_SHORT_5_6_5_REV 0x8364
 27.1471 +    #define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365
 27.1472 +    #define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366
 27.1473 +    #define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367
 27.1474 +    #define GL_ALIASED_POINT_SIZE_RANGE 0x846D
 27.1475 +    #define GL_ALIASED_LINE_WIDTH_RANGE 0x846E
 27.1476 +
 27.1477 +    typedef void (GLAPIENTRY * PFNGLCOPYTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
 27.1478 +    typedef void (GLAPIENTRY * PFNGLDRAWRANGEELEMENTSPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices);
 27.1479 +    typedef void (GLAPIENTRY * PFNGLTEXIMAGE3DPROC) (GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels);
 27.1480 +    typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels);
 27.1481 +
 27.1482 +    #define glCopyTexSubImage3D GLEGetCurrentFunction(glCopyTexSubImage3D)
 27.1483 +    #define glDrawRangeElements GLEGetCurrentFunction(glDrawRangeElements)
 27.1484 +    #define glTexImage3D        GLEGetCurrentFunction(glTexImage3D)
 27.1485 +    #define glTexSubImage3D     GLEGetCurrentFunction(glTexSubImage3D)
 27.1486 +
 27.1487 +    // OpenGL 2.1 deprecated functions
 27.1488 +    /*
 27.1489 +    typedef void (GLAPIENTRY PFNGLBLENDCOLORPROC) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
 27.1490 +    typedef void (GLAPIENTRY PFNGLBLENDEQUATIONPROC) (GLenum mode);
 27.1491 +    typedef void (GLAPIENTRY PFNGLCOLORTABLEPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *table);
 27.1492 +    typedef void (GLAPIENTRY PFNGLCOLORTABLEPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat *params);
 27.1493 +    typedef void (GLAPIENTRY PFNGLCOLORTABLEPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint *params);
 27.1494 +    typedef void (GLAPIENTRY PFNGLCOPYCOLORTABLEPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width);
 27.1495 +    typedef void (GLAPIENTRY PFNGLGETCOLORTABLEPROC) (GLenum target, GLenum format, GLenum type, GLvoid *table);
 27.1496 +    typedef void (GLAPIENTRY PFNGLGETCOLORTABLEPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params);
 27.1497 +    typedef void (GLAPIENTRY PFNGLGETCOLORTABLEPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
 27.1498 +    typedef void (GLAPIENTRY PFNGLCOLORSUBTABLEPROC) (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid *data);
 27.1499 +    typedef void (GLAPIENTRY PFNGLCOPYCOLORSUBTABLEPROC) (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width);
 27.1500 +    typedef void (GLAPIENTRY PFNGLCONVOLUTIONFILTER1DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *image);
 27.1501 +    typedef void (GLAPIENTRY PFNGLCONVOLUTIONFILTER2DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *image);
 27.1502 +    typedef void (GLAPIENTRY PFNGLCONVOLUTIONPARAMETERFPROC) (GLenum target, GLenum pname, GLfloat params);
 27.1503 +    typedef void (GLAPIENTRY PFNGLCONVOLUTIONPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat *params);
 27.1504 +    typedef void (GLAPIENTRY PFNGLCONVOLUTIONPARAMETERIPROC) (GLenum target, GLenum pname, GLint params);
 27.1505 +    typedef void (GLAPIENTRY PFNGLCONVOLUTIONPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint *params);
 27.1506 +    typedef void (GLAPIENTRY PFNGLCOPYCONVOLUTIONFILTER1DPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width);
 27.1507 +    typedef void (GLAPIENTRY PFNGLCOPYCONVOLUTIONFILTER2DPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height);
 27.1508 +    typedef void (GLAPIENTRY PFNGLGETCONVOLUTIONFILTERPROC) (GLenum target, GLenum format, GLenum type, GLvoid *image);
 27.1509 +    typedef void (GLAPIENTRY PFNGLGETCONVOLUTIONPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params);
 27.1510 +    typedef void (GLAPIENTRY PFNGLGETCONVOLUTIONPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
 27.1511 +    typedef void (GLAPIENTRY PFNGLGETSEPARABLEFILTERPROC) (GLenum target, GLenum format, GLenum type, GLvoid *row, GLvoid *column, GLvoid *span);
 27.1512 +    typedef void (GLAPIENTRY PFNGLSEPARABLEFILTER2DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *row, const GLvoid *column);
 27.1513 +    typedef void (GLAPIENTRY PFNGLGETHISTOGRAMPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values);
 27.1514 +    typedef void (GLAPIENTRY PFNGLGETHISTOGRAMPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params);
 27.1515 +    typedef void (GLAPIENTRY PFNGLGETHISTOGRAMPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
 27.1516 +    typedef void (GLAPIENTRY PFNGLGETMINMAXPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values);
 27.1517 +    typedef void (GLAPIENTRY PFNGLGETMINMAXPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params);
 27.1518 +    typedef void (GLAPIENTRY PFNGLGETMINMAXPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
 27.1519 +    typedef void (GLAPIENTRY PFNGLHISTOGRAMPROC) (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink);
 27.1520 +    typedef void (GLAPIENTRY PFNGLMINMAXPROC) (GLenum target, GLenum internalformat, GLboolean sink);
 27.1521 +    typedef void (GLAPIENTRY PFNGLRESETHISTOGRAMPROC) (GLenum target);
 27.1522 +    typedef void (GLAPIENTRY PFNGLRESETMINMAXPROC) (GLenum target);
 27.1523 +    */
 27.1524 +#endif // GL_VERSION_1_2
 27.1525 +
 27.1526 +
 27.1527 +
 27.1528 +#ifndef GL_VERSION_1_3
 27.1529 +    #define GL_VERSION_1_3 1
 27.1530 +
 27.1531 +    #define GL_MULTISAMPLE 0x809D
 27.1532 +    #define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E
 27.1533 +    #define GL_SAMPLE_ALPHA_TO_ONE 0x809F
 27.1534 +    #define GL_SAMPLE_COVERAGE 0x80A0
 27.1535 +    #define GL_SAMPLE_BUFFERS 0x80A8
 27.1536 +    #define GL_SAMPLES 0x80A9
 27.1537 +    #define GL_SAMPLE_COVERAGE_VALUE 0x80AA
 27.1538 +    #define GL_SAMPLE_COVERAGE_INVERT 0x80AB
 27.1539 +    #define GL_CLAMP_TO_BORDER 0x812D
 27.1540 +    #define GL_TEXTURE0 0x84C0
 27.1541 +    #define GL_TEXTURE1 0x84C1
 27.1542 +    #define GL_TEXTURE2 0x84C2
 27.1543 +    #define GL_TEXTURE3 0x84C3
 27.1544 +    #define GL_TEXTURE4 0x84C4
 27.1545 +    #define GL_TEXTURE5 0x84C5
 27.1546 +    #define GL_TEXTURE6 0x84C6
 27.1547 +    #define GL_TEXTURE7 0x84C7
 27.1548 +    #define GL_TEXTURE8 0x84C8
 27.1549 +    #define GL_TEXTURE9 0x84C9
 27.1550 +    #define GL_TEXTURE10 0x84CA
 27.1551 +    #define GL_TEXTURE11 0x84CB
 27.1552 +    #define GL_TEXTURE12 0x84CC
 27.1553 +    #define GL_TEXTURE13 0x84CD
 27.1554 +    #define GL_TEXTURE14 0x84CE
 27.1555 +    #define GL_TEXTURE15 0x84CF
 27.1556 +    #define GL_TEXTURE16 0x84D0
 27.1557 +    #define GL_TEXTURE17 0x84D1
 27.1558 +    #define GL_TEXTURE18 0x84D2
 27.1559 +    #define GL_TEXTURE19 0x84D3
 27.1560 +    #define GL_TEXTURE20 0x84D4
 27.1561 +    #define GL_TEXTURE21 0x84D5
 27.1562 +    #define GL_TEXTURE22 0x84D6
 27.1563 +    #define GL_TEXTURE23 0x84D7
 27.1564 +    #define GL_TEXTURE24 0x84D8
 27.1565 +    #define GL_TEXTURE25 0x84D9
 27.1566 +    #define GL_TEXTURE26 0x84DA
 27.1567 +    #define GL_TEXTURE27 0x84DB
 27.1568 +    #define GL_TEXTURE28 0x84DC
 27.1569 +    #define GL_TEXTURE29 0x84DD
 27.1570 +    #define GL_TEXTURE30 0x84DE
 27.1571 +    #define GL_TEXTURE31 0x84DF
 27.1572 +    #define GL_ACTIVE_TEXTURE 0x84E0
 27.1573 +    #define GL_CLIENT_ACTIVE_TEXTURE 0x84E1
 27.1574 +    #define GL_MAX_TEXTURE_UNITS 0x84E2
 27.1575 +    #define GL_TRANSPOSE_MODELVIEW_MATRIX 0x84E3
 27.1576 +    #define GL_TRANSPOSE_PROJECTION_MATRIX 0x84E4
 27.1577 +    #define GL_TRANSPOSE_TEXTURE_MATRIX 0x84E5
 27.1578 +    #define GL_TRANSPOSE_COLOR_MATRIX 0x84E6
 27.1579 +    #define GL_SUBTRACT 0x84E7
 27.1580 +    #define GL_COMPRESSED_ALPHA 0x84E9
 27.1581 +    #define GL_COMPRESSED_LUMINANCE 0x84EA
 27.1582 +    #define GL_COMPRESSED_LUMINANCE_ALPHA 0x84EB
 27.1583 +    #define GL_COMPRESSED_INTENSITY 0x84EC
 27.1584 +    #define GL_COMPRESSED_RGB 0x84ED
 27.1585 +    #define GL_COMPRESSED_RGBA 0x84EE
 27.1586 +    #define GL_TEXTURE_COMPRESSION_HINT 0x84EF
 27.1587 +    #define GL_NORMAL_MAP 0x8511
 27.1588 +    #define GL_REFLECTION_MAP 0x8512
 27.1589 +    #define GL_TEXTURE_CUBE_MAP 0x8513
 27.1590 +    #define GL_TEXTURE_BINDING_CUBE_MAP 0x8514
 27.1591 +    #define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515
 27.1592 +    #define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516
 27.1593 +    #define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517
 27.1594 +    #define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518
 27.1595 +    #define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519
 27.1596 +    #define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A
 27.1597 +    #define GL_PROXY_TEXTURE_CUBE_MAP 0x851B
 27.1598 +    #define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C
 27.1599 +    #define GL_COMBINE 0x8570
 27.1600 +    #define GL_COMBINE_RGB 0x8571
 27.1601 +    #define GL_COMBINE_ALPHA 0x8572
 27.1602 +    #define GL_RGB_SCALE 0x8573
 27.1603 +    #define GL_ADD_SIGNED 0x8574
 27.1604 +    #define GL_INTERPOLATE 0x8575
 27.1605 +    #define GL_CONSTANT 0x8576
 27.1606 +    #define GL_PRIMARY_COLOR 0x8577
 27.1607 +    #define GL_PREVIOUS 0x8578
 27.1608 +    #define GL_SOURCE0_RGB 0x8580
 27.1609 +    #define GL_SOURCE1_RGB 0x8581
 27.1610 +    #define GL_SOURCE2_RGB 0x8582
 27.1611 +    #define GL_SOURCE0_ALPHA 0x8588
 27.1612 +    #define GL_SOURCE1_ALPHA 0x8589
 27.1613 +    #define GL_SOURCE2_ALPHA 0x858A
 27.1614 +    #define GL_OPERAND0_RGB 0x8590
 27.1615 +    #define GL_OPERAND1_RGB 0x8591
 27.1616 +    #define GL_OPERAND2_RGB 0x8592
 27.1617 +    #define GL_OPERAND0_ALPHA 0x8598
 27.1618 +    #define GL_OPERAND1_ALPHA 0x8599
 27.1619 +    #define GL_OPERAND2_ALPHA 0x859A
 27.1620 +    #define GL_TEXTURE_COMPRESSED_IMAGE_SIZE 0x86A0
 27.1621 +    #define GL_TEXTURE_COMPRESSED 0x86A1
 27.1622 +    #define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2
 27.1623 +    #define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3
 27.1624 +    #define GL_DOT3_RGB 0x86AE
 27.1625 +    #define GL_DOT3_RGBA 0x86AF
 27.1626 +    #define GL_MULTISAMPLE_BIT 0x20000000
 27.1627 +
 27.1628 +    typedef void (GLAPIENTRY * PFNGLACTIVETEXTUREPROC) (GLenum texture);
 27.1629 +    typedef void (GLAPIENTRY * PFNGLCLIENTACTIVETEXTUREPROC) (GLenum texture);
 27.1630 +    typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE1DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void *data);
 27.1631 +    typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE2DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data);
 27.1632 +    typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE3DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data);
 27.1633 +    typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void *data);
 27.1634 +    typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data);
 27.1635 +    typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data);
 27.1636 +    typedef void (GLAPIENTRY * PFNGLGETCOMPRESSEDTEXIMAGEPROC) (GLenum target, GLint lod, void *img);
 27.1637 +    typedef void (GLAPIENTRY * PFNGLLOADTRANSPOSEMATRIXDPROC) (const GLdouble m[16]);
 27.1638 +    typedef void (GLAPIENTRY * PFNGLLOADTRANSPOSEMATRIXFPROC) (const GLfloat m[16]);
 27.1639 +    typedef void (GLAPIENTRY * PFNGLMULTTRANSPOSEMATRIXDPROC) (const GLdouble m[16]);
 27.1640 +    typedef void (GLAPIENTRY * PFNGLMULTTRANSPOSEMATRIXFPROC) (const GLfloat m[16]);
 27.1641 +    typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1DPROC) (GLenum target, GLdouble s);
 27.1642 +    typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1DVPROC) (GLenum target, const GLdouble *v);
 27.1643 +    typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1FPROC) (GLenum target, GLfloat s);
 27.1644 +    typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1FVPROC) (GLenum target, const GLfloat *v);
 27.1645 +    typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1IPROC) (GLenum target, GLint s);
 27.1646 +    typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1IVPROC) (GLenum target, const GLint *v);
 27.1647 +    typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1SPROC) (GLenum target, GLshort s);
 27.1648 +    typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1SVPROC) (GLenum target, const GLshort *v);
 27.1649 +    typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2DPROC) (GLenum target, GLdouble s, GLdouble t);
 27.1650 +    typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2DVPROC) (GLenum target, const GLdouble *v);
 27.1651 +    typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2FPROC) (GLenum target, GLfloat s, GLfloat t);
 27.1652 +    typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2FVPROC) (GLenum target, const GLfloat *v);
 27.1653 +    typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2IPROC) (GLenum target, GLint s, GLint t);
 27.1654 +    typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2IVPROC) (GLenum target, const GLint *v);
 27.1655 +    typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2SPROC) (GLenum target, GLshort s, GLshort t);
 27.1656 +    typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2SVPROC) (GLenum target, const GLshort *v);
 27.1657 +    typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3DPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r);
 27.1658 +    typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3DVPROC) (GLenum target, const GLdouble *v);
 27.1659 +    typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3FPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r);
 27.1660 +    typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3FVPROC) (GLenum target, const GLfloat *v);
 27.1661 +    typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3IPROC) (GLenum target, GLint s, GLint t, GLint r);
 27.1662 +    typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3IVPROC) (GLenum target, const GLint *v);
 27.1663 +    typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3SPROC) (GLenum target, GLshort s, GLshort t, GLshort r);
 27.1664 +    typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3SVPROC) (GLenum target, const GLshort *v);
 27.1665 +    typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4DPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q);
 27.1666 +    typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4DVPROC) (GLenum target, const GLdouble *v);
 27.1667 +    typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4FPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q);
 27.1668 +    typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4FVPROC) (GLenum target, const GLfloat *v);
 27.1669 +    typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4IPROC) (GLenum target, GLint s, GLint t, GLint r, GLint q);
 27.1670 +    typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4IVPROC) (GLenum target, const GLint *v);
 27.1671 +    typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4SPROC) (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q);
 27.1672 +    typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4SVPROC) (GLenum target, const GLshort *v);
 27.1673 +    typedef void (GLAPIENTRY * PFNGLSAMPLECOVERAGEPROC) (GLclampf value, GLboolean invert);
 27.1674 +
 27.1675 +    #define glActiveTexture             GLEGetCurrentFunction(glActiveTexture)
 27.1676 +    #define glClientActiveTexture       GLEGetCurrentFunction(glClientActiveTexture)
 27.1677 +    #define glCompressedTexImage1D      GLEGetCurrentFunction(glCompressedTexImage1D)
 27.1678 +    #define glCompressedTexImage2D      GLEGetCurrentFunction(glCompressedTexImage2D)
 27.1679 +    #define glCompressedTexImage3D      GLEGetCurrentFunction(glCompressedTexImage3D)
 27.1680 +    #define glCompressedTexSubImage1D   GLEGetCurrentFunction(glCompressedTexSubImage1D)
 27.1681 +    #define glCompressedTexSubImage2D   GLEGetCurrentFunction(glCompressedTexSubImage2D)
 27.1682 +    #define glCompressedTexSubImage3D   GLEGetCurrentFunction(glCompressedTexSubImage3D)
 27.1683 +    #define glGetCompressedTexImage     GLEGetCurrentFunction(glGetCompressedTexImage)
 27.1684 +    #define glLoadTransposeMatrixd      GLEGetCurrentFunction(glLoadTransposeMatrixd)
 27.1685 +    #define glLoadTransposeMatrixf      GLEGetCurrentFunction(glLoadTransposeMatrixf)
 27.1686 +    #define glMultTransposeMatrixd      GLEGetCurrentFunction(glMultTransposeMatrixd)
 27.1687 +    #define glMultTransposeMatrixf      GLEGetCurrentFunction(glMultTransposeMatrixf)
 27.1688 +    #define glMultiTexCoord1d           GLEGetCurrentFunction(glMultiTexCoord1d)
 27.1689 +    #define glMultiTexCoord1dv          GLEGetCurrentFunction(glMultiTexCoord1dv)
 27.1690 +    #define glMultiTexCoord1f           GLEGetCurrentFunction(glMultiTexCoord1f)
 27.1691 +    #define glMultiTexCoord1fv          GLEGetCurrentFunction(glMultiTexCoord1fv)
 27.1692 +    #define glMultiTexCoord1i           GLEGetCurrentFunction(glMultiTexCoord1i)
 27.1693 +    #define glMultiTexCoord1iv          GLEGetCurrentFunction(glMultiTexCoord1iv)
 27.1694 +    #define glMultiTexCoord1s           GLEGetCurrentFunction(glMultiTexCoord1s)
 27.1695 +    #define glMultiTexCoord1sv          GLEGetCurrentFunction(glMultiTexCoord1sv)
 27.1696 +    #define glMultiTexCoord2d           GLEGetCurrentFunction(glMultiTexCoord2d)
 27.1697 +    #define glMultiTexCoord2dv          GLEGetCurrentFunction(glMultiTexCoord2dv)
 27.1698 +    #define glMultiTexCoord2f           GLEGetCurrentFunction(glMultiTexCoord2f)
 27.1699 +    #define glMultiTexCoord2fv          GLEGetCurrentFunction(glMultiTexCoord2fv)
 27.1700 +    #define glMultiTexCoord2i           GLEGetCurrentFunction(glMultiTexCoord2i)
 27.1701 +    #define glMultiTexCoord2iv          GLEGetCurrentFunction(glMultiTexCoord2iv)
 27.1702 +    #define glMultiTexCoord2s           GLEGetCurrentFunction(glMultiTexCoord2s)
 27.1703 +    #define glMultiTexCoord2sv          GLEGetCurrentFunction(glMultiTexCoord2sv)
 27.1704 +    #define glMultiTexCoord3d           GLEGetCurrentFunction(glMultiTexCoord3d)
 27.1705 +    #define glMultiTexCoord3dv          GLEGetCurrentFunction(glMultiTexCoord3dv)
 27.1706 +    #define glMultiTexCoord3f           GLEGetCurrentFunction(glMultiTexCoord3f)
 27.1707 +    #define glMultiTexCoord3fv          GLEGetCurrentFunction(glMultiTexCoord3fv)
 27.1708 +    #define glMultiTexCoord3i           GLEGetCurrentFunction(glMultiTexCoord3i)
 27.1709 +    #define glMultiTexCoord3iv          GLEGetCurrentFunction(glMultiTexCoord3iv)
 27.1710 +    #define glMultiTexCoord3s           GLEGetCurrentFunction(glMultiTexCoord3s)
 27.1711 +    #define glMultiTexCoord3sv          GLEGetCurrentFunction(glMultiTexCoord3sv)
 27.1712 +    #define glMultiTexCoord4d           GLEGetCurrentFunction(glMultiTexCoord4d)
 27.1713 +    #define glMultiTexCoord4dv          GLEGetCurrentFunction(glMultiTexCoord4dv)
 27.1714 +    #define glMultiTexCoord4f           GLEGetCurrentFunction(glMultiTexCoord4f)
 27.1715 +    #define glMultiTexCoord4fv          GLEGetCurrentFunction(glMultiTexCoord4fv)
 27.1716 +    #define glMultiTexCoord4i           GLEGetCurrentFunction(glMultiTexCoord4i)
 27.1717 +    #define glMultiTexCoord4iv          GLEGetCurrentFunction(glMultiTexCoord4iv)
 27.1718 +    #define glMultiTexCoord4s           GLEGetCurrentFunction(glMultiTexCoord4s)
 27.1719 +    #define glMultiTexCoord4sv          GLEGetCurrentFunction(glMultiTexCoord4sv)
 27.1720 +    #define glSampleCoverage            GLEGetCurrentFunction(glSampleCoverage)
 27.1721 +
 27.1722 +#endif // GL_VERSION_1_3
 27.1723 +
 27.1724 +
 27.1725 +
 27.1726 +#ifndef GL_VERSION_1_4
 27.1727 +    #define GL_VERSION_1_4 1
 27.1728 +
 27.1729 +    #define GL_BLEND_DST_RGB 0x80C8
 27.1730 +    #define GL_BLEND_SRC_RGB 0x80C9
 27.1731 +    #define GL_BLEND_DST_ALPHA 0x80CA
 27.1732 +    #define GL_BLEND_SRC_ALPHA 0x80CB
 27.1733 +    #define GL_POINT_SIZE_MIN 0x8126
 27.1734 +    #define GL_POINT_SIZE_MAX 0x8127
 27.1735 +    #define GL_POINT_FADE_THRESHOLD_SIZE 0x8128
 27.1736 +    #define GL_POINT_DISTANCE_ATTENUATION 0x8129
 27.1737 +    #define GL_GENERATE_MIPMAP 0x8191
 27.1738 +    #define GL_GENERATE_MIPMAP_HINT 0x8192
 27.1739 +    #define GL_DEPTH_COMPONENT16 0x81A5
 27.1740 +    #define GL_DEPTH_COMPONENT24 0x81A6
 27.1741 +    #define GL_DEPTH_COMPONENT32 0x81A7
 27.1742 +    #define GL_MIRRORED_REPEAT 0x8370
 27.1743 +    #define GL_FOG_COORDINATE_SOURCE 0x8450
 27.1744 +    #define GL_FOG_COORDINATE 0x8451
 27.1745 +    #define GL_FRAGMENT_DEPTH 0x8452
 27.1746 +    #define GL_CURRENT_FOG_COORDINATE 0x8453
 27.1747 +    #define GL_FOG_COORDINATE_ARRAY_TYPE 0x8454
 27.1748 +    #define GL_FOG_COORDINATE_ARRAY_STRIDE 0x8455
 27.1749 +    #define GL_FOG_COORDINATE_ARRAY_POINTER 0x8456
 27.1750 +    #define GL_FOG_COORDINATE_ARRAY 0x8457
 27.1751 +    #define GL_COLOR_SUM 0x8458
 27.1752 +    #define GL_CURRENT_SECONDARY_COLOR 0x8459
 27.1753 +    #define GL_SECONDARY_COLOR_ARRAY_SIZE 0x845A
 27.1754 +    #define GL_SECONDARY_COLOR_ARRAY_TYPE 0x845B
 27.1755 +    #define GL_SECONDARY_COLOR_ARRAY_STRIDE 0x845C
 27.1756 +    #define GL_SECONDARY_COLOR_ARRAY_POINTER 0x845D
 27.1757 +    #define GL_SECONDARY_COLOR_ARRAY 0x845E
 27.1758 +    #define GL_MAX_TEXTURE_LOD_BIAS 0x84FD
 27.1759 +    #define GL_TEXTURE_FILTER_CONTROL 0x8500
 27.1760 +    #define GL_TEXTURE_LOD_BIAS 0x8501
 27.1761 +    #define GL_INCR_WRAP 0x8507
 27.1762 +    #define GL_DECR_WRAP 0x8508
 27.1763 +    #define GL_TEXTURE_DEPTH_SIZE 0x884A
 27.1764 +    #define GL_DEPTH_TEXTURE_MODE 0x884B
 27.1765 +    #define GL_TEXTURE_COMPARE_MODE 0x884C
 27.1766 +    #define GL_TEXTURE_COMPARE_FUNC 0x884D
 27.1767 +    #define GL_COMPARE_R_TO_TEXTURE 0x884E
 27.1768 +
 27.1769 +    typedef void (GLAPIENTRY * PFNGLBLENDCOLORPROC) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
 27.1770 +    typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONPROC) (GLenum mode);
 27.1771 +    typedef void (GLAPIENTRY * PFNGLBLENDFUNCSEPARATEPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
 27.1772 +    typedef void (GLAPIENTRY * PFNGLFOGCOORDPOINTERPROC) (GLenum type, GLsizei stride, const void *pointer);
 27.1773 +    typedef void (GLAPIENTRY * PFNGLFOGCOORDDPROC) (GLdouble coord);
 27.1774 +    typedef void (GLAPIENTRY * PFNGLFOGCOORDDVPROC) (const GLdouble *coord);
 27.1775 +    typedef void (GLAPIENTRY * PFNGLFOGCOORDFPROC) (GLfloat coord);
 27.1776 +    typedef void (GLAPIENTRY * PFNGLFOGCOORDFVPROC) (const GLfloat *coord);
 27.1777 +    typedef void (GLAPIENTRY * PFNGLMULTIDRAWARRAYSPROC) (GLenum mode, const GLint *first, const GLsizei *count, GLsizei drawcount);
 27.1778 +    typedef void (GLAPIENTRY * PFNGLMULTIDRAWELEMENTSPROC) (GLenum mode, const GLsizei *count, GLenum type, const void *const* indices, GLsizei drawcount);
 27.1779 +    typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERFPROC) (GLenum pname, GLfloat param);
 27.1780 +    typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERFVPROC) (GLenum pname, const GLfloat *params);
 27.1781 +    typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERIPROC) (GLenum pname, GLint param);
 27.1782 +    typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERIVPROC) (GLenum pname, const GLint *params);
 27.1783 +    typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3BPROC) (GLbyte red, GLbyte green, GLbyte blue);
 27.1784 +    typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3BVPROC) (const GLbyte *v);
 27.1785 +    typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3DPROC) (GLdouble red, GLdouble green, GLdouble blue);
 27.1786 +    typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3DVPROC) (const GLdouble *v);
 27.1787 +    typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3FPROC) (GLfloat red, GLfloat green, GLfloat blue);
 27.1788 +    typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3FVPROC) (const GLfloat *v);
 27.1789 +    typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3IPROC) (GLint red, GLint green, GLint blue);
 27.1790 +    typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3IVPROC) (const GLint *v);
 27.1791 +    typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3SPROC) (GLshort red, GLshort green, GLshort blue);
 27.1792 +    typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3SVPROC) (const GLshort *v);
 27.1793 +    typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3UBPROC) (GLubyte red, GLubyte green, GLubyte blue);
 27.1794 +    typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3UBVPROC) (const GLubyte *v);
 27.1795 +    typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3UIPROC) (GLuint red, GLuint green, GLuint blue);
 27.1796 +    typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3UIVPROC) (const GLuint *v);
 27.1797 +    typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3USPROC) (GLushort red, GLushort green, GLushort blue);
 27.1798 +    typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3USVPROC) (const GLushort *v);
 27.1799 +    typedef void (GLAPIENTRY * PFNGLSECONDARYCOLORPOINTERPROC) (GLint size, GLenum type, GLsizei stride, const void *pointer);
 27.1800 +    typedef void (GLAPIENTRY * PFNGLWINDOWPOS2DPROC) (GLdouble x, GLdouble y);
 27.1801 +    typedef void (GLAPIENTRY * PFNGLWINDOWPOS2DVPROC) (const GLdouble *p);
 27.1802 +    typedef void (GLAPIENTRY * PFNGLWINDOWPOS2FPROC) (GLfloat x, GLfloat y);
 27.1803 +    typedef void (GLAPIENTRY * PFNGLWINDOWPOS2FVPROC) (const GLfloat *p);
 27.1804 +    typedef void (GLAPIENTRY * PFNGLWINDOWPOS2IPROC) (GLint x, GLint y);
 27.1805 +    typedef void (GLAPIENTRY * PFNGLWINDOWPOS2IVPROC) (const GLint *p);
 27.1806 +    typedef void (GLAPIENTRY * PFNGLWINDOWPOS2SPROC) (GLshort x, GLshort y);
 27.1807 +    typedef void (GLAPIENTRY * PFNGLWINDOWPOS2SVPROC) (const GLshort *p);
 27.1808 +    typedef void (GLAPIENTRY * PFNGLWINDOWPOS3DPROC) (GLdouble x, GLdouble y, GLdouble z);
 27.1809 +    typedef void (GLAPIENTRY * PFNGLWINDOWPOS3DVPROC) (const GLdouble *p);
 27.1810 +    typedef void (GLAPIENTRY * PFNGLWINDOWPOS3FPROC) (GLfloat x, GLfloat y, GLfloat z);
 27.1811 +    typedef void (GLAPIENTRY * PFNGLWINDOWPOS3FVPROC) (const GLfloat *p);
 27.1812 +    typedef void (GLAPIENTRY * PFNGLWINDOWPOS3IPROC) (GLint x, GLint y, GLint z);
 27.1813 +    typedef void (GLAPIENTRY * PFNGLWINDOWPOS3IVPROC) (const GLint *p);
 27.1814 +    typedef void (GLAPIENTRY * PFNGLWINDOWPOS3SPROC) (GLshort x, GLshort y, GLshort z);
 27.1815 +    typedef void (GLAPIENTRY * PFNGLWINDOWPOS3SVPROC) (const GLshort *p);
 27.1816 +
 27.1817 +    #define glBlendColor GLEGetCurrentFunction(glBlendColor)
 27.1818 +    #define glBlendEquation GLEGetCurrentFunction(glBlendEquation)
 27.1819 +    #define glBlendFuncSeparate GLEGetCurrentFunction(glBlendFuncSeparate)
 27.1820 +    #define glFogCoordPointer GLEGetCurrentFunction(glFogCoordPointer)
 27.1821 +    #define glFogCoordd GLEGetCurrentFunction(glFogCoordd)
 27.1822 +    #define glFogCoorddv GLEGetCurrentFunction(glFogCoorddv)
 27.1823 +    #define glFogCoordf GLEGetCurrentFunction(glFogCoordf)
 27.1824 +    #define glFogCoordfv GLEGetCurrentFunction(glFogCoordfv)
 27.1825 +    #define glMultiDrawArrays GLEGetCurrentFunction(glMultiDrawArrays)
 27.1826 +    #define glMultiDrawElements GLEGetCurrentFunction(glMultiDrawElements)
 27.1827 +    #define glPointParameterf GLEGetCurrentFunction(glPointParameterf)
 27.1828 +    #define glPointParameterfv GLEGetCurrentFunction(glPointParameterfv)
 27.1829 +    #define glPointParameteri GLEGetCurrentFunction(glPointParameteri)
 27.1830 +    #define glPointParameteriv GLEGetCurrentFunction(glPointParameteriv)
 27.1831 +    #define glSecondaryColor3b GLEGetCurrentFunction(glSecondaryColor3b)
 27.1832 +    #define glSecondaryColor3bv GLEGetCurrentFunction(glSecondaryColor3bv)
 27.1833 +    #define glSecondaryColor3d GLEGetCurrentFunction(glSecondaryColor3d)
 27.1834 +    #define glSecondaryColor3dv GLEGetCurrentFunction(glSecondaryColor3dv)
 27.1835 +    #define glSecondaryColor3f GLEGetCurrentFunction(glSecondaryColor3f)
 27.1836 +    #define glSecondaryColor3fv GLEGetCurrentFunction(glSecondaryColor3fv)
 27.1837 +    #define glSecondaryColor3i GLEGetCurrentFunction(glSecondaryColor3i)
 27.1838 +    #define glSecondaryColor3iv GLEGetCurrentFunction(glSecondaryColor3iv)
 27.1839 +    #define glSecondaryColor3s GLEGetCurrentFunction(glSecondaryColor3s)
 27.1840 +    #define glSecondaryColor3sv GLEGetCurrentFunction(glSecondaryColor3sv)
 27.1841 +    #define glSecondaryColor3ub GLEGetCurrentFunction(glSecondaryColor3ub)
 27.1842 +    #define glSecondaryColor3ubv GLEGetCurrentFunction(glSecondaryColor3ubv)
 27.1843 +    #define glSecondaryColor3ui GLEGetCurrentFunction(glSecondaryColor3ui)
 27.1844 +    #define glSecondaryColor3uiv GLEGetCurrentFunction(glSecondaryColor3uiv)
 27.1845 +    #define glSecondaryColor3us GLEGetCurrentFunction(glSecondaryColor3us)
 27.1846 +    #define glSecondaryColor3usv GLEGetCurrentFunction(glSecondaryColor3usv)
 27.1847 +    #define glSecondaryColorPointer GLEGetCurrentFunction(glSecondaryColorPointer)
 27.1848 +    #define glWindowPos2d GLEGetCurrentFunction(glWindowPos2d)
 27.1849 +    #define glWindowPos2dv GLEGetCurrentFunction(glWindowPos2dv)
 27.1850 +    #define glWindowPos2f GLEGetCurrentFunction(glWindowPos2f)
 27.1851 +    #define glWindowPos2fv GLEGetCurrentFunction(glWindowPos2fv)
 27.1852 +    #define glWindowPos2i GLEGetCurrentFunction(glWindowPos2i)
 27.1853 +    #define glWindowPos2iv GLEGetCurrentFunction(glWindowPos2iv)
 27.1854 +    #define glWindowPos2s GLEGetCurrentFunction(glWindowPos2s)
 27.1855 +    #define glWindowPos2sv GLEGetCurrentFunction(glWindowPos2sv)
 27.1856 +    #define glWindowPos3d GLEGetCurrentFunction(glWindowPos3d)
 27.1857 +    #define glWindowPos3dv GLEGetCurrentFunction(glWindowPos3dv)
 27.1858 +    #define glWindowPos3f GLEGetCurrentFunction(glWindowPos3f)
 27.1859 +    #define glWindowPos3fv GLEGetCurrentFunction(glWindowPos3fv)
 27.1860 +    #define glWindowPos3i GLEGetCurrentFunction(glWindowPos3i)
 27.1861 +    #define glWindowPos3iv GLEGetCurrentFunction(glWindowPos3iv)
 27.1862 +    #define glWindowPos3s GLEGetCurrentFunction(glWindowPos3s)
 27.1863 +    #define glWindowPos3sv GLEGetCurrentFunction(glWindowPos3sv)
 27.1864 +
 27.1865 +#endif // GL_VERSION_1_4
 27.1866 +
 27.1867 +
 27.1868 +
 27.1869 +#ifndef GL_VERSION_1_5
 27.1870 +    #define GL_VERSION_1_5 1
 27.1871 +
 27.1872 +    #define GL_CURRENT_FOG_COORD GL_CURRENT_FOG_COORDINATE
 27.1873 +    #define GL_FOG_COORD GL_FOG_COORDINATE
 27.1874 +    #define GL_FOG_COORD_ARRAY GL_FOG_COORDINATE_ARRAY
 27.1875 +    #define GL_FOG_COORD_ARRAY_BUFFER_BINDING GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING
 27.1876 +    #define GL_FOG_COORD_ARRAY_POINTER GL_FOG_COORDINATE_ARRAY_POINTER
 27.1877 +    #define GL_FOG_COORD_ARRAY_STRIDE GL_FOG_COORDINATE_ARRAY_STRIDE
 27.1878 +    #define GL_FOG_COORD_ARRAY_TYPE GL_FOG_COORDINATE_ARRAY_TYPE
 27.1879 +    #define GL_FOG_COORD_SRC GL_FOG_COORDINATE_SOURCE
 27.1880 +    #define GL_SRC0_ALPHA GL_SOURCE0_ALPHA
 27.1881 +    #define GL_SRC0_RGB GL_SOURCE0_RGB
 27.1882 +    #define GL_SRC1_ALPHA GL_SOURCE1_ALPHA
 27.1883 +    #define GL_SRC1_RGB GL_SOURCE1_RGB
 27.1884 +    #define GL_SRC2_ALPHA GL_SOURCE2_ALPHA
 27.1885 +    #define GL_SRC2_RGB GL_SOURCE2_RGB
 27.1886 +    #define GL_BUFFER_SIZE 0x8764
 27.1887 +    #define GL_BUFFER_USAGE 0x8765
 27.1888 +    #define GL_QUERY_COUNTER_BITS 0x8864
 27.1889 +    #define GL_CURRENT_QUERY 0x8865
 27.1890 +    #define GL_QUERY_RESULT 0x8866
 27.1891 +    #define GL_QUERY_RESULT_AVAILABLE 0x8867
 27.1892 +    #define GL_ARRAY_BUFFER 0x8892
 27.1893 +    #define GL_ELEMENT_ARRAY_BUFFER 0x8893
 27.1894 +    #define GL_ARRAY_BUFFER_BINDING 0x8894
 27.1895 +    #define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895
 27.1896 +    #define GL_VERTEX_ARRAY_BUFFER_BINDING 0x8896
 27.1897 +    #define GL_NORMAL_ARRAY_BUFFER_BINDING 0x8897
 27.1898 +    #define GL_COLOR_ARRAY_BUFFER_BINDING 0x8898
 27.1899 +    #define GL_INDEX_ARRAY_BUFFER_BINDING 0x8899
 27.1900 +    #define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING 0x889A
 27.1901 +    #define GL_EDGE_FLAG_ARRAY_BUFFER_BINDING 0x889B
 27.1902 +    #define GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING 0x889C
 27.1903 +    #define GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING 0x889D
 27.1904 +    #define GL_WEIGHT_ARRAY_BUFFER_BINDING 0x889E
 27.1905 +    #define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F
 27.1906 +    #define GL_READ_ONLY 0x88B8
 27.1907 +    #define GL_WRITE_ONLY 0x88B9
 27.1908 +    #define GL_READ_WRITE 0x88BA
 27.1909 +    #define GL_BUFFER_ACCESS 0x88BB
 27.1910 +    #define GL_BUFFER_MAPPED 0x88BC
 27.1911 +    #define GL_BUFFER_MAP_POINTER 0x88BD
 27.1912 +    #define GL_STREAM_DRAW 0x88E0
 27.1913 +    #define GL_STREAM_READ 0x88E1
 27.1914 +    #define GL_STREAM_COPY 0x88E2
 27.1915 +    #define GL_STATIC_DRAW 0x88E4
 27.1916 +    #define GL_STATIC_READ 0x88E5
 27.1917 +    #define GL_STATIC_COPY 0x88E6
 27.1918 +    #define GL_DYNAMIC_DRAW 0x88E8
 27.1919 +    #define GL_DYNAMIC_READ 0x88E9
 27.1920 +    #define GL_DYNAMIC_COPY 0x88EA
 27.1921 +    #define GL_SAMPLES_PASSED 0x8914
 27.1922 +
 27.1923 +    typedef ptrdiff_t GLintptr;
 27.1924 +    typedef ptrdiff_t GLsizeiptr;
 27.1925 +
 27.1926 +    typedef void      (GLAPIENTRY * PFNGLBEGINQUERYPROC) (GLenum target, GLuint id);
 27.1927 +    typedef void      (GLAPIENTRY * PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer);
 27.1928 +    typedef void      (GLAPIENTRY * PFNGLBUFFERDATAPROC) (GLenum target, GLsizeiptr size, const void* data, GLenum usage);
 27.1929 +    typedef void      (GLAPIENTRY * PFNGLBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, const void* data);
 27.1930 +    typedef void      (GLAPIENTRY * PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint* buffers);
 27.1931 +    typedef void      (GLAPIENTRY * PFNGLDELETEQUERIESPROC) (GLsizei n, const GLuint* ids);
 27.1932 +    typedef void      (GLAPIENTRY * PFNGLENDQUERYPROC) (GLenum target);
 27.1933 +    typedef void      (GLAPIENTRY * PFNGLGENBUFFERSPROC) (GLsizei n, GLuint* buffers);
 27.1934 +    typedef void      (GLAPIENTRY * PFNGLGENQUERIESPROC) (GLsizei n, GLuint* ids);
 27.1935 +    typedef void      (GLAPIENTRY * PFNGLGETBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint* params);
 27.1936 +    typedef void      (GLAPIENTRY * PFNGLGETBUFFERPOINTERVPROC) (GLenum target, GLenum pname, void** params);
 27.1937 +    typedef void      (GLAPIENTRY * PFNGLGETBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, void* data);
 27.1938 +    typedef void      (GLAPIENTRY * PFNGLGETQUERYOBJECTIVPROC) (GLuint id, GLenum pname, GLint* params);
 27.1939 +    typedef void      (GLAPIENTRY * PFNGLGETQUERYOBJECTUIVPROC) (GLuint id, GLenum pname, GLuint* params);
 27.1940 +    typedef void      (GLAPIENTRY * PFNGLGETQUERYIVPROC) (GLenum target, GLenum pname, GLint* params);
 27.1941 +    typedef GLboolean (GLAPIENTRY * PFNGLISBUFFERPROC) (GLuint buffer);
 27.1942 +    typedef GLboolean (GLAPIENTRY * PFNGLISQUERYPROC) (GLuint id);
 27.1943 +    typedef void*     (GLAPIENTRY * PFNGLMAPBUFFERPROC) (GLenum target, GLenum access);
 27.1944 +    typedef GLboolean (GLAPIENTRY * PFNGLUNMAPBUFFERPROC) (GLenum target);
 27.1945 +
 27.1946 +    #define glBeginQuery GLEGetCurrentFunction(glBeginQuery)
 27.1947 +    #define glBindBuffer GLEGetCurrentFunction(glBindBuffer)
 27.1948 +    #define glBufferData GLEGetCurrentFunction(glBufferData)
 27.1949 +    #define glBufferSubData GLEGetCurrentFunction(glBufferSubData)
 27.1950 +    #define glDeleteBuffers GLEGetCurrentFunction(glDeleteBuffers)
 27.1951 +    #define glDeleteQueries GLEGetCurrentFunction(glDeleteQueries)
 27.1952 +    #define glEndQuery GLEGetCurrentFunction(glEndQuery)
 27.1953 +    #define glGenBuffers GLEGetCurrentFunction(glGenBuffers)
 27.1954 +    #define glGenQueries GLEGetCurrentFunction(glGenQueries)
 27.1955 +    #define glGetBufferParameteriv GLEGetCurrentFunction(glGetBufferParameteriv)
 27.1956 +    #define glGetBufferPointerv GLEGetCurrentFunction(glGetBufferPointerv)
 27.1957 +    #define glGetBufferSubData GLEGetCurrentFunction(glGetBufferSubData)
 27.1958 +    #define glGetQueryObjectiv GLEGetCurrentFunction(glGetQueryObjectiv)
 27.1959 +    #define glGetQueryObjectuiv GLEGetCurrentFunction(glGetQueryObjectuiv)
 27.1960 +    #define glGetQueryiv GLEGetCurrentFunction(glGetQueryiv)
 27.1961 +    #define glIsBuffer GLEGetCurrentFunction(glIsBuffer)
 27.1962 +    #define glIsQuery GLEGetCurrentFunction(glIsQuery)
 27.1963 +    #define glMapBuffer GLEGetCurrentFunction(glMapBuffer)
 27.1964 +    #define glUnmapBuffer GLEGetCurrentFunction(glUnmapBuffer)
 27.1965 +
 27.1966 +#endif // GL_VERSION_1_5
 27.1967 +
 27.1968 +
 27.1969 +
 27.1970 +
 27.1971 +#ifndef GL_VERSION_2_0
 27.1972 +    #define GL_VERSION_2_0 1
 27.1973 +
 27.1974 +    #define GL_BLEND_EQUATION_RGB GL_BLEND_EQUATION
 27.1975 +    #define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622
 27.1976 +    #define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623
 27.1977 +    #define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624
 27.1978 +    #define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625
 27.1979 +    #define GL_CURRENT_VERTEX_ATTRIB 0x8626
 27.1980 +    #define GL_VERTEX_PROGRAM_POINT_SIZE 0x8642
 27.1981 +    #define GL_VERTEX_PROGRAM_TWO_SIDE 0x8643
 27.1982 +    #define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645
 27.1983 +    #define GL_STENCIL_BACK_FUNC 0x8800
 27.1984 +    #define GL_STENCIL_BACK_FAIL 0x8801
 27.1985 +    #define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802
 27.1986 +    #define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803
 27.1987 +    #define GL_MAX_DRAW_BUFFERS 0x8824
 27.1988 +    #define GL_DRAW_BUFFER0 0x8825
 27.1989 +    #define GL_DRAW_BUFFER1 0x8826
 27.1990 +    #define GL_DRAW_BUFFER2 0x8827
 27.1991 +    #define GL_DRAW_BUFFER3 0x8828
 27.1992 +    #define GL_DRAW_BUFFER4 0x8829
 27.1993 +    #define GL_DRAW_BUFFER5 0x882A
 27.1994 +    #define GL_DRAW_BUFFER6 0x882B
 27.1995 +    #define GL_DRAW_BUFFER7 0x882C
 27.1996 +    #define GL_DRAW_BUFFER8 0x882D
 27.1997 +    #define GL_DRAW_BUFFER9 0x882E
 27.1998 +    #define GL_DRAW_BUFFER10 0x882F
 27.1999 +    #define GL_DRAW_BUFFER11 0x8830
 27.2000 +    #define GL_DRAW_BUFFER12 0x8831
 27.2001 +    #define GL_DRAW_BUFFER13 0x8832
 27.2002 +    #define GL_DRAW_BUFFER14 0x8833
 27.2003 +    #define GL_DRAW_BUFFER15 0x8834
 27.2004 +    #define GL_BLEND_EQUATION_ALPHA 0x883D
 27.2005 +    #define GL_POINT_SPRITE 0x8861
 27.2006 +    #define GL_COORD_REPLACE 0x8862
 27.2007 +    #define GL_MAX_VERTEX_ATTRIBS 0x8869
 27.2008 +    #define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A
 27.2009 +    #define GL_MAX_TEXTURE_COORDS 0x8871
 27.2010 +    #define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872
 27.2011 +    #define GL_FRAGMENT_SHADER 0x8B30
 27.2012 +    #define GL_VERTEX_SHADER 0x8B31
 27.2013 +    #define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS 0x8B49
 27.2014 +    #define GL_MAX_VERTEX_UNIFORM_COMPONENTS 0x8B4A
 27.2015 +    #define GL_MAX_VARYING_FLOATS 0x8B4B
 27.2016 +    #define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C
 27.2017 +    #define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D
 27.2018 +    #define GL_SHADER_TYPE 0x8B4F
 27.2019 +    #define GL_FLOAT_VEC2 0x8B50
 27.2020 +    #define GL_FLOAT_VEC3 0x8B51
 27.2021 +    #define GL_FLOAT_VEC4 0x8B52
 27.2022 +    #define GL_INT_VEC2 0x8B53
 27.2023 +    #define GL_INT_VEC3 0x8B54
 27.2024 +    #define GL_INT_VEC4 0x8B55
 27.2025 +    #define GL_BOOL 0x8B56
 27.2026 +    #define GL_BOOL_VEC2 0x8B57
 27.2027 +    #define GL_BOOL_VEC3 0x8B58
 27.2028 +    #define GL_BOOL_VEC4 0x8B59
 27.2029 +    #define GL_FLOAT_MAT2 0x8B5A
 27.2030 +    #define GL_FLOAT_MAT3 0x8B5B
 27.2031 +    #define GL_FLOAT_MAT4 0x8B5C
 27.2032 +    #define GL_SAMPLER_1D 0x8B5D
 27.2033 +    #define GL_SAMPLER_2D 0x8B5E
 27.2034 +    #define GL_SAMPLER_3D 0x8B5F
 27.2035 +    #define GL_SAMPLER_CUBE 0x8B60
 27.2036 +    #define GL_SAMPLER_1D_SHADOW 0x8B61
 27.2037 +    #define GL_SAMPLER_2D_SHADOW 0x8B62
 27.2038 +    #define GL_DELETE_STATUS 0x8B80
 27.2039 +    #define GL_COMPILE_STATUS 0x8B81
 27.2040 +    #define GL_LINK_STATUS 0x8B82
 27.2041 +    #define GL_VALIDATE_STATUS 0x8B83
 27.2042 +    #define GL_INFO_LOG_LENGTH 0x8B84
 27.2043 +    #define GL_ATTACHED_SHADERS 0x8B85
 27.2044 +    #define GL_ACTIVE_UNIFORMS 0x8B86
 27.2045 +    #define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87
 27.2046 +    #define GL_SHADER_SOURCE_LENGTH 0x8B88
 27.2047 +    #define GL_ACTIVE_ATTRIBUTES 0x8B89
 27.2048 +    #define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A
 27.2049 +    #define GL_FRAGMENT_SHADER_DERIVATIVE_HINT 0x8B8B
 27.2050 +    #define GL_SHADING_LANGUAGE_VERSION 0x8B8C
 27.2051 +    #define GL_CURRENT_PROGRAM 0x8B8D
 27.2052 +    #define GL_POINT_SPRITE_COORD_ORIGIN 0x8CA0
 27.2053 +    #define GL_LOWER_LEFT 0x8CA1
 27.2054 +    #define GL_UPPER_LEFT 0x8CA2
 27.2055 +    #define GL_STENCIL_BACK_REF 0x8CA3
 27.2056 +    #define GL_STENCIL_BACK_VALUE_MASK 0x8CA4
 27.2057 +    #define GL_STENCIL_BACK_WRITEMASK 0x8CA5
 27.2058 +
 27.2059 +    typedef void (GLAPIENTRY * PFNGLATTACHSHADERPROC) (GLuint program, GLuint shader);
 27.2060 +    typedef void (GLAPIENTRY * PFNGLBINDATTRIBLOCATIONPROC) (GLuint program, GLuint index, const GLchar* name);
 27.2061 +    typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONSEPARATEPROC) (GLenum modeRGB, GLenum modeAlpha);
 27.2062 +    typedef void (GLAPIENTRY * PFNGLCOMPILESHADERPROC) (GLuint shader);
 27.2063 +    typedef GLuint (GLAPIENTRY * PFNGLCREATEPROGRAMPROC) (void);
 27.2064 +    typedef GLuint (GLAPIENTRY * PFNGLCREATESHADERPROC) (GLenum type);
 27.2065 +    typedef void (GLAPIENTRY * PFNGLDELETEPROGRAMPROC) (GLuint program);
 27.2066 +    typedef void (GLAPIENTRY * PFNGLDELETESHADERPROC) (GLuint shader);
 27.2067 +    typedef void (GLAPIENTRY * PFNGLDETACHSHADERPROC) (GLuint program, GLuint shader);
 27.2068 +    typedef void (GLAPIENTRY * PFNGLDISABLEVERTEXATTRIBARRAYPROC) (GLuint index);
 27.2069 +    typedef void (GLAPIENTRY * PFNGLDRAWBUFFERSPROC) (GLsizei n, const GLenum* bufs);
 27.2070 +    typedef void (GLAPIENTRY * PFNGLENABLEVERTEXATTRIBARRAYPROC) (GLuint index);
 27.2071 +    typedef void (GLAPIENTRY * PFNGLGETACTIVEATTRIBPROC) (GLuint program, GLuint index, GLsizei maxLength, GLsizei* length, GLint* size, GLenum* type, GLchar* name);
 27.2072 +    typedef void (GLAPIENTRY * PFNGLGETACTIVEUNIFORMPROC) (GLuint program, GLuint index, GLsizei maxLength, GLsizei* length, GLint* size, GLenum* type, GLchar* name);
 27.2073 +    typedef void (GLAPIENTRY * PFNGLGETATTACHEDSHADERSPROC) (GLuint program, GLsizei maxCount, GLsizei* count, GLuint* shaders);
 27.2074 +    typedef GLint (GLAPIENTRY * PFNGLGETATTRIBLOCATIONPROC) (GLuint program, const GLchar* name);
 27.2075 +    typedef void (GLAPIENTRY * PFNGLGETPROGRAMINFOLOGPROC) (GLuint program, GLsizei bufSize, GLsizei* length, GLchar* infoLog);
 27.2076 +    typedef void (GLAPIENTRY * PFNGLGETPROGRAMIVPROC) (GLuint program, GLenum pname, GLint* param);
 27.2077 +    typedef void (GLAPIENTRY * PFNGLGETSHADERINFOLOGPROC) (GLuint shader, GLsizei bufSize, GLsizei* length, GLchar* infoLog);
 27.2078 +    typedef void (GLAPIENTRY * PFNGLGETSHADERSOURCEPROC) (GLuint obj, GLsizei maxLength, GLsizei* length, GLchar* source);
 27.2079 +    typedef void (GLAPIENTRY * PFNGLGETSHADERIVPROC) (GLuint shader, GLenum pname, GLint* param);
 27.2080 +    typedef GLint     (GLAPIENTRY * PFNGLGETUNIFORMLOCATIONPROC) (GLuint program, const GLchar* name);
 27.2081 +    typedef void      (GLAPIENTRY * PFNGLGETUNIFORMFVPROC) (GLuint program, GLint location, GLfloat* params);
 27.2082 +    typedef void      (GLAPIENTRY * PFNGLGETUNIFORMIVPROC) (GLuint program, GLint location, GLint* params);
 27.2083 +    typedef void      (GLAPIENTRY * PFNGLGETVERTEXATTRIBPOINTERVPROC) (GLuint index, GLenum pname, void** pointer);
 27.2084 +    typedef void      (GLAPIENTRY * PFNGLGETVERTEXATTRIBDVPROC) (GLuint index, GLenum pname, GLdouble* params);
 27.2085 +    typedef void      (GLAPIENTRY * PFNGLGETVERTEXATTRIBFVPROC) (GLuint index, GLenum pname, GLfloat* params);
 27.2086 +    typedef void      (GLAPIENTRY * PFNGLGETVERTEXATTRIBIVPROC) (GLuint index, GLenum pname, GLint* params);
 27.2087 +    typedef GLboolean (GLAPIENTRY * PFNGLISPROGRAMPROC) (GLuint program);
 27.2088 +    typedef GLboolean (GLAPIENTRY * PFNGLISSHADERPROC) (GLuint shader);
 27.2089 +    typedef void      (GLAPIENTRY * PFNGLLINKPROGRAMPROC) (GLuint program);
 27.2090 +    typedef void      (GLAPIENTRY * PFNGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const GLchar *const* string, const GLint* length);
 27.2091 +    typedef void      (GLAPIENTRY * PFNGLSTENCILFUNCSEPARATEPROC) (GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask);
 27.2092 +    typedef void      (GLAPIENTRY * PFNGLSTENCILMASKSEPARATEPROC) (GLenum face, GLuint mask);
 27.2093 +    typedef void      (GLAPIENTRY * PFNGLSTENCILOPSEPARATEPROC) (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
 27.2094 +    typedef void      (GLAPIENTRY * PFNGLUNIFORM1FPROC) (GLint location, GLfloat v0);
 27.2095 +    typedef void      (GLAPIENTRY * PFNGLUNIFORM1FVPROC) (GLint location, GLsizei count, const GLfloat* value);
 27.2096 +    typedef void      (GLAPIENTRY * PFNGLUNIFORM1IPROC) (GLint location, GLint v0);
 27.2097 +    typedef void (GLAPIENTRY * PFNGLUNIFORM1IVPROC) (GLint location, GLsizei count, const GLint* value);
 27.2098 +    typedef void (GLAPIENTRY * PFNGLUNIFORM2FPROC) (GLint location, GLfloat v0, GLfloat v1);
 27.2099 +    typedef void (GLAPIENTRY * PFNGLUNIFORM2FVPROC) (GLint location, GLsizei count, const GLfloat* value);
 27.2100 +    typedef void (GLAPIENTRY * PFNGLUNIFORM2IPROC) (GLint location, GLint v0, GLint v1);
 27.2101 +    typedef void (GLAPIENTRY * PFNGLUNIFORM2IVPROC) (GLint location, GLsizei count, const GLint* value);
 27.2102 +    typedef void (GLAPIENTRY * PFNGLUNIFORM3FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
 27.2103 +    typedef void (GLAPIENTRY * PFNGLUNIFORM3FVPROC) (GLint location, GLsizei count, const GLfloat* value);
 27.2104 +    typedef void (GLAPIENTRY * PFNGLUNIFORM3IPROC) (GLint location, GLint v0, GLint v1, GLint v2);
 27.2105 +    typedef void (GLAPIENTRY * PFNGLUNIFORM3IVPROC) (GLint location, GLsizei count, const GLint* value);
 27.2106 +    typedef void (GLAPIENTRY * PFNGLUNIFORM4FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
 27.2107 +    typedef void (GLAPIENTRY * PFNGLUNIFORM4FVPROC) (GLint location, GLsizei count, const GLfloat* value);
 27.2108 +    typedef void (GLAPIENTRY * PFNGLUNIFORM4IPROC) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
 27.2109 +    typedef void (GLAPIENTRY * PFNGLUNIFORM4IVPROC) (GLint location, GLsizei count, const GLint* value);
 27.2110 +    typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
 27.2111 +    typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
 27.2112 +    typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
 27.2113 +    typedef void (GLAPIENTRY * PFNGLUSEPROGRAMPROC) (GLuint program);
 27.2114 +    typedef void (GLAPIENTRY * PFNGLVALIDATEPROGRAMPROC) (GLuint program);
 27.2115 +    typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1DPROC) (GLuint index, GLdouble x);
 27.2116 +    typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1DVPROC) (GLuint index, const GLdouble* v);
 27.2117 +    typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1FPROC) (GLuint index, GLfloat x);
 27.2118 +    typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1FVPROC) (GLuint index, const GLfloat* v);
 27.2119 +    typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1SPROC) (GLuint index, GLshort x);
 27.2120 +    typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1SVPROC) (GLuint index, const GLshort* v);
 27.2121 +    typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2DPROC) (GLuint index, GLdouble x, GLdouble y);
 27.2122 +    typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2DVPROC) (GLuint index, const GLdouble* v);
 27.2123 +    typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2FPROC) (GLuint index, GLfloat x, GLfloat y);
 27.2124 +    typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2FVPROC) (GLuint index, const GLfloat* v);
 27.2125 +    typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2SPROC) (GLuint index, GLshort x, GLshort y);
 27.2126 +    typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2SVPROC) (GLuint index, const GLshort* v);
 27.2127 +    typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z);
 27.2128 +    typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3DVPROC) (GLuint index, const GLdouble* v);
 27.2129 +    typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z);
 27.2130 +    typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3FVPROC) (GLuint index, const GLfloat* v);
 27.2131 +    typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3SPROC) (GLuint index, GLshort x, GLshort y, GLshort z);
 27.2132 +    typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3SVPROC) (GLuint index, const GLshort* v);
 27.2133 +    typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NBVPROC) (GLuint index, const GLbyte* v);
 27.2134 +    typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NIVPROC) (GLuint index, const GLint* v);
 27.2135 +    typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NSVPROC) (GLuint index, const GLshort* v);
 27.2136 +    typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NUBPROC) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w);
 27.2137 +    typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NUBVPROC) (GLuint index, const GLubyte* v);
 27.2138 +    typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NUIVPROC) (GLuint index, const GLuint* v);
 27.2139 +    typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NUSVPROC) (GLuint index, const GLushort* v);
 27.2140 +    typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4BVPROC) (GLuint index, const GLbyte* v);
 27.2141 +    typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
 27.2142 +    typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4DVPROC) (GLuint index, const GLdouble* v);
 27.2143 +    typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
 27.2144 +    typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4FVPROC) (GLuint index, const GLfloat* v);
 27.2145 +    typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4IVPROC) (GLuint index, const GLint* v);
 27.2146 +    typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4SPROC) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w);
 27.2147 +    typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4SVPROC) (GLuint index, const GLshort* v);
 27.2148 +    typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4UBVPROC) (GLuint index, const GLubyte* v);
 27.2149 +    typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4UIVPROC) (GLuint index, const GLuint* v);
 27.2150 +    typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4USVPROC) (GLuint index, const GLushort* v);
 27.2151 +    typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* pointer);
 27.2152 +
 27.2153 +    #define glAttachShader GLEGetCurrentFunction(glAttachShader)
 27.2154 +    #define glBindAttribLocation GLEGetCurrentFunction(glBindAttribLocation)
 27.2155 +    #define glBlendEquationSeparate GLEGetCurrentFunction(glBlendEquationSeparate)
 27.2156 +    #define glCompileShader GLEGetCurrentFunction(glCompileShader)
 27.2157 +    #define glCreateProgram GLEGetCurrentFunction(glCreateProgram)
 27.2158 +    #define glCreateShader GLEGetCurrentFunction(glCreateShader)
 27.2159 +    #define glDeleteProgram GLEGetCurrentFunction(glDeleteProgram)
 27.2160 +    #define glDeleteShader GLEGetCurrentFunction(glDeleteShader)
 27.2161 +    #define glDetachShader GLEGetCurrentFunction(glDetachShader)
 27.2162 +    #define glDisableVertexAttribArray GLEGetCurrentFunction(glDisableVertexAttribArray)
 27.2163 +    #define glDrawBuffers GLEGetCurrentFunction(glDrawBuffers)
 27.2164 +    #define glEnableVertexAttribArray GLEGetCurrentFunction(glEnableVertexAttribArray)
 27.2165 +    #define glGetActiveAttrib GLEGetCurrentFunction(glGetActiveAttrib)
 27.2166 +    #define glGetActiveUniform GLEGetCurrentFunction(glGetActiveUniform)
 27.2167 +    #define glGetAttachedShaders GLEGetCurrentFunction(glGetAttachedShaders)
 27.2168 +    #define glGetAttribLocation GLEGetCurrentFunction(glGetAttribLocation)
 27.2169 +    #define glGetProgramInfoLog GLEGetCurrentFunction(glGetProgramInfoLog)
 27.2170 +    #define glGetProgramiv GLEGetCurrentFunction(glGetProgramiv)
 27.2171 +    #define glGetShaderInfoLog GLEGetCurrentFunction(glGetShaderInfoLog)
 27.2172 +    #define glGetShaderSource GLEGetCurrentFunction(glGetShaderSource)
 27.2173 +    #define glGetShaderiv GLEGetCurrentFunction(glGetShaderiv)
 27.2174 +    #define glGetUniformLocation GLEGetCurrentFunction(glGetUniformLocation)
 27.2175 +    #define glGetUniformfv GLEGetCurrentFunction(glGetUniformfv)
 27.2176 +    #define glGetUniformiv GLEGetCurrentFunction(glGetUniformiv)
 27.2177 +    #define glGetVertexAttribPointerv GLEGetCurrentFunction(glGetVertexAttribPointerv)
 27.2178 +    #define glGetVertexAttribdv GLEGetCurrentFunction(glGetVertexAttribdv)
 27.2179 +    #define glGetVertexAttribfv GLEGetCurrentFunction(glGetVertexAttribfv)
 27.2180 +    #define glGetVertexAttribiv GLEGetCurrentFunction(glGetVertexAttribiv)
 27.2181 +    #define glIsProgram GLEGetCurrentFunction(glIsProgram)
 27.2182 +    #define glIsShader GLEGetCurrentFunction(glIsShader)
 27.2183 +    #define glLinkProgram GLEGetCurrentFunction(glLinkProgram)
 27.2184 +    #define glShaderSource GLEGetCurrentFunction(glShaderSource)
 27.2185 +    #define glStencilFuncSeparate GLEGetCurrentFunction(glStencilFuncSeparate)
 27.2186 +    #define glStencilMaskSeparate GLEGetCurrentFunction(glStencilMaskSeparate)
 27.2187 +    #define glStencilOpSeparate GLEGetCurrentFunction(glStencilOpSeparate)
 27.2188 +    #define glUniform1f GLEGetCurrentFunction(glUniform1f)
 27.2189 +    #define glUniform1fv GLEGetCurrentFunction(glUniform1fv)
 27.2190 +    #define glUniform1i GLEGetCurrentFunction(glUniform1i)
 27.2191 +    #define glUniform1iv GLEGetCurrentFunction(glUniform1iv)
 27.2192 +    #define glUniform2f GLEGetCurrentFunction(glUniform2f)
 27.2193 +    #define glUniform2fv GLEGetCurrentFunction(glUniform2fv)
 27.2194 +    #define glUniform2i GLEGetCurrentFunction(glUniform2i)
 27.2195 +    #define glUniform2iv GLEGetCurrentFunction(glUniform2iv)
 27.2196 +    #define glUniform3f GLEGetCurrentFunction(glUniform3f)
 27.2197 +    #define glUniform3fv GLEGetCurrentFunction(glUniform3fv)
 27.2198 +    #define glUniform3i GLEGetCurrentFunction(glUniform3i)
 27.2199 +    #define glUniform3iv GLEGetCurrentFunction(glUniform3iv)
 27.2200 +    #define glUniform4f GLEGetCurrentFunction(glUniform4f)
 27.2201 +    #define glUniform4fv GLEGetCurrentFunction(glUniform4fv)
 27.2202 +    #define glUniform4i GLEGetCurrentFunction(glUniform4i)
 27.2203 +    #define glUniform4iv GLEGetCurrentFunction(glUniform4iv)
 27.2204 +    #define glUniformMatrix2fv GLEGetCurrentFunction(glUniformMatrix2fv)
 27.2205 +    #define glUniformMatrix3fv GLEGetCurrentFunction(glUniformMatrix3fv)
 27.2206 +    #define glUniformMatrix4fv GLEGetCurrentFunction(glUniformMatrix4fv)
 27.2207 +    #define glUseProgram GLEGetCurrentFunction(glUseProgram)
 27.2208 +    #define glValidateProgram GLEGetCurrentFunction(glValidateProgram)
 27.2209 +    #define glVertexAttrib1d GLEGetCurrentFunction(glVertexAttrib1d)
 27.2210 +    #define glVertexAttrib1dv GLEGetCurrentFunction(glVertexAttrib1dv)
 27.2211 +    #define glVertexAttrib1f GLEGetCurrentFunction(glVertexAttrib1f)
 27.2212 +    #define glVertexAttrib1fv GLEGetCurrentFunction(glVertexAttrib1fv)
 27.2213 +    #define glVertexAttrib1s GLEGetCurrentFunction(glVertexAttrib1s)
 27.2214 +    #define glVertexAttrib1sv GLEGetCurrentFunction(glVertexAttrib1sv)
 27.2215 +    #define glVertexAttrib2d GLEGetCurrentFunction(glVertexAttrib2d)
 27.2216 +    #define glVertexAttrib2dv GLEGetCurrentFunction(glVertexAttrib2dv)
 27.2217 +    #define glVertexAttrib2f GLEGetCurrentFunction(glVertexAttrib2f)
 27.2218 +    #define glVertexAttrib2fv GLEGetCurrentFunction(glVertexAttrib2fv)
 27.2219 +    #define glVertexAttrib2s GLEGetCurrentFunction(glVertexAttrib2s)
 27.2220 +    #define glVertexAttrib2sv GLEGetCurrentFunction(glVertexAttrib2sv)
 27.2221 +    #define glVertexAttrib3d GLEGetCurrentFunction(glVertexAttrib3d)
 27.2222 +    #define glVertexAttrib3dv GLEGetCurrentFunction(glVertexAttrib3dv)
 27.2223 +    #define glVertexAttrib3f GLEGetCurrentFunction(glVertexAttrib3f)
 27.2224 +    #define glVertexAttrib3fv GLEGetCurrentFunction(glVertexAttrib3fv)
 27.2225 +    #define glVertexAttrib3s GLEGetCurrentFunction(glVertexAttrib3s)
 27.2226 +    #define glVertexAttrib3sv GLEGetCurrentFunction(glVertexAttrib3sv)
 27.2227 +    #define glVertexAttrib4Nbv GLEGetCurrentFunction(glVertexAttrib4Nbv)
 27.2228 +    #define glVertexAttrib4Niv GLEGetCurrentFunction(glVertexAttrib4Niv)
 27.2229 +    #define glVertexAttrib4Nsv GLEGetCurrentFunction(glVertexAttrib4Nsv)
 27.2230 +    #define glVertexAttrib4Nub GLEGetCurrentFunction(glVertexAttrib4Nub)
 27.2231 +    #define glVertexAttrib4Nubv GLEGetCurrentFunction(glVertexAttrib4Nubv)
 27.2232 +    #define glVertexAttrib4Nuiv GLEGetCurrentFunction(glVertexAttrib4Nuiv)
 27.2233 +    #define glVertexAttrib4Nusv GLEGetCurrentFunction(glVertexAttrib4Nusv)
 27.2234 +    #define glVertexAttrib4bv GLEGetCurrentFunction(glVertexAttrib4bv)
 27.2235 +    #define glVertexAttrib4d GLEGetCurrentFunction(glVertexAttrib4d)
 27.2236 +    #define glVertexAttrib4dv GLEGetCurrentFunction(glVertexAttrib4dv)
 27.2237 +    #define glVertexAttrib4f GLEGetCurrentFunction(glVertexAttrib4f)
 27.2238 +    #define glVertexAttrib4fv GLEGetCurrentFunction(glVertexAttrib4fv)
 27.2239 +    #define glVertexAttrib4iv GLEGetCurrentFunction(glVertexAttrib4iv)
 27.2240 +    #define glVertexAttrib4s GLEGetCurrentFunction(glVertexAttrib4s)
 27.2241 +    #define glVertexAttrib4sv GLEGetCurrentFunction(glVertexAttrib4sv)
 27.2242 +    #define glVertexAttrib4ubv GLEGetCurrentFunction(glVertexAttrib4ubv)
 27.2243 +    #define glVertexAttrib4uiv GLEGetCurrentFunction(glVertexAttrib4uiv)
 27.2244 +    #define glVertexAttrib4usv GLEGetCurrentFunction(glVertexAttrib4usv)
 27.2245 +    #define glVertexAttribPointer GLEGetCurrentFunction(glVertexAttribPointer)
 27.2246 +
 27.2247 +#endif // GL_VERSION_2_0
 27.2248 +
 27.2249 +
 27.2250 +
 27.2251 +#ifndef GL_VERSION_2_1
 27.2252 +    #define GL_VERSION_2_1 1
 27.2253 +
 27.2254 +    #define GL_CURRENT_RASTER_SECONDARY_COLOR 0x845F
 27.2255 +    #define GL_PIXEL_PACK_BUFFER 0x88EB
 27.2256 +    #define GL_PIXEL_UNPACK_BUFFER 0x88EC
 27.2257 +    #define GL_PIXEL_PACK_BUFFER_BINDING 0x88ED
 27.2258 +    #define GL_PIXEL_UNPACK_BUFFER_BINDING 0x88EF
 27.2259 +    #define GL_FLOAT_MAT2x3 0x8B65
 27.2260 +    #define GL_FLOAT_MAT2x4 0x8B66
 27.2261 +    #define GL_FLOAT_MAT3x2 0x8B67
 27.2262 +    #define GL_FLOAT_MAT3x4 0x8B68
 27.2263 +    #define GL_FLOAT_MAT4x2 0x8B69
 27.2264 +    #define GL_FLOAT_MAT4x3 0x8B6A
 27.2265 +    #define GL_SRGB 0x8C40
 27.2266 +    #define GL_SRGB8 0x8C41
 27.2267 +    #define GL_SRGB_ALPHA 0x8C42
 27.2268 +    #define GL_SRGB8_ALPHA8 0x8C43
 27.2269 +    #define GL_SLUMINANCE_ALPHA 0x8C44
 27.2270 +    #define GL_SLUMINANCE8_ALPHA8 0x8C45
 27.2271 +    #define GL_SLUMINANCE 0x8C46
 27.2272 +    #define GL_SLUMINANCE8 0x8C47
 27.2273 +    #define GL_COMPRESSED_SRGB 0x8C48
 27.2274 +    #define GL_COMPRESSED_SRGB_ALPHA 0x8C49
 27.2275 +    #define GL_COMPRESSED_SLUMINANCE 0x8C4A
 27.2276 +    #define GL_COMPRESSED_SLUMINANCE_ALPHA 0x8C4B
 27.2277 +
 27.2278 +    typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX2X3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
 27.2279 +    typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX2X4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
 27.2280 +    typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX3X2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
 27.2281 +    typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX3X4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
 27.2282 +    typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX4X2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
 27.2283 +    typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX4X3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
 27.2284 +
 27.2285 +    #define glUniformMatrix2x3fv GLEGetCurrentFunction(glUniformMatrix2x3fv)
 27.2286 +    #define glUniformMatrix2x4fv GLEGetCurrentFunction(glUniformMatrix2x4fv)
 27.2287 +    #define glUniformMatrix3x2fv GLEGetCurrentFunction(glUniformMatrix3x2fv)
 27.2288 +    #define glUniformMatrix3x4fv GLEGetCurrentFunction(glUniformMatrix3x4fv)
 27.2289 +    #define glUniformMatrix4x2fv GLEGetCurrentFunction(glUniformMatrix4x2fv)
 27.2290 +    #define glUniformMatrix4x3fv GLEGetCurrentFunction(glUniformMatrix4x3fv)
 27.2291 +
 27.2292 +#endif // GL_VERSION_2_1
 27.2293 +
 27.2294 +
 27.2295 +
 27.2296 +
 27.2297 +#ifndef GL_VERSION_3_0
 27.2298 +    #define GL_VERSION_3_0 1
 27.2299 +
 27.2300 +    #define GL_CLIP_DISTANCE0 GL_CLIP_PLANE0
 27.2301 +    #define GL_CLIP_DISTANCE1 GL_CLIP_PLANE1
 27.2302 +    #define GL_CLIP_DISTANCE2 GL_CLIP_PLANE2
 27.2303 +    #define GL_CLIP_DISTANCE3 GL_CLIP_PLANE3
 27.2304 +    #define GL_CLIP_DISTANCE4 GL_CLIP_PLANE4
 27.2305 +    #define GL_CLIP_DISTANCE5 GL_CLIP_PLANE5
 27.2306 +    #define GL_COMPARE_REF_TO_TEXTURE GL_COMPARE_R_TO_TEXTURE_ARB
 27.2307 +    #define GL_MAX_CLIP_DISTANCES GL_MAX_CLIP_PLANES
 27.2308 +    #define GL_MAX_VARYING_COMPONENTS GL_MAX_VARYING_FLOATS
 27.2309 +    #define GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT 0x0001
 27.2310 +    #define GL_MAJOR_VERSION 0x821B
 27.2311 +    #define GL_MINOR_VERSION 0x821C
 27.2312 +    #define GL_NUM_EXTENSIONS 0x821D
 27.2313 +    #define GL_CONTEXT_FLAGS 0x821E
 27.2314 +    #define GL_DEPTH_BUFFER 0x8223
 27.2315 +    #define GL_STENCIL_BUFFER 0x8224
 27.2316 +    #define GL_RGBA32F 0x8814
 27.2317 +    #define GL_RGB32F 0x8815
 27.2318 +    #define GL_RGBA16F 0x881A
 27.2319 +    #define GL_RGB16F 0x881B
 27.2320 +    #define GL_VERTEX_ATTRIB_ARRAY_INTEGER 0x88FD
 27.2321 +    #define GL_MAX_ARRAY_TEXTURE_LAYERS 0x88FF
 27.2322 +    #define GL_MIN_PROGRAM_TEXEL_OFFSET 0x8904
 27.2323 +    #define GL_MAX_PROGRAM_TEXEL_OFFSET 0x8905
 27.2324 +    #define GL_CLAMP_VERTEX_COLOR 0x891A
 27.2325 +    #define GL_CLAMP_FRAGMENT_COLOR 0x891B
 27.2326 +    #define GL_CLAMP_READ_COLOR 0x891C
 27.2327 +    #define GL_FIXED_ONLY 0x891D
 27.2328 +    #define GL_TEXTURE_RED_TYPE 0x8C10
 27.2329 +    #define GL_TEXTURE_GREEN_TYPE 0x8C11
 27.2330 +    #define GL_TEXTURE_BLUE_TYPE 0x8C12
 27.2331 +    #define GL_TEXTURE_ALPHA_TYPE 0x8C13
 27.2332 +    #define GL_TEXTURE_LUMINANCE_TYPE 0x8C14
 27.2333 +    #define GL_TEXTURE_INTENSITY_TYPE 0x8C15
 27.2334 +    #define GL_TEXTURE_DEPTH_TYPE 0x8C16
 27.2335 +    #define GL_TEXTURE_1D_ARRAY 0x8C18
 27.2336 +    #define GL_PROXY_TEXTURE_1D_ARRAY 0x8C19
 27.2337 +    #define GL_TEXTURE_2D_ARRAY 0x8C1A
 27.2338 +    #define GL_PROXY_TEXTURE_2D_ARRAY 0x8C1B
 27.2339 +    #define GL_TEXTURE_BINDING_1D_ARRAY 0x8C1C
 27.2340 +    #define GL_TEXTURE_BINDING_2D_ARRAY 0x8C1D
 27.2341 +    #define GL_R11F_G11F_B10F 0x8C3A
 27.2342 +    #define GL_UNSIGNED_INT_10F_11F_11F_REV 0x8C3B
 27.2343 +    #define GL_RGB9_E5 0x8C3D
 27.2344 +    #define GL_UNSIGNED_INT_5_9_9_9_REV 0x8C3E
 27.2345 +    #define GL_TEXTURE_SHARED_SIZE 0x8C3F
 27.2346 +    #define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH 0x8C76
 27.2347 +    #define GL_TRANSFORM_FEEDBACK_BUFFER_MODE 0x8C7F
 27.2348 +    #define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS 0x8C80
 27.2349 +    #define GL_TRANSFORM_FEEDBACK_VARYINGS 0x8C83
 27.2350 +    #define GL_TRANSFORM_FEEDBACK_BUFFER_START 0x8C84
 27.2351 +    #define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE 0x8C85
 27.2352 +    #define GL_PRIMITIVES_GENERATED 0x8C87
 27.2353 +    #define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN 0x8C88
 27.2354 +    #define GL_RASTERIZER_DISCARD 0x8C89
 27.2355 +    #define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS 0x8C8A
 27.2356 +    #define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS 0x8C8B
 27.2357 +    #define GL_INTERLEAVED_ATTRIBS 0x8C8C
 27.2358 +    #define GL_SEPARATE_ATTRIBS 0x8C8D
 27.2359 +    #define GL_TRANSFORM_FEEDBACK_BUFFER 0x8C8E
 27.2360 +    #define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING 0x8C8F
 27.2361 +    #define GL_RGBA32UI 0x8D70
 27.2362 +    #define GL_RGB32UI 0x8D71
 27.2363 +    #define GL_RGBA16UI 0x8D76
 27.2364 +    #define GL_RGB16UI 0x8D77
 27.2365 +    #define GL_RGBA8UI 0x8D7C
 27.2366 +    #define GL_RGB8UI 0x8D7D
 27.2367 +    #define GL_RGBA32I 0x8D82
 27.2368 +    #define GL_RGB32I 0x8D83
 27.2369 +    #define GL_RGBA16I 0x8D88
 27.2370 +    #define GL_RGB16I 0x8D89
 27.2371 +    #define GL_RGBA8I 0x8D8E
 27.2372 +    #define GL_RGB8I 0x8D8F
 27.2373 +    #define GL_RED_INTEGER 0x8D94
 27.2374 +    #define GL_GREEN_INTEGER 0x8D95
 27.2375 +    #define GL_BLUE_INTEGER 0x8D96
 27.2376 +    #define GL_ALPHA_INTEGER 0x8D97
 27.2377 +    #define GL_RGB_INTEGER 0x8D98
 27.2378 +    #define GL_RGBA_INTEGER 0x8D99
 27.2379 +    #define GL_BGR_INTEGER 0x8D9A
 27.2380 +    #define GL_BGRA_INTEGER 0x8D9B
 27.2381 +    #define GL_SAMPLER_1D_ARRAY 0x8DC0
 27.2382 +    #define GL_SAMPLER_2D_ARRAY 0x8DC1
 27.2383 +    #define GL_SAMPLER_1D_ARRAY_SHADOW 0x8DC3
 27.2384 +    #define GL_SAMPLER_2D_ARRAY_SHADOW 0x8DC4
 27.2385 +    #define GL_SAMPLER_CUBE_SHADOW 0x8DC5
 27.2386 +    #define GL_UNSIGNED_INT_VEC2 0x8DC6
 27.2387 +    #define GL_UNSIGNED_INT_VEC3 0x8DC7
 27.2388 +    #define GL_UNSIGNED_INT_VEC4 0x8DC8
 27.2389 +    #define GL_INT_SAMPLER_1D 0x8DC9
 27.2390 +    #define GL_INT_SAMPLER_2D 0x8DCA
 27.2391 +    #define GL_INT_SAMPLER_3D 0x8DCB
 27.2392 +    #define GL_INT_SAMPLER_CUBE 0x8DCC
 27.2393 +    #define GL_INT_SAMPLER_1D_ARRAY 0x8DCE
 27.2394 +    #define GL_INT_SAMPLER_2D_ARRAY 0x8DCF
 27.2395 +    #define GL_UNSIGNED_INT_SAMPLER_1D 0x8DD1
 27.2396 +    #define GL_UNSIGNED_INT_SAMPLER_2D 0x8DD2
 27.2397 +    #define GL_UNSIGNED_INT_SAMPLER_3D 0x8DD3
 27.2398 +    #define GL_UNSIGNED_INT_SAMPLER_CUBE 0x8DD4
 27.2399 +    #define GL_UNSIGNED_INT_SAMPLER_1D_ARRAY 0x8DD6
 27.2400 +    #define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY 0x8DD7
 27.2401 +    #define GL_QUERY_WAIT 0x8E13
 27.2402 +    #define GL_QUERY_NO_WAIT 0x8E14
 27.2403 +    #define GL_QUERY_BY_REGION_WAIT 0x8E15
 27.2404 +    #define GL_QUERY_BY_REGION_NO_WAIT 0x8E16
 27.2405 +
 27.2406 +    typedef void (GLAPIENTRY * PFNGLBEGINCONDITIONALRENDERPROC) (GLuint id, GLenum mode);
 27.2407 +    typedef void (GLAPIENTRY * PFNGLBEGINTRANSFORMFEEDBACKPROC) (GLenum primitiveMode);
 27.2408 +    typedef void (GLAPIENTRY * PFNGLBINDFRAGDATALOCATIONPROC) (GLuint program, GLuint colorNumber, const GLchar* name);
 27.2409 +    typedef void (GLAPIENTRY * PFNGLCLAMPCOLORPROC) (GLenum target, GLenum clamp);
 27.2410 +    typedef void (GLAPIENTRY * PFNGLCLEARBUFFERFIPROC) (GLenum buffer, GLint drawBuffer, GLfloat depth, GLint stencil);
 27.2411 +    typedef void (GLAPIENTRY * PFNGLCLEARBUFFERFVPROC) (GLenum buffer, GLint drawBuffer, const GLfloat* value);
 27.2412 +    typedef void (GLAPIENTRY * PFNGLCLEARBUFFERIVPROC) (GLenum buffer, GLint drawBuffer, const GLint* value);
 27.2413 +    typedef void (GLAPIENTRY * PFNGLCLEARBUFFERUIVPROC) (GLenum buffer, GLint drawBuffer, const GLuint* value);
 27.2414 +    typedef void (GLAPIENTRY * PFNGLCOLORMASKIPROC) (GLuint buf, GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
 27.2415 +    typedef void (GLAPIENTRY * PFNGLDISABLEIPROC) (GLenum cap, GLuint index);
 27.2416 +    typedef void (GLAPIENTRY * PFNGLENABLEIPROC) (GLenum cap, GLuint index);
 27.2417 +    typedef void (GLAPIENTRY * PFNGLENDCONDITIONALRENDERPROC) (void);
 27.2418 +    typedef void (GLAPIENTRY * PFNGLENDTRANSFORMFEEDBACKPROC) (void);
 27.2419 +    typedef void (GLAPIENTRY * PFNGLBINDBUFFERRANGEPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
 27.2420 +    typedef void (GLAPIENTRY * PFNGLBINDBUFFERBASEPROC) (GLenum target, GLuint index, GLuint buffer);
 27.2421 +    typedef void (GLAPIENTRY * PFNGLGETBOOLEANI_VPROC) (GLenum pname, GLuint index, GLboolean* data);
 27.2422 +    typedef void (GLAPIENTRY * PFNGLGETINTEGERI_VPROC) (GLenum target, GLuint index, GLint* data);
 27.2423 +    typedef GLint (GLAPIENTRY * PFNGLGETFRAGDATALOCATIONPROC) (GLuint program, const GLchar* name);
 27.2424 +    typedef const GLubyte* (GLAPIENTRY * PFNGLGETSTRINGIPROC) (GLenum name, GLuint index);
 27.2425 +    typedef void (GLAPIENTRY * PFNGLGETTEXPARAMETERIIVPROC) (GLenum target, GLenum pname, GLint* params);
 27.2426 +    typedef void (GLAPIENTRY * PFNGLGETTEXPARAMETERIUIVPROC) (GLenum target, GLenum pname, GLuint* params);
 27.2427 +    typedef void (GLAPIENTRY * PFNGLGETTRANSFORMFEEDBACKVARYINGPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLsizei * size, GLenum * type, GLchar * name);
 27.2428 +    typedef void (GLAPIENTRY * PFNGLGETUNIFORMUIVPROC) (GLuint program, GLint location, GLuint* params);
 27.2429 +    typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBIIVPROC) (GLuint index, GLenum pname, GLint* params);
 27.2430 +    typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBIUIVPROC) (GLuint index, GLenum pname, GLuint* params);
 27.2431 +    typedef GLboolean (GLAPIENTRY * PFNGLISENABLEDIPROC) (GLenum cap, GLuint index);
 27.2432 +    typedef void (GLAPIENTRY * PFNGLTEXPARAMETERIIVPROC) (GLenum target, GLenum pname, const GLint* params);
 27.2433 +    typedef void (GLAPIENTRY * PFNGLTEXPARAMETERIUIVPROC) (GLenum target, GLenum pname, const GLuint* params);
 27.2434 +    typedef void (GLAPIENTRY * PFNGLTRANSFORMFEEDBACKVARYINGSPROC) (GLuint program, GLsizei count, const GLchar *const* varyings, GLenum bufferMode);
 27.2435 +    typedef void (GLAPIENTRY * PFNGLUNIFORM1UIPROC) (GLint location, GLuint v0);
 27.2436 +    typedef void (GLAPIENTRY * PFNGLUNIFORM1UIVPROC) (GLint location, GLsizei count, const GLuint* value);
 27.2437 +    typedef void (GLAPIENTRY * PFNGLUNIFORM2UIPROC) (GLint location, GLuint v0, GLuint v1);
 27.2438 +    typedef void (GLAPIENTRY * PFNGLUNIFORM2UIVPROC) (GLint location, GLsizei count, const GLuint* value);
 27.2439 +    typedef void (GLAPIENTRY * PFNGLUNIFORM3UIPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2);
 27.2440 +    typedef void (GLAPIENTRY * PFNGLUNIFORM3UIVPROC) (GLint location, GLsizei count, const GLuint* value);
 27.2441 +    typedef void (GLAPIENTRY * PFNGLUNIFORM4UIPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
 27.2442 +    typedef void (GLAPIENTRY * PFNGLUNIFORM4UIVPROC) (GLint location, GLsizei count, const GLuint* value);
 27.2443 +    typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI1IPROC) (GLuint index, GLint v0);
 27.2444 +    typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI1IVPROC) (GLuint index, const GLint* v0);
 27.2445 +    typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI1UIPROC) (GLuint index, GLuint v0);
 27.2446 +    typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI1UIVPROC) (GLuint index, const GLuint* v0);
 27.2447 +    typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI2IPROC) (GLuint index, GLint v0, GLint v1);
 27.2448 +    typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI2IVPROC) (GLuint index, const GLint* v0);
 27.2449 +    typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI2UIPROC) (GLuint index, GLuint v0, GLuint v1);
 27.2450 +    typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI2UIVPROC) (GLuint index, const GLuint* v0);
 27.2451 +    typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI3IPROC) (GLuint index, GLint v0, GLint v1, GLint v2);
 27.2452 +    typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI3IVPROC) (GLuint index, const GLint* v0);
 27.2453 +    typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI3UIPROC) (GLuint index, GLuint v0, GLuint v1, GLuint v2);
 27.2454 +    typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI3UIVPROC) (GLuint index, const GLuint* v0);
 27.2455 +    typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4BVPROC) (GLuint index, const GLbyte* v0);
 27.2456 +    typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4IPROC) (GLuint index, GLint v0, GLint v1, GLint v2, GLint v3);
 27.2457 +    typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4IVPROC) (GLuint index, const GLint* v0);
 27.2458 +    typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4SVPROC) (GLuint index, const GLshort* v0);
 27.2459 +    typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4UBVPROC) (GLuint index, const GLubyte* v0);
 27.2460 +    typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4UIPROC) (GLuint index, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
 27.2461 +    typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4UIVPROC) (GLuint index, const GLuint* v0);
 27.2462 +    typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4USVPROC) (GLuint index, const GLushort* v0);
 27.2463 +    typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBIPOINTERPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const void*pointer);
 27.2464 +
 27.2465 +    #define glBeginConditionalRender GLEGetCurrentFunction(glBeginConditionalRender)
 27.2466 +    #define glBeginTransformFeedback GLEGetCurrentFunction(glBeginTransformFeedback)
 27.2467 +    #define glBindFragDataLocation GLEGetCurrentFunction(glBindFragDataLocation)
 27.2468 +    #define glClampColor GLEGetCurrentFunction(glClampColor)
 27.2469 +    #define glClearBufferfi GLEGetCurrentFunction(glClearBufferfi)
 27.2470 +    #define glClearBufferfv GLEGetCurrentFunction(glClearBufferfv)
 27.2471 +    #define glClearBufferiv GLEGetCurrentFunction(glClearBufferiv)
 27.2472 +    #define glClearBufferuiv GLEGetCurrentFunction(glClearBufferuiv)
 27.2473 +    #define glColorMaski GLEGetCurrentFunction(glColorMaski)
 27.2474 +    #define glDisablei GLEGetCurrentFunction(glDisablei)
 27.2475 +    #define glEnablei GLEGetCurrentFunction(glEnablei)
 27.2476 +    #define glEndConditionalRender GLEGetCurrentFunction(glEndConditionalRender)
 27.2477 +    #define glEndTransformFeedback GLEGetCurrentFunction(glEndTransformFeedback)
 27.2478 +    #define glGetBooleani_v GLEGetCurrentFunction(glGetBooleani_v)
 27.2479 +    #define glGetIntegeri_v GLEGetCurrentFunction(glGetIntegeri_v)
 27.2480 +    #define glGetFragDataLocation GLEGetCurrentFunction(glGetFragDataLocation)
 27.2481 +    #define glGetStringi GLEGetCurrentFunction(glGetStringi)
 27.2482 +    #define glGetTexParameterIiv GLEGetCurrentFunction(glGetTexParameterIiv)
 27.2483 +    #define glGetTexParameterIuiv GLEGetCurrentFunction(glGetTexParameterIuiv)
 27.2484 +    #define glGetTransformFeedbackVarying GLEGetCurrentFunction(glGetTransformFeedbackVarying)
 27.2485 +    #define glGetUniformuiv GLEGetCurrentFunction(glGetUniformuiv)
 27.2486 +    #define glGetVertexAttribIiv GLEGetCurrentFunction(glGetVertexAttribIiv)
 27.2487 +    #define glGetVertexAttribIuiv GLEGetCurrentFunction(glGetVertexAttribIuiv)
 27.2488 +    #define glIsEnabledi GLEGetCurrentFunction(glIsEnabledi)
 27.2489 +    #define glTexParameterIiv GLEGetCurrentFunction(glTexParameterIiv)
 27.2490 +    #define glTexParameterIuiv GLEGetCurrentFunction(glTexParameterIuiv)
 27.2491 +    #define glTransformFeedbackVaryings GLEGetCurrentFunction(glTransformFeedbackVaryings)
 27.2492 +    #define glUniform1ui GLEGetCurrentFunction(glUniform1ui)
 27.2493 +    #define glUniform1uiv GLEGetCurrentFunction(glUniform1uiv)
 27.2494 +    #define glUniform2ui GLEGetCurrentFunction(glUniform2ui)
 27.2495 +    #define glUniform2uiv GLEGetCurrentFunction(glUniform2uiv)
 27.2496 +    #define glUniform3ui GLEGetCurrentFunction(glUniform3ui)
 27.2497 +    #define glUniform3uiv GLEGetCurrentFunction(glUniform3uiv)
 27.2498 +    #define glUniform4ui GLEGetCurrentFunction(glUniform4ui)
 27.2499 +    #define glUniform4uiv GLEGetCurrentFunction(glUniform4uiv)
 27.2500 +    #define glVertexAttribI1i GLEGetCurrentFunction(glVertexAttribI1i)
 27.2501 +    #define glVertexAttribI1iv GLEGetCurrentFunction(glVertexAttribI1iv)
 27.2502 +    #define glVertexAttribI1ui GLEGetCurrentFunction(glVertexAttribI1ui)
 27.2503 +    #define glVertexAttribI1uiv GLEGetCurrentFunction(glVertexAttribI1uiv)
 27.2504 +    #define glVertexAttribI2i GLEGetCurrentFunction(glVertexAttribI2i)
 27.2505 +    #define glVertexAttribI2iv GLEGetCurrentFunction(glVertexAttribI2iv)
 27.2506 +    #define glVertexAttribI2ui GLEGetCurrentFunction(glVertexAttribI2ui)
 27.2507 +    #define glVertexAttribI2uiv GLEGetCurrentFunction(glVertexAttribI2uiv)
 27.2508 +    #define glVertexAttribI3i GLEGetCurrentFunction(glVertexAttribI3i)
 27.2509 +    #define glVertexAttribI3iv GLEGetCurrentFunction(glVertexAttribI3iv)
 27.2510 +    #define glVertexAttribI3ui GLEGetCurrentFunction(glVertexAttribI3ui)
 27.2511 +    #define glVertexAttribI3uiv GLEGetCurrentFunction(glVertexAttribI3uiv)
 27.2512 +    #define glVertexAttribI4bv GLEGetCurrentFunction(glVertexAttribI4bv)
 27.2513 +    #define glVertexAttribI4i GLEGetCurrentFunction(glVertexAttribI4i)
 27.2514 +    #define glVertexAttribI4iv GLEGetCurrentFunction(glVertexAttribI4iv)
 27.2515 +    #define glVertexAttribI4sv GLEGetCurrentFunction(glVertexAttribI4sv)
 27.2516 +    #define glVertexAttribI4ubv GLEGetCurrentFunction(glVertexAttribI4ubv)
 27.2517 +    #define glVertexAttribI4ui GLEGetCurrentFunction(glVertexAttribI4ui)
 27.2518 +    #define glVertexAttribI4uiv GLEGetCurrentFunction(glVertexAttribI4uiv)
 27.2519 +    #define glVertexAttribI4usv GLEGetCurrentFunction(glVertexAttribI4usv)
 27.2520 +    #define glVertexAttribIPointer GLEGetCurrentFunction(glVertexAttribIPointer)
 27.2521 +
 27.2522 +#endif // GL_VERSION_3_0
 27.2523 +
 27.2524 +
 27.2525 +
 27.2526 +
 27.2527 +#ifndef GL_VERSION_3_1
 27.2528 +    #define GL_VERSION_3_1 1
 27.2529 +
 27.2530 +    #define GL_TEXTURE_RECTANGLE 0x84F5
 27.2531 +    #define GL_TEXTURE_BINDING_RECTANGLE 0x84F6
 27.2532 +    #define GL_PROXY_TEXTURE_RECTANGLE 0x84F7
 27.2533 +    #define GL_MAX_RECTANGLE_TEXTURE_SIZE 0x84F8
 27.2534 +    #define GL_SAMPLER_2D_RECT 0x8B63
 27.2535 +    #define GL_SAMPLER_2D_RECT_SHADOW 0x8B64
 27.2536 +    #define GL_TEXTURE_BUFFER 0x8C2A
 27.2537 +    #define GL_MAX_TEXTURE_BUFFER_SIZE 0x8C2B
 27.2538 +    #define GL_TEXTURE_BINDING_BUFFER 0x8C2C
 27.2539 +    #define GL_TEXTURE_BUFFER_DATA_STORE_BINDING 0x8C2D
 27.2540 +    #define GL_TEXTURE_BUFFER_FORMAT 0x8C2E
 27.2541 +    #define GL_SAMPLER_BUFFER 0x8DC2
 27.2542 +    #define GL_INT_SAMPLER_2D_RECT 0x8DCD
 27.2543 +    #define GL_INT_SAMPLER_BUFFER 0x8DD0
 27.2544 +    #define GL_UNSIGNED_INT_SAMPLER_2D_RECT 0x8DD5
 27.2545 +    #define GL_UNSIGNED_INT_SAMPLER_BUFFER 0x8DD8
 27.2546 +    #define GL_RED_SNORM 0x8F90
 27.2547 +    #define GL_RG_SNORM 0x8F91
 27.2548 +    #define GL_RGB_SNORM 0x8F92
 27.2549 +    #define GL_RGBA_SNORM 0x8F93
 27.2550 +    #define GL_R8_SNORM 0x8F94
 27.2551 +    #define GL_RG8_SNORM 0x8F95
 27.2552 +    #define GL_RGB8_SNORM 0x8F96
 27.2553 +    #define GL_RGBA8_SNORM 0x8F97
 27.2554 +    #define GL_R16_SNORM 0x8F98
 27.2555 +    #define GL_RG16_SNORM 0x8F99
 27.2556 +    #define GL_RGB16_SNORM 0x8F9A
 27.2557 +    #define GL_RGBA16_SNORM 0x8F9B
 27.2558 +    #define GL_SIGNED_NORMALIZED 0x8F9C
 27.2559 +    #define GL_PRIMITIVE_RESTART 0x8F9D
 27.2560 +    #define GL_PRIMITIVE_RESTART_INDEX 0x8F9E
 27.2561 +    #define GL_BUFFER_ACCESS_FLAGS 0x911F
 27.2562 +    #define GL_BUFFER_MAP_LENGTH 0x9120
 27.2563 +    #define GL_BUFFER_MAP_OFFSET 0x9121
 27.2564 +
 27.2565 +    typedef void (GLAPIENTRY * PFNGLDRAWARRAYSINSTANCEDPROC) (GLenum mode, GLint first, GLsizei count, GLsizei primcount);
 27.2566 +    typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINSTANCEDPROC) (GLenum mode, GLsizei count, GLenum type, const void* indices, GLsizei primcount);
 27.2567 +    typedef void (GLAPIENTRY * PFNGLPRIMITIVERESTARTINDEXPROC) (GLuint buffer);
 27.2568 +    typedef void (GLAPIENTRY * PFNGLTEXBUFFERPROC) (GLenum target, GLenum internalFormat, GLuint buffer);
 27.2569 +
 27.2570 +    #define glDrawArraysInstanced GLEGetCurrentFunction(glDrawArraysInstanced)
 27.2571 +    #define glDrawElementsInstanced GLEGetCurrentFunction(glDrawElementsInstanced)
 27.2572 +    #define glPrimitiveRestartIndex GLEGetCurrentFunction(glPrimitiveRestartIndex)
 27.2573 +    #define glTexBuffer GLEGetCurrentFunction(glTexBuffer)
 27.2574 +
 27.2575 +#endif // GL_VERSION_3_1
 27.2576 +
 27.2577 +
 27.2578 +
 27.2579 +#ifndef GL_VERSION_3_2
 27.2580 +    #define GL_VERSION_3_2 1
 27.2581 +
 27.2582 +    #define GL_CONTEXT_CORE_PROFILE_BIT 0x00000001
 27.2583 +    #define GL_CONTEXT_COMPATIBILITY_PROFILE_BIT 0x00000002
 27.2584 +    #define GL_LINES_ADJACENCY 0x000A
 27.2585 +    #define GL_LINE_STRIP_ADJACENCY 0x000B
 27.2586 +    #define GL_TRIANGLES_ADJACENCY 0x000C
 27.2587 +    #define GL_TRIANGLE_STRIP_ADJACENCY 0x000D
 27.2588 +    #define GL_PROGRAM_POINT_SIZE 0x8642
 27.2589 +    #define GL_GEOMETRY_VERTICES_OUT 0x8916
 27.2590 +    #define GL_GEOMETRY_INPUT_TYPE 0x8917
 27.2591 +    #define GL_GEOMETRY_OUTPUT_TYPE 0x8918
 27.2592 +    #define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS 0x8C29
 27.2593 +    #define GL_FRAMEBUFFER_ATTACHMENT_LAYERED 0x8DA7
 27.2594 +    #define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS 0x8DA8
 27.2595 +    #define GL_GEOMETRY_SHADER 0x8DD9
 27.2596 +    #define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS 0x8DDF
 27.2597 +    #define GL_MAX_GEOMETRY_OUTPUT_VERTICES 0x8DE0
 27.2598 +    #define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS 0x8DE1
 27.2599 +    #define GL_MAX_VERTEX_OUTPUT_COMPONENTS 0x9122
 27.2600 +    #define GL_MAX_GEOMETRY_INPUT_COMPONENTS 0x9123
 27.2601 +    #define GL_MAX_GEOMETRY_OUTPUT_COMPONENTS 0x9124
 27.2602 +    #define GL_MAX_FRAGMENT_INPUT_COMPONENTS 0x9125
 27.2603 +    #define GL_CONTEXT_PROFILE_MASK 0x9126
 27.2604 +
 27.2605 +    typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTUREPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level);
 27.2606 +    typedef void (GLAPIENTRY * PFNGLGETBUFFERPARAMETERI64VPROC) (GLenum target, GLenum value, GLint64 * data);
 27.2607 +    typedef void (GLAPIENTRY * PFNGLGETINTEGER64I_VPROC) (GLenum pname, GLuint index, GLint64 * data);
 27.2608 +
 27.2609 +    #define glFramebufferTexture GLEGetCurrentFunction(glFramebufferTexture)
 27.2610 +    #define glGetBufferParameteri64v GLEGetCurrentFunction(glGetBufferParameteri64v)
 27.2611 +    #define glGetInteger64i_v GLEGetCurrentFunction(glGetInteger64i_v)
 27.2612 +    
 27.2613 +#endif // GL_VERSION_3_2
 27.2614 +
 27.2615 +
 27.2616 +
 27.2617 +#ifndef GL_VERSION_3_3
 27.2618 +    #define GL_VERSION_3_3 1
 27.2619 +
 27.2620 +    #define GL_VERTEX_ATTRIB_ARRAY_DIVISOR 0x88FE
 27.2621 +    #define GL_RGB10_A2UI 0x906F
 27.2622 +
 27.2623 +    typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBDIVISORPROC) (GLuint index, GLuint divisor);
 27.2624 +
 27.2625 +    #define glVertexAttribDivisor GLEGetCurrentFunction(glVertexAttribDivisor)
 27.2626 +#endif
 27.2627 +
 27.2628 +
 27.2629 +
 27.2630 +#ifndef GL_VERSION_4_0
 27.2631 +    #define GL_VERSION_4_0 1
 27.2632 +
 27.2633 +    #define GL_SAMPLE_SHADING 0x8C36
 27.2634 +    #define GL_MIN_SAMPLE_SHADING_VALUE 0x8C37
 27.2635 +    #define GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET 0x8E5E
 27.2636 +    #define GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET 0x8E5F
 27.2637 +    #define GL_MAX_PROGRAM_TEXTURE_GATHER_COMPONENTS 0x8F9F
 27.2638 +    #define GL_TEXTURE_CUBE_MAP_ARRAY 0x9009
 27.2639 +    #define GL_TEXTURE_BINDING_CUBE_MAP_ARRAY 0x900A
 27.2640 +    #define GL_PROXY_TEXTURE_CUBE_MAP_ARRAY 0x900B
 27.2641 +    #define GL_SAMPLER_CUBE_MAP_ARRAY 0x900C
 27.2642 +    #define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW 0x900D
 27.2643 +    #define GL_INT_SAMPLER_CUBE_MAP_ARRAY 0x900E
 27.2644 +    #define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY 0x900F
 27.2645 +
 27.2646 +    typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONSEPARATEIPROC) (GLuint buf, GLenum modeRGB, GLenum modeAlpha);
 27.2647 +    typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONIPROC) (GLuint buf, GLenum mode);
 27.2648 +    typedef void (GLAPIENTRY * PFNGLBLENDFUNCSEPARATEIPROC) (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
 27.2649 +    typedef void (GLAPIENTRY * PFNGLBLENDFUNCIPROC) (GLuint buf, GLenum src, GLenum dst);
 27.2650 +    typedef void (GLAPIENTRY * PFNGLMINSAMPLESHADINGPROC) (GLclampf value);
 27.2651 +
 27.2652 +    #define glBlendEquationSeparatei GLEGetCurrentFunction(glBlendEquationSeparatei)
 27.2653 +    #define glBlendEquationi GLEGetCurrentFunction(glBlendEquationi)
 27.2654 +    #define glBlendFuncSeparatei GLEGetCurrentFunction(glBlendFuncSeparatei)
 27.2655 +    #define glBlendFunci GLEGetCurrentFunction(glBlendFunci)
 27.2656 +    #define glMinSampleShading GLEGetCurrentFunction(glMinSampleShading)
 27.2657 +
 27.2658 +#endif // GL_VERSION_4_0
 27.2659 +
 27.2660 +
 27.2661 +
 27.2662 +
 27.2663 +#ifndef GL_VERSION_4_1
 27.2664 +    #define GL_VERSION_4_1 1
 27.2665 +    // Empty
 27.2666 +#endif
 27.2667 +
 27.2668 +
 27.2669 +
 27.2670 +#ifndef GL_VERSION_4_2
 27.2671 +    #define GL_VERSION_4_2 1
 27.2672 +
 27.2673 +    #define GL_COMPRESSED_RGBA_BPTC_UNORM 0x8E8C
 27.2674 +    #define GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM 0x8E8D
 27.2675 +    #define GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT 0x8E8E
 27.2676 +    #define GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT 0x8E8F
 27.2677 +#endif
 27.2678 +
 27.2679 +
 27.2680 +
 27.2681 +#ifndef GL_VERSION_4_3
 27.2682 +    #define GL_VERSION_4_3 1
 27.2683 +    
 27.2684 +    #define GL_NUM_SHADING_LANGUAGE_VERSIONS 0x82E9
 27.2685 +    #define GL_VERTEX_ATTRIB_ARRAY_LONG 0x874E
 27.2686 +#endif
 27.2687 +
 27.2688 +
 27.2689 +
 27.2690 +#ifndef GL_VERSION_4_4
 27.2691 +    #define GL_VERSION_4_4 1
 27.2692 +    
 27.2693 +    #define GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED 0x8221
 27.2694 +    #define GL_MAX_VERTEX_ATTRIB_STRIDE 0x82E5
 27.2695 +    #define GL_TEXTURE_BUFFER_BINDING 0x8C2A
 27.2696 +#endif
 27.2697 +
 27.2698 +
 27.2699 +
 27.2700 +#ifndef GL_VERSION_4_5
 27.2701 +    #define GL_VERSION_4_5 1
 27.2702 +    // Empty
 27.2703 +#endif
 27.2704 +
 27.2705 +
 27.2706 +
 27.2707 +#ifndef GL_AMD_debug_output
 27.2708 +    #define GL_AMD_debug_output 1
 27.2709 +
 27.2710 +    #define GL_MAX_DEBUG_MESSAGE_LENGTH_AMD 0x9143
 27.2711 +    #define GL_MAX_DEBUG_LOGGED_MESSAGES_AMD 0x9144
 27.2712 +    #define GL_DEBUG_LOGGED_MESSAGES_AMD 0x9145
 27.2713 +    #define GL_DEBUG_SEVERITY_HIGH_AMD 0x9146
 27.2714 +    #define GL_DEBUG_SEVERITY_MEDIUM_AMD 0x9147
 27.2715 +    #define GL_DEBUG_SEVERITY_LOW_AMD 0x9148
 27.2716 +    #define GL_DEBUG_CATEGORY_API_ERROR_AMD 0x9149
 27.2717 +    #define GL_DEBUG_CATEGORY_WINDOW_SYSTEM_AMD 0x914A
 27.2718 +    #define GL_DEBUG_CATEGORY_DEPRECATION_AMD 0x914B
 27.2719 +    #define GL_DEBUG_CATEGORY_UNDEFINED_BEHAVIOR_AMD 0x914C
 27.2720 +    #define GL_DEBUG_CATEGORY_PERFORMANCE_AMD 0x914D
 27.2721 +    #define GL_DEBUG_CATEGORY_SHADER_COMPILER_AMD 0x914E
 27.2722 +    #define GL_DEBUG_CATEGORY_APPLICATION_AMD 0x914F
 27.2723 +    #define GL_DEBUG_CATEGORY_OTHER_AMD 0x9150
 27.2724 +
 27.2725 +    typedef void (GLAPIENTRY *GLDEBUGPROCAMD)(GLuint id, GLenum category, GLenum severity, GLsizei length, const GLchar* message, void* userParam);
 27.2726 +
 27.2727 +    typedef void   (GLAPIENTRY * PFNGLDEBUGMESSAGECALLBACKAMDPROC) (GLDEBUGPROCAMD callback, void *userParam);
 27.2728 +    typedef void   (GLAPIENTRY * PFNGLDEBUGMESSAGEENABLEAMDPROC) (GLenum category, GLenum severity, GLsizei count, const GLuint* ids, GLboolean enabled);
 27.2729 +    typedef void   (GLAPIENTRY * PFNGLDEBUGMESSAGEINSERTAMDPROC) (GLenum category, GLenum severity, GLuint id, GLsizei length, const GLchar* buf);
 27.2730 +    typedef GLuint (GLAPIENTRY * PFNGLGETDEBUGMESSAGELOGAMDPROC) (GLuint count, GLsizei bufsize, GLenum* categories, GLuint* severities, GLuint* ids, GLsizei* lengths, GLchar* message);
 27.2731 +
 27.2732 +    #define glDebugMessageCallbackAMD GLEGetCurrentFunction(glDebugMessageCallbackAMD)
 27.2733 +    #define glDebugMessageEnableAMD   GLEGetCurrentFunction(glDebugMessageEnableAMD)
 27.2734 +    #define glDebugMessageInsertAMD   GLEGetCurrentFunction(glDebugMessageInsertAMD)
 27.2735 +    #define glGetDebugMessageLogAMD   GLEGetCurrentFunction(glGetDebugMessageLogAMD)
 27.2736 +
 27.2737 +    #define GLE_AMD_debug_output GLEGetCurrentVariable(gle_AMD_debug_output)
 27.2738 +
 27.2739 +#endif // GL_AMD_debug_output
 27.2740 +
 27.2741 +
 27.2742 +
 27.2743 +/* Disabled until needed
 27.2744 +#ifndef GL_AMD_performance_monitor
 27.2745 +    #define GL_AMD_performance_monitor 1
 27.2746 +
 27.2747 +    #define GL_COUNTER_TYPE_AMD 0x8BC0
 27.2748 +    #define GL_COUNTER_RANGE_AMD 0x8BC1
 27.2749 +    #define GL_UNSIGNED_INT64_AMD 0x8BC2
 27.2750 +    #define GL_PERCENTAGE_AMD 0x8BC3
 27.2751 +    #define GL_PERFMON_RESULT_AVAILABLE_AMD 0x8BC4
 27.2752 +    #define GL_PERFMON_RESULT_SIZE_AMD 0x8BC5
 27.2753 +    #define GL_PERFMON_RESULT_AMD 0x8BC6
 27.2754 +
 27.2755 +    typedef void (GLAPIENTRY * PFNGLBEGINPERFMONITORAMDPROC) (GLuint monitor);
 27.2756 +    typedef void (GLAPIENTRY * PFNGLDELETEPERFMONITORSAMDPROC) (GLsizei n, GLuint* monitors);
 27.2757 +    typedef void (GLAPIENTRY * PFNGLENDPERFMONITORAMDPROC) (GLuint monitor);
 27.2758 +    typedef void (GLAPIENTRY * PFNGLGENPERFMONITORSAMDPROC) (GLsizei n, GLuint* monitors);
 27.2759 +    typedef void (GLAPIENTRY * PFNGLGETPERFMONITORCOUNTERDATAAMDPROC) (GLuint monitor, GLenum pname, GLsizei dataSize, GLuint* data, GLint *bytesWritten);
 27.2760 +    typedef void (GLAPIENTRY * PFNGLGETPERFMONITORCOUNTERINFOAMDPROC) (GLuint group, GLuint counter, GLenum pname, void *data);
 27.2761 +    typedef void (GLAPIENTRY * PFNGLGETPERFMONITORCOUNTERSTRINGAMDPROC) (GLuint group, GLuint counter, GLsizei bufSize, GLsizei* length, GLchar *counterString);
 27.2762 +    typedef void (GLAPIENTRY * PFNGLGETPERFMONITORCOUNTERSAMDPROC) (GLuint group, GLint* numCounters, GLint *maxActiveCounters, GLsizei countersSize, GLuint *counters);
 27.2763 +    typedef void (GLAPIENTRY * PFNGLGETPERFMONITORGROUPSTRINGAMDPROC) (GLuint group, GLsizei bufSize, GLsizei* length, GLchar *groupString);
 27.2764 +    typedef void (GLAPIENTRY * PFNGLGETPERFMONITORGROUPSAMDPROC) (GLint* numGroups, GLsizei groupsSize, GLuint *groups);
 27.2765 +    typedef void (GLAPIENTRY * PFNGLSELECTPERFMONITORCOUNTERSAMDPROC) (GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint* counterList);
 27.2766 +
 27.2767 +    #define glBeginPerfMonitorAMD GLEGetCurrentFunction(glBeginPerfMonitorAMD)
 27.2768 +    #define glDeletePerfMonitorsAMD GLEGetCurrentFunction(glDeletePerfMonitorsAMD)
 27.2769 +    #define glEndPerfMonitorAMD GLEGetCurrentFunction(glEndPerfMonitorAMD)
 27.2770 +    #define glGenPerfMonitorsAMD GLEGetCurrentFunction(glGenPerfMonitorsAMD)
 27.2771 +    #define glGetPerfMonitorCounterDataAMD GLEGetCurrentFunction(glGetPerfMonitorCounterDataAMD)
 27.2772 +    #define glGetPerfMonitorCounterInfoAMD GLEGetCurrentFunction(glGetPerfMonitorCounterInfoAMD)
 27.2773 +    #define glGetPerfMonitorCounterStringAMD GLEGetCurrentFunction(glGetPerfMonitorCounterStringAMD)
 27.2774 +    #define glGetPerfMonitorCountersAMD GLEGetCurrentFunction(glGetPerfMonitorCountersAMD)
 27.2775 +    #define glGetPerfMonitorGroupStringAMD GLEGetCurrentFunction(glGetPerfMonitorGroupStringAMD)
 27.2776 +    #define glGetPerfMonitorGroupsAMD GLEGetCurrentFunction(glGetPerfMonitorGroupsAMD)
 27.2777 +    #define glSelectPerfMonitorCountersAMD GLEGetCurrentFunction(glSelectPerfMonitorCountersAMD)
 27.2778 +
 27.2779 +    #define GLE_AMD_performance_monitor GLEGetCurrentVariable(gle_AMD_performance_monitor)
 27.2780 +
 27.2781 +#endif // GL_AMD_performance_monitor
 27.2782 +*/
 27.2783 +
 27.2784 +
 27.2785 +#if defined(GLE_CGL_ENABLED)
 27.2786 +    #ifndef GL_APPLE_aux_depth_stencil
 27.2787 +        #define GL_APPLE_aux_depth_stencil 1
 27.2788 +
 27.2789 +        #define GL_AUX_DEPTH_STENCIL_APPLE 0x8A14g
 27.2790 +
 27.2791 +        #define GLE_APPLE_aux_depth_stencil GLEGetCurrentVariable(gle_APPLE_aux_depth_stencil)
 27.2792 +    #endif
 27.2793 +
 27.2794 +
 27.2795 +
 27.2796 +    #ifndef GL_APPLE_client_storage
 27.2797 +        #define GL_APPLE_client_storage 1
 27.2798 +
 27.2799 +        #define GL_UNPACK_CLIENT_STORAGE_APPLE 0x85B2
 27.2800 +
 27.2801 +        #define GLE_APPLE_client_storage GLEGetCurrentVariable(gle_APPLE_client_storage)
 27.2802 +    #endif
 27.2803 +
 27.2804 +
 27.2805 +
 27.2806 +    #ifndef GL_APPLE_element_array
 27.2807 +        #define GL_APPLE_element_array 1
 27.2808 +
 27.2809 +        #define GL_ELEMENT_ARRAY_APPLE 0x8A0C
 27.2810 +        #define GL_ELEMENT_ARRAY_TYPE_APPLE 0x8A0D
 27.2811 +        #define GL_ELEMENT_ARRAY_POINTER_APPLE 0x8A0E
 27.2812 +
 27.2813 +        typedef void (GLAPIENTRY * PFNGLDRAWELEMENTARRAYAPPLEPROC) (GLenum mode, GLint first, GLsizei count);
 27.2814 +        typedef void (GLAPIENTRY * PFNGLDRAWRANGEELEMENTARRAYAPPLEPROC) (GLenum mode, GLuint start, GLuint end, GLint first, GLsizei count);
 27.2815 +        typedef void (GLAPIENTRY * PFNGLELEMENTPOINTERAPPLEPROC) (GLenum type, const void *pointer);
 27.2816 +        typedef void (GLAPIENTRY * PFNGLMULTIDRAWELEMENTARRAYAPPLEPROC) (GLenum mode, const GLint* first, const GLsizei *count, GLsizei primcount);
 27.2817 +        typedef void (GLAPIENTRY * PFNGLMULTIDRAWRANGEELEMENTARRAYAPPLEPROC) (GLenum mode, GLuint start, GLuint end, const GLint* first, const GLsizei *count, GLsizei primcount);
 27.2818 +
 27.2819 +        #define glDrawElementArrayAPPLE GLEGetCurrentFunction(glDrawElementArrayAPPLE)
 27.2820 +        #define glDrawRangeElementArrayAPPLE GLEGetCurrentFunction(glDrawRangeElementArrayAPPLE)
 27.2821 +        #define glElementPointerAPPLE GLEGetCurrentFunction(glElementPointerAPPLE)
 27.2822 +        #define glMultiDrawElementArrayAPPLE GLEGetCurrentFunction(glMultiDrawElementArrayAPPLE)
 27.2823 +        #define glMultiDrawRangeElementArrayAPPLE GLEGetCurrentFunction(glMultiDrawRangeElementArrayAPPLE)
 27.2824 +
 27.2825 +        #define GLE_APPLE_element_array GLEGetCurrentVariable(gle_APPLE_element_array)
 27.2826 +    #endif
 27.2827 +
 27.2828 +
 27.2829 +
 27.2830 +    #ifndef GL_APPLE_fence
 27.2831 +        #define GL_APPLE_fence 1
 27.2832 +
 27.2833 +        #define GL_DRAW_PIXELS_APPLE 0x8A0A
 27.2834 +        #define GL_FENCE_APPLE 0x8A0B
 27.2835 +
 27.2836 +        typedef void (GLAPIENTRY * PFNGLDELETEFENCESAPPLEPROC) (GLsizei n, const GLuint* fences);
 27.2837 +        typedef void (GLAPIENTRY * PFNGLFINISHFENCEAPPLEPROC) (GLuint fence);
 27.2838 +        typedef void (GLAPIENTRY * PFNGLFINISHOBJECTAPPLEPROC) (GLenum object, GLint name);
 27.2839 +        typedef void (GLAPIENTRY * PFNGLGENFENCESAPPLEPROC) (GLsizei n, GLuint* fences);
 27.2840 +        typedef GLboolean (GLAPIENTRY * PFNGLISFENCEAPPLEPROC) (GLuint fence);
 27.2841 +        typedef void (GLAPIENTRY * PFNGLSETFENCEAPPLEPROC) (GLuint fence);
 27.2842 +        typedef GLboolean (GLAPIENTRY * PFNGLTESTFENCEAPPLEPROC) (GLuint fence);
 27.2843 +        typedef GLboolean (GLAPIENTRY * PFNGLTESTOBJECTAPPLEPROC) (GLenum object, GLuint name);
 27.2844 +
 27.2845 +        #define glDeleteFencesAPPLE GLEGetCurrentFunction(glDeleteFencesAPPLE)
 27.2846 +        #define glFinishFenceAPPLE GLEGetCurrentFunction(glFinishFenceAPPLE)
 27.2847 +        #define glFinishObjectAPPLE GLEGetCurrentFunction(glFinishObjectAPPLE)
 27.2848 +        #define glGenFencesAPPLE GLEGetCurrentFunction(glGenFencesAPPLE)
 27.2849 +        #define glIsFenceAPPLE GLEGetCurrentFunction(glIsFenceAPPLE)
 27.2850 +        #define glSetFenceAPPLE GLEGetCurrentFunction(glSetFenceAPPLE)
 27.2851 +        #define glTestFenceAPPLE GLEGetCurrentFunction(glTestFenceAPPLE)
 27.2852 +        #define glTestObjectAPPLE GLEGetCurrentFunction(glTestObjectAPPLE)
 27.2853 +
 27.2854 +        #define GLE_APPLE_fence GLEGetCurrentVariable(gle_APPLE_fence)
 27.2855 +
 27.2856 +    #endif
 27.2857 +
 27.2858 +
 27.2859 +
 27.2860 +    #ifndef GL_APPLE_float_pixels
 27.2861 +        #define GL_APPLE_float_pixels 1
 27.2862 +
 27.2863 +        #define GL_HALF_APPLE 0x140B
 27.2864 +        #define GL_RGBA_FLOAT32_APPLE 0x8814
 27.2865 +        #define GL_RGB_FLOAT32_APPLE 0x8815
 27.2866 +        #define GL_ALPHA_FLOAT32_APPLE 0x8816
 27.2867 +        #define GL_INTENSITY_FLOAT32_APPLE 0x8817
 27.2868 +        #define GL_LUMINANCE_FLOAT32_APPLE 0x8818
 27.2869 +        #define GL_LUMINANCE_ALPHA_FLOAT32_APPLE 0x8819
 27.2870 +        #define GL_RGBA_FLOAT16_APPLE 0x881A
 27.2871 +        #define GL_RGB_FLOAT16_APPLE 0x881B
 27.2872 +        #define GL_ALPHA_FLOAT16_APPLE 0x881C
 27.2873 +        #define GL_INTENSITY_FLOAT16_APPLE 0x881D
 27.2874 +        #define GL_LUMINANCE_FLOAT16_APPLE 0x881E
 27.2875 +        #define GL_LUMINANCE_ALPHA_FLOAT16_APPLE 0x881F
 27.2876 +        #define GL_COLOR_FLOAT_APPLE 0x8A0F
 27.2877 +
 27.2878 +        #define GLE_APPLE_float_pixels GLEGetCurrentVariable(gle_APPLE_float_pixels)
 27.2879 +    #endif
 27.2880 +
 27.2881 +
 27.2882 +
 27.2883 +    #ifndef GL_APPLE_flush_buffer_range
 27.2884 +        #define GL_APPLE_flush_buffer_range 1
 27.2885 +
 27.2886 +        #define GL_BUFFER_SERIALIZED_MODIFY_APPLE 0x8A12
 27.2887 +        #define GL_BUFFER_FLUSHING_UNMAP_APPLE 0x8A13
 27.2888 +
 27.2889 +        typedef void (GLAPIENTRY * PFNGLBUFFERPARAMETERIAPPLEPROC) (GLenum target, GLenum pname, GLint param);
 27.2890 +        typedef void (GLAPIENTRY * PFNGLFLUSHMAPPEDBUFFERRANGEAPPLEPROC) (GLenum target, GLintptr offset, GLsizeiptr size);
 27.2891 +
 27.2892 +        #define glBufferParameteriAPPLE GLEGetCurrentFunction(glBufferParameteriAPPLE)
 27.2893 +        #define glFlushMappedBufferRangeAPPLE GLEGetCurrentFunction(glFlushMappedBufferRangeAPPLE)
 27.2894 +
 27.2895 +        #define GLE_APPLE_flush_buffer_range GLEGetCurrentVariable(gle_APPLE_flush_buffer_range)
 27.2896 +    #endif
 27.2897 +
 27.2898 +
 27.2899 +
 27.2900 +    #ifndef GL_APPLE_object_purgeable
 27.2901 +        #define GL_APPLE_object_purgeable 1
 27.2902 +
 27.2903 +        #define GL_BUFFER_OBJECT_APPLE 0x85B3
 27.2904 +        #define GL_RELEASED_APPLE 0x8A19
 27.2905 +        #define GL_VOLATILE_APPLE 0x8A1A
 27.2906 +        #define GL_RETAINED_APPLE 0x8A1B
 27.2907 +        #define GL_UNDEFINED_APPLE 0x8A1C
 27.2908 +        #define GL_PURGEABLE_APPLE 0x8A1D
 27.2909 +
 27.2910 +        typedef void (GLAPIENTRY * PFNGLGETOBJECTPARAMETERIVAPPLEPROC) (GLenum objectType, GLuint name, GLenum pname, GLint* params);
 27.2911 +        typedef GLenum (GLAPIENTRY * PFNGLOBJECTPURGEABLEAPPLEPROC) (GLenum objectType, GLuint name, GLenum option);
 27.2912 +        typedef GLenum (GLAPIENTRY * PFNGLOBJECTUNPURGEABLEAPPLEPROC) (GLenum objectType, GLuint name, GLenum option);
 27.2913 +
 27.2914 +        #define glGetObjectParameterivAPPLE GLEGetCurrentFunction(glGetObjectParameterivAPPLE)
 27.2915 +        #define glObjectPurgeableAPPLE GLEGetCurrentFunction(glObjectPurgeableAPPLE)
 27.2916 +        #define glObjectUnpurgeableAPPLE GLEGetCurrentFunction(glObjectUnpurgeableAPPLE)
 27.2917 +
 27.2918 +        #define GLE_APPLE_object_purgeable GLEGetCurrentVariable(gle_APPLE_object_purgeable)
 27.2919 +    #endif
 27.2920 +
 27.2921 +
 27.2922 +
 27.2923 +    #ifndef GL_APPLE_pixel_buffer
 27.2924 +        #define GL_APPLE_pixel_buffer 1
 27.2925 +
 27.2926 +        #define GL_MIN_PBUFFER_VIEWPORT_DIMS_APPLE 0x8A10
 27.2927 +
 27.2928 +        #define GLE_APPLE_pixel_buffer GLEGetCurrentVariable(gle_APPLE_pixel_buffer)
 27.2929 +    #endif
 27.2930 +
 27.2931 +
 27.2932 +
 27.2933 +    #ifndef GL_APPLE_rgb_422
 27.2934 +        #define GL_APPLE_rgb_422 1
 27.2935 +
 27.2936 +        #define GL_UNSIGNED_SHORT_8_8_APPLE 0x85BA
 27.2937 +        #define GL_UNSIGNED_SHORT_8_8_REV_APPLE 0x85BB
 27.2938 +        #define GL_RGB_422_APPLE 0x8A1F
 27.2939 +        #define GL_RGB_RAW_422_APPLE 0x8A51
 27.2940 +
 27.2941 +        #define GLE_APPLE_rgb_422 GLEGetCurrentVariable(gle_APPLE_rgb_422)
 27.2942 +    #endif
 27.2943 +
 27.2944 +
 27.2945 +
 27.2946 +    #ifndef GL_APPLE_row_bytes
 27.2947 +        #define GL_APPLE_row_bytes 1
 27.2948 +
 27.2949 +        #define GL_PACK_ROW_BYTES_APPLE 0x8A15
 27.2950 +        #define GL_UNPACK_ROW_BYTES_APPLE 0x8A16
 27.2951 +
 27.2952 +        #define GLE_APPLE_row_bytes GLEGetCurrentVariable(gle_APPLE_row_bytes)
 27.2953 +    #endif
 27.2954 +
 27.2955 +
 27.2956 +
 27.2957 +    #ifndef GL_APPLE_specular_vector
 27.2958 +        #define GL_APPLE_specular_vector 1
 27.2959 +
 27.2960 +        #define GL_LIGHT_MODEL_SPECULAR_VECTOR_APPLE 0x85B0
 27.2961 +
 27.2962 +        #define GLE_APPLE_specular_vector GLEGetCurrentVariable(gle_APPLE_specular_vector)
 27.2963 +    #endif
 27.2964 +
 27.2965 +
 27.2966 +
 27.2967 +    #ifndef GL_APPLE_texture_range
 27.2968 +        #define GL_APPLE_texture_range 1
 27.2969 +
 27.2970 +        #define GL_TEXTURE_RANGE_LENGTH_APPLE 0x85B7
 27.2971 +        #define GL_TEXTURE_RANGE_POINTER_APPLE 0x85B8
 27.2972 +        #define GL_TEXTURE_STORAGE_HINT_APPLE 0x85BC
 27.2973 +        #define GL_STORAGE_PRIVATE_APPLE 0x85BD
 27.2974 +        #define GL_STORAGE_CACHED_APPLE 0x85BE
 27.2975 +        #define GL_STORAGE_SHARED_APPLE 0x85BF
 27.2976 +
 27.2977 +        typedef void (GLAPIENTRY * PFNGLGETTEXPARAMETERPOINTERVAPPLEPROC) (GLenum target, GLenum pname, void **params);
 27.2978 +        typedef void (GLAPIENTRY * PFNGLTEXTURERANGEAPPLEPROC) (GLenum target, GLsizei length, const void *pointer);
 27.2979 +
 27.2980 +        #define glGetTexParameterPointervAPPLE GLEGetCurrentFunction(glGetTexParameterPointervAPPLE)
 27.2981 +        #define glTextureRangeAPPLE GLEGetCurrentFunction(glTextureRangeAPPLE)
 27.2982 +
 27.2983 +        #define GLE_APPLE_texture_range GLEGetCurrentVariable(gle_APPLE_texture_range)
 27.2984 +    #endif
 27.2985 +
 27.2986 +
 27.2987 +    #ifndef GL_APPLE_transform_hint
 27.2988 +        #define GL_APPLE_transform_hint 1
 27.2989 +
 27.2990 +        #define GL_TRANSFORM_HINT_APPLE 0x85B1
 27.2991 +
 27.2992 +        #define GLE_APPLE_transform_hint GLEGetCurrentVariable(gle_APPLE_transform_hint)
 27.2993 +    #endif
 27.2994 +
 27.2995 +
 27.2996 +
 27.2997 +    #ifndef GL_APPLE_vertex_array_object
 27.2998 +        #define GL_APPLE_vertex_array_object 1
 27.2999 +        
 27.3000 +        // This has been superceded by GL_ARB_vertex_array_object, though if you are using Apple
 27.3001 +        // OpenGL prior to 3.x then only this interface will be available. However, we have made
 27.3002 +        // it so that glBindVertexArray maps to glBindVertexArrayApple when only the latter is present,
 27.3003 +        // thus allowing you to write cleaner code. You can always just call glBindVertexArray instead
 27.3004 +        // of glBindVertexArrayAPPLE, etc.
 27.3005 +        #define GL_VERTEX_ARRAY_BINDING_APPLE 0x85B5
 27.3006 +
 27.3007 +        typedef void      (GLAPIENTRY * PFNGLBINDVERTEXARRAYAPPLEPROC) (GLuint array);
 27.3008 +        typedef void      (GLAPIENTRY * PFNGLDELETEVERTEXARRAYSAPPLEPROC) (GLsizei n, const GLuint* arrays);
 27.3009 +        typedef void      (GLAPIENTRY * PFNGLGENVERTEXARRAYSAPPLEPROC) (GLsizei n, const GLuint* arrays); // It's not clear whether arrays needs to be const or not.
 27.3010 +        typedef GLboolean (GLAPIENTRY * PFNGLISVERTEXARRAYAPPLEPROC) (GLuint array);
 27.3011 +
 27.3012 +        #define glBindVertexArrayAPPLE    GLEGetCurrentFunction(glBindVertexArrayAPPLE)
 27.3013 +        #define glDeleteVertexArraysAPPLE GLEGetCurrentFunction(glDeleteVertexArraysAPPLE)
 27.3014 +        #define glGenVertexArraysAPPLE    GLEGetCurrentFunction(glGenVertexArraysAPPLE)
 27.3015 +        #define glIsVertexArrayAPPLE      GLEGetCurrentFunction(glIsVertexArrayAPPLE)
 27.3016 +
 27.3017 +        #define GLE_APPLE_vertex_array_object GLEGetCurrentVariable(gle_APPLE_vertex_array_object)
 27.3018 +    #endif
 27.3019 +
 27.3020 +
 27.3021 +
 27.3022 +    #ifndef GL_APPLE_vertex_array_range
 27.3023 +        #define GL_APPLE_vertex_array_range 1
 27.3024 +
 27.3025 +        #define GL_VERTEX_ARRAY_RANGE_APPLE 0x851D
 27.3026 +        #define GL_VERTEX_ARRAY_RANGE_LENGTH_APPLE 0x851E
 27.3027 +        #define GL_VERTEX_ARRAY_STORAGE_HINT_APPLE 0x851F
 27.3028 +        #define GL_MAX_VERTEX_ARRAY_RANGE_ELEMENT_APPLE 0x8520
 27.3029 +        #define GL_VERTEX_ARRAY_RANGE_POINTER_APPLE 0x8521
 27.3030 +        #define GL_STORAGE_CLIENT_APPLE 0x85B4
 27.3031 +        #define GL_STORAGE_CACHED_APPLE 0x85BE
 27.3032 +        #define GL_STORAGE_SHARED_APPLE 0x85BF
 27.3033 +
 27.3034 +        typedef void (GLAPIENTRY * PFNGLFLUSHVERTEXARRAYRANGEAPPLEPROC) (GLsizei length, void *pointer);
 27.3035 +        typedef void (GLAPIENTRY * PFNGLVERTEXARRAYPARAMETERIAPPLEPROC) (GLenum pname, GLint param);
 27.3036 +        typedef void (GLAPIENTRY * PFNGLVERTEXARRAYRANGEAPPLEPROC) (GLsizei length, void *pointer);
 27.3037 +
 27.3038 +        #define glFlushVertexArrayRangeAPPLE GLEGetCurrentFunction(glFlushVertexArrayRangeAPPLE)
 27.3039 +        #define glVertexArrayParameteriAPPLE GLEGetCurrentFunction(glVertexArrayParameteriAPPLE)
 27.3040 +        #define glVertexArrayRangeAPPLE GLEGetCurrentFunction(glVertexArrayRangeAPPLE)
 27.3041 +
 27.3042 +        #define GLE_APPLE_vertex_array_range GLEGetCurrentVariable(gle_APPLE_vertex_array_range)
 27.3043 +    #endif
 27.3044 +
 27.3045 +
 27.3046 +
 27.3047 +    #ifndef GL_APPLE_vertex_program_evaluators
 27.3048 +        #define GL_APPLE_vertex_program_evaluators 1
 27.3049 +
 27.3050 +        #define GL_VERTEX_ATTRIB_MAP1_APPLE 0x8A00
 27.3051 +        #define GL_VERTEX_ATTRIB_MAP2_APPLE 0x8A01
 27.3052 +        #define GL_VERTEX_ATTRIB_MAP1_SIZE_APPLE 0x8A02
 27.3053 +        #define GL_VERTEX_ATTRIB_MAP1_COEFF_APPLE 0x8A03
 27.3054 +        #define GL_VERTEX_ATTRIB_MAP1_ORDER_APPLE 0x8A04
 27.3055 +        #define GL_VERTEX_ATTRIB_MAP1_DOMAIN_APPLE 0x8A05
 27.3056 +        #define GL_VERTEX_ATTRIB_MAP2_SIZE_APPLE 0x8A06
 27.3057 +        #define GL_VERTEX_ATTRIB_MAP2_COEFF_APPLE 0x8A07
 27.3058 +        #define GL_VERTEX_ATTRIB_MAP2_ORDER_APPLE 0x8A08
 27.3059 +        #define GL_VERTEX_ATTRIB_MAP2_DOMAIN_APPLE 0x8A09
 27.3060 +
 27.3061 +        typedef void (GLAPIENTRY * PFNGLDISABLEVERTEXATTRIBAPPLEPROC) (GLuint index, GLenum pname);
 27.3062 +        typedef void (GLAPIENTRY * PFNGLENABLEVERTEXATTRIBAPPLEPROC) (GLuint index, GLenum pname);
 27.3063 +        typedef GLboolean (GLAPIENTRY * PFNGLISVERTEXATTRIBENABLEDAPPLEPROC) (GLuint index, GLenum pname);
 27.3064 +        typedef void (GLAPIENTRY * PFNGLMAPVERTEXATTRIB1DAPPLEPROC) (GLuint index, GLuint size, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble* points);
 27.3065 +        typedef void (GLAPIENTRY * PFNGLMAPVERTEXATTRIB1FAPPLEPROC) (GLuint index, GLuint size, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat* points);
 27.3066 +        typedef void (GLAPIENTRY * PFNGLMAPVERTEXATTRIB2DAPPLEPROC) (GLuint index, GLuint size, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble* points);
 27.3067 +        typedef void (GLAPIENTRY * PFNGLMAPVERTEXATTRIB2FAPPLEPROC) (GLuint index, GLuint size, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat* points);
 27.3068 +
 27.3069 +        #define glDisableVertexAttribAPPLE GLEGetCurrentFunction(glDisableVertexAttribAPPLE)
 27.3070 +        #define glEnableVertexAttribAPPLE GLEGetCurrentFunction(glEnableVertexAttribAPPLE)
 27.3071 +        #define glIsVertexAttribEnabledAPPLE GLEGetCurrentFunction(glIsVertexAttribEnabledAPPLE)
 27.3072 +        #define glMapVertexAttrib1dAPPLE GLEGetCurrentFunction(glMapVertexAttrib1dAPPLE)
 27.3073 +        #define glMapVertexAttrib1fAPPLE GLEGetCurrentFunction(glMapVertexAttrib1fAPPLE)
 27.3074 +        #define glMapVertexAttrib2dAPPLE GLEGetCurrentFunction(glMapVertexAttrib2dAPPLE)
 27.3075 +        #define glMapVertexAttrib2fAPPLE GLEGetCurrentFunction(glMapVertexAttrib2fAPPLE)
 27.3076 +
 27.3077 +        #define GLE_APPLE_vertex_program_evaluators GLEGetCurrentVariable(gle_APPLE_vertex_program_evaluators)
 27.3078 +    #endif
 27.3079 +
 27.3080 +#endif // GLE_CGL_ENABLED
 27.3081 +
 27.3082 +
 27.3083 +#ifndef GL_ARB_debug_output
 27.3084 +    #define GL_ARB_debug_output 1
 27.3085 +
 27.3086 +    #define GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB 0x8242
 27.3087 +    #define GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_ARB 0x8243
 27.3088 +    #define GL_DEBUG_CALLBACK_FUNCTION_ARB 0x8244
 27.3089 +    #define GL_DEBUG_CALLBACK_USER_PARAM_ARB 0x8245
 27.3090 +    #define GL_DEBUG_SOURCE_API_ARB 0x8246
 27.3091 +    #define GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB 0x8247
 27.3092 +    #define GL_DEBUG_SOURCE_SHADER_COMPILER_ARB 0x8248
 27.3093 +    #define GL_DEBUG_SOURCE_THIRD_PARTY_ARB 0x8249
 27.3094 +    #define GL_DEBUG_SOURCE_APPLICATION_ARB 0x824A
 27.3095 +    #define GL_DEBUG_SOURCE_OTHER_ARB 0x824B
 27.3096 +    #define GL_DEBUG_TYPE_ERROR_ARB 0x824C
 27.3097 +    #define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB 0x824D
 27.3098 +    #define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB 0x824E
 27.3099 +    #define GL_DEBUG_TYPE_PORTABILITY_ARB 0x824F
 27.3100 +    #define GL_DEBUG_TYPE_PERFORMANCE_ARB 0x8250
 27.3101 +    #define GL_DEBUG_TYPE_OTHER_ARB 0x8251
 27.3102 +    #define GL_MAX_DEBUG_MESSAGE_LENGTH_ARB 0x9143
 27.3103 +    #define GL_MAX_DEBUG_LOGGED_MESSAGES_ARB 0x9144
 27.3104 +    #define GL_DEBUG_LOGGED_MESSAGES_ARB 0x9145
 27.3105 +    #define GL_DEBUG_SEVERITY_HIGH_ARB 0x9146
 27.3106 +    #define GL_DEBUG_SEVERITY_MEDIUM_ARB 0x9147
 27.3107 +    #define GL_DEBUG_SEVERITY_LOW_ARB 0x9148
 27.3108 +
 27.3109 +    typedef void (GLAPIENTRY *GLDEBUGPROCARB)(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, const void* userParam);
 27.3110 +
 27.3111 +    typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGECALLBACKARBPROC) (GLDEBUGPROCARB callback, const void *userParam);
 27.3112 +    typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGECONTROLARBPROC) (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint* ids, GLboolean enabled);
 27.3113 +    typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGEINSERTARBPROC) (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* buf);
 27.3114 +    typedef GLuint (GLAPIENTRY * PFNGLGETDEBUGMESSAGELOGARBPROC) (GLuint count, GLsizei bufSize, GLenum* sources, GLenum* types, GLuint* ids, GLenum* severities, GLsizei* lengths, GLchar* messageLog);
 27.3115 +
 27.3116 +    #define glDebugMessageCallbackARB GLEGetCurrentFunction(glDebugMessageCallbackARB)
 27.3117 +    #define glDebugMessageControlARB GLEGetCurrentFunction(glDebugMessageControlARB)
 27.3118 +    #define glDebugMessageInsertARB GLEGetCurrentFunction(glDebugMessageInsertARB)
 27.3119 +    #define glGetDebugMessageLogARB GLEGetCurrentFunction(glGetDebugMessageLogARB)
 27.3120 +
 27.3121 +    #define GLE_ARB_debug_output GLEGetCurrentVariable(gle_ARB_debug_output)
 27.3122 +
 27.3123 +#endif // GL_ARB_debug_output
 27.3124 +
 27.3125 +
 27.3126 +
 27.3127 +#ifndef GL_ARB_depth_buffer_float
 27.3128 +    #define GL_ARB_depth_buffer_float 1
 27.3129 +
 27.3130 +    // Supercededs GL_NV_depth_buffer_float
 27.3131 +    #define GL_DEPTH_COMPONENT32F             0x8CAC
 27.3132 +    #define GL_DEPTH32F_STENCIL8              0x8CAD
 27.3133 +    #define GL_FLOAT_32_UNSIGNED_INT_24_8_REV 0x8DAD
 27.3134 +
 27.3135 +    #define GLE_ARB_depth_buffer_float GLEGetCurrentVariable(gle_ARB_depth_buffer_float)
 27.3136 +#endif
 27.3137 +
 27.3138 +
 27.3139 +/* Disabled until needed
 27.3140 +#ifndef GL_ARB_direct_state_access
 27.3141 +    #define GL_ARB_direct_state_access 1
 27.3142 +
 27.3143 +    #define GL_TEXTURE_TARGET 0x1006
 27.3144 +    #define GL_QUERY_TARGET 0x82EA
 27.3145 +    #define GL_TEXTURE_BINDING 0x82EB
 27.3146 +
 27.3147 +    typedef void (GLAPIENTRY * PFNGLBINDTEXTUREUNITPROC) (GLuint unit, GLuint texture);
 27.3148 +    typedef void (GLAPIENTRY * PFNGLBLITNAMEDFRAMEBUFFERPROC) (GLuint readFramebuffer, GLuint drawFramebuffer, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
 27.3149 +    typedef GLenum (GLAPIENTRY * PFNGLCHECKNAMEDFRAMEBUFFERSTATUSPROC) (GLuint framebuffer, GLenum target);
 27.3150 +    typedef void (GLAPIENTRY * PFNGLCLEARNAMEDBUFFERDATAPROC) (GLuint buffer, GLenum internalformat, GLenum format, GLenum type, const void *data);
 27.3151 +    typedef void (GLAPIENTRY * PFNGLCLEARNAMEDBUFFERSUBDATAPROC) (GLuint buffer, GLenum internalformat, GLintptr offset, GLsizeiptr size, GLenum format, GLenum type, const void *data);
 27.3152 +    typedef void (GLAPIENTRY * PFNGLCLEARNAMEDFRAMEBUFFERFIPROC) (GLuint framebuffer, GLenum buffer, GLfloat depth, GLint stencil);
 27.3153 +    typedef void (GLAPIENTRY * PFNGLCLEARNAMEDFRAMEBUFFERFVPROC) (GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLfloat* value);
 27.3154 +    typedef void (GLAPIENTRY * PFNGLCLEARNAMEDFRAMEBUFFERIVPROC) (GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLint* value);
 27.3155 +    typedef void (GLAPIENTRY * PFNGLCLEARNAMEDFRAMEBUFFERUIVPROC) (GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLuint* value);
 27.3156 +    typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTURESUBIMAGE1DPROC) (GLuint texture, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void *data);
 27.3157 +    typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTURESUBIMAGE2DPROC) (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data);
 27.3158 +    typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTURESUBIMAGE3DPROC) (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data);
 27.3159 +    typedef void (GLAPIENTRY * PFNGLCOPYNAMEDBUFFERSUBDATAPROC) (GLuint readBuffer, GLuint writeBuffer, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
 27.3160 +    typedef void (GLAPIENTRY * PFNGLCOPYTEXTURESUBIMAGE1DPROC) (GLuint texture, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);
 27.3161 +    typedef void (GLAPIENTRY * PFNGLCOPYTEXTURESUBIMAGE2DPROC) (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
 27.3162 +    typedef void (GLAPIENTRY * PFNGLCOPYTEXTURESUBIMAGE3DPROC) (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
 27.3163 +    typedef void (GLAPIENTRY * PFNGLCREATEBUFFERSPROC) (GLsizei n, GLuint* buffers);
 27.3164 +    typedef void (GLAPIENTRY * PFNGLCREATEFRAMEBUFFERSPROC) (GLsizei n, GLuint* framebuffers);
 27.3165 +    typedef void (GLAPIENTRY * PFNGLCREATEPROGRAMPIPELINESPROC) (GLsizei n, GLuint* pipelines);
 27.3166 +    typedef void (GLAPIENTRY * PFNGLCREATEQUERIESPROC) (GLenum target, GLsizei n, GLuint* ids);
 27.3167 +    typedef void (GLAPIENTRY * PFNGLCREATERENDERBUFFERSPROC) (GLsizei n, GLuint* renderbuffers);
 27.3168 +    typedef void (GLAPIENTRY * PFNGLCREATESAMPLERSPROC) (GLsizei n, GLuint* samplers);
 27.3169 +    typedef void (GLAPIENTRY * PFNGLCREATETEXTURESPROC) (GLenum target, GLsizei n, GLuint* textures);
 27.3170 +    typedef void (GLAPIENTRY * PFNGLCREATETRANSFORMFEEDBACKSPROC) (GLsizei n, GLuint* ids);
 27.3171 +    typedef void (GLAPIENTRY * PFNGLCREATEVERTEXARRAYSPROC) (GLsizei n, GLuint* arrays);
 27.3172 +    typedef void (GLAPIENTRY * PFNGLDISABLEVERTEXARRAYATTRIBPROC) (GLuint vaobj, GLuint index);
 27.3173 +    typedef void (GLAPIENTRY * PFNGLENABLEVERTEXARRAYATTRIBPROC) (GLuint vaobj, GLuint index);
 27.3174 +    typedef void (GLAPIENTRY * PFNGLFLUSHMAPPEDNAMEDBUFFERRANGEPROC) (GLuint buffer, GLintptr offset, GLsizeiptr length);
 27.3175 +    typedef void (GLAPIENTRY * PFNGLGENERATETEXTUREMIPMAPPROC) (GLuint texture);
 27.3176 +    typedef void (GLAPIENTRY * PFNGLGETCOMPRESSEDTEXTUREIMAGEPROC) (GLuint texture, GLint level, GLsizei bufSize, void *pixels);
 27.3177 +    typedef void (GLAPIENTRY * PFNGLGETNAMEDBUFFERPARAMETERI64VPROC) (GLuint buffer, GLenum pname, GLint64* params);
 27.3178 +    typedef void (GLAPIENTRY * PFNGLGETNAMEDBUFFERPARAMETERIVPROC) (GLuint buffer, GLenum pname, GLint* params);
 27.3179 +    typedef void (GLAPIENTRY * PFNGLGETNAMEDBUFFERPOINTERVPROC) (GLuint buffer, GLenum pname, void** params);
 27.3180 +    typedef void (GLAPIENTRY * PFNGLGETNAMEDBUFFERSUBDATAPROC) (GLuint buffer, GLintptr offset, GLsizeiptr size, void *data);
 27.3181 +    typedef void (GLAPIENTRY * PFNGLGETNAMEDFRAMEBUFFERATTACHMENTPARAMETERIVPROC) (GLuint framebuffer, GLenum attachment, GLenum pname, GLint* params);
 27.3182 +    typedef void (GLAPIENTRY * PFNGLGETNAMEDFRAMEBUFFERPARAMETERIVPROC) (GLuint framebuffer, GLenum pname, GLint* param);
 27.3183 +    typedef void (GLAPIENTRY * PFNGLGETNAMEDRENDERBUFFERPARAMETERIVPROC) (GLuint renderbuffer, GLenum pname, GLint* params);
 27.3184 +    typedef void (GLAPIENTRY * PFNGLGETTEXTUREIMAGEPROC) (GLuint texture, GLint level, GLenum format, GLenum type, GLsizei bufSize, void *pixels);
 27.3185 +    typedef void (GLAPIENTRY * PFNGLGETTEXTURELEVELPARAMETERFVPROC) (GLuint texture, GLint level, GLenum pname, GLfloat* params);
 27.3186 +    typedef void (GLAPIENTRY * PFNGLGETTEXTURELEVELPARAMETERIVPROC) (GLuint texture, GLint level, GLenum pname, GLint* params);
 27.3187 +    typedef void (GLAPIENTRY * PFNGLGETTEXTUREPARAMETERIIVPROC) (GLuint texture, GLenum pname, GLint* params);
 27.3188 +    typedef void (GLAPIENTRY * PFNGLGETTEXTUREPARAMETERIUIVPROC) (GLuint texture, GLenum pname, GLuint* params);
 27.3189 +    typedef void (GLAPIENTRY * PFNGLGETTEXTUREPARAMETERFVPROC) (GLuint texture, GLenum pname, GLfloat* params);
 27.3190 +    typedef void (GLAPIENTRY * PFNGLGETTEXTUREPARAMETERIVPROC) (GLuint texture, GLenum pname, GLint* params);
 27.3191 +    typedef void (GLAPIENTRY * PFNGLGETTRANSFORMFEEDBACKI64_VPROC) (GLuint xfb, GLenum pname, GLuint index, GLint64* param);
 27.3192 +    typedef void (GLAPIENTRY * PFNGLGETTRANSFORMFEEDBACKI_VPROC) (GLuint xfb, GLenum pname, GLuint index, GLint* param);
 27.3193 +    typedef void (GLAPIENTRY * PFNGLGETTRANSFORMFEEDBACKIVPROC) (GLuint xfb, GLenum pname, GLint* param);
 27.3194 +    typedef void (GLAPIENTRY * PFNGLGETVERTEXARRAYINDEXED64IVPROC) (GLuint vaobj, GLuint index, GLenum pname, GLint64* param);
 27.3195 +    typedef void (GLAPIENTRY * PFNGLGETVERTEXARRAYINDEXEDIVPROC) (GLuint vaobj, GLuint index, GLenum pname, GLint* param);
 27.3196 +    typedef void (GLAPIENTRY * PFNGLGETVERTEXARRAYIVPROC) (GLuint vaobj, GLenum pname, GLint* param);
 27.3197 +    typedef void (GLAPIENTRY * PFNGLINVALIDATENAMEDFRAMEBUFFERDATAPROC) (GLuint framebuffer, GLsizei numAttachments, const GLenum* attachments);
 27.3198 +    typedef void (GLAPIENTRY * PFNGLINVALIDATENAMEDFRAMEBUFFERSUBDATAPROC) (GLuint framebuffer, GLsizei numAttachments, const GLenum* attachments, GLint x, GLint y, GLsizei width, GLsizei height);
 27.3199 +    typedef void * (GLAPIENTRY * PFNGLMAPNAMEDBUFFERPROC) (GLuint buffer, GLenum access);
 27.3200 +    typedef void * (GLAPIENTRY * PFNGLMAPNAMEDBUFFERRANGEPROC) (GLuint buffer, GLintptr offset, GLsizeiptr length, GLbitfield access);
 27.3201 +    typedef void (GLAPIENTRY * PFNGLNAMEDBUFFERDATAPROC) (GLuint buffer, GLsizeiptr size, const void *data, GLenum usage);
 27.3202 +    typedef void (GLAPIENTRY * PFNGLNAMEDBUFFERSTORAGEPROC) (GLuint buffer, GLsizeiptr size, const void *data, GLbitfield flags);
 27.3203 +    typedef void (GLAPIENTRY * PFNGLNAMEDBUFFERSUBDATAPROC) (GLuint buffer, GLintptr offset, GLsizeiptr size, const void *data);
 27.3204 +    typedef void (GLAPIENTRY * PFNGLNAMEDFRAMEBUFFERDRAWBUFFERPROC) (GLuint framebuffer, GLenum mode);
 27.3205 +    typedef void (GLAPIENTRY * PFNGLNAMEDFRAMEBUFFERDRAWBUFFERSPROC) (GLuint framebuffer, GLsizei n, const GLenum* bufs);
 27.3206 +    typedef void (GLAPIENTRY * PFNGLNAMEDFRAMEBUFFERPARAMETERIPROC) (GLuint framebuffer, GLenum pname, GLint param);
 27.3207 +    typedef void (GLAPIENTRY * PFNGLNAMEDFRAMEBUFFERREADBUFFERPROC) (GLuint framebuffer, GLenum mode);
 27.3208 +    typedef void (GLAPIENTRY * PFNGLNAMEDFRAMEBUFFERRENDERBUFFERPROC) (GLuint framebuffer, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
 27.3209 +    typedef void (GLAPIENTRY * PFNGLNAMEDFRAMEBUFFERTEXTUREPROC) (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level);
 27.3210 +    typedef void (GLAPIENTRY * PFNGLNAMEDFRAMEBUFFERTEXTURELAYERPROC) (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level, GLint layer);
 27.3211 +    typedef void (GLAPIENTRY * PFNGLNAMEDRENDERBUFFERSTORAGEPROC) (GLuint renderbuffer, GLenum internalformat, GLsizei width, GLsizei height);
 27.3212 +    typedef void (GLAPIENTRY * PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEPROC) (GLuint renderbuffer, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
 27.3213 +    typedef void (GLAPIENTRY * PFNGLTEXTUREBUFFERPROC) (GLuint texture, GLenum internalformat, GLuint buffer);
 27.3214 +    typedef void (GLAPIENTRY * PFNGLTEXTUREBUFFERRANGEPROC) (GLuint texture, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size);
 27.3215 +    typedef void (GLAPIENTRY * PFNGLTEXTUREPARAMETERIIVPROC) (GLuint texture, GLenum pname, const GLint* params);
 27.3216 +    typedef void (GLAPIENTRY * PFNGLTEXTUREPARAMETERIUIVPROC) (GLuint texture, GLenum pname, const GLuint* params);
 27.3217 +    typedef void (GLAPIENTRY * PFNGLTEXTUREPARAMETERFPROC) (GLuint texture, GLenum pname, GLfloat param);
 27.3218 +    typedef void (GLAPIENTRY * PFNGLTEXTUREPARAMETERFVPROC) (GLuint texture, GLenum pname, const GLfloat* param);
 27.3219 +    typedef void (GLAPIENTRY * PFNGLTEXTUREPARAMETERIPROC) (GLuint texture, GLenum pname, GLint param);
 27.3220 +    typedef void (GLAPIENTRY * PFNGLTEXTUREPARAMETERIVPROC) (GLuint texture, GLenum pname, const GLint* param);
 27.3221 +    typedef void (GLAPIENTRY * PFNGLTEXTURESTORAGE1DPROC) (GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width);
 27.3222 +    typedef void (GLAPIENTRY * PFNGLTEXTURESTORAGE2DPROC) (GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
 27.3223 +    typedef void (GLAPIENTRY * PFNGLTEXTURESTORAGE2DMULTISAMPLEPROC) (GLuint texture, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations);
 27.3224 +    typedef void (GLAPIENTRY * PFNGLTEXTURESTORAGE3DPROC) (GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
 27.3225 +    typedef void (GLAPIENTRY * PFNGLTEXTURESTORAGE3DMULTISAMPLEPROC) (GLuint texture, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations);
 27.3226 +    typedef void (GLAPIENTRY * PFNGLTEXTURESUBIMAGE1DPROC) (GLuint texture, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void *pixels);
 27.3227 +    typedef void (GLAPIENTRY * PFNGLTEXTURESUBIMAGE2DPROC) (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
 27.3228 +    typedef void (GLAPIENTRY * PFNGLTEXTURESUBIMAGE3DPROC) (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels);
 27.3229 +    typedef void (GLAPIENTRY * PFNGLTRANSFORMFEEDBACKBUFFERBASEPROC) (GLuint xfb, GLuint index, GLuint buffer);
 27.3230 +    typedef void (GLAPIENTRY * PFNGLTRANSFORMFEEDBACKBUFFERRANGEPROC) (GLuint xfb, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
 27.3231 +    typedef GLboolean (GLAPIENTRY * PFNGLUNMAPNAMEDBUFFERPROC) (GLuint buffer);
 27.3232 +    typedef void (GLAPIENTRY * PFNGLVERTEXARRAYATTRIBBINDINGPROC) (GLuint vaobj, GLuint attribindex, GLuint bindingindex);
 27.3233 +    typedef void (GLAPIENTRY * PFNGLVERTEXARRAYATTRIBFORMATPROC) (GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset);
 27.3234 +    typedef void (GLAPIENTRY * PFNGLVERTEXARRAYATTRIBIFORMATPROC) (GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
 27.3235 +    typedef void (GLAPIENTRY * PFNGLVERTEXARRAYATTRIBLFORMATPROC) (GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
 27.3236 +    typedef void (GLAPIENTRY * PFNGLVERTEXARRAYBINDINGDIVISORPROC) (GLuint vaobj, GLuint bindingindex, GLuint divisor);
 27.3237 +    typedef void (GLAPIENTRY * PFNGLVERTEXARRAYELEMENTBUFFERPROC) (GLuint vaobj, GLuint buffer);
 27.3238 +    typedef void (GLAPIENTRY * PFNGLVERTEXARRAYVERTEXBUFFERPROC) (GLuint vaobj, GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride);
 27.3239 +    typedef void (GLAPIENTRY * PFNGLVERTEXARRAYVERTEXBUFFERSPROC) (GLuint vaobj, GLuint first, GLsizei count, const GLuint* buffers, const GLintptr *offsets, const GLsizei *strides);
 27.3240 +
 27.3241 +    #define glBindTextureUnit GLEGetCurrentFunction(glBindTextureUnit)
 27.3242 +    #define glBlitNamedFramebuffer GLEGetCurrentFunction(glBlitNamedFramebuffer)
 27.3243 +    #define glCheckNamedFramebufferStatus GLEGetCurrentFunction(glCheckNamedFramebufferStatus)
 27.3244 +    #define glClearNamedBufferData GLEGetCurrentFunction(glClearNamedBufferData)
 27.3245 +    #define glClearNamedBufferSubData GLEGetCurrentFunction(glClearNamedBufferSubData)
 27.3246 +    #define glClearNamedFramebufferfi GLEGetCurrentFunction(glClearNamedFramebufferfi)
 27.3247 +    #define glClearNamedFramebufferfv GLEGetCurrentFunction(glClearNamedFramebufferfv)
 27.3248 +    #define glClearNamedFramebufferiv GLEGetCurrentFunction(glClearNamedFramebufferiv)
 27.3249 +    #define glClearNamedFramebufferuiv GLEGetCurrentFunction(glClearNamedFramebufferuiv)
 27.3250 +    #define glCompressedTextureSubImage1D GLEGetCurrentFunction(glCompressedTextureSubImage1D)
 27.3251 +    #define glCompressedTextureSubImage2D GLEGetCurrentFunction(glCompressedTextureSubImage2D)
 27.3252 +    #define glCompressedTextureSubImage3D GLEGetCurrentFunction(glCompressedTextureSubImage3D)
 27.3253 +    #define glCopyNamedBufferSubData GLEGetCurrentFunction(glCopyNamedBufferSubData)
 27.3254 +    #define glCopyTextureSubImage1D GLEGetCurrentFunction(glCopyTextureSubImage1D)
 27.3255 +    #define glCopyTextureSubImage2D GLEGetCurrentFunction(glCopyTextureSubImage2D)
 27.3256 +    #define glCopyTextureSubImage3D GLEGetCurrentFunction(glCopyTextureSubImage3D)
 27.3257 +    #define glCreateBuffers GLEGetCurrentFunction(glCreateBuffers)
 27.3258 +    #define glCreateFramebuffers GLEGetCurrentFunction(glCreateFramebuffers)
 27.3259 +    #define glCreateProgramPipelines GLEGetCurrentFunction(glCreateProgramPipelines)
 27.3260 +    #define glCreateQueries GLEGetCurrentFunction(glCreateQueries)
 27.3261 +    #define glCreateRenderbuffers GLEGetCurrentFunction(glCreateRenderbuffers)
 27.3262 +    #define glCreateSamplers GLEGetCurrentFunction(glCreateSamplers)
 27.3263 +    #define glCreateTextures GLEGetCurrentFunction(glCreateTextures)
 27.3264 +    #define glCreateTransformFeedbacks GLEGetCurrentFunction(glCreateTransformFeedbacks)
 27.3265 +    #define glCreateVertexArrays GLEGetCurrentFunction(glCreateVertexArrays)
 27.3266 +    #define glDisableVertexArrayAttrib GLEGetCurrentFunction(glDisableVertexArrayAttrib)
 27.3267 +    #define glEnableVertexArrayAttrib GLEGetCurrentFunction(glEnableVertexArrayAttrib)
 27.3268 +    #define glFlushMappedNamedBufferRange GLEGetCurrentFunction(glFlushMappedNamedBufferRange)
 27.3269 +    #define glGenerateTextureMipmap GLEGetCurrentFunction(glGenerateTextureMipmap)
 27.3270 +    #define glGetCompressedTextureImage GLEGetCurrentFunction(glGetCompressedTextureImage)
 27.3271 +    #define glGetNamedBufferParameteri64v GLEGetCurrentFunction(glGetNamedBufferParameteri64v)
 27.3272 +    #define glGetNamedBufferParameteriv GLEGetCurrentFunction(glGetNamedBufferParameteriv)
 27.3273 +    #define glGetNamedBufferPointerv GLEGetCurrentFunction(glGetNamedBufferPointerv)
 27.3274 +    #define glGetNamedBufferSubData GLEGetCurrentFunction(glGetNamedBufferSubData)
 27.3275 +    #define glGetNamedFramebufferAttachmentParameteriv GLEGetCurrentFunction(glGetNamedFramebufferAttachmentParameteriv)
 27.3276 +    #define glGetNamedFramebufferParameteriv GLEGetCurrentFunction(glGetNamedFramebufferParameteriv)
 27.3277 +    #define glGetNamedRenderbufferParameteriv GLEGetCurrentFunction(glGetNamedRenderbufferParameteriv)
 27.3278 +    #define glGetTextureImage GLEGetCurrentFunction(glGetTextureImage)
 27.3279 +    #define glGetTextureLevelParameterfv GLEGetCurrentFunction(glGetTextureLevelParameterfv)
 27.3280 +    #define glGetTextureLevelParameteriv GLEGetCurrentFunction(glGetTextureLevelParameteriv)
 27.3281 +    #define glGetTextureParameterIiv GLEGetCurrentFunction(glGetTextureParameterIiv)
 27.3282 +    #define glGetTextureParameterIuiv GLEGetCurrentFunction(glGetTextureParameterIuiv)
 27.3283 +    #define glGetTextureParameterfv GLEGetCurrentFunction(glGetTextureParameterfv)
 27.3284 +    #define glGetTextureParameteriv GLEGetCurrentFunction(glGetTextureParameteriv)
 27.3285 +    #define glGetTransformFeedbacki64_v GLEGetCurrentFunction(glGetTransformFeedbacki64_v)
 27.3286 +    #define glGetTransformFeedbacki_v GLEGetCurrentFunction(glGetTransformFeedbacki_v)
 27.3287 +    #define glGetTransformFeedbackiv GLEGetCurrentFunction(glGetTransformFeedbackiv)
 27.3288 +    #define glGetVertexArrayIndexed64iv GLEGetCurrentFunction(glGetVertexArrayIndexed64iv)
 27.3289 +    #define glGetVertexArrayIndexediv GLEGetCurrentFunction(glGetVertexArrayIndexediv)
 27.3290 +    #define glGetVertexArrayiv GLEGetCurrentFunction(glGetVertexArrayiv)
 27.3291 +    #define glInvalidateNamedFramebufferData GLEGetCurrentFunction(glInvalidateNamedFramebufferData)
 27.3292 +    #define glInvalidateNamedFramebufferSubData GLEGetCurrentFunction(glInvalidateNamedFramebufferSubData)
 27.3293 +    #define glMapNamedBuffer GLEGetCurrentFunction(glMapNamedBuffer)
 27.3294 +    #define glMapNamedBufferRange GLEGetCurrentFunction(glMapNamedBufferRange)
 27.3295 +    #define glNamedBufferData GLEGetCurrentFunction(glNamedBufferData)
 27.3296 +    #define glNamedBufferStorage GLEGetCurrentFunction(glNamedBufferStorage)
 27.3297 +    #define glNamedBufferSubData GLEGetCurrentFunction(glNamedBufferSubData)
 27.3298 +    #define glNamedFramebufferDrawBuffer GLEGetCurrentFunction(glNamedFramebufferDrawBuffer)
 27.3299 +    #define glNamedFramebufferDrawBuffers GLEGetCurrentFunction(glNamedFramebufferDrawBuffers)
 27.3300 +    #define glNamedFramebufferParameteri GLEGetCurrentFunction(glNamedFramebufferParameteri)
 27.3301 +    #define glNamedFramebufferReadBuffer GLEGetCurrentFunction(glNamedFramebufferReadBuffer)
 27.3302 +    #define glNamedFramebufferRenderbuffer GLEGetCurrentFunction(glNamedFramebufferRenderbuffer)
 27.3303 +    #define glNamedFramebufferTexture GLEGetCurrentFunction(glNamedFramebufferTexture)
 27.3304 +    #define glNamedFramebufferTextureLayer GLEGetCurrentFunction(glNamedFramebufferTextureLayer)
 27.3305 +    #define glNamedRenderbufferStorage GLEGetCurrentFunction(glNamedRenderbufferStorage)
 27.3306 +    #define glNamedRenderbufferStorageMultisample GLEGetCurrentFunction(glNamedRenderbufferStorageMultisample)
 27.3307 +    #define glTextureBuffer GLEGetCurrentFunction(glTextureBuffer)
 27.3308 +    #define glTextureBufferRange GLEGetCurrentFunction(glTextureBufferRange)
 27.3309 +    #define glTextureParameterIiv GLEGetCurrentFunction(glTextureParameterIiv)
 27.3310 +    #define glTextureParameterIuiv GLEGetCurrentFunction(glTextureParameterIuiv)
 27.3311 +    #define glTextureParameterf GLEGetCurrentFunction(glTextureParameterf)
 27.3312 +    #define glTextureParameterfv GLEGetCurrentFunction(glTextureParameterfv)
 27.3313 +    #define glTextureParameteri GLEGetCurrentFunction(glTextureParameteri)
 27.3314 +    #define glTextureParameteriv GLEGetCurrentFunction(glTextureParameteriv)
 27.3315 +    #define glTextureStorage1D GLEGetCurrentFunction(glTextureStorage1D)
 27.3316 +    #define glTextureStorage2D GLEGetCurrentFunction(glTextureStorage2D)
 27.3317 +    #define glTextureStorage2DMultisample GLEGetCurrentFunction(glTextureStorage2DMultisample)
 27.3318 +    #define glTextureStorage3D GLEGetCurrentFunction(glTextureStorage3D)
 27.3319 +    #define glTextureStorage3DMultisample GLEGetCurrentFunction(glTextureStorage3DMultisample)
 27.3320 +    #define glTextureSubImage1D GLEGetCurrentFunction(glTextureSubImage1D)
 27.3321 +    #define glTextureSubImage2D GLEGetCurrentFunction(glTextureSubImage2D)
 27.3322 +    #define glTextureSubImage3D GLEGetCurrentFunction(glTextureSubImage3D)
 27.3323 +    #define glTransformFeedbackBufferBase GLEGetCurrentFunction(glTransformFeedbackBufferBase)
 27.3324 +    #define glTransformFeedbackBufferRange GLEGetCurrentFunction(glTransformFeedbackBufferRange)
 27.3325 +    #define glUnmapNamedBuffer GLEGetCurrentFunction(glUnmapNamedBuffer)
 27.3326 +    #define glVertexArrayAttribBinding GLEGetCurrentFunction(glVertexArrayAttribBinding)
 27.3327 +    #define glVertexArrayAttribFormat GLEGetCurrentFunction(glVertexArrayAttribFormat)
 27.3328 +    #define glVertexArrayAttribIFormat GLEGetCurrentFunction(glVertexArrayAttribIFormat)
 27.3329 +    #define glVertexArrayAttribLFormat GLEGetCurrentFunction(glVertexArrayAttribLFormat)
 27.3330 +    #define glVertexArrayBindingDivisor GLEGetCurrentFunction(glVertexArrayBindingDivisor)
 27.3331 +    #define glVertexArrayElementBuffer GLEGetCurrentFunction(glVertexArrayElementBuffer)
 27.3332 +    #define glVertexArrayVertexBuffer GLEGetCurrentFunction(glVertexArrayVertexBuffer)
 27.3333 +    #define glVertexArrayVertexBuffers GLEGetCurrentFunction(glVertexArrayVertexBuffers)
 27.3334 +
 27.3335 +    #define GLE_ARB_direct_state_access GLEGetCurrentVariable(gle_ARB_direct_state_access)
 27.3336 +#endif // GL_ARB_direct_state_access */
 27.3337 +
 27.3338 +
 27.3339 +
 27.3340 +#ifndef GL_ARB_ES2_compatibility
 27.3341 +    #define GL_ARB_ES2_compatibility 1
 27.3342 +
 27.3343 +    // This is for OpenGL ES compatibility.
 27.3344 +    #define GL_FIXED 0x140C
 27.3345 +    #define GL_IMPLEMENTATION_COLOR_READ_TYPE 0x8B9A
 27.3346 +    #define GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B
 27.3347 +    #define GL_RGB565 0x8D62
 27.3348 +    #define GL_LOW_FLOAT 0x8DF0
 27.3349 +    #define GL_MEDIUM_FLOAT 0x8DF1
 27.3350 +    #define GL_HIGH_FLOAT 0x8DF2
 27.3351 +    #define GL_LOW_INT 0x8DF3
 27.3352 +    #define GL_MEDIUM_INT 0x8DF4
 27.3353 +    #define GL_HIGH_INT 0x8DF5
 27.3354 +    #define GL_SHADER_BINARY_FORMATS 0x8DF8
 27.3355 +    #define GL_NUM_SHADER_BINARY_FORMATS 0x8DF9
 27.3356 +    #define GL_SHADER_COMPILER 0x8DFA
 27.3357 +    #define GL_MAX_VERTEX_UNIFORM_VECTORS 0x8DFB
 27.3358 +    #define GL_MAX_VARYING_VECTORS 0x8DFC
 27.3359 +    #define GL_MAX_FRAGMENT_UNIFORM_VECTORS 0x8DFD
 27.3360 +
 27.3361 +    typedef int GLfixed;
 27.3362 +
 27.3363 +    typedef void (GLAPIENTRY * PFNGLCLEARDEPTHFPROC) (GLclampf d);
 27.3364 +    typedef void (GLAPIENTRY * PFNGLDEPTHRANGEFPROC) (GLclampf n, GLclampf f);
 27.3365 +    typedef void (GLAPIENTRY * PFNGLGETSHADERPRECISIONFORMATPROC) (GLenum shadertype, GLenum precisiontype, GLint* range, GLint *precision);
 27.3366 +    typedef void (GLAPIENTRY * PFNGLRELEASESHADERCOMPILERPROC) (void);
 27.3367 +    typedef void (GLAPIENTRY * PFNGLSHADERBINARYPROC) (GLsizei count, const GLuint* shaders, GLenum binaryformat, const void*binary, GLsizei length);
 27.3368 +
 27.3369 +    #define glClearDepthf              GLEGetCurrentFunction(glClearDepthf)
 27.3370 +    #define glDepthRangef              GLEGetCurrentFunction(glDepthRangef)
 27.3371 +    #define glGetShaderPrecisionFormat GLEGetCurrentFunction(glGetShaderPrecisionFormat)
 27.3372 +    #define glReleaseShaderCompiler    GLEGetCurrentFunction(glReleaseShaderCompiler)
 27.3373 +    #define glShaderBinary             GLEGetCurrentFunction(glShaderBinary)
 27.3374 +
 27.3375 +    #define GLE_ARB_ES2_compatibility GLEGetCurrentVariable(gle_ARB_ES2_compatibility)
 27.3376 +#endif
 27.3377 +
 27.3378 +
 27.3379 +
 27.3380 +#ifndef GL_ARB_framebuffer_object
 27.3381 +    #define GL_ARB_framebuffer_object 1
 27.3382 +
 27.3383 +    // GL_ARB_framebuffer_object is part of the OpenGL 4.4 core profile.
 27.3384 +    #define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506
 27.3385 +    #define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING 0x8210
 27.3386 +    #define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE 0x8211
 27.3387 +    #define GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE 0x8212
 27.3388 +    #define GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE 0x8213
 27.3389 +    #define GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE 0x8214
 27.3390 +    #define GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE 0x8215
 27.3391 +    #define GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE 0x8216
 27.3392 +    #define GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE 0x8217
 27.3393 +    #define GL_FRAMEBUFFER_DEFAULT 0x8218
 27.3394 +    #define GL_FRAMEBUFFER_UNDEFINED 0x8219
 27.3395 +    #define GL_DEPTH_STENCIL_ATTACHMENT 0x821A
 27.3396 +    #define GL_INDEX 0x8222
 27.3397 +    #define GL_MAX_RENDERBUFFER_SIZE 0x84E8
 27.3398 +    #define GL_DEPTH_STENCIL 0x84F9
 27.3399 +    #define GL_UNSIGNED_INT_24_8 0x84FA
 27.3400 +    #define GL_DEPTH24_STENCIL8 0x88F0
 27.3401 +    #define GL_TEXTURE_STENCIL_SIZE 0x88F1
 27.3402 +    #define GL_UNSIGNED_NORMALIZED 0x8C17
 27.3403 +    #define GL_SRGB 0x8C40
 27.3404 +    #define GL_DRAW_FRAMEBUFFER_BINDING 0x8CA6
 27.3405 +    #define GL_FRAMEBUFFER_BINDING 0x8CA6
 27.3406 +    #define GL_RENDERBUFFER_BINDING 0x8CA7
 27.3407 +    #define GL_READ_FRAMEBUFFER 0x8CA8
 27.3408 +    #define GL_DRAW_FRAMEBUFFER 0x8CA9
 27.3409 +    #define GL_READ_FRAMEBUFFER_BINDING 0x8CAA
 27.3410 +    #define GL_RENDERBUFFER_SAMPLES 0x8CAB
 27.3411 +    #define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0
 27.3412 +    #define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1
 27.3413 +    #define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2
 27.3414 +    #define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3
 27.3415 +    #define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER 0x8CD4
 27.3416 +    #define GL_FRAMEBUFFER_COMPLETE 0x8CD5
 27.3417 +    #define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6
 27.3418 +    #define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7
 27.3419 +    #define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER 0x8CDB
 27.3420 +    #define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER 0x8CDC
 27.3421 +    #define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD
 27.3422 +    #define GL_MAX_COLOR_ATTACHMENTS 0x8CDF
 27.3423 +    #define GL_COLOR_ATTACHMENT0 0x8CE0
 27.3424 +    #define GL_COLOR_ATTACHMENT1 0x8CE1
 27.3425 +    #define GL_COLOR_ATTACHMENT2 0x8CE2
 27.3426 +    #define GL_COLOR_ATTACHMENT3 0x8CE3
 27.3427 +    #define GL_COLOR_ATTACHMENT4 0x8CE4
 27.3428 +    #define GL_COLOR_ATTACHMENT5 0x8CE5
 27.3429 +    #define GL_COLOR_ATTACHMENT6 0x8CE6
 27.3430 +    #define GL_COLOR_ATTACHMENT7 0x8CE7
 27.3431 +    #define GL_COLOR_ATTACHMENT8 0x8CE8
 27.3432 +    #define GL_COLOR_ATTACHMENT9 0x8CE9
 27.3433 +    #define GL_COLOR_ATTACHMENT10 0x8CEA
 27.3434 +    #define GL_COLOR_ATTACHMENT11 0x8CEB
 27.3435 +    #define GL_COLOR_ATTACHMENT12 0x8CEC
 27.3436 +    #define GL_COLOR_ATTACHMENT13 0x8CED
 27.3437 +    #define GL_COLOR_ATTACHMENT14 0x8CEE
 27.3438 +    #define GL_COLOR_ATTACHMENT15 0x8CEF
 27.3439 +    #define GL_DEPTH_ATTACHMENT 0x8D00
 27.3440 +    #define GL_STENCIL_ATTACHMENT 0x8D20
 27.3441 +    #define GL_FRAMEBUFFER 0x8D40
 27.3442 +    #define GL_RENDERBUFFER 0x8D41
 27.3443 +    #define GL_RENDERBUFFER_WIDTH 0x8D42
 27.3444 +    #define GL_RENDERBUFFER_HEIGHT 0x8D43
 27.3445 +    #define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44
 27.3446 +    #define GL_STENCIL_INDEX1 0x8D46
 27.3447 +    #define GL_STENCIL_INDEX4 0x8D47
 27.3448 +    #define GL_STENCIL_INDEX8 0x8D48
 27.3449 +    #define GL_STENCIL_INDEX16 0x8D49
 27.3450 +    #define GL_RENDERBUFFER_RED_SIZE 0x8D50
 27.3451 +    #define GL_RENDERBUFFER_GREEN_SIZE 0x8D51
 27.3452 +    #define GL_RENDERBUFFER_BLUE_SIZE 0x8D52
 27.3453 +    #define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53
 27.3454 +    #define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54
 27.3455 +    #define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55
 27.3456 +    #define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56
 27.3457 +    #define GL_MAX_SAMPLES 0x8D57
 27.3458 +
 27.3459 +    typedef void      (GLAPIENTRY * PFNGLBINDFRAMEBUFFERPROC) (GLenum target, GLuint framebuffer);
 27.3460 +    typedef void      (GLAPIENTRY * PFNGLBINDRENDERBUFFERPROC) (GLenum target, GLuint renderbuffer);
 27.3461 +    typedef void      (GLAPIENTRY * PFNGLBLITFRAMEBUFFERPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
 27.3462 +    typedef GLenum    (GLAPIENTRY * PFNGLCHECKFRAMEBUFFERSTATUSPROC) (GLenum target);
 27.3463 +    typedef void      (GLAPIENTRY * PFNGLDELETEFRAMEBUFFERSPROC) (GLsizei n, const GLuint* framebuffers);
 27.3464 +    typedef void      (GLAPIENTRY * PFNGLDELETERENDERBUFFERSPROC) (GLsizei n, const GLuint* renderbuffers);
 27.3465 +    typedef void      (GLAPIENTRY * PFNGLFRAMEBUFFERRENDERBUFFERPROC) (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
 27.3466 +    typedef void      (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURE1DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
 27.3467 +    typedef void      (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURE2DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
 27.3468 +    typedef void      (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURE3DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint layer);
 27.3469 +    typedef void      (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURELAYERPROC) (GLenum target,GLenum attachment, GLuint texture,GLint level,GLint layer);
 27.3470 +    typedef void      (GLAPIENTRY * PFNGLGENFRAMEBUFFERSPROC) (GLsizei n, GLuint* framebuffers);
 27.3471 +    typedef void      (GLAPIENTRY * PFNGLGENRENDERBUFFERSPROC) (GLsizei n, GLuint* renderbuffers);
 27.3472 +    typedef void      (GLAPIENTRY * PFNGLGENERATEMIPMAPPROC) (GLenum target);
 27.3473 +    typedef void      (GLAPIENTRY * PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC) (GLenum target, GLenum attachment, GLenum pname, GLint* params);
 27.3474 +    typedef void      (GLAPIENTRY * PFNGLGETRENDERBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint* params);
 27.3475 +    typedef GLboolean (GLAPIENTRY * PFNGLISFRAMEBUFFERPROC) (GLuint framebuffer);
 27.3476 +    typedef GLboolean (GLAPIENTRY * PFNGLISRENDERBUFFERPROC) (GLuint renderbuffer);
 27.3477 +    typedef void      (GLAPIENTRY * PFNGLRENDERBUFFERSTORAGEPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
 27.3478 +    typedef void      (GLAPIENTRY * PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
 27.3479 +
 27.3480 +    #define glBindFramebuffer                     GLEGetCurrentFunction(glBindFramebuffer)
 27.3481 +    #define glBindRenderbuffer                    GLEGetCurrentFunction(glBindRenderbuffer)
 27.3482 +    #define glBlitFramebuffer                     GLEGetCurrentFunction(glBlitFramebuffer)
 27.3483 +    #define glCheckFramebufferStatus              GLEGetCurrentFunction(glCheckFramebufferStatus)
 27.3484 +    #define glDeleteFramebuffers                  GLEGetCurrentFunction(glDeleteFramebuffers)
 27.3485 +    #define glDeleteRenderbuffers                 GLEGetCurrentFunction(glDeleteRenderbuffers)
 27.3486 +    #define glFramebufferRenderbuffer             GLEGetCurrentFunction(glFramebufferRenderbuffer)
 27.3487 +    #define glFramebufferTexture1D                GLEGetCurrentFunction(glFramebufferTexture1D)
 27.3488 +    #define glFramebufferTexture2D                GLEGetCurrentFunction(glFramebufferTexture2D)
 27.3489 +    #define glFramebufferTexture3D                GLEGetCurrentFunction(glFramebufferTexture3D)
 27.3490 +    #define glFramebufferTextureLayer             GLEGetCurrentFunction(glFramebufferTextureLayer)
 27.3491 +    #define glGenFramebuffers                     GLEGetCurrentFunction(glGenFramebuffers)
 27.3492 +    #define glGenRenderbuffers                    GLEGetCurrentFunction(glGenRenderbuffers)
 27.3493 +    #define glGenerateMipmap                      GLEGetCurrentFunction(glGenerateMipmap)
 27.3494 +    #define glGetFramebufferAttachmentParameteriv GLEGetCurrentFunction(glGetFramebufferAttachmentParameteriv)
 27.3495 +    #define glGetRenderbufferParameteriv          GLEGetCurrentFunction(glGetRenderbufferParameteriv)
 27.3496 +    #define glIsFramebuffer                       GLEGetCurrentFunction(glIsFramebuffer)
 27.3497 +    #define glIsRenderbuffer                      GLEGetCurrentFunction(glIsRenderbuffer)
 27.3498 +    #define glRenderbufferStorage                 GLEGetCurrentFunction(glRenderbufferStorage)
 27.3499 +    #define glRenderbufferStorageMultisample      GLEGetCurrentFunction(glRenderbufferStorageMultisample)
 27.3500 +
 27.3501 +    #define GLE_ARB_framebuffer_object GLEGetCurrentVariable(gle_ARB_framebuffer_object)
 27.3502 +
 27.3503 +#endif // GL_ARB_framebuffer_object
 27.3504 +
 27.3505 +
 27.3506 +
 27.3507 +#ifndef GL_ARB_framebuffer_sRGB
 27.3508 +    #define GL_ARB_framebuffer_sRGB 1
 27.3509 +
 27.3510 +    // GL_ARB_framebuffer_sRGB is part of the OpenGL 4.4 core profile.
 27.3511 +    #define GL_FRAMEBUFFER_SRGB 0x8DB9
 27.3512 +
 27.3513 +    #define GLE_ARB_framebuffer_sRGB GLEGetCurrentVariable(gle_ARB_framebuffer_sRGB)
 27.3514 +#endif
 27.3515 +
 27.3516 +
 27.3517 +
 27.3518 +#ifndef GL_ARB_texture_multisample
 27.3519 +    #define GL_ARB_texture_multisample 1
 27.3520 +
 27.3521 +    #define GL_SAMPLE_POSITION 0x8E50
 27.3522 +    #define GL_SAMPLE_MASK 0x8E51
 27.3523 +    #define GL_SAMPLE_MASK_VALUE 0x8E52
 27.3524 +    #define GL_MAX_SAMPLE_MASK_WORDS 0x8E59
 27.3525 +    #define GL_TEXTURE_2D_MULTISAMPLE 0x9100
 27.3526 +    #define GL_PROXY_TEXTURE_2D_MULTISAMPLE 0x9101
 27.3527 +    #define GL_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9102
 27.3528 +    #define GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9103
 27.3529 +    #define GL_TEXTURE_BINDING_2D_MULTISAMPLE 0x9104
 27.3530 +    #define GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY 0x9105
 27.3531 +    #define GL_TEXTURE_SAMPLES 0x9106
 27.3532 +    #define GL_TEXTURE_FIXED_SAMPLE_LOCATIONS 0x9107
 27.3533 +    #define GL_SAMPLER_2D_MULTISAMPLE 0x9108
 27.3534 +    #define GL_INT_SAMPLER_2D_MULTISAMPLE 0x9109
 27.3535 +    #define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE 0x910A
 27.3536 +    #define GL_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910B
 27.3537 +    #define GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910C
 27.3538 +    #define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910D
 27.3539 +    #define GL_MAX_COLOR_TEXTURE_SAMPLES 0x910E
 27.3540 +    #define GL_MAX_DEPTH_TEXTURE_SAMPLES 0x910F
 27.3541 +    #define GL_MAX_INTEGER_SAMPLES 0x9110
 27.3542 +
 27.3543 +    typedef void (GLAPIENTRY * PFNGLGETMULTISAMPLEFVPROC) (GLenum pname, GLuint index, GLfloat* val);
 27.3544 +    typedef void (GLAPIENTRY * PFNGLSAMPLEMASKIPROC) (GLuint index, GLbitfield mask);
 27.3545 +    typedef void (GLAPIENTRY * PFNGLTEXIMAGE2DMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations);
 27.3546 +    typedef void (GLAPIENTRY * PFNGLTEXIMAGE3DMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations);
 27.3547 +
 27.3548 +    #define glGetMultisamplefv      GLEGetCurrentFunction(glGetMultisamplefv)
 27.3549 +    #define glSampleMaski           GLEGetCurrentFunction(glSampleMaski)
 27.3550 +    #define glTexImage2DMultisample GLEGetCurrentFunction(glTexImage2DMultisample)
 27.3551 +    #define glTexImage3DMultisample GLEGetCurrentFunction(glTexImage3DMultisample)
 27.3552 +
 27.3553 +    #define GLE_ARB_texture_multisample GLEGetCurrentVariable(gle_ARB_texture_multisample)
 27.3554 +
 27.3555 +#endif // GL_ARB_texture_multisample
 27.3556 +
 27.3557 +
 27.3558 +
 27.3559 +#ifndef GL_ARB_texture_non_power_of_two
 27.3560 +    #define GL_ARB_texture_non_power_of_two 1
 27.3561 +
 27.3562 +    #define GLE_ARB_texture_non_power_of_two GLEGetCurrentVariable(gle_ARB_texture_non_power_of_two)
 27.3563 +#endif
 27.3564 +
 27.3565 +
 27.3566 +
 27.3567 +#ifndef GL_ARB_texture_rectangle
 27.3568 +    #define GL_ARB_texture_rectangle 1
 27.3569 +
 27.3570 +    // texture_rectangle was added to the OpenGL 3.1 core profile and so this extension is not needed
 27.3571 +    // unless using an earlier version of OpenGL.
 27.3572 +    // There are also the GL_EXT_texture_rectangle and GL_NV_texture_rectangle extensions. Apple reports
 27.3573 +    // the preseence of GL_EXT_texture_rectangle but not GL_ARB_texture_rectangle or GL_NV_texture_rectangle.
 27.3574 +    // You should check for GL_ARB_texture_rectangle instead of these other two.
 27.3575 +    #define GL_TEXTURE_RECTANGLE_ARB          0x84F5
 27.3576 +    #define GL_TEXTURE_BINDING_RECTANGLE_ARB  0x84F6
 27.3577 +    #define GL_PROXY_TEXTURE_RECTANGLE_ARB    0x84F7
 27.3578 +    #define GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB 0x84F8
 27.3579 +    #define GL_SAMPLER_2D_RECT_ARB            0x8B63
 27.3580 +    #define GL_SAMPLER_2D_RECT_SHADOW_ARB     0x8B64
 27.3581 +
 27.3582 +    #define GLE_ARB_texture_rectangle GLEGetCurrentVariable(gle_ARB_texture_rectangle)
 27.3583 +#endif
 27.3584 +
 27.3585 +
 27.3586 +
 27.3587 +#ifndef GL_ARB_timer_query
 27.3588 +    #define GL_ARB_timer_query 1
 27.3589 +
 27.3590 +    #define GL_TIME_ELAPSED 0x88BF
 27.3591 +    #define GL_TIMESTAMP 0x8E28
 27.3592 +
 27.3593 +    typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTI64VPROC) (GLuint id, GLenum pname, GLint64* params);
 27.3594 +    typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTUI64VPROC) (GLuint id, GLenum pname, GLuint64* params);
 27.3595 +    typedef void (GLAPIENTRY * PFNGLQUERYCOUNTERPROC) (GLuint id, GLenum target);
 27.3596 +
 27.3597 +    #define glGetQueryObjecti64v  GLEGetCurrentFunction(glGetQueryObjecti64v)
 27.3598 +    #define glGetQueryObjectui64v GLEGetCurrentFunction(glGetQueryObjectui64v)
 27.3599 +    #define glQueryCounter        GLEGetCurrentFunction(glQueryCounter)
 27.3600 +
 27.3601 +    #define GLE_ARB_timer_query GLEGetCurrentVariable(gle_ARB_timer_query)
 27.3602 +#endif
 27.3603 +
 27.3604 +
 27.3605 +
 27.3606 +#ifndef GL_ARB_vertex_array_object
 27.3607 +    #define GL_ARB_vertex_array_object 1
 27.3608 +
 27.3609 +    #define GL_VERTEX_ARRAY_BINDING 0x85B5
 27.3610 +
 27.3611 +    typedef void      (GLAPIENTRY * PFNGLBINDVERTEXARRAYPROC) (GLuint array);
 27.3612 +    typedef void      (GLAPIENTRY * PFNGLDELETEVERTEXARRAYSPROC) (GLsizei n, const GLuint* arrays);
 27.3613 +    typedef void      (GLAPIENTRY * PFNGLGENVERTEXARRAYSPROC) (GLsizei n, GLuint* arrays);
 27.3614 +    typedef GLboolean (GLAPIENTRY * PFNGLISVERTEXARRAYPROC) (GLuint array);
 27.3615 +
 27.3616 +    #define glBindVertexArray    GLEGetCurrentFunction(glBindVertexArray)
 27.3617 +    #define glDeleteVertexArrays GLEGetCurrentFunction(glDeleteVertexArrays)
 27.3618 +    #define glGenVertexArrays    GLEGetCurrentFunction(glGenVertexArrays)
 27.3619 +    #define glIsVertexArray      GLEGetCurrentFunction(glIsVertexArray)
 27.3620 +
 27.3621 +    #define GLE_ARB_vertex_array_object GLEGetCurrentVariable(gle_ARB_vertex_array_object)
 27.3622 +#endif
 27.3623 +
 27.3624 +
 27.3625 +
 27.3626 +/* Disabled until needed
 27.3627 +#ifndef GL_ARB_vertex_attrib_binding
 27.3628 +    #define GL_ARB_vertex_attrib_binding 1
 27.3629 +
 27.3630 +    #define GL_VERTEX_ATTRIB_BINDING 0x82D4
 27.3631 +    #define GL_VERTEX_ATTRIB_RELATIVE_OFFSET 0x82D5
 27.3632 +    #define GL_VERTEX_BINDING_DIVISOR 0x82D6
 27.3633 +    #define GL_VERTEX_BINDING_OFFSET 0x82D7
 27.3634 +    #define GL_VERTEX_BINDING_STRIDE 0x82D8
 27.3635 +    #define GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET 0x82D9
 27.3636 +    #define GL_MAX_VERTEX_ATTRIB_BINDINGS 0x82DA
 27.3637 +    #define GL_VERTEX_BINDING_BUFFER 0x8F4F
 27.3638 +
 27.3639 +    typedef void (GLAPIENTRY * PFNGLBINDVERTEXBUFFERPROC) (GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride);
 27.3640 +    typedef void (GLAPIENTRY * PFNGLVERTEXARRAYBINDVERTEXBUFFEREXTPROC) (GLuint vaobj, GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride);
 27.3641 +    typedef void (GLAPIENTRY * PFNGLVERTEXARRAYVERTEXATTRIBBINDINGEXTPROC) (GLuint vaobj, GLuint attribindex, GLuint bindingindex);
 27.3642 +    typedef void (GLAPIENTRY * PFNGLVERTEXARRAYVERTEXATTRIBFORMATEXTPROC) (GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset);
 27.3643 +    typedef void (GLAPIENTRY * PFNGLVERTEXARRAYVERTEXATTRIBIFORMATEXTPROC) (GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
 27.3644 +    typedef void (GLAPIENTRY * PFNGLVERTEXARRAYVERTEXATTRIBLFORMATEXTPROC) (GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
 27.3645 +    typedef void (GLAPIENTRY * PFNGLVERTEXARRAYVERTEXBINDINGDIVISOREXTPROC) (GLuint vaobj, GLuint bindingindex, GLuint divisor);
 27.3646 +    typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBBINDINGPROC) (GLuint attribindex, GLuint bindingindex);
 27.3647 +    typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBFORMATPROC) (GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset);
 27.3648 +    typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBIFORMATPROC) (GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
 27.3649 +    typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBLFORMATPROC) (GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
 27.3650 +    typedef void (GLAPIENTRY * PFNGLVERTEXBINDINGDIVISORPROC) (GLuint bindingindex, GLuint divisor);
 27.3651 +
 27.3652 +    #define glBindVertexBuffer GLEGetCurrentFunction(glBindVertexBuffer)
 27.3653 +    #define glVertexArrayBindVertexBufferEXT GLEGetCurrentFunction(glVertexArrayBindVertexBufferEXT)
 27.3654 +    #define glVertexArrayVertexAttribBindingEXT GLEGetCurrentFunction(glVertexArrayVertexAttribBindingEXT)
 27.3655 +    #define glVertexArrayVertexAttribFormatEXT GLEGetCurrentFunction(glVertexArrayVertexAttribFormatEXT)
 27.3656 +    #define glVertexArrayVertexAttribIFormatEXT GLEGetCurrentFunction(glVertexArrayVertexAttribIFormatEXT)
 27.3657 +    #define glVertexArrayVertexAttribLFormatEXT GLEGetCurrentFunction(glVertexArrayVertexAttribLFormatEXT)
 27.3658 +    #define glVertexArrayVertexBindingDivisorEXT GLEGetCurrentFunction(glVertexArrayVertexBindingDivisorEXT)
 27.3659 +    #define glVertexAttribBinding GLEGetCurrentFunction(glVertexAttribBinding)
 27.3660 +    #define glVertexAttribFormat GLEGetCurrentFunction(glVertexAttribFormat)
 27.3661 +    #define glVertexAttribIFormat GLEGetCurrentFunction(glVertexAttribIFormat)
 27.3662 +    #define glVertexAttribLFormat GLEGetCurrentFunction(glVertexAttribLFormat)
 27.3663 +    #define glVertexBindingDivisor GLEGetCurrentFunction(glVertexBindingDivisor)
 27.3664 +
 27.3665 +    #define GLE_ARB_vertex_attrib_binding GLEGetCurrentVariable(gle_ARB_vertex_attrib_binding)
 27.3666 +#endif
 27.3667 +*/
 27.3668 +
 27.3669 +
 27.3670 +#ifndef GL_EXT_draw_buffers2
 27.3671 +    #define GL_EXT_draw_buffers2 1
 27.3672 +
 27.3673 +    typedef void      (GLAPIENTRY * PFNGLCOLORMASKINDEXEDEXTPROC) (GLuint buf, GLboolean r, GLboolean g, GLboolean b, GLboolean a);
 27.3674 +    typedef void      (GLAPIENTRY * PFNGLDISABLEINDEXEDEXTPROC) (GLenum target, GLuint index);
 27.3675 +    typedef void      (GLAPIENTRY * PFNGLENABLEINDEXEDEXTPROC) (GLenum target, GLuint index);
 27.3676 +    typedef void      (GLAPIENTRY * PFNGLGETBOOLEANINDEXEDVEXTPROC) (GLenum value, GLuint index, GLboolean* data);
 27.3677 +    typedef void      (GLAPIENTRY * PFNGLGETINTEGERINDEXEDVEXTPROC) (GLenum value, GLuint index, GLint* data);
 27.3678 +    typedef GLboolean (GLAPIENTRY * PFNGLISENABLEDINDEXEDEXTPROC) (GLenum target, GLuint index);
 27.3679 +
 27.3680 +    #define glColorMaskIndexedEXT   GLEGetCurrentFunction(glColorMaskIndexedEXT)
 27.3681 +    #define glDisableIndexedEXT     GLEGetCurrentFunction(glDisableIndexedEXT)
 27.3682 +    #define glEnableIndexedEXT      GLEGetCurrentFunction(glEnableIndexedEXT)
 27.3683 +    #define glGetBooleanIndexedvEXT GLEGetCurrentFunction(glGetBooleanIndexedvEXT)
 27.3684 +    #define glGetIntegerIndexedvEXT GLEGetCurrentFunction(glGetIntegerIndexedvEXT)
 27.3685 +    #define glIsEnabledIndexedEXT   GLEGetCurrentFunction(glIsEnabledIndexedEXT)
 27.3686 +
 27.3687 +    #define GLE_EXT_draw_buffers2 GLEGetCurrentVariable(gle_EXT_draw_buffers2)
 27.3688 +#endif
 27.3689 +
 27.3690 +
 27.3691 +
 27.3692 +#ifndef GL_EXT_texture_compression_s3tc
 27.3693 +    #define GL_EXT_texture_compression_s3tc 1
 27.3694 +
 27.3695 +    #define GL_COMPRESSED_RGB_S3TC_DXT1_EXT  0x83F0
 27.3696 +    #define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1
 27.3697 +    #define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2
 27.3698 +    #define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3
 27.3699 +
 27.3700 +    #define GLE_EXT_texture_compression_s3tc GLEGetCurrentVariable(gle_EXT_texture_compression_s3tc)
 27.3701 +#endif
 27.3702 +
 27.3703 +
 27.3704 +
 27.3705 +#ifndef GL_EXT_texture_filter_anisotropic
 27.3706 +    #define GL_EXT_texture_filter_anisotropic 1
 27.3707 +
 27.3708 +    #define GL_TEXTURE_MAX_ANISOTROPY_EXT     0x84FE
 27.3709 +    #define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF
 27.3710 +
 27.3711 +    #define GLE_EXT_texture_filter_anisotropic GLEGetCurrentVariable(gle_EXT_texture_filter_anisotropic)
 27.3712 +#endif
 27.3713 +
 27.3714 +
 27.3715 +
 27.3716 +/* Disabled until needed
 27.3717 +#ifndef GL_KHR_context_flush_control
 27.3718 +    #define GL_KHR_context_flush_control 1
 27.3719 +
 27.3720 +    #define GLE_KHR_context_flush_control GLEGetCurrentVariable(gle_KHR_context_flush_control)
 27.3721 +#endif
 27.3722 +*/
 27.3723 +
 27.3724 +
 27.3725 +
 27.3726 +#ifndef GL_KHR_debug
 27.3727 +    #define GL_KHR_debug 1
 27.3728 +
 27.3729 +    #define GL_CONTEXT_FLAG_DEBUG_BIT 0x00000002
 27.3730 +    #define GL_STACK_OVERFLOW 0x0503
 27.3731 +    #define GL_STACK_UNDERFLOW 0x0504
 27.3732 +    #define GL_DEBUG_OUTPUT_SYNCHRONOUS 0x8242
 27.3733 +    #define GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH 0x8243
 27.3734 +    #define GL_DEBUG_CALLBACK_FUNCTION 0x8244
 27.3735 +    #define GL_DEBUG_CALLBACK_USER_PARAM 0x8245
 27.3736 +    #define GL_DEBUG_SOURCE_API 0x8246
 27.3737 +    #define GL_DEBUG_SOURCE_WINDOW_SYSTEM 0x8247
 27.3738 +    #define GL_DEBUG_SOURCE_SHADER_COMPILER 0x8248
 27.3739 +    #define GL_DEBUG_SOURCE_THIRD_PARTY 0x8249
 27.3740 +    #define GL_DEBUG_SOURCE_APPLICATION 0x824A
 27.3741 +    #define GL_DEBUG_SOURCE_OTHER 0x824B
 27.3742 +    #define GL_DEBUG_TYPE_ERROR 0x824C
 27.3743 +    #define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR 0x824D
 27.3744 +    #define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR 0x824E
 27.3745 +    #define GL_DEBUG_TYPE_PORTABILITY 0x824F
 27.3746 +    #define GL_DEBUG_TYPE_PERFORMANCE 0x8250
 27.3747 +    #define GL_DEBUG_TYPE_OTHER 0x8251
 27.3748 +    #define GL_DEBUG_TYPE_MARKER 0x8268
 27.3749 +    #define GL_DEBUG_TYPE_PUSH_GROUP 0x8269
 27.3750 +    #define GL_DEBUG_TYPE_POP_GROUP 0x826A
 27.3751 +    #define GL_DEBUG_SEVERITY_NOTIFICATION 0x826B
 27.3752 +    #define GL_MAX_DEBUG_GROUP_STACK_DEPTH 0x826C
 27.3753 +    #define GL_DEBUG_GROUP_STACK_DEPTH 0x826D
 27.3754 +    #define GL_BUFFER 0x82E0
 27.3755 +    #define GL_SHADER 0x82E1
 27.3756 +    #define GL_PROGRAM 0x82E2
 27.3757 +    #define GL_QUERY 0x82E3
 27.3758 +    #define GL_PROGRAM_PIPELINE 0x82E4
 27.3759 +    #define GL_SAMPLER 0x82E6
 27.3760 +    #define GL_DISPLAY_LIST 0x82E7
 27.3761 +    #define GL_MAX_LABEL_LENGTH 0x82E8
 27.3762 +    #define GL_MAX_DEBUG_MESSAGE_LENGTH 0x9143
 27.3763 +    #define GL_MAX_DEBUG_LOGGED_MESSAGES 0x9144
 27.3764 +    #define GL_DEBUG_LOGGED_MESSAGES 0x9145
 27.3765 +    #define GL_DEBUG_SEVERITY_HIGH 0x9146
 27.3766 +    #define GL_DEBUG_SEVERITY_MEDIUM 0x9147
 27.3767 +    #define GL_DEBUG_SEVERITY_LOW 0x9148
 27.3768 +    #define GL_DEBUG_OUTPUT 0x92E0
 27.3769 +
 27.3770 +    typedef void (GLAPIENTRY *GLDEBUGPROC)(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, const void* userParam);
 27.3771 +
 27.3772 +    typedef void   (GLAPIENTRY * PFNGLDEBUGMESSAGECALLBACKPROC) (GLDEBUGPROC callback, const void *userParam);
 27.3773 +    typedef void   (GLAPIENTRY * PFNGLDEBUGMESSAGECONTROLPROC) (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint* ids, GLboolean enabled);
 27.3774 +    typedef void   (GLAPIENTRY * PFNGLDEBUGMESSAGEINSERTPROC) (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* buf);
 27.3775 +    typedef GLuint (GLAPIENTRY * PFNGLGETDEBUGMESSAGELOGPROC) (GLuint count, GLsizei bufSize, GLenum* sources, GLenum* types, GLuint* ids, GLenum* severities, GLsizei* lengths, GLchar* messageLog);
 27.3776 +    typedef void   (GLAPIENTRY * PFNGLGETOBJECTLABELPROC) (GLenum identifier, GLuint name, GLsizei bufSize, GLsizei* length, GLchar *label);
 27.3777 +    typedef void   (GLAPIENTRY * PFNGLGETOBJECTPTRLABELPROC) (const void *ptr, GLsizei bufSize, GLsizei* length, GLchar *label);
 27.3778 +    typedef void   (GLAPIENTRY * PFNGLOBJECTLABELPROC) (GLenum identifier, GLuint name, GLsizei length, const GLchar* label);
 27.3779 +    typedef void   (GLAPIENTRY * PFNGLOBJECTPTRLABELPROC) (const void *ptr, GLsizei length, const GLchar* label);
 27.3780 +    typedef void   (GLAPIENTRY * PFNGLPOPDEBUGGROUPPROC) (void);
 27.3781 +    typedef void   (GLAPIENTRY * PFNGLPUSHDEBUGGROUPPROC) (GLenum source, GLuint id, GLsizei length, const GLchar * message);
 27.3782 +
 27.3783 +    #define glDebugMessageCallback GLEGetCurrentFunction(glDebugMessageCallback)
 27.3784 +    #define glDebugMessageControl GLEGetCurrentFunction(glDebugMessageControl)
 27.3785 +    #define glDebugMessageInsert GLEGetCurrentFunction(glDebugMessageInsert)
 27.3786 +    #define glGetDebugMessageLog GLEGetCurrentFunction(glGetDebugMessageLog)
 27.3787 +    #define glGetObjectLabel GLEGetCurrentFunction(glGetObjectLabel)
 27.3788 +    #define glGetObjectPtrLabel GLEGetCurrentFunction(glGetObjectPtrLabel)
 27.3789 +    #define glObjectLabel GLEGetCurrentFunction(glObjectLabel)
 27.3790 +    #define glObjectPtrLabel GLEGetCurrentFunction(glObjectPtrLabel)
 27.3791 +    #define glPopDebugGroup GLEGetCurrentFunction(glPopDebugGroup)
 27.3792 +    #define glPushDebugGroup GLEGetCurrentFunction(glPushDebugGroup)
 27.3793 +
 27.3794 +    #define GLE_KHR_debug GLEGetCurrentVariable(gle_KHR_debug)
 27.3795 +#endif // GL_KHR_debug
 27.3796 +
 27.3797 +
 27.3798 +
 27.3799 +#ifndef GL_KHR_robust_buffer_access_behavior
 27.3800 +    #define GL_KHR_robust_buffer_access_behavior 1
 27.3801 +
 27.3802 +    #define GLE_KHR_robust_buffer_access_behavior GLEGetCurrentVariable(gle_KHR_robust_buffer_access_behavior)
 27.3803 +#endif
 27.3804 +
 27.3805 +
 27.3806 +
 27.3807 +/* Disabled until needed
 27.3808 +#ifndef GL_KHR_robustness
 27.3809 +    #define GL_KHR_robustness 1
 27.3810 +
 27.3811 +    #define GL_CONTEXT_LOST 0x0507
 27.3812 +    #define GL_LOSE_CONTEXT_ON_RESET 0x8252
 27.3813 +    #define GL_GUILTY_CONTEXT_RESET 0x8253
 27.3814 +    #define GL_INNOCENT_CONTEXT_RESET 0x8254
 27.3815 +    #define GL_UNKNOWN_CONTEXT_RESET 0x8255
 27.3816 +    #define GL_RESET_NOTIFICATION_STRATEGY 0x8256
 27.3817 +    #define GL_NO_RESET_NOTIFICATION 0x8261
 27.3818 +    #define GL_CONTEXT_ROBUST_ACCESS 0x90F3
 27.3819 +
 27.3820 +    typedef void (GLAPIENTRY * PFNGLGETNUNIFORMFVPROC) (GLuint program, GLint location, GLsizei bufSize, GLfloat* params);
 27.3821 +    typedef void (GLAPIENTRY * PFNGLGETNUNIFORMIVPROC) (GLuint program, GLint location, GLsizei bufSize, GLint* params);
 27.3822 +    typedef void (GLAPIENTRY * PFNGLGETNUNIFORMUIVPROC) (GLuint program, GLint location, GLsizei bufSize, GLuint* params);
 27.3823 +    typedef void (GLAPIENTRY * PFNGLREADNPIXELSPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data);
 27.3824 +
 27.3825 +    #define glGetnUniformfv  GLEGetCurrentFunction(glGetnUniformfv)
 27.3826 +    #define glGetnUniformiv  GLEGetCurrentFunction(glGetnUniformiv)
 27.3827 +    #define glGetnUniformuiv GLEGetCurrentFunction(glGetnUniformuiv)
 27.3828 +    #define glReadnPixels    GLEGetCurrentFunction(glReadnPixels)
 27.3829 +
 27.3830 +    #define GLE_KHR_robustness GLEGetCurrentVariable(gle_KHR_robustness)
 27.3831 +
 27.3832 +#endif // GL_KHR_robustness
 27.3833 +*/
 27.3834 +
 27.3835 +
 27.3836 +
 27.3837 +#ifndef GL_WIN_swap_hint
 27.3838 +    #define GL_WIN_swap_hint 1
 27.3839 +
 27.3840 +    typedef void (GLAPIENTRY * PFNGLADDSWAPHINTRECTWINPROC) (GLint x, GLint y, GLsizei width, GLsizei height);
 27.3841 +
 27.3842 +    #define glAddSwapHintRectWIN GLEGetCurrentFunction(glAddSwapHintRectWIN)
 27.3843 +
 27.3844 +    #define GLE_WIN_swap_hint GLEGetCurrentVariable(gle_WIN_swap_hint)
 27.3845 +#endif
 27.3846 +
 27.3847 +
 27.3848 +
 27.3849 +/************************************************************************************
 27.3850 +   Windows-specific (WGL) functionality
 27.3851 +************************************************************************************/
 27.3852 +
 27.3853 +#if defined(GLE_WGL_ENABLED)
 27.3854 +    #ifdef __wglext_h_
 27.3855 +        #error wglext.h was included before this header. This header needs to be inlcuded instead of or at least before wglext.h
 27.3856 +    #endif
 27.3857 +    #define __wglext_h_ // Prevent wglext.h from having any future effect if it's #included.
 27.3858 +
 27.3859 +    // Declare shared types and structs from wglext.h
 27.3860 +    DECLARE_HANDLE(HPBUFFERARB); // This type is used by a couple extensions.
 27.3861 +
 27.3862 +    // WGL functions from <wingdi.h>
 27.3863 +    #if 0 // defined(GLE_HOOKING_ENABLED) We currently don't hook these.
 27.3864 +        #define wglCopyContext(...)              GLEGetCurrentFunction(wglCopyContext)(__VA_ARGS__)
 27.3865 +        #define wglCreateContext(...)            GLEGetCurrentFunction(wglCreateContext)(__VA_ARGS__)
 27.3866 +        #define wglCreateLayerContext(...)       GLEGetCurrentFunction(wglCreateLayerContext)(__VA_ARGS__)
 27.3867 +        #define wglDeleteContext(...)            GLEGetCurrentFunction(wglDeleteContext)(__VA_ARGS__)
 27.3868 +        #define wglGetCurrentContext(...)        GLEGetCurrentFunction(wglGetCurrentContext)(__VA_ARGS__)
 27.3869 +        #define wglGetCurrentDC(...)             GLEGetCurrentFunction(wglGetCurrentDC)(__VA_ARGS__)
 27.3870 +        #define wglGetProcAddress(...)           GLEGetCurrentFunction(wglGetProcAddress)(__VA_ARGS__)
 27.3871 +        #define wglMakeCurrent(...)              GLEGetCurrentFunction(wglMakeCurrent)(__VA_ARGS__)
 27.3872 +        #define wglShareLists(...)               GLEGetCurrentFunction(wglShareLists)(__VA_ARGS__)
 27.3873 +        #define wglUseFontBitmapsA(...)          GLEGetCurrentFunction(wglUseFontBitmapsA)(__VA_ARGS__)
 27.3874 +        #define wglUseFontBitmapsW(...)          GLEGetCurrentFunction(wglUseFontBitmapsW)(__VA_ARGS__)
 27.3875 +        #define wglUseFontOutlinesA(...)         GLEGetCurrentFunction(wglUseFontOutlinesA)(__VA_ARGS__)
 27.3876 +        #define wglUseFontOutlinesW(...)         GLEGetCurrentFunction(wglUseFontOutlinesW)(__VA_ARGS__)
 27.3877 +        #define wglDescribeLayerPlane(...)       GLEGetCurrentFunction(wglDescribeLayerPlane)(__VA_ARGS__)
 27.3878 +        #define wglSetLayerPaletteEntries(...)   GLEGetCurrentFunction(wglSetLayerPaletteEntries)(__VA_ARGS__)
 27.3879 +        #define wglGetLayerPaletteEntries(...)   GLEGetCurrentFunction(wglGetLayerPaletteEntries)(__VA_ARGS__)
 27.3880 +        #define wglRealizeLayerPalette(...)      GLEGetCurrentFunction(wglRealizeLayerPalette)(__VA_ARGS__)
 27.3881 +        #define wglSwapLayerBuffers(...)         GLEGetCurrentFunction(wglSwapLayerBuffers)(__VA_ARGS__)
 27.3882 +        #define wglSwapMultipleBuffers(...)      GLEGetCurrentFunction(wglSwapMultipleBuffers)(__VA_ARGS__)
 27.3883 +    #else
 27.3884 +        // The following functions are directly declared in Microsoft's <wingdi.h> without associated typedefs, and are exported from Opengl32.dll.
 27.3885 +        // We can link to them directly through Opengl32.lib/dll (same as OpenGL 1.1 functions) or we can dynamically link them from OpenGL32.dll at runtime.
 27.3886 +        typedef BOOL  (WINAPI * PFNWGLCOPYCONTEXTPROC)(HGLRC, HGLRC, UINT);
 27.3887 +        typedef HGLRC (WINAPI * PFNWGLCREATECONTEXTPROC)(HDC);
 27.3888 +        typedef HGLRC (WINAPI * PFNWGLCREATELAYERCONTEXTPROC)(HDC, int);
 27.3889 +        typedef BOOL  (WINAPI * PFNWGLDELETECONTEXTPROC)(HGLRC);
 27.3890 +        typedef HGLRC (WINAPI * PFNWGLGETCURRENTCONTEXTPROC)(VOID);
 27.3891 +        typedef HDC   (WINAPI * PFNWGLGETCURRENTDCPROC)(VOID);
 27.3892 +        typedef PROC  (WINAPI * PFNWGLGETPROCADDRESSPROC)(LPCSTR);
 27.3893 +        typedef BOOL  (WINAPI * PFNWGLMAKECURRENTPROC)(HDC, HGLRC);
 27.3894 +        typedef BOOL  (WINAPI * PFNWGLSHARELISTSPROC)(HGLRC, HGLRC);
 27.3895 +        typedef BOOL  (WINAPI * PFNWGLUSEFONTBITMAPSAPROC)(HDC, DWORD, DWORD, DWORD);
 27.3896 +        typedef BOOL  (WINAPI * PFNWGLUSEFONTBITMAPSWPROC)(HDC, DWORD, DWORD, DWORD);
 27.3897 +        typedef BOOL  (WINAPI * PFNWGLUSEFONTOUTLINESAPROC)(HDC, DWORD, DWORD, DWORD, FLOAT, FLOAT, int, LPGLYPHMETRICSFLOAT);
 27.3898 +        typedef BOOL  (WINAPI * PFNWGLUSEFONTOUTLINESWPROC)(HDC, DWORD, DWORD, DWORD, FLOAT, FLOAT, int, LPGLYPHMETRICSFLOAT);
 27.3899 +        typedef BOOL  (WINAPI * PFNWGLDESCRIBELAYERPLANEPROC)(HDC, int, int, UINT, LPLAYERPLANEDESCRIPTOR);
 27.3900 +        typedef int   (WINAPI * PFNWGLSETLAYERPALETTEENTRIESPROC)(HDC, int, int, int, CONST COLORREF *);
 27.3901 +        typedef int   (WINAPI * PFNWGLGETLAYERPALETTEENTRIESPROC)(HDC, int, int, int, COLORREF *);
 27.3902 +        typedef BOOL  (WINAPI * PFNWGLREALIZELAYERPALETTEPROC)(HDC, int, BOOL);
 27.3903 +        typedef BOOL  (WINAPI * PFNWGLSWAPLAYERBUFFERSPROC)(HDC, UINT);
 27.3904 +        typedef DWORD (WINAPI * PFNWGLSWAPMULTIPLEBUFFERSPROC)(UINT, CONST WGLSWAP *);
 27.3905 +
 27.3906 +        #if 0
 27.3907 +        #define wglCopyContext             GLEContext::GetCurrentContext()->wglCopyContext_Impl
 27.3908 +        #define wglCreateContext           GLEContext::GetCurrentContext()->wglCreateContext_Impl
 27.3909 +        #define wglCreateLayerContext      GLEContext::GetCurrentContext()->wglCreateLayerContext_Impl
 27.3910 +        #define wglDeleteContext           GLEContext::GetCurrentContext()->wglDeleteContext_Impl
 27.3911 +        #define wglGetCurrentContext       GLEContext::GetCurrentContext()->wglGetCurrentContext_Impl
 27.3912 +        #define wglGetCurrentDC            GLEContext::GetCurrentContext()->wglGetCurrentDC_Impl
 27.3913 +        #define wglGetProcAddress          GLEContext::GetCurrentContext()->wglGetProcAddress_Impl
 27.3914 +        #define wglMakeCurrent             GLEContext::GetCurrentContext()->wglMakeCurrent_Impl
 27.3915 +        #define wglShareLists              GLEContext::GetCurrentContext()->wglShareLists_Impl
 27.3916 +        #define wglUseFontBitmapsA         GLEContext::GetCurrentContext()->wglUseFontBitmapsA_Impl
 27.3917 +        #define wglUseFontBitmapsW         GLEContext::GetCurrentContext()->wglUseFontBitmapsW_Impl
 27.3918 +        #define wglUseFontOutlinesA        GLEContext::GetCurrentContext()->wglUseFontOutlinesA_Impl
 27.3919 +        #define wglUseFontOutlinesW        GLEContext::GetCurrentContext()->wglUseFontOutlinesW_Impl
 27.3920 +        #define wglDescribeLayerPlane      GLEContext::GetCurrentContext()->wglDescribeLayerPlane_Impl
 27.3921 +        #define wglSetLayerPaletteEntries  GLEContext::GetCurrentContext()->wglSetLayerPaletteEntries_Impl
 27.3922 +        #define wglGetLayerPaletteEntries  GLEContext::GetCurrentContext()->wglGetLayerPaletteEntries_Impl
 27.3923 +        #define wglRealizeLayerPalette     GLEContext::GetCurrentContext()->wglRealizeLayerPalette_Impl
 27.3924 +        #define wglSwapLayerBuffers        GLEContext::GetCurrentContext()->wglSwapLayerBuffers_Impl
 27.3925 +        #define wglSwapMultipleBuffers     GLEContext::GetCurrentContext()->wglSwapMultipleBuffers_Impl
 27.3926 +        #endif
 27.3927 +    #endif
 27.3928 +
 27.3929 +    // Note: In order to detect the WGL extensions' availability, we need to call wglGetExtensionsStringARB or 
 27.3930 +    // wglGetExtensionsStringEXT instead of glGetString(GL_EXTENSIONS).
 27.3931 +    #ifndef WGL_ARB_buffer_region
 27.3932 +        #define WGL_ARB_buffer_region 1
 27.3933 +
 27.3934 +        #define WGL_FRONT_COLOR_BUFFER_BIT_ARB 0x00000001
 27.3935 +        #define WGL_BACK_COLOR_BUFFER_BIT_ARB  0x00000002
 27.3936 +        #define WGL_DEPTH_BUFFER_BIT_ARB       0x00000004
 27.3937 +        #define WGL_STENCIL_BUFFER_BIT_ARB     0x00000008
 27.3938 +
 27.3939 +        typedef HANDLE (WINAPI * PFNWGLCREATEBUFFERREGIONARBPROC) (HDC hDC, int iLayerPlane, UINT uType);
 27.3940 +        typedef VOID   (WINAPI * PFNWGLDELETEBUFFERREGIONARBPROC) (HANDLE hRegion);
 27.3941 +        typedef BOOL   (WINAPI * PFNWGLSAVEBUFFERREGIONARBPROC) (HANDLE hRegion, int x, int y, int width, int height);
 27.3942 +        typedef BOOL   (WINAPI * PFNWGLRESTOREBUFFERREGIONARBPROC) (HANDLE hRegion, int x, int y, int width, int height, int xSrc, int ySrc);
 27.3943 +
 27.3944 +        #define wglCreateBufferRegionARB  GLEGetCurrentFunction(wglCreateBufferRegionARB)
 27.3945 +        #define wglDeleteBufferRegionARB  GLEGetCurrentFunction(wglDeleteBufferRegionARB)
 27.3946 +        #define wglSaveBufferRegionARB    GLEGetCurrentFunction(wglSaveBufferRegionARB)
 27.3947 +        #define wglRestoreBufferRegionARB GLEGetCurrentFunction(wglRestoreBufferRegionARB)
 27.3948 +
 27.3949 +        #define GLE_WGL_ARB_buffer_region GLEGetCurrentVariable(gle_WGL_ARB_buffer_region)
 27.3950 +    #endif
 27.3951 +
 27.3952 +
 27.3953 +    #ifndef WGL_ARB_extensions_string
 27.3954 +        #define WGL_ARB_extensions_string 1
 27.3955 +
 27.3956 +        typedef const char * (WINAPI * PFNWGLGETEXTENSIONSSTRINGARBPROC) (HDC hdc);
 27.3957 +
 27.3958 +        #define wglGetExtensionsStringARB  GLEGetCurrentFunction(wglGetExtensionsStringARB)
 27.3959 +
 27.3960 +        #define GLE_WGL_ARB_extensions_string GLEGetCurrentVariable(gle_WGL_ARB_extensions_string)
 27.3961 +    #endif
 27.3962 +
 27.3963 +
 27.3964 +    #ifndef WGL_ARB_pixel_format
 27.3965 +        #define WGL_ARB_pixel_format 1
 27.3966 +
 27.3967 +        #define WGL_NUMBER_PIXEL_FORMATS_ARB   0x2000
 27.3968 +        #define WGL_DRAW_TO_WINDOW_ARB         0x2001
 27.3969 +        #define WGL_DRAW_TO_BITMAP_ARB         0x2002
 27.3970 +        #define WGL_ACCELERATION_ARB           0x2003
 27.3971 +        #define WGL_NEED_PALETTE_ARB           0x2004
 27.3972 +        #define WGL_NEED_SYSTEM_PALETTE_ARB    0x2005
 27.3973 +        #define WGL_SWAP_LAYER_BUFFERS_ARB     0x2006
 27.3974 +        #define WGL_SWAP_METHOD_ARB            0x2007
 27.3975 +        #define WGL_NUMBER_OVERLAYS_ARB        0x2008
 27.3976 +        #define WGL_NUMBER_UNDERLAYS_ARB       0x2009
 27.3977 +        #define WGL_TRANSPARENT_ARB            0x200A
 27.3978 +        #define WGL_TRANSPARENT_RED_VALUE_ARB  0x2037
 27.3979 +        #define WGL_TRANSPARENT_GREEN_VALUE_ARB 0x2038
 27.3980 +        #define WGL_TRANSPARENT_BLUE_VALUE_ARB 0x2039
 27.3981 +        #define WGL_TRANSPARENT_ALPHA_VALUE_ARB 0x203A
 27.3982 +        #define WGL_TRANSPARENT_INDEX_VALUE_ARB 0x203B
 27.3983 +        #define WGL_SHARE_DEPTH_ARB            0x200C
 27.3984 +        #define WGL_SHARE_STENCIL_ARB          0x200D
 27.3985 +        #define WGL_SHARE_ACCUM_ARB            0x200E
 27.3986 +        #define WGL_SUPPORT_GDI_ARB            0x200F
 27.3987 +        #define WGL_SUPPORT_OPENGL_ARB         0x2010
 27.3988 +        #define WGL_DOUBLE_BUFFER_ARB          0x2011
 27.3989 +        #define WGL_STEREO_ARB                 0x2012
 27.3990 +        #define WGL_PIXEL_TYPE_ARB             0x2013
 27.3991 +        #define WGL_COLOR_BITS_ARB             0x2014
 27.3992 +        #define WGL_RED_BITS_ARB               0x2015
 27.3993 +        #define WGL_RED_SHIFT_ARB              0x2016
 27.3994 +        #define WGL_GREEN_BITS_ARB             0x2017
 27.3995 +        #define WGL_GREEN_SHIFT_ARB            0x2018
 27.3996 +        #define WGL_BLUE_BITS_ARB              0x2019
 27.3997 +        #define WGL_BLUE_SHIFT_ARB             0x201A
 27.3998 +        #define WGL_ALPHA_BITS_ARB             0x201B
 27.3999 +        #define WGL_ALPHA_SHIFT_ARB            0x201C
 27.4000 +        #define WGL_ACCUM_BITS_ARB             0x201D
 27.4001 +        #define WGL_ACCUM_RED_BITS_ARB         0x201E
 27.4002 +        #define WGL_ACCUM_GREEN_BITS_ARB       0x201F
 27.4003 +        #define WGL_ACCUM_BLUE_BITS_ARB        0x2020
 27.4004 +        #define WGL_ACCUM_ALPHA_BITS_ARB       0x2021
 27.4005 +        #define WGL_DEPTH_BITS_ARB             0x2022
 27.4006 +        #define WGL_STENCIL_BITS_ARB           0x2023
 27.4007 +        #define WGL_AUX_BUFFERS_ARB            0x2024
 27.4008 +        #define WGL_NO_ACCELERATION_ARB        0x2025
 27.4009 +        #define WGL_GENERIC_ACCELERATION_ARB   0x2026
 27.4010 +        #define WGL_FULL_ACCELERATION_ARB      0x2027
 27.4011 +        #define WGL_SWAP_EXCHANGE_ARB          0x2028
 27.4012 +        #define WGL_SWAP_COPY_ARB              0x2029
 27.4013 +        #define WGL_SWAP_UNDEFINED_ARB         0x202A
 27.4014 +        #define WGL_TYPE_RGBA_ARB              0x202B
 27.4015 +        #define WGL_TYPE_COLORINDEX_ARB        0x202C
 27.4016 +
 27.4017 +        typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVARBPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, int *piValues);
 27.4018 +        typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBFVARBPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, FLOAT *pfValues);
 27.4019 +        typedef BOOL (WINAPI * PFNWGLCHOOSEPIXELFORMATARBPROC) (HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats);
 27.4020 +
 27.4021 +        #define wglGetPixelFormatAttribivARB  GLEGetCurrentFunction(wglGetPixelFormatAttribivARB)
 27.4022 +        #define wglGetPixelFormatAttribfvARB  GLEGetCurrentFunction(wglGetPixelFormatAttribfvARB)
 27.4023 +        #define wglChoosePixelFormatARB  GLEGetCurrentFunction(wglChoosePixelFormatARB)
 27.4024 +
 27.4025 +        #define GLE_WGL_ARB_pixel_format GLEGetCurrentVariable(gle_WGL_ARB_pixel_format)
 27.4026 +    #endif
 27.4027 +
 27.4028 +
 27.4029 +    #ifndef WGL_ARB_make_current_read
 27.4030 +        #define WGL_ARB_make_current_read 1
 27.4031 +
 27.4032 +        #define ERROR_INVALID_PIXEL_TYPE_ARB   0x2043
 27.4033 +        #define ERROR_INCOMPATIBLE_DEVICE_CONTEXTS_ARB 0x2054
 27.4034 +
 27.4035 +        typedef BOOL (WINAPI * PFNWGLMAKECONTEXTCURRENTARBPROC) (HDC hDrawDC, HDC hReadDC, HGLRC hglrc);
 27.4036 +        typedef HDC  (WINAPI * PFNWGLGETCURRENTREADDCARBPROC) (void);
 27.4037 +
 27.4038 +        #define wglMakeContextCurrentARB  GLEGetCurrentFunction(wglMakeContextCurrentARB)
 27.4039 +        #define wglGetCurrentReadDCARB  GLEGetCurrentFunction(wglGetCurrentReadDCARB)
 27.4040 +
 27.4041 +        #define GLE_WGL_ARB_make_current_read GLEGetCurrentVariable(gle_WGL_ARB_make_current_read)
 27.4042 +    #endif
 27.4043 +
 27.4044 +
 27.4045 +    #ifndef WGL_ARB_pbuffer
 27.4046 +        #define WGL_ARB_pbuffer 1
 27.4047 +
 27.4048 +        #define WGL_DRAW_TO_PBUFFER_ARB        0x202D
 27.4049 +        #define WGL_MAX_PBUFFER_PIXELS_ARB     0x202E
 27.4050 +        #define WGL_MAX_PBUFFER_WIDTH_ARB      0x202F
 27.4051 +        #define WGL_MAX_PBUFFER_HEIGHT_ARB     0x2030
 27.4052 +        #define WGL_PBUFFER_LARGEST_ARB        0x2033
 27.4053 +        #define WGL_PBUFFER_WIDTH_ARB          0x2034
 27.4054 +        #define WGL_PBUFFER_HEIGHT_ARB         0x2035
 27.4055 +
 27.4056 +        typedef HPBUFFERARB (WINAPI * PFNWGLCREATEPBUFFERARBPROC) (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int *piAttribList);
 27.4057 +        typedef HDC         (WINAPI * PFNWGLGETPBUFFERDCARBPROC) (HPBUFFERARB hPbuffer);
 27.4058 +        typedef int         (WINAPI * PFNWGLRELEASEPBUFFERDCARBPROC) (HPBUFFERARB hPbuffer, HDC hDC);
 27.4059 +        typedef BOOL        (WINAPI * PFNWGLDESTROYPBUFFERARBPROC) (HPBUFFERARB hPbuffer);
 27.4060 +        typedef BOOL        (WINAPI * PFNWGLQUERYPBUFFERARBPROC) (HPBUFFERARB hPbuffer, int iAttribute, int *piValue);
 27.4061 +
 27.4062 +        #define wglCreatePbufferARB  GLEGetCurrentFunction(wglCreatePbufferARB)
 27.4063 +        #define wglGetPbufferDCARB  GLEGetCurrentFunction(wglGetPbufferDCARB)
 27.4064 +        #define wglReleasePbufferDCARB  GLEGetCurrentFunction(wglReleasePbufferDCARB)
 27.4065 +        #define wglDestroyPbufferARB  GLEGetCurrentFunction(wglDestroyPbufferARB)
 27.4066 +        #define wglQueryPbufferARB  GLEGetCurrentFunction(wglQueryPbufferARB)
 27.4067 +
 27.4068 +        #define GLE_WGL_ARB_pbuffer GLEGetCurrentVariable(gle_WGL_ARB_pbuffer)
 27.4069 +    #endif
 27.4070 +
 27.4071 +
 27.4072 +    #ifndef WGL_ARB_render_texture
 27.4073 +        #define WGL_ARB_render_texture 1
 27.4074 +
 27.4075 +        #define WGL_BIND_TO_TEXTURE_RGB_ARB         0x2070
 27.4076 +        #define WGL_BIND_TO_TEXTURE_RGBA_ARB        0x2071
 27.4077 +        #define WGL_TEXTURE_FORMAT_ARB              0x2072
 27.4078 +        #define WGL_TEXTURE_TARGET_ARB              0x2073
 27.4079 +        #define WGL_MIPMAP_TEXTURE_ARB              0x2074
 27.4080 +        #define WGL_TEXTURE_RGB_ARB                 0x2075
 27.4081 +        #define WGL_TEXTURE_RGBA_ARB                0x2076
 27.4082 +        #define WGL_NO_TEXTURE_ARB                  0x2077
 27.4083 +        #define WGL_TEXTURE_CUBE_MAP_ARB            0x2078
 27.4084 +        #define WGL_TEXTURE_1D_ARB                  0x2079
 27.4085 +        #define WGL_TEXTURE_2D_ARB                  0x207A
 27.4086 +        #define WGL_MIPMAP_LEVEL_ARB                0x207B
 27.4087 +        #define WGL_CUBE_MAP_FACE_ARB               0x207C
 27.4088 +        #define WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB 0x207D
 27.4089 +        #define WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB 0x207E
 27.4090 +        #define WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB 0x207F
 27.4091 +        #define WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB 0x2080
 27.4092 +        #define WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB 0x2081
 27.4093 +        #define WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB 0x2082
 27.4094 +        #define WGL_FRONT_LEFT_ARB                  0x2083
 27.4095 +        #define WGL_FRONT_RIGHT_ARB                 0x2084
 27.4096 +        #define WGL_BACK_LEFT_ARB                   0x2085
 27.4097 +        #define WGL_BACK_RIGHT_ARB                  0x2086
 27.4098 +        #define WGL_AUX0_ARB                        0x2087
 27.4099 +        #define WGL_AUX1_ARB                        0x2088
 27.4100 +        #define WGL_AUX2_ARB                        0x2089
 27.4101 +        #define WGL_AUX3_ARB                        0x208A
 27.4102 +        #define WGL_AUX4_ARB                        0x208B
 27.4103 +        #define WGL_AUX5_ARB                        0x208C
 27.4104 +        #define WGL_AUX6_ARB                        0x208D
 27.4105 +        #define WGL_AUX7_ARB                        0x208E
 27.4106 +        #define WGL_AUX8_ARB                        0x208F
 27.4107 +        #define WGL_AUX9_ARB                        0x2090
 27.4108 +
 27.4109 +        typedef BOOL (WINAPI * PFNWGLBINDTEXIMAGEARBPROC) (HPBUFFERARB hPbuffer, int iBuffer);
 27.4110 +        typedef BOOL (WINAPI * PFNWGLRELEASETEXIMAGEARBPROC) (HPBUFFERARB hPbuffer, int iBuffer);
 27.4111 +        typedef BOOL (WINAPI * PFNWGLSETPBUFFERATTRIBARBPROC) (HPBUFFERARB hPbuffer, const int *piAttribList);
 27.4112 +
 27.4113 +        #define wglBindTexImageARB     GLEGetCurrentFunction(wglBindTexImageARB)
 27.4114 +        #define wglReleaseTexImageARB  GLEGetCurrentFunction(wglReleaseTexImageARB)
 27.4115 +        #define wglSetPbufferAttribARB GLEGetCurrentFunction(wglSetPbufferAttribARB)
 27.4116 +
 27.4117 +        #define GLE_WGL_ARB_render_texture GLEGetCurrentVariable(gle_WGL_ARB_render_texture)
 27.4118 +    #endif
 27.4119 +
 27.4120 +
 27.4121 +    #ifndef WGL_ARB_pixel_format_float
 27.4122 +        #define WGL_ARB_pixel_format_float 1
 27.4123 +
 27.4124 +        #define WGL_TYPE_RGBA_FLOAT_ARB        0x21A0
 27.4125 +
 27.4126 +        #define GLE_WGL_ARB_pixel_format_float GLEGetCurrentVariable(gle_WGL_ARB_pixel_format_float)
 27.4127 +    #endif
 27.4128 +
 27.4129 +
 27.4130 +    #ifndef WGL_ARB_framebuffer_sRGB
 27.4131 +        #define WGL_ARB_framebuffer_sRGB 1
 27.4132 +
 27.4133 +        // There is also the WGL_EXT_framebuffer_sRGB extension, which is the
 27.4134 +        // same as this. So use this one instead of that for checking.
 27.4135 +        #define WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20A9
 27.4136 +
 27.4137 +        #define GLE_WGL_ARB_framebuffer_sRGB GLEGetCurrentVariable(gle_WGL_ARB_framebuffer_sRGB)
 27.4138 +    #endif
 27.4139 +
 27.4140 +
 27.4141 +    #ifndef WGL_NV_present_video
 27.4142 +        #define WGL_NV_present_video 1
 27.4143 +
 27.4144 +        DECLARE_HANDLE(HVIDEOOUTPUTDEVICENV);
 27.4145 +
 27.4146 +        typedef int  (WINAPI * PFNWGLENUMERATEVIDEODEVICESNVPROC) (HDC hDC, HVIDEOOUTPUTDEVICENV *phDeviceList);
 27.4147 +        typedef BOOL (WINAPI * PFNWGLBINDVIDEODEVICENVPROC) (HDC hDC, unsigned int uVideoSlot, HVIDEOOUTPUTDEVICENV hVideoDevice, const int *piAttribList);
 27.4148 +        typedef BOOL (WINAPI * PFNWGLQUERYCURRENTCONTEXTNVPROC) (int iAttribute, int *piValue);
 27.4149 +
 27.4150 +        #define wglEnumerateVideoDevicesNV GLEGetCurrentFunction(wglEnumerateVideoDevicesNV)
 27.4151 +        #define wglBindVideoDeviceNV       GLEGetCurrentFunction(wglBindVideoDeviceNV)
 27.4152 +        #define wglQueryCurrentContextNV   GLEGetCurrentFunction(wglQueryCurrentContextNV)
 27.4153 +
 27.4154 +        #define GLE_WGL_NV_present_video GLEGetCurrentVariable(gle_WGL_NV_present_video)
 27.4155 +    #endif
 27.4156 +
 27.4157 +
 27.4158 +    #ifndef WGL_ARB_create_context
 27.4159 +        #define WGL_ARB_create_context 1
 27.4160 +
 27.4161 +        #define WGL_CONTEXT_DEBUG_BIT_ARB      0x00000001
 27.4162 +        #define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x00000002
 27.4163 +        #define WGL_CONTEXT_MAJOR_VERSION_ARB  0x2091
 27.4164 +        #define WGL_CONTEXT_MINOR_VERSION_ARB  0x2092
 27.4165 +        #define WGL_CONTEXT_LAYER_PLANE_ARB    0x2093
 27.4166 +        #define WGL_CONTEXT_FLAGS_ARB          0x2094
 27.4167 +        #define ERROR_INVALID_VERSION_ARB      0x2095
 27.4168 +
 27.4169 +        typedef HGLRC (WINAPI * PFNWGLCREATECONTEXTATTRIBSARBPROC) (HDC hDC, HGLRC hShareContext, const int *attribList);
 27.4170 +
 27.4171 +        #define wglCreateContextAttribsARB  GLEGetCurrentFunction(wglCreateContextAttribsARB)
 27.4172 +
 27.4173 +        #define GLE_WGL_ARB_create_context GLEGetCurrentVariable(gle_WGL_ARB_create_context)
 27.4174 +    #endif
 27.4175 +
 27.4176 +
 27.4177 +    #ifndef WGL_ARB_create_context_profile
 27.4178 +        #define WGL_ARB_create_context_profile 1
 27.4179 +
 27.4180 +        #define WGL_CONTEXT_PROFILE_MASK_ARB   0x9126
 27.4181 +        #define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
 27.4182 +        #define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
 27.4183 +        #define ERROR_INVALID_PROFILE_ARB      0x2096
 27.4184 +
 27.4185 +        #define GLE_WGL_ARB_create_context_profile GLEGetCurrentVariable(gle_WGL_ARB_create_context_profile)
 27.4186 +    #endif
 27.4187 +
 27.4188 +
 27.4189 +    #ifndef WGL_ARB_create_context_robustness
 27.4190 +        #define WGL_ARB_create_context_robustness 1
 27.4191 +
 27.4192 +        #define WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB 0x00000004
 27.4193 +        #define WGL_LOSE_CONTEXT_ON_RESET_ARB  0x8252
 27.4194 +        #define WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB 0x8256
 27.4195 +        #define WGL_NO_RESET_NOTIFICATION_ARB  0x8261
 27.4196 +
 27.4197 +        #define GLE_WGL_ARB_create_context_robustness GLEGetCurrentVariable(gle_WGL_ARB_create_context_robustness)
 27.4198 +    #endif
 27.4199 +
 27.4200 +
 27.4201 +
 27.4202 +    #ifndef WGL_ATI_render_texture_rectangle
 27.4203 +        #define WGL_ATI_render_texture_rectangle 1
 27.4204 +
 27.4205 +        #define WGL_TEXTURE_RECTANGLE_ATI 0x21A5
 27.4206 +
 27.4207 +        #define GLE_WGL_ATI_render_texture_rectangle GLEGetCurrentVariable(gle_WGL_ATI_render_texture_rectangle)
 27.4208 +    #endif
 27.4209 +
 27.4210 +
 27.4211 +    #ifndef WGL_EXT_extensions_string
 27.4212 +        #define WGL_EXT_extensions_string 1
 27.4213 +
 27.4214 +        typedef const char * (WINAPI * PFNWGLGETEXTENSIONSSTRINGEXTPROC) (void);
 27.4215 +
 27.4216 +        #define wglGetExtensionsStringEXT  GLEGetCurrentFunction(wglGetExtensionsStringEXT)
 27.4217 +
 27.4218 +        #define GLE_WGL_EXT_extensions_string GLEGetCurrentVariable(gle_WGL_EXT_extensions_string)
 27.4219 +    #endif
 27.4220 +
 27.4221 +
 27.4222 +    #ifndef WGL_NV_render_texture_rectangle
 27.4223 +        #define WGL_NV_render_texture_rectangle 1
 27.4224 +
 27.4225 +        #define WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV  0x20A0
 27.4226 +        #define WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV 0x20A1
 27.4227 +        #define WGL_TEXTURE_RECTANGLE_NV              0x20A2
 27.4228 +
 27.4229 +        #define GLE_WGL_NV_render_texture_rectangle GLEGetCurrentVariable(gle_WGL_NV_render_texture_rectangle)
 27.4230 +    #endif
 27.4231 +
 27.4232 +
 27.4233 +    #ifndef WGL_EXT_swap_control
 27.4234 +        #define WGL_EXT_swap_control 1
 27.4235 +
 27.4236 +        typedef int  (WINAPI * PFNWGLGETSWAPINTERVALEXTPROC) (void);
 27.4237 +        typedef BOOL (WINAPI * PFNWGLSWAPINTERVALEXTPROC) (int interval);
 27.4238 +
 27.4239 +        #define wglGetSwapIntervalEXT GLEGetCurrentFunction(wglGetSwapIntervalEXT)
 27.4240 +        #define wglSwapIntervalEXT    GLEGetCurrentFunction(wglSwapIntervalEXT)
 27.4241 +
 27.4242 +        #define GLE_WGL_EXT_swap_control GLEGetCurrentVariable(gle_WGL_EXT_swap_control)
 27.4243 +    #endif
 27.4244 +
 27.4245 +
 27.4246 +    #ifndef WGL_OML_sync_control
 27.4247 +        #define WGL_OML_sync_control 1
 27.4248 +
 27.4249 +        typedef BOOL  (WINAPI * PFNWGLGETSYNCVALUESOMLPROC) (HDC hdc, INT64 *ust, INT64 *msc, INT64 *sbc);
 27.4250 +        typedef BOOL  (WINAPI * PFNWGLGETMSCRATEOMLPROC) (HDC hdc, INT32 *numerator, INT32 *denominator);
 27.4251 +        typedef INT64 (WINAPI * PFNWGLSWAPBUFFERSMSCOMLPROC) (HDC hdc, INT64 target_msc, INT64 divisor, INT64 remainder);
 27.4252 +        typedef INT64 (WINAPI * PFNWGLSWAPLAYERBUFFERSMSCOMLPROC) (HDC hdc, int fuPlanes, INT64 target_msc, INT64 divisor, INT64 remainder);
 27.4253 +        typedef BOOL  (WINAPI * PFNWGLWAITFORMSCOMLPROC) (HDC hdc, INT64 target_msc, INT64 divisor, INT64 remainder, INT64 *ust, INT64 *msc, INT64 *sbc);
 27.4254 +        typedef BOOL  (WINAPI * PFNWGLWAITFORSBCOMLPROC) (HDC hdc, INT64 target_sbc, INT64 *ust, INT64 *msc, INT64 *sbc);
 27.4255 +
 27.4256 +        #define wglGetSyncValuesOML       GLEGetCurrentFunction(wglGetSyncValuesOML)
 27.4257 +        #define wglGetMscRateOML          GLEGetCurrentFunction(wglGetMscRateOML)
 27.4258 +        #define wglSwapBuffersMscOML      GLEGetCurrentFunction(wglSwapBuffersMscOML)
 27.4259 +        #define wglSwapLayerBuffersMscOML GLEGetCurrentFunction(wglSwapLayerBuffersMscOML)
 27.4260 +        #define wglWaitForMscOML          GLEGetCurrentFunction(wglWaitForMscOML)
 27.4261 +        #define wglWaitForSbcOML          GLEGetCurrentFunction(wglWaitForSbcOML)
 27.4262 +
 27.4263 +        #define GLE_WGL_OML_sync_control GLEGetCurrentVariable(gle_WGL_OML_sync_control)
 27.4264 +    #endif
 27.4265 +
 27.4266 +
 27.4267 +    #ifndef WGL_NV_video_output
 27.4268 +        #define WGL_NV_video_output 1
 27.4269 +
 27.4270 +        DECLARE_HANDLE(HPVIDEODEV);
 27.4271 +
 27.4272 +        typedef BOOL (WINAPI * PFNWGLGETVIDEODEVICENVPROC) (HDC hDC, int numDevices, HPVIDEODEV *hVideoDevice);
 27.4273 +        typedef BOOL (WINAPI * PFNWGLRELEASEVIDEODEVICENVPROC) (HPVIDEODEV hVideoDevice);
 27.4274 +        typedef BOOL (WINAPI * PFNWGLBINDVIDEOIMAGENVPROC) (HPVIDEODEV hVideoDevice, HPBUFFERARB hPbuffer, int iVideoBuffer);
 27.4275 +        typedef BOOL (WINAPI * PFNWGLRELEASEVIDEOIMAGENVPROC) (HPBUFFERARB hPbuffer, int iVideoBuffer);
 27.4276 +        typedef BOOL (WINAPI * PFNWGLSENDPBUFFERTOVIDEONVPROC) (HPBUFFERARB hPbuffer, int iBufferType, unsigned long *pulCounterPbuffer, BOOL bBlock);
 27.4277 +        typedef BOOL (WINAPI * PFNWGLGETVIDEOINFONVPROC) (HPVIDEODEV hpVideoDevice, unsigned long *pulCounterOutputPbuffer, unsigned long *pulCounterOutputVideo);
 27.4278 +
 27.4279 +        #define wglGetVideoDeviceNV      GLEGetCurrentFunction(wglGetVideoDeviceNV)
 27.4280 +        #define wglReleaseVideoDeviceNV  GLEGetCurrentFunction(wglReleaseVideoDeviceNV)
 27.4281 +        #define wglBindVideoImageNV      GLEGetCurrentFunction(wglBindVideoImageNV)
 27.4282 +        #define wglReleaseVideoImageNV   GLEGetCurrentFunction(wglReleaseVideoImageNV)
 27.4283 +        #define wglSendPbufferToVideoNV  GLEGetCurrentFunction(wglSendPbufferToVideoNV)
 27.4284 +        #define wglGetVideoInfoNV        GLEGetCurrentFunction(wglGetVideoInfoNV)
 27.4285 +
 27.4286 +        #define GLE_WGL_NV_video_output GLEGetCurrentVariable(gle_WGL_NV_video_output)
 27.4287 +    #endif
 27.4288 +
 27.4289 +
 27.4290 +    #ifndef WGL_NV_swap_group
 27.4291 +        #define WGL_NV_swap_group 1
 27.4292 +
 27.4293 +        typedef BOOL (WINAPI * PFNWGLJOINSWAPGROUPNVPROC) (HDC hDC, GLuint group);
 27.4294 +        typedef BOOL (WINAPI * PFNWGLBINDSWAPBARRIERNVPROC) (GLuint group, GLuint barrier);
 27.4295 +        typedef BOOL (WINAPI * PFNWGLQUERYSWAPGROUPNVPROC) (HDC hDC, GLuint *group, GLuint *barrier);
 27.4296 +        typedef BOOL (WINAPI * PFNWGLQUERYMAXSWAPGROUPSNVPROC) (HDC hDC, GLuint *maxGroups, GLuint *maxBarriers);
 27.4297 +        typedef BOOL (WINAPI * PFNWGLQUERYFRAMECOUNTNVPROC) (HDC hDC, GLuint *count);
 27.4298 +        typedef BOOL (WINAPI * PFNWGLRESETFRAMECOUNTNVPROC) (HDC hDC);
 27.4299 +
 27.4300 +        #define wglJoinSwapGroupNV        GLEGetCurrentFunction(wglJoinSwapGroupNV)
 27.4301 +        #define wglBindSwapBarrierNV      GLEGetCurrentFunction(wglBindSwapBarrierNV)
 27.4302 +        #define wglQuerySwapGroupNV       GLEGetCurrentFunction(wglQuerySwapGroupNV)
 27.4303 +        #define wglQueryMaxSwapGroupsNV   GLEGetCurrentFunction(wglQueryMaxSwapGroupsNV)
 27.4304 +        #define wglQueryFrameCountNV      GLEGetCurrentFunction(wglQueryFrameCountNV)
 27.4305 +        #define wglResetFrameCountNV      GLEGetCurrentFunction(wglResetFrameCountNV)
 27.4306 +
 27.4307 +        #define GLE_WGL_NV_swap_group GLEGetCurrentVariable(gle_WGL_NV_swap_group)
 27.4308 +    #endif
 27.4309 +
 27.4310 +
 27.4311 +    #ifndef WGL_NV_video_capture
 27.4312 +        #define WGL_NV_video_capture 1
 27.4313 +
 27.4314 +        #define WGL_UNIQUE_ID_NV               0x20CE
 27.4315 +        #define WGL_NUM_VIDEO_CAPTURE_SLOTS_NV 0x20CF
 27.4316 +
 27.4317 +        typedef struct _GPU_DEVICE {
 27.4318 +            DWORD  cb;
 27.4319 +            CHAR   DeviceName[32];
 27.4320 +            CHAR   DeviceString[128];
 27.4321 +            DWORD  Flags;
 27.4322 +            RECT   rcVirtualScreen;
 27.4323 +        } GPU_DEVICE, *PGPU_DEVICE;
 27.4324 +        DECLARE_HANDLE(HVIDEOINPUTDEVICENV);
 27.4325 +
 27.4326 +        typedef BOOL (WINAPI * PFNWGLBINDVIDEOCAPTUREDEVICENVPROC) (UINT uVideoSlot, HVIDEOINPUTDEVICENV hDevice);
 27.4327 +        typedef UINT (WINAPI * PFNWGLENUMERATEVIDEOCAPTUREDEVICESNVPROC) (HDC hDc, HVIDEOINPUTDEVICENV *phDeviceList);
 27.4328 +        typedef BOOL (WINAPI * PFNWGLLOCKVIDEOCAPTUREDEVICENVPROC) (HDC hDc, HVIDEOINPUTDEVICENV hDevice);
 27.4329 +        typedef BOOL (WINAPI * PFNWGLQUERYVIDEOCAPTUREDEVICENVPROC) (HDC hDc, HVIDEOINPUTDEVICENV hDevice, int iAttribute, int *piValue);
 27.4330 +        typedef BOOL (WINAPI * PFNWGLRELEASEVIDEOCAPTUREDEVICENVPROC) (HDC hDc, HVIDEOINPUTDEVICENV hDevice);
 27.4331 +
 27.4332 +        #define wglBindVideoCaptureDeviceNV        GLEGetCurrentFunction(wglBindVideoCaptureDeviceNV)
 27.4333 +        #define wglEnumerateVideoCaptureDevicesNV  GLEGetCurrentFunction(wglEnumerateVideoCaptureDevicesNV)
 27.4334 +        #define wglLockVideoCaptureDeviceNV        GLEGetCurrentFunction(wglLockVideoCaptureDeviceNV)
 27.4335 +        #define wglQueryVideoCaptureDeviceNV       GLEGetCurrentFunction(wglQueryVideoCaptureDeviceNV)
 27.4336 +        #define wglReleaseVideoCaptureDeviceNV     GLEGetCurrentFunction(wglReleaseVideoCaptureDeviceNV)
 27.4337 +
 27.4338 +        #define GLE_WGL_NV_video_capture GLEGetCurrentVariable(gle_WGL_NV_video_capture)
 27.4339 +    #endif
 27.4340 +
 27.4341 +
 27.4342 +    #ifndef WGL_NV_copy_image
 27.4343 +        #define WGL_NV_copy_image 1
 27.4344 +
 27.4345 +        typedef BOOL (WINAPI * PFNWGLCOPYIMAGESUBDATANVPROC) (HGLRC hSrcRC, GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, HGLRC hDstRC, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei width, GLsizei height, GLsizei depth);
 27.4346 +
 27.4347 +        #define wglCopyImageSubDataNV GLEGetCurrentFunction(wglCopyImageSubDataNV)
 27.4348 +
 27.4349 +        #define GLE_WGL_NV_copy_image GLEGetCurrentVariable(gle_WGL_NV_copy_image)
 27.4350 +    #endif
 27.4351 +
 27.4352 +
 27.4353 +    #ifndef WGL_NV_DX_interop
 27.4354 +        #define WGL_NV_DX_interop 1
 27.4355 +
 27.4356 +        // Note that modern AMD drivers support this NVidia extension.
 27.4357 +        #define WGL_ACCESS_READ_ONLY_NV     0x0000
 27.4358 +        #define WGL_ACCESS_READ_WRITE_NV    0x0001
 27.4359 +        #define WGL_ACCESS_WRITE_DISCARD_NV 0x0002
 27.4360 +
 27.4361 +        typedef BOOL   (WINAPI * PFNWGLDXCLOSEDEVICENVPROC) (HANDLE hDevice);
 27.4362 +        typedef BOOL   (WINAPI * PFNWGLDXLOCKOBJECTSNVPROC) (HANDLE hDevice, GLint count, HANDLE* hObjects);
 27.4363 +        typedef BOOL   (WINAPI * PFNWGLDXOBJECTACCESSNVPROC) (HANDLE hObject, GLenum access);
 27.4364 +        typedef HANDLE (WINAPI * PFNWGLDXOPENDEVICENVPROC) (void* dxDevice);
 27.4365 +        typedef HANDLE (WINAPI * PFNWGLDXREGISTEROBJECTNVPROC) (HANDLE hDevice, void* dxObject, GLuint name, GLenum type, GLenum access);
 27.4366 +        typedef BOOL   (WINAPI * PFNWGLDXSETRESOURCESHAREHANDLENVPROC) (void* dxObject, HANDLE shareHandle);
 27.4367 +        typedef BOOL   (WINAPI * PFNWGLDXUNLOCKOBJECTSNVPROC) (HANDLE hDevice, GLint count, HANDLE* hObjects);
 27.4368 +        typedef BOOL   (WINAPI * PFNWGLDXUNREGISTEROBJECTNVPROC) (HANDLE hDevice, HANDLE hObject);
 27.4369 +
 27.4370 +        #define wglDXCloseDeviceNV            GLEGetCurrentFunction(wglDXCloseDeviceNV)
 27.4371 +        #define wglDXLockObjectsNV            GLEGetCurrentFunction(wglDXLockObjectsNV)
 27.4372 +        #define wglDXObjectAccessNV           GLEGetCurrentFunction(wglDXObjectAccessNV)
 27.4373 +        #define wglDXOpenDeviceNV             GLEGetCurrentFunction(wglDXOpenDeviceNV)
 27.4374 +        #define wglDXRegisterObjectNV         GLEGetCurrentFunction(wglDXRegisterObjectNV)
 27.4375 +        #define wglDXSetResourceShareHandleNV GLEGetCurrentFunction(wglDXSetResourceShareHandleNV)
 27.4376 +        #define wglDXUnlockObjectsNV          GLEGetCurrentFunction(wglDXUnlockObjectsNV)
 27.4377 +        #define wglDXUnregisterObjectNV       GLEGetCurrentFunction(wglDXUnregisterObjectNV)
 27.4378 +
 27.4379 +        #define GLE_WGL_NV_DX_interop GLEGetCurrentVariable(gle_WGL_NV_DX_interop)
 27.4380 +    #endif
 27.4381 +    
 27.4382 +
 27.4383 +    #ifndef WGL_NV_DX_interop2
 27.4384 +        #define WGL_NV_DX_interop2 1
 27.4385 +
 27.4386 +        // This is an update to WGL_NV_DX_interop to support DX10/DX11.
 27.4387 +        // https://www.opengl.org/registry/specs/NV/DX_interop2.txt
 27.4388 +        #define GLE_WGL_NV_DX_interop2 GLEGetCurrentVariable(gle_WGL_NV_DX_interop2)
 27.4389 +
 27.4390 +        #endif
 27.4391 +
 27.4392 +#endif // GLE_WGL_ENABLED
 27.4393 +
 27.4394 +
 27.4395 +
 27.4396 +/************************************************************************************
 27.4397 +   Apple-specific (CGL) functionality
 27.4398 +************************************************************************************/
 27.4399 +
 27.4400 +#if defined(GLE_CGL_ENABLED)
 27.4401 +    // We don't currently disable Apple's OpenGL/OpenGL.h and replicate its declarations here.
 27.4402 +    // We might want to do that if we intended to support hooking its functions here like we do for wgl functions.
 27.4403 +    #include <OpenGL/OpenGL.h>
 27.4404 +#endif
 27.4405 +
 27.4406 +
 27.4407 +
 27.4408 +/************************************************************************************
 27.4409 +   Unix-specific (GLX) functionality
 27.4410 +************************************************************************************/
 27.4411 +
 27.4412 +#if defined(GLE_GLX_ENABLED)
 27.4413 +    #ifdef __glxext_h_
 27.4414 +        #error glxext.h was included before this header. This header needs to be inlcuded instead of or at least before glxext.h
 27.4415 +    #endif
 27.4416 +    #define __glxext_h_
 27.4417 +
 27.4418 +    #if defined(GLX_H) || defined(__GLX_glx_h__) || defined(__glx_h__)
 27.4419 +        #error glx.h was included before this header. This header needs to be inlcuded instead of or at least before glx.h
 27.4420 +    #endif
 27.4421 +    #define GLX_H
 27.4422 +    #define __GLX_glx_h__
 27.4423 +    #define __glx_h__
 27.4424 +
 27.4425 +    #include <X11/Xlib.h>
 27.4426 +    #include <X11/Xutil.h>
 27.4427 +    #include <X11/Xmd.h>
 27.4428 +
 27.4429 +    // GLX version 1.0 functions are assumed to always be present.
 27.4430 +    #ifndef GLX_VERSION_1_0
 27.4431 +        #define GLX_VERSION_1_0 1
 27.4432 +
 27.4433 +        #define GLX_USE_GL 1
 27.4434 +        #define GLX_BUFFER_SIZE 2
 27.4435 +        #define GLX_LEVEL 3
 27.4436 +        #define GLX_RGBA 4
 27.4437 +        #define GLX_DOUBLEBUFFER 5
 27.4438 +        #define GLX_STEREO 6
 27.4439 +        #define GLX_AUX_BUFFERS 7
 27.4440 +        #define GLX_RED_SIZE 8
 27.4441 +        #define GLX_GREEN_SIZE 9
 27.4442 +        #define GLX_BLUE_SIZE 10
 27.4443 +        #define GLX_ALPHA_SIZE 11
 27.4444 +        #define GLX_DEPTH_SIZE 12
 27.4445 +        #define GLX_STENCIL_SIZE 13
 27.4446 +        #define GLX_ACCUM_RED_SIZE 14
 27.4447 +        #define GLX_ACCUM_GREEN_SIZE 15
 27.4448 +        #define GLX_ACCUM_BLUE_SIZE 16
 27.4449 +        #define GLX_ACCUM_ALPHA_SIZE 17
 27.4450 +        #define GLX_BAD_SCREEN 1
 27.4451 +        #define GLX_BAD_ATTRIBUTE 2
 27.4452 +        #define GLX_NO_EXTENSION 3
 27.4453 +        #define GLX_BAD_VISUAL 4
 27.4454 +        #define GLX_BAD_CONTEXT 5
 27.4455 +        #define GLX_BAD_VALUE 6
 27.4456 +        #define GLX_BAD_ENUM 7
 27.4457 +
 27.4458 +        typedef XID GLXDrawable;
 27.4459 +        typedef XID GLXPixmap;
 27.4460 +        typedef unsigned int GLXVideoDeviceNV; 
 27.4461 +        typedef struct __GLXcontextRec *GLXContext;
 27.4462 +
 27.4463 +        // GLE_HOOKING_ENABLED
 27.4464 +        // We don't currently support hooking the following GLX 1.0 functions like we do with the analagous windows wgl functions.
 27.4465 +        // However, we can do this if needed. We would just have something like this:
 27.4466 +        //     #define glXQueryExtension(...) GLEGetCurrentFunction(glXQueryExtension)(__VA_ARGS__)
 27.4467 +        // plus a member function like:
 27.4468 +        //      Bool glXQueryExtension_Hook(Display*, int*, int*);
 27.4469 +        // See wglCopyContext for an example.
 27.4470 +    
 27.4471 +        extern Bool         glXQueryExtension (Display *dpy, int *errorBase, int *eventBase);
 27.4472 +        extern Bool         glXQueryVersion (Display *dpy, int *major, int *minor);
 27.4473 +        extern int          glXGetConfig (Display *dpy, XVisualInfo *vis, int attrib, int *value);
 27.4474 +        extern XVisualInfo* glXChooseVisual (Display *dpy, int screen, int *attribList);
 27.4475 +        extern GLXPixmap    glXCreateGLXPixmap (Display *dpy, XVisualInfo *vis, Pixmap pixmap);
 27.4476 +        extern void         glXDestroyGLXPixmap (Display *dpy, GLXPixmap pix);
 27.4477 +        extern GLXContext   glXCreateContext (Display *dpy, XVisualInfo *vis, GLXContext shareList, Bool direct);
 27.4478 +        extern void         glXDestroyContext (Display *dpy, GLXContext ctx);
 27.4479 +        extern Bool         glXIsDirect (Display *dpy, GLXContext ctx);
 27.4480 +        extern void         glXCopyContext (Display *dpy, GLXContext src, GLXContext dst, GLulong mask);
 27.4481 +        extern Bool         glXMakeCurrent (Display *dpy, GLXDrawable drawable, GLXContext ctx);
 27.4482 +        extern GLXContext   glXGetCurrentContext (void);
 27.4483 +        extern GLXDrawable  glXGetCurrentDrawable (void);
 27.4484 +        extern void         glXWaitGL (void);
 27.4485 +        extern void         glXWaitX (void);
 27.4486 +        extern void         glXSwapBuffers (Display *dpy, GLXDrawable drawable);
 27.4487 +        extern void         glXUseXFont (Font font, int first, int count, int listBase);
 27.4488 +
 27.4489 +    #endif // GLX_VERSION_1_0
 27.4490 +
 27.4491 +
 27.4492 +
 27.4493 +    #ifndef GLX_VERSION_1_1
 27.4494 +        #define GLX_VERSION_1_1
 27.4495 +
 27.4496 +        #define GLX_VENDOR 0x1
 27.4497 +        #define GLX_VERSION 0x2
 27.4498 +        #define GLX_EXTENSIONS 0x3
 27.4499 +
 27.4500 +        // These function pointers are assumed to always be present.
 27.4501 +        extern const char* glXQueryExtensionsString (Display *dpy, int screen);
 27.4502 +        extern const char* glXGetClientString (Display *dpy, int name);
 27.4503 +        extern const char* glXQueryServerString (Display *dpy, int screen, int name);
 27.4504 +    #endif
 27.4505 +
 27.4506 +
 27.4507 +    #ifndef GLX_VERSION_1_2
 27.4508 +        #define GLX_VERSION_1_2 1
 27.4509 +
 27.4510 +        typedef Display* (* PFNGLXGETCURRENTDISPLAYPROC) (void);
 27.4511 +
 27.4512 +        #define glXGetCurrentDisplay GLEGetCurrentFunction(glXGetCurrentDisplay)
 27.4513 +    #endif
 27.4514 +
 27.4515 +
 27.4516 +
 27.4517 +    #ifndef GLX_VERSION_1_3
 27.4518 +        #define GLX_VERSION_1_3 1
 27.4519 +
 27.4520 +        #define GLX_FRONT_LEFT_BUFFER_BIT 0x00000001
 27.4521 +        #define GLX_RGBA_BIT 0x00000001
 27.4522 +        #define GLX_WINDOW_BIT 0x00000001
 27.4523 +        #define GLX_COLOR_INDEX_BIT 0x00000002
 27.4524 +        #define GLX_FRONT_RIGHT_BUFFER_BIT 0x00000002
 27.4525 +        #define GLX_PIXMAP_BIT 0x00000002
 27.4526 +        #define GLX_BACK_LEFT_BUFFER_BIT 0x00000004
 27.4527 +        #define GLX_PBUFFER_BIT 0x00000004
 27.4528 +        #define GLX_BACK_RIGHT_BUFFER_BIT 0x00000008
 27.4529 +        #define GLX_AUX_BUFFERS_BIT 0x00000010
 27.4530 +        #define GLX_CONFIG_CAVEAT 0x20
 27.4531 +        #define GLX_DEPTH_BUFFER_BIT 0x00000020
 27.4532 +        #define GLX_X_VISUAL_TYPE 0x22
 27.4533 +        #define GLX_TRANSPARENT_TYPE 0x23
 27.4534 +        #define GLX_TRANSPARENT_INDEX_VALUE 0x24
 27.4535 +        #define GLX_TRANSPARENT_RED_VALUE 0x25
 27.4536 +        #define GLX_TRANSPARENT_GREEN_VALUE 0x26
 27.4537 +        #define GLX_TRANSPARENT_BLUE_VALUE 0x27
 27.4538 +        #define GLX_TRANSPARENT_ALPHA_VALUE 0x28
 27.4539 +        #define GLX_STENCIL_BUFFER_BIT 0x00000040
 27.4540 +        #define GLX_ACCUM_BUFFER_BIT 0x00000080
 27.4541 +        #define GLX_NONE 0x8000
 27.4542 +        #define GLX_SLOW_CONFIG 0x8001
 27.4543 +        #define GLX_TRUE_COLOR 0x8002
 27.4544 +        #define GLX_DIRECT_COLOR 0x8003
 27.4545 +        #define GLX_PSEUDO_COLOR 0x8004
 27.4546 +        #define GLX_STATIC_COLOR 0x8005
 27.4547 +        #define GLX_GRAY_SCALE 0x8006
 27.4548 +        #define GLX_STATIC_GRAY 0x8007
 27.4549 +        #define GLX_TRANSPARENT_RGB 0x8008
 27.4550 +        #define GLX_TRANSPARENT_INDEX 0x8009
 27.4551 +        #define GLX_VISUAL_ID 0x800B
 27.4552 +        #define GLX_SCREEN 0x800C
 27.4553 +        #define GLX_NON_CONFORMANT_CONFIG 0x800D
 27.4554 +        #define GLX_DRAWABLE_TYPE 0x8010
 27.4555 +        #define GLX_RENDER_TYPE 0x8011
 27.4556 +        #define GLX_X_RENDERABLE 0x8012
 27.4557 +        #define GLX_FBCONFIG_ID 0x8013
 27.4558 +        #define GLX_RGBA_TYPE 0x8014
 27.4559 +        #define GLX_COLOR_INDEX_TYPE 0x8015
 27.4560 +        #define GLX_MAX_PBUFFER_WIDTH 0x8016
 27.4561 +        #define GLX_MAX_PBUFFER_HEIGHT 0x8017
 27.4562 +        #define GLX_MAX_PBUFFER_PIXELS 0x8018
 27.4563 +        #define GLX_PRESERVED_CONTENTS 0x801B
 27.4564 +        #define GLX_LARGEST_PBUFFER 0x801C
 27.4565 +        #define GLX_WIDTH 0x801D
 27.4566 +        #define GLX_HEIGHT 0x801E
 27.4567 +        #define GLX_EVENT_MASK 0x801F
 27.4568 +        #define GLX_DAMAGED 0x8020
 27.4569 +        #define GLX_SAVED 0x8021
 27.4570 +        #define GLX_WINDOW 0x8022
 27.4571 +        #define GLX_PBUFFER 0x8023
 27.4572 +        #define GLX_PBUFFER_HEIGHT 0x8040
 27.4573 +        #define GLX_PBUFFER_WIDTH 0x8041
 27.4574 +        #define GLX_PBUFFER_CLOBBER_MASK 0x08000000
 27.4575 +        #define GLX_DONT_CARE 0xFFFFFFFF
 27.4576 +
 27.4577 +        typedef XID GLXFBConfigID;
 27.4578 +        typedef XID GLXPbuffer;
 27.4579 +        typedef XID GLXWindow;
 27.4580 +        typedef struct __GLXFBConfigRec *GLXFBConfig;
 27.4581 +
 27.4582 +        typedef struct {
 27.4583 +          int event_type; 
 27.4584 +          int draw_type; 
 27.4585 +          unsigned long serial; 
 27.4586 +          Bool send_event; 
 27.4587 +          Display *display; 
 27.4588 +          GLXDrawable drawable; 
 27.4589 +          unsigned int buffer_mask; 
 27.4590 +          unsigned int aux_buffer; 
 27.4591 +          int x, y; 
 27.4592 +          int width, height; 
 27.4593 +          int count; 
 27.4594 +        } GLXPbufferClobberEvent;
 27.4595 +     
 27.4596 +        typedef union __GLXEvent {
 27.4597 +          GLXPbufferClobberEvent glxpbufferclobber; 
 27.4598 +          long pad[24]; 
 27.4599 +        } GLXEvent;
 27.4600 +
 27.4601 +        typedef GLXFBConfig* (* PFNGLXCHOOSEFBCONFIGPROC) (::Display *dpy, int screen, const int *attrib_list, int *nelements);
 27.4602 +        typedef GLXContext   (* PFNGLXCREATENEWCONTEXTPROC) (::Display *dpy, GLXFBConfig config, int render_type, GLXContext share_list, Bool direct);
 27.4603 +        typedef GLXPbuffer   (* PFNGLXCREATEPBUFFERPROC) (::Display *dpy, GLXFBConfig config, const int *attrib_list);
 27.4604 +        typedef GLXPixmap    (* PFNGLXCREATEPIXMAPPROC) (::Display *dpy, GLXFBConfig config, Pixmap pixmap, const int *attrib_list);
 27.4605 +        typedef GLXWindow    (* PFNGLXCREATEWINDOWPROC) (::Display *dpy, GLXFBConfig config, Window win, const int *attrib_list);
 27.4606 +        typedef void         (* PFNGLXDESTROYPBUFFERPROC) (::Display *dpy, GLXPbuffer pbuf);
 27.4607 +        typedef void         (* PFNGLXDESTROYPIXMAPPROC) (::Display *dpy, GLXPixmap pixmap);
 27.4608 +        typedef void         (* PFNGLXDESTROYWINDOWPROC) (::Display *dpy, GLXWindow win);
 27.4609 +        typedef GLXDrawable  (* PFNGLXGETCURRENTREADDRAWABLEPROC) (void);
 27.4610 +        typedef int          (* PFNGLXGETFBCONFIGATTRIBPROC) (::Display *dpy, GLXFBConfig config, int attribute, int *value);
 27.4611 +        typedef GLXFBConfig* (* PFNGLXGETFBCONFIGSPROC) (::Display *dpy, int screen, int *nelements);
 27.4612 +        typedef void         (* PFNGLXGETSELECTEDEVENTPROC) (::Display *dpy, GLXDrawable draw, unsigned long *event_mask);
 27.4613 +        typedef XVisualInfo* (* PFNGLXGETVISUALFROMFBCONFIGPROC) (::Display *dpy, GLXFBConfig config);
 27.4614 +        typedef Bool         (* PFNGLXMAKECONTEXTCURRENTPROC) (::Display *display, GLXDrawable draw, GLXDrawable read, GLXContext ctx);
 27.4615 +        typedef int          (* PFNGLXQUERYCONTEXTPROC) (::Display *dpy, GLXContext ctx, int attribute, int *value);
 27.4616 +        typedef void         (* PFNGLXQUERYDRAWABLEPROC) (::Display *dpy, GLXDrawable draw, int attribute, unsigned int *value);
 27.4617 +        typedef void         (* PFNGLXSELECTEVENTPROC) (::Display *dpy, GLXDrawable draw, unsigned long event_mask);
 27.4618 +    
 27.4619 +        #define glXChooseFBConfig         GLEGetCurrentFunction(glXChooseFBConfig)
 27.4620 +        #define glXCreateNewContext       GLEGetCurrentFunction(glXCreateNewContext)
 27.4621 +        #define glXCreatePbuffer          GLEGetCurrentFunction(glXCreatePbuffer)
 27.4622 +        #define glXCreatePixmap           GLEGetCurrentFunction(glXCreatePixmap)
 27.4623 +        #define glXCreateWindow           GLEGetCurrentFunction(glXCreateWindow)
 27.4624 +        #define glXDestroyPbuffer         GLEGetCurrentFunction(glXDestroyPbuffer)
 27.4625 +        #define glXDestroyPixmap          GLEGetCurrentFunction(glXDestroyPixmap)
 27.4626 +        #define glXDestroyWindow          GLEGetCurrentFunction(glXDestroyWindow)
 27.4627 +        #define glXGetCurrentReadDrawable GLEGetCurrentFunction(glXGetCurrentReadDrawable)
 27.4628 +        #define glXGetFBConfigAttrib      GLEGetCurrentFunction(glXGetFBConfigAttrib)
 27.4629 +        #define glXGetFBConfigs           GLEGetCurrentFunction(glXGetFBConfigs)
 27.4630 +        #define glXGetSelectedEvent       GLEGetCurrentFunction(glXGetSelectedEvent)
 27.4631 +        #define glXGetVisualFromFBConfig  GLEGetCurrentFunction(glXGetVisualFromFBConfig)
 27.4632 +        #define glXMakeContextCurrent     GLEGetCurrentFunction(glXMakeContextCurrent)
 27.4633 +        #define glXQueryContext           GLEGetCurrentFunction(glXQueryContext)
 27.4634 +        #define glXQueryDrawable          GLEGetCurrentFunction(glXQueryDrawable)
 27.4635 +        #define glXSelectEvent            GLEGetCurrentFunction(glXSelectEvent)
 27.4636 +
 27.4637 +    #endif // GLX_VERSION_1_3
 27.4638 +
 27.4639 +
 27.4640 +
 27.4641 +    #ifndef GLX_VERSION_1_4
 27.4642 +        #define GLX_VERSION_1_4 1
 27.4643 +
 27.4644 +        #define GLX_SAMPLE_BUFFERS 100000
 27.4645 +        #define GLX_SAMPLES 100001
 27.4646 +
 27.4647 +        // This was glXGetProcAddressARB in GLX versions prior to v1.4.
 27.4648 +        // This function pointer is assumed to always be present.
 27.4649 +        extern void (* glXGetProcAddress(const GLubyte *procName)) ();
 27.4650 +
 27.4651 +        // For backward compatibility
 27.4652 +        extern void (* glXGetProcAddressARB(const GLubyte *procName)) ();
 27.4653 +    #endif
 27.4654 +
 27.4655 +
 27.4656 +
 27.4657 +	#ifndef GLX_ARB_create_context
 27.4658 +        #define GLX_ARB_create_context 1
 27.4659 +
 27.4660 +        #define GLX_CONTEXT_DEBUG_BIT_ARB              0x0001
 27.4661 +        #define GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002
 27.4662 +        #define GLX_CONTEXT_MAJOR_VERSION_ARB          0x2091
 27.4663 +        #define GLX_CONTEXT_MINOR_VERSION_ARB          0x2092
 27.4664 +        #define GLX_CONTEXT_FLAGS_ARB                  0x2094
 27.4665 +
 27.4666 +        typedef GLXContext (* PFNGLXCREATECONTEXTATTRIBSARBPROC) (Display* dpy, GLXFBConfig config, GLXContext share_context, Bool direct, const int *attrib_list);
 27.4667 +
 27.4668 +        #define glXCreateContextAttribsARB GLEGetCurrentFunction(glXCreateContextAttribsARB)
 27.4669 +
 27.4670 +        #define GLE_GLX_ARB_create_context GLEGetCurrentVariable(gle_GLX_ARB_create_context)
 27.4671 +    #endif
 27.4672 +
 27.4673 +
 27.4674 +    #ifndef GLX_ARB_create_context_profile
 27.4675 +        #define GLX_ARB_create_context_profile 1
 27.4676 +
 27.4677 +        #define GLX_CONTEXT_CORE_PROFILE_BIT_ARB 		  0x00000001
 27.4678 +        #define GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
 27.4679 +        #define GLX_CONTEXT_PROFILE_MASK_ARB 		0x9126
 27.4680 +
 27.4681 +        #define GLE_GLX_ARB_create_context_profile GLEGetCurrentVariable(gle_GLX_ARB_create_context_profile)
 27.4682 +    #endif
 27.4683 +
 27.4684 +
 27.4685 +    #ifndef GLX_ARB_create_context_robustness
 27.4686 +        #define GLX_ARB_create_context_robustness 1
 27.4687 +
 27.4688 +        #define GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB 		0x00000004
 27.4689 +        #define GLX_LOSE_CONTEXT_ON_RESET_ARB               0x8252
 27.4690 +        #define GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB 0x8256
 27.4691 +        #define GLX_NO_RESET_NOTIFICATION_ARB       		0x8261
 27.4692 +
 27.4693 +        #define GLE_GLX_ARB_create_context_robustness GLEGetCurrentVariable(gle_GLX_ARB_create_context_robustness)
 27.4694 +    #endif
 27.4695 +
 27.4696 +
 27.4697 +    // Note: In order to detect the GLX extensions' availability, we need to call glXQueryExtensionsString instead of glGetString(GL_EXTENSIONS).
 27.4698 +    #ifndef GLX_EXT_swap_control
 27.4699 +        #define GLX_EXT_swap_control 1
 27.4700 +
 27.4701 +        #define GLX_SWAP_INTERVAL_EXT 0x20F1
 27.4702 +        #define GLX_MAX_SWAP_INTERVAL_EXT 0x20F2
 27.4703 +
 27.4704 +        typedef void (* PFNGLXSWAPINTERVALEXTPROC) (Display* dpy, GLXDrawable drawable, int interval);
 27.4705 +
 27.4706 +        #define glXSwapIntervalEXT GLEGetCurrentFunction(glXSwapIntervalEXT)
 27.4707 +
 27.4708 +        #define GLE_GLX_EXT_swap_control GLEGetCurrentVariable(gle_GLX_EXT_swap_control)
 27.4709 +    #endif
 27.4710 +    
 27.4711 +
 27.4712 +    #ifndef GLX_OML_sync_control
 27.4713 +        #define GLX_OML_sync_control 1
 27.4714 +
 27.4715 +        typedef Bool    (* PFNGLXGETMSCRATEOMLPROC) (Display* dpy, GLXDrawable drawable, int32_t* numerator, int32_t* denominator);
 27.4716 +        typedef Bool    (* PFNGLXGETSYNCVALUESOMLPROC) (Display* dpy, GLXDrawable drawable, int64_t* ust, int64_t* msc, int64_t* sbc);
 27.4717 +        typedef int64_t (* PFNGLXSWAPBUFFERSMSCOMLPROC) (Display* dpy, GLXDrawable drawable, int64_t target_msc, int64_t divisor, int64_t remainder);
 27.4718 +        typedef Bool    (* PFNGLXWAITFORMSCOMLPROC) (Display* dpy, GLXDrawable drawable, int64_t target_msc, int64_t divisor, int64_t remainder, int64_t* ust, int64_t* msc, int64_t* sbc);
 27.4719 +        typedef Bool    (* PFNGLXWAITFORSBCOMLPROC) (Display* dpy, GLXDrawable drawable, int64_t target_sbc, int64_t* ust, int64_t* msc, int64_t* sbc);
 27.4720 +
 27.4721 +        #define glXGetMscRateOML     GLEGetCurrentFunction(glXGetMscRateOML)
 27.4722 +        #define glXGetSyncValuesOML  GLEGetCurrentFunction(glXGetSyncValuesOML)
 27.4723 +        #define glXSwapBuffersMscOML GLEGetCurrentFunction(glXSwapBuffersMscOML)
 27.4724 +        #define glXWaitForMscOML     GLEGetCurrentFunction(glXWaitForMscOML)
 27.4725 +        #define glXWaitForSbcOML     GLEGetCurrentFunction(glXWaitForSbcOML)
 27.4726 +
 27.4727 +        #define GLE_GLX_OML_sync_control GLEGetCurrentVariable(gle_GLX_OML_sync_control)
 27.4728 +    #endif
 27.4729 +    
 27.4730 +    
 27.4731 +    #ifndef GLX_MESA_swap_control
 27.4732 +        #define GLX_MESA_swap_control 1
 27.4733 +
 27.4734 +        // GLX_MESA_swap_control has the same functionality as GLX_EXT_swap_control but with a different interface, so we have an independent entry for it here.
 27.4735 +        typedef int (* PFNGLXGETSWAPINTERVALMESAPROC) (void);
 27.4736 +        typedef int (* PFNGLXSWAPINTERVALMESAPROC) (unsigned int interval);
 27.4737 +
 27.4738 +        #define glXGetSwapIntervalMESA GLEGetCurrentFunction(glXGetSwapIntervalMESA)
 27.4739 +        #define glXSwapIntervalMESA    GLEGetCurrentFunction(glXSwapIntervalMESA)
 27.4740 +
 27.4741 +        #define GLE_MESA_swap_control GLEGetCurrentVariable(gle_MESA_swap_control)
 27.4742 +    #endif
 27.4743 +
 27.4744 +#endif // GLE_GLX_ENABLED
 27.4745 +
 27.4746 +
 27.4747 +// Undo some defines, because the user may include <Windows.h> after including this header.
 27.4748 +#if defined(GLE_WINGDIAPI_DEFINED)
 27.4749 +    #undef WINGDIAPI
 27.4750 +#endif
 27.4751 +
 27.4752 +
 27.4753 +#ifdef __cplusplus
 27.4754 +} // extern "C"
 27.4755 +#endif
 27.4756 +
 27.4757 +
 27.4758 +
 27.4759 +#endif // Header include guard
 27.4760 +
 27.4761 +
 27.4762 +
 27.4763 +
 27.4764 +
    28.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    28.2 +++ b/LibOVR/Src/CAPI/GL/CAPI_GL_DistortionRenderer.cpp	Wed Jan 14 06:51:16 2015 +0200
    28.3 @@ -0,0 +1,1011 @@
    28.4 +/************************************************************************************
    28.5 +
    28.6 +Filename    :   CAPI_GL_DistortionRenderer.h
    28.7 +Content     :   Distortion renderer header for GL
    28.8 +Created     :   November 11, 2013
    28.9 +Authors     :   David Borel, Lee Cooper
   28.10 +
   28.11 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   28.12 +
   28.13 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License");
   28.14 +you may not use the Oculus VR Rift SDK except in compliance with the License,
   28.15 +which is provided at the time of installation or download, or which
   28.16 +otherwise accompanies this software in either electronic or hard copy form.
   28.17 +
   28.18 +You may obtain a copy of the License at
   28.19 +
   28.20 +http://www.oculusvr.com/licenses/LICENSE-3.2
   28.21 +
   28.22 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK
   28.23 +distributed under the License is distributed on an "AS IS" BASIS,
   28.24 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   28.25 +See the License for the specific language governing permissions and
   28.26 +limitations under the License.
   28.27 +
   28.28 +************************************************************************************/
   28.29 +
   28.30 +#include "CAPI_GL_DistortionRenderer.h"
   28.31 +
   28.32 +#include "CAPI_GL_DistortionShaders.h"
   28.33 +
   28.34 +#include "../../OVR_CAPI_GL.h"
   28.35 +#include "../../Kernel/OVR_Color.h"
   28.36 +
   28.37 +#if defined(OVR_OS_LINUX)
   28.38 +    #include "../../Displays/OVR_Linux_SDKWindow.h"
   28.39 +#elif defined(OVR_OS_MAC)
   28.40 +    #include <CoreGraphics/CGDirectDisplay.h>
   28.41 +    #include <OpenGL/OpenGL.h>
   28.42 +#endif
   28.43 +
   28.44 +namespace OVR { namespace CAPI { namespace GL {
   28.45 +
   28.46 +
   28.47 +// Distortion pixel shader lookup.
   28.48 +//  Bit 0: Chroma Correction
   28.49 +//  Bit 1: Timewarp
   28.50 +
   28.51 +enum {
   28.52 +    DistortionVertexShaderBitMask = 3,
   28.53 +    DistortionVertexShaderCount   = DistortionVertexShaderBitMask + 1,
   28.54 +    DistortionPixelShaderBitMask  = 1,
   28.55 +    DistortionPixelShaderCount    = DistortionPixelShaderBitMask + 1
   28.56 +};
   28.57 +
   28.58 +struct ShaderInfo
   28.59 +{
   28.60 +    const char* ShaderData;
   28.61 +    size_t ShaderSize;
   28.62 +    const ShaderBase::Uniform* ReflectionData;
   28.63 +    size_t ReflectionSize;
   28.64 +};
   28.65 +
   28.66 +// Do add a new distortion shader use these macros (with or w/o reflection)
   28.67 +#define SI_NOREFL(shader) { shader, sizeof(shader), NULL, 0 }
   28.68 +#define SI_REFL__(shader) { shader, sizeof(shader), shader ## _refl, sizeof( shader ## _refl )/sizeof(*(shader ## _refl)) }
   28.69 +
   28.70 +
   28.71 +static ShaderInfo DistortionVertexShaderLookup[DistortionVertexShaderCount] =
   28.72 +{
   28.73 +    SI_REFL__(Distortion_vs),
   28.74 +    SI_REFL__(DistortionChroma_vs),
   28.75 +    SI_REFL__(DistortionTimewarp_vs),
   28.76 +    SI_REFL__(DistortionTimewarpChroma_vs)
   28.77 +};
   28.78 +
   28.79 +static ShaderInfo DistortionPixelShaderLookup[DistortionPixelShaderCount] =
   28.80 +{
   28.81 +    SI_NOREFL(Distortion_fs),
   28.82 +    SI_NOREFL(DistortionChroma_fs)
   28.83 +};
   28.84 +
   28.85 +void DistortionShaderBitIndexCheck()
   28.86 +{
   28.87 +    OVR_COMPILER_ASSERT(ovrDistortionCap_Chromatic == 1);
   28.88 +    OVR_COMPILER_ASSERT(ovrDistortionCap_TimeWarp  == 2);
   28.89 +}
   28.90 +
   28.91 +
   28.92 +
   28.93 +struct DistortionVertex
   28.94 +{
   28.95 +    Vector2f ScreenPosNDC;
   28.96 +    Vector2f TanEyeAnglesR;
   28.97 +    Vector2f TanEyeAnglesG;
   28.98 +    Vector2f TanEyeAnglesB;
   28.99 +    Color    Col;
  28.100 +};
  28.101 +
  28.102 +
  28.103 +// Vertex type; same format is used for all shapes for simplicity.
  28.104 +// Shapes are built by adding vertices to Model.
  28.105 +struct LatencyVertex
  28.106 +{
  28.107 +    Vector3f  Pos;
  28.108 +    LatencyVertex (const Vector3f& p) : Pos(p) {}
  28.109 +};
  28.110 +
  28.111 +
  28.112 +//----------------------------------------------------------------------------
  28.113 +// ***** GL::DistortionRenderer
  28.114 +
  28.115 +DistortionRenderer::DistortionRenderer(ovrHmd hmd, FrameTimeManager& timeManager,
  28.116 +                                       const HMDRenderState& renderState)
  28.117 +    : CAPI::DistortionRenderer(ovrRenderAPI_OpenGL, hmd, timeManager, renderState)
  28.118 +    , RotateCCW90(false)
  28.119 +	, LatencyVAO(0)
  28.120 +    , OverdriveFbo(0)
  28.121 +{
  28.122 +	DistortionMeshVAOs[0] = 0;
  28.123 +	DistortionMeshVAOs[1] = 0;
  28.124 +
  28.125 +    // Initialize render params.
  28.126 +    memset(&RParams, 0, sizeof(RParams));
  28.127 +}
  28.128 +
  28.129 +DistortionRenderer::~DistortionRenderer()
  28.130 +{
  28.131 +    destroy();
  28.132 +}
  28.133 +
  28.134 +// static
  28.135 +CAPI::DistortionRenderer* DistortionRenderer::Create(ovrHmd hmd,
  28.136 +                                                     FrameTimeManager& timeManager,
  28.137 +                                                     const HMDRenderState& renderState)
  28.138 +{
  28.139 +    InitGLExtensions();
  28.140 +
  28.141 +    return new DistortionRenderer(hmd, timeManager, renderState);
  28.142 +}
  28.143 +
  28.144 +
  28.145 +bool DistortionRenderer::Initialize(const ovrRenderAPIConfig* apiConfig)
  28.146 +{
  28.147 +    const ovrGLConfig* config = (const ovrGLConfig*)apiConfig;
  28.148 +
  28.149 +    if (!config)
  28.150 +    {
  28.151 +        // Cleanup
  28.152 +        pEyeTextures[0].Clear();
  28.153 +        pEyeTextures[1].Clear();
  28.154 +        memset(&RParams, 0, sizeof(RParams));
  28.155 +        return true;
  28.156 +    }
  28.157 +
  28.158 +	RParams.Multisample = config->OGL.Header.Multisample;
  28.159 +	RParams.BackBufferSize      = config->OGL.Header.BackBufferSize;
  28.160 +#if defined(OVR_OS_WIN32)
  28.161 +	RParams.Window      = (config->OGL.Window) ? config->OGL.Window : GetActiveWindow();
  28.162 +    RParams.DC          = config->OGL.DC;
  28.163 +#elif defined(OVR_OS_LINUX)
  28.164 +    RotateCCW90 = false;
  28.165 +    if (   RState.DistortionCaps & ovrDistortionCap_LinuxDevFullscreen
  28.166 +        && SDKWindow::getRotation(HMD) == DistRotateCCW90)
  28.167 +    {
  28.168 +        RotateCCW90 = true;
  28.169 +    }
  28.170 +    if (config->OGL.Disp)
  28.171 +    {
  28.172 +        RParams.Disp = config->OGL.Disp;
  28.173 +    }
  28.174 +    if (!RParams.Disp)
  28.175 +    {
  28.176 +        RParams.Disp = glXGetCurrentDisplay();
  28.177 +    }
  28.178 +    if (!RParams.Disp)
  28.179 +    {
  28.180 +        OVR_DEBUG_LOG(("glXGetCurrentDisplay failed."));
  28.181 +        return false;
  28.182 +    }
  28.183 +#endif
  28.184 +	
  28.185 +    DistortionMeshVAOs[0] = 0;
  28.186 +    DistortionMeshVAOs[1] = 0;
  28.187 +
  28.188 +    LatencyVAO = 0;
  28.189 +
  28.190 +    GL::AutoContext autoGLContext(distortionContext); // Initializes distortionContext if not already, saves the current GL context, binds distortionContext, then at the end of scope re-binds the current GL context.
  28.191 +
  28.192 +    pEyeTextures[0] = *new Texture(&RParams, 0, 0);
  28.193 +    pEyeTextures[1] = *new Texture(&RParams, 0, 0);
  28.194 +
  28.195 +    initBuffersAndShaders();
  28.196 +
  28.197 +    initOverdrive();
  28.198 +
  28.199 +    return true;
  28.200 +}
  28.201 +
  28.202 +
  28.203 +void DistortionRenderer::initOverdrive()
  28.204 +{
  28.205 +	if(RState.DistortionCaps & ovrDistortionCap_Overdrive)
  28.206 +	{
  28.207 +		LastUsedOverdriveTextureIndex = 0;
  28.208 +        
  28.209 +        glGenFramebuffers(1, &OverdriveFbo);
  28.210 +        
  28.211 +        GLint internalFormat = (RState.DistortionCaps & ovrDistortionCap_SRGB) ? GL_SRGB_ALPHA : GL_RGBA;
  28.212 +        
  28.213 +		for (int i = 0; i < NumOverdriveTextures ; i++)
  28.214 +		{
  28.215 +            pOverdriveTextures[i] = *new Texture(&RParams, RParams.BackBufferSize.w, RParams.BackBufferSize.h);
  28.216 +            
  28.217 +            glBindTexture(GL_TEXTURE_2D, pOverdriveTextures[i]->TexId);
  28.218 +            glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, RParams.BackBufferSize.w, RParams.BackBufferSize.h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
  28.219 +            OVR_ASSERT( glGetError() == GL_NO_ERROR );
  28.220 +
  28.221 +            pOverdriveTextures[i]->SetSampleMode(Sample_ClampBorder | Sample_Linear);
  28.222 +            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
  28.223 +            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
  28.224 +            OVR_ASSERT(glGetError() == 0);
  28.225 +
  28.226 +            // clear the new buffer
  28.227 +            glBindFramebuffer(GL_FRAMEBUFFER, OverdriveFbo );
  28.228 +            glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, pOverdriveTextures[i]->TexId, 0);
  28.229 +            glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
  28.230 +            OVR_ASSERT(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
  28.231 +            GLenum drawBuffers[] = { GL_COLOR_ATTACHMENT0};
  28.232 +            glDrawBuffers(OVR_ARRAY_COUNT(drawBuffers), drawBuffers);
  28.233 +            glClearColor(0,0,0,1);
  28.234 +            glClear(GL_COLOR_BUFFER_BIT);
  28.235 +        }
  28.236 +
  28.237 +        {
  28.238 +            OverdriveBackBufferTexture = *new Texture(&RParams, RParams.BackBufferSize.w, RParams.BackBufferSize.h);
  28.239 +
  28.240 +            glBindTexture(GL_TEXTURE_2D, OverdriveBackBufferTexture->TexId);
  28.241 +            glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, RParams.BackBufferSize.w, RParams.BackBufferSize.h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
  28.242 +            OVR_ASSERT(glGetError() == 0);
  28.243 +
  28.244 +            OverdriveBackBufferTexture->SetSampleMode(Sample_ClampBorder | Sample_Linear);
  28.245 +            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
  28.246 +            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
  28.247 +            OVR_ASSERT(glGetError() == 0);
  28.248 +
  28.249 +            // clear the new buffer
  28.250 +            glBindFramebuffer(GL_FRAMEBUFFER, OverdriveFbo );
  28.251 +            glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, OverdriveBackBufferTexture->TexId, 0);
  28.252 +            glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
  28.253 +            OVR_ASSERT(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
  28.254 +            GLenum drawBuffers[] = { GL_COLOR_ATTACHMENT0};
  28.255 +            glDrawBuffers(OVR_ARRAY_COUNT(drawBuffers), drawBuffers);
  28.256 +            glClearColor(0,0,0,1);
  28.257 +            glClear(GL_COLOR_BUFFER_BIT);
  28.258 +        }
  28.259 +
  28.260 +        glBindFramebuffer(GL_FRAMEBUFFER, 0);
  28.261 +	}
  28.262 +	else
  28.263 +	{
  28.264 +		LastUsedOverdriveTextureIndex = -1;
  28.265 +	}
  28.266 +}
  28.267 +
  28.268 +void DistortionRenderer::SubmitEye(int eyeId, const ovrTexture* eyeTexture)
  28.269 +{
  28.270 +    // Doesn't do a lot in here??
  28.271 +	const ovrGLTexture* tex = (const ovrGLTexture*)eyeTexture;
  28.272 +
  28.273 +	if (tex)
  28.274 +	{
  28.275 +        // Write in values
  28.276 +        eachEye[eyeId].texture = tex->OGL.TexId;
  28.277 +
  28.278 +        // Its only at this point we discover what the viewport of the texture is.
  28.279 +	    // because presumably we allow users to realtime adjust the resolution.
  28.280 +        eachEye[eyeId].TextureSize    = tex->OGL.Header.TextureSize;
  28.281 +        eachEye[eyeId].RenderViewport = tex->OGL.Header.RenderViewport;
  28.282 +
  28.283 +        const ovrEyeRenderDesc& erd = RState.EyeRenderDesc[eyeId];
  28.284 +    
  28.285 +        ovrHmd_GetRenderScaleAndOffset( erd.Fov,
  28.286 +                                        eachEye[eyeId].TextureSize, eachEye[eyeId].RenderViewport,
  28.287 +                                        eachEye[eyeId].UVScaleOffset );
  28.288 +
  28.289 +		if (!(RState.DistortionCaps & ovrDistortionCap_FlipInput))
  28.290 +		{
  28.291 +			eachEye[eyeId].UVScaleOffset[0].y = -eachEye[eyeId].UVScaleOffset[0].y;
  28.292 +			eachEye[eyeId].UVScaleOffset[1].y = 1.0f - eachEye[eyeId].UVScaleOffset[1].y;
  28.293 +		}
  28.294 +
  28.295 +        pEyeTextures[eyeId]->UpdatePlaceholderTexture(tex->OGL.TexId,
  28.296 +                                                      tex->OGL.Header.TextureSize);
  28.297 +	}
  28.298 +}
  28.299 +
  28.300 +void DistortionRenderer::renderEndFrame()
  28.301 +{
  28.302 +    renderDistortion(pEyeTextures[0], pEyeTextures[1]);
  28.303 +
  28.304 +    // TODO: Add rendering context to callback.
  28.305 +    if(RegisteredPostDistortionCallback)
  28.306 +       RegisteredPostDistortionCallback(NULL);
  28.307 +
  28.308 +    if(LatencyTest2Active)
  28.309 +    {
  28.310 +        renderLatencyPixel(LatencyTest2DrawColor);
  28.311 +    }
  28.312 +}
  28.313 +
  28.314 +void DistortionRenderer::EndFrame(bool swapBuffers)
  28.315 +{
  28.316 +    Context currContext;
  28.317 +    currContext.InitFromCurrent();
  28.318 +#if defined(OVR_OS_MAC)
  28.319 +    distortionContext.SetSurface( currContext );
  28.320 +#endif
  28.321 +
  28.322 +    // Don't spin if we are explicitly asked not to
  28.323 +    if ((RState.DistortionCaps & ovrDistortionCap_TimeWarp) &&
  28.324 +        !(RState.DistortionCaps & ovrDistortionCap_ProfileNoTimewarpSpinWaits))
  28.325 +    {
  28.326 +        if (!TimeManager.NeedDistortionTimeMeasurement())
  28.327 +        {
  28.328 +            // Wait for timewarp distortion if it is time and Gpu idle
  28.329 +            FlushGpuAndWaitTillTime(TimeManager.GetFrameTiming().TimewarpPointTime);
  28.330 +
  28.331 +            distortionContext.Bind();
  28.332 +            renderEndFrame();
  28.333 +        }
  28.334 +        else
  28.335 +        {
  28.336 +            // If needed, measure distortion time so that TimeManager can better estimate
  28.337 +            // latency-reducing time-warp wait timing.
  28.338 +            WaitUntilGpuIdle();
  28.339 +            double  distortionStartTime = ovr_GetTimeInSeconds();
  28.340 +
  28.341 +            distortionContext.Bind();
  28.342 +            renderEndFrame();
  28.343 +
  28.344 +            WaitUntilGpuIdle();
  28.345 +            TimeManager.AddDistortionTimeMeasurement(ovr_GetTimeInSeconds() - distortionStartTime);
  28.346 +        }
  28.347 +    }
  28.348 +    else
  28.349 +    {
  28.350 +        distortionContext.Bind();
  28.351 +        renderEndFrame();
  28.352 +    }
  28.353 +
  28.354 +    if(LatencyTestActive)
  28.355 +    {
  28.356 +        renderLatencyQuad(LatencyTestDrawColor);
  28.357 +    }
  28.358 +
  28.359 +    if (swapBuffers)
  28.360 +    {
  28.361 +		bool useVsync = ((RState.EnabledHmdCaps & ovrHmdCap_NoVSync) == 0);
  28.362 +        int ourSwapInterval = (useVsync) ? 1 : 0;
  28.363 +        int originalSwapInterval;
  28.364 +        
  28.365 +#if defined(OVR_OS_WIN32)
  28.366 +        originalSwapInterval = wglGetSwapIntervalEXT();
  28.367 +        
  28.368 +        if (ourSwapInterval != originalSwapInterval)
  28.369 +            wglSwapIntervalEXT(ourSwapInterval);
  28.370 +
  28.371 +        HDC dc = (RParams.DC != NULL) ? RParams.DC : GetDC(RParams.Window);
  28.372 +		BOOL success = SwapBuffers(dc);
  28.373 +        OVR_ASSERT_AND_UNUSED(success, success);
  28.374 +
  28.375 +        if (RParams.DC == NULL)
  28.376 +            ReleaseDC(RParams.Window, dc);
  28.377 +        
  28.378 +#elif defined(OVR_OS_MAC)
  28.379 +        originalSwapInterval = 0;
  28.380 +        CGLContextObj context = CGLGetCurrentContext();
  28.381 +        CGLError err = CGLGetParameter(context, kCGLCPSwapInterval, &originalSwapInterval);
  28.382 +        OVR_ASSERT_AND_UNUSED(err == kCGLNoError, err);
  28.383 +        
  28.384 +        if (ourSwapInterval != originalSwapInterval)
  28.385 +            CGLSetParameter(context, kCGLCPSwapInterval, &ourSwapInterval);
  28.386 +        
  28.387 +        CGLFlushDrawable(context);
  28.388 +        
  28.389 +#elif defined(OVR_OS_LINUX)
  28.390 +        originalSwapInterval = 0;
  28.391 +        GLXDrawable drawable = glXGetCurrentDrawable();
  28.392 +        struct _XDisplay* x11Display = RParams.Disp;
  28.393 +
  28.394 +        if(GLE_GLX_EXT_swap_control)
  28.395 +        {
  28.396 +            static_assert(sizeof(GLuint) == sizeof(originalSwapInterval), "size mismatch");
  28.397 +            glXQueryDrawable(x11Display, drawable, GLX_SWAP_INTERVAL_EXT, (GLuint*)&originalSwapInterval);
  28.398 +
  28.399 +            if (ourSwapInterval != originalSwapInterval)
  28.400 +                glXSwapIntervalEXT(x11Display, drawable, ourSwapInterval);
  28.401 +        }
  28.402 +        else if (GLE_MESA_swap_control) // There is also GLX_SGI_swap_control
  28.403 +        {
  28.404 +            originalSwapInterval = glXGetSwapIntervalMESA();
  28.405 +
  28.406 +            if (ourSwapInterval != originalSwapInterval)
  28.407 +                glXSwapIntervalMESA(ourSwapInterval);
  28.408 +        }
  28.409 +
  28.410 +        glXSwapBuffers(x11Display, drawable);
  28.411 +#endif
  28.412 +
  28.413 +        // Force GPU to flush the scene, resulting in the lowest possible latency.
  28.414 +        // It's critical that this flush is *after* present, because it results in the wait
  28.415 +        // below completing after the vsync.
  28.416 +        // With the display driver (direct mode) this flush is obsolete and theoretically
  28.417 +        // should be a no-op and so doesn't need to be done if running in direct mode.
  28.418 +        if (RState.OurHMDInfo.InCompatibilityMode &&
  28.419 +            !(RState.DistortionCaps & ovrDistortionCap_ProfileNoTimewarpSpinWaits))
  28.420 +            WaitUntilGpuIdle();
  28.421 +        
  28.422 +        // Restore the original swap interval if we changed it above.
  28.423 +        if (originalSwapInterval != ourSwapInterval)
  28.424 +        {
  28.425 +#if defined(OVR_OS_WIN32)
  28.426 +            wglSwapIntervalEXT(originalSwapInterval);
  28.427 +#elif defined(OVR_OS_MAC)
  28.428 +            CGLSetParameter(context, kCGLCPSwapInterval, &originalSwapInterval);
  28.429 +#elif defined(OVR_OS_LINUX)
  28.430 +            if(GLE_GLX_EXT_swap_control)
  28.431 +                glXSwapIntervalEXT(x11Display, drawable, (GLuint)originalSwapInterval);
  28.432 +            else if(GLE_MESA_swap_control)
  28.433 +                glXSwapIntervalMESA(originalSwapInterval);
  28.434 +#endif
  28.435 +        }
  28.436 +    }
  28.437 +
  28.438 +    currContext.Bind();
  28.439 +}
  28.440 +
  28.441 +void DistortionRenderer::WaitUntilGpuIdle()
  28.442 +{
  28.443 +	glFinish(); // Block until current OpenGL commands (including swap) are complete.
  28.444 +}
  28.445 +
  28.446 +double DistortionRenderer::FlushGpuAndWaitTillTime(double absTime)
  28.447 +{
  28.448 +    // because glFlush() is not strict enough certain GL drivers
  28.449 +    // we do a glFinish(), but before doing so, we make sure we're not
  28.450 +    // running late
  28.451 +    double initialTime = ovr_GetTimeInSeconds();
  28.452 +    if (initialTime >= absTime)
  28.453 +        return 0.0;
  28.454 +
  28.455 +    glFinish();
  28.456 +
  28.457 +    return WaitTillTime(absTime);
  28.458 +}
  28.459 +
  28.460 +void DistortionRenderer::initBuffersAndShaders()
  28.461 +{
  28.462 +    for ( int eyeNum = 0; eyeNum < 2; eyeNum++ )
  28.463 +    {
  28.464 +        // Allocate & generate distortion mesh vertices.
  28.465 +        ovrDistortionMesh meshData;
  28.466 +
  28.467 +        if (!ovrHmd_CreateDistortionMesh( HMD,
  28.468 +                                          RState.EyeRenderDesc[eyeNum].Eye,
  28.469 +                                          RState.EyeRenderDesc[eyeNum].Fov,
  28.470 +                                          RState.DistortionCaps,
  28.471 +                                          &meshData) )
  28.472 +        {
  28.473 +            OVR_ASSERT(false);
  28.474 +            continue;
  28.475 +        }
  28.476 +
  28.477 +        // Now parse the vertex data and create a render ready vertex buffer from it
  28.478 +        DistortionVertex *   pVBVerts    = (DistortionVertex*)OVR_ALLOC ( sizeof(DistortionVertex) * meshData.VertexCount );
  28.479 +        DistortionVertex *   pCurVBVert  = pVBVerts;
  28.480 +        ovrDistortionVertex* pCurOvrVert = meshData.pVertexData;
  28.481 +
  28.482 +        for ( unsigned vertNum = 0; vertNum < meshData.VertexCount; vertNum++ )
  28.483 +        {
  28.484 +            pCurVBVert->ScreenPosNDC.x = pCurOvrVert->ScreenPosNDC.x;
  28.485 +            pCurVBVert->ScreenPosNDC.y = pCurOvrVert->ScreenPosNDC.y;
  28.486 +
  28.487 +            if (RotateCCW90)
  28.488 +            {
  28.489 +                OVR::Alg::Swap(pCurVBVert->ScreenPosNDC.x, pCurVBVert->ScreenPosNDC.y);
  28.490 +                pCurVBVert->ScreenPosNDC.x = -pCurVBVert->ScreenPosNDC.x;
  28.491 +            }
  28.492 +
  28.493 +            // Previous code here did this: pCurVBVert->TanEyeAnglesR = (*(Vector2f*)&pCurOvrVert->TanEyeAnglesR); However that's an usafe
  28.494 +            // cast of unrelated types which can result in undefined behavior by a conforming compiler. A safe equivalent is simply memcpy.
  28.495 +            static_assert(sizeof(OVR::Vector2f) == sizeof(ovrVector2f), "Mismatch of structs that are presumed binary equivalents.");
  28.496 +            memcpy(&pCurVBVert->TanEyeAnglesR, &pCurOvrVert->TanEyeAnglesR, sizeof(pCurVBVert->TanEyeAnglesR));
  28.497 +            memcpy(&pCurVBVert->TanEyeAnglesG, &pCurOvrVert->TanEyeAnglesG, sizeof(pCurVBVert->TanEyeAnglesG));
  28.498 +            memcpy(&pCurVBVert->TanEyeAnglesB, &pCurOvrVert->TanEyeAnglesB, sizeof(pCurVBVert->TanEyeAnglesB));
  28.499 +
  28.500 +            // Convert [0.0f,1.0f] to [0,255]
  28.501 +			if (RState.DistortionCaps & ovrDistortionCap_Vignette)
  28.502 +            {
  28.503 +                if(RState.DistortionCaps & ovrDistortionCap_SRGB)
  28.504 +                    pCurOvrVert->VignetteFactor = pow(pCurOvrVert->VignetteFactor, 2.1f);
  28.505 +
  28.506 +                pCurVBVert->Col.R = (uint8_t)( Alg::Max ( pCurOvrVert->VignetteFactor, 0.0f ) * 255.99f );
  28.507 +            }
  28.508 +			else
  28.509 +				pCurVBVert->Col.R = 255;
  28.510 +
  28.511 +            pCurVBVert->Col.G = pCurVBVert->Col.R;
  28.512 +            pCurVBVert->Col.B = pCurVBVert->Col.R;
  28.513 +            pCurVBVert->Col.A = (uint8_t)( pCurOvrVert->TimeWarpFactor * 255.99f );;
  28.514 +            pCurOvrVert++;
  28.515 +            pCurVBVert++;
  28.516 +        }
  28.517 +
  28.518 +        DistortionMeshVBs[eyeNum] = *new Buffer(&RParams);
  28.519 +        DistortionMeshVBs[eyeNum]->Data ( Buffer_Vertex | Buffer_ReadOnly, pVBVerts, sizeof(DistortionVertex) * meshData.VertexCount );
  28.520 +        DistortionMeshIBs[eyeNum] = *new Buffer(&RParams);
  28.521 +        DistortionMeshIBs[eyeNum]->Data ( Buffer_Index | Buffer_ReadOnly, meshData.pIndexData, ( sizeof(int16_t) * meshData.IndexCount ) );
  28.522 +
  28.523 +        OVR_FREE ( pVBVerts );
  28.524 +        ovrHmd_DestroyDistortionMesh( &meshData );
  28.525 +    }
  28.526 +
  28.527 +    initShaders();
  28.528 +}
  28.529 +
  28.530 +void DistortionRenderer::renderDistortion(Texture* leftEyeTexture, Texture* rightEyeTexture)
  28.531 +{
  28.532 +    bool overdriveActive = IsOverdriveActive();
  28.533 +    int currOverdriveTextureIndex = -1;
  28.534 +
  28.535 +    if(overdriveActive)
  28.536 +    {
  28.537 +        currOverdriveTextureIndex = (LastUsedOverdriveTextureIndex + 1) % NumOverdriveTextures;
  28.538 +
  28.539 +        //glBindFramebuffer(GL_FRAMEBUFFER, 0);
  28.540 +        glBindFramebuffer(GL_FRAMEBUFFER, OverdriveFbo );
  28.541 +        
  28.542 +        GLenum drawBuffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
  28.543 +        glDrawBuffers(OVR_ARRAY_COUNT(drawBuffers), drawBuffers);
  28.544 +
  28.545 +        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, pOverdriveTextures[currOverdriveTextureIndex]->TexId, 0);
  28.546 +        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, OverdriveBackBufferTexture->TexId, 0);
  28.547 +        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
  28.548 +        OVR_ASSERT(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
  28.549 +    }
  28.550 +    else
  28.551 +    {
  28.552 +        glBindFramebuffer(GL_FRAMEBUFFER, 0);
  28.553 +    }
  28.554 +
  28.555 +    setViewport( Recti(0,0, RParams.BackBufferSize.w, RParams.BackBufferSize.h) );
  28.556 +
  28.557 +	if (RState.DistortionCaps & ovrDistortionCap_SRGB)
  28.558 +		glEnable(GL_FRAMEBUFFER_SRGB);
  28.559 +    else
  28.560 +        glDisable(GL_FRAMEBUFFER_SRGB);
  28.561 +
  28.562 +	glDisable(GL_CULL_FACE);
  28.563 +	glDisable(GL_DEPTH_TEST);
  28.564 +    
  28.565 +    if (GLE_EXT_draw_buffers2)
  28.566 +    {
  28.567 +        glDisablei(GL_BLEND, 0);
  28.568 +        glColorMaski(0, GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
  28.569 +    }
  28.570 +    else
  28.571 +    {
  28.572 +        glDisable(GL_BLEND);
  28.573 +        glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
  28.574 +    }
  28.575 +    
  28.576 +    glDisable(GL_DITHER);
  28.577 +    glDisable(GL_RASTERIZER_DISCARD);
  28.578 +    if (GLEContext::GetCurrentContext()->WholeVersion >= 302)
  28.579 +    {
  28.580 +        glDisable(GL_SAMPLE_MASK);
  28.581 +    }
  28.582 +        
  28.583 +	glClearColor(
  28.584 +		RState.ClearColor[0],
  28.585 +		RState.ClearColor[1],
  28.586 +		RState.ClearColor[2],
  28.587 +		RState.ClearColor[3] );
  28.588 +
  28.589 +    glClear(GL_COLOR_BUFFER_BIT);
  28.590 +
  28.591 +    for (int eyeNum = 0; eyeNum < 2; eyeNum++)
  28.592 +    {
  28.593 +		ShaderFill distortionShaderFill(DistortionShader);
  28.594 +        distortionShaderFill.SetTexture(0, eyeNum == 0 ? leftEyeTexture : rightEyeTexture);
  28.595 +
  28.596 +        if(overdriveActive)
  28.597 +        {
  28.598 +            distortionShaderFill.SetTexture(1, pOverdriveTextures[LastUsedOverdriveTextureIndex]);
  28.599 +
  28.600 +            float overdriveScaleRegularRise;
  28.601 +            float overdriveScaleRegularFall;
  28.602 +            GetOverdriveScales(overdriveScaleRegularRise, overdriveScaleRegularFall);
  28.603 +            DistortionShader->SetUniform3f("OverdriveScales_IsSrgb", overdriveScaleRegularRise, overdriveScaleRegularFall,
  28.604 +																	(RState.DistortionCaps & ovrDistortionCap_SRGB) ? 1.0f : -1.0f);
  28.605 +        }
  28.606 +        else
  28.607 +        {
  28.608 +            // -1.0f disables PLO            
  28.609 +            DistortionShader->SetUniform3f("OverdriveScales_IsSrgb", -1.0f, -1.0f, -1.0f);
  28.610 +        }
  28.611 +
  28.612 +		DistortionShader->SetUniform2f("EyeToSourceUVScale",  eachEye[eyeNum].UVScaleOffset[0].x, eachEye[eyeNum].UVScaleOffset[0].y);
  28.613 +        // Convert Y to 1-Y as OpenGL is inverse of D3D
  28.614 +		DistortionShader->SetUniform2f("EyeToSourceUVOffset", eachEye[eyeNum].UVScaleOffset[1].x, 1.0f - eachEye[eyeNum].UVScaleOffset[1].y);
  28.615 +        
  28.616 +		if (RState.DistortionCaps & ovrDistortionCap_TimeWarp)
  28.617 +		{                       
  28.618 +            ovrMatrix4f timeWarpMatrices[2];            
  28.619 +            ovrHmd_GetEyeTimewarpMatrices(HMD, (ovrEyeType)eyeNum,
  28.620 +                                          RState.EyeRenderPoses[eyeNum], timeWarpMatrices);
  28.621 +
  28.622 +            // Feed identity like matrices in until we get proper timewarp calculation going on
  28.623 +			DistortionShader->SetUniform4x4f("EyeRotationStart", Matrix4f(timeWarpMatrices[0]).Transposed());
  28.624 +			DistortionShader->SetUniform4x4f("EyeRotationEnd",   Matrix4f(timeWarpMatrices[1]).Transposed());
  28.625 +
  28.626 +            renderPrimitives(&distortionShaderFill, DistortionMeshVBs[eyeNum], DistortionMeshIBs[eyeNum],
  28.627 +                            0, (int)DistortionMeshIBs[eyeNum]->GetSize()/2, Prim_Triangles, &DistortionMeshVAOs[eyeNum], true);
  28.628 +		}
  28.629 +        else
  28.630 +        {
  28.631 +            renderPrimitives(&distortionShaderFill, DistortionMeshVBs[eyeNum], DistortionMeshIBs[eyeNum],
  28.632 +                            0, (int)DistortionMeshIBs[eyeNum]->GetSize()/2, Prim_Triangles, &DistortionMeshVAOs[eyeNum], true);
  28.633 +        }
  28.634 +    }
  28.635 +
  28.636 +    LastUsedOverdriveTextureIndex = currOverdriveTextureIndex;
  28.637 +
  28.638 +    // Re-activate to only draw on back buffer
  28.639 +    if(overdriveActive)
  28.640 +    {
  28.641 +        GLenum drawBuffers[] = { GL_COLOR_ATTACHMENT0};
  28.642 +        glDrawBuffers(OVR_ARRAY_COUNT(drawBuffers), drawBuffers);
  28.643 +
  28.644 +        glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
  28.645 +        //glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
  28.646 +        //glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, 0, 0);
  28.647 +        OVR_ASSERT(glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
  28.648 +
  28.649 +        glBindFramebuffer( GL_READ_FRAMEBUFFER, OverdriveFbo );
  28.650 +        glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, OverdriveBackBufferTexture->TexId, 0);
  28.651 +        glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
  28.652 +        OVR_ASSERT(glCheckFramebufferStatus(GL_READ_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
  28.653 +
  28.654 +        glBlitFramebuffer( 0, 0, OverdriveBackBufferTexture->GetWidth(), OverdriveBackBufferTexture->GetHeight(),
  28.655 +                           0, 0, OverdriveBackBufferTexture->GetWidth(), OverdriveBackBufferTexture->GetHeight(),
  28.656 +                           GL_COLOR_BUFFER_BIT, GL_NEAREST );
  28.657 +
  28.658 +        glBindFramebuffer( GL_FRAMEBUFFER, 0 );
  28.659 +        GLint err = glGetError();
  28.660 +        OVR_ASSERT(!err); OVR_UNUSED(err);
  28.661 +    }
  28.662 +}
  28.663 +
  28.664 +
  28.665 +void DistortionRenderer::createDrawQuad()
  28.666 +{
  28.667 +    const int numQuadVerts = 4;
  28.668 +    LatencyTesterQuadVB = *new Buffer(&RParams);
  28.669 +    if(!LatencyTesterQuadVB)
  28.670 +    {
  28.671 +        return;
  28.672 +    }
  28.673 +
  28.674 +    LatencyTesterQuadVB->Data(Buffer_Vertex, NULL, numQuadVerts * sizeof(LatencyVertex));
  28.675 +    LatencyVertex* vertices = (LatencyVertex*)LatencyTesterQuadVB->Map(0, numQuadVerts * sizeof(LatencyVertex), Map_Discard);
  28.676 +    if(!vertices)
  28.677 +    {
  28.678 +        OVR_ASSERT(false); // failed to lock vertex buffer
  28.679 +        return;
  28.680 +    }
  28.681 +
  28.682 +    const float left   = -1.0f;
  28.683 +    const float top    = -1.0f;
  28.684 +    const float right  =  1.0f;
  28.685 +    const float bottom =  1.0f;
  28.686 +
  28.687 +    vertices[0] = LatencyVertex(Vector3f(left,  top,    0.0f));
  28.688 +    vertices[1] = LatencyVertex(Vector3f(left,  bottom, 0.0f));
  28.689 +    vertices[2] = LatencyVertex(Vector3f(right, top,    0.0f));
  28.690 +    vertices[3] = LatencyVertex(Vector3f(right, bottom, 0.0f));
  28.691 +
  28.692 +    LatencyTesterQuadVB->Unmap(vertices);
  28.693 +}
  28.694 +
  28.695 +void DistortionRenderer::renderLatencyQuad(unsigned char* latencyTesterDrawColor)
  28.696 +{
  28.697 +    const int numQuadVerts = 4;
  28.698 +
  28.699 +    if(!LatencyTesterQuadVB)
  28.700 +    {
  28.701 +        createDrawQuad();
  28.702 +    }
  28.703 +       
  28.704 +    Ptr<ShaderSet> quadShader = (RState.DistortionCaps & ovrDistortionCap_SRGB) ? SimpleQuadGammaShader : SimpleQuadShader;
  28.705 +    ShaderFill quadFill(quadShader);
  28.706 +    //quadFill.SetInputLayout(SimpleQuadVertexIL);
  28.707 +
  28.708 +    setViewport(Recti(0,0, RParams.BackBufferSize.w, RParams.BackBufferSize.h));
  28.709 +
  28.710 +    quadShader->SetUniform2f("Scale", 0.3f, 0.3f);
  28.711 +    quadShader->SetUniform4f("Color", (float)latencyTesterDrawColor[0] / 255.99f,
  28.712 +                                      (float)latencyTesterDrawColor[0] / 255.99f,
  28.713 +                                      (float)latencyTesterDrawColor[0] / 255.99f,
  28.714 +                                      1.0f);
  28.715 +
  28.716 +    for(int eyeNum = 0; eyeNum < 2; eyeNum++)
  28.717 +    {
  28.718 +        quadShader->SetUniform2f("PositionOffset", eyeNum == 0 ? -0.5f : 0.5f, 0.0f);    
  28.719 +        renderPrimitives(&quadFill, LatencyTesterQuadVB, NULL, 0, numQuadVerts, Prim_TriangleStrip, &LatencyVAO, false);
  28.720 +    }
  28.721 +}
  28.722 +
  28.723 +void DistortionRenderer::renderLatencyPixel(unsigned char* latencyTesterPixelColor)
  28.724 +{
  28.725 +    const int numQuadVerts = 4;
  28.726 +
  28.727 +    if(!LatencyTesterQuadVB)
  28.728 +    {
  28.729 +        createDrawQuad();
  28.730 +    }
  28.731 +
  28.732 +    Ptr<ShaderSet> quadShader = (RState.DistortionCaps & ovrDistortionCap_SRGB) ? SimpleQuadGammaShader : SimpleQuadShader;
  28.733 +    ShaderFill quadFill(quadShader);
  28.734 +
  28.735 +    setViewport(Recti(0,0, RParams.BackBufferSize.w, RParams.BackBufferSize.h));
  28.736 +
  28.737 +#ifdef OVR_BUILD_DEBUG
  28.738 +    quadShader->SetUniform4f("Color", (float)latencyTesterPixelColor[0] / 255.99f,
  28.739 +                                      (float)latencyTesterPixelColor[1] / 255.99f,
  28.740 +                                      (float)latencyTesterPixelColor[2] / 255.99f,
  28.741 +                                      1.0f);
  28.742 +
  28.743 +    Vector2f scale(20.0f / RParams.BackBufferSize.w, 20.0f / RParams.BackBufferSize.h); 
  28.744 +#else
  28.745 +    quadShader->SetUniform4f("Color", (float)latencyTesterPixelColor[0] / 255.99f,
  28.746 +                                      (float)latencyTesterPixelColor[0] / 255.99f,
  28.747 +                                      (float)latencyTesterPixelColor[0] / 255.99f,
  28.748 +                                      1.0f);
  28.749 +
  28.750 +    Vector2f scale(1.0f / RParams.BackBufferSize.w, 1.0f / RParams.BackBufferSize.h); 
  28.751 +#endif
  28.752 +    quadShader->SetUniform2f("Scale", scale.x, scale.y);
  28.753 +    if (!RotateCCW90)
  28.754 +        quadShader->SetUniform2f("PositionOffset", 1.0f-scale.x, 1.0f-scale.y);
  28.755 +    else
  28.756 +        quadShader->SetUniform2f("PositionOffset", -(1.0f-scale.x), 1.0f-scale.y);
  28.757 +	renderPrimitives(&quadFill, LatencyTesterQuadVB, NULL, 0, numQuadVerts, Prim_TriangleStrip, &LatencyVAO, false);
  28.758 +}
  28.759 +
  28.760 +void DistortionRenderer::renderPrimitives(
  28.761 +                          const ShaderFill* fill,
  28.762 +                          Buffer* vertices, Buffer* indices,
  28.763 +                          int offset, int count,
  28.764 +                          PrimitiveType rprim, GLuint* vao, bool isDistortionMesh)
  28.765 +{
  28.766 +    GLenum prim;
  28.767 +    switch (rprim)
  28.768 +    {
  28.769 +    case Prim_Triangles:
  28.770 +        prim = GL_TRIANGLES;
  28.771 +        break;
  28.772 +    case Prim_Lines:
  28.773 +        prim = GL_LINES;
  28.774 +        break;
  28.775 +    case Prim_TriangleStrip:
  28.776 +        prim = GL_TRIANGLE_STRIP;
  28.777 +        break;
  28.778 +    default:
  28.779 +        OVR_ASSERT(false);
  28.780 +        return;
  28.781 +    }
  28.782 +
  28.783 +    fill->Set();
  28.784 +    
  28.785 +    GLuint prog = fill->GetShaders()->Prog;
  28.786 +
  28.787 +	if (vao != NULL)
  28.788 +	{
  28.789 +		if (*vao != 0)
  28.790 +		{
  28.791 +            glBindVertexArray(*vao);
  28.792 +
  28.793 +			if (isDistortionMesh)
  28.794 +				glDrawElements(prim, count, GL_UNSIGNED_SHORT, NULL);
  28.795 +			else
  28.796 +				glDrawArrays(prim, 0, count);
  28.797 +
  28.798 +            glBindVertexArray(0);
  28.799 +		}
  28.800 +		else
  28.801 +		{
  28.802 +            if (GL_ARB_vertex_array_object)
  28.803 +            {
  28.804 +                glGenVertexArrays(1, vao);
  28.805 +                glBindVertexArray(*vao);
  28.806 +            }
  28.807 +
  28.808 +			int attributeCount = (isDistortionMesh) ? 5 : 1;
  28.809 +			int* locs = new int[attributeCount];
  28.810 +
  28.811 +			glBindBuffer(GL_ARRAY_BUFFER, ((Buffer*)vertices)->GLBuffer);
  28.812 +
  28.813 +			if (isDistortionMesh)
  28.814 +			{
  28.815 +				glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ((Buffer*)indices)->GLBuffer);
  28.816 +
  28.817 +				locs[0] = glGetAttribLocation(prog, "Position");
  28.818 +				locs[1] = glGetAttribLocation(prog, "Color");
  28.819 +				locs[2] = glGetAttribLocation(prog, "TexCoord0");
  28.820 +				locs[3] = glGetAttribLocation(prog, "TexCoord1");
  28.821 +				locs[4] = glGetAttribLocation(prog, "TexCoord2");
  28.822 +
  28.823 +				glVertexAttribPointer(locs[0], 2, GL_FLOAT, false, sizeof(DistortionVertex), reinterpret_cast<char*>(offset)+offsetof(DistortionVertex, ScreenPosNDC));
  28.824 +				glVertexAttribPointer(locs[1], 4, GL_UNSIGNED_BYTE, true, sizeof(DistortionVertex), reinterpret_cast<char*>(offset)+offsetof(DistortionVertex, Col));
  28.825 +				glVertexAttribPointer(locs[2], 2, GL_FLOAT, false, sizeof(DistortionVertex), reinterpret_cast<char*>(offset)+offsetof(DistortionVertex, TanEyeAnglesR));
  28.826 +				glVertexAttribPointer(locs[3], 2, GL_FLOAT, false, sizeof(DistortionVertex), reinterpret_cast<char*>(offset)+offsetof(DistortionVertex, TanEyeAnglesG));
  28.827 +				glVertexAttribPointer(locs[4], 2, GL_FLOAT, false, sizeof(DistortionVertex), reinterpret_cast<char*>(offset)+offsetof(DistortionVertex, TanEyeAnglesB));
  28.828 +			}
  28.829 +			else
  28.830 +			{
  28.831 +				locs[0] = glGetAttribLocation(prog, "Position");
  28.832 +
  28.833 +				glVertexAttribPointer(locs[0], 3, GL_FLOAT, false, sizeof(LatencyVertex), reinterpret_cast<char*>(offset)+offsetof(LatencyVertex, Pos));
  28.834 +			}
  28.835 +
  28.836 +            for (int i = 0; i < attributeCount; ++i)
  28.837 +                glEnableVertexAttribArray(locs[i]);
  28.838 +            
  28.839 +			if (isDistortionMesh)
  28.840 +				glDrawElements(prim, count, GL_UNSIGNED_SHORT, NULL);
  28.841 +			else
  28.842 +				glDrawArrays(prim, 0, count);
  28.843 +
  28.844 +
  28.845 +            if (!GL_ARB_vertex_array_object)
  28.846 +            {
  28.847 +				for (int i = 0; i < attributeCount; ++i)
  28.848 +                    glDisableVertexAttribArray(locs[i]);
  28.849 +            }
  28.850 +
  28.851 +			delete[] locs;
  28.852 +
  28.853 +            if (GL_ARB_vertex_array_object)
  28.854 +            {
  28.855 +                glBindVertexArray(0);
  28.856 +            }
  28.857 +		}
  28.858 +	}
  28.859 +}
  28.860 +
  28.861 +void DistortionRenderer::setViewport(const Recti& vp)
  28.862 +{
  28.863 +    glViewport(vp.x, vp.y, vp.w, vp.h);
  28.864 +}
  28.865 +
  28.866 +
  28.867 +void DistortionRenderer::initShaders()
  28.868 +{
  28.869 +    const char* shaderPrefix = (GLEContext::GetCurrentContext()->WholeVersion >= 302) ? glsl3Prefix : glsl2Prefix;
  28.870 +
  28.871 +    {
  28.872 +		ShaderInfo vsInfo = DistortionVertexShaderLookup[DistortionVertexShaderBitMask & RState.DistortionCaps];
  28.873 +
  28.874 +		size_t vsSize = strlen(shaderPrefix)+vsInfo.ShaderSize;
  28.875 +		char* vsSource = new char[vsSize];
  28.876 +		OVR_strcpy(vsSource, vsSize, shaderPrefix);
  28.877 +		OVR_strcat(vsSource, vsSize, vsInfo.ShaderData);
  28.878 +
  28.879 +        Ptr<GL::VertexShader> vs = *new GL::VertexShader(
  28.880 +            &RParams,
  28.881 +			(void*)vsSource, vsSize,
  28.882 +			vsInfo.ReflectionData, vsInfo.ReflectionSize);
  28.883 +
  28.884 +        DistortionShader = *new ShaderSet;
  28.885 +        DistortionShader->SetShader(vs);
  28.886 +
  28.887 +		delete[](vsSource);
  28.888 +
  28.889 +		ShaderInfo psInfo = DistortionPixelShaderLookup[DistortionPixelShaderBitMask & RState.DistortionCaps];
  28.890 +
  28.891 +		size_t psSize = strlen(shaderPrefix)+psInfo.ShaderSize;
  28.892 +		char* psSource = new char[psSize];
  28.893 +		OVR_strcpy(psSource, psSize, shaderPrefix);
  28.894 +		OVR_strcat(psSource, psSize, psInfo.ShaderData);
  28.895 +
  28.896 +        Ptr<GL::FragmentShader> ps  = *new GL::FragmentShader(
  28.897 +            &RParams,
  28.898 +			(void*)psSource, psSize,
  28.899 +			psInfo.ReflectionData, psInfo.ReflectionSize);
  28.900 +
  28.901 +        DistortionShader->SetShader(ps);
  28.902 +
  28.903 +		delete[](psSource);
  28.904 +    }
  28.905 +	{
  28.906 +		size_t vsSize = strlen(shaderPrefix)+sizeof(SimpleQuad_vs);
  28.907 +		char* vsSource = new char[vsSize];
  28.908 +		OVR_strcpy(vsSource, vsSize, shaderPrefix);
  28.909 +		OVR_strcat(vsSource, vsSize, SimpleQuad_vs);
  28.910 +
  28.911 +        Ptr<GL::VertexShader> vs = *new GL::VertexShader(
  28.912 +            &RParams,
  28.913 +            (void*)vsSource, vsSize,
  28.914 +			SimpleQuad_vs_refl, sizeof(SimpleQuad_vs_refl) / sizeof(SimpleQuad_vs_refl[0]));
  28.915 +
  28.916 +        SimpleQuadShader = *new ShaderSet;
  28.917 +		SimpleQuadShader->SetShader(vs);
  28.918 +
  28.919 +		delete[](vsSource);
  28.920 +
  28.921 +		size_t psSize = strlen(shaderPrefix)+sizeof(SimpleQuad_fs);
  28.922 +		char* psSource = new char[psSize];
  28.923 +		OVR_strcpy(psSource, psSize, shaderPrefix);
  28.924 +		OVR_strcat(psSource, psSize, SimpleQuad_fs);
  28.925 +
  28.926 +        Ptr<GL::FragmentShader> ps  = *new GL::FragmentShader(
  28.927 +            &RParams,
  28.928 +            (void*)psSource, psSize,
  28.929 +            SimpleQuad_fs_refl, sizeof(SimpleQuad_fs_refl) / sizeof(SimpleQuad_fs_refl[0]));
  28.930 +
  28.931 +		SimpleQuadShader->SetShader(ps);
  28.932 +
  28.933 +		delete[](psSource);
  28.934 +    }
  28.935 +    {
  28.936 +        size_t vsSize = strlen(shaderPrefix)+sizeof(SimpleQuad_vs);
  28.937 +        char* vsSource = new char[vsSize];
  28.938 +        OVR_strcpy(vsSource, vsSize, shaderPrefix);
  28.939 +        OVR_strcat(vsSource, vsSize, SimpleQuad_vs);
  28.940 +
  28.941 +        Ptr<GL::VertexShader> vs = *new GL::VertexShader(
  28.942 +            &RParams,
  28.943 +            (void*)vsSource, vsSize,
  28.944 +            SimpleQuad_vs_refl, sizeof(SimpleQuad_vs_refl) / sizeof(SimpleQuad_vs_refl[0]));
  28.945 +
  28.946 +        SimpleQuadGammaShader = *new ShaderSet;
  28.947 +        SimpleQuadGammaShader->SetShader(vs);
  28.948 +
  28.949 +        delete[](vsSource);
  28.950 +
  28.951 +        size_t psSize = strlen(shaderPrefix)+sizeof(SimpleQuadGamma_fs);
  28.952 +        char* psSource = new char[psSize];
  28.953 +        OVR_strcpy(psSource, psSize, shaderPrefix);
  28.954 +        OVR_strcat(psSource, psSize, SimpleQuadGamma_fs);
  28.955 +
  28.956 +        Ptr<GL::FragmentShader> ps  = *new GL::FragmentShader(
  28.957 +            &RParams,
  28.958 +            (void*)psSource, psSize,
  28.959 +            SimpleQuadGamma_fs_refl, sizeof(SimpleQuadGamma_fs_refl) / sizeof(SimpleQuadGamma_fs_refl[0]));
  28.960 +
  28.961 +        SimpleQuadGammaShader->SetShader(ps);
  28.962 +
  28.963 +        delete[](psSource);
  28.964 +    }
  28.965 +}
  28.966 +
  28.967 +
  28.968 +void DistortionRenderer::destroy()
  28.969 +{
  28.970 +    Context currContext;
  28.971 +    currContext.InitFromCurrent();
  28.972 +    
  28.973 +    distortionContext.Bind();
  28.974 +
  28.975 +	for(int eyeNum = 0; eyeNum < 2; eyeNum++)
  28.976 +	{
  28.977 +        if (GL_ARB_vertex_array_object)
  28.978 +        {
  28.979 +            glDeleteVertexArrays(1, &DistortionMeshVAOs[eyeNum]);
  28.980 +        }
  28.981 +
  28.982 +		DistortionMeshVAOs[eyeNum] = 0;
  28.983 +
  28.984 +		DistortionMeshVBs[eyeNum].Clear();
  28.985 +		DistortionMeshIBs[eyeNum].Clear();
  28.986 +	}
  28.987 +
  28.988 +	if (DistortionShader)
  28.989 +    {
  28.990 +        DistortionShader->UnsetShader(Shader_Vertex);
  28.991 +	    DistortionShader->UnsetShader(Shader_Pixel);
  28.992 +	    DistortionShader.Clear();
  28.993 +    }
  28.994 +
  28.995 +    LatencyTesterQuadVB.Clear();
  28.996 +
  28.997 +    if(LatencyVAO != 0)
  28.998 +    {
  28.999 +        glDeleteVertexArrays(1, &LatencyVAO);
 28.1000 +	    LatencyVAO = 0;
 28.1001 +    }
 28.1002 +
 28.1003 +    if(OverdriveFbo != 0)
 28.1004 +    {
 28.1005 +        glDeleteFramebuffers(1, &OverdriveFbo);
 28.1006 +    }
 28.1007 +
 28.1008 +    currContext.Bind();
 28.1009 +    distortionContext.Destroy();
 28.1010 +    // Who is responsible for destroying the app's context?
 28.1011 +}
 28.1012 +
 28.1013 +
 28.1014 +}}} // OVR::CAPI::GL
    29.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    29.2 +++ b/LibOVR/Src/CAPI/GL/CAPI_GL_DistortionRenderer.h	Wed Jan 14 06:51:16 2015 +0200
    29.3 @@ -0,0 +1,150 @@
    29.4 +/************************************************************************************
    29.5 +
    29.6 +Filename    :   CAPI_GL_DistortionRenderer.h
    29.7 +Content     :   Distortion renderer header for GL
    29.8 +Created     :   November 11, 2013
    29.9 +Authors     :   David Borel, Lee Cooper
   29.10 +
   29.11 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   29.12 +
   29.13 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License");
   29.14 +you may not use the Oculus VR Rift SDK except in compliance with the License,
   29.15 +which is provided at the time of installation or download, or which
   29.16 +otherwise accompanies this software in either electronic or hard copy form.
   29.17 +
   29.18 +You may obtain a copy of the License at
   29.19 +
   29.20 +http://www.oculusvr.com/licenses/LICENSE-3.2
   29.21 +
   29.22 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK
   29.23 +distributed under the License is distributed on an "AS IS" BASIS,
   29.24 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   29.25 +See the License for the specific language governing permissions and
   29.26 +limitations under the License.
   29.27 +
   29.28 +************************************************************************************/
   29.29 +
   29.30 +#ifndef OVR_CAPI_GL_DistortionRenderer_h
   29.31 +#define OVR_CAPI_GL_DistortionRenderer_h
   29.32 +
   29.33 +#include "../CAPI_DistortionRenderer.h"
   29.34 +
   29.35 +#include "../../Kernel/OVR_Log.h"
   29.36 +#include "CAPI_GL_Util.h"
   29.37 +
   29.38 +namespace OVR { namespace CAPI { namespace GL {
   29.39 +
   29.40 +// ***** GL::DistortionRenderer
   29.41 +
   29.42 +// Implementation of DistortionRenderer for GL.
   29.43 +
   29.44 +class DistortionRenderer : public CAPI::DistortionRenderer
   29.45 +{
   29.46 +public:    
   29.47 +    DistortionRenderer(ovrHmd hmd,
   29.48 +                       FrameTimeManager& timeManager,
   29.49 +                       const HMDRenderState& renderState);
   29.50 +    virtual ~DistortionRenderer();
   29.51 +
   29.52 +    
   29.53 +    // Creation function for the device.    
   29.54 +    static CAPI::DistortionRenderer* Create(ovrHmd hmd,
   29.55 +                                            FrameTimeManager& timeManager,
   29.56 +                                            const HMDRenderState& renderState);
   29.57 +
   29.58 +
   29.59 +    // ***** Public DistortionRenderer interface
   29.60 +	
   29.61 +    virtual bool Initialize(const ovrRenderAPIConfig* apiConfig) OVR_OVERRIDE;
   29.62 +
   29.63 +    virtual void SubmitEye(int eyeId, const ovrTexture* eyeTexture);
   29.64 +
   29.65 +    virtual void EndFrame(bool swapBuffers);
   29.66 +
   29.67 +    void         WaitUntilGpuIdle();
   29.68 +
   29.69 +	// Similar to ovr_WaitTillTime but it also flushes GPU.
   29.70 +	// Note, it exits when time expires, even if GPU is not in idle state yet.
   29.71 +	double       FlushGpuAndWaitTillTime(double absTime);
   29.72 +
   29.73 +protected:
   29.74 +
   29.75 +	struct FOR_EACH_EYE
   29.76 +	{
   29.77 +        FOR_EACH_EYE() : numVerts(0), numIndices(0), texture(0), /*UVScaleOffset[],*/ TextureSize(0, 0), RenderViewport(0, 0, 0, 0) { }
   29.78 +
   29.79 +		int                       numVerts;
   29.80 +		int                       numIndices;
   29.81 +
   29.82 +		GLuint                    texture;
   29.83 +
   29.84 +		ovrVector2f			 	  UVScaleOffset[2];
   29.85 +        Sizei                     TextureSize;
   29.86 +        Recti                     RenderViewport;
   29.87 +	} eachEye[2];
   29.88 +
   29.89 +    Ptr<Texture>    pOverdriveTextures[NumOverdriveTextures];
   29.90 +    Ptr<Texture>    OverdriveBackBufferTexture;
   29.91 +
   29.92 +    // GL context and utility variables.
   29.93 +    RenderParams        RParams;
   29.94 +    Context             distortionContext;  // We are currently using this private OpenGL context instead of using the CAPI SaveGraphicsState/RestoreGraphicsState mechanism. To consider: Move this Context into SaveGraphicsState/RestoreGraphicState so there's consistency between DirectX and OpenGL.
   29.95 +
   29.96 +	// Helpers
   29.97 +    void initOverdrive();
   29.98 +    void initBuffersAndShaders();
   29.99 +    void initShaders();
  29.100 +    void initFullscreenQuad();
  29.101 +    void destroy();
  29.102 +	
  29.103 +    void setViewport(const Recti& vp);
  29.104 +
  29.105 +    void renderDistortion(Texture* leftEyeTexture, Texture* rightEyeTexture);
  29.106 +
  29.107 +    void renderPrimitives(const ShaderFill* fill, Buffer* vertices, Buffer* indices,
  29.108 +                          int offset, int count,
  29.109 +						  PrimitiveType rprim, GLuint* vao, bool isDistortionMesh);
  29.110 +
  29.111 +	void createDrawQuad();
  29.112 +    void renderLatencyQuad(unsigned char* latencyTesterDrawColor);
  29.113 +    void renderLatencyPixel(unsigned char* latencyTesterPixelColor);
  29.114 +	
  29.115 +    void renderEndFrame();
  29.116 +
  29.117 +    Ptr<Texture>        pEyeTextures[2];
  29.118 +
  29.119 +	Ptr<Buffer>         DistortionMeshVBs[2];    // one per-eye
  29.120 +	Ptr<Buffer>         DistortionMeshIBs[2];    // one per-eye
  29.121 +	GLuint              DistortionMeshVAOs[2];   // one per-eye
  29.122 +
  29.123 +	Ptr<ShaderSet>      DistortionShader;
  29.124 +
  29.125 +    bool                RotateCCW90;
  29.126 +
  29.127 +    struct StandardUniformData
  29.128 +    {
  29.129 +        Matrix4f  Proj;
  29.130 +        Matrix4f  View;
  29.131 +    }                   StdUniforms;
  29.132 +	
  29.133 +	GLuint              LatencyVAO;
  29.134 +    Ptr<Buffer>         LatencyTesterQuadVB;
  29.135 +    Ptr<ShaderSet>      SimpleQuadShader;
  29.136 +    Ptr<ShaderSet>      SimpleQuadGammaShader;
  29.137 +
  29.138 +    GLuint              OverdriveFbo;
  29.139 +
  29.140 +	GLint SavedViewport[4];
  29.141 +	GLfloat SavedClearColor[4];
  29.142 +	GLint SavedDepthTest;
  29.143 +	GLint SavedCullFace;
  29.144 +	GLint SavedProgram;
  29.145 +	GLint SavedActiveTexture;
  29.146 +	GLint SavedBoundTexture;
  29.147 +	GLint SavedVertexArray;
  29.148 +    GLint SavedBoundFrameBuffer;
  29.149 +};
  29.150 +
  29.151 +}}} // OVR::CAPI::GL
  29.152 +
  29.153 +#endif // OVR_CAPI_GL_DistortionRenderer_h
    30.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    30.2 +++ b/LibOVR/Src/CAPI/GL/CAPI_GL_DistortionShaders.h	Wed Jan 14 06:51:16 2015 +0200
    30.3 @@ -0,0 +1,456 @@
    30.4 +/************************************************************************************
    30.5 + 
    30.6 + Filename    :   CAPI_GL_Shaders.h
    30.7 + Content     :   Distortion shader header for GL
    30.8 + Created     :   November 11, 2013
    30.9 + Authors     :   David Borel, Volga Aksoy
   30.10 + 
   30.11 + Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   30.12 +
   30.13 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
   30.14 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
   30.15 +which is provided at the time of installation or download, or which 
   30.16 +otherwise accompanies this software in either electronic or hard copy form.
   30.17 +
   30.18 +You may obtain a copy of the License at
   30.19 +
   30.20 +http://www.oculusvr.com/licenses/LICENSE-3.2 
   30.21 +
   30.22 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
   30.23 +distributed under the License is distributed on an "AS IS" BASIS,
   30.24 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   30.25 +See the License for the specific language governing permissions and
   30.26 +limitations under the License.
   30.27 + 
   30.28 + ************************************************************************************/
   30.29 +
   30.30 +
   30.31 +#ifndef OVR_CAPI_GL_Shaders_h
   30.32 +#define OVR_CAPI_GL_Shaders_h
   30.33 +
   30.34 +
   30.35 +#include "CAPI_GL_Util.h"
   30.36 +
   30.37 +namespace OVR { namespace CAPI { namespace GL {
   30.38 +    
   30.39 +    static const char glsl2Prefix[] =
   30.40 +    "#version 110\n"
   30.41 +    "#extension GL_ARB_shader_texture_lod : enable\n"
   30.42 +    "#extension GL_ARB_draw_buffers : enable\n"
   30.43 +    "#extension GL_EXT_gpu_shader4 : enable\n"
   30.44 +    "#define _FRAGCOLOR_DECLARATION\n"
   30.45 +    "#define _MRTFRAGCOLOR0_DECLARATION\n"
   30.46 +    "#define _MRTFRAGCOLOR1_DECLARATION\n"
   30.47 +    "#define _GLFRAGCOORD_DECLARATION\n"
   30.48 +    "#define _VS_IN attribute\n"
   30.49 +    "#define _VS_OUT varying\n"
   30.50 +    "#define _FS_IN varying\n"
   30.51 +    "#define _TEXTURELOD texture2DLod\n"
   30.52 +    "#define _TEXTURE texture2D\n"
   30.53 +    "#define _FRAGCOLOR gl_FragColor\n"
   30.54 +    "#define _MRTFRAGCOLOR0 gl_FragData[0]\n"
   30.55 +    "#define _MRTFRAGCOLOR1 gl_FragData[1]\n"       // The texture coordinate [0.0,1.0] for texel i of a texture of size N is: (2i + 1)/2N
   30.56 +    "#ifdef GL_EXT_gpu_shader4\n"
   30.57 +    "  #define _TEXELFETCHDECL vec4 texelFetch(sampler2D tex, ivec2 coord, int lod){ ivec2 size = textureSize2D(tex, lod); return texture2D(tex, vec2(float((coord.x * 2) + 1) / float(size.x * 2), float((coord.y * 2) + 1) / float(size.y * 2))); }\n"
   30.58 +    "#endif\n";
   30.59 +    
   30.60 +    static const char glsl3Prefix[] =
   30.61 +    "#version 150\n"
   30.62 +    "#define _FRAGCOLOR_DECLARATION out vec4 FragColor;\n"
   30.63 +    "#define _MRTFRAGCOLOR0_DECLARATION out vec4 FragData0;\n"
   30.64 +    "#define _MRTFRAGCOLOR1_DECLARATION out vec4 FragData1;\n"
   30.65 +    "#define _GLFRAGCOORD_DECLARATION in vec4 gl_FragCoord;\n"
   30.66 +    "#define _VS_IN in\n"
   30.67 +    "#define _VS_OUT out\n"
   30.68 +    "#define _FS_IN in\n"
   30.69 +    "#define _TEXTURELOD textureLod\n"
   30.70 +    "#define _TEXTURE texture\n"
   30.71 +    "#define _FRAGCOLOR FragColor\n"
   30.72 +    "#define _MRTFRAGCOLOR0 FragData0\n"
   30.73 +    "#define _MRTFRAGCOLOR1 FragData1\n"
   30.74 +    "#define _TEXELFETCHDECL\n";
   30.75 +    
   30.76 +    static const char SimpleQuad_vs[] =
   30.77 +    "uniform vec2 PositionOffset;\n"
   30.78 +    "uniform vec2 Scale;\n"
   30.79 +    
   30.80 +    "_VS_IN vec3 Position;\n"
   30.81 +    
   30.82 +	"void main()\n"
   30.83 +	"{\n"
   30.84 +	"	gl_Position = vec4(Position.xy * Scale + PositionOffset, 0.5, 1.0);\n"
   30.85 +	"}\n";
   30.86 +    
   30.87 +    const OVR::CAPI::GL::ShaderBase::Uniform SimpleQuad_vs_refl[] =
   30.88 +    {
   30.89 +        { "PositionOffset", OVR::CAPI::GL::ShaderBase::VARTYPE_FLOAT, 0, 8 },
   30.90 +        { "Scale",          OVR::CAPI::GL::ShaderBase::VARTYPE_FLOAT, 8, 8 },
   30.91 +    };
   30.92 +    
   30.93 +    static const char SimpleQuad_fs[] =
   30.94 +    "uniform vec4 Color;\n"
   30.95 +    
   30.96 +    "_FRAGCOLOR_DECLARATION\n"
   30.97 +    
   30.98 +	"void main()\n"
   30.99 +	"{\n"
  30.100 +	"    _FRAGCOLOR = Color;\n"
  30.101 +	"}\n";
  30.102 +    
  30.103 +    const OVR::CAPI::GL::ShaderBase::Uniform SimpleQuad_fs_refl[] =
  30.104 +    {
  30.105 +        { "Color", OVR::CAPI::GL::ShaderBase::VARTYPE_FLOAT, 0, 16 },
  30.106 +    };
  30.107 +
  30.108 +    static const char SimpleQuadGamma_fs[] =
  30.109 +        "uniform vec4 Color;\n"
  30.110 +
  30.111 +        "_FRAGCOLOR_DECLARATION\n"
  30.112 +
  30.113 +        "void main()\n"
  30.114 +        "{\n"
  30.115 +        "    _FRAGCOLOR.rgb = pow(Color.rgb, vec3(2.2));\n"
  30.116 +        "    _FRAGCOLOR.a = Color.a;\n"
  30.117 +        "}\n";
  30.118 +
  30.119 +    const OVR::CAPI::GL::ShaderBase::Uniform SimpleQuadGamma_fs_refl[] =
  30.120 +    {
  30.121 +        { "Color", OVR::CAPI::GL::ShaderBase::VARTYPE_FLOAT, 0, 16 },
  30.122 +    };
  30.123 +
  30.124 +    // This must be prefixed with glsl2Prefix or glsl3Prefix before being compiled.
  30.125 +    static const char SimpleTexturedQuad_vs[] =
  30.126 +        "uniform vec2 PositionOffset;\n"
  30.127 +        "uniform vec2 Scale;\n"
  30.128 +
  30.129 +        "_VS_IN vec3 Position;\n"
  30.130 +        "_VS_IN vec4 Color;\n"
  30.131 +        "_VS_IN vec2 TexCoord;\n"
  30.132 +  
  30.133 +        "_VS_OUT vec4 oColor;\n"
  30.134 +        "_VS_OUT vec2 oTexCoord;\n"
  30.135 +
  30.136 +        "void main()\n"
  30.137 +        "{\n"
  30.138 +	    "	gl_Position = vec4(Position.xy * Scale + PositionOffset, 0.5, 1.0);\n"
  30.139 +        "   oColor = Color;\n"
  30.140 +        "   oTexCoord = TexCoord;\n"
  30.141 +        "}\n";
  30.142 +
  30.143 +    // The following declaration is copied from the generated D3D SimpleTexturedQuad_vs_refl.h file, with D3D_NS renamed to GL.
  30.144 +    const OVR::CAPI::GL::ShaderBase::Uniform SimpleTexturedQuad_vs_refl[] =
  30.145 +    {
  30.146 +	    { "PositionOffset", OVR::CAPI::GL::ShaderBase::VARTYPE_FLOAT, 0, 8 },
  30.147 +	    { "Scale",          OVR::CAPI::GL::ShaderBase::VARTYPE_FLOAT, 8, 8 },
  30.148 +    };
  30.149 +
  30.150 +
  30.151 +    // This must be prefixed with glsl2Prefix or glsl3Prefix before being compiled.
  30.152 +    static const char SimpleTexturedQuad_ps[] =
  30.153 +        "uniform sampler2D Texture0;\n"
  30.154 +    
  30.155 +        "_FS_IN vec4 oColor;\n"
  30.156 +        "_FS_IN vec2 oTexCoord;\n"
  30.157 +    
  30.158 +        "_FRAGCOLOR_DECLARATION\n"
  30.159 +
  30.160 +        "void main()\n"
  30.161 +        "{\n"
  30.162 +        "   _FRAGCOLOR = oColor * _TEXTURE(Texture0, oTexCoord);\n"
  30.163 +        "}\n";
  30.164 +
  30.165 +    // The following is copied from the generated D3D SimpleTexturedQuad_ps_refl.h file, with D3D_NS renamed to GL.
  30.166 +    const OVR::CAPI::GL::ShaderBase::Uniform SimpleTexturedQuad_ps_refl[] =
  30.167 +    {
  30.168 +	    { "Color", 	OVR::CAPI::GL::ShaderBase::VARTYPE_FLOAT, 0, 16 },
  30.169 +    };
  30.170 +
  30.171 +    
  30.172 +    static const char Distortion_vs[] =
  30.173 +    "uniform vec2 EyeToSourceUVScale;\n"
  30.174 +    "uniform vec2 EyeToSourceUVOffset;\n"
  30.175 +    
  30.176 +    "_VS_IN vec2 Position;\n"
  30.177 +    "_VS_IN vec4 Color;\n"
  30.178 +    "_VS_IN vec2 TexCoord0;\n"
  30.179 +    
  30.180 +    "_VS_OUT vec4 oColor;\n"
  30.181 +    "_VS_OUT vec2 oTexCoord0;\n"
  30.182 +    
  30.183 +    "void main()\n"
  30.184 +    "{\n"
  30.185 +    "   gl_Position.x = Position.x;\n"
  30.186 +    "   gl_Position.y = Position.y;\n"
  30.187 +    "   gl_Position.z = 0.5;\n"
  30.188 +    "   gl_Position.w = 1.0;\n"
  30.189 +    // Vertex inputs are in TanEyeAngle space for the R,G,B channels (i.e. after chromatic aberration and distortion).
  30.190 +    // Scale them into the correct [0-1],[0-1] UV lookup space (depending on eye)
  30.191 +    "   oTexCoord0 = TexCoord0 * EyeToSourceUVScale + EyeToSourceUVOffset;\n"
  30.192 +    "   oColor = Color;\n"              // Used for vignette fade.
  30.193 +    "}\n";
  30.194 +    
  30.195 +    const OVR::CAPI::GL::ShaderBase::Uniform Distortion_vs_refl[] =
  30.196 +    {
  30.197 +        { "EyeToSourceUVScale",  OVR::CAPI::GL::ShaderBase::VARTYPE_FLOAT, 0, 8 },
  30.198 +        { "EyeToSourceUVOffset", OVR::CAPI::GL::ShaderBase::VARTYPE_FLOAT, 8, 8 },
  30.199 +    };
  30.200 +    
  30.201 +    static const char Distortion_fs[] =
  30.202 +    "uniform sampler2D Texture0;\n"
  30.203 +    
  30.204 +    "_FS_IN vec4 oColor;\n"
  30.205 +    "_FS_IN vec2 oTexCoord0;\n"
  30.206 +    
  30.207 +    "_FRAGCOLOR_DECLARATION\n"
  30.208 +    
  30.209 +    "void main()\n"
  30.210 +    "{\n"
  30.211 +    "   _FRAGCOLOR = _TEXTURE(Texture0, oTexCoord0, 0.0);\n"
  30.212 +    "   _FRAGCOLOR.a = 1.0;\n"
  30.213 +    "}\n";
  30.214 +    
  30.215 +    
  30.216 +    static const char DistortionTimewarp_vs[] =
  30.217 +    "uniform vec2 EyeToSourceUVScale;\n"
  30.218 +    "uniform vec2 EyeToSourceUVOffset;\n"
  30.219 +    "uniform mat4 EyeRotationStart;\n"
  30.220 +    "uniform mat4 EyeRotationEnd;\n"
  30.221 +    
  30.222 +    "_VS_IN vec2 Position;\n"
  30.223 +    "_VS_IN vec4 Color;\n"
  30.224 +    "_VS_IN vec2 TexCoord0;\n"
  30.225 +    
  30.226 +    "_VS_OUT vec4 oColor;\n"
  30.227 +    "_VS_OUT vec2 oTexCoord0;\n"
  30.228 +    
  30.229 +    "void main()\n"
  30.230 +    "{\n"
  30.231 +    "   gl_Position.x = Position.x;\n"
  30.232 +    "   gl_Position.y = Position.y;\n"
  30.233 +    "   gl_Position.z = 0.0;\n"
  30.234 +    "   gl_Position.w = 1.0;\n"
  30.235 +    
  30.236 +    // Vertex inputs are in TanEyeAngle space for the R,G,B channels (i.e. after chromatic aberration and distortion).
  30.237 +    // These are now "real world" vectors in direction (x,y,1) relative to the eye of the HMD.
  30.238 +    "   vec3 TanEyeAngle = vec3 ( TexCoord0.x, TexCoord0.y, 1.0 );\n"
  30.239 +    
  30.240 +    // Accurate time warp lerp vs. faster
  30.241 +#if 1
  30.242 +    // Apply the two 3x3 timewarp rotations to these vectors.
  30.243 +	"   vec3 TransformedStart = (EyeRotationStart * vec4(TanEyeAngle, 0)).xyz;\n"
  30.244 +	"   vec3 TransformedEnd   = (EyeRotationEnd * vec4(TanEyeAngle, 0)).xyz;\n"
  30.245 +    // And blend between them.
  30.246 +    "   vec3 Transformed = mix ( TransformedStart, TransformedEnd, Color.a );\n"
  30.247 +#else
  30.248 +    "   mat4 EyeRotation = mix ( EyeRotationStart, EyeRotationEnd, Color.a );\n"
  30.249 +    "   vec3 Transformed   = EyeRotation * TanEyeAngle;\n"
  30.250 +#endif
  30.251 +    
  30.252 +    // Project them back onto the Z=1 plane of the rendered images.
  30.253 +    "   float RecipZ = 1.0 / Transformed.z;\n"
  30.254 +    "   vec2 Flattened = vec2 ( Transformed.x * RecipZ, Transformed.y * RecipZ );\n"
  30.255 +    
  30.256 +    // These are now still in TanEyeAngle space.
  30.257 +    // Scale them into the correct [0-1],[0-1] UV lookup space (depending on eye)
  30.258 +    "   vec2 SrcCoord = Flattened * EyeToSourceUVScale + EyeToSourceUVOffset;\n"
  30.259 +    "   oTexCoord0 = SrcCoord;\n"
  30.260 +    "   oColor = vec4(Color.r, Color.r, Color.r, Color.r);\n"              // Used for vignette fade.
  30.261 +    "}\n";
  30.262 +
  30.263 +    
  30.264 +    const OVR::CAPI::GL::ShaderBase::Uniform DistortionTimewarp_vs_refl[] =
  30.265 +    {
  30.266 +        { "EyeToSourceUVScale",  OVR::CAPI::GL::ShaderBase::VARTYPE_FLOAT, 0, 8 },
  30.267 +        { "EyeToSourceUVOffset", OVR::CAPI::GL::ShaderBase::VARTYPE_FLOAT, 8, 8 },
  30.268 +    };
  30.269 +    
  30.270 +    static const char DistortionChroma_vs[] =
  30.271 +    "uniform vec2 EyeToSourceUVScale;\n"
  30.272 +    "uniform vec2 EyeToSourceUVOffset;\n"
  30.273 +    
  30.274 +    "_VS_IN vec2 Position;\n"
  30.275 +    "_VS_IN vec4 Color;\n"
  30.276 +    "_VS_IN vec2 TexCoord0;\n"
  30.277 +    "_VS_IN vec2 TexCoord1;\n"
  30.278 +    "_VS_IN vec2 TexCoord2;\n"
  30.279 +    
  30.280 +    "_VS_OUT vec4 oColor;\n"
  30.281 +    "_VS_OUT vec2 oTexCoord0;\n"
  30.282 +    "_VS_OUT vec2 oTexCoord1;\n"
  30.283 +    "_VS_OUT vec2 oTexCoord2;\n"
  30.284 +    
  30.285 +    "void main()\n"
  30.286 +    "{\n"
  30.287 +    "   gl_Position.x = Position.x;\n"
  30.288 +    "   gl_Position.y = Position.y;\n"
  30.289 +    "   gl_Position.z = 0.5;\n"
  30.290 +    "   gl_Position.w = 1.0;\n"
  30.291 +    
  30.292 +    // Vertex inputs are in TanEyeAngle space for the R,G,B channels (i.e. after chromatic aberration and distortion).
  30.293 +    // Scale them into the correct [0-1],[0-1] UV lookup space (depending on eye)
  30.294 +    "   oTexCoord0 = TexCoord0 * EyeToSourceUVScale + EyeToSourceUVOffset;\n"
  30.295 +    "   oTexCoord1 = TexCoord1 * EyeToSourceUVScale + EyeToSourceUVOffset;\n"
  30.296 +    "   oTexCoord2 = TexCoord2 * EyeToSourceUVScale + EyeToSourceUVOffset;\n"
  30.297 +    
  30.298 +    "   oColor = Color;\n" // Used for vignette fade.
  30.299 +    "}\n";
  30.300 +    
  30.301 +    const OVR::CAPI::GL::ShaderBase::Uniform DistortionChroma_vs_refl[] =
  30.302 +    {
  30.303 +        { "EyeToSourceUVScale",  OVR::CAPI::GL::ShaderBase::VARTYPE_FLOAT, 0, 8 },
  30.304 +        { "EyeToSourceUVOffset", OVR::CAPI::GL::ShaderBase::VARTYPE_FLOAT, 8, 8 },
  30.305 +    };
  30.306 +    
  30.307 +    static const char DistortionChroma_fs[] =
  30.308 +    "uniform sampler2D Texture0;\n"
  30.309 +    "uniform sampler2D Texture1;\n"
  30.310 +    "uniform vec3 OverdriveScales_IsSrgb;\n"
  30.311 +
  30.312 +    "_FS_IN vec4 oColor;\n"
  30.313 +    "_FS_IN vec2 oTexCoord0;\n"
  30.314 +    "_FS_IN vec2 oTexCoord1;\n"
  30.315 +    "_FS_IN vec2 oTexCoord2;\n"
  30.316 +    
  30.317 +    "_MRTFRAGCOLOR0_DECLARATION\n"   // Desired color (next frame's "PrevTexture")
  30.318 +    "_MRTFRAGCOLOR1_DECLARATION\n"   // Overdriven color (Back-buffer)
  30.319 +    "_GLFRAGCOORD_DECLARATION\n"
  30.320 +
  30.321 +    "#ifdef _TEXELFETCHDECL\n"
  30.322 +    "_TEXELFETCHDECL\n"
  30.323 +    "#endif\n"
  30.324 +    
  30.325 +    "void main()\n"
  30.326 +    "{\n"
  30.327 +    "   float ResultR = _TEXTURE(Texture0, oTexCoord0, 0.0).r;\n"
  30.328 +    "   float ResultG = _TEXTURE(Texture0, oTexCoord1, 0.0).g;\n"
  30.329 +    "   float ResultB = _TEXTURE(Texture0, oTexCoord2, 0.0).b;\n"
  30.330 +    "   vec3 newColor = vec3(ResultR * oColor.r, ResultG * oColor.g, ResultB * oColor.b);\n"
  30.331 +
  30.332 +    "   _MRTFRAGCOLOR0 = vec4(newColor, 1);\n"
  30.333 +    "   _MRTFRAGCOLOR1 = _MRTFRAGCOLOR0;\n"
  30.334 +
  30.335 +    "   #ifdef _TEXELFETCHDECL\n"
  30.336 +    // pixel luminance overdrive
  30.337 +    "   if(OverdriveScales_IsSrgb.x > 0.0)\n"
  30.338 +    "   {\n"
  30.339 +    "       ivec2 pixelCoord = ivec2(gl_FragCoord.x, gl_FragCoord.y);\n"
  30.340 +    "       vec3 oldColor = texelFetch(Texture1, pixelCoord, 0).rgb;\n"
  30.341 +
  30.342 +    "       vec3 adjustedScales;\n"
  30.343 +    "       adjustedScales.x = newColor.x > oldColor.x ? OverdriveScales_IsSrgb.x : OverdriveScales_IsSrgb.y;\n"
  30.344 +    "       adjustedScales.y = newColor.y > oldColor.y ? OverdriveScales_IsSrgb.x : OverdriveScales_IsSrgb.y;\n"
  30.345 +    "       adjustedScales.z = newColor.z > oldColor.z ? OverdriveScales_IsSrgb.x : OverdriveScales_IsSrgb.y;\n"
  30.346 +
  30.347 +	// overdrive is tuned for gamma space so if we're in linear space fix gamma before doing the calculation
  30.348 +	"		vec3 overdriveColor;\n"
  30.349 +	"       if(OverdriveScales_IsSrgb.z > 0.0)\n"
  30.350 +	"		{\n"
  30.351 +	"           oldColor = pow(oldColor, vec3(1.0/2.2, 1.0/2.2, 1.0/2.2));\n"
  30.352 +	"			newColor = pow(newColor, vec3(1.0/2.2, 1.0/2.2, 1.0/2.2));\n"
  30.353 +    "			overdriveColor = clamp(newColor + (newColor - oldColor) * adjustedScales, 0.0, 1.0);\n"
  30.354 +    "           overdriveColor = pow(overdriveColor, vec3(2.2, 2.2, 2.2));\n"
  30.355 +	"		}\n"
  30.356 +	"		else\n"
  30.357 +	"			overdriveColor = clamp(newColor + (newColor - oldColor) * adjustedScales, 0.0, 1.0);\n"
  30.358 +
  30.359 +    "       _MRTFRAGCOLOR1 = vec4(overdriveColor, 1.0);\n"
  30.360 +    "   }\n"
  30.361 +    "   #else\n"
  30.362 +    // If statement to keep OverdriveScales_IsSrgb from being optimized out.
  30.363 +    "   if(OverdriveScales_IsSrgb.x > 0.0)\n"
  30.364 +    "     _MRTFRAGCOLOR1 = vec4(newColor, 1);\n"
  30.365 +    "   #endif\n"
  30.366 +    "}\n";
  30.367 +
  30.368 +    const OVR::CAPI::GL::ShaderBase::Uniform DistortionChroma_ps_refl[] =
  30.369 +    {
  30.370 +        { "OverdriveScales_IsSrgb", OVR::CAPI::GL::ShaderBase::VARTYPE_FLOAT, 0, 12 },
  30.371 +    };
  30.372 +    
  30.373 +    static const char DistortionTimewarpChroma_vs[] =
  30.374 +    "uniform vec2 EyeToSourceUVScale;\n"
  30.375 +    "uniform vec2 EyeToSourceUVOffset;\n"
  30.376 +    "uniform mat4 EyeRotationStart;\n"
  30.377 +    "uniform mat4 EyeRotationEnd;\n"
  30.378 +    
  30.379 +    "_VS_IN vec2 Position;\n"
  30.380 +    "_VS_IN vec4 Color;\n"
  30.381 +    "_VS_IN vec2 TexCoord0;\n"
  30.382 +    "_VS_IN vec2 TexCoord1;\n"
  30.383 +    "_VS_IN vec2 TexCoord2;\n"
  30.384 +    
  30.385 +    "_VS_OUT vec4 oColor;\n"
  30.386 +    "_VS_OUT vec2 oTexCoord0;\n"
  30.387 +    "_VS_OUT vec2 oTexCoord1;\n"
  30.388 +    "_VS_OUT vec2 oTexCoord2;\n"
  30.389 +    
  30.390 +    "void main()\n"
  30.391 +    "{\n"
  30.392 +    "   gl_Position.x = Position.x;\n"
  30.393 +    "   gl_Position.y = Position.y;\n"
  30.394 +    "   gl_Position.z = 0.0;\n"
  30.395 +    "   gl_Position.w = 1.0;\n"
  30.396 +    
  30.397 +    // Vertex inputs are in TanEyeAngle space for the R,G,B channels (i.e. after chromatic aberration and distortion).
  30.398 +    // These are now "real world" vectors in direction (x,y,1) relative to the eye of the HMD.
  30.399 +    "   vec3 TanEyeAngleR = vec3 ( TexCoord0.x, TexCoord0.y, 1.0 );\n"
  30.400 +    "   vec3 TanEyeAngleG = vec3 ( TexCoord1.x, TexCoord1.y, 1.0 );\n"
  30.401 +    "   vec3 TanEyeAngleB = vec3 ( TexCoord2.x, TexCoord2.y, 1.0 );\n"
  30.402 +    
  30.403 +    // Accurate time warp lerp vs. faster
  30.404 +#if 1
  30.405 +    // Apply the two 3x3 timewarp rotations to these vectors.
  30.406 +	"   vec3 TransformedRStart = (EyeRotationStart * vec4(TanEyeAngleR, 0)).xyz;\n"
  30.407 +	"   vec3 TransformedGStart = (EyeRotationStart * vec4(TanEyeAngleG, 0)).xyz;\n"
  30.408 +	"   vec3 TransformedBStart = (EyeRotationStart * vec4(TanEyeAngleB, 0)).xyz;\n"
  30.409 +	"   vec3 TransformedREnd   = (EyeRotationEnd * vec4(TanEyeAngleR, 0)).xyz;\n"
  30.410 +	"   vec3 TransformedGEnd   = (EyeRotationEnd * vec4(TanEyeAngleG, 0)).xyz;\n"
  30.411 +	"   vec3 TransformedBEnd   = (EyeRotationEnd * vec4(TanEyeAngleB, 0)).xyz;\n"
  30.412 +    
  30.413 +    // And blend between them.
  30.414 +    "   vec3 TransformedR = mix ( TransformedRStart, TransformedREnd, Color.a );\n"
  30.415 +    "   vec3 TransformedG = mix ( TransformedGStart, TransformedGEnd, Color.a );\n"
  30.416 +    "   vec3 TransformedB = mix ( TransformedBStart, TransformedBEnd, Color.a );\n"
  30.417 +#else
  30.418 +    "   mat3 EyeRotation;\n"
  30.419 +    "   EyeRotation[0] = mix ( EyeRotationStart[0], EyeRotationEnd[0], Color.a ).xyz;\n"
  30.420 +    "   EyeRotation[1] = mix ( EyeRotationStart[1], EyeRotationEnd[1], Color.a ).xyz;\n"
  30.421 +    "   EyeRotation[2] = mix ( EyeRotationStart[2], EyeRotationEnd[2], Color.a ).xyz;\n"
  30.422 +    "   vec3 TransformedR   = EyeRotation * TanEyeAngleR;\n"
  30.423 +    "   vec3 TransformedG   = EyeRotation * TanEyeAngleG;\n"
  30.424 +    "   vec3 TransformedB   = EyeRotation * TanEyeAngleB;\n"
  30.425 +#endif
  30.426 +    
  30.427 +    // Project them back onto the Z=1 plane of the rendered images.
  30.428 +    "   float RecipZR = 1.0 / TransformedR.z;\n"
  30.429 +    "   float RecipZG = 1.0 / TransformedG.z;\n"
  30.430 +    "   float RecipZB = 1.0 / TransformedB.z;\n"
  30.431 +    "   vec2 FlattenedR = vec2 ( TransformedR.x * RecipZR, TransformedR.y * RecipZR );\n"
  30.432 +    "   vec2 FlattenedG = vec2 ( TransformedG.x * RecipZG, TransformedG.y * RecipZG );\n"
  30.433 +    "   vec2 FlattenedB = vec2 ( TransformedB.x * RecipZB, TransformedB.y * RecipZB );\n"
  30.434 +    
  30.435 +    // These are now still in TanEyeAngle space.
  30.436 +    // Scale them into the correct [0-1],[0-1] UV lookup space (depending on eye)
  30.437 +    "   vec2 SrcCoordR = FlattenedR * EyeToSourceUVScale + EyeToSourceUVOffset;\n"
  30.438 +    "   vec2 SrcCoordG = FlattenedG * EyeToSourceUVScale + EyeToSourceUVOffset;\n"
  30.439 +    "   vec2 SrcCoordB = FlattenedB * EyeToSourceUVScale + EyeToSourceUVOffset;\n"
  30.440 +    
  30.441 +    "   oTexCoord0 = SrcCoordR;\n"
  30.442 +    "   oTexCoord1 = SrcCoordG;\n"
  30.443 +    "   oTexCoord2 = SrcCoordB;\n"
  30.444 +    
  30.445 +    "   oColor = vec4(Color.r, Color.r, Color.r, Color.r);\n"              // Used for vignette fade.
  30.446 +    "}\n";
  30.447 +    
  30.448 +
  30.449 +    const OVR::CAPI::GL::ShaderBase::Uniform DistortionTimewarpChroma_vs_refl[] =
  30.450 +    {
  30.451 +        { "EyeToSourceUVScale",  OVR::CAPI::GL::ShaderBase::VARTYPE_FLOAT, 0, 8 },
  30.452 +        { "EyeToSourceUVOffset", OVR::CAPI::GL::ShaderBase::VARTYPE_FLOAT, 8, 8 },
  30.453 +        { "EyeRotationStart",    OVR::CAPI::GL::ShaderBase::VARTYPE_FLOAT, 16, 64 },
  30.454 +        { "EyeRotationEnd",      OVR::CAPI::GL::ShaderBase::VARTYPE_FLOAT, 80, 64 },
  30.455 +    };
  30.456 +    
  30.457 +}}} // OVR::CAPI::GL
  30.458 +
  30.459 +#endif // OVR_CAPI_GL_Shaders_h
    31.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    31.2 +++ b/LibOVR/Src/CAPI/GL/CAPI_GL_HSWDisplay.cpp	Wed Jan 14 06:51:16 2015 +0200
    31.3 @@ -0,0 +1,500 @@
    31.4 +/************************************************************************************
    31.5 +
    31.6 +Filename    :   CAPI_GL_HSWDisplay.cpp
    31.7 +Content     :   Implements Health and Safety Warning system.
    31.8 +Created     :   July 7, 2014
    31.9 +Authors     :   Paul Pedriana
   31.10 +
   31.11 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   31.12 +
   31.13 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
   31.14 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
   31.15 +which is provided at the time of installation or download, or which 
   31.16 +otherwise accompanies this software in either electronic or hard copy form.
   31.17 +
   31.18 +You may obtain a copy of the License at
   31.19 +
   31.20 +http://www.oculusvr.com/licenses/LICENSE-3.2 
   31.21 +
   31.22 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
   31.23 +distributed under the License is distributed on an "AS IS" BASIS,
   31.24 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   31.25 +See the License for the specific language governing permissions and
   31.26 +limitations under the License.
   31.27 +
   31.28 +************************************************************************************/
   31.29 +
   31.30 +
   31.31 +#include "CAPI_GL_HSWDisplay.h"
   31.32 +#include "CAPI_GL_DistortionShaders.h"
   31.33 +#include "../../OVR_CAPI_GL.h"
   31.34 +#include "../../Kernel/OVR_File.h"
   31.35 +#include "../../Kernel/OVR_Math.h"
   31.36 +#include "../../Kernel/OVR_Allocator.h"
   31.37 +#include "../../Kernel/OVR_Color.h"
   31.38 +
   31.39 +
   31.40 +OVR_DISABLE_MSVC_WARNING(4996) // "This function or variable may be unsafe..."
   31.41 +
   31.42 +
   31.43 +namespace OVR { namespace CAPI { 
   31.44 +
   31.45 +
   31.46 +// Loads the TGA data from the File as an array of width * height 32 bit Texture_RGBA values.
   31.47 +// Returned pointer must be freed with OVR_FREE.
   31.48 +uint8_t* LoadTextureTgaData(OVR::File* f, uint8_t alpha, int& width, int& height)
   31.49 +{
   31.50 +    // See http://www.fileformat.info/format/tga/egff.htm for format details.
   31.51 +    // TGA files are stored with little-endian data.
   31.52 +    uint8_t* pRGBA  = NULL;
   31.53 +
   31.54 +    f->SeekToBegin();
   31.55 +    
   31.56 +    const int desclen = f->ReadUByte();
   31.57 +    const int palette = f->ReadUByte();
   31.58 +    OVR_UNUSED(palette);
   31.59 +    const int imgtype = f->ReadUByte();
   31.60 +    f->ReadUInt16(); // Skip bytes
   31.61 +    int palCount = f->ReadUInt16();
   31.62 +    int palSize = f->ReadUByte();
   31.63 +    f->ReadUInt16();
   31.64 +    f->ReadUInt16();
   31.65 +    width = f->ReadUInt16();
   31.66 +    height = f->ReadUInt16();
   31.67 +    int bpp = f->ReadUByte();
   31.68 +    f->ReadUByte();
   31.69 +
   31.70 +    const int ImgTypeBGRAUncompressed = 2;
   31.71 +    const int ImgTypeBGRARLECompressed = 10;
   31.72 +
   31.73 +    OVR_ASSERT(((imgtype == ImgTypeBGRAUncompressed) || (imgtype == ImgTypeBGRARLECompressed)) && ((bpp == 24) || (bpp == 32)));
   31.74 +
   31.75 +    // imgType 2 is uncompressed true-color image.
   31.76 +    // imgType 10 is run-length encoded true-color image.
   31.77 +    if(((imgtype == ImgTypeBGRAUncompressed) || (imgtype == ImgTypeBGRARLECompressed)) && ((bpp == 24) || (bpp == 32)))
   31.78 +    {
   31.79 +        int imgsize = width * height * 4;
   31.80 +        pRGBA = (uint8_t*) OVR_ALLOC(imgsize);
   31.81 +        f->Skip(desclen);
   31.82 +        f->Skip(palCount * (palSize + 7) >> 3);
   31.83 +        int strideBytes = width * 4; // This is the number of bytes between successive rows.
   31.84 +
   31.85 +        unsigned char buf[4] = { 0, 0, 0, alpha }; // If bpp is 24 then this alpha will be unmodified below.
   31.86 +
   31.87 +        switch (imgtype)
   31.88 +        {
   31.89 +        case ImgTypeBGRAUncompressed:
   31.90 +            switch (bpp)
   31.91 +            {
   31.92 +            case 24:
   31.93 +            case 32:
   31.94 +                for (int y = 0; y < height; y++)
   31.95 +                {
   31.96 +                    for (int x = 0; x < width; x++)
   31.97 +                    {
   31.98 +                        f->Read(buf, bpp / 8); // Data is stored as B, G, R
   31.99 +                        pRGBA[y*strideBytes + x*4 + 0] = buf[2];
  31.100 +                        pRGBA[y*strideBytes + x*4 + 1] = buf[1];
  31.101 +                        pRGBA[y*strideBytes + x*4 + 2] = buf[0];
  31.102 +                        pRGBA[y*strideBytes + x*4 + 3] = buf[3];
  31.103 +                    }
  31.104 +                }
  31.105 +                break;
  31.106 +            }
  31.107 +            break;
  31.108 +
  31.109 +        case ImgTypeBGRARLECompressed:
  31.110 +            switch (bpp)
  31.111 +            {
  31.112 +            case 24:
  31.113 +            case 32:
  31.114 +                for (int y = 0; y < height; y++) // RLE spans don't cross successive rows.
  31.115 +                {
  31.116 +                    int x = 0;
  31.117 +
  31.118 +                    while(x < width)
  31.119 +                    {
  31.120 +                        uint8_t rleByte;
  31.121 +                        f->Read(&rleByte, 1);
  31.122 +
  31.123 +                        if(rleByte & 0x80) // If the high byte is set then what follows are RLE bytes.
  31.124 +                        {
  31.125 +                            size_t rleCount = ((rleByte & 0x7f) + 1);
  31.126 +                            f->Read(buf, bpp / 8); // Data is stored as B, G, R, A
  31.127 +
  31.128 +                            for (; rleCount; --rleCount, ++x)
  31.129 +                            {
  31.130 +                                pRGBA[y*strideBytes + x*4 + 0] = buf[2];
  31.131 +                                pRGBA[y*strideBytes + x*4 + 1] = buf[1];
  31.132 +                                pRGBA[y*strideBytes + x*4 + 2] = buf[0];
  31.133 +                                pRGBA[y*strideBytes + x*4 + 3] = buf[3];
  31.134 +                            }   
  31.135 +                        }
  31.136 +                        else // Else what follows are regular bytes of a count indicated by rleByte
  31.137 +                        {
  31.138 +                            for (size_t rleCount = (rleByte + 1); rleCount; --rleCount, ++x)
  31.139 +                            {
  31.140 +                                f->Read(buf, bpp / 8); // Data is stored as B, G, R, A
  31.141 +                                pRGBA[y*strideBytes + x*4 + 0] = buf[2];
  31.142 +                                pRGBA[y*strideBytes + x*4 + 1] = buf[1];
  31.143 +                                pRGBA[y*strideBytes + x*4 + 2] = buf[0];
  31.144 +                                pRGBA[y*strideBytes + x*4 + 3] = buf[3];
  31.145 +                            }
  31.146 +                        }
  31.147 +                    }
  31.148 +                }
  31.149 +                break;
  31.150 +            }
  31.151 +            break;
  31.152 +        }
  31.153 +    }
  31.154 +
  31.155 +    return pRGBA;
  31.156 +} // LoadTextureTgaData
  31.157 +
  31.158 +
  31.159 +
  31.160 +namespace GL {
  31.161 +
  31.162 +
  31.163 +// To do: This needs to be promoted to a central version, possibly in CAPI_HSWDisplay.h
  31.164 +struct HASWVertex
  31.165 +{
  31.166 +    Vector3f  Pos;
  31.167 +    Color     C;
  31.168 +    float     U, V;    
  31.169 +
  31.170 +    HASWVertex(const Vector3f& p, const Color& c = Color(64,0,0,255), float u = 0, float v = 0)
  31.171 +        : Pos(p), C(c), U(u), V(v)
  31.172 +    {}
  31.173 +
  31.174 +    HASWVertex(float x, float y, float z, const Color& c = Color(64,0,0,255), float u = 0, float v = 0) 
  31.175 +        : Pos(x,y,z), C(c), U(u), V(v)
  31.176 +    {}
  31.177 +
  31.178 +    bool operator==(const HASWVertex& b) const
  31.179 +    {
  31.180 +        return (Pos == b.Pos) && (C == b.C) && (U == b.U) && (V == b.V);
  31.181 +    }
  31.182 +};
  31.183 +
  31.184 +
  31.185 +
  31.186 +// This is a temporary function implementation, and it functionality needs to be implemented in a more generic way.
  31.187 +Texture* LoadTextureTga(RenderParams& rParams, int samplerMode, OVR::File* f, uint8_t alpha)
  31.188 +{
  31.189 +    OVR::CAPI::GL::Texture* pTexture = NULL;
  31.190 +
  31.191 +    int width, height;
  31.192 +    const uint8_t* pRGBA = LoadTextureTgaData(f, alpha, width, height);
  31.193 +
  31.194 +    if (pRGBA)
  31.195 +    {
  31.196 +        pTexture = new OVR::CAPI::GL::Texture(&rParams, width, height);
  31.197 +
  31.198 +        // SetSampleMode forces the use of mipmaps through GL_LINEAR_MIPMAP_LINEAR.
  31.199 +        pTexture->SetSampleMode(samplerMode); // Calls glBindTexture internally.
  31.200 +
  31.201 +        // We are intentionally not using mipmaps. We need to use this because Texture::SetSampleMode unilaterally uses GL_LINEAR_MIPMAP_LINEAR.
  31.202 +        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
  31.203 +        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
  31.204 +        OVR_ASSERT(glGetError() == 0);
  31.205 +
  31.206 +        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pRGBA);
  31.207 +        OVR_ASSERT(glGetError() == 0);
  31.208 +
  31.209 +        // With OpenGL 4.2+ we can use this instead of glTexImage2D:
  31.210 +        // glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, width, height);
  31.211 +        // glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pRGBA);
  31.212 +
  31.213 +        OVR_FREE(const_cast<uint8_t*>(pRGBA));
  31.214 +    }
  31.215 +
  31.216 +    return pTexture;
  31.217 +}
  31.218 +
  31.219 +
  31.220 +// Loads a texture from a memory image of a TGA file.
  31.221 +Texture* LoadTextureTga(RenderParams& rParams, int samplerMode, const uint8_t* pData, int dataSize, uint8_t alpha)
  31.222 +{
  31.223 +    MemoryFile memoryFile("", pData, dataSize);
  31.224 +
  31.225 +    return LoadTextureTga(rParams, samplerMode, &memoryFile, alpha);
  31.226 +}
  31.227 +
  31.228 +
  31.229 +
  31.230 +
  31.231 +// The texture below may conceivably be shared between HSWDisplay instances. However,  
  31.232 +// beware that sharing may not be possible if two HMDs are using different locales  
  31.233 +// simultaneously. As of this writing it's not clear if that can occur in practice.
  31.234 +
  31.235 +HSWDisplay::HSWDisplay(ovrRenderAPIType api, ovrHmd hmd, const HMDRenderState& renderState)
  31.236 +  : OVR::CAPI::HSWDisplay(api, hmd, renderState)
  31.237 +  , RenderParams()
  31.238 +  , GLContext()
  31.239 +  , FrameBuffer(0)
  31.240 +  , pTexture()
  31.241 +  , pShaderSet()
  31.242 +  , pVertexShader()
  31.243 +  , pFragmentShader()
  31.244 +  , pVB()
  31.245 +  , VAO(0)
  31.246 +  , VAOInitialized(false)
  31.247 +  , OrthoProjection()
  31.248 +{
  31.249 +}
  31.250 +
  31.251 +
  31.252 +bool HSWDisplay::Initialize(const ovrRenderAPIConfig* apiConfig)
  31.253 +{
  31.254 +    const ovrGLConfig* config = (const ovrGLConfig*)apiConfig;
  31.255 +
  31.256 +    if(config)
  31.257 +    {
  31.258 +        // The following is essentially copied from CAPI_GL_DistortionRender.cpp's 
  31.259 +        // Initialize function. To do: Merge this to a central location.
  31.260 +        RenderParams.Multisample = config->OGL.Header.Multisample;
  31.261 +        RenderParams.BackBufferSize     = config->OGL.Header.BackBufferSize;
  31.262 +
  31.263 +        #if defined(OVR_OS_WIN32)
  31.264 +            RenderParams.Window = (config->OGL.Window) ? config->OGL.Window : GetActiveWindow();
  31.265 +            RenderParams.DC     = config->OGL.DC;
  31.266 +        #elif defined(OVR_OS_LINUX)
  31.267 +            if (config->OGL.Disp)
  31.268 +            {
  31.269 +                RenderParams.Disp = config->OGL.Disp;
  31.270 +            }
  31.271 +            if (!RenderParams.Disp)
  31.272 +            {
  31.273 +                RenderParams.Disp = glXGetCurrentDisplay();
  31.274 +            }
  31.275 +            if (!RenderParams.Disp)
  31.276 +            {
  31.277 +                OVR_DEBUG_LOG(("glXGetCurrentDisplay failed."));
  31.278 +                return false;
  31.279 +            }
  31.280 +        #endif
  31.281 +    }
  31.282 +    else
  31.283 +    {
  31.284 +        UnloadGraphics();
  31.285 +    }
  31.286 +
  31.287 +    return true;
  31.288 +}
  31.289 +
  31.290 +
  31.291 +void HSWDisplay::Shutdown()
  31.292 +{
  31.293 +    UnloadGraphics();
  31.294 +}
  31.295 +
  31.296 +
  31.297 +void HSWDisplay::DisplayInternal()
  31.298 +{
  31.299 +    HSWDISPLAY_LOG(("[HSWDisplay GL] DisplayInternal()"));
  31.300 +    // We may want to call LoadGraphics here instead of within Render.
  31.301 +}
  31.302 +
  31.303 +
  31.304 +void HSWDisplay::DismissInternal()
  31.305 +{
  31.306 +    HSWDISPLAY_LOG(("[HSWDisplay GL] DismissInternal()"));
  31.307 +    UnloadGraphicsRequested = true; // We don't directly call UnloadGraphics here because this may be executed within a different thread.
  31.308 +}
  31.309 +
  31.310 +
  31.311 +void HSWDisplay::UnloadGraphics()
  31.312 +{
  31.313 +    if(pTexture) // If initialized...
  31.314 +    {
  31.315 +        Context currentGLContext;
  31.316 +        currentGLContext.InitFromCurrent();
  31.317 +        GLContext.Bind();
  31.318 +
  31.319 +    // RenderParams: No need to clear.
  31.320 +    if(FrameBuffer != 0)
  31.321 +    {
  31.322 +        glDeleteFramebuffers(1, &FrameBuffer);
  31.323 +        FrameBuffer = 0;
  31.324 +    }
  31.325 +    pTexture.Clear();
  31.326 +    pShaderSet.Clear();
  31.327 +    pVertexShader.Clear();
  31.328 +    pFragmentShader.Clear();
  31.329 +    pVB.Clear();
  31.330 +    if(VAO)
  31.331 +    {
  31.332 +            glDeleteVertexArrays(1, &VAO);
  31.333 +        currentGLContext.Bind();
  31.334 +        GLContext.Destroy();
  31.335 +    }
  31.336 +}
  31.337 +}
  31.338 +
  31.339 +
  31.340 +void HSWDisplay::LoadGraphics()
  31.341 +{
  31.342 +    // We assume here that the current GL context is the one our resources will be associated with.
  31.343 +
  31.344 +    if (FrameBuffer == 0)
  31.345 +    {
  31.346 +        glGenFramebuffers(1, &FrameBuffer);
  31.347 +    }
  31.348 +
  31.349 +    if (!pTexture) // To do: Add support for .dds files, which would be significantly smaller than the size of the tga.
  31.350 +    {
  31.351 +        size_t textureSize;
  31.352 +        const uint8_t* TextureData = GetDefaultTexture(textureSize);
  31.353 +        pTexture = *LoadTextureTga(RenderParams, Sample_Linear | Sample_Clamp, TextureData, (int)textureSize, 255);
  31.354 +    }
  31.355 +
  31.356 +    if (!pShaderSet)
  31.357 +    {
  31.358 +        pShaderSet = *new ShaderSet();
  31.359 +    }
  31.360 +
  31.361 +    if(!pVertexShader)
  31.362 +    {
  31.363 +        OVR::String strShader((GLEContext::GetCurrentContext()->WholeVersion >= 302) ? glsl3Prefix : glsl2Prefix);
  31.364 +        strShader += SimpleTexturedQuad_vs;
  31.365 +
  31.366 +        pVertexShader = *new VertexShader(&RenderParams, const_cast<char*>(strShader.ToCStr()), strShader.GetLength(), SimpleTexturedQuad_vs_refl, OVR_ARRAY_COUNT(SimpleTexturedQuad_vs_refl));
  31.367 +        pShaderSet->SetShader(pVertexShader);
  31.368 +    }
  31.369 +
  31.370 +    if(!pFragmentShader)
  31.371 +    {
  31.372 +        OVR::String strShader((GLEContext::GetCurrentContext()->WholeVersion >= 302) ? glsl3Prefix : glsl2Prefix);
  31.373 +        strShader += SimpleTexturedQuad_ps;
  31.374 +
  31.375 +        pFragmentShader = *new FragmentShader(&RenderParams, const_cast<char*>(strShader.ToCStr()), strShader.GetLength(), SimpleTexturedQuad_ps_refl, OVR_ARRAY_COUNT(SimpleTexturedQuad_ps_refl));
  31.376 +        pShaderSet->SetShader(pFragmentShader);
  31.377 +    }
  31.378 +
  31.379 +    if(!pVB)
  31.380 +    {
  31.381 +        pVB = *new Buffer(&RenderParams);
  31.382 +
  31.383 +        pVB->Data(Buffer_Vertex, NULL, 4 * sizeof(HASWVertex));
  31.384 +        HASWVertex* pVertices = (HASWVertex*)pVB->Map(0, 4 * sizeof(HASWVertex), Map_Discard);
  31.385 +        OVR_ASSERT(pVertices);
  31.386 +
  31.387 +        if(pVertices)
  31.388 +        {
  31.389 +            const bool  flip   = ((RenderState.DistortionCaps & ovrDistortionCap_FlipInput) != 0);
  31.390 +            const float left   = -1.0f; // We currently draw this in normalized device coordinates with an stereo translation
  31.391 +            const float top    = -1.1f; // applied as a vertex shader uniform. In the future when we have a more formal graphics
  31.392 +            const float right  =  1.0f; // API abstraction we may move this draw to an overlay layer or to a more formal 
  31.393 +            const float bottom =  0.9f; // model/mesh scheme with a perspective projection.
  31.394 +
  31.395 +            pVertices[0] = HASWVertex(left,  top,    0.f, Color(255, 255, 255, 255), 0.f, flip ? 1.f : 0.f);
  31.396 +            pVertices[1] = HASWVertex(left,  bottom, 0.f, Color(255, 255, 255, 255), 0.f, flip ? 0.f : 1.f);
  31.397 +            pVertices[2] = HASWVertex(right, top,    0.f, Color(255, 255, 255, 255), 1.f, flip ? 1.f : 0.f); 
  31.398 +            pVertices[3] = HASWVertex(right, bottom, 0.f, Color(255, 255, 255, 255), 1.f, flip ? 0.f : 1.f);
  31.399 +
  31.400 +            pVB->Unmap(pVertices);
  31.401 +        }
  31.402 +    }
  31.403 +
  31.404 +    // We don't bind or initialize the vertex arrays here.
  31.405 +    if (!VAO && GLE_ARB_vertex_array_object)
  31.406 +    {
  31.407 +        OVR_ASSERT(!VAOInitialized);
  31.408 +            glGenVertexArrays(1, &VAO);
  31.409 +    }
  31.410 +}
  31.411 +
  31.412 +
  31.413 +void HSWDisplay::RenderInternal(ovrEyeType eye, const ovrTexture* eyeTexture)
  31.414 +{
  31.415 +    if(RenderEnabled && eyeTexture)
  31.416 +    {        
  31.417 +        // We need to render to the eyeTexture with the texture viewport.
  31.418 +        // Setup rendering to the texture.
  31.419 +        ovrGLTexture* eyeTextureGL = const_cast<ovrGLTexture*>(reinterpret_cast<const ovrGLTexture*>(eyeTexture));
  31.420 +        OVR_ASSERT(eyeTextureGL->Texture.Header.API == ovrRenderAPI_OpenGL);
  31.421 +
  31.422 +        GL::AutoContext autoGLContext(GLContext); // Saves the current GL context, binds our GLContext, then at the end of scope re-binds the current GL context.
  31.423 +
  31.424 +        // Load the graphics if not loaded already.
  31.425 +        if (!pTexture)
  31.426 +            LoadGraphics();
  31.427 +
  31.428 +        // Calculate ortho projection.
  31.429 +        GetOrthoProjection(RenderState, OrthoProjection);
  31.430 +
  31.431 +        // Set the rendering to be to the eye texture.
  31.432 +        glBindFramebuffer(GL_FRAMEBUFFER, FrameBuffer);
  31.433 +        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, eyeTextureGL->OGL.TexId, 0);
  31.434 +        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0); // We aren't using depth, as we currently want this to overwrite everything.
  31.435 +        GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
  31.436 +        OVR_ASSERT(status == GL_FRAMEBUFFER_COMPLETE); OVR_UNUSED(status);
  31.437 +
  31.438 +        // Set up the viewport
  31.439 +        const GLint   x = (GLint)eyeTextureGL->Texture.Header.RenderViewport.Pos.x;
  31.440 +        const GLint   y = (GLint)eyeTextureGL->Texture.Header.RenderViewport.Pos.y; // Note that GL uses bottom-up coordinates.
  31.441 +        const GLsizei w = (GLsizei)eyeTextureGL->Texture.Header.RenderViewport.Size.w;
  31.442 +        const GLsizei h = (GLsizei)eyeTextureGL->Texture.Header.RenderViewport.Size.h;
  31.443 +        glViewport(x, y, w, h);
  31.444 +
  31.445 +        // Set fixed-function render states.
  31.446 +        //glDepthRange(0.0,  1.0); // This is the default
  31.447 +        glDepthMask(GL_FALSE);
  31.448 +        glDisable(GL_DEPTH_TEST);
  31.449 +        glFrontFace(GL_CW);
  31.450 +        glEnable(GL_BLEND);
  31.451 +        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  31.452 +
  31.453 +        // Enable the buffer and shaders we use.
  31.454 +        ShaderFill fill(pShaderSet);
  31.455 +        if (pTexture)
  31.456 +            fill.SetTexture(0, pTexture);
  31.457 +
  31.458 +        // Set shader uniforms.
  31.459 +        const float scale  = HSWDISPLAY_SCALE * ((RenderState.OurHMDInfo.HmdType == HmdType_DK1) ? 0.70f : 1.f);
  31.460 +        pShaderSet->SetUniform2f("Scale", scale, scale / 2.f); // X and Y scale. Y is a fixed proportion to X in order to give a certain aspect ratio.
  31.461 +        pShaderSet->SetUniform2f("PositionOffset", OrthoProjection[eye].GetTranslation().x, 0.0f);
  31.462 +
  31.463 +        // Set vertex attributes
  31.464 +        if (GLE_ARB_vertex_array_object)
  31.465 +        {
  31.466 +            OVR_ASSERT(VAO != 0);
  31.467 +            glBindVertexArray(VAO);
  31.468 +        }
  31.469 +
  31.470 +        if(!VAOInitialized) // This executes for the case that VAO isn't supported.
  31.471 +        {
  31.472 +            glBindBuffer(GL_ARRAY_BUFFER, pVB->GLBuffer); // This must be called before glVertexAttribPointer is called below.
  31.473 +
  31.474 +            const GLuint shaderProgram = pShaderSet->Prog;
  31.475 +            GLint attributeLocationArray[3];
  31.476 +
  31.477 +            attributeLocationArray[0] = glGetAttribLocation(shaderProgram, "Position");
  31.478 +            glVertexAttribPointer(attributeLocationArray[0], sizeof(Vector3f)/sizeof(float), GL_FLOAT,         false, sizeof(HASWVertex), reinterpret_cast<char*>(offsetof(HASWVertex, Pos)));
  31.479 +
  31.480 +            attributeLocationArray[1] = glGetAttribLocation(shaderProgram, "Color");
  31.481 +            glVertexAttribPointer(attributeLocationArray[1], sizeof(Color)/sizeof(uint8_t),  GL_UNSIGNED_BYTE,  true, sizeof(HASWVertex), reinterpret_cast<char*>(offsetof(HASWVertex, C)));  // True because we want it to convert [0,255] to [0,1] for us.
  31.482 +
  31.483 +            attributeLocationArray[2] = glGetAttribLocation(shaderProgram, "TexCoord");
  31.484 +            glVertexAttribPointer(attributeLocationArray[2], sizeof(float[2])/sizeof(float), GL_FLOAT,         false, sizeof(HASWVertex), reinterpret_cast<char*>(offsetof(HASWVertex, U)));
  31.485 +
  31.486 +            for (size_t i = 0; i < OVR_ARRAY_COUNT(attributeLocationArray); i++)
  31.487 +                glEnableVertexAttribArray((GLuint)i);
  31.488 +        }
  31.489 +
  31.490 +        fill.Set(Prim_TriangleStrip);
  31.491 +
  31.492 +        glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
  31.493 +
  31.494 +        if (GLE_ARB_vertex_array_object)
  31.495 +        {
  31.496 +            VAOInitialized = true;
  31.497 +            glBindVertexArray(0);
  31.498 +        }
  31.499 +    }
  31.500 +}
  31.501 +
  31.502 + 
  31.503 +}}} // namespace OVR::CAPI::GL
    32.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    32.2 +++ b/LibOVR/Src/CAPI/GL/CAPI_GL_HSWDisplay.h	Wed Jan 14 06:51:16 2015 +0200
    32.3 @@ -0,0 +1,77 @@
    32.4 +/************************************************************************************
    32.5 +
    32.6 +Filename    :   CAPI_GL_HSWDisplay.h
    32.7 +Content     :   Implements Health and Safety Warning system.
    32.8 +Created     :   July 7, 2014
    32.9 +Authors     :   Paul Pedriana
   32.10 +
   32.11 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   32.12 +
   32.13 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
   32.14 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
   32.15 +which is provided at the time of installation or download, or which 
   32.16 +otherwise accompanies this software in either electronic or hard copy form.
   32.17 +
   32.18 +You may obtain a copy of the License at
   32.19 +
   32.20 +http://www.oculusvr.com/licenses/LICENSE-3.2 
   32.21 +
   32.22 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
   32.23 +distributed under the License is distributed on an "AS IS" BASIS,
   32.24 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   32.25 +See the License for the specific language governing permissions and
   32.26 +limitations under the License.
   32.27 +
   32.28 +************************************************************************************/
   32.29 +
   32.30 +#ifndef OVR_CAPI_GL_HSWDisplay_h
   32.31 +#define OVR_CAPI_GL_HSWDisplay_h
   32.32 +
   32.33 +
   32.34 +#include "../CAPI_HSWDisplay.h"
   32.35 +#include "CAPI_GL_Util.h"
   32.36 +
   32.37 +
   32.38 +namespace OVR { namespace CAPI { namespace GL {
   32.39 +
   32.40 +    class HSWDisplay : public CAPI::HSWDisplay
   32.41 +    {
   32.42 +    public:
   32.43 +        HSWDisplay(ovrRenderAPIType api, ovrHmd hmd, const HMDRenderState& renderState);
   32.44 +
   32.45 +        // Must be called before use. apiConfig is such that:
   32.46 +        //   const ovrGLConfig* config = (const ovrGLConfig*)apiConfig; or
   32.47 +        bool Initialize(const ovrRenderAPIConfig* apiConfig);
   32.48 +        void Shutdown();
   32.49 +        void DisplayInternal();
   32.50 +        void DismissInternal();
   32.51 +
   32.52 +        // Draws the warning to the eye texture(s). This must be done at the end of a 
   32.53 +        // frame but prior to executing the distortion rendering of the eye textures. 
   32.54 +        void RenderInternal(ovrEyeType eye, const ovrTexture* eyeTexture);
   32.55 +
   32.56 +    protected:
   32.57 +        void UnloadGraphics();
   32.58 +        void LoadGraphics();
   32.59 +
   32.60 +        OVR::CAPI::GL::RenderParams        RenderParams;
   32.61 +        OVR::CAPI::GL::Context             GLContext;           // Our prive OpenGL context for drawing.
   32.62 +        GLuint                             FrameBuffer;         // This is a container for a texture, depth buffer, stencil buffer to be rendered to. To consider: Make a wrapper class, like the OculusWorldDemo RBuffer class. 
   32.63 +        Ptr<OVR::CAPI::GL::Texture>        pTexture;
   32.64 +        Ptr<OVR::CAPI::GL::ShaderSet>      pShaderSet;
   32.65 +        Ptr<OVR::CAPI::GL::VertexShader>   pVertexShader;
   32.66 +        Ptr<OVR::CAPI::GL::FragmentShader> pFragmentShader;
   32.67 +        Ptr<OVR::CAPI::GL::Buffer>         pVB;
   32.68 +        GLuint                             VAO;                 // Vertex Array Object.
   32.69 +        bool                               VAOInitialized;      // True if the VAO was initialized with vertex buffer data.
   32.70 +        Matrix4f                           OrthoProjection[2];  // Projection for 2D.
   32.71 +
   32.72 +    private:
   32.73 +        OVR_NON_COPYABLE(HSWDisplay)
   32.74 +    };
   32.75 +
   32.76 +}}} // namespace OVR::CAPI::GL
   32.77 +
   32.78 +
   32.79 +#endif // OVR_CAPI_GL_HSWDisplay_h
   32.80 +
    33.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    33.2 +++ b/LibOVR/Src/CAPI/GL/CAPI_GL_Util.cpp	Wed Jan 14 06:51:16 2015 +0200
    33.3 @@ -0,0 +1,571 @@
    33.4 +/************************************************************************************
    33.5 +
    33.6 +Filename    :   CAPI_GL_Util.cpp
    33.7 +Content     :   RenderDevice implementation for OpenGL
    33.8 +Created     :   September 10, 2012
    33.9 +Authors     :   David Borel, Andrew Reisse
   33.10 +
   33.11 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   33.12 +
   33.13 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License");
   33.14 +you may not use the Oculus VR Rift SDK except in compliance with the License,
   33.15 +which is provided at the time of installation or download, or which
   33.16 +otherwise accompanies this software in either electronic or hard copy form.
   33.17 +
   33.18 +You may obtain a copy of the License at
   33.19 +
   33.20 +http://www.oculusvr.com/licenses/LICENSE-3.2
   33.21 +
   33.22 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK
   33.23 +distributed under the License is distributed on an "AS IS" BASIS,
   33.24 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   33.25 +See the License for the specific language governing permissions and
   33.26 +limitations under the License.
   33.27 +
   33.28 +************************************************************************************/
   33.29 +
   33.30 +#include "CAPI_GL_Util.h"
   33.31 +#include "../../Kernel/OVR_Log.h"
   33.32 +#include <string.h>
   33.33 +
   33.34 +#if defined(OVR_OS_LINUX)
   33.35 + #include "../../Displays/OVR_Linux_SDKWindow.h"
   33.36 +#endif
   33.37 +
   33.38 +#if defined(OVR_OS_MAC)
   33.39 +    #include <CoreGraphics/CGDirectDisplay.h>
   33.40 +    #include <OpenGL/OpenGL.h>
   33.41 +
   33.42 +typedef void *CGSConnectionID;
   33.43 +typedef int32_t CGSWindowID;
   33.44 +typedef int32_t CGSSurfaceID;
   33.45 +
   33.46 +extern "C" CGLError CGLGetSurface(CGLContextObj ctx, CGSConnectionID *cid, CGSWindowID *wid, CGSSurfaceID *sid);
   33.47 +extern "C" CGLError CGLSetSurface(CGLContextObj ctx, CGSConnectionID cid, CGSWindowID wid, CGSSurfaceID sid);
   33.48 +#endif
   33.49 +
   33.50 +
   33.51 +
   33.52 +
   33.53 +namespace OVR {
   33.54 +
   33.55 +
   33.56 +OVR::GLEContext gleContext;
   33.57 +
   33.58 +
   33.59 +OVR::GLEContext* GetGLEContext()
   33.60 +{
   33.61 +    return &gleContext;
   33.62 +}
   33.63 +
   33.64 +
   33.65 +namespace CAPI { namespace GL {
   33.66 +
   33.67 +
   33.68 +void InitGLExtensions()
   33.69 +{
   33.70 +    if(!gleContext.IsInitialized())
   33.71 +    {
   33.72 +        gleContext.SetCurrentContext(&gleContext);
   33.73 +        gleContext.Init();
   33.74 +    }
   33.75 +}
   33.76 +    
   33.77 +    
   33.78 +Buffer::Buffer(RenderParams* rp) : pParams(rp), Size(0), Use(0), GLBuffer(0)
   33.79 +{
   33.80 +}
   33.81 +
   33.82 +Buffer::~Buffer()
   33.83 +{
   33.84 +    if (GLBuffer)
   33.85 +        glDeleteBuffers(1, &GLBuffer);
   33.86 +}
   33.87 +
   33.88 +bool Buffer::Data(int use, const void* buffer, size_t size)
   33.89 +{
   33.90 +    Size = size;
   33.91 +
   33.92 +    switch (use & Buffer_TypeMask)
   33.93 +    {
   33.94 +    case Buffer_Index:     Use = GL_ELEMENT_ARRAY_BUFFER; break;
   33.95 +    default:               Use = GL_ARRAY_BUFFER; break;
   33.96 +    }
   33.97 +
   33.98 +    if (!GLBuffer)
   33.99 +        glGenBuffers(1, &GLBuffer);
  33.100 +
  33.101 +    int mode = GL_DYNAMIC_DRAW;
  33.102 +    if (use & Buffer_ReadOnly)
  33.103 +        mode = GL_STATIC_DRAW;
  33.104 +
  33.105 +    glBindBuffer(Use, GLBuffer);
  33.106 +    glBufferData(Use, size, buffer, mode);
  33.107 +    return 1;
  33.108 +}
  33.109 +
  33.110 +void* Buffer::Map(size_t, size_t, int)
  33.111 +{
  33.112 +    int mode = GL_WRITE_ONLY;
  33.113 +    //if (flags & Map_Unsynchronized)
  33.114 +    //    mode |= GL_MAP_UNSYNCHRONIZED;
  33.115 +    
  33.116 +    glBindBuffer(Use, GLBuffer);
  33.117 +    void* v = glMapBuffer(Use, mode);
  33.118 +    return v;
  33.119 +}
  33.120 +
  33.121 +bool Buffer::Unmap(void*)
  33.122 +{
  33.123 +    glBindBuffer(Use, GLBuffer);
  33.124 +    int r = glUnmapBuffer(Use);
  33.125 +    return r != 0;
  33.126 +}
  33.127 +
  33.128 +ShaderSet::ShaderSet() : 
  33.129 +  //Shaders[],
  33.130 +    UniformInfo(),
  33.131 +  //Prog(0)
  33.132 +    ProjLoc(0),
  33.133 +    ViewLoc(0),
  33.134 +  //TexLoc[],
  33.135 +    UsesLighting(false),
  33.136 +    LightingVer(0)
  33.137 +{
  33.138 +    memset(TexLoc, 0, sizeof(TexLoc));
  33.139 +    Prog = glCreateProgram();
  33.140 +}
  33.141 +ShaderSet::~ShaderSet()
  33.142 +{
  33.143 +    glDeleteProgram(Prog);
  33.144 +}
  33.145 +
  33.146 +GLint ShaderSet::GetGLShader(Shader* s)
  33.147 +{
  33.148 +    switch (s->Stage)
  33.149 +    {
  33.150 +    case Shader_Vertex: {
  33.151 +        ShaderImpl<Shader_Vertex, GL_VERTEX_SHADER>* gls = (ShaderImpl<Shader_Vertex, GL_VERTEX_SHADER>*)s;
  33.152 +        return gls->GLShader;
  33.153 +    } break;
  33.154 +    case Shader_Fragment: {
  33.155 +        ShaderImpl<Shader_Fragment, GL_FRAGMENT_SHADER>* gls = (ShaderImpl<Shader_Fragment, GL_FRAGMENT_SHADER>*)s;
  33.156 +        return gls->GLShader;
  33.157 +    } break;
  33.158 +    default: break;
  33.159 +    }
  33.160 +
  33.161 +    return -1;
  33.162 +}
  33.163 +
  33.164 +void ShaderSet::SetShader(Shader *s)
  33.165 +{
  33.166 +    Shaders[s->Stage] = s;
  33.167 +    GLint GLShader = GetGLShader(s);
  33.168 +    glAttachShader(Prog, GLShader);
  33.169 +    if (Shaders[Shader_Vertex] && Shaders[Shader_Fragment])
  33.170 +        Link();
  33.171 +}
  33.172 +
  33.173 +void ShaderSet::UnsetShader(int stage)
  33.174 +{
  33.175 +    if (Shaders[stage] == NULL)
  33.176 +        return;
  33.177 +
  33.178 +    GLint GLShader = GetGLShader(Shaders[stage]);
  33.179 +    glDetachShader(Prog, GLShader);
  33.180 +
  33.181 +    Shaders[stage] = NULL;
  33.182 +}
  33.183 +
  33.184 +bool ShaderSet::SetUniform(const char* name, int n, const float* v)
  33.185 +{
  33.186 +    for (unsigned int i = 0; i < UniformInfo.GetSize(); i++)
  33.187 +        if (!strcmp(UniformInfo[i].Name.ToCStr(), name))
  33.188 +        {
  33.189 +            OVR_ASSERT(UniformInfo[i].Location >= 0);
  33.190 +            glUseProgram(Prog);
  33.191 +            switch (UniformInfo[i].Type)
  33.192 +            {
  33.193 +            case 1:   glUniform1fv(UniformInfo[i].Location, n, v); break;
  33.194 +            case 2:   glUniform2fv(UniformInfo[i].Location, n/2, v); break;
  33.195 +            case 3:   glUniform3fv(UniformInfo[i].Location, n/3, v); break;
  33.196 +            case 4:   glUniform4fv(UniformInfo[i].Location, n/4, v); break;
  33.197 +            case 12:  glUniformMatrix3fv(UniformInfo[i].Location, 1, 1, v); break;
  33.198 +            case 16:  glUniformMatrix4fv(UniformInfo[i].Location, 1, 1, v); break;
  33.199 +            default: OVR_ASSERT(0);
  33.200 +            }
  33.201 +            return 1;
  33.202 +        }
  33.203 +
  33.204 +    OVR_DEBUG_LOG(("Warning: uniform %s not present in selected shader", name));
  33.205 +    return 0;
  33.206 +}
  33.207 +
  33.208 +bool ShaderSet::Link()
  33.209 +{
  33.210 +    glLinkProgram(Prog);
  33.211 +    GLint r;
  33.212 +    glGetProgramiv(Prog, GL_LINK_STATUS, &r);
  33.213 +    if (!r)
  33.214 +    {
  33.215 +        GLchar msg[1024];
  33.216 +        glGetProgramInfoLog(Prog, sizeof(msg), 0, msg);
  33.217 +        OVR_DEBUG_LOG(("Linking shaders failed: %s\n", msg));
  33.218 +        if (!r)
  33.219 +            return 0;
  33.220 +    }
  33.221 +    glUseProgram(Prog);
  33.222 +
  33.223 +    UniformInfo.Clear();
  33.224 +    LightingVer = 0;
  33.225 +    UsesLighting = 0;
  33.226 +
  33.227 +    GLint uniformCount = 0;
  33.228 +    glGetProgramiv(Prog, GL_ACTIVE_UNIFORMS, &uniformCount);
  33.229 +    OVR_ASSERT(uniformCount >= 0);
  33.230 +
  33.231 +    for(GLuint i = 0; i < (GLuint)uniformCount; i++)
  33.232 +    {
  33.233 +        GLsizei namelen;
  33.234 +        GLint size = 0;
  33.235 +        GLenum type;
  33.236 +        GLchar name[32];
  33.237 +        glGetActiveUniform(Prog, i, sizeof(name), &namelen, &size, &type, name);
  33.238 +
  33.239 +        if (size)
  33.240 +        {
  33.241 +            int l = glGetUniformLocation(Prog, name);
  33.242 +            char *np = name;
  33.243 +            while (*np)
  33.244 +            {
  33.245 +                if (*np == '[')
  33.246 +                    *np = 0;
  33.247 +                np++;
  33.248 +            }
  33.249 +            Uniform u;
  33.250 +            u.Name = name;
  33.251 +            u.Location = l;
  33.252 +            u.Size = size;
  33.253 +            switch (type)
  33.254 +            {
  33.255 +            case GL_FLOAT:      u.Type = 1; break;
  33.256 +            case GL_FLOAT_VEC2: u.Type = 2; break;
  33.257 +            case GL_FLOAT_VEC3: u.Type = 3; break;
  33.258 +            case GL_FLOAT_VEC4: u.Type = 4; break;
  33.259 +            case GL_FLOAT_MAT3: u.Type = 12; break;
  33.260 +            case GL_FLOAT_MAT4: u.Type = 16; break;
  33.261 +            default:
  33.262 +                continue;
  33.263 +            }
  33.264 +            UniformInfo.PushBack(u);
  33.265 +            if (!strcmp(name, "LightCount"))
  33.266 +                UsesLighting = 1;
  33.267 +        }
  33.268 +        else
  33.269 +            break;
  33.270 +    }
  33.271 +
  33.272 +    ProjLoc = glGetUniformLocation(Prog, "Proj");
  33.273 +    ViewLoc = glGetUniformLocation(Prog, "View");
  33.274 +    for (int i = 0; i < 8; i++)
  33.275 +    {
  33.276 +        char texv[32];
  33.277 +        OVR_sprintf(texv, 10, "Texture%d", i);
  33.278 +        TexLoc[i] = glGetUniformLocation(Prog, texv);
  33.279 +        if (TexLoc[i] < 0)
  33.280 +            break;
  33.281 +
  33.282 +        glUniform1i(TexLoc[i], i);
  33.283 +    }
  33.284 +    if (UsesLighting)
  33.285 +        OVR_ASSERT(ProjLoc >= 0 && ViewLoc >= 0);
  33.286 +    return 1;
  33.287 +}
  33.288 +
  33.289 +bool ShaderBase::SetUniform(const char* name, int n, const float* v)
  33.290 +{
  33.291 +    for(unsigned i = 0; i < UniformReflSize; i++)
  33.292 +    {
  33.293 +        if (!strcmp(UniformRefl[i].Name, name))
  33.294 +        {
  33.295 +            memcpy(UniformData + UniformRefl[i].Offset, v, n * sizeof(float));
  33.296 +            return 1;
  33.297 +        }
  33.298 +    }
  33.299 +    return 0;
  33.300 +}
  33.301 +
  33.302 +bool ShaderBase::SetUniformBool(const char* name, int n, const bool* v) 
  33.303 +{
  33.304 +    OVR_UNUSED(n);
  33.305 +    for(unsigned i = 0; i < UniformReflSize; i++)
  33.306 +    {
  33.307 +        if (!strcmp(UniformRefl[i].Name, name))
  33.308 +        {
  33.309 +            memcpy(UniformData + UniformRefl[i].Offset, v, UniformRefl[i].Size);
  33.310 +            return 1;
  33.311 +        }
  33.312 +    }
  33.313 +    return 0;
  33.314 +}
  33.315 +
  33.316 +void ShaderBase::InitUniforms(const Uniform* refl, size_t reflSize)
  33.317 +{
  33.318 +    if(!refl)
  33.319 +    {
  33.320 +        UniformRefl = NULL;
  33.321 +        UniformReflSize = 0;
  33.322 +
  33.323 +        UniformsSize = 0;
  33.324 +        if (UniformData)
  33.325 +        {
  33.326 +            OVR_FREE(UniformData);
  33.327 +            UniformData = 0;
  33.328 +        }
  33.329 +        return; // no reflection data
  33.330 +    }
  33.331 +
  33.332 +    UniformRefl = refl;
  33.333 +    UniformReflSize = reflSize;
  33.334 +    
  33.335 +    UniformsSize = UniformRefl[UniformReflSize-1].Offset + UniformRefl[UniformReflSize-1].Size;
  33.336 +    UniformData = (unsigned char*)OVR_ALLOC(UniformsSize);
  33.337 +}
  33.338 +
  33.339 +Texture::Texture(RenderParams* rp, int w, int h) : IsUserAllocated(false), pParams(rp), TexId(0), Width(w), Height(h)
  33.340 +{
  33.341 +    if (w && h)
  33.342 +        glGenTextures(1, &TexId);
  33.343 +}
  33.344 +
  33.345 +Texture::~Texture()
  33.346 +{
  33.347 +    if (TexId && !IsUserAllocated)
  33.348 +        glDeleteTextures(1, &TexId);
  33.349 +}
  33.350 +
  33.351 +void Texture::Set(int slot, ShaderStage) const
  33.352 +{
  33.353 +    glActiveTexture(GL_TEXTURE0 + slot);
  33.354 +    glBindTexture(GL_TEXTURE_2D, TexId);
  33.355 +}
  33.356 +
  33.357 +void Texture::SetSampleMode(int sm)
  33.358 +{
  33.359 +    glBindTexture(GL_TEXTURE_2D, TexId);
  33.360 +    switch (sm & Sample_FilterMask)
  33.361 +    {
  33.362 +    case Sample_Linear:
  33.363 +        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
  33.364 +        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  33.365 +        if(GLE_EXT_texture_filter_anisotropic)
  33.366 +        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1);
  33.367 +        break;
  33.368 +
  33.369 +    case Sample_Anisotropic:
  33.370 +        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
  33.371 +        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  33.372 +        if(GLE_EXT_texture_filter_anisotropic)
  33.373 +        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 8);
  33.374 +        break;
  33.375 +
  33.376 +    case Sample_Nearest:
  33.377 +        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  33.378 +        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  33.379 +        if(GLE_EXT_texture_filter_anisotropic)
  33.380 +        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1);
  33.381 +        break;
  33.382 +    }
  33.383 +
  33.384 +    switch (sm & Sample_AddressMask)
  33.385 +    {
  33.386 +    case Sample_Repeat:
  33.387 +        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
  33.388 +        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
  33.389 +        break;
  33.390 +
  33.391 +    case Sample_Clamp:
  33.392 +        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  33.393 +        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  33.394 +        break;
  33.395 +
  33.396 +    case Sample_ClampBorder:
  33.397 +        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
  33.398 +        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
  33.399 +        break;
  33.400 +    }
  33.401 +}
  33.402 +
  33.403 +void Texture::UpdatePlaceholderTexture(GLuint texId, const Sizei& textureSize)
  33.404 +{
  33.405 +    if (!IsUserAllocated && TexId && texId != TexId)
  33.406 +        glDeleteTextures(1, &TexId);
  33.407 +
  33.408 +    TexId = texId;
  33.409 +    Width = textureSize.w;
  33.410 +    Height = textureSize.h;
  33.411 +
  33.412 +    IsUserAllocated = true;
  33.413 +}
  33.414 +
  33.415 +
  33.416 +
  33.417 +
  33.418 +
  33.419 +Context::Context() : initialized(false), ownsContext(true), incarnation(0)
  33.420 +{
  33.421 +#if defined(OVR_OS_MAC)
  33.422 +    systemContext = 0;
  33.423 +#elif defined(OVR_OS_WIN32)
  33.424 +    hdc = 0;
  33.425 +    systemContext = 0;
  33.426 +#elif defined(OVR_OS_LINUX)
  33.427 +    x11Display = NULL;
  33.428 +    x11Drawable = 0;
  33.429 +    systemContext = 0;
  33.430 +    memset(&x11Visual, 0, sizeof(x11Visual));
  33.431 +#endif
  33.432 +
  33.433 +}
  33.434 +
  33.435 +void Context::InitFromCurrent()
  33.436 +{
  33.437 +    Destroy();
  33.438 +
  33.439 +    initialized = true;
  33.440 +    ownsContext = false;
  33.441 +    incarnation++;
  33.442 +    
  33.443 +#if defined(OVR_OS_MAC)
  33.444 +    systemContext = CGLGetCurrentContext();
  33.445 +    {
  33.446 +        CGSConnectionID cid;
  33.447 +        CGSWindowID wid;
  33.448 +        CGSSurfaceID sid;
  33.449 +        CGLError e  = kCGLNoError;
  33.450 +        e = CGLGetSurface(systemContext, &cid, &wid, &sid);
  33.451 +        OVR_ASSERT(e == kCGLNoError); OVR_UNUSED(e);
  33.452 +    }
  33.453 +
  33.454 +#elif defined(OVR_OS_WIN32)
  33.455 +    hdc = wglGetCurrentDC();
  33.456 +    systemContext = wglGetCurrentContext();
  33.457 +#elif defined(OVR_OS_LINUX)
  33.458 +    x11Display = glXGetCurrentDisplay();
  33.459 +    x11Drawable = glXGetCurrentDrawable();
  33.460 +    systemContext = glXGetCurrentContext();
  33.461 +    if (!SDKWindow::getVisualFromDrawable(x11Drawable, &x11Visual))
  33.462 +    {
  33.463 +        OVR::LogError("[Context] Unable to obtain x11 visual from context");
  33.464 +        memset(&x11Visual, 0, sizeof(x11Visual));
  33.465 +    }
  33.466 +#endif
  33.467 +}
  33.468 +
  33.469 +
  33.470 +void Context::CreateShared( Context & ctx )
  33.471 +{
  33.472 +    Destroy();
  33.473 +    OVR_ASSERT( ctx.initialized == true );
  33.474 +    if( ctx.initialized == false )
  33.475 +    {
  33.476 +        return;
  33.477 +    }
  33.478 +
  33.479 +    initialized = true;
  33.480 +    ownsContext = true;
  33.481 +    incarnation++;
  33.482 +    
  33.483 +#if defined(OVR_OS_MAC)
  33.484 +    CGLPixelFormatObj pixelFormat = CGLGetPixelFormat( ctx.systemContext );
  33.485 +    CGLError e = CGLCreateContext( pixelFormat, ctx.systemContext, &systemContext );
  33.486 +    OVR_ASSERT(e == kCGLNoError); OVR_UNUSED(e);
  33.487 +    SetSurface(ctx);
  33.488 +#elif defined(OVR_OS_WIN32)
  33.489 +    hdc = ctx.hdc;
  33.490 +    systemContext = wglCreateContext( ctx.hdc );
  33.491 +    BOOL success = wglShareLists(ctx.systemContext, systemContext );
  33.492 +    OVR_ASSERT( success == TRUE );
  33.493 +    OVR_UNUSED(success);
  33.494 +#elif defined(OVR_OS_LINUX)
  33.495 +    x11Display = ctx.x11Display;
  33.496 +    x11Drawable = ctx.x11Drawable;
  33.497 +    x11Visual = ctx.x11Visual;
  33.498 +        systemContext = glXCreateContext( ctx.x11Display, &x11Visual, ctx.systemContext, True );
  33.499 +        OVR_ASSERT( systemContext != NULL );
  33.500 +#endif
  33.501 +}
  33.502 +
  33.503 +#if defined(OVR_OS_MAC)
  33.504 +void Context::SetSurface( Context & ctx ) {
  33.505 +    CGLError e = kCGLNoError;
  33.506 +    CGSConnectionID cid, cid2;
  33.507 +    CGSWindowID wid, wid2;
  33.508 +    CGSSurfaceID sid, sid2;
  33.509 +
  33.510 +    e = CGLGetSurface(ctx.systemContext, &cid, &wid, &sid);
  33.511 +    OVR_ASSERT(e == kCGLNoError); OVR_UNUSED(e);
  33.512 +    e = CGLGetSurface(systemContext, &cid2, &wid2, &sid2);
  33.513 +    OVR_ASSERT(e == kCGLNoError); OVR_UNUSED(e);
  33.514 +    if( sid && sid != sid2 ) {
  33.515 +        e = CGLSetSurface(systemContext, cid, wid, sid);
  33.516 +        OVR_ASSERT(e == kCGLNoError); OVR_UNUSED(e);
  33.517 +    }
  33.518 +}
  33.519 +#endif
  33.520 +
  33.521 +void Context::Destroy()
  33.522 +{
  33.523 +    if( initialized == false )
  33.524 +    {
  33.525 +        return;
  33.526 +    }
  33.527 +  
  33.528 +    if (systemContext)
  33.529 +    {
  33.530 +#if defined(OVR_OS_MAC)
  33.531 +        CGLDestroyContext( systemContext );
  33.532 +#elif defined(OVR_OS_WIN32)
  33.533 +        BOOL success = wglDeleteContext( systemContext );
  33.534 +        OVR_ASSERT( success == TRUE );
  33.535 +        OVR_UNUSED( success );
  33.536 +#elif defined(OVR_OS_LINUX)
  33.537 +        glXDestroyContext( x11Display, systemContext );
  33.538 +#endif
  33.539 +
  33.540 +        systemContext = NULL;
  33.541 +    }
  33.542 +  
  33.543 +    initialized = false;
  33.544 +    ownsContext = true;
  33.545 +}
  33.546 +
  33.547 +void Context::Bind()
  33.548 +{
  33.549 +    if(systemContext)
  33.550 +    {
  33.551 +#if defined(OVR_OS_MAC)
  33.552 +        glFlush(); //Apple doesn't automatically flush within CGLSetCurrentContext, unlike other platforms.
  33.553 +        CGLSetCurrentContext( systemContext );
  33.554 +#elif defined(OVR_OS_WIN32)
  33.555 +        wglMakeCurrent( hdc, systemContext );
  33.556 +#elif defined(OVR_OS_LINUX)
  33.557 +        glXMakeCurrent( x11Display, x11Drawable, systemContext );
  33.558 +#endif
  33.559 +    }
  33.560 +}
  33.561 +
  33.562 +void Context::Unbind()
  33.563 +{
  33.564 +#if defined(OVR_OS_MAC)
  33.565 +    glFlush(); //Apple doesn't automatically flush within CGLSetCurrentContext, unlike other platforms.
  33.566 +    CGLSetCurrentContext( NULL );
  33.567 +#elif defined(OVR_OS_WIN32)
  33.568 +    wglMakeCurrent( hdc, NULL );
  33.569 +#elif defined(OVR_OS_LINUX)
  33.570 +    glXMakeCurrent( x11Display, None, NULL );
  33.571 +#endif
  33.572 +}
  33.573 +
  33.574 +}}} // namespace OVR::CAPI::GL
    34.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    34.2 +++ b/LibOVR/Src/CAPI/GL/CAPI_GL_Util.h	Wed Jan 14 06:51:16 2015 +0200
    34.3 @@ -0,0 +1,553 @@
    34.4 +/************************************************************************************
    34.5 +
    34.6 +Filename    :   CAPI_GL_Util.h
    34.7 +Content     :   Utility header for OpenGL
    34.8 +Created     :   March 27, 2014
    34.9 +Authors     :   Andrew Reisse, David Borel
   34.10 +
   34.11 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   34.12 +
   34.13 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License");
   34.14 +you may not use the Oculus VR Rift SDK except in compliance with the License,
   34.15 +which is provided at the time of installation or download, or which
   34.16 +otherwise accompanies this software in either electronic or hard copy form.
   34.17 +
   34.18 +You may obtain a copy of the License at
   34.19 +
   34.20 +http://www.oculusvr.com/licenses/LICENSE-3.2
   34.21 +
   34.22 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK
   34.23 +distributed under the License is distributed on an "AS IS" BASIS,
   34.24 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   34.25 +See the License for the specific language governing permissions and
   34.26 +limitations under the License.
   34.27 +
   34.28 +************************************************************************************/
   34.29 +
   34.30 +#ifndef INC_OVR_CAPI_GL_Util_h
   34.31 +#define INC_OVR_CAPI_GL_Util_h
   34.32 +
   34.33 +#include "../../OVR_CAPI.h"  
   34.34 +#include "../../Kernel/OVR_Array.h"
   34.35 +#include "../../Kernel/OVR_Math.h"
   34.36 +#include "../../Kernel/OVR_RefCount.h"
   34.37 +#include "../../Kernel/OVR_String.h"
   34.38 +#include "../../Kernel/OVR_Types.h"
   34.39 +#include "../../Kernel/OVR_Log.h"
   34.40 +
   34.41 +#if defined(OVR_OS_WIN32)
   34.42 +#define WIN32_LEAN_AND_MEAN
   34.43 +#include <Windows.h>
   34.44 +#endif
   34.45 +
   34.46 +#if !defined(OVR_DISABLE_GLE)   // By default we use the GLE module in order to link to OpenGL functions. However, if an external user 
   34.47 +#include "CAPI_GLE.h"           // wants to use an alternative mechanism to connect to OpenGL functions, they can #define OVR_DISABLE_GLE.
   34.48 +#endif
   34.49 +
   34.50 +
   34.51 +#if defined(OVR_OS_MAC)
   34.52 +    #include <CoreGraphics/CGDirectDisplay.h>
   34.53 +    #include <OpenGL/CGLTypes.h>
   34.54 +#endif
   34.55 +
   34.56 +
   34.57 +namespace OVR
   34.58 +{
   34.59 +    // Get the shared LibOVR GLEContext instance.
   34.60 +    class GLEContext;
   34.61 +    GLEContext* GetGLEContext();
   34.62 +}
   34.63 +
   34.64 +namespace OVR { namespace CAPI { namespace GL {
   34.65 +void InitGLExtensions();
   34.66 +
   34.67 +
   34.68 +// Rendering primitive type used to render Model.
   34.69 +enum PrimitiveType
   34.70 +{
   34.71 +    Prim_Triangles,
   34.72 +    Prim_Lines,
   34.73 +    Prim_TriangleStrip,
   34.74 +    Prim_Unknown,
   34.75 +    Prim_Count
   34.76 +};
   34.77 +
   34.78 +// Types of shaders that can be stored together in a ShaderSet.
   34.79 +enum ShaderStage
   34.80 +{
   34.81 +    Shader_Vertex   = 0,
   34.82 +    Shader_Fragment = 2,
   34.83 +    Shader_Pixel    = 2,
   34.84 +    Shader_Count    = 3,
   34.85 +};
   34.86 +
   34.87 +enum MapFlags
   34.88 +{
   34.89 +    Map_Discard        = 1,
   34.90 +    Map_Read           = 2, // do not use
   34.91 +    Map_Unsynchronized = 4, // like D3D11_MAP_NO_OVERWRITE
   34.92 +};
   34.93 +
   34.94 +
   34.95 +// Buffer types used for uploading geometry & constants.
   34.96 +enum BufferUsage
   34.97 +{
   34.98 +    Buffer_Unknown  = 0,
   34.99 +    Buffer_Vertex   = 1,
  34.100 +    Buffer_Index    = 2,
  34.101 +    Buffer_Uniform  = 4,
  34.102 +    Buffer_TypeMask = 0xff,
  34.103 +    Buffer_ReadOnly = 0x100, // Buffer must be created with Data().
  34.104 +};
  34.105 +
  34.106 +enum TextureFormat
  34.107 +{
  34.108 +    Texture_RGBA            = 0x0100,
  34.109 +    Texture_Depth           = 0x8000,
  34.110 +    Texture_TypeMask        = 0xff00,
  34.111 +    Texture_SamplesMask     = 0x00ff,
  34.112 +    Texture_RenderTarget    = 0x10000,
  34.113 +    Texture_GenMipmaps      = 0x20000,
  34.114 +};
  34.115 +
  34.116 +// Texture sampling modes.
  34.117 +enum SampleMode
  34.118 +{
  34.119 +    Sample_Linear       = 0,
  34.120 +    Sample_Nearest      = 1,
  34.121 +    Sample_Anisotropic  = 2,
  34.122 +    Sample_FilterMask   = 3,
  34.123 +
  34.124 +    Sample_Repeat       = 0,
  34.125 +    Sample_Clamp        = 4,
  34.126 +    Sample_ClampBorder  = 8, // If unsupported Clamp is used instead.
  34.127 +    Sample_AddressMask  =12,
  34.128 +
  34.129 +    Sample_Count        =13,
  34.130 +};
  34.131 +
  34.132 +
  34.133 +// Rendering parameters/pointers describing GL rendering setup.
  34.134 +struct RenderParams
  34.135 +{
  34.136 +#if defined(OVR_OS_WIN32)
  34.137 +    HWND   Window;
  34.138 +    HDC    DC;
  34.139 +#elif defined(OVR_OS_LINUX)
  34.140 +    struct _XDisplay* Disp;
  34.141 +#endif
  34.142 +
  34.143 +    ovrSizei    BackBufferSize;
  34.144 +    int    Multisample;
  34.145 +};
  34.146 +
  34.147 +
  34.148 +class Buffer : public RefCountBase<Buffer>
  34.149 +{
  34.150 +public:
  34.151 +    RenderParams* pParams;
  34.152 +    size_t        Size;
  34.153 +    GLenum        Use;
  34.154 +    GLuint        GLBuffer;
  34.155 +
  34.156 +public:
  34.157 +    Buffer(RenderParams* r);
  34.158 +    ~Buffer();
  34.159 +
  34.160 +    GLuint         GetBuffer() { return GLBuffer; }
  34.161 +
  34.162 +    virtual size_t GetSize() { return Size; }
  34.163 +    virtual void*  Map(size_t start, size_t size, int flags = 0);
  34.164 +    virtual bool   Unmap(void *m);
  34.165 +    virtual bool   Data(int use, const void* buffer, size_t size);
  34.166 +};
  34.167 +
  34.168 +class Texture : public RefCountBase<Texture>
  34.169 +{
  34.170 +	bool IsUserAllocated;
  34.171 +
  34.172 +public:
  34.173 +    RenderParams* pParams;
  34.174 +    GLuint        TexId;
  34.175 +    int           Width, Height;
  34.176 +
  34.177 +    Texture(RenderParams* rp, int w, int h);
  34.178 +    ~Texture();
  34.179 +
  34.180 +    virtual int GetWidth() const { return Width; }
  34.181 +    virtual int GetHeight() const { return Height; }
  34.182 +
  34.183 +    virtual void SetSampleMode(int sm);
  34.184 +
  34.185 +    // Updates texture to point to specified resources
  34.186 +    //  - used for slave rendering.
  34.187 +    void UpdatePlaceholderTexture(GLuint texId,
  34.188 +                                  const Sizei& textureSize);
  34.189 +
  34.190 +    virtual void Set(int slot, ShaderStage stage = Shader_Fragment) const;
  34.191 +};
  34.192 +
  34.193 +// Base class for vertex and pixel shaders. Stored in ShaderSet.
  34.194 +class Shader : public RefCountBase<Shader>
  34.195 +{
  34.196 +    friend class ShaderSet;
  34.197 +
  34.198 +protected:
  34.199 +    ShaderStage Stage;
  34.200 +
  34.201 +public:
  34.202 +    Shader(ShaderStage s) : Stage(s) {}
  34.203 +    virtual ~Shader() {}
  34.204 +
  34.205 +    ShaderStage GetStage() const { return Stage; }
  34.206 +
  34.207 +    virtual void Set(PrimitiveType) const { }
  34.208 +    virtual void SetUniformBuffer(class Buffer* buffers, int i = 0) { OVR_UNUSED2(buffers, i); }
  34.209 +
  34.210 +protected:
  34.211 +    virtual bool SetUniform(const char* name, int n, const float* v) { OVR_UNUSED3(name, n, v); return false; }
  34.212 +    virtual bool SetUniformBool(const char* name, int n, const bool* v) { OVR_UNUSED3(name, n, v); return false; }
  34.213 +};
  34.214 +
  34.215 +
  34.216 +
  34.217 +// A group of shaders, one per stage.
  34.218 +// A ShaderSet is applied for rendering with a given fill.
  34.219 +class ShaderSet : public RefCountBase<ShaderSet>
  34.220 +{
  34.221 +protected:
  34.222 +    Ptr<Shader> Shaders[Shader_Count];
  34.223 +
  34.224 +    struct Uniform
  34.225 +    {
  34.226 +        String Name;
  34.227 +        int    Location, Size;
  34.228 +        int    Type; // currently number of floats in vector
  34.229 +
  34.230 +        Uniform() : Name(), Location(0), Size(0), Type(0){}
  34.231 +    };
  34.232 +    Array<Uniform> UniformInfo;
  34.233 +	
  34.234 +public:
  34.235 +	GLuint    Prog;
  34.236 +    GLint     ProjLoc, ViewLoc;
  34.237 +    GLint     TexLoc[8];
  34.238 +    bool      UsesLighting;
  34.239 +    int       LightingVer;
  34.240 +
  34.241 +    ShaderSet();
  34.242 +    ~ShaderSet();
  34.243 +
  34.244 +    virtual void SetShader(Shader *s);
  34.245 +    virtual void UnsetShader(int stage);
  34.246 +    Shader* GetShader(int stage) { return Shaders[stage]; }
  34.247 +
  34.248 +    virtual void Set(PrimitiveType prim) const
  34.249 +    {
  34.250 +		glUseProgram(Prog);
  34.251 +
  34.252 +        for (int i = 0; i < Shader_Count; i++)
  34.253 +            if (Shaders[i])
  34.254 +                Shaders[i]->Set(prim);
  34.255 +    }
  34.256 +
  34.257 +    // Set a uniform (other than the standard matrices). It is undefined whether the
  34.258 +    // uniforms from one shader occupy the same space as those in other shaders
  34.259 +    // (unless a buffer is used, then each buffer is independent).     
  34.260 +    virtual bool SetUniform(const char* name, int n, const float* v);
  34.261 +    bool SetUniform1f(const char* name, float x)
  34.262 +    {
  34.263 +        const float v[] = {x};
  34.264 +        return SetUniform(name, 1, v);
  34.265 +    }
  34.266 +    bool SetUniform2f(const char* name, float x, float y)
  34.267 +    {
  34.268 +        const float v[] = {x,y};
  34.269 +        return SetUniform(name, 2, v);
  34.270 +    }
  34.271 +    bool SetUniform3f(const char* name, float x, float y, float z)
  34.272 +    {
  34.273 +        const float v[] = {x,y,z};
  34.274 +        return SetUniform(name, 3, v);
  34.275 +    }
  34.276 +    bool SetUniform4f(const char* name, float x, float y, float z, float w = 1)
  34.277 +    {
  34.278 +        const float v[] = {x,y,z,w};
  34.279 +        return SetUniform(name, 4, v);
  34.280 +    }
  34.281 +
  34.282 +    bool SetUniformv(const char* name, const Vector3f& v)
  34.283 +    {
  34.284 +        const float a[] = {v.x,v.y,v.z,1};
  34.285 +        return SetUniform(name, 4, a);
  34.286 +    }
  34.287 + 
  34.288 +    virtual bool SetUniform4x4f(const char* name, const Matrix4f& m)
  34.289 +    {
  34.290 +        Matrix4f mt = m.Transposed();
  34.291 +        return SetUniform(name, 16, &mt.M[0][0]);
  34.292 +    }
  34.293 +
  34.294 +    virtual bool SetUniform3x3f(const char* name, const Matrix4f& m)
  34.295 +    {
  34.296 +        Matrix4f mt = m.Transposed();
  34.297 +        // float3x3 is actually stored the same way as float4x3, with the last items ignored by the code.
  34.298 +        return SetUniform(name, 12, &mt.M[0][0]);
  34.299 +    }
  34.300 +
  34.301 +
  34.302 +protected:
  34.303 +	GLint GetGLShader(Shader* s);
  34.304 +    bool Link();
  34.305 +};
  34.306 +
  34.307 +
  34.308 +// Fill combines a ShaderSet (vertex, pixel) with textures, if any.
  34.309 +// Every model has a fill.
  34.310 +class ShaderFill : public RefCountBase<ShaderFill>
  34.311 +{
  34.312 +    Ptr<ShaderSet>     Shaders;
  34.313 +    Ptr<class Texture> Textures[8];
  34.314 +    void*              InputLayout; // HACK this should be abstracted
  34.315 +
  34.316 +public:
  34.317 +    ShaderFill(ShaderSet* sh) : Shaders(sh) { InputLayout = NULL; }
  34.318 +    ShaderFill(ShaderSet& sh) : Shaders(sh) { InputLayout = NULL; }    
  34.319 +
  34.320 +    ShaderSet*  GetShaders() const      { return Shaders; }
  34.321 +    void*       GetInputLayout() const  { return InputLayout; }
  34.322 +
  34.323 +    virtual void Set(PrimitiveType prim = Prim_Unknown) const {
  34.324 +		Shaders->Set(prim);
  34.325 +		for(int i = 0; i < 8; i++)
  34.326 +		{
  34.327 +			if(Textures[i])
  34.328 +			{
  34.329 +				Textures[i]->Set(i);
  34.330 +			}
  34.331 +		}
  34.332 +	}
  34.333 +
  34.334 +    virtual void SetTexture(int i, class Texture* tex) { if (i < 8) Textures[i] = tex; }
  34.335 +};
  34.336 +
  34.337 +    
  34.338 +struct DisplayId
  34.339 +{
  34.340 +    // Windows
  34.341 +    String MonitorName; // Monitor name for fullscreen mode
  34.342 +    
  34.343 +    // MacOS
  34.344 +    long   CgDisplayId; // CGDirectDisplayID
  34.345 +    
  34.346 +    DisplayId() : CgDisplayId(0) {}
  34.347 +    DisplayId(long id) : CgDisplayId(id) {}
  34.348 +    DisplayId(String m, long id=0) : MonitorName(m), CgDisplayId(id) {}
  34.349 +    
  34.350 +    operator bool () const
  34.351 +    {
  34.352 +        return MonitorName.GetLength() || CgDisplayId;
  34.353 +    }
  34.354 +    
  34.355 +    bool operator== (const DisplayId& b) const
  34.356 +    {
  34.357 +        return CgDisplayId == b.CgDisplayId &&
  34.358 +            (strstr(MonitorName.ToCStr(), b.MonitorName.ToCStr()) ||
  34.359 +             strstr(b.MonitorName.ToCStr(), MonitorName.ToCStr()));
  34.360 +    }
  34.361 +};
  34.362 +
  34.363 +
  34.364 +class ShaderBase : public Shader
  34.365 +{
  34.366 +public:    
  34.367 +    RenderParams*   pParams;
  34.368 +    unsigned char*  UniformData;
  34.369 +    int             UniformsSize;
  34.370 +
  34.371 +	enum VarType
  34.372 +	{
  34.373 +		VARTYPE_FLOAT,
  34.374 +		VARTYPE_INT,
  34.375 +		VARTYPE_BOOL,
  34.376 +	};
  34.377 +
  34.378 +	struct Uniform
  34.379 +	{
  34.380 +		const char* Name;
  34.381 +		VarType     Type;
  34.382 +        int         Offset;
  34.383 +        int         Size;
  34.384 +	};
  34.385 +
  34.386 +    const Uniform*  UniformRefl;
  34.387 +    size_t          UniformReflSize;
  34.388 +
  34.389 +	ShaderBase(RenderParams* rp, ShaderStage stage) :
  34.390 +        Shader(stage),
  34.391 +        pParams(rp),
  34.392 +        UniformData(NULL),
  34.393 +        UniformsSize(0),
  34.394 +        UniformRefl(NULL),
  34.395 +        UniformReflSize(0)
  34.396 +    {
  34.397 +    }
  34.398 +	~ShaderBase()
  34.399 +	{
  34.400 +        if (UniformData)
  34.401 +        {
  34.402 +            OVR_FREE(UniformData);
  34.403 +            UniformData = NULL;
  34.404 +        }
  34.405 +
  34.406 +        // Do not need to free UniformRefl
  34.407 +        UniformRefl = NULL;
  34.408 +	}
  34.409 +
  34.410 +    void InitUniforms(const Uniform* refl, size_t reflSize);
  34.411 +	bool SetUniform(const char* name, int n, const float* v);
  34.412 +	bool SetUniformBool(const char* name, int n, const bool* v);
  34.413 +};
  34.414 +
  34.415 +
  34.416 +template<ShaderStage SStage, GLenum SType>
  34.417 +class ShaderImpl : public ShaderBase
  34.418 +{
  34.419 +    friend class ShaderSet;
  34.420 +
  34.421 +public:
  34.422 +    ShaderImpl(RenderParams* rp, void* s, size_t size, const Uniform* refl, size_t reflSize)
  34.423 +		: ShaderBase(rp, SStage)
  34.424 +		, GLShader(0)
  34.425 +    {
  34.426 +		bool success;
  34.427 +        OVR_UNUSED(size);
  34.428 +        success = Compile((const char*) s);
  34.429 +        OVR_ASSERT(success);
  34.430 +        OVR_UNUSED(success);
  34.431 +		InitUniforms(refl, reflSize);
  34.432 +    }
  34.433 +    ~ShaderImpl()
  34.434 +    {      
  34.435 +		if (GLShader)
  34.436 +		{
  34.437 +			glDeleteShader(GLShader);
  34.438 +			GLShader = 0;
  34.439 +		}
  34.440 +    }
  34.441 +    bool Compile(const char* src)
  34.442 +	{
  34.443 +		if (!GLShader)
  34.444 +			GLShader = glCreateShader(GLStage());
  34.445 +
  34.446 +		glShaderSource(GLShader, 1, &src, 0);
  34.447 +		glCompileShader(GLShader);
  34.448 +		GLint r;
  34.449 +		glGetShaderiv(GLShader, GL_COMPILE_STATUS, &r);
  34.450 +		if (!r)
  34.451 +		{
  34.452 +			GLchar msg[1024];
  34.453 +			glGetShaderInfoLog(GLShader, sizeof(msg), 0, msg);
  34.454 +			if (msg[0])
  34.455 +				OVR_DEBUG_LOG(("Compiling shader\n%s\nfailed: %s\n", src, msg));
  34.456 +
  34.457 +			return 0;
  34.458 +		}
  34.459 +		return 1;
  34.460 +	}
  34.461 +	
  34.462 +    GLenum GLStage() const
  34.463 +    {
  34.464 +		return SType;
  34.465 +	}
  34.466 +
  34.467 +private:
  34.468 +	GLuint GLShader;
  34.469 +};
  34.470 +
  34.471 +typedef ShaderImpl<Shader_Vertex,  GL_VERTEX_SHADER> VertexShader;
  34.472 +typedef ShaderImpl<Shader_Fragment, GL_FRAGMENT_SHADER> FragmentShader;
  34.473 +
  34.474 +
  34.475 +
  34.476 +// Allows us to have independent OpenGL contexts for our systems.
  34.477 +class Context
  34.478 +{
  34.479 +    bool                initialized;
  34.480 +    bool                ownsContext;
  34.481 +    int                 incarnation;
  34.482 +#if defined(OVR_OS_WIN32)
  34.483 +    HDC                 hdc;
  34.484 +    HGLRC               systemContext;
  34.485 +#elif defined(OVR_OS_LINUX)
  34.486 +    Display            *x11Display;
  34.487 +    GLXDrawable         x11Drawable;
  34.488 +    GLXContext          systemContext;
  34.489 +    XVisualInfo         x11Visual;
  34.490 +#elif defined(OVR_OS_MAC)
  34.491 +    CGLContextObj       systemContext;
  34.492 +#endif
  34.493 +        
  34.494 +public:
  34.495 +
  34.496 +    Context();
  34.497 +    void InitFromCurrent();
  34.498 +    void CreateShared( Context & ctx );
  34.499 +#if defined(OVR_OS_MAC)
  34.500 +    void SetSurface( Context & ctx );
  34.501 +#endif
  34.502 +    void Destroy();
  34.503 +    void Bind();
  34.504 +    void Unbind();
  34.505 +    int  GetIncarnation() const { return incarnation; }
  34.506 +
  34.507 +};
  34.508 +
  34.509 +
  34.510 +// AutoContext
  34.511 +//
  34.512 +// Implements a common sequence of function calls with the Context class.
  34.513 +// See the AutoContext constructor below for what it does. 
  34.514 +//
  34.515 +// Example usage:
  34.516 +//     void SomeClass::Draw()
  34.517 +//     {
  34.518 +//         AutoContext autoContext(someClassContext);
  34.519 +//
  34.520 +//         <draw calls>
  34.521 +//     }
  34.522 +
  34.523 +struct AutoContext
  34.524 +{
  34.525 +    Context  savedCurrentContext;
  34.526 +    Context& ourContext;
  34.527 +
  34.528 +    AutoContext(Context& context) :
  34.529 +        savedCurrentContext(), ourContext(context)
  34.530 +    {
  34.531 +        // We use a member savedCurrentContext which is initialized here, as opposed to having the user pass in a 
  34.532 +        // pre-existing Context (which the user could declare as a global or C++ member variable). We have to do this
  34.533 +        // because if we were to use some pre-existing Context the app might delete its underlying GL context behind our back
  34.534 +        // or associate it with another thread, which would cause our bind of it in our dtor to be a bad operation.
  34.535 +        savedCurrentContext.InitFromCurrent();
  34.536 +        if(ourContext.GetIncarnation() == 0) // If not yet initialized...
  34.537 +            ourContext.CreateShared(savedCurrentContext);
  34.538 +        ourContext.Bind();
  34.539 +        #if defined(OVR_OS_MAC) // To consider: merge the following into the Bind function.
  34.540 +            ourContext.SetSurface(savedCurrentContext);
  34.541 +        #endif
  34.542 +    }
  34.543 +
  34.544 +   ~AutoContext()
  34.545 +    {
  34.546 +        savedCurrentContext.Bind();
  34.547 +    }
  34.548 +
  34.549 +    OVR_NON_COPYABLE(AutoContext)
  34.550 +};
  34.551 +
  34.552 +
  34.553 +}}} // namespace OVR::CAPI::GL
  34.554 +
  34.555 +
  34.556 +#endif // INC_OVR_CAPI_GL_Util_h
    35.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    35.2 +++ b/LibOVR/Src/CAPI/Textures/healthAndSafety.tga.h	Wed Jan 14 06:51:16 2015 +0200
    35.3 @@ -0,0 +1,3363 @@
    35.4 +const uint8_t healthAndSafety_tga[107525] = {
    35.5 +   0x00,0x00,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x02,0x20,0x08,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
    35.6 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
    35.7 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
    35.8 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
    35.9 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
   35.10 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
   35.11 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
   35.12 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
   35.13 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
   35.14 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
   35.15 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
   35.16 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
   35.17 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
   35.18 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
   35.19 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
   35.20 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
   35.21 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
   35.22 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
   35.23 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
   35.24 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
   35.25 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
   35.26 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
   35.27 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
   35.28 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
   35.29 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
   35.30 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
   35.31 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
   35.32 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
   35.33 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
   35.34 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
   35.35 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
   35.36 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
   35.37 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
   35.38 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
   35.39 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
   35.40 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
   35.41 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
   35.42 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
   35.43 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
   35.44 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
   35.45 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
   35.46 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
   35.47 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
   35.48 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
   35.49 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
   35.50 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
   35.51 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
   35.52 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
   35.53 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
   35.54 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
   35.55 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
   35.56 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
   35.57 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
   35.58 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
   35.59 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
   35.60 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
   35.61 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
   35.62 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
   35.63 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
   35.64 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
   35.65 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
   35.66 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
   35.67 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
   35.68 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
   35.69 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
   35.70 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
   35.71 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
   35.72 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
   35.73 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
   35.74 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
   35.75 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
   35.76 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
   35.77 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
   35.78 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
   35.79 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
   35.80 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
   35.81 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
   35.82 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
   35.83 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
   35.84 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
   35.85 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
   35.86 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
   35.87 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
   35.88 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
   35.89 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
   35.90 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
   35.91 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
   35.92 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
   35.93 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
   35.94 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
   35.95 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
   35.96 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
   35.97 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
   35.98 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
   35.99 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
  35.100 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
  35.101 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
  35.102 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
  35.103 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xc7,0x00,0x00,0x00,0xb3,0x81,0x7e,0x7e,0x7e,0xc7,0x00,0x52,0x52,0x52,0xbd,
  35.104 +   0x9f,0x00,0x00,0x00,0xb3,0x00,0x33,0x33,0x33,0xb8,0x81,0x7e,0x7e,0x7e,0xc7,0x00,0x33,0x33,0x33,0xb8,0xff,0x00,0x00,0x00,0xb3,0x00,0x00,0x00,0x00,0xb3,0x82,0x7e,
  35.105 +   0x7e,0x7e,0xc7,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0x8c,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
  35.106 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xc6,0x00,0x00,0x00,0xb3,0x00,0xd2,0xd2,0xd2,0xe6,0x82,0xff,0xff,0xff,0xff,0x01,0xdc,0xdc,0xdc,0xeb,0x33,0x33,0x33,0xb8,0x9d,0x00,
  35.107 +   0x00,0x00,0xb3,0x00,0xf7,0xf7,0xf7,0xfa,0x82,0xff,0xff,0xff,0xff,0x00,0xbb,0xbb,0xbb,0xdc,0xfc,0x00,0x00,0x00,0xb3,0x01,0x52,0x52,0x52,0xbd,0xd2,0xd2,0xd2,0xe6,
  35.108 +   0x84,0xff,0xff,0xff,0xff,0x00,0xbb,0xbb,0xbb,0xdc,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0x8a,0x00,0x00,0x00,0xb3,0xff,0x00,
  35.109 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xc6,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x83,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,
  35.110 +   0xd6,0x9d,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x83,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0xfb,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x86,
  35.111 +   0xff,0xff,0xff,0xff,0x00,0xc7,0xc7,0xc7,0xe1,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0x89,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
  35.112 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xc6,0x00,0x00,0x00,0xb3,0x05,0x52,0x52,0x52,0xbd,0x00,0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,0xe6,0xe6,
  35.113 +   0xe6,0xf0,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0x9d,0x00,0x00,0x00,0xb3,0x05,0x52,0x52,0x52,0xbd,0x00,0x00,0x00,0xb3,0x6a,0x6a,0x6a,0xc2,0xf7,0xf7,0xf7,0xfa,
  35.114 +   0xff,0xff,0xff,0xff,0xd2,0xd2,0xd2,0xe6,0xfc,0x00,0x00,0x00,0xb3,0x05,0xef,0xef,0xef,0xf5,0xe6,0xe6,0xe6,0xf0,0xa0,0xa0,0xa0,0xd1,0x7e,0x7e,0x7e,0xc7,0xa0,0xa0,
  35.115 +   0xa0,0xd1,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x00,0x52,0x52,0x52,0xbd,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0x88,
  35.116 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0x96,0x00,0x00,0x00,0xb3,0x02,0x6a,0x6a,0x6a,0xc2,0x7e,0x7e,0x7e,
  35.117 +   0xc7,0x52,0x52,0x52,0xbd,0x84,0x00,0x00,0x00,0xb3,0x00,0x6a,0x6a,0x6a,0xc2,0x81,0x7e,0x7e,0x7e,0xc7,0x84,0x00,0x00,0x00,0xb3,0x00,0x33,0x33,0x33,0xb8,0x81,0x7e,
  35.118 +   0x7e,0x7e,0xc7,0x00,0x52,0x52,0x52,0xbd,0x89,0x00,0x00,0x00,0xb3,0x02,0x33,0x33,0x33,0xb8,0x7e,0x7e,0x7e,0xc7,0x6a,0x6a,0x6a,0xc2,0x91,0x00,0x00,0x00,0xb3,0x00,
  35.119 +   0x90,0x90,0x90,0xcc,0x81,0xff,0xff,0xff,0xff,0x00,0xa0,0xa0,0xa0,0xd1,0x95,0x00,0x00,0x00,0xb3,0x00,0x33,0x33,0x33,0xb8,0x81,0x7e,0x7e,0x7e,0xc7,0x86,0x00,0x00,
  35.120 +   0x00,0xb3,0x00,0xbb,0xbb,0xbb,0xdc,0x81,0xff,0xff,0xff,0xff,0x00,0x52,0x52,0x52,0xbd,0x8a,0x00,0x00,0x00,0xb3,0x00,0x33,0x33,0x33,0xb8,0x81,0x7e,0x7e,0x7e,0xc7,
  35.121 +   0x00,0x33,0x33,0x33,0xb8,0x83,0x00,0x00,0x00,0xb3,0x00,0x52,0x52,0x52,0xbd,0x81,0x7e,0x7e,0x7e,0xc7,0x8b,0x00,0x00,0x00,0xb3,0x02,0x6a,0x6a,0x6a,0xc2,0x7e,0x7e,
  35.122 +   0x7e,0xc7,0x33,0x33,0x33,0xb8,0x87,0x00,0x00,0x00,0xb3,0x00,0x33,0x33,0x33,0xb8,0x81,0x7e,0x7e,0x7e,0xc7,0x99,0x00,0x00,0x00,0xb3,0x00,0x52,0x52,0x52,0xbd,0x81,
  35.123 +   0x7e,0x7e,0x7e,0xc7,0x9b,0x00,0x00,0x00,0xb3,0x02,0x6a,0x6a,0x6a,0xc2,0x7e,0x7e,0x7e,0xc7,0x52,0x52,0x52,0xbd,0x86,0x00,0x00,0x00,0xb3,0x81,0x7e,0x7e,0x7e,0xc7,
  35.124 +   0x86,0x00,0x00,0x00,0xb3,0x00,0x6a,0x6a,0x6a,0xc2,0x83,0x00,0x00,0x00,0xb3,0x00,0xa0,0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x84,0x00,
  35.125 +   0x00,0x00,0xb3,0x02,0x6a,0x6a,0x6a,0xc2,0x7e,0x7e,0x7e,0xc7,0x52,0x52,0x52,0xbd,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0x00,
  35.126 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0x01,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,
  35.127 +   0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x86,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x84,0x00,0x00,0x00,0xb3,0x01,
  35.128 +   0xaf,0xaf,0xaf,0xd6,0xef,0xef,0xef,0xf5,0x82,0xff,0xff,0xff,0xff,0x04,0xdc,0xdc,0xdc,0xeb,0x6a,0x6a,0x6a,0xc2,0x00,0x00,0x00,0xb3,0x90,0x90,0x90,0xcc,0xef,0xef,
  35.129 +   0xef,0xf5,0x83,0xff,0xff,0xff,0xff,0x03,0xbb,0xbb,0xbb,0xdc,0x00,0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,0xc7,0xc7,0xc7,0xe1,0x83,0xff,0xff,0xff,0xff,0x01,0xef,0xef,
  35.130 +   0xef,0xf5,0x6a,0x6a,0x6a,0xc2,0x86,0x00,0x00,0x00,0xb3,0x00,0xbb,0xbb,0xbb,0xdc,0x82,0xff,0xff,0xff,0xff,0x01,0xef,0xef,0xef,0xf5,0xd2,0xd2,0xd2,0xe6,0x81,0xff,
  35.131 +   0xff,0xff,0xff,0x01,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,
  35.132 +   0x81,0xff,0xff,0xff,0xff,0x83,0x00,0x00,0x00,0xb3,0x00,0xa0,0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,0xff,0x00,0xd2,0xd2,0xd2,0xe6,0x88,0x00,0x00,0x00,0xb3,0x00,0xdc,
  35.133 +   0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0x90,0x90,0x90,0xcc,0x81,0xff,0xff,0xff,0xff,0x04,0xf7,0xf7,0xf7,0xfa,0x52,0x52,0x52,0xbd,
  35.134 +   0x00,0x00,0x00,0xb3,0x52,0x52,0x52,0xbd,0xd2,0xd2,0xd2,0xe6,0x82,0xff,0xff,0xff,0xff,0x01,0xf7,0xf7,0xf7,0xfa,0xaf,0xaf,0xaf,0xd6,0x84,0x00,0x00,0x00,0xb3,0x00,
  35.135 +   0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x89,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x83,0xff,0xff,0xff,0xff,0x81,0x00,0x00,
  35.136 +   0x00,0xb3,0x01,0x6a,0x6a,0x6a,0xc2,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x01,0xf7,0xf7,0xf7,0xfa,0xaf,0xaf,0xaf,0xd6,0x87,0x00,0x00,0x00,0xb3,0x01,0x6a,
  35.137 +   0x6a,0x6a,0xc2,0xef,0xef,0xef,0xf5,0x82,0xff,0xff,0xff,0xff,0x00,0xbb,0xbb,0xbb,0xdc,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,
  35.138 +   0x01,0x52,0x52,0x52,0xbd,0xd2,0xd2,0xd2,0xe6,0x82,0xff,0xff,0xff,0xff,0x02,0xf7,0xf7,0xf7,0xfa,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,
  35.139 +   0x00,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x00,0xbb,0xbb,0xbb,0xdc,0x81,0xff,0xff,0xff,0xff,0x01,0xdc,0xdc,0xdc,0xeb,0x33,0x33,0x33,0xb8,0x81,0xff,0xff,
  35.140 +   0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,
  35.141 +   0x01,0x6a,0x6a,0x6a,0xc2,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x01,0xf7,0xf7,0xf7,0xfa,0xaf,0xaf,0xaf,0xd6,0x84,0x00,0x00,0x00,0xb3,0x00,0xe6,0xe6,0xe6,
  35.142 +   0xf0,0x81,0xff,0xff,0xff,0xff,0x00,0x6a,0x6a,0x6a,0xc2,0x81,0x00,0x00,0x00,0xb3,0x00,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x00,0xa0,0xa0,0xa0,0xd1,0x82,
  35.143 +   0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x82,0x00,0x00,0x00,0xb3,0x01,0xaf,0xaf,0xaf,0xd6,0xef,0xef,0xef,0xf5,0x82,0xff,0xff,0xff,
  35.144 +   0xff,0x01,0xdc,0xdc,0xdc,0xeb,0x6a,0x6a,0x6a,0xc2,0x82,0x00,0x00,0x00,0xb3,0x01,0x90,0x90,0x90,0xcc,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x01,0xef,0xef,
  35.145 +   0xef,0xf5,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x05,0x33,0x33,0x33,0xb8,0xc7,0xc7,0xc7,0xe1,0xf7,0xf7,
  35.146 +   0xf7,0xfa,0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,0xeb,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,0x01,0xaf,0xaf,
  35.147 +   0xaf,0xd6,0xef,0xef,0xef,0xf5,0x82,0xff,0xff,0xff,0xff,0x01,0xdc,0xdc,0xdc,0xeb,0x6a,0x6a,0x6a,0xc2,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xfe,0x00,
  35.148 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0x01,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,
  35.149 +   0x00,0xaf,0xaf,0xaf,0xd6,0x86,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x83,0x00,0x00,0x00,0xb3,0x00,0xaf,
  35.150 +   0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x01,0xef,0xef,0xef,0xf5,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0x6a,
  35.151 +   0x6a,0x6a,0xc2,0x81,0xff,0xff,0xff,0xff,0x01,0xdc,0xdc,0xdc,0xeb,0xef,0xef,0xef,0xf5,0x81,0xff,0xff,0xff,0xff,0x05,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xd2,
  35.152 +   0xd2,0xd2,0xe6,0xff,0xff,0xff,0xff,0xef,0xef,0xef,0xf5,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x01,0xf7,0xf7,0xf7,0xfa,0x33,0x33,0x33,0xb8,0x84,0x00,0x00,
  35.153 +   0x00,0xb3,0x00,0xa0,0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0xaf,0xaf,0xaf,0xd6,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x01,0x00,
  35.154 +   0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,
  35.155 +   0x83,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x00,0x52,0x52,0x52,0xbd,0x87,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,
  35.156 +   0xff,0xff,0xff,0x02,0x00,0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x03,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0x33,0x33,
  35.157 +   0x33,0xb8,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x01,0xdc,0xdc,0xdc,0xeb,0xef,0xef,0xef,0xf5,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0x00,
  35.158 +   0x00,0x00,0xb3,0x01,0x33,0x33,0x33,0xb8,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x00,0xef,0xef,0xef,0xf5,0x88,0x00,0x00,0x00,0xb3,0x00,0x52,0x52,0x52,0xbd,
  35.159 +   0x84,0xff,0xff,0xff,0xff,0x02,0x00,0x00,0x00,0xb3,0x52,0x52,0x52,0xbd,0xf7,0xf7,0xf7,0xfa,0x85,0xff,0xff,0xff,0xff,0x00,0xbb,0xbb,0xbb,0xdc,0x86,0x00,0x00,0x00,
  35.160 +   0xb3,0x02,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0x81,0xbb,0xbb,0xbb,0xdc,0x00,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x03,0xaf,0xaf,
  35.161 +   0xaf,0xd6,0x00,0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,0xf7,0xf7,0xf7,0xfa,0x84,0xff,0xff,0xff,0xff,0x01,0xc7,0xc7,0xc7,0xe1,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,
  35.162 +   0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x02,0xf7,0xf7,0xf7,0xfa,0x33,0x33,0x33,0xb8,0x00,0x00,0x00,0xb3,
  35.163 +   0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x03,0x7e,0x7e,0x7e,0xc7,0x00,0x00,
  35.164 +   0x00,0xb3,0x52,0x52,0x52,0xbd,0xf7,0xf7,0xf7,0xfa,0x85,0xff,0xff,0xff,0xff,0x00,0xbb,0xbb,0xbb,0xdc,0x82,0x00,0x00,0x00,0xb3,0x00,0x6a,0x6a,0x6a,0xc2,0x82,0xff,
  35.165 +   0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0xef,0xef,0xef,0xf5,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0x00,0x00,0x00,
  35.166 +   0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x01,0xef,0xef,0xef,0xf5,0xdc,
  35.167 +   0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x87,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,
  35.168 +   0xc7,0x81,0x00,0x00,0x00,0xb3,0x00,0xe6,0xe6,0xe6,0xf0,0x86,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,
  35.169 +   0xff,0xff,0xff,0xff,0x01,0xef,0xef,0xef,0xf5,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
  35.170 +   0xb3,0xfe,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0x01,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,
  35.171 +   0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x86,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,
  35.172 +   0xb3,0x00,0x52,0x52,0x52,0xbd,0x81,0xff,0xff,0xff,0xff,0x00,0xd2,0xd2,0xd2,0xe6,0x81,0x00,0x00,0x00,0xb3,0x02,0x6a,0x6a,0x6a,0xc2,0xbb,0xbb,0xbb,0xdc,0x33,0x33,
  35.173 +   0x33,0xb8,0x81,0x00,0x00,0x00,0xb3,0x03,0xa0,0xa0,0xa0,0xd1,0x6a,0x6a,0x6a,0xc2,0x00,0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,0x81,0xff,0xff,0xff,0xff,0x03,0xdc,0xdc,
  35.174 +   0xdc,0xeb,0x00,0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0xbb,0xbb,0xbb,0xdc,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,
  35.175 +   0x7e,0xc7,0x84,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x82,0x00,0x00,0x00,0xb3,0x00,0xd2,0xd2,0xd2,0xe6,0x81,0xff,0xff,0xff,0xff,
  35.176 +   0x01,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,
  35.177 +   0xff,0xff,0x82,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x83,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x87,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,
  35.178 +   0x81,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0xb3,0xd2,0xd2,0xd2,0xe6,0x81,0xff,0xff,0xff,0xff,0x00,0xbb,0xbb,0xbb,0xdc,0x81,0x00,0x00,0x00,0xb3,0x00,0xc7,0xc7,
  35.179 +   0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x00,0x6a,0x6a,0x6a,0xc2,0x81,0x00,0x00,0x00,0xb3,0x01,0xbb,0xbb,0xbb,0xdc,0x7e,0x7e,0x7e,0xc7,0x83,0x00,0x00,0x00,0xb3,0x00,
  35.180 +   0xaf,0xaf,0xaf,0xd6,0x83,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x87,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x04,0xd2,0xd2,
  35.181 +   0xd2,0xe6,0x00,0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,0x00,0x00,0x00,0xb3,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x03,0xd2,0xd2,0xd2,0xe6,0x7e,0x7e,0x7e,0xc7,
  35.182 +   0xa0,0xa0,0xa0,0xd1,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x00,0x52,0x52,0x52,0xbd,0x85,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,
  35.183 +   0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0x6a,0x6a,0x6a,0xc2,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,
  35.184 +   0xff,0xff,0x03,0xd2,0xd2,0xd2,0xe6,0x7e,0x7e,0x7e,0xc7,0xa0,0xa0,0xa0,0xd1,0xc7,0xc7,0xc7,0xe1,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,
  35.185 +   0xdc,0xeb,0x33,0x33,0x33,0xb8,0xef,0xef,0xef,0xf5,0x81,0xff,0xff,0xff,0xff,0x00,0x90,0x90,0x90,0xcc,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,
  35.186 +   0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x02,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0xc7,0xc7,0xc7,0xe1,0x81,
  35.187 +   0xff,0xff,0xff,0xff,0x03,0xd2,0xd2,0xd2,0xe6,0x7e,0x7e,0x7e,0xc7,0xa0,0xa0,0xa0,0xd1,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x00,0x52,0x52,0x52,0xbd,0x81,
  35.188 +   0x00,0x00,0x00,0xb3,0x00,0xbb,0xbb,0xbb,0xdc,0x82,0xff,0xff,0xff,0xff,0x02,0xe6,0xe6,0xe6,0xf0,0x00,0x00,0x00,0xb3,0x6a,0x6a,0x6a,0xc2,0x83,0xff,0xff,0xff,0xff,
  35.189 +   0x00,0x52,0x52,0x52,0xbd,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0xb3,0x52,0x52,0x52,0xbd,0x81,0xff,0xff,
  35.190 +   0xff,0xff,0x00,0xd2,0xd2,0xd2,0xe6,0x81,0x00,0x00,0x00,0xb3,0x02,0x6a,0x6a,0x6a,0xc2,0xbb,0xbb,0xbb,0xdc,0x33,0x33,0x33,0xb8,0x81,0x00,0x00,0x00,0xb3,0x00,0xd2,
  35.191 +   0xd2,0xd2,0xe6,0x81,0xff,0xff,0xff,0xff,0x03,0xd2,0xd2,0xd2,0xe6,0x7e,0x7e,0x7e,0xc7,0x90,0x90,0x90,0xcc,0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,0x02,0x7e,
  35.192 +   0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0xa0,0xa0,0xa0,0xd1,0x82,0xff,0xff,0xff,0xff,0x02,0xc7,0xc7,0xc7,0xe1,0xaf,0xaf,0xaf,0xd6,0xef,0xef,0xef,0xf5,0x81,0xff,0xff,
  35.193 +   0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0x52,0x52,0x52,0xbd,0x81,0xff,0xff,0xff,0xff,0x00,0xd2,0xd2,0xd2,0xe6,0x81,0x00,0x00,0x00,0xb3,0x02,0x6a,
  35.194 +   0x6a,0x6a,0xc2,0xbb,0xbb,0xbb,0xdc,0x33,0x33,0x33,0xb8,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xfe,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
  35.195 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0x01,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x86,0x00,0x00,0x00,
  35.196 +   0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,
  35.197 +   0xc7,0xc7,0xc7,0xe1,0x84,0xaf,0xaf,0xaf,0xd6,0x05,0x52,0x52,0x52,0xbd,0x00,0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,0xaf,0xaf,0xaf,0xd6,0xd2,0xd2,0xd2,0xe6,0xf7,0xf7,
  35.198 +   0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x00,0xc7,0xc7,0xc7,0xe1,0x81,0x00,0x00,0x00,0xb3,0x02,0x7e,0x7e,0x7e,0xc7,0xbb,0xbb,0xbb,0xdc,0xe6,0xe6,0xe6,0xf0,0x82,0xff,
  35.199 +   0xff,0xff,0xff,0x00,0x52,0x52,0x52,0xbd,0x84,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x03,0xd2,0xd2,0xd2,0xe6,0x90,0x90,0x90,0xcc,
  35.200 +   0x7e,0x7e,0x7e,0xc7,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,
  35.201 +   0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x82,0x00,0x00,0x00,0xb3,0x00,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x02,0xc7,
  35.202 +   0xc7,0xc7,0xe1,0xff,0xff,0xff,0xff,0xef,0xef,0xef,0xf5,0x87,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x00,0x90,0x90,0x90,0xcc,0x81,
  35.203 +   0xff,0xff,0xff,0xff,0x00,0xe6,0xe6,0xe6,0xf0,0x82,0x00,0x00,0x00,0xb3,0x02,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xef,0xef,0xef,0xf5,0x84,0xaf,0xaf,0xaf,0xd6,
  35.204 +   0x00,0xa0,0xa0,0xa0,0xd1,0x82,0x00,0x00,0x00,0xb3,0x01,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0x81,0xe6,0xe6,0xe6,0xf0,0x01,0xff,0xff,0xff,0xff,0xc7,0xc7,0xc7,
  35.205 +   0xe1,0x87,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,0x02,0xf7,0xf7,0xf7,0xfa,0xff,
  35.206 +   0xff,0xff,0xff,0xef,0xef,0xef,0xf5,0x82,0x00,0x00,0x00,0xb3,0x00,0xa0,0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x85,0x00,0x00,0x00,0xb3,
  35.207 +   0x03,0xdc,0xdc,0xdc,0xeb,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0xaf,0xaf,0xaf,0xd6,0x81,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x04,0xaf,0xaf,0xaf,0xd6,
  35.208 +   0x00,0x00,0x00,0xb3,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xef,0xef,0xef,0xf5,0x85,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x01,0xdc,0xdc,0xdc,0xeb,0xbb,
  35.209 +   0xbb,0xbb,0xdc,0x81,0xff,0xff,0xff,0xff,0x00,0xbb,0xbb,0xbb,0xdc,0x82,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,
  35.210 +   0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x04,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xef,0xef,0xef,0xf5,
  35.211 +   0x82,0x00,0x00,0x00,0xb3,0x00,0xa0,0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x02,0xef,0xef,0xef,0xf5,0xff,0xff,
  35.212 +   0xff,0xff,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x06,0x33,0x33,0x33,0xb8,0xbb,0xbb,0xbb,0xdc,0xff,0xff,0xff,0xff,0xef,0xef,0xef,0xf5,0xf7,0xf7,0xf7,0xfa,
  35.213 +   0xff,0xff,0xff,0xff,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,
  35.214 +   0x81,0xff,0xff,0xff,0xff,0x00,0xc7,0xc7,0xc7,0xe1,0x84,0xaf,0xaf,0xaf,0xd6,0x01,0x52,0x52,0x52,0xbd,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xef,0xef,
  35.215 +   0xef,0xf5,0x82,0x00,0x00,0x00,0xb3,0x00,0x52,0x52,0x52,0xbd,0x81,0xff,0xff,0xff,0xff,0x02,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0xd2,0xd2,0xd2,0xe6,0x81,0xff,
  35.216 +   0xff,0xff,0xff,0x00,0x90,0x90,0x90,0xcc,0x81,0x00,0x00,0x00,0xb3,0x05,0x33,0x33,0x33,0xb8,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xaf,0xaf,0xaf,0xd6,0x00,0x00,
  35.217 +   0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0xc7,0xc7,0xc7,0xe1,0x84,0xaf,0xaf,0xaf,0xd6,0x00,0x52,0x52,0x52,0xbd,0xff,0x00,0x00,0x00,0xb3,0xff,
  35.218 +   0x00,0x00,0x00,0xb3,0xfd,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0x01,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,
  35.219 +   0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x86,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,
  35.220 +   0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x87,0xff,0xff,0xff,0xff,0x02,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0xe6,0xe6,0xe6,0xf0,0x83,0xff,0xff,0xff,0xff,
  35.221 +   0x03,0xef,0xef,0xef,0xf5,0x6a,0x6a,0x6a,0xc2,0x00,0x00,0x00,0xb3,0x90,0x90,0x90,0xcc,0x84,0xff,0xff,0xff,0xff,0x00,0xbb,0xbb,0xbb,0xdc,0x86,0x00,0x00,0x00,0xb3,
  35.222 +   0x00,0xaf,0xaf,0xaf,0xd6,0x86,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,
  35.223 +   0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0x52,0x52,0x52,0xbd,0x81,0xff,0xff,0xff,0xff,0x01,0xc7,0xc7,0xc7,0xe1,
  35.224 +   0x6a,0x6a,0x6a,0xc2,0x81,0xff,0xff,0xff,0xff,0x00,0x90,0x90,0x90,0xcc,0x86,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x00,0xf7,0xf7,
  35.225 +   0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x00,0x52,0x52,0x52,0xbd,0x82,0x00,0x00,0x00,0xb3,0x87,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,
  35.226 +   0x00,0xa0,0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,0xff,0x01,0xa0,0xa0,0xa0,0xd1,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x33,0x33,0x33,0xb8,0x86,0x00,0x00,
  35.227 +   0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,
  35.228 +   0x82,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x85,0x00,0x00,0x00,0xb3,0x01,0x6a,0x6a,0x6a,0xc2,0xe6,0xe6,
  35.229 +   0xe6,0xf0,0x85,0xff,0xff,0xff,0xff,0x01,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x85,0x00,0x00,0x00,0xb3,0x81,
  35.230 +   0xff,0xff,0xff,0xff,0x00,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x00,0xef,0xef,0xef,0xf5,0x83,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,
  35.231 +   0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x01,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,
  35.232 +   0xdc,0xdc,0xdc,0xeb,0x82,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0x90,0x90,0x90,0xcc,
  35.233 +   0x81,0xff,0xff,0xff,0xff,0x09,0xaf,0xaf,0xaf,0xd6,0xe6,0xe6,0xe6,0xf0,0xff,0xff,0xff,0xff,0x90,0x90,0x90,0xcc,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0xbb,0xbb,
  35.234 +   0xbb,0xdc,0xd2,0xd2,0xd2,0xe6,0xff,0xff,0xff,0xff,0xe6,0xe6,0xe6,0xf0,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x01,0x00,0x00,
  35.235 +   0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x87,0xff,0xff,0xff,0xff,0x01,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x83,0x00,
  35.236 +   0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x02,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x83,0x00,0x00,0x00,0xb3,0x04,
  35.237 +   0xdc,0xdc,0xdc,0xeb,0xff,0xff,0xff,0xff,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x87,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0xff,0x00,
  35.238 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xfd,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0x01,0x00,0x00,0x00,
  35.239 +   0xb3,0x7e,0x7e,0x7e,0xc7,0x85,0xff,0xff,0xff,0xff,0x01,0xdc,0xdc,0xdc,0xeb,0xa0,0xa0,0xa0,0xd1,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,
  35.240 +   0xff,0xff,0x00,0xe6,0xe6,0xe6,0xf0,0x82,0x00,0x00,0x00,0xb3,0x00,0xa0,0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x7e,0x7e,0x7e,0xc7,
  35.241 +   0x00,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x01,0x6a,0x6a,0x6a,0xc2,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x02,0xf7,0xf7,0xf7,0xfa,0xbb,0xbb,0xbb,
  35.242 +   0xdc,0x90,0x90,0x90,0xcc,0x82,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0xaf,0xaf,0xaf,0xd6,0x52,0x52,0x52,
  35.243 +   0xbd,0x88,0x00,0x00,0x00,0xb3,0x01,0x33,0x33,0x33,0xb8,0x7e,0x7e,0x7e,0xc7,0x81,0xaf,0xaf,0xaf,0xd6,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x01,0x00,
  35.244 +   0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xc7,0xc7,0xc7,0xe1,0x81,0x00,0x00,0x00,0xb3,0x00,0xef,0xef,0xef,0xf5,0x81,0xff,0xff,0xff,0xff,
  35.245 +   0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x04,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,
  35.246 +   0xd2,0xd2,0xd2,0xe6,0x86,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x00,0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,0x00,0xa0,0xa0,
  35.247 +   0xa0,0xd1,0x82,0x00,0x00,0x00,0xb3,0x02,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0xef,0xef,0xef,0xf5,0x82,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xd2,
  35.248 +   0xd2,0xd2,0xe6,0x81,0x00,0x00,0x00,0xb3,0x04,0xdc,0xdc,0xdc,0xeb,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0x33,0x33,0x33,0xb8,0x52,0x52,0x52,0xbd,0x81,0xff,0xff,
  35.249 +   0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x86,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,
  35.250 +   0x03,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0x33,0x33,0x33,0xb8,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,
  35.251 +   0x00,0xa0,0xa0,0xa0,0xd1,0x87,0x00,0x00,0x00,0xb3,0x01,0x6a,0x6a,0x6a,0xc2,0xa0,0xa0,0xa0,0xd1,0x81,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x05,0xaf,0xaf,
  35.252 +   0xaf,0xd6,0x00,0x00,0x00,0xb3,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0x33,0x33,0x33,0xb8,0x81,0x00,0x00,0x00,0xb3,0x00,0x33,0x33,0x33,0xb8,
  35.253 +   0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x04,0xef,0xef,0xef,0xf5,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0x6a,0x6a,0x6a,0xc2,0x82,
  35.254 +   0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xef,0xef,0xef,0xf5,0x81,0x00,0x00,0x00,0xb3,0x00,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x05,0x7e,0x7e,
  35.255 +   0x7e,0xc7,0x00,0x00,0x00,0xb3,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0x33,0x33,0x33,0xb8,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,
  35.256 +   0x81,0xff,0xff,0xff,0xff,0x02,0xa0,0xa0,0xa0,0xd1,0x00,0x00,0x00,0xb3,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x03,0x52,0x52,0x52,0xbd,0xbb,0xbb,0xbb,0xdc,
  35.257 +   0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x01,0x7e,0x7e,0x7e,0xc7,0xa0,0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,0xff,0x02,0x6a,0x6a,0x6a,0xc2,
  35.258 +   0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0xb3,0xa0,0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,
  35.259 +   0x81,0x7e,0x7e,0x7e,0xc7,0x00,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x05,0x6a,0x6a,0x6a,0xc2,0x00,0x00,0x00,0xb3,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,
  35.260 +   0xf7,0xf7,0xf7,0xfa,0x33,0x33,0x33,0xb8,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x02,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,
  35.261 +   0xd2,0xd2,0xd2,0xe6,0x81,0xff,0xff,0xff,0xff,0x00,0x90,0x90,0x90,0xcc,0x81,0x00,0x00,0x00,0xb3,0x05,0x33,0x33,0x33,0xb8,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,
  35.262 +   0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xa0,0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x7e,0x7e,0x7e,0xc7,0x00,0xc7,0xc7,0xc7,0xe1,
  35.263 +   0x81,0xff,0xff,0xff,0xff,0x00,0x6a,0x6a,0x6a,0xc2,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xfd,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
  35.264 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0x01,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x87,0xff,0xff,0xff,0xff,0x02,0xbb,0xbb,0xbb,0xdc,0x00,0x00,0x00,0xb3,0x7e,
  35.265 +   0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xaf,0xaf,0xaf,0xd6,0x0a,0x33,0x33,0x33,0xb8,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xe6,
  35.266 +   0xe6,0xe6,0xf0,0x33,0x33,0x33,0xb8,0x52,0x52,0x52,0xbd,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0xef,0xef,0xef,0xf5,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,
  35.267 +   0xff,0xff,0xff,0xff,0x03,0xc7,0xc7,0xc7,0xe1,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0xa0,0xa0,0xa0,0xd1,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,
  35.268 +   0xff,0xff,0xff,0xff,0x03,0x52,0x52,0x52,0xbd,0x33,0x33,0x33,0xb8,0xaf,0xaf,0xaf,0xd6,0x33,0x33,0x33,0xb8,0x87,0x00,0x00,0x00,0xb3,0x08,0xaf,0xaf,0xaf,0xd6,0x52,
  35.269 +   0x52,0x52,0xbd,0x00,0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,0xdc,0xdc,0xdc,0xeb,0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x82,
  35.270 +   0xff,0xff,0xff,0xff,0x01,0xbb,0xbb,0xbb,0xdc,0xd2,0xd2,0xd2,0xe6,0x81,0xff,0xff,0xff,0xff,0x05,0xef,0xef,0xef,0xf5,0x00,0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,0xf7,
  35.271 +   0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xef,0xef,0xef,0xf5,0x81,0x00,0x00,0x00,0xb3,0x00,0xbb,0xbb,0xbb,0xdc,0x81,0xff,0xff,0xff,0xff,0x00,0x33,0x33,0x33,0xb8,0x85,
  35.272 +   0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x01,0x33,0x33,0x33,0xb8,0xef,0xef,0xef,0xf5,0x81,0xff,0xff,0xff,0xff,0x00,0xa0,0xa0,0xa0,
  35.273 +   0xd1,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x02,0xa0,0xa0,0xa0,0xd1,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,
  35.274 +   0xff,0xff,0x02,0xa0,0xa0,0xa0,0xd1,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xc7,0xc7,0xc7,0xe1,0x81,0x00,0x00,0x00,0xb3,0x02,0xe6,
  35.275 +   0xe6,0xe6,0xf0,0xff,0xff,0xff,0xff,0xe6,0xe6,0xe6,0xf0,0x85,0x00,0x00,0x00,0xb3,0x01,0xaf,0xaf,0xaf,0xd6,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,
  35.276 +   0xdc,0xdc,0xeb,0x81,0xaf,0xaf,0xaf,0xd6,0x01,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x02,0xef,0xef,0xef,0xf5,0xaf,0xaf,0xaf,0xd6,0xc7,
  35.277 +   0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x01,0xf7,0xf7,0xf7,0xfa,0x33,0x33,0x33,0xb8,0x86,0x00,0x00,0x00,0xb3,0x01,0x6a,0x6a,0x6a,0xc2,0xaf,0xaf,0xaf,0xd6,0x81,
  35.278 +   0x00,0x00,0x00,0xb3,0x00,0x90,0x90,0x90,0xcc,0x81,0xff,0xff,0xff,0xff,0x02,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,
  35.279 +   0x05,0xef,0xef,0xef,0xf5,0xaf,0xaf,0xaf,0xd6,0xc7,0xc7,0xc7,0xe1,0xe6,0xe6,0xe6,0xf0,0x33,0x33,0x33,0xb8,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x01,0xdc,
  35.280 +   0xdc,0xdc,0xeb,0x6a,0x6a,0x6a,0xc2,0x81,0xff,0xff,0xff,0xff,0x01,0xf7,0xf7,0xf7,0xfa,0x6a,0x6a,0x6a,0xc2,0x81,0x00,0x00,0x00,0xb3,0x82,0xff,0xff,0xff,0xff,0x01,
  35.281 +   0xd2,0xd2,0xd2,0xe6,0xbb,0xbb,0xbb,0xdc,0x82,0xff,0xff,0xff,0xff,0x02,0x52,0x52,0x52,0xbd,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x02,
  35.282 +   0xef,0xef,0xef,0xf5,0xaf,0xaf,0xaf,0xd6,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x00,0xf7,0xf7,0xf7,0xfa,0x81,0x33,0x33,0x33,0xb8,0x81,0xff,0xff,0xff,0xff,
  35.283 +   0x02,0xe6,0xe6,0xe6,0xf0,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x02,0xf7,0xf7,0xf7,0xfa,0x00,0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,0x81,
  35.284 +   0xff,0xff,0xff,0xff,0x02,0xbb,0xbb,0xbb,0xdc,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x09,0x00,0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,0xf7,
  35.285 +   0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xe6,0xe6,0xe6,0xf0,0x33,0x33,0x33,0xb8,0x52,0x52,0x52,0xbd,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0xef,0xef,0xef,0xf5,0x81,
  35.286 +   0x00,0x00,0x00,0xb3,0x00,0xbb,0xbb,0xbb,0xdc,0x81,0xff,0xff,0xff,0xff,0x03,0xef,0xef,0xef,0xf5,0xaf,0xaf,0xaf,0xd6,0xbb,0xbb,0xbb,0xdc,0xf7,0xf7,0xf7,0xfa,0x81,
  35.287 +   0xff,0xff,0xff,0xff,0x02,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0xa0,0xa0,0xa0,0xd1,0x82,0xff,0xff,0xff,0xff,0x02,0xc7,0xc7,0xc7,0xe1,0xaf,0xaf,0xaf,0xd6,0xef,
  35.288 +   0xef,0xef,0xf5,0x81,0xff,0xff,0xff,0xff,0x0a,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xe6,0xe6,0xe6,
  35.289 +   0xf0,0x33,0x33,0x33,0xb8,0x52,0x52,0x52,0xbd,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0xef,0xef,0xef,0xf5,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xfe,
  35.290 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0x01,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,
  35.291 +   0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xaf,0xaf,0xaf,0xd6,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x01,0x33,0x33,0x33,0xb8,0x7e,0x7e,0x7e,0xc7,0x81,0xff,
  35.292 +   0xff,0xff,0xff,0x00,0xe6,0xe6,0xe6,0xf0,0x82,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0xb3,0xa0,0xa0,0xa0,0xd1,0x85,0xff,0xff,0xff,0xff,0x00,0x90,0x90,0x90,0xcc,
  35.293 +   0x81,0x00,0x00,0x00,0xb3,0x00,0xe6,0xe6,0xe6,0xf0,0x84,0xff,0xff,0xff,0xff,0x02,0xa0,0xa0,0xa0,0xd1,0x00,0x00,0x00,0xb3,0x90,0x90,0x90,0xcc,0x84,0xff,0xff,0xff,
  35.294 +   0xff,0x01,0xe6,0xe6,0xe6,0xf0,0x33,0x33,0x33,0xb8,0x85,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x01,0xdc,0xdc,0xdc,0xeb,0xef,0xef,
  35.295 +   0xef,0xf5,0x81,0xff,0xff,0xff,0xff,0x02,0xa0,0xa0,0xa0,0xd1,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xf7,0xf7,0xf7,0xfa,0x83,0xff,
  35.296 +   0xff,0xff,0xff,0x02,0xc7,0xc7,0xc7,0xe1,0x00,0x00,0x00,0xb3,0xa0,0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,
  35.297 +   0x6a,0x6a,0x6a,0xc2,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x85,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x08,0x00,0x00,
  35.298 +   0x00,0xb3,0x6a,0x6a,0x6a,0xc2,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0x6a,0x6a,0x6a,0xc2,0x00,0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,0xe6,0xe6,
  35.299 +   0xe6,0xf0,0x84,0xff,0xff,0xff,0xff,0x00,0xe6,0xe6,0xe6,0xf0,0x81,0x00,0x00,0x00,0xb3,0x00,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x00,0x6a,0x6a,0x6a,0xc2,
  35.300 +   0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x6a,0x6a,0x6a,0xc2,0x84,0x00,0x00,0x00,0xb3,0x86,0xff,0xff,0xff,0xff,0x02,0x00,
  35.301 +   0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,0xe6,0xe6,0xe6,0xf0,0x85,0xff,0xff,0xff,0xff,0x00,0xa0,0xa0,0xa0,0xd1,0x86,0x00,0x00,0x00,0xb3,0x04,0x33,0x33,0x33,0xb8,0xf7,
  35.302 +   0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xef,0xef,0xef,0xf5,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x00,0xef,0xef,0xef,0xf5,0x82,0x00,0x00,0x00,0xb3,0x00,0xe6,
  35.303 +   0xe6,0xe6,0xf0,0x84,0xff,0xff,0xff,0xff,0x01,0xe6,0xe6,0xe6,0xf0,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0xa0,
  35.304 +   0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,0xff,0x02,0xe6,0xe6,0xe6,0xf0,0x33,0x33,0x33,0xb8,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xf7,0xf7,0xf7,0xfa,0x83,
  35.305 +   0xff,0xff,0xff,0xff,0x00,0xef,0xef,0xef,0xf5,0x81,0x00,0x00,0x00,0xb3,0x01,0x33,0x33,0x33,0xb8,0xe6,0xe6,0xe6,0xf0,0x85,0xff,0xff,0xff,0xff,0x02,0xa0,0xa0,0xa0,
  35.306 +   0xd1,0x00,0x00,0x00,0xb3,0xa0,0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x82,0xff,0xff,0xff,0xff,0x00,0xd2,0xd2,
  35.307 +   0xd2,0xe6,0x81,0x00,0x00,0x00,0xb3,0x04,0xe6,0xe6,0xe6,0xf0,0xff,0xff,0xff,0xff,0xef,0xef,0xef,0xf5,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,
  35.308 +   0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0xa0,0xa0,0xa0,0xd1,0x85,0xff,0xff,0xff,0xff,0x00,0x90,0x90,0x90,0xcc,0x81,0x00,0x00,0x00,0xb3,0x01,0x33,0x33,0x33,0xb8,0xf7,
  35.309 +   0xf7,0xf7,0xfa,0x86,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x00,0xe6,0xe6,0xe6,0xf0,0x83,0xff,0xff,0xff,0xff,0x00,0xf7,0xf7,0xf7,
  35.310 +   0xfa,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0xa0,0xa0,0xa0,0xd1,0x85,0xff,0xff,0xff,0xff,0x00,0x90,0x90,0x90,0xcc,0xff,
  35.311 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xfe,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0x01,0x00,0x00,
  35.312 +   0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,0x00,0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,0x01,
  35.313 +   0x7e,0x7e,0x7e,0xc7,0x6a,0x6a,0x6a,0xc2,0x81,0xdc,0xdc,0xdc,0xeb,0x03,0xa0,0xa0,0xa0,0xd1,0xaf,0xaf,0xaf,0xd6,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0x81,0x00,
  35.314 +   0x00,0x00,0xb3,0x01,0x7e,0x7e,0x7e,0xc7,0xd2,0xd2,0xd2,0xe6,0x81,0xff,0xff,0xff,0xff,0x01,0xe6,0xe6,0xe6,0xf0,0x90,0x90,0x90,0xcc,0x82,0x00,0x00,0x00,0xb3,0x06,
  35.315 +   0x33,0x33,0x33,0xb8,0xc7,0xc7,0xc7,0xe1,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0xc7,0xc7,0xc7,0xe1,0x52,0x52,0x52,0xbd,0x81,0x00,0x00,0x00,
  35.316 +   0xb3,0x01,0x90,0x90,0x90,0xcc,0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,0x01,0xe6,0xe6,0xe6,0xf0,0xa0,0xa0,0xa0,0xd1,0x86,0x00,0x00,0x00,0xb3,0x02,0x33,0x33,
  35.317 +   0x33,0xb8,0xaf,0xaf,0xaf,0xd6,0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,0x01,0xe6,0xe6,0xe6,0xf0,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0x6a,0x6a,
  35.318 +   0x6a,0xc2,0x81,0xdc,0xdc,0xdc,0xeb,0x01,0xa0,0xa0,0xa0,0xd1,0xbb,0xbb,0xbb,0xdc,0x81,0xff,0xff,0xff,0xff,0x03,0xc7,0xc7,0xc7,0xe1,0x33,0x33,0x33,0xb8,0x00,0x00,
  35.319 +   0x00,0xb3,0xc7,0xc7,0xc7,0xe1,0x81,0xdc,0xdc,0xdc,0xeb,0x00,0x33,0x33,0x33,0xb8,0x82,0x00,0x00,0x00,0xb3,0x02,0xd2,0xd2,0xd2,0xe6,0xdc,0xdc,0xdc,0xeb,0xc7,0xc7,
  35.320 +   0xc7,0xe1,0x85,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0x6a,0x6a,0x6a,0xc2,0x81,0xdc,0xdc,0xdc,0xeb,
  35.321 +   0x0b,0xd2,0xd2,0xd2,0xe6,0x33,0x33,0x33,0xb8,0x00,0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,0xaf,0xaf,0xaf,0xd6,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,
  35.322 +   0xfa,0xc7,0xc7,0xc7,0xe1,0x33,0x33,0x33,0xb8,0x00,0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,0x81,0xdc,0xdc,0xdc,0xeb,0x00,0xc7,0xc7,0xc7,0xe1,0x82,0x00,0x00,0x00,0xb3,
  35.323 +   0x00,0x52,0x52,0x52,0xbd,0x81,0xdc,0xdc,0xdc,0xeb,0x00,0xaf,0xaf,0xaf,0xd6,0x84,0x00,0x00,0x00,0xb3,0x01,0xdc,0xdc,0xdc,0xeb,0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,
  35.324 +   0xff,0xff,0x00,0xef,0xef,0xef,0xf5,0x81,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x02,0x33,0x33,0x33,0xb8,0xaf,0xaf,0xaf,0xd6,0xef,0xef,0xef,0xf5,0x81,0xff,
  35.325 +   0xff,0xff,0xff,0x01,0xd2,0xd2,0xd2,0xe6,0x7e,0x7e,0x7e,0xc7,0x88,0x00,0x00,0x00,0xb3,0x06,0x7e,0x7e,0x7e,0xc7,0xd2,0xd2,0xd2,0xe6,0xf7,0xf7,0xf7,0xfa,0xff,0xff,
  35.326 +   0xff,0xff,0xf7,0xf7,0xf7,0xfa,0xd2,0xd2,0xd2,0xe6,0x52,0x52,0x52,0xbd,0x83,0x00,0x00,0x00,0xb3,0x01,0xaf,0xaf,0xaf,0xd6,0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,
  35.327 +   0xff,0x02,0xd2,0xd2,0xd2,0xe6,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x00,0xa0,0xa0,
  35.328 +   0xa0,0xd1,0x81,0xdc,0xdc,0xdc,0xeb,0x01,0xbb,0xbb,0xbb,0xdc,0x00,0x00,0x00,0xb3,0x81,0xdc,0xdc,0xdc,0xeb,0x05,0xbb,0xbb,0xbb,0xdc,0xa0,0xa0,0xa0,0xd1,0xf7,0xf7,
  35.329 +   0xf7,0xfa,0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,0xeb,0x6a,0x6a,0x6a,0xc2,0x82,0x00,0x00,0x00,0xb3,0x02,0x33,0x33,0x33,0xb8,0xaf,0xaf,0xaf,0xd6,0xef,0xef,0xef,0xf5,
  35.330 +   0x81,0xff,0xff,0xff,0xff,0x01,0xd2,0xd2,0xd2,0xe6,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xdc,0xdc,0xdc,0xeb,0x00,0x52,0x52,
  35.331 +   0x52,0xbd,0x81,0x00,0x00,0x00,0xb3,0x00,0xbb,0xbb,0xbb,0xdc,0x81,0xdc,0xdc,0xdc,0xeb,0x00,0x90,0x90,0x90,0xcc,0x81,0x00,0x00,0x00,0xb3,0x00,0xa0,0xa0,0xa0,0xd1,
  35.332 +   0x81,0xdc,0xdc,0xdc,0xeb,0x01,0x52,0x52,0x52,0xbd,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x82,0x00,0x00,0x00,0xb3,0x01,0x7e,0x7e,0x7e,0xc7,0xd2,0xd2,0xd2,
  35.333 +   0xe6,0x81,0xff,0xff,0xff,0xff,0x01,0xe6,0xe6,0xe6,0xf0,0x90,0x90,0x90,0xcc,0x83,0x00,0x00,0x00,0xb3,0x01,0x6a,0x6a,0x6a,0xc2,0xd2,0xd2,0xd2,0xe6,0x81,0xff,0xff,
  35.334 +   0xff,0xff,0x01,0xc7,0xc7,0xc7,0xe1,0xbb,0xbb,0xbb,0xdc,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x01,0x33,0x33,0x33,0xb8,0xc7,
  35.335 +   0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x01,0xd2,0xd2,0xd2,0xe6,0x6a,0x6a,0x6a,0xc2,0x81,0xdc,0xdc,0xdc,0xeb,0x00,0xa0,0xa0,0xa0,0xd1,0x82,0x00,0x00,0x00,0xb3,
  35.336 +   0x01,0x7e,0x7e,0x7e,0xc7,0xd2,0xd2,0xd2,0xe6,0x81,0xff,0xff,0xff,0xff,0x01,0xe6,0xe6,0xe6,0xf0,0x90,0x90,0x90,0xcc,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
  35.337 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0x01,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,
  35.338 +   0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x01,0x33,0x33,0x33,0xb8,0xef,0xef,0xef,0xf5,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,
  35.339 +   0xca,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0xa0,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,
  35.340 +   0xaf,0xaf,0xd6,0xa5,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0xaa,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,
  35.341 +   0xff,0x91,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
  35.342 +   0x00,0x00,0x00,0xb3,0x93,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0x01,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,
  35.343 +   0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xef,0xef,0xef,0xf5,0x81,0xdc,0xdc,0xdc,0xeb,0x00,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x00,0xf7,0xf7,0xf7,0xfa,0xcb,
  35.344 +   0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0xa0,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,
  35.345 +   0xaf,0xd6,0xa5,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0xaa,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,
  35.346 +   0x91,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
  35.347 +   0x00,0x00,0xb3,0x93,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0x01,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,
  35.348 +   0x87,0xff,0xff,0xff,0xff,0x00,0xa0,0xa0,0xa0,0xd1,0xcb,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0xa0,0x00,0x00,0x00,0xb3,0x00,0x33,
  35.349 +   0x33,0x33,0xb8,0x81,0x7e,0x7e,0x7e,0xc7,0x00,0x52,0x52,0x52,0xbd,0xa5,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0xaa,0x00,0x00,0x00,
  35.350 +   0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x91,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0xff,
  35.351 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0x93,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
  35.352 +   0x00,0xb3,0x01,0x00,0x00,0x00,0xb3,0x6a,0x6a,0x6a,0xc2,0x85,0xdc,0xdc,0xdc,0xeb,0x01,0xaf,0xaf,0xaf,0xd6,0x52,0x52,0x52,0xbd,0xcc,0x00,0x00,0x00,0xb3,0x00,0xdc,
  35.353 +   0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0xca,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0xaa,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,
  35.354 +   0xeb,0x81,0xff,0xff,0xff,0xff,0x91,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0xff,0x00,0x00,0x00,0xb3,0xff,
  35.355 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0x93,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xd6,0x00,0x00,
  35.356 +   0x00,0xb3,0x00,0xa0,0xa0,0xa0,0xd1,0x81,0xaf,0xaf,0xaf,0xd6,0xca,0x00,0x00,0x00,0xb3,0x81,0xaf,0xaf,0xaf,0xd6,0x00,0xa0,0xa0,0xa0,0xd1,0xaa,0x00,0x00,0x00,0xb3,
  35.357 +   0x00,0xa0,0xa0,0xa0,0xd1,0x81,0xaf,0xaf,0xaf,0xd6,0x91,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xaf,0xaf,0xaf,0xd6,0x00,0x52,0x52,0x52,0xbd,0xff,0x00,
  35.358 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0x93,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
  35.359 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
  35.360 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
  35.361 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
  35.362 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
  35.363 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
  35.364 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
  35.365 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
  35.366 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
  35.367 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
  35.368 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
  35.369 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
  35.370 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
  35.371 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
  35.372 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
  35.373 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
  35.374 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
  35.375 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
  35.376 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
  35.377 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
  35.378 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
  35.379 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
  35.380 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0x8f,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb4,0xf1,0x00,0x00,0x00,0xb4,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
  35.381 +   0x00,0xb3,0xfd,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xd6,0x00,0x00,0x00,0xb3,0xc3,0x00,0x00,0x00,0xb4,0xff,0x01,0x00,0x00,0xb4,
  35.382 +   0xdb,0x01,0x00,0x00,0xb4,0xc3,0x00,0x00,0x00,0xb4,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xc4,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
  35.383 +   0x00,0x00,0xb3,0xb5,0x00,0x00,0x00,0xb3,0x82,0x00,0x00,0x00,0xb4,0x8b,0x00,0x00,0x00,0xb3,0x97,0x00,0x00,0x00,0xb4,0x92,0x01,0x00,0x00,0xb4,0x91,0x01,0x00,0x00,
  35.384 +   0xb5,0x8c,0x01,0x01,0x00,0xb5,0xff,0x01,0x01,0x01,0xb6,0xf3,0x01,0x01,0x01,0xb6,0x8c,0x01,0x01,0x00,0xb5,0x91,0x01,0x00,0x00,0xb5,0x92,0x01,0x00,0x00,0xb4,0x97,
  35.385 +   0x00,0x00,0x00,0xb4,0x8b,0x00,0x00,0x00,0xb3,0x82,0x00,0x00,0x00,0xb4,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xa3,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
  35.386 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xa8,0x00,0x00,0x00,0xb3,0x9b,0x00,0x00,0x00,0xb4,0x8e,0x01,0x00,0x00,0xb4,0x88,0x01,0x00,0x00,0xb5,0x81,0x01,0x01,0x00,0xb5,
  35.387 +   0x8f,0x01,0x01,0x01,0xb6,0x00,0x01,0x01,0x01,0xb7,0x8b,0x02,0x01,0x01,0xb7,0xa8,0x02,0x01,0x01,0xb8,0x00,0x02,0x02,0x01,0xb9,0x81,0x03,0x02,0x01,0xb9,0x82,0x02,
  35.388 +   0x02,0x01,0xb9,0x82,0x03,0x02,0x01,0xb9,0x83,0x02,0x02,0x01,0xb9,0x00,0x03,0x02,0x01,0xb9,0x81,0x02,0x02,0x01,0xb9,0x00,0x03,0x02,0x01,0xb9,0x81,0x02,0x02,0x01,
  35.389 +   0xb9,0x00,0x03,0x02,0x01,0xb9,0x85,0x02,0x02,0x01,0xb9,0x02,0x03,0x02,0x01,0xb9,0x02,0x02,0x01,0xb9,0x03,0x02,0x01,0xb9,0x82,0x02,0x02,0x01,0xb9,0x00,0x03,0x02,
  35.390 +   0x01,0xb9,0x82,0x02,0x02,0x01,0xb9,0x81,0x03,0x02,0x01,0xb9,0x81,0x02,0x02,0x01,0xb9,0x04,0x03,0x02,0x01,0xb9,0x02,0x02,0x01,0xb9,0x03,0x02,0x01,0xb9,0x02,0x02,
  35.391 +   0x01,0xb9,0x03,0x02,0x01,0xb9,0x84,0x02,0x02,0x01,0xb9,0x00,0x03,0x02,0x01,0xb9,0x81,0x02,0x02,0x01,0xb9,0x00,0x03,0x02,0x01,0xb9,0x83,0x02,0x02,0x01,0xb9,0x00,
  35.392 +   0x03,0x02,0x01,0xb9,0x85,0x02,0x02,0x01,0xb9,0x81,0x03,0x02,0x01,0xb9,0x82,0x02,0x02,0x01,0xb9,0x00,0x03,0x02,0x01,0xb9,0x83,0x02,0x02,0x01,0xb9,0x00,0x03,0x02,
  35.393 +   0x01,0xb9,0x81,0x02,0x02,0x01,0xb9,0x81,0x03,0x02,0x01,0xb9,0x02,0x02,0x02,0x01,0xb9,0x03,0x02,0x01,0xb9,0x02,0x02,0x01,0xb9,0x81,0x03,0x02,0x01,0xb9,0x81,0x02,
  35.394 +   0x02,0x01,0xb9,0x00,0x03,0x02,0x01,0xb9,0x81,0x02,0x02,0x01,0xb9,0x00,0x03,0x02,0x01,0xb9,0x8d,0x02,0x02,0x01,0xb9,0x01,0x03,0x02,0x01,0xb9,0x02,0x02,0x01,0xb9,
  35.395 +   0x81,0x03,0x02,0x01,0xb9,0x81,0x02,0x02,0x01,0xb9,0x00,0x03,0x02,0x01,0xb9,0x82,0x02,0x02,0x01,0xb9,0x00,0x03,0x02,0x01,0xb9,0x87,0x02,0x02,0x01,0xb9,0x81,0x03,
  35.396 +   0x02,0x01,0xb9,0x81,0x02,0x02,0x01,0xb9,0x00,0x03,0x02,0x01,0xb9,0x83,0x02,0x02,0x01,0xb9,0x00,0x03,0x02,0x01,0xb9,0x87,0x02,0x02,0x01,0xb9,0x00,0x03,0x02,0x01,
  35.397 +   0xb9,0x85,0x02,0x02,0x01,0xb9,0x00,0x03,0x02,0x01,0xb9,0x81,0x02,0x02,0x01,0xb9,0x00,0x03,0x02,0x01,0xb9,0x85,0x02,0x02,0x01,0xb9,0x00,0x03,0x02,0x01,0xb9,0x84,
  35.398 +   0x02,0x02,0x01,0xb9,0x82,0x03,0x02,0x01,0xb9,0x81,0x02,0x02,0x01,0xb9,0x00,0x03,0x02,0x01,0xb9,0x82,0x02,0x02,0x01,0xb9,0x01,0x03,0x02,0x01,0xb9,0x02,0x02,0x01,
  35.399 +   0xb9,0x82,0x03,0x02,0x01,0xb9,0x83,0x02,0x02,0x01,0xb9,0x00,0x03,0x02,0x01,0xb9,0x8b,0x02,0x02,0x01,0xb9,0x00,0x03,0x02,0x01,0xb9,0x82,0x02,0x02,0x01,0xb9,0x8d,
  35.400 +   0x02,0x01,0x01,0xb8,0x00,0x02,0x02,0x01,0xb8,0x90,0x02,0x01,0x01,0xb8,0x00,0x02,0x02,0x01,0xb8,0x87,0x02,0x01,0x01,0xb8,0x8b,0x02,0x01,0x01,0xb7,0x00,0x01,0x01,
  35.401 +   0x01,0xb7,0x8f,0x01,0x01,0x01,0xb6,0x81,0x01,0x01,0x00,0xb5,0x88,0x01,0x00,0x00,0xb5,0x8e,0x01,0x00,0x00,0xb4,0x9b,0x00,0x00,0x00,0xb4,0xff,0x00,0x00,0x00,0xb3,
  35.402 +   0xff,0x00,0x00,0x00,0xb3,0x96,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xa6,0x00,0x00,0x00,0xb3,0x91,0x00,0x00,0x00,0xb4,0x87,0x01,
  35.403 +   0x00,0x00,0xb4,0x85,0x01,0x00,0x00,0xb5,0x88,0x01,0x01,0x00,0xb5,0x86,0x01,0x01,0x01,0xb6,0x81,0x01,0x01,0x01,0xb7,0x86,0x02,0x01,0x01,0xb7,0x83,0x02,0x01,0x01,
  35.404 +   0xb8,0x00,0x02,0x02,0x01,0xb8,0x86,0x02,0x01,0x01,0xb8,0x83,0x02,0x02,0x01,0xb9,0x81,0x03,0x02,0x01,0xb9,0x89,0x03,0x02,0x01,0xba,0x82,0x03,0x02,0x02,0xbb,0x00,
  35.405 +   0x03,0x02,0x01,0xbb,0x8c,0x03,0x02,0x02,0xbb,0x00,0x03,0x02,0x02,0xbc,0x8d,0x04,0x02,0x02,0xbc,0xff,0x04,0x03,0x02,0xbd,0xd9,0x04,0x03,0x02,0xbd,0x85,0x04,0x02,
  35.406 +   0x02,0xbc,0x00,0x04,0x03,0x02,0xbc,0x86,0x04,0x02,0x02,0xbc,0x00,0x03,0x02,0x02,0xbc,0x87,0x03,0x02,0x02,0xbb,0x00,0x03,0x02,0x01,0xbb,0x87,0x03,0x02,0x02,0xbb,
  35.407 +   0x89,0x03,0x02,0x01,0xba,0x00,0x03,0x02,0x01,0xb9,0x84,0x02,0x02,0x01,0xb9,0x8b,0x02,0x01,0x01,0xb8,0x86,0x02,0x01,0x01,0xb7,0x81,0x01,0x01,0x01,0xb7,0x86,0x01,
  35.408 +   0x01,0x01,0xb6,0x88,0x01,0x01,0x00,0xb5,0x85,0x01,0x00,0x00,0xb5,0x87,0x01,0x00,0x00,0xb4,0x91,0x00,0x00,0x00,0xb4,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
  35.409 +   0xb3,0x94,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0x9d,0x00,0x00,0x00,0xb3,0x92,0x00,0x00,0x00,0xb4,0x88,0x01,0x00,0x00,0xb4,0x84,
  35.410 +   0x01,0x00,0x00,0xb5,0x86,0x01,0x01,0x00,0xb5,0x83,0x01,0x01,0x01,0xb6,0x01,0x02,0x01,0x01,0xb7,0x01,0x01,0x01,0xb7,0x85,0x02,0x01,0x01,0xb7,0x86,0x02,0x01,0x01,
  35.411 +   0xb8,0x82,0x02,0x02,0x01,0xb9,0x82,0x03,0x02,0x01,0xb9,0x83,0x03,0x02,0x01,0xba,0x00,0x03,0x02,0x01,0xbb,0x82,0x03,0x02,0x02,0xbb,0x00,0x03,0x02,0x01,0xbb,0x83,
  35.412 +   0x03,0x02,0x02,0xbb,0x81,0x03,0x02,0x02,0xbc,0x01,0x04,0x02,0x02,0xbc,0x03,0x02,0x02,0xbc,0x84,0x04,0x02,0x02,0xbc,0x88,0x04,0x03,0x02,0xbd,0x01,0x04,0x03,0x02,
  35.413 +   0xbe,0x05,0x03,0x02,0xbe,0x85,0x04,0x03,0x02,0xbe,0x00,0x04,0x03,0x02,0xbf,0x85,0x05,0x03,0x02,0xbf,0x85,0x05,0x03,0x02,0xc0,0x00,0x05,0x04,0x01,0xc0,0x81,0x05,
  35.414 +   0x03,0x02,0xc0,0x00,0x05,0x03,0x03,0xc0,0x8d,0x05,0x04,0x03,0xc0,0x00,0x06,0x04,0x03,0xc1,0x83,0x05,0x04,0x03,0xc1,0x02,0x06,0x04,0x03,0xc1,0x05,0x04,0x03,0xc1,
  35.415 +   0x05,0x04,0x01,0xc1,0x81,0x05,0x04,0x03,0xc1,0x81,0x06,0x04,0x03,0xc1,0x05,0x05,0x04,0x03,0xc1,0x06,0x04,0x03,0xc1,0x05,0x04,0x03,0xc1,0x06,0x04,0x03,0xc1,0x05,
  35.416 +   0x04,0x03,0xc1,0x06,0x04,0x03,0xc1,0x82,0x05,0x04,0x03,0xc1,0x00,0x05,0x04,0x01,0xc1,0x81,0x05,0x04,0x03,0xc1,0x00,0x06,0x04,0x03,0xc1,0x83,0x05,0x04,0x03,0xc1,
  35.417 +   0x00,0x06,0x04,0x03,0xc1,0x83,0x05,0x04,0x03,0xc1,0x00,0x05,0x04,0x01,0xc1,0x81,0x05,0x04,0x03,0xc1,0x00,0x06,0x04,0x03,0xc1,0x81,0x05,0x04,0x03,0xc1,0x02,0x06,
  35.418 +   0x04,0x03,0xc1,0x05,0x04,0x03,0xc1,0x06,0x04,0x03,0xc1,0x81,0x05,0x04,0x03,0xc1,0x02,0x06,0x04,0x03,0xc1,0x05,0x04,0x03,0xc1,0x06,0x04,0x03,0xc1,0x82,0x05,0x04,
  35.419 +   0x03,0xc1,0x00,0x06,0x04,0x03,0xc1,0x82,0x05,0x04,0x03,0xc1,0xd9,0x06,0x04,0x03,0xc2,0x05,0x05,0x04,0x03,0xc1,0x06,0x04,0x03,0xc1,0x05,0x04,0x03,0xc1,0x06,0x04,
  35.420 +   0x03,0xc1,0x05,0x04,0x03,0xc1,0x06,0x04,0x03,0xc1,0x83,0x05,0x04,0x03,0xc1,0x02,0x06,0x04,0x03,0xc1,0x05,0x04,0x03,0xc1,0x06,0x04,0x03,0xc1,0x81,0x05,0x04,0x03,
  35.421 +   0xc1,0x00,0x06,0x04,0x03,0xc1,0x81,0x05,0x04,0x03,0xc1,0x00,0x06,0x04,0x03,0xc1,0x82,0x05,0x04,0x03,0xc1,0x00,0x06,0x04,0x03,0xc1,0x82,0x05,0x04,0x03,0xc1,0x01,
  35.422 +   0x05,0x04,0x01,0xc1,0x05,0x04,0x03,0xc1,0x82,0x06,0x04,0x03,0xc1,0x00,0x05,0x04,0x03,0xc1,0x81,0x06,0x04,0x03,0xc1,0x03,0x05,0x04,0x03,0xc1,0x06,0x04,0x03,0xc1,
  35.423 +   0x05,0x04,0x03,0xc1,0x06,0x04,0x03,0xc1,0x85,0x05,0x04,0x03,0xc1,0x00,0x05,0x04,0x01,0xc1,0x81,0x05,0x04,0x03,0xc1,0x01,0x06,0x04,0x03,0xc1,0x05,0x04,0x03,0xc1,
  35.424 +   0x81,0x06,0x04,0x03,0xc1,0x81,0x05,0x04,0x03,0xc1,0x81,0x06,0x04,0x03,0xc1,0x8d,0x05,0x04,0x03,0xc0,0x00,0x05,0x03,0x03,0xc0,0x81,0x05,0x03,0x02,0xc0,0x00,0x05,
  35.425 +   0x04,0x01,0xc0,0x85,0x05,0x03,0x02,0xc0,0x85,0x05,0x03,0x02,0xbf,0x00,0x04,0x03,0x02,0xbf,0x81,0x04,0x03,0x02,0xbe,0x82,0x05,0x03,0x02,0xbe,0x02,0x04,0x03,0x02,
  35.426 +   0xbe,0x05,0x03,0x02,0xbe,0x04,0x03,0x02,0xbe,0x88,0x04,0x03,0x02,0xbd,0x84,0x04,0x02,0x02,0xbc,0x82,0x03,0x02,0x02,0xbc,0x00,0x04,0x02,0x02,0xbc,0x88,0x03,0x02,
  35.427 +   0x02,0xbb,0x83,0x03,0x02,0x01,0xba,0x82,0x03,0x02,0x01,0xb9,0x82,0x02,0x02,0x01,0xb9,0x86,0x02,0x01,0x01,0xb8,0x85,0x02,0x01,0x01,0xb7,0x81,0x01,0x01,0x01,0xb7,
  35.428 +   0x83,0x01,0x01,0x01,0xb6,0x86,0x01,0x01,0x00,0xb5,0x84,0x01,0x00,0x00,0xb5,0x88,0x01,0x00,0x00,0xb4,0x92,0x00,0x00,0x00,0xb4,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
  35.429 +   0x00,0x00,0xb3,0x8b,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0x9b,0x00,0x00,0x00,0xb3,0x91,0x00,0x00,0x00,0xb4,0x87,0x01,0x00,0x00,
  35.430 +   0xb4,0x82,0x01,0x00,0x00,0xb5,0x81,0x01,0x01,0x00,0xb5,0x89,0x01,0x01,0x01,0xb6,0x81,0x02,0x01,0x01,0xb7,0x8a,0x02,0x01,0x01,0xb8,0x81,0x02,0x02,0x01,0xb9,0x81,
  35.431 +   0x03,0x02,0x01,0xb9,0x84,0x03,0x02,0x01,0xba,0x83,0x03,0x02,0x02,0xbb,0x00,0x03,0x02,0x02,0xbc,0x85,0x04,0x02,0x02,0xbc,0x84,0x04,0x03,0x02,0xbd,0x01,0x04,0x03,
  35.432 +   0x02,0xbe,0x05,0x03,0x02,0xbe,0x81,0x04,0x03,0x02,0xbe,0x81,0x05,0x03,0x02,0xbe,0x82,0x04,0x03,0x02,0xbe,0x00,0x04,0x03,0x02,0xbf,0x81,0x05,0x03,0x02,0xbf,0x82,
  35.433 +   0x05,0x03,0x02,0xc0,0x00,0x05,0x04,0x03,0xc0,0x81,0x05,0x04,0x03,0xc1,0x02,0x06,0x04,0x03,0xc1,0x05,0x04,0x03,0xc1,0x06,0x04,0x03,0xc1,0x85,0x05,0x04,0x03,0xc1,
  35.434 +   0x87,0x06,0x04,0x03,0xc2,0x86,0x06,0x04,0x03,0xc3,0x86,0x06,0x04,0x03,0xc4,0x81,0x07,0x04,0x03,0xc5,0x97,0x07,0x05,0x02,0xc5,0xa4,0x07,0x05,0x02,0xc6,0x8b,0x07,
  35.435 +   0x05,0x04,0xc6,0x00,0x07,0x05,0x02,0xc6,0x96,0x07,0x05,0x04,0xc6,0x00,0x07,0x05,0x02,0xc6,0x98,0x07,0x05,0x04,0xc6,0x00,0x07,0x05,0x02,0xc6,0x8b,0x07,0x05,0x04,
  35.436 +   0xc6,0x00,0x07,0x05,0x02,0xc6,0x88,0x07,0x05,0x04,0xc6,0x00,0x07,0x05,0x02,0xc6,0x85,0x07,0x05,0x04,0xc6,0xa4,0x07,0x05,0x02,0xc6,0x98,0x07,0x05,0x02,0xc5,0x00,
  35.437 +   0x07,0x04,0x03,0xc5,0x81,0x06,0x04,0x03,0xc4,0x81,0x07,0x04,0x03,0xc4,0x82,0x06,0x04,0x03,0xc4,0x86,0x06,0x04,0x03,0xc3,0x87,0x06,0x04,0x03,0xc2,0x82,0x06,0x04,
  35.438 +   0x03,0xc1,0x01,0x05,0x04,0x03,0xc1,0x06,0x04,0x03,0xc1,0x81,0x05,0x04,0x03,0xc1,0x00,0x05,0x04,0x01,0xc1,0x82,0x05,0x04,0x03,0xc1,0x01,0x05,0x04,0x03,0xc0,0x05,
  35.439 +   0x03,0x03,0xc0,0x81,0x05,0x03,0x02,0xc0,0x82,0x05,0x03,0x02,0xbf,0x00,0x05,0x03,0x02,0xbe,0x85,0x04,0x03,0x02,0xbe,0x01,0x05,0x03,0x02,0xbe,0x04,0x03,0x02,0xbe,
  35.440 +   0x84,0x04,0x03,0x02,0xbd,0x82,0x04,0x02,0x02,0xbc,0x00,0x04,0x03,0x02,0xbc,0x82,0x04,0x02,0x02,0xbc,0x83,0x03,0x02,0x02,0xbb,0x84,0x03,0x02,0x01,0xba,0x82,0x03,
  35.441 +   0x02,0x01,0xb9,0x00,0x02,0x02,0x01,0xb9,0x8a,0x02,0x01,0x01,0xb8,0x81,0x02,0x01,0x01,0xb7,0x89,0x01,0x01,0x01,0xb6,0x81,0x01,0x01,0x00,0xb5,0x82,0x01,0x00,0x00,
  35.442 +   0xb5,0x87,0x01,0x00,0x00,0xb4,0x91,0x00,0x00,0x00,0xb4,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0x89,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
  35.443 +   0x00,0x00,0x00,0xb3,0x99,0x00,0x00,0x00,0xb3,0x91,0x00,0x00,0x00,0xb4,0x81,0x01,0x00,0x00,0xb4,0x87,0x01,0x00,0x00,0xb5,0x82,0x01,0x01,0x00,0xb5,0x83,0x01,0x01,
  35.444 +   0x01,0xb6,0x03,0x02,0x01,0x01,0xb7,0x01,0x01,0x01,0xb7,0x02,0x01,0x01,0xb7,0x01,0x01,0x01,0xb7,0x83,0x02,0x01,0x01,0xb7,0x82,0x02,0x01,0x01,0xb8,0x85,0x02,0x02,
  35.445 +   0x01,0xb9,0x85,0x03,0x02,0x01,0xba,0x82,0x03,0x02,0x02,0xbb,0x83,0x03,0x02,0x02,0xbc,0x82,0x04,0x02,0x02,0xbc,0x85,0x04,0x03,0x02,0xbd,0x81,0x04,0x03,0x02,0xbe,
  35.446 +   0x83,0x04,0x03,0x02,0xbf,0x00,0x05,0x03,0x02,0xbf,0x81,0x05,0x03,0x02,0xc0,0x01,0x05,0x03,0x03,0xc0,0x05,0x04,0x03,0xc0,0x86,0x05,0x04,0x03,0xc1,0x83,0x06,0x04,
  35.447 +   0x03,0xc2,0x81,0x06,0x04,0x03,0xc3,0x00,0x06,0x05,0x02,0xc3,0x83,0x06,0x04,0x03,0xc3,0x82,0x06,0x04,0x03,0xc4,0x81,0x07,0x04,0x03,0xc5,0x89,0x07,0x05,0x02,0xc5,
  35.448 +   0x04,0x07,0x05,0x02,0xc6,0x07,0x05,0x04,0xc6,0x07,0x05,0x02,0xc6,0x07,0x05,0x02,0xc7,0x07,0x05,0x04,0xc7,0x82,0x08,0x05,0x04,0xc7,0x00,0x08,0x05,0x02,0xc7,0x86,
  35.449 +   0x08,0x05,0x04,0xc7,0x86,0x08,0x05,0x04,0xc8,0x00,0x08,0x05,0x02,0xc8,0x8f,0x08,0x05,0x04,0xc8,0x81,0x08,0x05,0x04,0xc9,0xff,0x08,0x06,0x03,0xc9,0x9d,0x08,0x06,
  35.450 +   0x03,0xc9,0x81,0x08,0x05,0x04,0xc9,0x84,0x08,0x05,0x04,0xc8,0x00,0x08,0x06,0x03,0xc8,0x91,0x08,0x05,0x04,0xc8,0x89,0x08,0x05,0x04,0xc7,0x82,0x07,0x05,0x04,0xc7,
  35.451 +   0x02,0x07,0x05,0x02,0xc6,0x07,0x05,0x04,0xc6,0x07,0x05,0x02,0xc6,0x89,0x07,0x05,0x02,0xc5,0x81,0x07,0x04,0x03,0xc5,0x82,0x06,0x04,0x03,0xc4,0x86,0x06,0x04,0x03,
  35.452 +   0xc3,0x83,0x06,0x04,0x03,0xc2,0x00,0x05,0x04,0x03,0xc1,0x81,0x06,0x04,0x03,0xc1,0x01,0x05,0x04,0x03,0xc1,0x06,0x04,0x03,0xc1,0x81,0x05,0x04,0x03,0xc1,0x01,0x05,
  35.453 +   0x04,0x03,0xc0,0x05,0x03,0x03,0xc0,0x81,0x05,0x03,0x02,0xc0,0x83,0x05,0x03,0x02,0xbf,0x00,0x04,0x03,0x02,0xbf,0x81,0x04,0x03,0x02,0xbe,0x85,0x04,0x03,0x02,0xbd,
  35.454 +   0x82,0x04,0x02,0x02,0xbc,0x81,0x03,0x02,0x02,0xbc,0x01,0x04,0x02,0x02,0xbc,0x03,0x02,0x02,0xbc,0x82,0x03,0x02,0x02,0xbb,0x85,0x03,0x02,0x01,0xba,0x85,0x02,0x02,
  35.455 +   0x01,0xb9,0x82,0x02,0x01,0x01,0xb8,0x84,0x02,0x01,0x01,0xb7,0x82,0x01,0x01,0x01,0xb7,0x83,0x01,0x01,0x01,0xb6,0x82,0x01,0x01,0x00,0xb5,0x87,0x01,0x00,0x00,0xb5,
  35.456 +   0x81,0x01,0x00,0x00,0xb4,0x91,0x00,0x00,0x00,0xb4,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0x87,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
  35.457 +   0x00,0x00,0xb3,0x99,0x00,0x00,0x00,0xb3,0x8d,0x00,0x00,0x00,0xb4,0x85,0x01,0x00,0x00,0xb4,0x87,0x01,0x00,0x00,0xb5,0x00,0x01,0x01,0x00,0xb5,0x87,0x01,0x01,0x01,
  35.458 +   0xb6,0x00,0x01,0x01,0x01,0xb7,0x82,0x02,0x01,0x01,0xb7,0x83,0x02,0x01,0x01,0xb8,0x00,0x02,0x02,0x01,0xb9,0x84,0x03,0x02,0x01,0xb9,0x84,0x03,0x02,0x01,0xba,0x02,
  35.459 +   0x03,0x02,0x02,0xbb,0x03,0x02,0x01,0xbb,0x03,0x02,0x02,0xbb,0x81,0x04,0x02,0x02,0xbc,0x01,0x04,0x03,0x02,0xbc,0x04,0x02,0x02,0xbc,0x85,0x04,0x03,0x02,0xbd,0x02,
  35.460 +   0x04,0x03,0x02,0xbe,0x05,0x03,0x02,0xbe,0x04,0x03,0x02,0xbf,0x83,0x05,0x03,0x02,0xbf,0x81,0x05,0x03,0x02,0xc0,0x81,0x05,0x03,0x03,0xc0,0x81,0x05,0x04,0x03,0xc0,
  35.461 +   0x81,0x05,0x04,0x03,0xc1,0x86,0x06,0x04,0x03,0xc2,0x81,0x06,0x04,0x03,0xc3,0x00,0x07,0x04,0x03,0xc4,0x81,0x06,0x04,0x03,0xc4,0x81,0x07,0x04,0x03,0xc4,0x82,0x06,
  35.462 +   0x04,0x03,0xc4,0x00,0x07,0x04,0x03,0xc5,0x84,0x07,0x05,0x02,0xc5,0x81,0x07,0x05,0x04,0xc6,0x02,0x07,0x05,0x04,0xc7,0x08,0x05,0x04,0xc7,0x07,0x05,0x02,0xc7,0x81,
  35.463 +   0x08,0x05,0x04,0xc7,0x81,0x07,0x05,0x04,0xc7,0x82,0x08,0x05,0x04,0xc7,0x87,0x08,0x05,0x04,0xc8,0x00,0x08,0x05,0x04,0xc9,0x89,0x08,0x06,0x03,0xc9,0x00,0x09,0x06,
  35.464 +   0x03,0xca,0x88,0x08,0x06,0x03,0xca,0x02,0x09,0x06,0x03,0xca,0x08,0x06,0x03,0xca,0x09,0x06,0x03,0xca,0x85,0x08,0x06,0x03,0xca,0x00,0x09,0x06,0x03,0xca,0xff,0x09,
  35.465 +   0x06,0x03,0xcb,0xa1,0x09,0x06,0x03,0xcb,0x01,0x08,0x06,0x03,0xca,0x09,0x06,0x03,0xca,0x86,0x08,0x06,0x03,0xca,0x00,0x09,0x06,0x03,0xca,0x82,0x08,0x06,0x03,0xca,
  35.466 +   0x02,0x09,0x06,0x03,0xca,0x08,0x06,0x03,0xca,0x09,0x06,0x03,0xca,0x83,0x08,0x06,0x03,0xca,0x89,0x08,0x06,0x03,0xc9,0x00,0x08,0x05,0x04,0xc9,0x83,0x08,0x05,0x04,
  35.467 +   0xc8,0x00,0x08,0x06,0x03,0xc8,0x82,0x08,0x05,0x04,0xc8,0x81,0x08,0x05,0x04,0xc7,0x81,0x07,0x05,0x04,0xc7,0x02,0x08,0x05,0x04,0xc7,0x07,0x05,0x04,0xc7,0x08,0x05,
  35.468 +   0x04,0xc7,0x82,0x07,0x05,0x04,0xc7,0x81,0x07,0x05,0x04,0xc6,0x84,0x07,0x05,0x02,0xc5,0x00,0x07,0x04,0x03,0xc5,0x81,0x06,0x04,0x03,0xc4,0x03,0x07,0x04,0x03,0xc4,
  35.469 +   0x06,0x04,0x03,0xc4,0x07,0x05,0x02,0xc4,0x07,0x04,0x03,0xc4,0x81,0x06,0x04,0x03,0xc4,0x81,0x06,0x04,0x03,0xc3,0x86,0x06,0x04,0x03,0xc2,0x81,0x05,0x04,0x03,0xc1,
  35.470 +   0x81,0x05,0x04,0x03,0xc0,0x81,0x05,0x03,0x03,0xc0,0x81,0x05,0x03,0x02,0xc0,0x83,0x05,0x03,0x02,0xbf,0x02,0x04,0x03,0x02,0xbf,0x05,0x03,0x02,0xbe,0x04,0x03,0x02,
  35.471 +   0xbe,0x85,0x04,0x03,0x02,0xbd,0x82,0x04,0x02,0x02,0xbc,0x00,0x03,0x02,0x02,0xbc,0x82,0x03,0x02,0x02,0xbb,0x84,0x03,0x02,0x01,0xba,0x83,0x03,0x02,0x01,0xb9,0x81,
  35.472 +   0x02,0x02,0x01,0xb9,0x83,0x02,0x01,0x01,0xb8,0x82,0x02,0x01,0x01,0xb7,0x00,0x01,0x01,0x01,0xb7,0x87,0x01,0x01,0x01,0xb6,0x00,0x01,0x01,0x00,0xb5,0x87,0x01,0x00,
  35.473 +   0x00,0xb5,0x85,0x01,0x00,0x00,0xb4,0x8d,0x00,0x00,0x00,0xb4,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0x87,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
  35.474 +   0xff,0x00,0x00,0x00,0xb3,0x99,0x00,0x00,0x00,0xb3,0x91,0x00,0x00,0x00,0xb4,0x81,0x01,0x00,0x00,0xb4,0x87,0x01,0x00,0x00,0xb5,0x00,0x01,0x01,0x00,0xb5,0x87,0x01,
  35.475 +   0x01,0x01,0xb6,0x00,0x01,0x01,0x01,0xb7,0x82,0x02,0x01,0x01,0xb7,0x83,0x02,0x01,0x01,0xb8,0x00,0x02,0x02,0x01,0xb9,0x84,0x03,0x02,0x01,0xb9,0x84,0x03,0x02,0x01,
  35.476 +   0xba,0x82,0x03,0x02,0x02,0xbb,0x00,0x03,0x02,0x02,0xbc,0x82,0x04,0x02,0x02,0xbc,0x85,0x04,0x03,0x02,0xbd,0x01,0x05,0x03,0x02,0xbe,0x04,0x03,0x02,0xbe,0x82,0x04,
  35.477 +   0x03,0x02,0xbf,0x81,0x05,0x03,0x02,0xbf,0x02,0x05,0x04,0x01,0xc0,0x05,0x03,0x02,0xc0,0x05,0x03,0x03,0xc0,0x82,0x05,0x04,0x03,0xc0,0x81,0x06,0x04,0x03,0xc1,0x86,
  35.478 +   0x06,0x04,0x03,0xc2,0x81,0x06,0x04,0x03,0xc3,0x84,0x06,0x04,0x03,0xc4,0x03,0x07,0x04,0x03,0xc4,0x06,0x04,0x03,0xc4,0x07,0x04,0x03,0xc4,0x07,0x05,0x02,0xc4,0x82,
  35.479 +   0x07,0x05,0x02,0xc5,0x00,0x07,0x05,0x02,0xc6,0x81,0x07,0x05,0x04,0xc6,0x00,0x08,0x05,0x04,0xc6,0x81,0x07,0x05,0x04,0xc7,0x87,0x08,0x05,0x04,0xc7,0x83,0x08,0x05,
  35.480 +   0x04,0xc8,0x8b,0x08,0x06,0x03,0xc9,0x01,0x09,0x06,0x03,0xc9,0x09,0x06,0x03,0xca,0x81,0x08,0x06,0x03,0xca,0x00,0x09,0x06,0x03,0xca,0x84,0x08,0x06,0x03,0xca,0x81,
  35.481 +   0x09,0x06,0x03,0xca,0x85,0x08,0x06,0x03,0xca,0x81,0x09,0x06,0x03,0xca,0xff,0x09,0x06,0x03,0xcb,0xa7,0x09,0x06,0x03,0xcb,0x81,0x09,0x06,0x03,0xca,0x81,0x08,0x06,
  35.482 +   0x03,0xca,0x06,0x09,0x06,0x03,0xca,0x08,0x06,0x03,0xca,0x09,0x06,0x03,0xca,0x08,0x06,0x03,0xca,0x09,0x06,0x03,0xca,0x08,0x06,0x03,0xca,0x09,0x06,0x03,0xca,0x81,
  35.483 +   0x08,0x06,0x03,0xca,0x00,0x09,0x06,0x03,0xca,0x81,0x08,0x06,0x03,0xca,0x02,0x09,0x06,0x03,0xca,0x08,0x06,0x03,0xca,0x09,0x06,0x03,0xca,0x8c,0x08,0x06,0x03,0xc9,
  35.484 +   0x83,0x08,0x05,0x04,0xc8,0x87,0x08,0x05,0x04,0xc7,0x81,0x07,0x05,0x04,0xc7,0x82,0x07,0x05,0x04,0xc6,0x00,0x07,0x05,0x02,0xc6,0x82,0x07,0x05,0x02,0xc5,0x83,0x06,
  35.485 +   0x04,0x03,0xc4,0x02,0x07,0x05,0x02,0xc4,0x07,0x04,0x03,0xc4,0x06,0x04,0x03,0xc4,0x81,0x07,0x04,0x03,0xc4,0x81,0x06,0x04,0x03,0xc3,0x86,0x06,0x04,0x03,0xc2,0x81,
  35.486 +   0x06,0x04,0x03,0xc1,0x81,0x05,0x04,0x03,0xc0,0x81,0x05,0x03,0x03,0xc0,0x81,0x05,0x03,0x02,0xc0,0x81,0x05,0x03,0x02,0xbf,0x82,0x04,0x03,0x02,0xbf,0x01,0x04,0x03,
  35.487 +   0x02,0xbe,0x05,0x03,0x02,0xbe,0x85,0x04,0x03,0x02,0xbd,0x82,0x04,0x02,0x02,0xbc,0x00,0x03,0x02,0x02,0xbc,0x81,0x03,0x02,0x02,0xbb,0x00,0x03,0x02,0x01,0xbb,0x84,
  35.488 +   0x03,0x02,0x01,0xba,0x83,0x03,0x02,0x01,0xb9,0x81,0x02,0x02,0x01,0xb9,0x83,0x02,0x01,0x01,0xb8,0x82,0x02,0x01,0x01,0xb7,0x00,0x01,0x01,0x01,0xb7,0x87,0x01,0x01,
  35.489 +   0x01,0xb6,0x00,0x01,0x01,0x00,0xb5,0x87,0x01,0x00,0x00,0xb5,0x81,0x01,0x00,0x00,0xb4,0x91,0x00,0x00,0x00,0xb4,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
  35.490 +   0x87,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0x9b,0x00,0x00,0x00,0xb3,0x8f,0x00,0x00,0x00,0xb4,0x81,0x01,0x00,0x00,0xb4,0x85,0x01,
  35.491 +   0x00,0x00,0xb5,0x01,0x01,0x01,0x00,0xb5,0x01,0x00,0x00,0xb5,0x82,0x01,0x01,0x00,0xb5,0x86,0x01,0x01,0x01,0xb6,0x00,0x01,0x01,0x01,0xb7,0x84,0x02,0x01,0x01,0xb7,
  35.492 +   0x81,0x02,0x01,0x01,0xb8,0x86,0x02,0x02,0x01,0xb9,0x00,0x03,0x02,0x01,0xb9,0x83,0x03,0x02,0x01,0xba,0x81,0x03,0x02,0x02,0xbb,0x86,0x04,0x02,0x02,0xbc,0x82,0x04,
  35.493 +   0x03,0x02,0xbd,0x00,0x04,0x03,0x02,0xbe,0x82,0x05,0x03,0x02,0xbe,0x00,0x04,0x03,0x02,0xbf,0x81,0x05,0x03,0x02,0xbf,0x84,0x05,0x03,0x02,0xc0,0x01,0x05,0x03,0x03,
  35.494 +   0xc0,0x05,0x04,0x03,0xc0,0x81,0x05,0x04,0x03,0xc1,0x87,0x06,0x04,0x03,0xc2,0x82,0x06,0x04,0x03,0xc3,0x81,0x07,0x04,0x03,0xc4,0x00,0x06,0x04,0x03,0xc4,0x84,0x07,
  35.495 +   0x04,0x03,0xc5,0x81,0x07,0x05,0x02,0xc5,0x82,0x07,0x05,0x02,0xc6,0x83,0x07,0x05,0x04,0xc6,0x00,0x08,0x05,0x04,0xc6,0x81,0x07,0x05,0x04,0xc7,0x00,0x08,0x05,0x04,
  35.496 +   0xc7,0x83,0x07,0x05,0x04,0xc7,0x00,0x08,0x05,0x04,0xc7,0x8e,0x08,0x05,0x04,0xc8,0x02,0x08,0x06,0x03,0xc8,0x08,0x05,0x04,0xc8,0x08,0x05,0x04,0xc9,0x87,0x08,0x06,
  35.497 +   0x03,0xc9,0x00,0x08,0x06,0x03,0xca,0x82,0x09,0x06,0x03,0xca,0x04,0x08,0x06,0x03,0xca,0x09,0x06,0x03,0xca,0x08,0x06,0x03,0xca,0x09,0x06,0x03,0xca,0x08,0x06,0x03,
  35.498 +   0xca,0x81,0x09,0x06,0x03,0xca,0x85,0x08,0x06,0x03,0xca,0x81,0x09,0x06,0x03,0xca,0x81,0x08,0x06,0x03,0xca,0x03,0x09,0x06,0x03,0xca,0x08,0x06,0x03,0xca,0x09,0x06,
  35.499 +   0x03,0xca,0x08,0x06,0x03,0xca,0x81,0x09,0x06,0x03,0xca,0x84,0x08,0x06,0x03,0xca,0x06,0x09,0x06,0x03,0xca,0x08,0x06,0x03,0xca,0x09,0x06,0x03,0xca,0x08,0x06,0x03,
  35.500 +   0xca,0x09,0x06,0x03,0xca,0x08,0x06,0x03,0xca,0x09,0x06,0x03,0xca,0x87,0x08,0x06,0x03,0xca,0x81,0x09,0x06,0x03,0xca,0x82,0x08,0x06,0x03,0xca,0x00,0x09,0x06,0x03,
  35.501 +   0xca,0x81,0x08,0x06,0x03,0xca,0x02,0x09,0x06,0x03,0xca,0x08,0x06,0x03,0xca,0x09,0x06,0x03,0xca,0x84,0x08,0x06,0x03,0xca,0x81,0x09,0x06,0x03,0xca,0x88,0x08,0x06,
  35.502 +   0x03,0xca,0x00,0x09,0x06,0x03,0xca,0x81,0x08,0x06,0x03,0xca,0x00,0x09,0x06,0x03,0xca,0x81,0x08,0x06,0x03,0xca,0x81,0x09,0x06,0x03,0xca,0x81,0x08,0x06,0x03,0xca,
  35.503 +   0x81,0x09,0x06,0x03,0xca,0x84,0x08,0x06,0x03,0xca,0x01,0x09,0x06,0x03,0xca,0x08,0x06,0x03,0xca,0x81,0x09,0x06,0x03,0xca,0x81,0x08,0x06,0x03,0xca,0x00,0x09,0x06,
  35.504 +   0x03,0xca,0x81,0x08,0x06,0x03,0xca,0x82,0x09,0x06,0x03,0xca,0x84,0x08,0x06,0x03,0xca,0x00,0x09,0x06,0x03,0xca,0x81,0x08,0x06,0x03,0xca,0x00,0x09,0x06,0x03,0xca,
  35.505 +   0x81,0x08,0x06,0x03,0xca,0x81,0x09,0x06,0x03,0xca,0x01,0x08,0x06,0x03,0xca,0x09,0x06,0x03,0xca,0x81,0x08,0x06,0x03,0xca,0x00,0x09,0x06,0x03,0xca,0x82,0x08,0x06,
  35.506 +   0x03,0xca,0x00,0x09,0x06,0x03,0xca,0x84,0x08,0x06,0x03,0xca,0x00,0x09,0x06,0x03,0xca,0x85,0x08,0x06,0x03,0xca,0x00,0x09,0x06,0x03,0xca,0x81,0x08,0x06,0x03,0xca,
  35.507 +   0x00,0x09,0x06,0x03,0xca,0x8a,0x08,0x06,0x03,0xca,0x00,0x09,0x06,0x03,0xca,0x83,0x08,0x06,0x03,0xca,0x00,0x09,0x06,0x03,0xca,0x84,0x08,0x06,0x03,0xca,0x01,0x09,
  35.508 +   0x06,0x03,0xca,0x08,0x06,0x03,0xca,0x81,0x09,0x06,0x03,0xca,0x82,0x08,0x06,0x03,0xca,0x00,0x09,0x06,0x03,0xca,0x83,0x08,0x06,0x03,0xca,0x81,0x09,0x06,0x03,0xca,
  35.509 +   0x82,0x08,0x06,0x03,0xca,0x01,0x08,0x06,0x03,0xc9,0x09,0x06,0x03,0xc9,0x85,0x08,0x06,0x03,0xc9,0x00,0x08,0x05,0x04,0xc9,0x90,0x08,0x05,0x04,0xc8,0x05,0x08,0x05,
  35.510 +   0x04,0xc7,0x07,0x05,0x04,0xc7,0x08,0x05,0x04,0xc7,0x07,0x05,0x04,0xc7,0x07,0x05,0x02,0xc7,0x07,0x05,0x04,0xc7,0x81,0x08,0x05,0x04,0xc7,0x00,0x08,0x05,0x04,0xc6,
  35.511 +   0x83,0x07,0x05,0x04,0xc6,0x82,0x07,0x05,0x02,0xc6,0x81,0x07,0x05,0x02,0xc5,0x84,0x07,0x04,0x03,0xc5,0x00,0x07,0x04,0x03,0xc4,0x81,0x06,0x04,0x03,0xc4,0x82,0x06,
  35.512 +   0x04,0x03,0xc3,0x87,0x06,0x04,0x03,0xc2,0x03,0x06,0x04,0x03,0xc1,0x05,0x04,0x03,0xc1,0x05,0x04,0x03,0xc0,0x05,0x03,0x03,0xc0,0x84,0x05,0x03,0x02,0xc0,0x81,0x05,
  35.513 +   0x03,0x02,0xbf,0x00,0x04,0x03,0x02,0xbf,0x81,0x04,0x03,0x02,0xbe,0x01,0x05,0x03,0x02,0xbe,0x04,0x03,0x02,0xbe,0x82,0x04,0x03,0x02,0xbd,0x84,0x04,0x02,0x02,0xbc,
  35.514 +   0x01,0x04,0x03,0x02,0xbc,0x03,0x02,0x02,0xbc,0x81,0x03,0x02,0x02,0xbb,0x83,0x03,0x02,0x01,0xba,0x81,0x03,0x02,0x01,0xb9,0x85,0x02,0x02,0x01,0xb9,0x81,0x02,0x01,
  35.515 +   0x01,0xb8,0x85,0x02,0x01,0x01,0xb7,0x86,0x01,0x01,0x01,0xb6,0x82,0x01,0x01,0x00,0xb5,0x87,0x01,0x00,0x00,0xb5,0x81,0x01,0x00,0x00,0xb4,0x8f,0x00,0x00,0x00,0xb4,
  35.516 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0x89,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0x9b,0x00,0x00,0x00,0xb3,0x91,0x00,
  35.517 +   0x00,0x00,0xb4,0x81,0x01,0x00,0x00,0xb4,0x85,0x01,0x00,0x00,0xb5,0x85,0x01,0x01,0x00,0xb5,0x83,0x01,0x01,0x01,0xb6,0x00,0x01,0x01,0x01,0xb7,0x84,0x02,0x01,0x01,
  35.518 +   0xb7,0x87,0x02,0x01,0x01,0xb8,0x81,0x02,0x02,0x01,0xb9,0x81,0x03,0x02,0x01,0xb9,0x83,0x03,0x02,0x01,0xba,0x84,0x03,0x02,0x02,0xbb,0x00,0x03,0x02,0x02,0xbc,0x84,
  35.519 +   0x04,0x02,0x02,0xbc,0x82,0x04,0x03,0x02,0xbd,0x83,0x04,0x03,0x02,0xbe,0x01,0x05,0x03,0x02,0xbe,0x04,0x03,0x02,0xbe,0x82,0x05,0x03,0x02,0xbf,0x83,0x05,0x03,0x02,
  35.520 +   0xc0,0x81,0x05,0x03,0x03,0xc0,0x82,0x05,0x04,0x03,0xc0,0x81,0x05,0x04,0x03,0xc1,0x86,0x06,0x04,0x03,0xc2,0x81,0x06,0x04,0x03,0xc3,0x00,0x07,0x05,0x02,0xc4,0x82,
  35.521 +   0x06,0x04,0x03,0xc4,0x02,0x07,0x04,0x03,0xc4,0x06,0x04,0x03,0xc4,0x07,0x04,0x03,0xc4,0x81,0x06,0x04,0x03,0xc4,0x89,0x07,0x05,0x02,0xc5,0x00,0x07,0x05,0x02,0xc6,
  35.522 +   0x89,0x07,0x05,0x04,0xc6,0x00,0x07,0x05,0x02,0xc7,0x81,0x07,0x05,0x04,0xc7,0x02,0x07,0x05,0x02,0xc7,0x08,0x05,0x04,0xc7,0x07,0x05,0x02,0xc7,0x81,0x07,0x05,0x04,
  35.523 +   0xc7,0x85,0x08,0x05,0x04,0xc7,0x88,0x08,0x05,0x04,0xc8,0x00,0x08,0x05,0x02,0xc8,0xb5,0x08,0x05,0x04,0xc8,0x00,0x08,0x06,0x03,0xc8,0x81,0x08,0x05,0x04,0xc8,0x00,
  35.524 +   0x08,0x06,0x03,0xc8,0xbd,0x08,0x05,0x04,0xc8,0x00,0x08,0x06,0x03,0xc8,0xa7,0x08,0x05,0x04,0xc8,0x00,0x08,0x05,0x02,0xc8,0x83,0x08,0x05,0x04,0xc8,0x00,0x08,0x05,
  35.525 +   0x02,0xc8,0x84,0x08,0x05,0x04,0xc8,0x01,0x08,0x05,0x02,0xc8,0x08,0x05,0x04,0xc8,0x85,0x08,0x05,0x04,0xc7,0x85,0x07,0x05,0x04,0xc7,0x81,0x08,0x05,0x04,0xc7,0x81,
  35.526 +   0x07,0x05,0x04,0xc6,0x00,0x07,0x05,0x02,0xc6,0x86,0x07,0x05,0x04,0xc6,0x00,0x07,0x05,0x02,0xc6,0x88,0x07,0x05,0x02,0xc5,0x01,0x07,0x04,0x03,0xc5,0x07,0x04,0x03,
  35.527 +   0xc4,0x87,0x06,0x04,0x03,0xc4,0x81,0x06,0x04,0x03,0xc3,0x86,0x06,0x04,0x03,0xc2,0x81,0x05,0x04,0x03,0xc1,0x82,0x05,0x04,0x03,0xc0,0x81,0x05,0x03,0x03,0xc0,0x83,
  35.528 +   0x05,0x03,0x02,0xc0,0x81,0x05,0x03,0x02,0xbf,0x00,0x04,0x03,0x02,0xbf,0x85,0x04,0x03,0x02,0xbe,0x82,0x04,0x03,0x02,0xbd,0x83,0x04,0x02,0x02,0xbc,0x01,0x03,0x02,
  35.529 +   0x02,0xbc,0x04,0x02,0x02,0xbc,0x84,0x03,0x02,0x02,0xbb,0x83,0x03,0x02,0x01,0xba,0x00,0x03,0x02,0x01,0xb9,0x82,0x02,0x02,0x01,0xb9,0x87,0x02,0x01,0x01,0xb8,0x85,
  35.530 +   0x02,0x01,0x01,0xb7,0x83,0x01,0x01,0x01,0xb6,0x85,0x01,0x01,0x00,0xb5,0x85,0x01,0x00,0x00,0xb5,0x81,0x01,0x00,0x00,0xb4,0x91,0x00,0x00,0x00,0xb4,0xff,0x00,0x00,
  35.531 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0x89,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0x9d,0x00,0x00,0x00,0xb3,0x8f,0x00,0x00,0x00,0xb4,
  35.532 +   0x87,0x01,0x00,0x00,0xb4,0x83,0x01,0x00,0x00,0xb5,0x86,0x01,0x01,0x00,0xb5,0x84,0x01,0x01,0x01,0xb6,0x00,0x01,0x01,0x01,0xb7,0x86,0x02,0x01,0x01,0xb7,0x84,0x02,
  35.533 +   0x01,0x01,0xb8,0x01,0x02,0x02,0x01,0xb9,0x03,0x02,0x01,0xb9,0x83,0x03,0x02,0x01,0xba,0x85,0x03,0x02,0x02,0xbb,0x01,0x03,0x02,0x02,0xbc,0x04,0x03,0x02,0xbc,0x81,
  35.534 +   0x04,0x02,0x02,0xbc,0x01,0x04,0x03,0x02,0xbc,0x04,0x02,0x02,0xbc,0x85,0x04,0x03,0x02,0xbd,0x88,0x04,0x03,0x02,0xbe,0x82,0x05,0x03,0x02,0xbf,0x81,0x05,0x03,0x02,
  35.535 +   0xc0,0x03,0x05,0x03,0x03,0xc0,0x05,0x04,0x03,0xc0,0x05,0x04,0x03,0xc1,0x06,0x04,0x03,0xc1,0x81,0x05,0x04,0x03,0xc1,0x00,0x06,0x04,0x03,0xc1,0x81,0x05,0x04,0x03,
  35.536 +   0xc1,0x8a,0x06,0x04,0x03,0xc2,0x87,0x06,0x04,0x03,0xc3,0x84,0x06,0x04,0x03,0xc4,0x00,0x07,0x04,0x03,0xc4,0x81,0x06,0x04,0x03,0xc4,0x89,0x07,0x04,0x03,0xc5,0x9f,
  35.537 +   0x07,0x05,0x02,0xc5,0xff,0x07,0x05,0x02,0xc6,0x83,0x07,0x05,0x02,0xc6,0x9f,0x07,0x05,0x02,0xc5,0x83,0x07,0x04,0x03,0xc5,0x00,0x07,0x05,0x02,0xc5,0x84,0x07,0x04,
  35.538 +   0x03,0xc5,0x87,0x06,0x04,0x03,0xc4,0x00,0x06,0x05,0x02,0xc3,0x86,0x06,0x04,0x03,0xc3,0x8a,0x06,0x04,0x03,0xc2,0x00,0x06,0x04,0x03,0xc1,0x83,0x05,0x04,0x03,0xc1,
  35.539 +   0x81,0x06,0x04,0x03,0xc1,0x01,0x05,0x04,0x03,0xc0,0x05,0x03,0x03,0xc0,0x81,0x05,0x03,0x02,0xc0,0x81,0x05,0x03,0x02,0xbf,0x00,0x04,0x03,0x02,0xbf,0x83,0x04,0x03,
  35.540 +   0x02,0xbe,0x00,0x05,0x03,0x02,0xbe,0x83,0x04,0x03,0x02,0xbe,0x85,0x04,0x03,0x02,0xbd,0x85,0x04,0x02,0x02,0xbc,0x85,0x03,0x02,0x02,0xbb,0x83,0x03,0x02,0x01,0xba,
  35.541 +   0x01,0x03,0x02,0x01,0xb9,0x02,0x02,0x01,0xb9,0x84,0x02,0x01,0x01,0xb8,0x86,0x02,0x01,0x01,0xb7,0x00,0x01,0x01,0x01,0xb7,0x84,0x01,0x01,0x01,0xb6,0x86,0x01,0x01,
  35.542 +   0x00,0xb5,0x83,0x01,0x00,0x00,0xb5,0x87,0x01,0x00,0x00,0xb4,0x8f,0x00,0x00,0x00,0xb4,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0x8b,0x00,0x00,0x00,0xb3,
  35.543 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xa2,0x00,0x00,0x00,0xb3,0x92,0x00,0x00,0x00,0xb4,0x83,0x01,0x00,0x00,0xb4,0x00,0x01,0x00,0x00,0xb5,0x85,0x01,
  35.544 +   0x01,0x00,0xb5,0x88,0x01,0x01,0x01,0xb6,0x83,0x01,0x01,0x01,0xb7,0x85,0x02,0x01,0x01,0xb7,0x82,0x02,0x01,0x01,0xb8,0x82,0x02,0x02,0x01,0xb9,0x82,0x03,0x02,0x01,
  35.545 +   0xb9,0x82,0x03,0x02,0x01,0xba,0x88,0x03,0x02,0x02,0xbb,0x83,0x04,0x02,0x02,0xbc,0x8a,0x04,0x03,0x02,0xbd,0x00,0x04,0x03,0x02,0xbe,0x81,0x05,0x03,0x02,0xbe,0x00,
  35.546 +   0x04,0x03,0x02,0xbe,0x87,0x05,0x03,0x02,0xbf,0x81,0x05,0x03,0x02,0xc0,0x86,0x05,0x03,0x03,0xc0,0x00,0x05,0x04,0x03,0xc0,0x81,0x05,0x04,0x03,0xc1,0x00,0x05,0x04,
  35.547 +   0x01,0xc1,0x82,0x05,0x04,0x03,0xc1,0x00,0x06,0x04,0x03,0xc1,0x81,0x05,0x04,0x03,0xc1,0xa0,0x06,0x04,0x03,0xc2,0xcf,0x06,0x04,0x03,0xc3,0x00,0x06,0x05,0x02,0xc3,
  35.548 +   0xd0,0x06,0x04,0x03,0xc3,0xa0,0x06,0x04,0x03,0xc2,0x83,0x05,0x04,0x03,0xc1,0x00,0x06,0x04,0x03,0xc1,0x83,0x05,0x04,0x03,0xc1,0x00,0x05,0x04,0x01,0xc0,0x86,0x05,
  35.549 +   0x03,0x03,0xc0,0x81,0x05,0x03,0x02,0xc0,0x86,0x05,0x03,0x02,0xbf,0x00,0x04,0x03,0x02,0xbf,0x83,0x04,0x03,0x02,0xbe,0x8a,0x04,0x03,0x02,0xbd,0x82,0x04,0x02,0x02,
  35.550 +   0xbc,0x00,0x03,0x02,0x02,0xbc,0x85,0x03,0x02,0x02,0xbb,0x00,0x03,0x02,0x01,0xbb,0x81,0x03,0x02,0x02,0xbb,0x82,0x03,0x02,0x01,0xba,0x83,0x03,0x02,0x01,0xb9,0x81,
  35.551 +   0x02,0x02,0x01,0xb9,0x82,0x02,0x01,0x01,0xb8,0x86,0x02,0x01,0x01,0xb7,0x82,0x01,0x01,0x01,0xb7,0x88,0x01,0x01,0x01,0xb6,0x85,0x01,0x01,0x00,0xb5,0x00,0x01,0x00,
  35.552 +   0x00,0xb5,0x83,0x01,0x00,0x00,0xb4,0x92,0x00,0x00,0x00,0xb4,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0x90,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
  35.553 +   0xff,0x00,0x00,0x00,0xb3,0xa6,0x00,0x00,0x00,0xb3,0x8e,0x00,0x00,0x00,0xb4,0x82,0x01,0x00,0x00,0xb4,0x87,0x01,0x00,0x00,0xb5,0x86,0x01,0x01,0x00,0xb5,0x87,0x01,
  35.554 +   0x01,0x01,0xb6,0x86,0x02,0x01,0x01,0xb7,0x86,0x02,0x01,0x01,0xb8,0x01,0x02,0x02,0x01,0xb8,0x02,0x01,0x01,0xb8,0x81,0x02,0x02,0x01,0xb9,0x00,0x03,0x02,0x01,0xb9,
  35.555 +   0x88,0x03,0x02,0x01,0xba,0x85,0x03,0x02,0x02,0xbb,0x02,0x03,0x02,0x01,0xbb,0x04,0x02,0x02,0xbc,0x03,0x02,0x02,0xbc,0x85,0x04,0x02,0x02,0xbc,0x89,0x04,0x03,0x02,
  35.556 +   0xbd,0x8d,0x04,0x03,0x02,0xbe,0x00,0x04,0x03,0x02,0xbf,0x89,0x05,0x03,0x02,0xbf,0x8c,0x05,0x03,0x02,0xc0,0x90,0x05,0x03,0x03,0xc0,0x00,0x05,0x04,0x03,0xc0,0x87,
  35.557 +   0x05,0x03,0x03,0xc0,0x83,0x05,0x04,0x03,0xc0,0x02,0x05,0x04,0x01,0xc0,0x05,0x04,0x03,0xc0,0x05,0x04,0x01,0xc0,0x88,0x05,0x04,0x03,0xc0,0x00,0x05,0x04,0x01,0xc0,
  35.558 +   0x86,0x05,0x04,0x03,0xc0,0x00,0x05,0x04,0x01,0xc0,0x8e,0x05,0x04,0x03,0xc0,0x00,0x05,0x04,0x01,0xc0,0xa1,0x05,0x04,0x03,0xc0,0x00,0x05,0x04,0x01,0xc0,0x98,0x05,
  35.559 +   0x04,0x03,0xc0,0x00,0x05,0x04,0x01,0xc0,0x92,0x05,0x04,0x03,0xc0,0x00,0x05,0x04,0x01,0xc0,0x8d,0x05,0x04,0x03,0xc0,0x99,0x05,0x03,0x03,0xc0,0x8c,0x05,0x03,0x02,
  35.560 +   0xc0,0x8a,0x05,0x03,0x02,0xbf,0x02,0x04,0x03,0x02,0xbe,0x05,0x03,0x02,0xbe,0x04,0x03,0x02,0xbe,0x81,0x05,0x03,0x02,0xbe,0x00,0x04,0x03,0x02,0xbe,0x83,0x05,0x03,
  35.561 +   0x02,0xbe,0x01,0x04,0x03,0x02,0xbe,0x05,0x03,0x02,0xbe,0x81,0x04,0x03,0x02,0xbe,0x89,0x04,0x03,0x02,0xbd,0x85,0x04,0x02,0x02,0xbc,0x81,0x03,0x02,0x02,0xbc,0x86,
  35.562 +   0x03,0x02,0x02,0xbb,0x88,0x03,0x02,0x01,0xba,0x81,0x03,0x02,0x01,0xb9,0x00,0x02,0x02,0x01,0xb9,0x88,0x02,0x01,0x01,0xb8,0x85,0x02,0x01,0x01,0xb7,0x00,0x01,0x01,
  35.563 +   0x01,0xb7,0x87,0x01,0x01,0x01,0xb6,0x86,0x01,0x01,0x00,0xb5,0x87,0x01,0x00,0x00,0xb5,0x82,0x01,0x00,0x00,0xb4,0x8e,0x00,0x00,0x00,0xb4,0xff,0x00,0x00,0x00,0xb3,
  35.564 +   0xff,0x00,0x00,0x00,0xb3,0x94,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xa6,0x00,0x00,0x00,0xb3,0x91,0x00,0x00,0x00,0xb4,0x85,0x01,
  35.565 +   0x00,0x00,0xb4,0x88,0x01,0x00,0x00,0xb5,0x81,0x01,0x01,0x00,0xb5,0x8c,0x01,0x01,0x01,0xb6,0x00,0x01,0x01,0x01,0xb7,0x87,0x02,0x01,0x01,0xb7,0x89,0x02,0x01,0x01,
  35.566 +   0xb8,0x85,0x02,0x02,0x01,0xb9,0x00,0x03,0x02,0x01,0xb9,0x8b,0x03,0x02,0x01,0xba,0x89,0x03,0x02,0x02,0xbb,0x00,0x03,0x02,0x02,0xbc,0x8c,0x04,0x02,0x02,0xbc,0xaf,
  35.567 +   0x04,0x03,0x02,0xbd,0x83,0x04,0x03,0x02,0xbe,0x00,0x05,0x03,0x02,0xbe,0x88,0x04,0x03,0x02,0xbe,0x00,0x05,0x03,0x02,0xbe,0x83,0x04,0x03,0x02,0xbe,0x02,0x05,0x03,
  35.568 +   0x02,0xbe,0x04,0x03,0x02,0xbe,0x05,0x03,0x02,0xbe,0x84,0x04,0x03,0x02,0xbe,0x00,0x05,0x03,0x02,0xbe,0x81,0x04,0x03,0x02,0xbe,0x00,0x05,0x03,0x02,0xbe,0x83,0x04,
  35.569 +   0x03,0x02,0xbe,0x04,0x05,0x03,0x02,0xbe,0x04,0x03,0x02,0xbe,0x05,0x03,0x02,0xbe,0x04,0x03,0x02,0xbe,0x05,0x03,0x02,0xbe,0x88,0x04,0x03,0x02,0xbe,0x00,0x05,0x03,
  35.570 +   0x02,0xbe,0x82,0x04,0x03,0x02,0xbe,0x04,0x05,0x03,0x02,0xbe,0x04,0x03,0x02,0xbe,0x05,0x03,0x02,0xbe,0x04,0x03,0x02,0xbe,0x05,0x03,0x02,0xbe,0x81,0x04,0x03,0x02,
  35.571 +   0xbe,0x00,0x05,0x03,0x02,0xbe,0x82,0x04,0x03,0x02,0xbe,0x00,0x05,0x03,0x02,0xbe,0x82,0x04,0x03,0x02,0xbe,0x81,0x05,0x03,0x02,0xbe,0x82,0x04,0x03,0x02,0xbe,0x81,
  35.572 +   0x05,0x03,0x02,0xbe,0x81,0x04,0x03,0x02,0xbe,0x00,0x05,0x03,0x02,0xbe,0x82,0x04,0x03,0x02,0xbe,0x81,0x05,0x03,0x02,0xbe,0x81,0x04,0x03,0x02,0xbe,0x81,0x05,0x03,
  35.573 +   0x02,0xbe,0x85,0x04,0x03,0x02,0xbe,0x00,0x05,0x03,0x02,0xbe,0x82,0x04,0x03,0x02,0xbe,0x81,0x05,0x03,0x02,0xbe,0x85,0x04,0x03,0x02,0xbe,0x00,0x05,0x03,0x02,0xbe,
  35.574 +   0x86,0x04,0x03,0x02,0xbe,0x02,0x05,0x03,0x02,0xbe,0x04,0x03,0x02,0xbe,0x05,0x03,0x02,0xbe,0x81,0x04,0x03,0x02,0xbe,0x00,0x05,0x03,0x02,0xbe,0x85,0x04,0x03,0x02,
  35.575 +   0xbe,0x81,0x05,0x03,0x02,0xbe,0x03,0x04,0x03,0x02,0xbe,0x05,0x03,0x02,0xbe,0x04,0x03,0x02,0xbe,0x05,0x03,0x02,0xbe,0x84,0x04,0x03,0x02,0xbe,0xaf,0x04,0x03,0x02,
  35.576 +   0xbd,0x8a,0x04,0x02,0x02,0xbc,0x00,0x04,0x03,0x02,0xbc,0x81,0x04,0x02,0x02,0xbc,0x86,0x03,0x02,0x02,0xbb,0x00,0x03,0x02,0x01,0xbb,0x81,0x03,0x02,0x02,0xbb,0x8b,
  35.577 +   0x03,0x02,0x01,0xba,0x00,0x03,0x02,0x01,0xb9,0x85,0x02,0x02,0x01,0xb9,0x89,0x02,0x01,0x01,0xb8,0x87,0x02,0x01,0x01,0xb7,0x00,0x01,0x01,0x01,0xb7,0x8c,0x01,0x01,
  35.578 +   0x01,0xb6,0x81,0x01,0x01,0x00,0xb5,0x88,0x01,0x00,0x00,0xb5,0x85,0x01,0x00,0x00,0xb4,0x91,0x00,0x00,0x00,0xb4,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
  35.579 +   0x94,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xa8,0x00,0x00,0x00,0xb3,0x95,0x00,0x00,0x00,0xb4,0x83,0x01,0x00,0x00,0xb4,0x81,0x00,
  35.580 +   0x00,0x00,0xb4,0x81,0x01,0x00,0x00,0xb4,0x00,0x01,0x00,0x00,0xb5,0x8c,0x01,0x01,0x00,0xb5,0x87,0x01,0x01,0x01,0xb6,0x01,0x02,0x01,0x01,0xb7,0x01,0x01,0x01,0xb7,
  35.581 +   0x8c,0x02,0x01,0x01,0xb7,0x83,0x02,0x01,0x01,0xb8,0x00,0x02,0x02,0x01,0xb8,0x87,0x02,0x01,0x01,0xb8,0x83,0x02,0x02,0x01,0xb9,0x00,0x03,0x02,0x01,0xb9,0x9b,0x03,
  35.582 +   0x02,0x01,0xba,0xa0,0x03,0x02,0x02,0xbb,0x00,0x03,0x02,0x01,0xbb,0x8f,0x03,0x02,0x02,0xbb,0x00,0x03,0x02,0x01,0xbb,0x8c,0x03,0x02,0x02,0xbb,0x00,0x03,0x02,0x02,
  35.583 +   0xbc,0x96,0x04,0x02,0x02,0xbc,0x00,0x04,0x03,0x02,0xbc,0xb0,0x04,0x02,0x02,0xbc,0x00,0x04,0x03,0x02,0xbc,0x92,0x04,0x02,0x02,0xbc,0x82,0x03,0x02,0x02,0xbb,0x00,
  35.584 +   0x03,0x02,0x01,0xbb,0x8e,0x03,0x02,0x02,0xbb,0x00,0x03,0x02,0x01,0xbb,0x82,0x03,0x02,0x02,0xbb,0x00,0x03,0x02,0x01,0xbb,0xa2,0x03,0x02,0x02,0xbb,0x00,0x03,0x02,
  35.585 +   0x01,0xbb,0x83,0x03,0x02,0x02,0xbb,0x9b,0x03,0x02,0x01,0xba,0x00,0x03,0x02,0x01,0xb9,0x83,0x02,0x02,0x01,0xb9,0x8c,0x02,0x01,0x01,0xb8,0x8e,0x02,0x01,0x01,0xb7,
  35.586 +   0x87,0x01,0x01,0x01,0xb6,0x8c,0x01,0x01,0x00,0xb5,0x00,0x01,0x00,0x00,0xb5,0x81,0x01,0x00,0x00,0xb4,0x81,0x00,0x00,0x00,0xb4,0x83,0x01,0x00,0x00,0xb4,0x95,0x00,
  35.587 +   0x00,0x00,0xb4,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0x96,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xb1,0x00,0x00,0x00,
  35.588 +   0xb3,0x99,0x00,0x00,0x00,0xb4,0x87,0x01,0x00,0x00,0xb4,0x86,0x01,0x00,0x00,0xb5,0x81,0x01,0x01,0x00,0xb5,0x8e,0x01,0x01,0x01,0xb6,0x81,0x01,0x01,0x01,0xb7,0x01,
  35.589 +   0x02,0x01,0x01,0xb7,0x01,0x01,0x01,0xb7,0x8a,0x02,0x01,0x01,0xb7,0x92,0x02,0x01,0x01,0xb8,0x02,0x02,0x02,0x01,0xb8,0x02,0x01,0x01,0xb8,0x02,0x02,0x01,0xb8,0x89,
  35.590 +   0x02,0x01,0x01,0xb8,0x82,0x02,0x02,0x01,0xb9,0x00,0x03,0x02,0x01,0xb9,0x89,0x02,0x02,0x01,0xb9,0x81,0x03,0x02,0x01,0xb9,0xff,0x03,0x02,0x01,0xba,0xbb,0x03,0x02,
  35.591 +   0x01,0xba,0x81,0x03,0x02,0x01,0xb9,0x82,0x02,0x02,0x01,0xb9,0x81,0x03,0x02,0x01,0xb9,0x01,0x02,0x02,0x01,0xb9,0x03,0x02,0x01,0xb9,0x81,0x02,0x02,0x01,0xb9,0x82,
  35.592 +   0x03,0x02,0x01,0xb9,0x81,0x02,0x02,0x01,0xb9,0x9f,0x02,0x01,0x01,0xb8,0x8a,0x02,0x01,0x01,0xb7,0x03,0x01,0x01,0x01,0xb7,0x02,0x01,0x01,0xb7,0x01,0x01,0x01,0xb7,
  35.593 +   0x02,0x01,0x01,0xb7,0x8e,0x01,0x01,0x01,0xb6,0x81,0x01,0x01,0x00,0xb5,0x86,0x01,0x00,0x00,0xb5,0x87,0x01,0x00,0x00,0xb4,0x99,0x00,0x00,0x00,0xb4,0xff,0x00,0x00,
  35.594 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0x9f,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xb9,0x00,0x00,0x00,0xb3,0x99,0x00,0x00,0x00,0xb4,
  35.595 +   0x88,0x01,0x00,0x00,0xb4,0x87,0x01,0x00,0x00,0xb5,0x89,0x01,0x01,0x00,0xb5,0x96,0x01,0x01,0x01,0xb6,0x01,0x02,0x01,0x01,0xb7,0x01,0x01,0x01,0xb7,0x9f,0x02,0x01,
  35.596 +   0x01,0xb7,0xff,0x02,0x01,0x01,0xb8,0xc1,0x02,0x01,0x01,0xb8,0x9f,0x02,0x01,0x01,0xb7,0x01,0x01,0x01,0x01,0xb7,0x02,0x01,0x01,0xb7,0x96,0x01,0x01,0x01,0xb6,0x89,
  35.597 +   0x01,0x01,0x00,0xb5,0x87,0x01,0x00,0x00,0xb5,0x88,0x01,0x00,0x00,0xb4,0x99,0x00,0x00,0x00,0xb4,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xa7,0x00,0x00,
  35.598 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xbf,0x00,0x00,0x00,0xb3,0x9c,0x00,0x00,0x00,0xb4,0x8c,0x01,0x00,0x00,0xb4,0x8f,0x01,0x00,0x00,0xb5,
  35.599 +   0x89,0x01,0x01,0x00,0xb5,0xd1,0x01,0x01,0x01,0xb6,0x81,0x01,0x01,0x01,0xb7,0xe1,0x02,0x01,0x01,0xb7,0x81,0x01,0x01,0x01,0xb7,0xd1,0x01,0x01,0x01,0xb6,0x89,0x01,
  35.600 +   0x01,0x00,0xb5,0x88,0x01,0x00,0x00,0xb5,0x02,0x01,0x01,0x00,0xb5,0x01,0x00,0x00,0xb5,0x01,0x01,0x00,0xb5,0x83,0x01,0x00,0x00,0xb5,0x8c,0x01,0x00,0x00,0xb4,0x9c,
  35.601 +   0x00,0x00,0x00,0xb4,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xad,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xc7,0x00,0x00,
  35.602 +   0x00,0xb3,0xa1,0x00,0x00,0x00,0xb4,0x93,0x01,0x00,0x00,0xb4,0x86,0x01,0x00,0x00,0xb5,0x00,0x01,0x01,0x00,0xb5,0x9e,0x01,0x00,0x00,0xb5,0xff,0x01,0x01,0x00,0xb5,
  35.603 +   0xc7,0x01,0x01,0x00,0xb5,0x87,0x01,0x00,0x00,0xb5,0x00,0x01,0x01,0x00,0xb5,0x81,0x01,0x00,0x00,0xb5,0x00,0x01,0x01,0x00,0xb5,0x9a,0x01,0x00,0x00,0xb5,0x93,0x01,
  35.604 +   0x00,0x00,0xb4,0xa1,0x00,0x00,0x00,0xb4,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xb5,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
  35.605 +   0xb3,0xd2,0x00,0x00,0x00,0xb3,0x87,0x00,0x00,0x00,0xb4,0x83,0x00,0x00,0x00,0xb3,0x9e,0x00,0x00,0x00,0xb4,0x91,0x01,0x00,0x00,0xb4,0x94,0x00,0x00,0x00,0xb4,0x8e,
  35.606 +   0x01,0x00,0x00,0xb4,0x87,0x01,0x00,0x00,0xb5,0x00,0x01,0x01,0x00,0xb5,0x9a,0x01,0x00,0x00,0xb5,0xe1,0x01,0x00,0x00,0xb4,0x01,0x01,0x00,0x00,0xb5,0x01,0x01,0x00,
  35.607 +   0xb5,0x9b,0x01,0x00,0x00,0xb5,0x00,0x01,0x01,0x00,0xb5,0x84,0x01,0x00,0x00,0xb5,0x8e,0x01,0x00,0x00,0xb4,0x94,0x00,0x00,0x00,0xb4,0x91,0x01,0x00,0x00,0xb4,0x9e,
  35.608 +   0x00,0x00,0x00,0xb4,0x83,0x00,0x00,0x00,0xb3,0x87,0x00,0x00,0x00,0xb4,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xc0,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
  35.609 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xeb,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb4,0xff,0x00,0x00,0x00,0xb4,0xb9,0x00,0x00,0x00,0xb4,0xff,0x00,0x00,0x00,0xb3,
  35.610 +   0xff,0x00,0x00,0x00,0xb3,0xd9,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xfe,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb4,0xff,0x00,
  35.611 +   0x00,0x00,0xb4,0x93,0x00,0x00,0x00,0xb4,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xec,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
  35.612 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
  35.613 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
  35.614 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
  35.615 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
  35.616 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
  35.617 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
  35.618 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
  35.619 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
  35.620 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
  35.621 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
  35.622 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
  35.623 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
  35.624 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
  35.625 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
  35.626 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
  35.627 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
  35.628 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
  35.629 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
  35.630 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
  35.631 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
  35.632 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
  35.633 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
  35.634 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
  35.635 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
  35.636 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
  35.637 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
  35.638 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
  35.639 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xfc,0x00,0x00,0x00,0xb3,
  35.640 +   0x00,0x52,0x52,0x52,0xbd,0x81,0x7e,0x7e,0x7e,0xc7,0x00,0x52,0x52,0x52,0xbd,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xfe,0x00,0x00,0x00,0xb3,0xff,0x00,
  35.641 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xfa,0x00,0x00,0x00,0xb3,0x01,0xaf,0xaf,0xaf,0xd6,0xef,0xef,0xef,0xf5,
  35.642 +   0x83,0xff,0xff,0xff,0xff,0x01,0xef,0xef,0xef,0xf5,0x6a,0x6a,0x6a,0xc2,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xfc,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
  35.643 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xf9,0x00,0x00,0x00,0xb3,0x01,0x33,0x33,0x33,0xb8,0xf7,0xf7,0xf7,0xfa,0x85,
  35.644 +   0xff,0xff,0xff,0xff,0x01,0xf7,0xf7,0xf7,0xfa,0x6a,0x6a,0x6a,0xc2,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xfb,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
  35.645 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xfa,0x00,0x00,0x00,0xb3,0x02,0xa0,0xa0,0xa0,0xd1,0xff,0xff,0xff,0xff,0xbb,0xbb,
  35.646 +   0xbb,0xdc,0x81,0x7e,0x7e,0x7e,0xc7,0x00,0xd2,0xd2,0xd2,0xe6,0x81,0xff,0xff,0xff,0xff,0x00,0xc7,0xc7,0xc7,0xe1,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
  35.647 +   0xfb,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0x86,0x00,0x00,0x00,0xb3,0x00,0x33,0x33,0x33,0xb8,0x81,0x7e,
  35.648 +   0x7e,0x7e,0xc7,0x00,0x33,0x33,0x33,0xb8,0x8d,0x00,0x00,0x00,0xb3,0x00,0x33,0x33,0x33,0xb8,0x81,0x7e,0x7e,0x7e,0xc7,0xc2,0x00,0x00,0x00,0xb3,0x00,0x52,0x52,0x52,
  35.649 +   0xbd,0x81,0x7e,0x7e,0x7e,0xc7,0x87,0x00,0x00,0x00,0xb3,0x00,0x33,0x33,0x33,0xb8,0x81,0x7e,0x7e,0x7e,0xc7,0x83,0x00,0x00,0x00,0xb3,0x02,0x33,0x33,0x33,0xb8,0x7e,
  35.650 +   0x7e,0x7e,0xc7,0x6a,0x6a,0x6a,0xc2,0x8b,0x00,0x00,0x00,0xb3,0x02,0x33,0x33,0x33,0xb8,0x7e,0x7e,0x7e,0xc7,0x6a,0x6a,0x6a,0xc2,0x86,0x00,0x00,0x00,0xb3,0x00,0x52,
  35.651 +   0x52,0x52,0xbd,0x81,0x7e,0x7e,0x7e,0xc7,0x00,0x33,0x33,0x33,0xb8,0x8b,0x00,0x00,0x00,0xb3,0x02,0x6a,0x6a,0x6a,0xc2,0x7e,0x7e,0x7e,0xc7,0x52,0x52,0x52,0xbd,0x84,
  35.652 +   0x00,0x00,0x00,0xb3,0x00,0x33,0x33,0x33,0xb8,0x81,0x7e,0x7e,0x7e,0xc7,0x00,0x33,0x33,0x33,0xb8,0x92,0x00,0x00,0x00,0xb3,0x02,0xaf,0xaf,0xaf,0xd6,0xdc,0xdc,0xdc,
  35.653 +   0xeb,0x52,0x52,0x52,0xbd,0x95,0x00,0x00,0x00,0xb3,0x81,0x7e,0x7e,0x7e,0xc7,0xa7,0x00,0x00,0x00,0xb3,0x00,0x6a,0x6a,0x6a,0xc2,0x83,0x00,0x00,0x00,0xb3,0x02,0xef,
  35.654 +   0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0x82,0x00,0x00,0x00,0xb3,0x00,0x52,0x52,0x52,0xbd,0x81,0x7e,0x7e,0x7e,0xc7,0x00,0x33,0x33,0x33,0xb8,0xff,
  35.655 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xf4,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xf2,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,
  35.656 +   0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0x90,0x90,0x90,0xcc,0x81,0xff,0xff,0xff,0xff,0x00,0x6a,0x6a,0x6a,0xc2,
  35.657 +   0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x01,0x33,0x33,0x33,0xb8,0xc7,0xc7,
  35.658 +   0xc7,0xe1,0x83,0xff,0xff,0xff,0xff,0x01,0xc7,0xc7,0xc7,0xe1,0x33,0x33,0x33,0xb8,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x84,
  35.659 +   0x00,0x00,0x00,0xb3,0x01,0x52,0x52,0x52,0xbd,0xd2,0xd2,0xd2,0xe6,0x82,0xff,0xff,0xff,0xff,0x01,0xf7,0xf7,0xf7,0xfa,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,
  35.660 +   0x02,0xdc,0xdc,0xdc,0xeb,0xff,0xff,0xff,0xff,0xaf,0xaf,0xaf,0xd6,0x88,0x00,0x00,0x00,0xb3,0x00,0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,0x00,0x6a,0x6a,0x6a,
  35.661 +   0xc2,0x81,0x00,0x00,0x00,0xb3,0x00,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x00,0xa0,0xa0,0xa0,0xd1,0x84,0x00,0x00,0x00,0xb3,0x00,0xe6,0xe6,0xe6,0xf0,0x81,
  35.662 +   0xff,0xff,0xff,0xff,0x00,0x6a,0x6a,0x6a,0xc2,0x81,0x00,0x00,0x00,0xb3,0x00,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x00,0xa0,0xa0,0xa0,0xd1,0x84,0x00,0x00,
  35.663 +   0x00,0xb3,0x00,0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,0x00,0x6a,0x6a,0x6a,0xc2,0x81,0x00,0x00,0x00,0xb3,0x00,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,
  35.664 +   0x00,0xa0,0xa0,0xa0,0xd1,0x81,0x00,0x00,0x00,0xb3,0x02,0xaf,0xaf,0xaf,0xd6,0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,0xeb,0x82,0x00,0x00,0x00,0xb3,0x01,0x6a,0x6a,0x6a,
  35.665 +   0xc2,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x01,0xf7,0xf7,0xf7,0xfa,0xaf,0xaf,0xaf,0xd6,0x83,0x00,0x00,0x00,0xb3,0x01,0x52,0x52,0x52,0xbd,0xd2,0xd2,0xd2,
  35.666 +   0xe6,0x82,0xff,0xff,0xff,0xff,0x04,0xf7,0xf7,0xf7,0xfa,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xa0,0xa0,0xa0,0xd1,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,
  35.667 +   0x01,0xc7,0xc7,0xc7,0xe1,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,
  35.668 +   0x00,0xb3,0x01,0xa0,0xa0,0xa0,0xd1,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x01,0xc7,0xc7,0xc7,0xe1,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x02,0x00,
  35.669 +   0x00,0x00,0xb3,0x6a,0x6a,0x6a,0xc2,0xdc,0xdc,0xdc,0xeb,0x83,0xff,0xff,0xff,0xff,0x06,0xdc,0xdc,0xdc,0xeb,0x33,0x33,0x33,0xb8,0x00,0x00,0x00,0xb3,0x52,0x52,0x52,
  35.670 +   0xbd,0xef,0xef,0xef,0xf5,0xf7,0xf7,0xf7,0xfa,0x90,0x90,0x90,0xcc,0x82,0x00,0x00,0x00,0xb3,0x01,0xaf,0xaf,0xaf,0xd6,0xef,0xef,0xef,0xf5,0x82,0xff,0xff,0xff,0xff,
  35.671 +   0x04,0xdc,0xdc,0xdc,0xeb,0x6a,0x6a,0x6a,0xc2,0x00,0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,0xc7,0xc7,0xc7,0xe1,0x83,0xff,0xff,0xff,0xff,0x01,0xc7,0xc7,0xc7,0xe1,0x33,
  35.672 +   0x33,0x33,0xb8,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,
  35.673 +   0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x03,0x7e,0x7e,0x7e,0xc7,0xdc,0xdc,0xdc,0xeb,0xff,0xff,
  35.674 +   0xff,0xff,0xaf,0xaf,0xaf,0xd6,0x86,0x00,0x00,0x00,0xb3,0x00,0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,0x00,0x6a,0x6a,0x6a,0xc2,0x81,0x00,0x00,0x00,0xb3,0x00,
  35.675 +   0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x00,0xa0,0xa0,0xa0,0xd1,0x82,0x00,0x00,0x00,0xb3,0x01,0xa0,0xa0,0xa0,0xd1,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,
  35.676 +   0xff,0x01,0xf7,0xf7,0xf7,0xfa,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x01,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,
  35.677 +   0xdc,0xeb,0x83,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,
  35.678 +   0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,
  35.679 +   0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x82,0x00,0x00,0x00,0xb3,0x05,0x90,0x90,0x90,0xcc,0xe6,
  35.680 +   0xe6,0xe6,0xf0,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0xaf,0xaf,0xaf,0xd6,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x02,0x00,0x00,0x00,0xb3,0x6a,0x6a,0x6a,
  35.681 +   0xc2,0xdc,0xdc,0xdc,0xeb,0x83,0xff,0xff,0xff,0xff,0x01,0xdc,0xdc,0xdc,0xeb,0x33,0x33,0x33,0xb8,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xf2,0x00,0x00,
  35.682 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xf2,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,
  35.683 +   0x81,0x00,0x00,0x00,0xb3,0x00,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x00,0xc7,0xc7,0xc7,0xe1,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,
  35.684 +   0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x00,0xe6,0xe6,0xe6,0xf0,0x85,0xff,0xff,0xff,0xff,0x00,0xe6,0xe6,0xe6,0xf0,0x81,0x00,0x00,0x00,
  35.685 +   0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x83,0x00,0x00,0x00,0xb3,0x01,0x33,0x33,0x33,0xb8,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x01,0xdc,
  35.686 +   0xdc,0xdc,0xeb,0xef,0xef,0xef,0xf5,0x81,0xff,0xff,0xff,0xff,0x02,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x87,0x00,
  35.687 +   0x00,0x00,0xb3,0x00,0x6a,0x6a,0x6a,0xc2,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0xef,0xef,0xef,0xf5,0x81,0xff,0xff,0xff,
  35.688 +   0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x83,0x00,0x00,0x00,0xb3,0x00,0x6a,0x6a,0x6a,0xc2,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,
  35.689 +   0xef,0xef,0xef,0xf5,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x83,0x00,0x00,0x00,0xb3,0x00,0x6a,0x6a,0x6a,0xc2,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,
  35.690 +   0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0xef,0xef,0xef,0xf5,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x82,0xff,0xff,0xff,0xff,
  35.691 +   0x03,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0x52,0x52,0x52,0xbd,0xf7,0xf7,0xf7,0xfa,0x85,0xff,0xff,0xff,0xff,0x00,0xbb,0xbb,0xbb,0xdc,0x81,0x00,0x00,0x00,0xb3,
  35.692 +   0x01,0x33,0x33,0x33,0xb8,0xf7,0xf7,0xf7,0xfa,0x84,0xff,0xff,0xff,0xff,0x02,0xc7,0xc7,0xc7,0xe1,0x00,0x00,0x00,0xb3,0xf7,0xf7,0xf7,0xfa,0x86,0xff,0xff,0xff,0xff,
  35.693 +   0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0xf7,0xf7,0xf7,0xfa,0x86,0xff,0xff,0xff,0xff,0x03,0x00,
  35.694 +   0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0x81,0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,
  35.695 +   0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x84,0xff,0xff,0xff,0xff,0x03,
  35.696 +   0xf7,0xf7,0xf7,0xfa,0x6a,0x6a,0x6a,0xc2,0x00,0x00,0x00,0xb3,0xe6,0xe6,0xe6,0xf0,0x85,0xff,0xff,0xff,0xff,0x00,0xe6,0xe6,0xe6,0xf0,0x81,0x00,0x00,0x00,0xb3,0x00,
  35.697 +   0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,
  35.698 +   0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x03,0x7e,0x7e,0x7e,0xc7,0xa0,0xa0,0xa0,0xd1,0xff,0xff,0xff,0xff,0xef,0xef,0xef,0xf5,0x85,0x00,0x00,
  35.699 +   0x00,0xb3,0x00,0x6a,0x6a,0x6a,0xc2,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0xef,0xef,0xef,0xf5,0x81,0xff,0xff,0xff,0xff,
  35.700 +   0x00,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x00,0x52,0x52,0x52,0xbd,0x81,0xff,0xff,0xff,0xff,0x02,0xef,0xef,0xef,0xf5,0xaf,0xaf,0xaf,0xd6,0xc7,0xc7,0xc7,
  35.701 +   0xe1,0x82,0xff,0xff,0xff,0xff,0x01,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x83,0x00,0x00,0x00,0xb3,0x00,0x7e,
  35.702 +   0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,
  35.703 +   0xb3,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,
  35.704 +   0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0x90,0x90,0x90,0xcc,0x87,0xff,0xff,0xff,0xff,0x03,0x00,0x00,0x00,0xb3,
  35.705 +   0x33,0x33,0x33,0xb8,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0x81,0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0xff,0x00,0x00,0x00,0xb3,
  35.706 +   0xff,0x00,0x00,0x00,0xb3,0xf2,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xf2,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,
  35.707 +   0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x00,0xf7,0xf7,0xf7,0xfa,0x81,0x00,0x00,0x00,
  35.708 +   0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x02,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0xa0,0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,0xff,0x00,0xe6,0xe6,
  35.709 +   0xe6,0xf0,0x81,0x90,0x90,0x90,0xcc,0x00,0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,0x02,0xa0,0xa0,0xa0,0xd1,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,
  35.710 +   0xff,0xff,0xff,0x83,0x00,0x00,0x00,0xb3,0x00,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x00,0x6a,0x6a,0x6a,0xc2,0x81,0x00,0x00,0x00,0xb3,0x01,0xbb,0xbb,0xbb,
  35.711 +   0xdc,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x03,0x33,0x33,0x33,0xb8,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,0xeb,0x87,0x00,0x00,0x00,0xb3,
  35.712 +   0x00,0xbb,0xbb,0xbb,0xdc,0x82,0xff,0xff,0xff,0xff,0x02,0xe6,0xe6,0xe6,0xf0,0x00,0x00,0x00,0xb3,0x6a,0x6a,0x6a,0xc2,0x83,0xff,0xff,0xff,0xff,0x00,0x52,0x52,0x52,
  35.713 +   0xbd,0x82,0x00,0x00,0x00,0xb3,0x00,0xbb,0xbb,0xbb,0xdc,0x82,0xff,0xff,0xff,0xff,0x02,0xe6,0xe6,0xe6,0xf0,0x00,0x00,0x00,0xb3,0x6a,0x6a,0x6a,0xc2,0x83,0xff,0xff,
  35.714 +   0xff,0xff,0x00,0x52,0x52,0x52,0xbd,0x82,0x00,0x00,0x00,0xb3,0x00,0xbb,0xbb,0xbb,0xdc,0x82,0xff,0xff,0xff,0xff,0x02,0xe6,0xe6,0xe6,0xf0,0x00,0x00,0x00,0xb3,0x6a,
  35.715 +   0x6a,0x6a,0xc2,0x83,0xff,0xff,0xff,0xff,0x07,0x52,0x52,0x52,0xbd,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0x33,0x33,0x33,
  35.716 +   0xb8,0x00,0x00,0x00,0xb3,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x03,0xd2,0xd2,0xd2,0xe6,0x7e,0x7e,0x7e,0xc7,0xa0,0xa0,0xa0,0xd1,0xf7,0xf7,0xf7,0xfa,0x81,
  35.717 +   0xff,0xff,0xff,0xff,0x02,0x52,0x52,0x52,0xbd,0x00,0x00,0x00,0xb3,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x05,0xd2,0xd2,0xd2,0xe6,0x7e,0x7e,0x7e,0xc7,0xa0,
  35.718 +   0xa0,0xa0,0xd1,0xc7,0xc7,0xc7,0xe1,0x00,0x00,0x00,0xb3,0x6a,0x6a,0x6a,0xc2,0x81,0xff,0xff,0xff,0xff,0x02,0xf7,0xf7,0xf7,0xfa,0x90,0x90,0x90,0xcc,0xaf,0xaf,0xaf,
  35.719 +   0xd6,0x82,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0xb3,0x6a,0x6a,0x6a,0xc2,0x81,0xff,
  35.720 +   0xff,0xff,0xff,0x02,0xf7,0xf7,0xf7,0xfa,0x90,0x90,0x90,0xcc,0xaf,0xaf,0xaf,0xd6,0x82,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x01,0x6a,0x6a,0x6a,0xc2,0xa0,
  35.721 +   0xa0,0xa0,0xd1,0x81,0x00,0x00,0x00,0xb3,0x00,0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,
  35.722 +   0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0x52,0x52,0x52,0xbd,0x81,0xff,0xff,0xff,0xff,0x06,0xf7,0xf7,0xf7,0xfa,0xa0,0xa0,0xa0,0xd1,0x7e,0x7e,0x7e,0xc7,0xd2,
  35.723 +   0xd2,0xd2,0xe6,0x6a,0x6a,0x6a,0xc2,0x00,0x00,0x00,0xb3,0xa0,0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,0xff,0x00,0xe6,0xe6,0xe6,0xf0,0x81,0x90,0x90,0x90,0xcc,0x00,0xe6,
  35.724 +   0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,0x02,0xa0,0xa0,0xa0,0xd1,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x81,
  35.725 +   0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x04,0x7e,0x7e,
  35.726 +   0x7e,0xc7,0x33,0x33,0x33,0xb8,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0x90,0x90,0x90,0xcc,0x84,0x00,0x00,0x00,0xb3,0x00,0xbb,0xbb,0xbb,0xdc,0x82,0xff,0xff,0xff,
  35.727 +   0xff,0x02,0xe6,0xe6,0xe6,0xf0,0x00,0x00,0x00,0xb3,0x6a,0x6a,0x6a,0xc2,0x83,0xff,0xff,0xff,0xff,0x02,0x52,0x52,0x52,0xbd,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,
  35.728 +   0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x01,0x7e,0x7e,0x7e,0xc7,0x00,0x00,
  35.729 +   0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x83,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,
  35.730 +   0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,
  35.731 +   0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,
  35.732 +   0x00,0x00,0x00,0xb3,0x00,0xef,0xef,0xef,0xf5,0x81,0xff,0xff,0xff,0xff,0x02,0xef,0xef,0xef,0xf5,0xaf,0xaf,0xaf,0xd6,0xc7,0xc7,0xc7,0xe1,0x82,0xff,0xff,0xff,0xff,
  35.733 +   0x81,0x00,0x00,0x00,0xb3,0x01,0x6a,0x6a,0x6a,0xc2,0xa0,0xa0,0xa0,0xd1,0x81,0x00,0x00,0x00,0xb3,0x00,0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,0xff,0x00,0x00,
  35.734 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xf2,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xf2,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,
  35.735 +   0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xa0,0xa0,0xa0,0xd1,0x83,0xff,0xff,0xff,0xff,0x02,0x90,0x90,0x90,0xcc,0x00,0x00,0x00,0xb3,
  35.736 +   0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x02,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0xd2,0xd2,0xd2,0xe6,0x81,0xff,0xff,0xff,0xff,0x00,0x52,0x52,0x52,0xbd,
  35.737 +   0x81,0x00,0x00,0x00,0xb3,0x00,0x52,0x52,0x52,0xbd,0x81,0xff,0xff,0xff,0xff,0x02,0xd2,0xd2,0xd2,0xe6,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,
  35.738 +   0xff,0x83,0x00,0x00,0x00,0xb3,0x02,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xef,0xef,0xef,0xf5,0x84,0xaf,0xaf,0xaf,0xd6,0x00,0xa0,0xa0,0xa0,0xd1,0x81,0x00,0x00,
  35.739 +   0x00,0xb3,0x01,0x33,0x33,0x33,0xb8,0x7e,0x7e,0x7e,0xc7,0x88,0x00,0x00,0x00,0xb3,0x02,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,
  35.740 +   0xff,0xff,0x06,0x33,0x33,0x33,0xb8,0xbb,0xbb,0xbb,0xdc,0xff,0xff,0xff,0xff,0xef,0xef,0xef,0xf5,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xaf,0xaf,0xaf,0xd6,0x82,
  35.741 +   0x00,0x00,0x00,0xb3,0x02,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x06,0x33,0x33,0x33,0xb8,0xbb,0xbb,0xbb,0xdc,0xff,
  35.742 +   0xff,0xff,0xff,0xef,0xef,0xef,0xf5,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,0x02,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,
  35.743 +   0xff,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x06,0x33,0x33,0x33,0xb8,0xbb,0xbb,0xbb,0xdc,0xff,0xff,0xff,0xff,0xef,0xef,0xef,0xf5,0xf7,0xf7,0xf7,0xfa,0xff,
  35.744 +   0xff,0xff,0xff,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x01,0x7e,0x7e,0x7e,0xc7,0x33,0x33,0x33,0xb8,0x81,0x00,0x00,0x00,0xb3,0x02,0xf7,0xf7,0xf7,0xfa,0xff,
  35.745 +   0xff,0xff,0xff,0xef,0xef,0xef,0xf5,0x82,0x00,0x00,0x00,0xb3,0x00,0xa0,0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,0xff,0x04,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xf7,
  35.746 +   0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xef,0xef,0xef,0xf5,0x84,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xbb,0xbb,0xbb,0xdc,0x81,
  35.747 +   0x00,0x00,0x00,0xb3,0x00,0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x01,0x00,0x00,
  35.748 +   0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xbb,0xbb,0xbb,0xdc,0x81,0x00,0x00,0x00,0xb3,0x00,0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,0x82,
  35.749 +   0x00,0x00,0x00,0xb3,0x02,0xa0,0xa0,0xa0,0xd1,0xc7,0xc7,0xc7,0xe1,0xef,0xef,0xef,0xf5,0x81,0xff,0xff,0xff,0xff,0x00,0xef,0xef,0xef,0xf5,0x81,0x00,0x00,0x00,0xb3,
  35.750 +   0x01,0x52,0x52,0x52,0xbd,0x6a,0x6a,0x6a,0xc2,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0xa0,0xa0,0xa0,0xd1,0x84,0x00,0x00,
  35.751 +   0x00,0xb3,0x00,0xd2,0xd2,0xd2,0xe6,0x81,0xff,0xff,0xff,0xff,0x00,0x52,0x52,0x52,0xbd,0x81,0x00,0x00,0x00,0xb3,0x00,0x52,0x52,0x52,0xbd,0x81,0xff,0xff,0xff,0xff,
  35.752 +   0x02,0xd2,0xd2,0xd2,0xe6,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,
  35.753 +   0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x04,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0xc7,0xc7,
  35.754 +   0xc7,0xe1,0xff,0xff,0xff,0xff,0xd2,0xd2,0xd2,0xe6,0x84,0x00,0x00,0x00,0xb3,0x02,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,
  35.755 +   0xff,0x0e,0x33,0x33,0x33,0xb8,0xbb,0xbb,0xbb,0xdc,0xff,0xff,0xff,0xff,0xef,0xef,0xef,0xf5,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xaf,0xaf,0xaf,0xd6,0x00,0x00,
  35.756 +   0x00,0xb3,0x33,0x33,0x33,0xb8,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xe6,0xe6,0xe6,0xf0,0xa0,0xa0,0xa0,0xd1,0x7e,0x7e,0x7e,0xc7,0xaf,0xaf,0xaf,0xd6,0x81,0xff,
  35.757 +   0xff,0xff,0xff,0x01,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x83,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,
  35.758 +   0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,
  35.759 +   0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,
  35.760 +   0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0xb3,0x6a,0x6a,0x6a,0xc2,0x81,0xff,0xff,0xff,0xff,0x00,0xe6,0xe6,0xe6,0xf0,0x82,0x00,0x00,0x00,
  35.761 +   0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x82,0x00,0x00,0x00,0xb3,0x02,0xa0,0xa0,0xa0,0xd1,0xc7,0xc7,0xc7,0xe1,0xef,0xef,0xef,0xf5,0x81,0xff,0xff,
  35.762 +   0xff,0xff,0x00,0xef,0xef,0xef,0xf5,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xf2,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
  35.763 +   0xf2,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x03,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xd2,0xd2,0xd2,0xe6,0xff,0xff,0xff,0xff,
  35.764 +   0x81,0xf7,0xf7,0xf7,0xfa,0x03,0xff,0xff,0xff,0xff,0xc7,0xc7,0xc7,0xe1,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x02,0x7e,0x7e,0x7e,0xc7,
  35.765 +   0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x83,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,
  35.766 +   0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x83,0x00,0x00,0x00,0xb3,0x87,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x8b,0x00,0x00,0x00,0xb3,0x00,0x90,0x90,
  35.767 +   0x90,0xcc,0x81,0xff,0xff,0xff,0xff,0x09,0xaf,0xaf,0xaf,0xd6,0xe6,0xe6,0xe6,0xf0,0xff,0xff,0xff,0xff,0x90,0x90,0x90,0xcc,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,
  35.768 +   0xbb,0xbb,0xbb,0xdc,0xd2,0xd2,0xd2,0xe6,0xff,0xff,0xff,0xff,0xe6,0xe6,0xe6,0xf0,0x81,0x00,0x00,0x00,0xb3,0x00,0x90,0x90,0x90,0xcc,0x81,0xff,0xff,0xff,0xff,0x09,
  35.769 +   0xaf,0xaf,0xaf,0xd6,0xe6,0xe6,0xe6,0xf0,0xff,0xff,0xff,0xff,0x90,0x90,0x90,0xcc,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0xbb,0xbb,0xbb,0xdc,0xd2,0xd2,0xd2,0xe6,
  35.770 +   0xff,0xff,0xff,0xff,0xe6,0xe6,0xe6,0xf0,0x81,0x00,0x00,0x00,0xb3,0x00,0x90,0x90,0x90,0xcc,0x81,0xff,0xff,0xff,0xff,0x09,0xaf,0xaf,0xaf,0xd6,0xe6,0xe6,0xe6,0xf0,
  35.771 +   0xff,0xff,0xff,0xff,0x90,0x90,0x90,0xcc,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0xbb,0xbb,0xbb,0xdc,0xd2,0xd2,0xd2,0xe6,0xff,0xff,0xff,0xff,0xe6,0xe6,0xe6,0xf0,
  35.772 +   0x85,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x01,0xaf,
  35.773 +   0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x84,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,
  35.774 +   0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,
  35.775 +   0xff,0xff,0xff,0x01,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,
  35.776 +   0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0xbb,0xbb,0xbb,0xdc,0x83,0xff,0xff,0xff,0xff,0x01,0xf7,0xf7,0xf7,0xfa,0xa0,0xa0,0xa0,0xd1,0x85,0x00,0x00,
  35.777 +   0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x84,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,
  35.778 +   0x83,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,
  35.779 +   0xc7,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x02,
  35.780 +   0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0x6a,0x6a,0x6a,0xc2,0x81,0xff,0xff,0xff,0xff,0x00,0x33,0x33,0x33,0xb8,0x82,0x00,0x00,0x00,0xb3,0x00,0x90,0x90,0x90,0xcc,
  35.781 +   0x81,0xff,0xff,0xff,0xff,0x09,0xaf,0xaf,0xaf,0xd6,0xe6,0xe6,0xe6,0xf0,0xff,0xff,0xff,0xff,0x90,0x90,0x90,0xcc,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0xbb,0xbb,
  35.782 +   0xbb,0xdc,0xd2,0xd2,0xd2,0xe6,0xff,0xff,0xff,0xff,0xe6,0xe6,0xe6,0xf0,0x81,0x00,0x00,0x00,0xb3,0x01,0x90,0x90,0x90,0xcc,0xf7,0xf7,0xf7,0xfa,0x85,0xff,0xff,0xff,
  35.783 +   0xff,0x01,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x83,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,
  35.784 +   0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,
  35.785 +   0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,
  35.786 +   0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,0x00,
  35.787 +   0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0xbb,0xbb,0xbb,0xdc,0x83,0xff,0xff,0xff,0xff,0x01,0xf7,0xf7,0xf7,0xfa,0xa0,0xa0,0xa0,
  35.788 +   0xd1,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xf2,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xf2,0x00,0x00,0x00,0xb3,0x00,
  35.789 +   0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x01,0xaf,0xaf,0xaf,0xd6,0x33,0x33,0x33,0xb8,0x81,0xff,0xff,0xff,0xff,0x81,0xc7,0xc7,0xc7,0xe1,0x03,0xff,0xff,0xff,
  35.790 +   0xff,0xf7,0xf7,0xf7,0xfa,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x02,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0xc7,0xc7,0xc7,0xe1,0x81,
  35.791 +   0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x02,0xc7,0xc7,0xc7,0xe1,0x00,0x00,0x00,
  35.792 +   0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x00,0x90,0x90,0x90,0xcc,0x82,0x00,0x00,0x00,0xb3,0x02,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0xef,0xef,0xef,
  35.793 +   0xf5,0x82,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xd2,0xd2,0xd2,0xe6,0x81,0x00,0x00,0x00,0xb3,0x01,0x33,0x33,0x33,0xb8,0x7e,0x7e,0x7e,0xc7,0x87,0x00,
  35.794 +   0x00,0x00,0xb3,0x00,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x03,0x52,0x52,0x52,0xbd,0xbb,0xbb,0xbb,0xdc,0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,0xeb,0x81,0xff,
  35.795 +   0xff,0xff,0xff,0x01,0x7e,0x7e,0x7e,0xc7,0xa0,0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,0xff,0x02,0x6a,0x6a,0x6a,0xc2,0x00,0x00,0x00,0xb3,0xc7,0xc7,0xc7,0xe1,0x81,0xff,
  35.796 +   0xff,0xff,0xff,0x03,0x52,0x52,0x52,0xbd,0xbb,0xbb,0xbb,0xdc,0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x01,0x7e,0x7e,0x7e,0xc7,0xa0,0xa0,
  35.797 +   0xa0,0xd1,0x81,0xff,0xff,0xff,0xff,0x02,0x6a,0x6a,0x6a,0xc2,0x00,0x00,0x00,0xb3,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x03,0x52,0x52,0x52,0xbd,0xbb,0xbb,
  35.798 +   0xbb,0xdc,0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x01,0x7e,0x7e,0x7e,0xc7,0xa0,0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,0xff,0x00,0x6a,0x6a,
  35.799 +   0x6a,0xc2,0x84,0x00,0x00,0x00,0xb3,0x03,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0x33,0x33,0x33,0xb8,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,
  35.800 +   0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x05,0xa0,0xa0,0xa0,0xd1,0x00,0x00,0x00,0xb3,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0x33,0x33,0x33,0xb8,
  35.801 +   0x81,0x00,0x00,0x00,0xb3,0x02,0x33,0x33,0x33,0xb8,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,
  35.802 +   0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0xb3,0x7e,
  35.803 +   0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,
  35.804 +   0xb3,0x82,0xff,0xff,0xff,0xff,0x02,0xc7,0xc7,0xc7,0xe1,0xa0,0xa0,0xa0,0xd1,0x33,0x33,0x33,0xb8,0x86,0x00,0x00,0x00,0xb3,0x00,0xa0,0xa0,0xa0,0xd1,0x81,0xff,0xff,
  35.805 +   0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0x33,0x33,0x33,0xb8,0x81,0x00,0x00,0x00,0xb3,0x00,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,
  35.806 +   0x00,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x02,0xc7,0xc7,0xc7,0xe1,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,
  35.807 +   0xd6,0x81,0xff,0xff,0xff,0xff,0x02,0xa0,0xa0,0xa0,0xd1,0x00,0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,0x81,0xff,0xff,0xff,0xff,0x00,0xef,0xef,0xef,0xf5,0x81,0x00,0x00,
  35.808 +   0x00,0xb3,0x00,0xbb,0xbb,0xbb,0xdc,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x02,0xe6,0xe6,0xe6,0xf0,0xff,0xff,0xff,0xff,0xaf,
  35.809 +   0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,0x00,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x03,0x52,0x52,0x52,0xbd,0xbb,0xbb,0xbb,0xdc,0xff,0xff,0xff,0xff,0xdc,
  35.810 +   0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x01,0x7e,0x7e,0x7e,0xc7,0xa0,0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,0xff,0x00,0x6a,0x6a,0x6a,0xc2,0x82,0x00,0x00,0x00,0xb3,
  35.811 +   0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xaf,0xaf,0xaf,0xd6,0x00,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x01,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0x82,0xff,0xff,
  35.812 +   0xff,0xff,0x00,0x33,0x33,0x33,0xb8,0x82,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xc7,0xc7,0xc7,0xe1,0x81,0x00,0x00,0x00,0xb3,
  35.813 +   0x00,0xef,0xef,0xef,0xf5,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,
  35.814 +   0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xc7,0xc7,0xc7,0xe1,0x81,0x00,0x00,0x00,0xb3,0x00,0xef,0xef,0xef,0xf5,0x81,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0xb3,0x6a,
  35.815 +   0x6a,0x6a,0xc2,0x81,0xff,0xff,0xff,0xff,0x00,0xe6,0xe6,0xe6,0xf0,0x82,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,
  35.816 +   0xb3,0x82,0xff,0xff,0xff,0xff,0x02,0xc7,0xc7,0xc7,0xe1,0xa0,0xa0,0xa0,0xd1,0x33,0x33,0x33,0xb8,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xf3,0x00,0x00,
  35.817 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xf2,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x01,0xaf,0xaf,0xaf,0xd6,
  35.818 +   0xa0,0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,0xff,0x01,0x7e,0x7e,0x7e,0xc7,0x6a,0x6a,0x6a,0xc2,0x81,0xff,0xff,0xff,0xff,0x01,0xa0,0xa0,0xa0,0xd1,0xaf,0xaf,0xaf,0xd6,
  35.819 +   0x81,0xff,0xff,0xff,0xff,0x02,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xf7,0xf7,0xf7,0xfa,0x81,0xbb,0xbb,0xbb,
  35.820 +   0xdc,0x00,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x02,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x04,0xf7,0xf7,
  35.821 +   0xf7,0xfa,0xbb,0xbb,0xbb,0xdc,0xaf,0xaf,0xaf,0xd6,0x7e,0x7e,0x7e,0xc7,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x02,0xa0,0xa0,0xa0,0xd1,0x00,0x00,0x00,0xb3,
  35.822 +   0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x05,0xa0,0xa0,0xa0,0xd1,0x00,0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xdc,0xdc,
  35.823 +   0xdc,0xeb,0x85,0x00,0x00,0x00,0xb3,0x00,0x33,0x33,0x33,0xb8,0x81,0xff,0xff,0xff,0xff,0x02,0xe6,0xe6,0xe6,0xf0,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x82,0xff,
  35.824 +   0xff,0xff,0xff,0x02,0xf7,0xf7,0xf7,0xfa,0x00,0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,0x81,0xff,0xff,0xff,0xff,0x01,0xbb,0xbb,0xbb,0xdc,0x33,0x33,0x33,0xb8,0x81,0xff,
  35.825 +   0xff,0xff,0xff,0x02,0xe6,0xe6,0xe6,0xf0,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x02,0xf7,0xf7,0xf7,0xfa,0x00,0x00,0x00,0xb3,0x33,0x33,
  35.826 +   0x33,0xb8,0x81,0xff,0xff,0xff,0xff,0x01,0xbb,0xbb,0xbb,0xdc,0x33,0x33,0x33,0xb8,0x81,0xff,0xff,0xff,0xff,0x02,0xe6,0xe6,0xe6,0xf0,0x00,0x00,0x00,0xb3,0x7e,0x7e,
  35.827 +   0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x02,0xf7,0xf7,0xf7,0xfa,0x00,0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,0x81,0xff,0xff,0xff,0xff,0x00,0xbb,0xbb,0xbb,0xdc,0x84,0x00,
  35.828 +   0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x02,0xef,0xef,0xef,0xf5,0xaf,0xaf,0xaf,0xd6,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x03,
  35.829 +   0xf7,0xf7,0xf7,0xfa,0x33,0x33,0x33,0xb8,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x05,0xef,0xef,0xef,0xf5,0xaf,0xaf,0xaf,0xd6,0xc7,0xc7,
  35.830 +   0xc7,0xe1,0xe6,0xe6,0xe6,0xf0,0x33,0x33,0x33,0xb8,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,
  35.831 +   0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,
  35.832 +   0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,
  35.833 +   0xff,0xff,0x03,0xe6,0xe6,0xe6,0xf0,0x33,0x33,0x33,0xb8,0x52,0x52,0x52,0xbd,0xaf,0xaf,0xaf,0xd6,0x86,0x00,0x00,0x00,0xb3,0x01,0x33,0x33,0x33,0xb8,0xf7,0xf7,0xf7,
  35.834 +   0xfa,0x81,0xff,0xff,0xff,0xff,0x05,0xc7,0xc7,0xc7,0xe1,0xaf,0xaf,0xaf,0xd6,0xef,0xef,0xef,0xf5,0xa0,0xa0,0xa0,0xd1,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,
  35.835 +   0xff,0xff,0xff,0xff,0x00,0xf7,0xf7,0xf7,0xfa,0x81,0xbb,0xbb,0xbb,0xdc,0x00,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x02,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,
  35.836 +   0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x02,0xf7,0xf7,0xf7,0xfa,0xaf,0xaf,0xaf,0xd6,0xd2,0xd2,0xd2,0xe6,0x82,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,
  35.837 +   0xeb,0xaf,0xaf,0xaf,0xd6,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x00,0x52,0x52,0x52,0xbd,0x81,0x00,0x00,0x00,0xb3,0x02,0xaf,0xaf,0xaf,0xd6,0xff,0xff,0xff,
  35.838 +   0xff,0xef,0xef,0xef,0xf5,0x81,0x00,0x00,0x00,0xb3,0x00,0x33,0x33,0x33,0xb8,0x81,0xff,0xff,0xff,0xff,0x02,0xe6,0xe6,0xe6,0xf0,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,
  35.839 +   0xc7,0x82,0xff,0xff,0xff,0xff,0x02,0xf7,0xf7,0xf7,0xfa,0x00,0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,0x81,0xff,0xff,0xff,0xff,0x00,0xbb,0xbb,0xbb,0xdc,0x81,0x00,0x00,
  35.840 +   0x00,0xb3,0x01,0xa0,0xa0,0xa0,0xd1,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x00,0xbb,0xbb,0xbb,0xdc,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x82,
  35.841 +   0xff,0xff,0xff,0xff,0x00,0xef,0xef,0xef,0xf5,0x81,0xaf,0xaf,0xaf,0xd6,0x01,0x52,0x52,0x52,0xbd,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x01,0xbb,0xbb,0xbb,
  35.842 +   0xdc,0xd2,0xd2,0xd2,0xe6,0x81,0xff,0xff,0xff,0xff,0x00,0xef,0xef,0xef,0xf5,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,
  35.843 +   0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x01,0xbb,0xbb,0xbb,0xdc,0xd2,0xd2,0xd2,0xe6,0x81,0xff,0xff,0xff,0xff,0x00,0xef,0xef,0xef,0xf5,0x81,0x00,
  35.844 +   0x00,0x00,0xb3,0x00,0xef,0xef,0xef,0xf5,0x81,0xff,0xff,0xff,0xff,0x02,0xef,0xef,0xef,0xf5,0xaf,0xaf,0xaf,0xd6,0xc7,0xc7,0xc7,0xe1,0x82,0xff,0xff,0xff,0xff,0x81,
  35.845 +   0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x03,0xe6,0xe6,0xe6,0xf0,0x33,0x33,0x33,0xb8,0x52,0x52,0x52,0xbd,0xaf,0xaf,0xaf,0xd6,0xff,0x00,0x00,0x00,0xb3,0xff,
  35.846 +   0x00,0x00,0x00,0xb3,0xf3,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xf2,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,
  35.847 +   0xff,0xff,0x03,0xaf,0xaf,0xaf,0xd6,0xd2,0xd2,0xd2,0xe6,0xff,0xff,0xff,0xff,0xef,0xef,0xef,0xf5,0x81,0x00,0x00,0x00,0xb3,0x03,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,
  35.848 +   0xff,0xd2,0xd2,0xd2,0xe6,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x00,0xc7,0xc7,0xc7,0xe1,0x85,0xff,0xff,
  35.849 +   0xff,0xff,0x00,0xc7,0xc7,0xc7,0xe1,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x00,0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,
  35.850 +   0x02,0xaf,0xaf,0xaf,0xd6,0x33,0x33,0x33,0xb8,0xe6,0xe6,0xe6,0xf0,0x84,0xff,0xff,0xff,0xff,0x00,0xe6,0xe6,0xe6,0xf0,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,
  35.851 +   0xc7,0x82,0xff,0xff,0xff,0xff,0x85,0x00,0x00,0x00,0xb3,0x00,0xa0,0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x82,
  35.852 +   0xff,0xff,0xff,0xff,0x00,0xd2,0xd2,0xd2,0xe6,0x81,0x00,0x00,0x00,0xb3,0x03,0xe6,0xe6,0xe6,0xf0,0xff,0xff,0xff,0xff,0xef,0xef,0xef,0xf5,0xa0,0xa0,0xa0,0xd1,0x81,
  35.853 +   0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x82,0xff,0xff,0xff,0xff,0x00,0xd2,0xd2,0xd2,0xe6,0x81,0x00,0x00,0x00,0xb3,0x03,0xe6,0xe6,
  35.854 +   0xe6,0xf0,0xff,0xff,0xff,0xff,0xef,0xef,0xef,0xf5,0xa0,0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x82,0xff,0xff,
  35.855 +   0xff,0xff,0x00,0xd2,0xd2,0xd2,0xe6,0x81,0x00,0x00,0x00,0xb3,0x02,0xe6,0xe6,0xe6,0xf0,0xff,0xff,0xff,0xff,0xef,0xef,0xef,0xf5,0x84,0x00,0x00,0x00,0xb3,0x01,0x33,
  35.856 +   0x33,0x33,0xb8,0xe6,0xe6,0xe6,0xf0,0x85,0xff,0xff,0xff,0xff,0x00,0xa0,0xa0,0xa0,0xd1,0x82,0x00,0x00,0x00,0xb3,0x00,0xe6,0xe6,0xe6,0xf0,0x84,0xff,0xff,0xff,0xff,
  35.857 +   0x01,0xe6,0xe6,0xe6,0xf0,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,
  35.858 +   0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,
  35.859 +   0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0xbb,0xbb,0xbb,0xdc,0x84,0xff,0xff,
  35.860 +   0xff,0xff,0x00,0xc7,0xc7,0xc7,0xe1,0x86,0x00,0x00,0x00,0xb3,0x00,0x90,0x90,0x90,0xcc,0x85,0xff,0xff,0xff,0xff,0x02,0x90,0x90,0x90,0xcc,0x00,0x00,0x00,0xb3,0xc7,
  35.861 +   0xc7,0xc7,0xe1,0x85,0xff,0xff,0xff,0xff,0x00,0xc7,0xc7,0xc7,0xe1,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0xf7,0xf7,0xf7,
  35.862 +   0xfa,0x83,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x83,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0x00,0x00,0x00,0xb3,0x00,0x33,0x33,0x33,0xb8,0x81,
  35.863 +   0xff,0xff,0xff,0xff,0x02,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0xa0,0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,
  35.864 +   0x82,0xff,0xff,0xff,0xff,0x00,0xd2,0xd2,0xd2,0xe6,0x81,0x00,0x00,0x00,0xb3,0x04,0xe6,0xe6,0xe6,0xf0,0xff,0xff,0xff,0xff,0xef,0xef,0xef,0xf5,0x00,0x00,0x00,0xb3,
  35.865 +   0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x81,0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,0x00,0xc7,0xc7,0xc7,0xe1,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,
  35.866 +   0xff,0xff,0x01,0xef,0xef,0xef,0xf5,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x81,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xf7,0xf7,0xf7,0xfa,0x83,
  35.867 +   0xff,0xff,0xff,0xff,0x00,0xc7,0xc7,0xc7,0xe1,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,
  35.868 +   0x81,0xff,0xff,0xff,0xff,0x00,0xf7,0xf7,0xf7,0xfa,0x83,0xff,0xff,0xff,0xff,0x00,0xc7,0xc7,0xc7,0xe1,0x81,0x00,0x00,0x00,0xb3,0x00,0x90,0x90,0x90,0xcc,0x84,0xff,
  35.869 +   0xff,0xff,0xff,0x00,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0xbb,0xbb,0xbb,0xdc,0x84,0xff,0xff,0xff,0xff,0x00,0xc7,0xc7,0xc7,
  35.870 +   0xe1,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xf2,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xf2,0x00,0x00,0x00,0xb3,0x00,
  35.871 +   0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xbb,0xbb,0xbb,0xdc,0x81,0xff,0xff,0xff,0xff,0x00,0xbb,0xbb,0xbb,0xdc,0x81,0x00,0x00,0x00,0xb3,0x00,0xbb,0xbb,
  35.872 +   0xbb,0xdc,0x81,0xff,0xff,0xff,0xff,0x00,0xbb,0xbb,0xbb,0xdc,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0x00,0x00,0x00,0xb3,0x01,0xa0,0xa0,0xa0,0xd1,
  35.873 +   0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,0x01,0xe6,0xe6,0xe6,0xf0,0xa0,0xa0,0xa0,0xd1,0x82,0x00,0x00,0x00,0xb3,0x00,0xbb,0xbb,0xbb,0xdc,0x81,0xdc,0xdc,0xdc,
  35.874 +   0xeb,0x0b,0x6a,0x6a,0x6a,0xc2,0xdc,0xdc,0xdc,0xeb,0xff,0xff,0xff,0xff,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,0xaf,0xaf,0xaf,0xd6,0xef,0xef,
  35.875 +   0xef,0xf5,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0xc7,0xc7,0xc7,0xe1,0x33,0x33,0x33,0xb8,0x82,0x00,0x00,0x00,0xb3,0x02,0xdc,0xdc,0xdc,0xeb,0xff,0xff,0xff,0xff,
  35.876 +   0xaf,0xaf,0xaf,0xd6,0x85,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xdc,0xdc,0xdc,0xeb,0x00,0x52,0x52,0x52,0xbd,0x81,0x00,0x00,0x00,0xb3,0x00,0xbb,0xbb,
  35.877 +   0xbb,0xdc,0x81,0xdc,0xdc,0xdc,0xeb,0x00,0x90,0x90,0x90,0xcc,0x81,0x00,0x00,0x00,0xb3,0x00,0xa0,0xa0,0xa0,0xd1,0x81,0xdc,0xdc,0xdc,0xeb,0x00,0xaf,0xaf,0xaf,0xd6,
  35.878 +   0x81,0xdc,0xdc,0xdc,0xeb,0x00,0x52,0x52,0x52,0xbd,0x81,0x00,0x00,0x00,0xb3,0x00,0xbb,0xbb,0xbb,0xdc,0x81,0xdc,0xdc,0xdc,0xeb,0x00,0x90,0x90,0x90,0xcc,0x81,0x00,
  35.879 +   0x00,0x00,0xb3,0x00,0xa0,0xa0,0xa0,0xd1,0x81,0xdc,0xdc,0xdc,0xeb,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xdc,0xdc,0xdc,0xeb,0x00,0x52,0x52,0x52,0xbd,0x81,0x00,0x00,0x00,
  35.880 +   0xb3,0x00,0xbb,0xbb,0xbb,0xdc,0x81,0xdc,0xdc,0xdc,0xeb,0x00,0x90,0x90,0x90,0xcc,0x81,0x00,0x00,0x00,0xb3,0x00,0xa0,0xa0,0xa0,0xd1,0x81,0xdc,0xdc,0xdc,0xeb,0x00,
  35.881 +   0x52,0x52,0x52,0xbd,0x84,0x00,0x00,0x00,0xb3,0x02,0x33,0x33,0x33,0xb8,0xaf,0xaf,0xaf,0xd6,0xef,0xef,0xef,0xf5,0x81,0xff,0xff,0xff,0xff,0x01,0xd2,0xd2,0xd2,0xe6,
  35.882 +   0x7e,0x7e,0x7e,0xc7,0x84,0x00,0x00,0x00,0xb3,0x01,0xaf,0xaf,0xaf,0xd6,0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,0x02,0xd2,0xd2,0xd2,0xe6,0x7e,0x7e,0x7e,0xc7,
  35.883 +   0x6a,0x6a,0x6a,0xc2,0x81,0xdc,0xdc,0xdc,0xeb,0x00,0xa0,0xa0,0xa0,0xd1,0x81,0x00,0x00,0x00,0xb3,0x00,0xbb,0xbb,0xbb,0xdc,0x81,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,
  35.884 +   0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0xb3,0x6a,0x6a,0x6a,0xc2,0x81,0xdc,0xdc,0xdc,0xeb,0x00,0xa0,0xa0,0xa0,0xd1,0x81,
  35.885 +   0x00,0x00,0x00,0xb3,0x00,0xbb,0xbb,0xbb,0xdc,0x81,0xdc,0xdc,0xdc,0xeb,0x82,0x00,0x00,0x00,0xb3,0x01,0xaf,0xaf,0xaf,0xd6,0xef,0xef,0xef,0xf5,0x81,0xff,0xff,0xff,
  35.886 +   0xff,0x01,0xd2,0xd2,0xd2,0xe6,0x7e,0x7e,0x7e,0xc7,0x87,0x00,0x00,0x00,0xb3,0x06,0x6a,0x6a,0x6a,0xc2,0xd2,0xd2,0xd2,0xe6,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,
  35.887 +   0xef,0xef,0xef,0xf5,0xaf,0xaf,0xaf,0xd6,0x33,0x33,0x33,0xb8,0x81,0x00,0x00,0x00,0xb3,0x01,0xa0,0xa0,0xa0,0xd1,0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,0x01,
  35.888 +   0xe6,0xe6,0xe6,0xf0,0xa0,0xa0,0xa0,0xd1,0x82,0x00,0x00,0x00,0xb3,0x00,0xa0,0xa0,0xa0,0xd1,0x81,0xdc,0xdc,0xdc,0xeb,0x06,0x7e,0x7e,0x7e,0xc7,0xd2,0xd2,0xd2,0xe6,
  35.889 +   0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xbb,0xbb,0xbb,0xdc,0x81,0xff,0xff,0xff,0xff,0x01,0xdc,0xdc,0xdc,0xeb,0x6a,0x6a,
  35.890 +   0x6a,0xc2,0x83,0x00,0x00,0x00,0xb3,0x04,0xc7,0xc7,0xc7,0xe1,0xff,0xff,0xff,0xff,0xc7,0xc7,0xc7,0xe1,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xdc,0xdc,0xdc,
  35.891 +   0xeb,0x00,0x52,0x52,0x52,0xbd,0x81,0x00,0x00,0x00,0xb3,0x00,0xbb,0xbb,0xbb,0xdc,0x81,0xdc,0xdc,0xdc,0xeb,0x00,0x90,0x90,0x90,0xcc,0x81,0x00,0x00,0x00,0xb3,0x00,
  35.892 +   0xa0,0xa0,0xa0,0xd1,0x81,0xdc,0xdc,0xdc,0xeb,0x03,0x52,0x52,0x52,0xbd,0x00,0x00,0x00,0xb3,0xa0,0xa0,0xa0,0xd1,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x02,
  35.893 +   0xef,0xef,0xef,0xf5,0xbb,0xbb,0xbb,0xdc,0x33,0x33,0x33,0xb8,0x81,0x00,0x00,0x00,0xb3,0x81,0xdc,0xdc,0xdc,0xeb,0x05,0xbb,0xbb,0xbb,0xdc,0x90,0x90,0x90,0xcc,0xef,
  35.894 +   0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0x7e,0x7e,0x7e,0xc7,0x6a,0x6a,0x6a,0xc2,0x81,0xdc,0xdc,0xdc,0xeb,0x01,0xa0,0xa0,0xa0,0xd1,0xbb,0xbb,0xbb,0xdc,0x81,0xff,0xff,
  35.895 +   0xff,0xff,0x01,0xc7,0xc7,0xc7,0xe1,0x33,0x33,0x33,0xb8,0x81,0x00,0x00,0x00,0xb3,0x81,0xdc,0xdc,0xdc,0xeb,0x02,0xbb,0xbb,0xbb,0xdc,0x00,0x00,0x00,0xb3,0x6a,0x6a,
  35.896 +   0x6a,0xc2,0x81,0xdc,0xdc,0xdc,0xeb,0x01,0xa0,0xa0,0xa0,0xd1,0xbb,0xbb,0xbb,0xdc,0x81,0xff,0xff,0xff,0xff,0x01,0xc7,0xc7,0xc7,0xe1,0x33,0x33,0x33,0xb8,0x82,0x00,
  35.897 +   0x00,0x00,0xb3,0x05,0x90,0x90,0x90,0xcc,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0xef,0xef,0xef,0xf5,0xaf,0xaf,0xaf,0xd6,0xa0,0xa0,0xa0,0xd1,0x81,0xdc,0xdc,0xdc,
  35.898 +   0xeb,0x82,0x00,0x00,0x00,0xb3,0x01,0xaf,0xaf,0xaf,0xd6,0xef,0xef,0xef,0xf5,0x81,0xff,0xff,0xff,0xff,0x01,0xd2,0xd2,0xd2,0xe6,0x7e,0x7e,0x7e,0xc7,0xff,0x00,0x00,
  35.899 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xf2,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xf2,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,
  35.900 +   0x81,0xff,0xff,0xff,0xff,0x00,0xef,0xef,0xef,0xf5,0x81,0xff,0xff,0xff,0xff,0x00,0x6a,0x6a,0x6a,0xc2,0x81,0x00,0x00,0x00,0xb3,0x00,0x52,0x52,0x52,0xbd,0x81,0xff,
  35.901 +   0xff,0xff,0xff,0x00,0xef,0xef,0xef,0xf5,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0xf6,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,
  35.902 +   0xff,0xbe,0x00,0x00,0x00,0xb3,0x03,0x90,0x90,0x90,0xcc,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0x33,0x33,0x33,0xb8,0xab,0x00,0x00,0x00,0xb3,0x01,0x33,0x33,0x33,
  35.903 +   0xb8,0x7e,0x7e,0x7e,0xc7,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0x91,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
  35.904 +   0x00,0x00,0xb3,0xf2,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x83,0xff,0xff,0xff,0xff,0x00,0xe6,0xe6,0xe6,0xf0,0x83,0x00,0x00,0x00,0xb3,0x00,0xe6,0xe6,0xe6,
  35.905 +   0xf0,0x83,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0xf6,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0xbf,0x00,0x00,0x00,0xb3,0x02,
  35.906 +   0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0xa0,0xa0,0xa0,0xd1,0xaa,0x00,0x00,0x00,0xb3,0x03,0x33,0x33,0x33,0xb8,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xdc,0xdc,
  35.907 +   0xdc,0xeb,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0x90,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
  35.908 +   0xf2,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x83,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x83,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x83,0xff,
  35.909 +   0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0xf6,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0xbf,0x00,0x00,0x00,0xb3,0x02,0xaf,0xaf,0xaf,
  35.910 +   0xd6,0xff,0xff,0xff,0xff,0xe6,0xe6,0xe6,0xf0,0xaa,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
  35.911 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0x90,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xf2,0x00,0x00,0x00,0xb3,0x00,0x6a,0x6a,0x6a,0xc2,
  35.912 +   0x83,0xdc,0xdc,0xdc,0xeb,0x00,0x52,0x52,0x52,0xbd,0x83,0x00,0x00,0x00,0xb3,0x00,0x52,0x52,0x52,0xbd,0x83,0xdc,0xdc,0xdc,0xeb,0x00,0x6a,0x6a,0x6a,0xc2,0xf6,0x00,
  35.913 +   0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0xbf,0x00,0x00,0x00,0xb3,0x00,0x52,0x52,0x52,0xbd,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,
  35.914 +   0xc7,0xaa,0x00,0x00,0x00,0xb3,0x02,0xdc,0xdc,0xdc,0xeb,0xff,0xff,0xff,0xff,0xaf,0xaf,0xaf,0xd6,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
  35.915 +   0x00,0xb3,0x90,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xf9,0x00,0x00,0x00,0xb3,0x00,0xa0,0xa0,0xa0,0xd1,
  35.916 +   0x81,0xaf,0xaf,0xaf,0xd6,0xc0,0x00,0x00,0x00,0xb3,0x01,0xaf,0xaf,0xaf,0xd6,0x90,0x90,0x90,0xcc,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
  35.917 +   0x00,0xb3,0xbf,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
  35.918 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
  35.919 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
  35.920 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
  35.921 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
  35.922 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
  35.923 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
  35.924 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
  35.925 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
  35.926 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
  35.927 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
  35.928 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
  35.929 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
  35.930 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
  35.931 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
  35.932 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
  35.933 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
  35.934 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
  35.935 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
  35.936 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
  35.937 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
  35.938 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
  35.939 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
  35.940 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
  35.941 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
  35.942 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
  35.943 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
  35.944 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
  35.945 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
  35.946 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
  35.947 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
  35.948 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
  35.949 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
  35.950 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
  35.951 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
  35.952 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
  35.953 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
  35.954 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
  35.955 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
  35.956 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
  35.957 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
  35.958 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
  35.959 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
  35.960 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
  35.961 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
  35.962 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
  35.963 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
  35.964 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
  35.965 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
  35.966 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
  35.967 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
  35.968 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0x03,0x00,
  35.969 +   0x00,0x00,0xb3,0x6a,0x6a,0x6a,0xc2,0x7e,0x7e,0x7e,0xc7,0x33,0x33,0x33,0xb8,0x8a,0x00,0x00,0x00,0xb3,0x00,0x33,0x33,0x33,0xb8,0x81,0x7e,0x7e,0x7e,0xc7,0x00,0x52,
  35.970 +   0x52,0x52,0xbd,0x86,0x00,0x00,0x00,0xb3,0x02,0x6a,0x6a,0x6a,0xc2,0x7e,0x7e,0x7e,0xc7,0x52,0x52,0x52,0xbd,0x84,0x00,0x00,0x00,0xb3,0x00,0x52,0x52,0x52,0xbd,0x81,
  35.971 +   0x7e,0x7e,0x7e,0xc7,0x9e,0x00,0x00,0x00,0xb3,0x81,0x7e,0x7e,0x7e,0xc7,0x00,0x52,0x52,0x52,0xbd,0x8d,0x00,0x00,0x00,0xb3,0x00,0x33,0x33,0x33,0xb8,0x81,0x7e,0x7e,
  35.972 +   0x7e,0xc7,0x00,0x33,0x33,0x33,0xb8,0x88,0x00,0x00,0x00,0xb3,0x00,0x33,0x33,0x33,0xb8,0x81,0x7e,0x7e,0x7e,0xc7,0x00,0x33,0x33,0x33,0xb8,0x9e,0x00,0x00,0x00,0xb3,
  35.973 +   0x81,0x7e,0x7e,0x7e,0xc7,0x00,0x33,0x33,0x33,0xb8,0x84,0x00,0x00,0x00,0xb3,0x02,0x52,0x52,0x52,0xbd,0x7e,0x7e,0x7e,0xc7,0x52,0x52,0x52,0xbd,0x8b,0x00,0x00,0x00,
  35.974 +   0xb3,0x00,0x33,0x33,0x33,0xb8,0x81,0x7e,0x7e,0x7e,0xc7,0x00,0x33,0x33,0x33,0xb8,0x9a,0x00,0x00,0x00,0xb3,0x02,0x52,0x52,0x52,0xbd,0x7e,0x7e,0x7e,0xc7,0x6a,0x6a,
  35.975 +   0x6a,0xc2,0x85,0x00,0x00,0x00,0xb3,0x02,0x6a,0x6a,0x6a,0xc2,0x7e,0x7e,0x7e,0xc7,0x33,0x33,0x33,0xb8,0x87,0x00,0x00,0x00,0xb3,0x02,0x52,0x52,0x52,0xbd,0x7e,0x7e,
  35.976 +   0x7e,0xc7,0x6a,0x6a,0x6a,0xc2,0x84,0x00,0x00,0x00,0xb3,0x00,0x52,0x52,0x52,0xbd,0x81,0x7e,0x7e,0x7e,0xc7,0x89,0x00,0x00,0x00,0xb3,0x81,0x7e,0x7e,0x7e,0xc7,0x00,
  35.977 +   0x52,0x52,0x52,0xbd,0x8f,0x00,0x00,0x00,0xb3,0x00,0x6a,0x6a,0x6a,0xc2,0x81,0x7e,0x7e,0x7e,0xc7,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
  35.978 +   0x00,0xb3,0x85,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xfe,0x00,0x00,0x00,0xb3,0x01,0x6a,0x6a,0x6a,0xc2,0xe6,0xe6,0xe6,0xf0,0x81,
  35.979 +   0xff,0xff,0xff,0xff,0x01,0xf7,0xf7,0xf7,0xfa,0xa0,0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,
  35.980 +   0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x33,0x33,0x33,0xb8,0xc7,0xc7,0xc7,0xe1,0x83,0xff,0xff,0xff,0xff,0x01,0xef,0xef,0xef,0xf5,0x6a,0x6a,0x6a,0xc2,0x82,
  35.981 +   0x00,0x00,0x00,0xb3,0x01,0xaf,0xaf,0xaf,0xd6,0xef,0xef,0xef,0xf5,0x82,0xff,0xff,0xff,0xff,0x04,0xdc,0xdc,0xdc,0xeb,0x6a,0x6a,0x6a,0xc2,0x00,0x00,0x00,0xb3,0x6a,
  35.982 +   0x6a,0x6a,0xc2,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x01,0xf7,0xf7,0xf7,0xfa,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,
  35.983 +   0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,
  35.984 +   0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x83,0x00,0x00,0x00,0xb3,
  35.985 +   0x01,0xaf,0xaf,0xaf,0xd6,0xf7,0xf7,0xf7,0xfa,0x82,0xff,0xff,0xff,0xff,0x01,0xdc,0xdc,0xdc,0xeb,0x6a,0x6a,0x6a,0xc2,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,
  35.986 +   0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x84,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x83,0xff,0xff,0xff,0xff,0x86,0x00,0x00,0x00,0xb3,0x01,
  35.987 +   0x33,0x33,0x33,0xb8,0xc7,0xc7,0xc7,0xe1,0x83,0xff,0xff,0xff,0xff,0x01,0xc7,0xc7,0xc7,0xe1,0x33,0x33,0x33,0xb8,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,
  35.988 +   0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x88,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,
  35.989 +   0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x02,0x33,0x33,0x33,0xb8,0xbb,0xbb,0xbb,0xdc,0xf7,0xf7,0xf7,0xfa,0x82,
  35.990 +   0xff,0xff,0xff,0xff,0x04,0xc7,0xc7,0xc7,0xe1,0x33,0x33,0x33,0xb8,0x00,0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x05,0xdc,
  35.991 +   0xdc,0xdc,0xeb,0xe6,0xe6,0xe6,0xf0,0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,
  35.992 +   0xc7,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x83,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,
  35.993 +   0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x86,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,
  35.994 +   0xeb,0x84,0x00,0x00,0x00,0xb3,0x01,0x7e,0x7e,0x7e,0xc7,0xe6,0xe6,0xe6,0xf0,0x82,0xff,0xff,0xff,0xff,0x01,0xef,0xef,0xef,0xf5,0x90,0x90,0x90,0xcc,0x81,0x00,0x00,
  35.995 +   0x00,0xb3,0x01,0x6a,0x6a,0x6a,0xc2,0xef,0xef,0xef,0xf5,0x82,0xff,0xff,0xff,0xff,0x00,0xbb,0xbb,0xbb,0xdc,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,
  35.996 +   0x00,0x00,0x00,0xb3,0x01,0x7e,0x7e,0x7e,0xc7,0xe6,0xe6,0xe6,0xf0,0x82,0xff,0xff,0xff,0xff,0x01,0xef,0xef,0xef,0xf5,0x90,0x90,0x90,0xcc,0x81,0x00,0x00,0x00,0xb3,
  35.997 +   0x00,0xd2,0xd2,0xd2,0xe6,0x82,0xff,0xff,0xff,0xff,0x01,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0x00,0x00,
  35.998 +   0x00,0xb3,0x01,0xaf,0xaf,0xaf,0xd6,0xf7,0xf7,0xf7,0xfa,0x82,0xff,0xff,0xff,0xff,0x01,0xdc,0xdc,0xdc,0xeb,0x6a,0x6a,0x6a,0xc2,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,
  35.999 +   0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x02,0x00,0x00,0x00,
 35.1000 +   0xb3,0x90,0x90,0x90,0xcc,0xef,0xef,0xef,0xf5,0x83,0xff,0xff,0xff,0xff,0x00,0xbb,0xbb,0xbb,0xdc,0x81,0x00,0x00,0x00,0xb3,0x03,0x90,0x90,0x90,0xcc,0xf7,0xf7,0xf7,
 35.1001 +   0xfa,0xef,0xef,0xef,0xf5,0x52,0x52,0x52,0xbd,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xfd,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
 35.1002 +   0x00,0xb3,0xfd,0x00,0x00,0x00,0xb3,0x01,0x33,0x33,0x33,0xb8,0xf7,0xf7,0xf7,0xfa,0x86,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0x7e,0x7e,
 35.1003 +   0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x05,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xd2,0xd2,0xd2,0xe6,0xff,0xff,0xff,0xff,0xef,0xef,0xef,0xf5,0xdc,0xdc,0xdc,0xeb,
 35.1004 +   0x81,0xff,0xff,0xff,0xff,0x03,0xf7,0xf7,0xf7,0xfa,0x33,0x33,0x33,0xb8,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x84,0xff,0xff,0xff,0xff,0x03,0xf7,0xf7,0xf7,0xfa,
 35.1005 +   0x6a,0x6a,0x6a,0xc2,0x52,0x52,0x52,0xbd,0xf7,0xf7,0xf7,0xfa,0x85,0xff,0xff,0xff,0xff,0x00,0xbb,0xbb,0xbb,0xdc,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,
 35.1006 +   0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,
 35.1007 +   0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,
 35.1008 +   0xb3,0x00,0xbb,0xbb,0xbb,0xdc,0x85,0xff,0xff,0xff,0xff,0x03,0xf7,0xf7,0xf7,0xfa,0x52,0x52,0x52,0xbd,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,
 35.1009 +   0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x83,0x00,0x00,0x00,0xb3,0x00,0x52,0x52,0x52,0xbd,0x84,0xff,0xff,0xff,0xff,0x86,0x00,0x00,0x00,0xb3,0x00,0xe6,0xe6,0xe6,0xf0,0x85,
 35.1010 +   0xff,0xff,0xff,0xff,0x00,0xe6,0xe6,0xe6,0xf0,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x88,0x00,0x00,
 35.1011 +   0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,
 35.1012 +   0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,
 35.1013 +   0x00,0xb3,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x02,0xc7,0xc7,0xc7,0xe1,0xaf,0xaf,0xaf,0xd6,0xef,0xef,0xef,0xf5,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,
 35.1014 +   0xdc,0xeb,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x02,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0x52,0x52,0x52,0xbd,0x84,0xff,0xff,0xff,
 35.1015 +   0xff,0x01,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,
 35.1016 +   0xdc,0xdc,0xeb,0x86,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x83,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,
 35.1017 +   0xff,0x09,0xf7,0xf7,0xf7,0xfa,0xdc,0xdc,0xdc,0xeb,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0x33,0x33,0x33,0xb8,0x00,0x00,0x00,0xb3,0xef,0xef,
 35.1018 +   0xef,0xf5,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0x81,0xbb,0xbb,0xbb,0xdc,0x00,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,
 35.1019 +   0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x85,0xff,0xff,0xff,0xff,0x02,0xa0,0xa0,0xa0,0xd1,0x00,0x00,0x00,0xb3,0xa0,0xa0,0xa0,0xd1,0x83,0xff,0xff,0xff,0xff,0x01,0xdc,0xdc,
 35.1020 +   0xdc,0xeb,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x00,0xbb,0xbb,0xbb,0xdc,0x85,0xff,0xff,0xff,0xff,0x03,
 35.1021 +   0xf7,0xf7,0xf7,0xfa,0x52,0x52,0x52,0xbd,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,
 35.1022 +   0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0xb3,0x6a,0x6a,0x6a,0xc2,0x81,0xff,0xff,0xff,0xff,0x01,0xdc,0xdc,0xdc,0xeb,0xef,0xef,0xef,0xf5,
 35.1023 +   0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0xff,0x00,0x00,0x00,
 35.1024 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xfd,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xfd,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,
 35.1025 +   0xff,0xff,0xff,0xff,0x03,0xe6,0xe6,0xe6,0xf0,0x90,0x90,0x90,0xcc,0x7e,0x7e,0x7e,0xc7,0xd2,0xd2,0xd2,0xe6,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,
 35.1026 +   0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x03,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,
 35.1027 +   0x00,0xb3,0x00,0xbb,0xbb,0xbb,0xdc,0x81,0xff,0xff,0xff,0xff,0x01,0x7e,0x7e,0x7e,0xc7,0x52,0x52,0x52,0xbd,0x81,0xff,0xff,0xff,0xff,0x06,0xf7,0xf7,0xf7,0xfa,0xa0,
 35.1028 +   0xa0,0xa0,0xd1,0x7e,0x7e,0x7e,0xc7,0xd2,0xd2,0xd2,0xe6,0x6a,0x6a,0x6a,0xc2,0x00,0x00,0x00,0xb3,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x03,0xd2,0xd2,0xd2,
 35.1029 +   0xe6,0x7e,0x7e,0x7e,0xc7,0xa0,0xa0,0xa0,0xd1,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x02,0x52,0x52,0x52,0xbd,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,
 35.1030 +   0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,
 35.1031 +   0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,
 35.1032 +   0x00,0x52,0x52,0x52,0xbd,0x81,0xff,0xff,0xff,0xff,0x03,0xf7,0xf7,0xf7,0xfa,0xa0,0xa0,0xa0,0xd1,0x7e,0x7e,0x7e,0xc7,0xd2,0xd2,0xd2,0xe6,0x81,0xff,0xff,0xff,0xff,
 35.1033 +   0x02,0xc7,0xc7,0xc7,0xe1,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x83,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,
 35.1034 +   0xc7,0x81,0xff,0xff,0xff,0xff,0x02,0xd2,0xd2,0xd2,0xe6,0x00,0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,0x85,0x00,0x00,0x00,0xb3,0x00,0xa0,0xa0,0xa0,0xd1,0x81,0xff,0xff,
 35.1035 +   0xff,0xff,0x00,0xe6,0xe6,0xe6,0xf0,0x81,0x90,0x90,0x90,0xcc,0x00,0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,0x02,0xa0,0xa0,0xa0,0xd1,0x00,0x00,0x00,0xb3,0xaf,
 35.1036 +   0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x88,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,
 35.1037 +   0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xa0,0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,
 35.1038 +   0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x01,0xa0,0xa0,0xa0,0xd1,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x02,0xdc,0xdc,0xdc,0xeb,0xff,0xff,0xff,0xff,0xdc,0xdc,
 35.1039 +   0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x05,0x33,0x33,0x33,0xb8,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,
 35.1040 +   0x81,0xff,0xff,0xff,0xff,0x02,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x04,0xd2,0xd2,0xd2,0xe6,0x00,0x00,0x00,0xb3,
 35.1041 +   0x33,0x33,0x33,0xb8,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,
 35.1042 +   0x00,0xdc,0xdc,0xdc,0xeb,0x86,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x83,0x00,0x00,0x00,0xb3,0x07,0xef,0xef,0xef,0xf5,0xff,0xff,
 35.1043 +   0xff,0xff,0xef,0xef,0xef,0xf5,0x33,0x33,0x33,0xb8,0x00,0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,0xc7,0xc7,0xc7,0xe1,0x52,0x52,0x52,0xbd,0x81,0x00,0x00,0x00,0xb3,0x81,
 35.1044 +   0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0x6a,0x6a,0x6a,0xc2,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,
 35.1045 +   0xb3,0xef,0xef,0xef,0xf5,0x81,0xff,0xff,0xff,0xff,0x03,0xaf,0xaf,0xaf,0xd6,0x7e,0x7e,0x7e,0xc7,0xbb,0xbb,0xbb,0xdc,0xa0,0xa0,0xa0,0xd1,0x81,0x00,0x00,0x00,0xb3,
 35.1046 +   0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x03,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,
 35.1047 +   0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0x52,0x52,0x52,0xbd,0x81,0xff,0xff,0xff,0xff,0x03,0xf7,0xf7,0xf7,0xfa,0xa0,0xa0,0xa0,0xd1,0x7e,0x7e,0x7e,0xc7,0xd2,
 35.1048 +   0xd2,0xd2,0xe6,0x81,0xff,0xff,0xff,0xff,0x02,0xc7,0xc7,0xc7,0xe1,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,
 35.1049 +   0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x03,0xa0,0xa0,0xa0,0xd1,0x6a,0x6a,0x6a,0xc2,0x00,0x00,0x00,0xb3,
 35.1050 +   0x33,0x33,0x33,0xb8,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,
 35.1051 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xfd,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xfd,0x00,0x00,0x00,0xb3,0x00,0xdc,
 35.1052 +   0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x00,0x52,0x52,0x52,0xbd,0x82,0x00,0x00,0x00,0xb3,0x04,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0xaf,0xaf,0xaf,0xd6,0x00,
 35.1053 +   0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x02,0x7e,0x7e,0x7e,0xc7,0xbb,0xbb,0xbb,0xdc,0xe6,
 35.1054 +   0xe6,0xe6,0xf0,0x82,0xff,0xff,0xff,0xff,0x01,0x52,0x52,0x52,0xbd,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0xa0,0xa0,0xa0,0xd1,0x84,0x00,0x00,0x00,0xb3,
 35.1055 +   0x02,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xef,0xef,0xef,0xf5,0x82,0x00,0x00,0x00,0xb3,0x00,0xa0,0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,
 35.1056 +   0xd6,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,
 35.1057 +   0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,
 35.1058 +   0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0xa0,0xa0,0xa0,0xd1,0x82,0x00,0x00,0x00,0xb3,0x04,0xef,
 35.1059 +   0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x83,0x00,0x00,
 35.1060 +   0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x87,0x00,0x00,0x00,0xb3,0x00,0xd2,0xd2,0xd2,0xe6,0x81,0xff,0xff,0xff,0xff,
 35.1061 +   0x00,0x52,0x52,0x52,0xbd,0x81,0x00,0x00,0x00,0xb3,0x00,0x52,0x52,0x52,0xbd,0x81,0xff,0xff,0xff,0xff,0x02,0xd2,0xd2,0xd2,0xe6,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,
 35.1062 +   0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x88,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,
 35.1063 +   0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xd2,0xd2,0xd2,0xe6,0x81,0xff,0xff,0xff,0xff,0x85,0xaf,0xaf,0xaf,0xd6,
 35.1064 +   0x01,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0xbb,0xbb,0xbb,0xdc,0x81,0x7e,0x7e,0x7e,0xc7,0x04,0xe6,0xe6,0xe6,0xf0,0xff,0xff,0xff,
 35.1065 +   0xff,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x02,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,
 35.1066 +   0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,
 35.1067 +   0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x86,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0x00,0x00,0x00,0xb3,
 35.1068 +   0x00,0x6a,0x6a,0x6a,0xc2,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x84,0xaf,0xaf,0xaf,0xd6,0x05,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,
 35.1069 +   0xeb,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0xaf,0xaf,0xaf,0xd6,0x81,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x01,0xaf,0xaf,0xaf,0xd6,0x6a,0x6a,0x6a,0xc2,
 35.1070 +   0x81,0xff,0xff,0xff,0xff,0x00,0xc7,0xc7,0xc7,0xe1,0x85,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0x00,
 35.1071 +   0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0xa0,0xa0,0xa0,0xd1,0x82,
 35.1072 +   0x00,0x00,0x00,0xb3,0x04,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,
 35.1073 +   0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x03,0x33,0x33,0x33,0xb8,0xaf,0xaf,0xaf,0xd6,
 35.1074 +   0xd2,0xd2,0xd2,0xe6,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x00,0xc7,0xc7,0xc7,0xe1,0x81,0x00,0x00,0x00,0xb3,0x01,0x6a,0x6a,0x6a,0xc2,0x52,0x52,0x52,0xbd,
 35.1075 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xfe,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xfd,0x00,0x00,0x00,0xb3,0x00,0xdc,
 35.1076 +   0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x83,0x00,0x00,0x00,0xb3,0x04,0xdc,0xdc,0xdc,0xeb,0xff,0xff,0xff,0xff,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0x7e,0x7e,
 35.1077 +   0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0x90,0x90,0x90,0xcc,0x84,0xff,0xff,0xff,0xff,0x02,0xbb,0xbb,0xbb,0xdc,0x00,0x00,
 35.1078 +   0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x84,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x82,
 35.1079 +   0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,
 35.1080 +   0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,
 35.1081 +   0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,
 35.1082 +   0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0xb3,0xaf,
 35.1083 +   0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x83,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,
 35.1084 +   0xd6,0x87,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x83,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,
 35.1085 +   0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x88,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,
 35.1086 +   0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x87,0xff,0xff,0xff,
 35.1087 +   0xff,0x02,0x00,0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,0xd2,0xd2,0xd2,0xe6,0x85,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,
 35.1088 +   0x81,0xff,0xff,0xff,0xff,0x02,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,
 35.1089 +   0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x86,
 35.1090 +   0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x87,0xff,0xff,0xff,0xff,0x03,0xaf,0xaf,
 35.1091 +   0xaf,0xd6,0x00,0x00,0x00,0xb3,0x6a,0x6a,0x6a,0xc2,0xe6,0xe6,0xe6,0xf0,0x85,0xff,0xff,0xff,0xff,0x01,0xaf,0xaf,0xaf,0xd6,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,
 35.1092 +   0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x85,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0x00,0x00,0x00,0xb3,0x81,
 35.1093 +   0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0x00,0x00,0x00,0xb3,
 35.1094 +   0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,
 35.1095 +   0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0xe6,0xe6,0xe6,0xf0,0x83,0xff,0xff,0xff,0xff,0x01,0xef,0xef,0xef,0xf5,
 35.1096 +   0x6a,0x6a,0x6a,0xc2,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0x82,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
 35.1097 +   0x00,0xb3,0xfd,0x00,0x00,0x00,0xb3,0x00,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x05,0x33,0x33,0x33,0xb8,
 35.1098 +   0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,
 35.1099 +   0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0xaf,0xaf,0xaf,0xd6,0x52,0x52,0x52,0xbd,0x81,0x00,0x00,0x00,0xb3,0x00,0xa0,0xa0,
 35.1100 +   0xa0,0xd1,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0x33,0x33,0x33,0xb8,0x81,0x00,0x00,0x00,0xb3,0x03,0xef,0xef,0xef,0xf5,
 35.1101 +   0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0x33,0x33,0x33,0xb8,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x02,0xa0,0xa0,0xa0,0xd1,
 35.1102 +   0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x02,0x52,0x52,0x52,0xbd,0x00,0x00,0x00,0xb3,0x90,0x90,0x90,0xcc,0x81,0xff,0xff,0xff,0xff,0x00,
 35.1103 +   0xc7,0xc7,0xc7,0xe1,0x81,0x00,0x00,0x00,0xb3,0x00,0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,
 35.1104 +   0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0xa0,0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,
 35.1105 +   0x05,0x33,0x33,0x33,0xb8,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xef,0xef,0xef,0xf5,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0xbb,
 35.1106 +   0xbb,0xbb,0xdc,0x83,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x87,0x00,0x00,0x00,0xb3,0x00,0xc7,0xc7,0xc7,
 35.1107 +   0xe1,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x02,0xc7,0xc7,0xc7,0xe1,0x00,
 35.1108 +   0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0xbb,0xbb,0xbb,0xdc,0x88,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,
 35.1109 +   0x02,0x52,0x52,0x52,0xbd,0x00,0x00,0x00,0xb3,0xa0,0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xc7,0xc7,0xc7,0xe1,0x81,
 35.1110 +   0xff,0xff,0xff,0xff,0x00,0x90,0x90,0x90,0xcc,0x81,0x7e,0x7e,0x7e,0xc7,0x02,0xe6,0xe6,0xe6,0xf0,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0x82,0x00,0x00,0x00,0xb3,
 35.1111 +   0x01,0x52,0x52,0x52,0xbd,0x90,0x90,0x90,0xcc,0x81,0xaf,0xaf,0xaf,0xd6,0x04,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0xaf,
 35.1112 +   0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x02,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,
 35.1113 +   0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x02,0xa0,0xa0,0xa0,0xd1,0x00,0x00,0x00,0xb3,0x52,0x52,0x52,0xbd,0x81,0xff,0xff,0xff,0xff,
 35.1114 +   0x00,0xdc,0xdc,0xdc,0xeb,0x86,0x00,0x00,0x00,0xb3,0x82,0xff,0xff,0xff,0xff,0x00,0x33,0x33,0x33,0xb8,0x81,0x00,0x00,0x00,0xb3,0x00,0x52,0x52,0x52,0xbd,0x81,0xff,
 35.1115 +   0xff,0xff,0xff,0x00,0xd2,0xd2,0xd2,0xe6,0x81,0x7e,0x7e,0x7e,0xc7,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,
 35.1116 +   0xb3,0x01,0x6a,0x6a,0x6a,0xc2,0xa0,0xa0,0xa0,0xd1,0x81,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x01,0xaf,0xaf,0xaf,0xd6,0x52,0x52,0x52,0xbd,0x81,0xff,0xff,
 35.1117 +   0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x00,0x33,0x33,0x33,0xb8,0x82,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,
 35.1118 +   0x00,0x7e,0x7e,0x7e,0xc7,0x82,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0xa0,0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,
 35.1119 +   0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x05,0x33,0x33,0x33,0xb8,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xef,0xef,0xef,0xf5,0x00,0x00,0x00,0xb3,
 35.1120 +   0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xc7,0xc7,0xc7,0xe1,0x81,0x00,0x00,0x00,0xb3,0x00,0xef,0xef,0xef,0xf5,0x81,0xff,0xff,0xff,0xff,0x01,0x00,0x00,
 35.1121 +   0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x02,0xf7,0xf7,0xf7,0xfa,0xbb,0xbb,0xbb,0xdc,0x90,0x90,0x90,0xcc,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
 35.1122 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0x84,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xfd,0x00,0x00,0x00,0xb3,0x00,0x90,0x90,0x90,0xcc,
 35.1123 +   0x81,0xff,0xff,0xff,0xff,0x03,0xf7,0xf7,0xf7,0xfa,0xbb,0xbb,0xbb,0xdc,0xaf,0xaf,0xaf,0xd6,0xef,0xef,0xef,0xf5,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,
 35.1124 +   0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x06,
 35.1125 +   0x52,0x52,0x52,0xbd,0x33,0x33,0x33,0xb8,0xaf,0xaf,0xaf,0xd6,0x33,0x33,0x33,0xb8,0x00,0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,
 35.1126 +   0xff,0x05,0xc7,0xc7,0xc7,0xe1,0xaf,0xaf,0xaf,0xd6,0xef,0xef,0xef,0xf5,0xa0,0xa0,0xa0,0xd1,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x02,
 35.1127 +   0xef,0xef,0xef,0xf5,0xaf,0xaf,0xaf,0xd6,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x03,0xf7,0xf7,0xf7,0xfa,0x33,0x33,0x33,0xb8,0x00,0x00,0x00,0xb3,0xdc,0xdc,
 35.1128 +   0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x02,0xe6,0xe6,0xe6,0xf0,0xaf,0xaf,0xaf,0xd6,0xe6,0xe6,0xe6,0xf0,0x82,0xff,0xff,0xff,0xff,0x01,0xc7,0xc7,0xc7,0xe1,0xbb,0xbb,
 35.1129 +   0xbb,0xdc,0x81,0xff,0xff,0xff,0xff,0x03,0xef,0xef,0xef,0xf5,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x04,0xdc,0xdc,
 35.1130 +   0xdc,0xeb,0xaf,0xaf,0xaf,0xd6,0x7e,0x7e,0x7e,0xc7,0x33,0x33,0x33,0xb8,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x02,0xc7,0xc7,0xc7,0xe1,0xaf,0xaf,0xaf,0xd6,
 35.1131 +   0xef,0xef,0xef,0xf5,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x82,0xff,0xff,0xff,0xff,0x04,0xc7,0xc7,0xc7,0xe1,
 35.1132 +   0xaf,0xaf,0xaf,0xd6,0xa0,0xa0,0xa0,0xd1,0xaf,0xaf,0xaf,0xd6,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xaf,0xaf,0xaf,0xd6,0x85,
 35.1133 +   0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xf7,0xf7,0xf7,0xfa,0x81,0xbb,0xbb,0xbb,0xdc,0x00,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,
 35.1134 +   0xff,0xff,0x02,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x82,0xff,0xff,0xff,0xff,0x02,0xc7,0xc7,0xc7,0xe1,0xaf,0xaf,0xaf,0xd6,0xa0,0xa0,0xa0,
 35.1135 +   0xd1,0x85,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x02,0xe6,0xe6,0xe6,0xf0,0xaf,0xaf,0xaf,0xd6,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,
 35.1136 +   0xff,0xff,0x02,0xa0,0xa0,0xa0,0xd1,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x02,0xc7,0xc7,0xc7,0xe1,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,
 35.1137 +   0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xc7,0xc7,0xc7,0xe1,0x81,0x00,0x00,0x00,0xb3,0x09,0x33,0x33,0x33,0xb8,0xaf,0xaf,0xaf,0xd6,0x33,0x33,0x33,0xb8,0x00,0x00,0x00,
 35.1138 +   0xb3,0x52,0x52,0x52,0xbd,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x02,0x7e,
 35.1139 +   0x7e,0x7e,0xc7,0xaf,0xaf,0xaf,0xd6,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xaf,0xaf,0xaf,0xd6,0x01,0x00,0x00,0x00,0xb3,0xaf,
 35.1140 +   0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x02,0xf7,0xf7,0xf7,0xfa,0xaf,0xaf,0xaf,0xd6,0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,0x00,0xc7,0xc7,0xc7,0xe1,0x86,
 35.1141 +   0x00,0x00,0x00,0xb3,0x82,0xff,0xff,0xff,0xff,0x00,0xef,0xef,0xef,0xf5,0x81,0xaf,0xaf,0xaf,0xd6,0x06,0x52,0x52,0x52,0xbd,0xdc,0xdc,0xdc,0xeb,0xff,0xff,0xff,0xff,
 35.1142 +   0xf7,0xf7,0xf7,0xfa,0x6a,0x6a,0x6a,0xc2,0x33,0x33,0x33,0xb8,0xd2,0xd2,0xd2,0xe6,0x81,0xff,0xff,0xff,0xff,0x00,0x52,0x52,0x52,0xbd,0x81,0x00,0x00,0x00,0xb3,0x01,
 35.1143 +   0x6a,0x6a,0x6a,0xc2,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0x90,0x90,0x90,0xcc,0x81,0xff,0xff,0xff,0xff,0x02,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,
 35.1144 +   0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x06,0xdc,0xdc,0xdc,0xeb,0xaf,0xaf,0xaf,0xd6,0xdc,0xdc,0xdc,0xeb,0xc7,0xc7,0xc7,0xe1,0x52,0x52,0x52,0xbd,0xaf,0xaf,
 35.1145 +   0xaf,0xd6,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x03,0xc7,0xc7,0xc7,0xe1,0xaf,0xaf,0xaf,0xd6,0xa0,0xa0,0xa0,0xd1,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,
 35.1146 +   0xff,0x03,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x02,0xc7,0xc7,0xc7,0xe1,0xaf,0xaf,0xaf,0xd6,
 35.1147 +   0xef,0xef,0xef,0xf5,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x01,0xbb,0xbb,0xbb,0xdc,
 35.1148 +   0xd2,0xd2,0xd2,0xe6,0x81,0xff,0xff,0xff,0xff,0x02,0xef,0xef,0xef,0xf5,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x03,0xc7,0xc7,0xc7,0xe1,
 35.1149 +   0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0xa0,0xa0,0xa0,0xd1,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0x83,0x00,0x00,0x00,0xb3,
 35.1150 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xfe,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x86,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,
 35.1151 +   0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0x90,0x90,0x90,0xcc,0x84,0xff,0xff,0xff,0xff,0x03,0xe6,0xe6,
 35.1152 +   0xe6,0xf0,0x33,0x33,0x33,0xb8,0x00,0x00,0x00,0xb3,0x90,0x90,0x90,0xcc,0x85,0xff,0xff,0xff,0xff,0x02,0x90,0x90,0x90,0xcc,0x33,0x33,0x33,0xb8,0xe6,0xe6,0xe6,0xf0,
 35.1153 +   0x85,0xff,0xff,0xff,0xff,0x00,0xa0,0xa0,0xa0,0xd1,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x00,0xf7,0xf7,0xf7,0xfa,0x82,0xff,
 35.1154 +   0xff,0xff,0xff,0x01,0xf7,0xf7,0xf7,0xfa,0xe6,0xe6,0xe6,0xf0,0x83,0xff,0xff,0xff,0xff,0x01,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0x85,0xff,0xff,0xff,0xff,0x02,
 35.1155 +   0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xa0,0xa0,0xa0,0xd1,0x85,0xff,0xff,0xff,0xff,0x03,0xe6,0xe6,0xe6,0xf0,0x33,0x33,0x33,0xb8,0x00,0x00,0x00,0xb3,0xaf,0xaf,
 35.1156 +   0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x86,0xff,0xff,0xff,0xff,0x86,0x00,0x00,0x00,0xb3,
 35.1157 +   0x00,0xc7,0xc7,0xc7,0xe1,0x85,0xff,0xff,0xff,0xff,0x00,0xc7,0xc7,0xc7,0xe1,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0xe6,
 35.1158 +   0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x85,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x00,0xf7,0xf7,0xf7,
 35.1159 +   0xfa,0x83,0xff,0xff,0xff,0xff,0x00,0x52,0x52,0x52,0xbd,0x81,0x00,0x00,0x00,0xb3,0x00,0xc7,0xc7,0xc7,0xe1,0x84,0xff,0xff,0xff,0xff,0x01,0xf7,0xf7,0xf7,0xfa,0x52,
 35.1160 +   0x52,0x52,0xbd,0x81,0x00,0x00,0x00,0xb3,0x04,0xdc,0xdc,0xdc,0xeb,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0xdc,0xdc,0xdc,0xeb,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,
 35.1161 +   0xff,0xff,0x02,0x52,0x52,0x52,0xbd,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x86,0xff,0xff,0xff,0xff,0x01,0x00,
 35.1162 +   0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0xf7,0xf7,0xf7,0xfa,0x83,0xff,0xff,0xff,0xff,0x00,0xa0,0xa0,0xa0,0xd1,0x86,0x00,0x00,0x00,0xb3,
 35.1163 +   0x81,0xff,0xff,0xff,0xff,0x01,0xef,0xef,0xef,0xf5,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x02,0x7e,0x7e,0x7e,0xc7,0x6a,0x6a,0x6a,0xc2,0xf7,0xf7,0xf7,0xfa,
 35.1164 +   0x84,0xff,0xff,0xff,0xff,0x00,0xbb,0xbb,0xbb,0xdc,0x81,0x00,0x00,0x00,0xb3,0x04,0x33,0x33,0x33,0xb8,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xef,0xef,0xef,0xf5,
 35.1165 +   0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x00,0xef,0xef,0xef,0xf5,0x81,0x00,0x00,0x00,0xb3,0x01,0x52,0x52,0x52,0xbd,0xf7,0xf7,0xf7,0xfa,0x84,0xff,0xff,0xff,
 35.1166 +   0xff,0x00,0xe6,0xe6,0xe6,0xf0,0x85,0xff,0xff,0xff,0xff,0x01,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0x00,
 35.1167 +   0x00,0x00,0xb3,0x00,0xa0,0xa0,0xa0,0xd1,0x85,0xff,0xff,0xff,0xff,0x03,0xe6,0xe6,0xe6,0xf0,0x33,0x33,0x33,0xb8,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,
 35.1168 +   0xff,0xff,0xff,0x00,0xf7,0xf7,0xf7,0xfa,0x83,0xff,0xff,0xff,0xff,0x00,0xc7,0xc7,0xc7,0xe1,0x81,0x00,0x00,0x00,0xb3,0x00,0xe6,0xe6,0xe6,0xf0,0x84,0xff,0xff,0xff,
 35.1169 +   0xff,0x00,0xa0,0xa0,0xa0,0xd1,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0x82,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
 35.1170 +   0x00,0x00,0x00,0xb3,0xfe,0x00,0x00,0x00,0xb3,0x05,0x33,0x33,0x33,0xb8,0xc7,0xc7,0xc7,0xe1,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,0xeb,0xaf,0xaf,
 35.1171 +   0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0x6a,0x6a,0x6a,0xc2,0x81,0xdc,0xdc,0xdc,0xeb,0x00,0xa0,0xa0,0xa0,0xd1,0x81,0x00,
 35.1172 +   0x00,0x00,0xb3,0x01,0x90,0x90,0x90,0xcc,0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,0x01,0xe6,0xe6,0xe6,0xf0,0xa0,0xa0,0xa0,0xd1,0x82,0x00,0x00,0x00,0xb3,0x0a,
 35.1173 +   0x6a,0x6a,0x6a,0xc2,0xd2,0xd2,0xd2,0xe6,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xef,0xef,0xef,0xf5,0xaf,0xaf,0xaf,0xd6,0x33,0x33,0x33,0xb8,0x00,0x00,0x00,0xb3,
 35.1174 +   0x33,0x33,0x33,0xb8,0xaf,0xaf,0xaf,0xd6,0xef,0xef,0xef,0xf5,0x81,0xff,0xff,0xff,0xff,0x01,0xd2,0xd2,0xd2,0xe6,0x7e,0x7e,0x7e,0xc7,0x82,0x00,0x00,0x00,0xb3,0x00,
 35.1175 +   0xbb,0xbb,0xbb,0xdc,0x81,0xdc,0xdc,0xdc,0xeb,0x06,0x6a,0x6a,0x6a,0xc2,0xe6,0xe6,0xe6,0xf0,0xff,0xff,0xff,0xff,0xef,0xef,0xef,0xf5,0x90,0x90,0x90,0xcc,0x33,0x33,
 35.1176 +   0x33,0xb8,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x04,0xc7,0xc7,0xc7,0xe1,0x33,0x33,0x33,0xb8,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0xe6,0xe6,0xe6,0xf0,
 35.1177 +   0x81,0xff,0xff,0xff,0xff,0x02,0xef,0xef,0xef,0xf5,0xdc,0xdc,0xdc,0xeb,0xa0,0xa0,0xa0,0xd1,0x81,0x00,0x00,0x00,0xb3,0x01,0x7e,0x7e,0x7e,0xc7,0xd2,0xd2,0xd2,0xe6,
 35.1178 +   0x81,0xff,0xff,0xff,0xff,0x02,0xef,0xef,0xef,0xf5,0xaf,0xaf,0xaf,0xd6,0x33,0x33,0x33,0xb8,0x81,0x00,0x00,0x00,0xb3,0x00,0xa0,0xa0,0xa0,0xd1,0x81,0xdc,0xdc,0xdc,
 35.1179 +   0xeb,0x02,0x7e,0x7e,0x7e,0xc7,0xc7,0xc7,0xc7,0xe1,0xff,0xff,0xff,0xff,0x81,0xdc,0xdc,0xdc,0xeb,0x00,0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,0x00,0xef,0xef,
 35.1180 +   0xef,0xf5,0x81,0xdc,0xdc,0xdc,0xeb,0x87,0x00,0x00,0x00,0xb3,0x01,0xa0,0xa0,0xa0,0xd1,0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,0x01,0xe6,0xe6,0xe6,0xf0,0xa0,
 35.1181 +   0xa0,0xa0,0xd1,0x82,0x00,0x00,0x00,0xb3,0x00,0xa0,0xa0,0xa0,0xd1,0x81,0xdc,0xdc,0xdc,0xeb,0x03,0x7e,0x7e,0x7e,0xc7,0xc7,0xc7,0xc7,0xe1,0xff,0xff,0xff,0xff,0xdc,
 35.1182 +   0xdc,0xdc,0xeb,0x85,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x04,0x90,0x90,0x90,0xcc,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0xef,
 35.1183 +   0xef,0xef,0xf5,0x90,0x90,0x90,0xcc,0x83,0x00,0x00,0x00,0xb3,0x01,0xa0,0xa0,0xa0,0xd1,0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,0x01,0xd2,0xd2,0xd2,0xe6,0x6a,
 35.1184 +   0x6a,0x6a,0xc2,0x82,0x00,0x00,0x00,0xb3,0x02,0x52,0x52,0x52,0xbd,0xc7,0xc7,0xc7,0xe1,0xef,0xef,0xef,0xf5,0x81,0xff,0xff,0xff,0xff,0x01,0xdc,0xdc,0xdc,0xeb,0x7e,
 35.1185 +   0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x02,0x7e,0x7e,0x7e,0xc7,0xdc,0xdc,0xdc,0xeb,0xe6,0xe6,0xe6,0xf0,0x81,
 35.1186 +   0xff,0xff,0xff,0xff,0x00,0xef,0xef,0xef,0xf5,0x81,0xdc,0xdc,0xdc,0xeb,0x01,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x04,0xaf,0xaf,0xaf,
 35.1187 +   0xd6,0xdc,0xdc,0xdc,0xeb,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0xaf,0xaf,0xaf,0xd6,0x87,0x00,0x00,0x00,0xb3,0x81,0xdc,0xdc,0xdc,0xeb,0x0b,0xbb,0xbb,0xbb,0xdc,
 35.1188 +   0x90,0x90,0x90,0xcc,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0x52,0x52,0x52,0xbd,0xc7,0xc7,0xc7,0xe1,0xf7,0xf7,0xf7,0xfa,
 35.1189 +   0xff,0xff,0xff,0xff,0xef,0xef,0xef,0xf5,0xaf,0xaf,0xaf,0xd6,0x83,0x00,0x00,0x00,0xb3,0x06,0x7e,0x7e,0x7e,0xc7,0xd2,0xd2,0xd2,0xe6,0xf7,0xf7,0xf7,0xfa,0xff,0xff,
 35.1190 +   0xff,0xff,0xf7,0xf7,0xf7,0xfa,0xd2,0xd2,0xd2,0xe6,0x52,0x52,0x52,0xbd,0x82,0x00,0x00,0x00,0xb3,0x08,0x33,0x33,0x33,0xb8,0xc7,0xc7,0xc7,0xe1,0xef,0xef,0xef,0xf5,
 35.1191 +   0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0xc7,0xc7,0xc7,0xe1,0x6a,0x6a,0x6a,0xc2,0xdc,0xdc,0xdc,0xeb,0xef,0xef,0xef,0xf5,0x81,0xff,0xff,0xff,0xff,0x03,0xe6,0xe6,
 35.1192 +   0xe6,0xf0,0xdc,0xdc,0xdc,0xeb,0xbb,0xbb,0xbb,0xdc,0x00,0x00,0x00,0xb3,0x81,0xdc,0xdc,0xdc,0xeb,0x00,0xbb,0xbb,0xbb,0xdc,0x82,0x00,0x00,0x00,0xb3,0x01,0x7e,0x7e,
 35.1193 +   0x7e,0xc7,0xd2,0xd2,0xd2,0xe6,0x81,0xff,0xff,0xff,0xff,0x02,0xef,0xef,0xef,0xf5,0xaf,0xaf,0xaf,0xd6,0x33,0x33,0x33,0xb8,0x81,0x00,0x00,0x00,0xb3,0x00,0x6a,0x6a,
 35.1194 +   0x6a,0xc2,0x81,0xdc,0xdc,0xdc,0xeb,0x01,0xa0,0xa0,0xa0,0xd1,0xbb,0xbb,0xbb,0xdc,0x81,0xff,0xff,0xff,0xff,0x01,0xc7,0xc7,0xc7,0xe1,0x33,0x33,0x33,0xb8,0x81,0x00,
 35.1195 +   0x00,0x00,0xb3,0x06,0x33,0x33,0x33,0xb8,0xc7,0xc7,0xc7,0xe1,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0xc7,0xc7,0xc7,0xe1,0x52,0x52,0x52,0xbd,
 35.1196 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0x82,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
 35.1197 +   0x00,0x00,0xb3,0x83,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x01,0x52,0x52,0x52,
 35.1198 +   0xbd,0x6a,0x6a,0x6a,0xc2,0xad,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x94,0x00,0x00,0x00,0xb3,0x00,0x7e,
 35.1199 +   0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x9f,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x9a,0x00,0x00,0x00,
 35.1200 +   0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x02,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,
 35.1201 +   0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0xaf,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,
 35.1202 +   0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0x00,0x00,0x00,0xb3,0x01,0x33,0x33,0x33,0xb8,0x7e,0x7e,0x7e,0xc7,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
 35.1203 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xa1,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0x83,0x00,0x00,0x00,0xb3,
 35.1204 +   0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,
 35.1205 +   0xd6,0xac,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x94,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,
 35.1206 +   0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x9f,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x9a,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,
 35.1207 +   0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x02,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0x00,
 35.1208 +   0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0xaf,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,
 35.1209 +   0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x03,0x33,0x33,0x33,0xb8,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,0xeb,0xff,0x00,0x00,0x00,
 35.1210 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xa0,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0x83,
 35.1211 +   0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,
 35.1212 +   0x00,0xdc,0xdc,0xdc,0xeb,0xac,0x00,0x00,0x00,0xb3,0x00,0x52,0x52,0x52,0xbd,0x81,0xff,0xff,0xff,0xff,0x00,0xf7,0xf7,0xf7,0xfa,0x81,0xaf,0xaf,0xaf,0xd6,0x92,0x00,
 35.1213 +   0x00,0x00,0xb3,0x00,0x33,0x33,0x33,0xb8,0x81,0x7e,0x7e,0x7e,0xc7,0x00,0x52,0x52,0x52,0xbd,0x9f,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,
 35.1214 +   0xff,0x9a,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x02,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,0x81,0x7e,0x7e,
 35.1215 +   0x7e,0xc7,0x00,0x52,0x52,0x52,0xbd,0x82,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0xaf,0x00,0x00,0x00,0xb3,
 35.1216 +   0x00,0x52,0x52,0x52,0xbd,0x81,0x7e,0x7e,0x7e,0xc7,0x00,0x33,0x33,0x33,0xb8,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0xff,0x00,
 35.1217 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xa0,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
 35.1218 +   0xb3,0x83,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x05,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0x52,0x52,0x52,0xbd,0xef,0xef,0xef,
 35.1219 +   0xf5,0xf7,0xf7,0xf7,0xfa,0x90,0x90,0x90,0xcc,0xad,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0xb6,0x00,0x00,
 35.1220 +   0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x9a,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,
 35.1221 +   0x87,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0xb6,0x00,0x00,0x00,0xb3,0x02,0xdc,0xdc,0xdc,0xeb,0xff,0xff,
 35.1222 +   0xff,0xff,0xaf,0xaf,0xaf,0xd6,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xa0,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
 35.1223 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0x83,0x00,0x00,0x00,0xb3,0x00,0x52,0x52,0x52,0xbd,0x81,0xaf,0xaf,0xaf,0xd6,0x00,0x7e,0x7e,0x7e,0xc7,0xb2,0x00,0x00,
 35.1224 +   0x00,0xb3,0x01,0x33,0x33,0x33,0xb8,0xaf,0xaf,0xaf,0xd6,0x81,0xdc,0xdc,0xdc,0xeb,0x00,0xbb,0xbb,0xbb,0xdc,0xb6,0x00,0x00,0x00,0xb3,0x00,0xa0,0xa0,0xa0,0xd1,0x81,
 35.1225 +   0xaf,0xaf,0xaf,0xd6,0x9a,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xaf,0xaf,0xaf,0xd6,0x00,0x52,0x52,0x52,0xbd,0x87,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,
 35.1226 +   0x7e,0xc7,0x81,0xaf,0xaf,0xaf,0xd6,0x00,0x52,0x52,0x52,0xbd,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xda,0x00,0x00,0x00,0xb3,
 35.1227 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
 35.1228 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
 35.1229 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
 35.1230 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
 35.1231 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
 35.1232 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
 35.1233 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
 35.1234 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
 35.1235 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
 35.1236 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
 35.1237 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
 35.1238 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xa7,0x00,0x00,0x00,
 35.1239 +   0xb3,0x00,0x33,0x33,0x33,0xb8,0x81,0x7e,0x7e,0x7e,0xc7,0x00,0x33,0x33,0x33,0xb8,0xff,0x00,0x00,0x00,0xb3,0x97,0x00,0x00,0x00,0xb3,0x02,0x6a,0x6a,0x6a,0xc2,0x7e,
 35.1240 +   0x7e,0x7e,0xc7,0x6a,0x6a,0x6a,0xc2,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xb8,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
 35.1241 +   0xff,0x00,0x00,0x00,0xb3,0xe4,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0xbe,0x00,0x00,0x00,0xb3,0x00,0xf7,
 35.1242 +   0xf7,0xf7,0xfa,0x82,0xff,0xff,0xff,0xff,0x00,0xbb,0xbb,0xbb,0xdc,0xb4,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0xdd,0x00,0x00,0x00,
 35.1243 +   0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0xff,0xff,0xff,0xff,0x01,0xef,0xef,0xef,0xf5,0x6a,0x6a,0x6a,0xc2,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xb6,0x00,
 35.1244 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xe4,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,
 35.1245 +   0xff,0x00,0x7e,0x7e,0x7e,0xc7,0xbe,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x83,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0xb3,0x00,0x00,0x00,0xb3,0x81,
 35.1246 +   0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0xdd,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x83,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0xff,0x00,0x00,
 35.1247 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xb6,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xe4,0x00,0x00,0x00,0xb3,
 35.1248 +   0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0xbe,0x00,0x00,0x00,0xb3,0x05,0x52,0x52,0x52,0xbd,0x00,0x00,0x00,0xb3,0x6a,0x6a,0x6a,
 35.1249 +   0xc2,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xd2,0xd2,0xd2,0xe6,0xb3,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0xdd,0x00,0x00,0x00,
 35.1250 +   0xb3,0x81,0x33,0x33,0x33,0xb8,0x01,0x00,0x00,0x00,0xb3,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x00,0x6a,0x6a,0x6a,0xc2,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
 35.1251 +   0x00,0x00,0xb3,0xb5,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xaa,0x00,0x00,0x00,0xb3,0x02,0x6a,0x6a,0x6a,0xc2,0x7e,0x7e,0x7e,0xc7,
 35.1252 +   0x52,0x52,0x52,0xbd,0x97,0x00,0x00,0x00,0xb3,0x02,0x33,0x33,0x33,0xb8,0x7e,0x7e,0x7e,0xc7,0x6a,0x6a,0x6a,0xc2,0x90,0x00,0x00,0x00,0xb3,0x81,0x7e,0x7e,0x7e,0xc7,
 35.1253 +   0x00,0x33,0x33,0x33,0xb8,0x94,0x00,0x00,0x00,0xb3,0x02,0x52,0x52,0x52,0xbd,0x7e,0x7e,0x7e,0xc7,0x52,0x52,0x52,0xbd,0x91,0x00,0x00,0x00,0xb3,0x02,0x33,0x33,0x33,
 35.1254 +   0xb8,0x7e,0x7e,0x7e,0xc7,0x6a,0x6a,0x6a,0xc2,0x88,0x00,0x00,0x00,0xb3,0x00,0x33,0x33,0x33,0xb8,0x81,0x7e,0x7e,0x7e,0xc7,0x9c,0x00,0x00,0x00,0xb3,0x04,0x21,0x21,
 35.1255 +   0x21,0xba,0x43,0x43,0x43,0xc2,0x4d,0x4d,0x4d,0xc5,0x41,0x41,0x41,0xc2,0x13,0x13,0x13,0xb7,0x91,0x00,0x00,0x00,0xb3,0x00,0x33,0x33,0x33,0xb8,0x81,0x7e,0x7e,0x7e,
 35.1256 +   0xc7,0x00,0x52,0x52,0x52,0xbd,0x86,0x00,0x00,0x00,0xb3,0x00,0x33,0x33,0x33,0xb8,0x81,0x7e,0x7e,0x7e,0xc7,0x00,0x33,0x33,0x33,0xb8,0x83,0x00,0x00,0x00,0xb3,0x00,
 35.1257 +   0x52,0x52,0x52,0xbd,0x81,0x7e,0x7e,0x7e,0xc7,0x84,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x01,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,
 35.1258 +   0xb3,0x81,0x7e,0x7e,0x7e,0xc7,0x8a,0x00,0x00,0x00,0xb3,0x02,0x33,0x33,0x33,0xb8,0x7e,0x7e,0x7e,0xc7,0x6a,0x6a,0x6a,0xc2,0x86,0x00,0x00,0x00,0xb3,0x00,0x52,0x52,
 35.1259 +   0x52,0xbd,0x81,0x7e,0x7e,0x7e,0xc7,0x00,0x33,0x33,0x33,0xb8,0x86,0x00,0x00,0x00,0xb3,0x81,0x7e,0x7e,0x7e,0xc7,0x00,0x33,0x33,0x33,0xb8,0x9b,0x00,0x00,0x00,0xb3,
 35.1260 +   0x00,0xbb,0xbb,0xbb,0xdc,0x81,0xff,0xff,0xff,0xff,0x00,0x52,0x52,0x52,0xbd,0x86,0x00,0x00,0x00,0xb3,0x81,0x7e,0x7e,0x7e,0xc7,0x00,0x52,0x52,0x52,0xbd,0x85,0x00,
 35.1261 +   0x00,0x00,0xb3,0x02,0x33,0x33,0x33,0xb8,0x7e,0x7e,0x7e,0xc7,0x6a,0x6a,0x6a,0xc2,0x8d,0x00,0x00,0x00,0xb3,0x00,0x33,0x33,0x33,0xb8,0x81,0x7e,0x7e,0x7e,0xc7,0x8e,
 35.1262 +   0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x04,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0x52,0x52,0x52,0xbd,0x7e,0x7e,0x7e,0xc7,0x52,0x52,0x52,0xbd,0x86,0x00,
 35.1263 +   0x00,0x00,0xb3,0x02,0x52,0x52,0x52,0xbd,0x7e,0x7e,0x7e,0xc7,0x6a,0x6a,0x6a,0xc2,0x92,0x00,0x00,0x00,0xb3,0x00,0x33,0x33,0x33,0xb8,0x81,0x7e,0x7e,0x7e,0xc7,0x91,
 35.1264 +   0x00,0x00,0x00,0xb3,0x02,0x52,0x52,0x52,0xbd,0x7e,0x7e,0x7e,0xc7,0x6a,0x6a,0x6a,0xc2,0x85,0x00,0x00,0x00,0xb3,0x81,0x7e,0x7e,0x7e,0xc7,0x00,0x33,0x33,0x33,0xb8,
 35.1265 +   0x8a,0x00,0x00,0x00,0xb3,0x81,0x7e,0x7e,0x7e,0xc7,0x91,0x00,0x00,0x00,0xb3,0x00,0x33,0x33,0x33,0xb8,0x81,0xff,0xff,0xff,0xff,0x00,0xc7,0xc7,0xc7,0xe1,0xff,0x00,
 35.1266 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xb5,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xa8,0x00,0x00,0x00,0xb3,0x01,0xaf,0xaf,0xaf,
 35.1267 +   0xd6,0xef,0xef,0xef,0xf5,0x82,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x6a,0x6a,0x6a,0xc2,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,
 35.1268 +   0xc7,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,
 35.1269 +   0xaf,0xd6,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0xff,
 35.1270 +   0xff,0xff,0xff,0x01,0xdc,0xdc,0xdc,0xeb,0xbb,0xbb,0xbb,0xdc,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,
 35.1271 +   0x00,0x7e,0x7e,0x7e,0xc7,0x83,0x00,0x00,0x00,0xb3,0x02,0x33,0x33,0x33,0xb8,0xbb,0xbb,0xbb,0xdc,0xf7,0xf7,0xf7,0xfa,0x82,0xff,0xff,0xff,0xff,0x03,0xc7,0xc7,0xc7,
 35.1272 +   0xe1,0x33,0x33,0x33,0xb8,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,
 35.1273 +   0xeb,0x81,0xff,0xff,0xff,0xff,0x87,0x00,0x00,0x00,0xb3,0x00,0xbb,0xbb,0xbb,0xdc,0x82,0xff,0xff,0xff,0xff,0x00,0xa0,0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,0xff,0x02,
 35.1274 +   0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,
 35.1275 +   0x81,0xff,0xff,0xff,0xff,0x82,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0xff,0xff,0xff,0xff,0x01,0xdc,0xdc,0xdc,0xeb,0xbb,0xbb,0xbb,0xdc,0x81,0xff,0xff,
 35.1276 +   0xff,0xff,0x82,0x00,0x00,0x00,0xb3,0x01,0x52,0x52,0x52,0xbd,0xd2,0xd2,0xd2,0xe6,0x82,0xff,0xff,0xff,0xff,0x01,0xf7,0xf7,0xf7,0xfa,0xaf,0xaf,0xaf,0xd6,0x81,0x00,
 35.1277 +   0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x87,0x00,0x00,0x00,0xb3,0x00,0xd7,0xd7,0xd7,0xf0,0x86,0xff,0xff,0xff,
 35.1278 +   0xff,0x00,0x89,0x89,0x89,0xd6,0x81,0x00,0x00,0x00,0xb3,0x01,0x9e,0x9e,0x9e,0xdc,0xec,0xec,0xec,0xf8,0x83,0xff,0xff,0xff,0xff,0x02,0xfd,0xfd,0xfd,0xff,0xca,0xca,
 35.1279 +   0xca,0xeb,0x3c,0x3c,0x3c,0xc1,0x83,0x00,0x00,0x00,0xb3,0x02,0xaf,0xaf,0xaf,0xd6,0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,0xeb,0x86,0x00,0x00,0x00,0xb3,0x01,0x6a,0x6a,
 35.1280 +   0x6a,0xc2,0xdc,0xdc,0xdc,0xeb,0x83,0xff,0xff,0xff,0xff,0x01,0xef,0xef,0xef,0xf5,0x7e,0x7e,0x7e,0xc7,0x83,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x83,0xff,
 35.1281 +   0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x01,0x6a,0x6a,0x6a,0xc2,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x01,0xf7,0xf7,0xf7,0xfa,0xaf,0xaf,0xaf,0xd6,0x82,
 35.1282 +   0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x01,0xc7,0xc7,0xc7,0xe1,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x01,0xef,0xef,0xef,
 35.1283 +   0xf5,0x6a,0x6a,0x6a,0xc2,0x87,0x00,0x00,0x00,0xb3,0x01,0xa0,0xa0,0xa0,0xd1,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x01,0xc7,0xc7,0xc7,0xe1,0xdc,0xdc,0xdc,
 35.1284 +   0xeb,0x81,0xff,0xff,0xff,0xff,0x02,0x00,0x00,0x00,0xb3,0x6a,0x6a,0x6a,0xc2,0xdc,0xdc,0xdc,0xeb,0x83,0xff,0xff,0xff,0xff,0x01,0xdc,0xdc,0xdc,0xeb,0x33,0x33,0x33,
 35.1285 +   0xb8,0x81,0x00,0x00,0x00,0xb3,0x02,0x33,0x33,0x33,0xb8,0xbb,0xbb,0xbb,0xdc,0xf7,0xf7,0xf7,0xfa,0x82,0xff,0xff,0xff,0xff,0x01,0xc7,0xc7,0xc7,0xe1,0x33,0x33,0x33,
 35.1286 +   0xb8,0x86,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,
 35.1287 +   0x7e,0x7e,0x7e,0xc7,0x89,0x00,0x00,0x00,0xb3,0x00,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x84,0x00,0x00,0x00,0xb3,0x01,0xaf,0xaf,
 35.1288 +   0xaf,0xd6,0xf7,0xf7,0xf7,0xfa,0x82,0xff,0xff,0xff,0xff,0x01,0xdc,0xdc,0xdc,0xeb,0x6a,0x6a,0x6a,0xc2,0x82,0x00,0x00,0x00,0xb3,0x01,0xa0,0xa0,0xa0,0xd1,0xf7,0xf7,
 35.1289 +   0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x01,0xc7,0xc7,0xc7,0xe1,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x87,0x00,0x00,0x00,0xb3,0x01,0x52,0x52,0x52,0xbd,0xd2,
 35.1290 +   0xd2,0xd2,0xe6,0x82,0xff,0xff,0xff,0xff,0x07,0xf7,0xf7,0xf7,0xfa,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0x52,0x52,0x52,0xbd,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,
 35.1291 +   0xff,0xf7,0xf7,0xf7,0xfa,0x52,0x52,0x52,0xbd,0x81,0x00,0x00,0x00,0xb3,0x00,0xbb,0xbb,0xbb,0xdc,0x81,0xff,0xff,0xff,0xff,0x01,0xc7,0xc7,0xc7,0xe1,0x00,0x00,0x00,
 35.1292 +   0xb3,0x81,0xff,0xff,0xff,0xff,0x01,0xe6,0xe6,0xe6,0xf0,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x00,0xbb,0xbb,0xbb,0xdc,0x83,0x00,0x00,0x00,0xb3,0x01,0x7e,
 35.1293 +   0x7e,0x7e,0xc7,0xe6,0xe6,0xe6,0xf0,0x82,0xff,0xff,0xff,0xff,0x01,0xef,0xef,0xef,0xf5,0x90,0x90,0x90,0xcc,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,
 35.1294 +   0xff,0xff,0xff,0xff,0x83,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x01,0x52,0x52,
 35.1295 +   0x52,0xbd,0xd2,0xd2,0xd2,0xe6,0x82,0xff,0xff,0xff,0xff,0x01,0xf7,0xf7,0xf7,0xfa,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,
 35.1296 +   0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0x00,0x00,0x00,0xb3,0x01,0x7e,0x7e,0x7e,
 35.1297 +   0xc7,0xe6,0xe6,0xe6,0xf0,0x82,0xff,0xff,0xff,0xff,0x05,0xef,0xef,0xef,0xf5,0x90,0x90,0x90,0xcc,0x00,0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,0xbb,0xbb,0xbb,0xdc,0xf7,
 35.1298 +   0xf7,0xf7,0xfa,0x82,0xff,0xff,0xff,0xff,0x01,0xc7,0xc7,0xc7,0xe1,0x33,0x33,0x33,0xb8,0x86,0x00,0x00,0x00,0xb3,0x01,0xa0,0xa0,0xa0,0xd1,0xf7,0xf7,0xf7,0xfa,0x81,
 35.1299 +   0xff,0xff,0xff,0xff,0x01,0xf7,0xf7,0xf7,0xfa,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x01,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,
 35.1300 +   0x00,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0x00,0x00,0x00,0xb3,0x00,0x52,
 35.1301 +   0x52,0x52,0xbd,0x81,0xff,0xff,0xff,0xff,0x00,0xf7,0xf7,0xf7,0xfa,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xb5,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
 35.1302 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xa7,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x84,0xff,0xff,0xff,0xff,0x02,0xf7,0xf7,0xf7,0xfa,0x6a,0x6a,0x6a,0xc2,0xaf,0xaf,
 35.1303 +   0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0x7e,
 35.1304 +   0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x02,0x7e,0x7e,0x7e,0xc7,0x00,
 35.1305 +   0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x87,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,
 35.1306 +   0x83,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,
 35.1307 +   0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x86,
 35.1308 +   0x00,0x00,0x00,0xb3,0x00,0x6a,0x6a,0x6a,0xc2,0x86,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,
 35.1309 +   0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x87,0xff,
 35.1310 +   0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x01,0x33,0x33,0x33,0xb8,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x01,0xdc,0xdc,0xdc,0xeb,0xef,0xef,0xef,0xf5,0x81,
 35.1311 +   0xff,0xff,0xff,0xff,0x02,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x87,0x00,0x00,0x00,0xb3,
 35.1312 +   0x00,0xd7,0xd7,0xd7,0xf0,0x86,0xff,0xff,0xff,0xff,0x00,0x89,0x89,0x89,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0xe1,0xe1,0xe1,0xf3,0x86,0xff,0xff,0xff,0xff,0x01,0xf6,
 35.1313 +   0xf6,0xf6,0xfc,0x41,0x41,0x41,0xc2,0x82,0x00,0x00,0x00,0xb3,0x82,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x84,0x00,0x00,0x00,0xb3,0x01,0x33,0x33,0x33,0xb8,
 35.1314 +   0xe6,0xe6,0xe6,0xf0,0x86,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x00,0x52,0x52,0x52,0xbd,0x84,0xff,0xff,0xff,0xff,0x02,0x00,0x00,
 35.1315 +   0x00,0xb3,0x52,0x52,0x52,0xbd,0xf7,0xf7,0xf7,0xfa,0x85,0xff,0xff,0xff,0xff,0x00,0xbb,0xbb,0xbb,0xdc,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x86,0xff,
 35.1316 +   0xff,0xff,0xff,0x01,0xef,0xef,0xef,0xf5,0x33,0x33,0x33,0xb8,0x86,0x00,0x00,0x00,0xb3,0x00,0xf7,0xf7,0xf7,0xfa,0x86,0xff,0xff,0xff,0xff,0x03,0x00,0x00,0x00,0xb3,
 35.1317 +   0x33,0x33,0x33,0xb8,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0x81,0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,
 35.1318 +   0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x86,0x00,0x00,0x00,0xb3,0x81,0xff,
 35.1319 +   0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x88,0x00,0x00,0x00,
 35.1320 +   0xb3,0x01,0x33,0x33,0x33,0xb8,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x00,0xef,0xef,0xef,0xf5,0x83,0x00,0x00,0x00,0xb3,0x00,0xbb,0xbb,0xbb,0xdc,0x85,0xff,
 35.1321 +   0xff,0xff,0xff,0x01,0xf7,0xf7,0xf7,0xfa,0x52,0x52,0x52,0xbd,0x81,0x00,0x00,0x00,0xb3,0x00,0xf7,0xf7,0xf7,0xfa,0x86,0xff,0xff,0xff,0xff,0x86,0x00,0x00,0x00,0xb3,
 35.1322 +   0x01,0x33,0x33,0x33,0xb8,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x01,0xdc,0xdc,0xdc,0xeb,0xef,0xef,0xef,0xf5,0x81,0xff,0xff,0xff,0xff,0x02,0x7e,0x7e,0x7e,
 35.1323 +   0xc7,0x00,0x00,0x00,0xb3,0x90,0x90,0x90,0xcc,0x81,0xff,0xff,0xff,0xff,0x02,0xe6,0xe6,0xe6,0xf0,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,
 35.1324 +   0x00,0xe6,0xe6,0xe6,0xf0,0x81,0x00,0x00,0x00,0xb3,0x87,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,
 35.1325 +   0xff,0xff,0xff,0x07,0xf7,0xf7,0xf7,0xfa,0xdc,0xdc,0xdc,0xeb,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0x33,0x33,0x33,0xb8,0x00,0x00,0x00,0xb3,
 35.1326 +   0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x83,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x03,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,
 35.1327 +   0xb3,0x33,0x33,0x33,0xb8,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x01,0xdc,0xdc,0xdc,0xeb,0xef,0xef,0xef,0xf5,0x81,0xff,0xff,0xff,0xff,0x02,0x7e,0x7e,0x7e,
 35.1328 +   0xc7,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,
 35.1329 +   0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x85,0xff,0xff,0xff,0xff,0x02,0xa0,0xa0,0xa0,0xd1,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,
 35.1330 +   0xff,0xff,0xff,0x81,0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x85,0x00,0x00,0x00,0xb3,0x00,0x52,0x52,0x52,0xbd,0x81,0xff,0xff,0xff,
 35.1331 +   0xff,0x02,0xef,0xef,0xef,0xf5,0xaf,0xaf,0xaf,0xd6,0xc7,0xc7,0xc7,0xe1,0x82,0xff,0xff,0xff,0xff,0x01,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,
 35.1332 +   0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0x00,0x00,0x00,0xb3,0x00,
 35.1333 +   0xaf,0xaf,0xaf,0xd6,0x82,0xff,0xff,0xff,0xff,0x00,0xa0,0xa0,0xa0,0xd1,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xb4,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
 35.1334 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xa6,0x00,0x00,0x00,0xb3,0x00,0x52,0x52,0x52,0xbd,0x81,0xff,0xff,0xff,0xff,0x06,0xf7,0xf7,0xf7,0xfa,0xa0,0xa0,0xa0,0xd1,0x7e,
 35.1335 +   0x7e,0x7e,0xc7,0xd2,0xd2,0xd2,0xe6,0x6a,0x6a,0x6a,0xc2,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,
 35.1336 +   0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,
 35.1337 +   0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x02,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x03,0xaf,0xaf,
 35.1338 +   0xaf,0xd6,0x7e,0x7e,0x7e,0xc7,0xa0,0xa0,0xa0,0xd1,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,
 35.1339 +   0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0x00,0x00,0x00,0xb3,0x00,0xa0,0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,
 35.1340 +   0x01,0xa0,0xa0,0xa0,0xd1,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,
 35.1341 +   0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x86,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x02,0xe6,0xe6,0xe6,0xf0,
 35.1342 +   0x7e,0x7e,0x7e,0xc7,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,
 35.1343 +   0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,
 35.1344 +   0xff,0xff,0x03,0xaf,0xaf,0xaf,0xd6,0x7e,0x7e,0x7e,0xc7,0xa0,0xa0,0xa0,0xd1,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0xc7,0xc7,
 35.1345 +   0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x00,0x6a,0x6a,0x6a,0xc2,0x81,0x00,0x00,0x00,0xb3,0x01,0xbb,0xbb,0xbb,0xdc,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x00,
 35.1346 +   0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x87,0x00,0x00,0x00,0xb3,0x02,0x28,0x28,0x28,0xbc,0x34,0x34,0x34,0xbf,0x63,0x63,0x63,0xcb,
 35.1347 +   0x81,0xff,0xff,0xff,0xff,0x00,0xef,0xef,0xef,0xf9,0x81,0x34,0x34,0x34,0xbf,0x00,0x17,0x17,0x17,0xb8,0x81,0x00,0x00,0x00,0xb3,0x06,0xe0,0xe0,0xe0,0xf3,0xce,0xce,
 35.1348 +   0xce,0xec,0x7d,0x7d,0x7d,0xd2,0x46,0x46,0x46,0xc3,0x44,0x44,0x44,0xc3,0x7e,0x7e,0x7e,0xd2,0xef,0xef,0xef,0xf9,0x81,0xff,0xff,0xff,0xff,0x00,0xc3,0xc3,0xc3,0xe8,
 35.1349 +   0x82,0x00,0x00,0x00,0xb3,0x03,0xdc,0xdc,0xdc,0xeb,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0x33,0x33,0x33,0xb8,0x85,0x00,0x00,0x00,0xb3,0x05,0x52,0x52,0x52,0xbd,
 35.1350 +   0xf7,0xf7,0xf7,0xfa,0xe6,0xe6,0xe6,0xf0,0xa0,0xa0,0xa0,0xd1,0x7e,0x7e,0x7e,0xc7,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0xe6,0xe6,0xe6,0xf0,0x81,0x00,
 35.1351 +   0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x04,0xd2,0xd2,0xd2,0xe6,0x00,0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,0x00,0x00,0x00,0xb3,0xc7,0xc7,
 35.1352 +   0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x03,0xd2,0xd2,0xd2,0xe6,0x7e,0x7e,0x7e,0xc7,0xa0,0xa0,0xa0,0xd1,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x02,0x52,0x52,
 35.1353 +   0x52,0xbd,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x03,0xd2,0xd2,0xd2,0xe6,0x7e,0x7e,0x7e,0xc7,0x90,0x90,0x90,0xcc,0xe6,0xe6,0xe6,0xf0,
 35.1354 +   0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x85,0x00,0x00,0x00,0xb3,0x00,0x6a,0x6a,0x6a,0xc2,0x81,0xff,0xff,0xff,0xff,0x02,0xf7,0xf7,0xf7,0xfa,0x90,0x90,
 35.1355 +   0x90,0xcc,0xaf,0xaf,0xaf,0xd6,0x82,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x01,0x6a,0x6a,0x6a,0xc2,0xa0,0xa0,0xa0,0xd1,0x81,0x00,0x00,0x00,0xb3,0x00,0xe6,
 35.1356 +   0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0xb3,0xa0,0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,
 35.1357 +   0x01,0xa0,0xa0,0xa0,0xd1,0xaf,0xaf,0xaf,0xd6,0x87,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,
 35.1358 +   0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x88,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x83,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,
 35.1359 +   0x81,0x00,0x00,0x00,0xb3,0x00,0x52,0x52,0x52,0xbd,0x81,0xff,0xff,0xff,0xff,0x03,0xf7,0xf7,0xf7,0xfa,0xa0,0xa0,0xa0,0xd1,0x7e,0x7e,0x7e,0xc7,0xd2,0xd2,0xd2,0xe6,
 35.1360 +   0x81,0xff,0xff,0xff,0xff,0x02,0xc7,0xc7,0xc7,0xe1,0x00,0x00,0x00,0xb3,0x6a,0x6a,0x6a,0xc2,0x81,0xff,0xff,0xff,0xff,0x02,0xf7,0xf7,0xf7,0xfa,0x90,0x90,0x90,0xcc,
 35.1361 +   0xaf,0xaf,0xaf,0xd6,0x82,0xff,0xff,0xff,0xff,0x86,0x00,0x00,0x00,0xb3,0x00,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x00,0x6a,0x6a,0x6a,0xc2,0x81,0x00,0x00,
 35.1362 +   0x00,0xb3,0x01,0xbb,0xbb,0xbb,0xdc,0x7e,0x7e,0x7e,0xc7,0x82,0x00,0x00,0x00,0xb3,0x00,0xbb,0xbb,0xbb,0xdc,0x81,0xff,0xff,0xff,0xff,0x04,0xbb,0xbb,0xbb,0xdc,0xef,
 35.1363 +   0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0x52,0x52,0x52,0xbd,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x03,0xf7,0xf7,0xf7,0xfa,0xa0,0xa0,
 35.1364 +   0xa0,0xd1,0x7e,0x7e,0x7e,0xc7,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0xf7,0xf7,0xf7,0xfa,0x81,0x00,0x00,0x00,0xb3,0x07,0xef,0xef,0xef,0xf5,0xff,0xff,
 35.1365 +   0xff,0xff,0xef,0xef,0xef,0xf5,0x33,0x33,0x33,0xb8,0x00,0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,0xc7,0xc7,0xc7,0xe1,0x52,0x52,0x52,0xbd,0x81,0x00,0x00,0x00,0xb3,0x00,
 35.1366 +   0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x83,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,
 35.1367 +   0xb3,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x00,0x6a,0x6a,0x6a,0xc2,0x81,0x00,0x00,0x00,0xb3,0x01,0xbb,0xbb,0xbb,0xdc,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,
 35.1368 +   0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,
 35.1369 +   0x81,0x00,0x00,0x00,0xb3,0x00,0xef,0xef,0xef,0xf5,0x81,0xff,0xff,0xff,0xff,0x05,0xaf,0xaf,0xaf,0xd6,0x7e,0x7e,0x7e,0xc7,0xbb,0xbb,0xbb,0xdc,0xa0,0xa0,0xa0,0xd1,
 35.1370 +   0x00,0x00,0x00,0xb3,0xa0,0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x01,0xa0,0xa0,0xa0,0xd1,0xaf,0xaf,0xaf,0xd6,
 35.1371 +   0x86,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,
 35.1372 +   0xff,0xff,0xff,0x01,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,
 35.1373 +   0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x01,0x33,0x33,0x33,0xb8,0xf7,0xf7,0xf7,0xfa,0x82,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,
 35.1374 +   0xdc,0xeb,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xb4,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xa6,0x00,0x00,0x00,0xb3,
 35.1375 +   0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0xa0,0xa0,0xa0,0xd1,0x84,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,
 35.1376 +   0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x02,
 35.1377 +   0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x81,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xc7,0xc7,0xc7,0xe1,
 35.1378 +   0x82,0x00,0x00,0x00,0xb3,0x00,0xa0,0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,
 35.1379 +   0x7e,0x7e,0xc7,0x82,0x00,0x00,0x00,0xb3,0x00,0xd2,0xd2,0xd2,0xe6,0x81,0xff,0xff,0xff,0xff,0x85,0xaf,0xaf,0xaf,0xd6,0x01,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,
 35.1380 +   0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x86,0x00,0x00,0x00,0xb3,0x00,0xaf,
 35.1381 +   0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x02,0x90,0x90,0x90,0xcc,0x00,0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,
 35.1382 +   0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,
 35.1383 +   0x01,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xc7,0xc7,0xc7,0xe1,0x82,0x00,0x00,0x00,0xb3,0x00,0xa0,0xa0,0xa0,0xd1,0x81,0xff,0xff,
 35.1384 +   0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x02,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xef,0xef,0xef,0xf5,0x84,0xaf,0xaf,0xaf,0xd6,0x02,0xa0,0xa0,0xa0,0xd1,0x00,0x00,
 35.1385 +   0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x89,0x00,0x00,0x00,0xb3,0x00,0x3e,0x3e,0x3e,0xc1,0x81,0xff,0xff,0xff,0xff,0x00,
 35.1386 +   0xed,0xed,0xed,0xf8,0x84,0x00,0x00,0x00,0xb3,0x00,0x2b,0x2b,0x2b,0xbd,0x84,0x00,0x00,0x00,0xb3,0x00,0x7c,0x7c,0x7c,0xd2,0x81,0xff,0xff,0xff,0xff,0x00,0xe9,0xe9,
 35.1387 +   0xe9,0xf7,0x83,0x00,0x00,0x00,0xb3,0x01,0x7e,0x7e,0x7e,0xc7,0x33,0x33,0x33,0xb8,0x87,0x00,0x00,0x00,0xb3,0x01,0x6a,0x6a,0x6a,0xc2,0x33,0x33,0x33,0xb8,0x82,0x00,
 35.1388 +   0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,
 35.1389 +   0xd6,0x82,0x00,0x00,0x00,0xb3,0x02,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xef,0xef,0xef,0xf5,0x82,0x00,0x00,0x00,0xb3,0x00,0xa0,0xa0,0xa0,0xd1,0x81,0xff,0xff,
 35.1390 +   0xff,0xff,0x04,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0xff,0xff,0xff,0xff,0xef,0xef,0xef,0xf5,0x82,0x00,0x00,0x00,0xb3,0x00,0x52,0x52,0x52,
 35.1391 +   0xbd,0x81,0xff,0xff,0xff,0xff,0x00,0xd2,0xd2,0xd2,0xe6,0x85,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xbb,0xbb,0xbb,0xdc,0x81,
 35.1392 +   0x00,0x00,0x00,0xb3,0x00,0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,0x82,0x00,0x00,0x00,0xb3,0x02,0xa0,0xa0,0xa0,0xd1,0xc7,0xc7,0xc7,0xe1,0xef,0xef,0xef,0xf5,
 35.1393 +   0x81,0xff,0xff,0xff,0xff,0x02,0xef,0xef,0xef,0xf5,0x00,0x00,0x00,0xb3,0xd2,0xd2,0xd2,0xe6,0x81,0xff,0xff,0xff,0xff,0x85,0xaf,0xaf,0xaf,0xd6,0x86,0x00,0x00,0x00,
 35.1394 +   0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x88,
 35.1395 +   0x00,0x00,0x00,0xb3,0x01,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0x81,0xe6,0xe6,0xe6,0xf0,0x01,0xff,0xff,0xff,0xff,0xc7,0xc7,0xc7,0xe1,0x81,0x00,0x00,0x00,0xb3,
 35.1396 +   0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0xa0,0xa0,0xa0,0xd1,0x82,0x00,0x00,0x00,0xb3,0x04,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,
 35.1397 +   0xfa,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xbb,0xbb,0xbb,0xdc,0x81,0x00,0x00,0x00,0xb3,0x00,0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,
 35.1398 +   0xff,0xff,0x86,0x00,0x00,0x00,0xb3,0x02,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xef,0xef,0xef,0xf5,0x84,0xaf,0xaf,0xaf,0xd6,0x00,0xa0,0xa0,0xa0,0xd1,0x82,0x00,
 35.1399 +   0x00,0x00,0xb3,0x00,0xe6,0xe6,0xe6,0xf0,0x83,0xff,0xff,0xff,0xff,0x00,0xa0,0xa0,0xa0,0xd1,0x82,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xa0,0xa0,0xa0,
 35.1400 +   0xd1,0x82,0x00,0x00,0x00,0xb3,0x00,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x81,0x6a,0x6a,0x6a,0xc2,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x84,
 35.1401 +   0xaf,0xaf,0xaf,0xd6,0x02,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x83,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,
 35.1402 +   0x81,0xff,0xff,0xff,0xff,0x04,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xef,0xef,0xef,0xf5,0x84,0xaf,0xaf,0xaf,0xd6,0x02,
 35.1403 +   0xa0,0xa0,0xa0,0xd1,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,
 35.1404 +   0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0x6a,0x6a,0x6a,0xc2,0x81,0xff,0xff,0xff,0xff,0x00,0xc7,0xc7,0xc7,0xe1,0x84,0x00,0x00,0x00,0xb3,0x00,0xd2,0xd2,0xd2,
 35.1405 +   0xe6,0x81,0xff,0xff,0xff,0xff,0x85,0xaf,0xaf,0xaf,0xd6,0x85,0x00,0x00,0x00,0xb3,0x06,0x33,0x33,0x33,0xb8,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xe6,0xe6,0xe6,
 35.1406 +   0xf0,0xa0,0xa0,0xa0,0xd1,0x7e,0x7e,0x7e,0xc7,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x01,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,
 35.1407 +   0x00,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x00,0xa0,
 35.1408 +   0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,0xff,0x00,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x00,0x52,0x52,0x52,0xbd,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
 35.1409 +   0xb3,0xb3,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xa6,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,
 35.1410 +   0x7e,0x7e,0x7e,0xc7,0x84,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,
 35.1411 +   0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,
 35.1412 +   0xd6,0x81,0xff,0xff,0xff,0xff,0x81,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,
 35.1413 +   0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,
 35.1414 +   0xdc,0xeb,0x87,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,
 35.1415 +   0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x86,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,
 35.1416 +   0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,
 35.1417 +   0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,
 35.1418 +   0x82,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x87,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,
 35.1419 +   0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x89,0x00,0x00,0x00,0xb3,0x00,0x3e,0x3e,0x3e,0xc1,0x81,0xff,0xff,0xff,0xff,0x00,
 35.1420 +   0xed,0xed,0xed,0xf8,0x8a,0x00,0x00,0x00,0xb3,0x00,0x92,0x92,0x92,0xd8,0x81,0xff,0xff,0xff,0xff,0x00,0xdb,0xdb,0xdb,0xf1,0x91,0x00,0x00,0x00,0xb3,0x00,0x90,0x90,
 35.1421 +   0x90,0xcc,0x82,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,
 35.1422 +   0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x04,0xaf,0xaf,0xaf,0xd6,0x00,0x00,
 35.1423 +   0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,0xeb,0x83,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x85,0x00,0x00,
 35.1424 +   0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,
 35.1425 +   0x81,0x00,0x00,0x00,0xb3,0x00,0xbb,0xbb,0xbb,0xdc,0x83,0xff,0xff,0xff,0xff,0x03,0xf7,0xf7,0xf7,0xfa,0xa0,0xa0,0xa0,0xd1,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,
 35.1426 +   0x87,0xff,0xff,0xff,0xff,0x86,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,
 35.1427 +   0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x87,0x00,0x00,0x00,0xb3,0x00,0xa0,0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,0xff,0x01,0xa0,0xa0,0xa0,0xd1,0xaf,0xaf,0xaf,0xd6,
 35.1428 +   0x81,0xff,0xff,0xff,0xff,0x02,0x33,0x33,0x33,0xb8,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0x00,0x00,0x00,
 35.1429 +   0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,
 35.1430 +   0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x86,0x00,0x00,0x00,0xb3,0x87,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0x00,0x00,0x00,
 35.1431 +   0xb3,0x00,0x52,0x52,0x52,0xbd,0x82,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x83,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x82,
 35.1432 +   0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x81,0x7e,0x7e,0x7e,0xc7,0x87,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,
 35.1433 +   0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x83,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x01,0xaf,0xaf,0xaf,0xd6,0x00,0x00,
 35.1434 +   0x00,0xb3,0x87,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0x00,
 35.1435 +   0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x84,
 35.1436 +   0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x87,0xff,0xff,0xff,0xff,0x86,0x00,0x00,0x00,0xb3,0x01,0x90,0x90,0x90,0xcc,0xf7,0xf7,0xf7,0xfa,0x85,0xff,0xff,0xff,
 35.1437 +   0xff,0x01,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,
 35.1438 +   0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x06,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0xef,0xef,0xef,0xf5,0x00,0x00,0x00,0xb3,0xf7,0xf7,
 35.1439 +   0xf7,0xfa,0xff,0xff,0xff,0xff,0xbb,0xbb,0xbb,0xdc,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xb3,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
 35.1440 +   0x00,0x00,0xb3,0xa6,0x00,0x00,0x00,0xb3,0x00,0xa0,0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0x33,0x33,0x33,
 35.1441 +   0xb8,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x02,0xa0,0xa0,0xa0,0xd1,0x00,0x00,0x00,0xb3,0x52,0x52,0x52,0xbd,0x81,0xff,0xff,
 35.1442 +   0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,
 35.1443 +   0xd6,0x81,0xff,0xff,0xff,0xff,0x01,0x7e,0x7e,0x7e,0xc7,0x52,0x52,0x52,0xbd,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0x00,0x00,0x00,0xb3,0x00,0xaf,
 35.1444 +   0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0xbb,0xbb,0xbb,0xdc,0x82,0x00,0x00,0x00,
 35.1445 +   0xb3,0x00,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x00,0x90,0x90,0x90,0xcc,0x81,0x7e,0x7e,0x7e,0xc7,0x04,0xe6,0xe6,0xe6,0xf0,0xff,0xff,0xff,0xff,0xf7,0xf7,
 35.1446 +   0xf7,0xfa,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xc7,0xc7,0xc7,0xe1,0x81,0x00,0x00,0x00,0xb3,0x00,0xef,0xef,0xef,0xf5,0x81,0xff,
 35.1447 +   0xff,0xff,0xff,0x86,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,
 35.1448 +   0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xc7,0xc7,0xc7,0xe1,0x81,0x00,0x00,0x00,0xb3,0x00,0xef,0xef,
 35.1449 +   0xef,0xf5,0x81,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0xb3,0x52,0x52,0x52,0xbd,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0x00,0x00,0x00,0xb3,0x00,
 35.1450 +   0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x02,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0xef,0xef,0xef,0xf5,0x82,0x7e,0x7e,0x7e,0xc7,
 35.1451 +   0x81,0xff,0xff,0xff,0xff,0x02,0xd2,0xd2,0xd2,0xe6,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xe6,0xe6,0xe6,0xf0,0x89,0x00,0x00,0x00,
 35.1452 +   0xb3,0x00,0x3e,0x3e,0x3e,0xc1,0x81,0xff,0xff,0xff,0xff,0x00,0xed,0xed,0xed,0xf8,0x87,0x00,0x00,0x00,0xb3,0x02,0xb0,0xb0,0xb0,0xe1,0xba,0xba,0xba,0xe5,0xd2,0xd2,
 35.1453 +   0xd2,0xee,0x81,0xff,0xff,0xff,0xff,0x01,0xf8,0xf8,0xf8,0xfd,0x58,0x58,0x58,0xc8,0x8e,0x00,0x00,0x00,0xb3,0x02,0x6a,0x6a,0x6a,0xc2,0xbb,0xbb,0xbb,0xdc,0xef,0xef,
 35.1454 +   0xef,0xf5,0x82,0xff,0xff,0xff,0xff,0x00,0xc7,0xc7,0xc7,0xe1,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,
 35.1455 +   0x82,0x00,0x00,0x00,0xb3,0x03,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0x33,0x33,0x33,0xb8,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,
 35.1456 +   0x81,0xff,0xff,0xff,0xff,0x05,0xa0,0xa0,0xa0,0xd1,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0x33,0x33,0x33,0xb8,0x81,0x00,
 35.1457 +   0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xd2,0xd2,0xd2,0xe6,0x85,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,
 35.1458 +   0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x82,0xff,0xff,0xff,0xff,0x02,
 35.1459 +   0xc7,0xc7,0xc7,0xe1,0xa0,0xa0,0xa0,0xd1,0x33,0x33,0x33,0xb8,0x81,0x00,0x00,0x00,0xb3,0x00,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x00,0x90,0x90,0x90,0xcc,
 35.1460 +   0x81,0x7e,0x7e,0x7e,0xc7,0x02,0xe6,0xe6,0xe6,0xf0,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0x86,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,
 35.1461 +   0xeb,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x87,0x00,0x00,0x00,0xb3,0x04,0xdc,0xdc,0xdc,0xeb,0xff,
 35.1462 +   0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0x33,0x33,0x33,0xb8,0x52,0x52,0x52,0xbd,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xa0,0xa0,0xa0,
 35.1463 +   0xd1,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x05,0x33,0x33,0x33,0xb8,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xef,0xef,0xef,
 35.1464 +   0xf5,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,
 35.1465 +   0xff,0xff,0x86,0x00,0x00,0x00,0xb3,0x02,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0xef,0xef,0xef,0xf5,0x82,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xd2,
 35.1466 +   0xd2,0xd2,0xe6,0x82,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0xff,0xff,0xff,0xff,0x01,0xf7,0xf7,0xf7,0xfa,0x52,0x52,0x52,0xbd,0x82,0x00,0x00,0x00,0xb3,
 35.1467 +   0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x01,0x6a,0x6a,0x6a,0xc2,0x52,0x52,
 35.1468 +   0x52,0xbd,0x81,0xff,0xff,0xff,0xff,0x00,0xd2,0xd2,0xd2,0xe6,0x81,0x7e,0x7e,0x7e,0xc7,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,
 35.1469 +   0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x00,0x90,0x90,0x90,0xcc,0x82,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,
 35.1470 +   0xff,0x04,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0xef,0xef,0xef,0xf5,0x82,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,
 35.1471 +   0x02,0xd2,0xd2,0xd2,0xe6,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x02,0xa0,0xa0,0xa0,0xd1,0x00,0x00,0x00,0xb3,0x52,0x52,0x52,0xbd,0x81,
 35.1472 +   0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0x52,0x52,0x52,0xbd,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,
 35.1473 +   0x00,0x33,0x33,0x33,0xb8,0x81,0x00,0x00,0x00,0xb3,0x00,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x00,0x90,0x90,0x90,0xcc,0x81,0x7e,0x7e,0x7e,0xc7,0x02,0xe6,
 35.1474 +   0xe6,0xe6,0xf0,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0x88,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xaf,0xaf,0xaf,0xd6,0x00,0xc7,0xc7,0xc7,0xe1,0x81,
 35.1475 +   0xff,0xff,0xff,0xff,0x01,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xef,0xef,0xef,0xf5,0x81,0x00,0x00,0x00,0xb3,0x00,0xc7,0xc7,0xc7,
 35.1476 +   0xe1,0x81,0xff,0xff,0xff,0xff,0x02,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x04,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,
 35.1477 +   0xb3,0xc7,0xc7,0xc7,0xe1,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xb3,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
 35.1478 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xa6,0x00,0x00,0x00,0xb3,0x01,0x33,0x33,0x33,0xb8,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x05,0xc7,0xc7,0xc7,0xe1,0xaf,0xaf,
 35.1479 +   0xaf,0xd6,0xef,0xef,0xef,0xf5,0xa0,0xa0,0xa0,0xd1,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x02,0xf7,0xf7,0xf7,0xfa,0xaf,0xaf,0xaf,0xd6,
 35.1480 +   0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,0x02,0xc7,0xc7,0xc7,0xe1,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,
 35.1481 +   0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x02,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,0x02,
 35.1482 +   0xdc,0xdc,0xdc,0xeb,0xaf,0xaf,0xaf,0xd6,0xc7,0xc7,0xc7,0xe1,0x82,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0xff,0xff,0xff,0xff,
 35.1483 +   0x03,0xc7,0xc7,0xc7,0xe1,0xaf,0xaf,0xaf,0xd6,0xa0,0xa0,0xa0,0xd1,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x02,0xc7,0xc7,0xc7,0xe1,0x00,0x00,0x00,0xb3,0x7e,
 35.1484 +   0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x02,0xc7,0xc7,0xc7,0xe1,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x01,0xbb,0xbb,0xbb,0xdc,0xd2,
 35.1485 +   0xd2,0xd2,0xe6,0x81,0xff,0xff,0xff,0xff,0x00,0xef,0xef,0xef,0xf5,0x86,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,
 35.1486 +   0xc7,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x01,0xbb,0xbb,
 35.1487 +   0xbb,0xdc,0xd2,0xd2,0xd2,0xe6,0x81,0xff,0xff,0xff,0xff,0x00,0xef,0xef,0xef,0xf5,0x81,0x00,0x00,0x00,0xb3,0x00,0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,0x02,
 35.1488 +   0xdc,0xdc,0xdc,0xeb,0xaf,0xaf,0xaf,0xd6,0xc7,0xc7,0xc7,0xe1,0x82,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,
 35.1489 +   0x02,0xa0,0xa0,0xa0,0xd1,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x02,0xa0,0xa0,0xa0,0xd1,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x82,
 35.1490 +   0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xaf,0xaf,0xaf,0xd6,0x86,0x00,0x00,0x00,0xb3,0x00,0x3e,0x3e,0x3e,0xc1,0x81,0xff,0xff,0xff,0xff,0x00,0xed,0xed,
 35.1491 +   0xed,0xf8,0x87,0x00,0x00,0x00,0xb3,0x00,0xf5,0xf5,0xf5,0xfc,0x82,0xff,0xff,0xff,0xff,0x01,0xca,0xca,0xca,0xeb,0x2b,0x2b,0x2b,0xbd,0x8e,0x00,0x00,0x00,0xb3,0x00,
 35.1492 +   0xc7,0xc7,0xc7,0xe1,0x84,0xff,0xff,0xff,0xff,0x04,0xdc,0xdc,0xdc,0xeb,0x33,0x33,0x33,0xb8,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0xc7,0xc7,0xc7,0xe1,0x81,0xff,
 35.1493 +   0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xaf,0xaf,0xaf,0xd6,0x01,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x02,0xef,0xef,0xef,0xf5,
 35.1494 +   0xaf,0xaf,0xaf,0xd6,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x03,0xf7,0xf7,0xf7,0xfa,0x33,0x33,0x33,0xb8,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,
 35.1495 +   0xff,0xff,0xff,0x03,0xef,0xef,0xef,0xf5,0xaf,0xaf,0xaf,0xd6,0xbb,0xbb,0xbb,0xdc,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x00,0xa0,0xa0,0xa0,0xd1,0x85,0x00,
 35.1496 +   0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,
 35.1497 +   0xff,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x03,0xe6,0xe6,0xe6,0xf0,0x33,0x33,0x33,0xb8,0x52,0x52,0x52,0xbd,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,
 35.1498 +   0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x02,0xc7,0xc7,0xc7,0xe1,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xc7,0xc7,
 35.1499 +   0xc7,0xe1,0x86,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x03,0xdc,0xdc,0xdc,0xeb,0x52,0x52,0x52,0xbd,0xaf,0xaf,0xaf,0xd6,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,
 35.1500 +   0xff,0xff,0x02,0xc7,0xc7,0xc7,0xe1,0xaf,0xaf,0xaf,0xd6,0x52,0x52,0x52,0xbd,0x84,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xc7,
 35.1501 +   0xc7,0xc7,0xe1,0x81,0x00,0x00,0x00,0xb3,0x05,0xe6,0xe6,0xe6,0xf0,0xff,0xff,0xff,0xff,0xe6,0xe6,0xe6,0xf0,0x00,0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,0xf7,0xf7,0xf7,
 35.1502 +   0xfa,0x81,0xff,0xff,0xff,0xff,0x02,0xc7,0xc7,0xc7,0xe1,0xaf,0xaf,0xaf,0xd6,0xef,0xef,0xef,0xf5,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,
 35.1503 +   0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x86,0x00,
 35.1504 +   0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x02,0xa0,0xa0,0xa0,0xd1,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,
 35.1505 +   0xa0,0xa0,0xa0,0xd1,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x03,0xe6,0xe6,0xe6,0xf0,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,
 35.1506 +   0xe6,0xe6,0xe6,0xf0,0x82,0x00,0x00,0x00,0xb3,0x82,0xff,0xff,0xff,0xff,0x02,0xc7,0xc7,0xc7,0xe1,0xaf,0xaf,0xaf,0xd6,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,
 35.1507 +   0x00,0xef,0xef,0xef,0xf5,0x81,0x00,0x00,0x00,0xb3,0x05,0xdc,0xdc,0xdc,0xeb,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0x6a,0x6a,0x6a,0xc2,0x33,0x33,0x33,0xb8,0xd2,
 35.1508 +   0xd2,0xd2,0xe6,0x81,0xff,0xff,0xff,0xff,0x02,0x52,0x52,0x52,0xbd,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x02,0xf7,0xf7,0xf7,0xfa,0xbb,
 35.1509 +   0xbb,0xbb,0xdc,0xaf,0xaf,0xaf,0xd6,0x81,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,
 35.1510 +   0xff,0xff,0xff,0x02,0xa0,0xa0,0xa0,0xd1,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x02,0xa0,0xa0,0xa0,0xd1,0x00,0x00,0x00,0xb3,0xaf,0xaf,
 35.1511 +   0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x02,0xf7,0xf7,0xf7,0xfa,0xaf,0xaf,0xaf,0xd6,0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,0x00,0xc7,0xc7,0xc7,0xe1,0x81,0x00,
 35.1512 +   0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x05,0xdc,0xdc,0xdc,0xeb,0xaf,0xaf,0xaf,0xd6,0xdc,0xdc,0xdc,0xeb,0xc7,0xc7,0xc7,0xe1,0x00,0x00,
 35.1513 +   0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x02,0xc7,0xc7,0xc7,0xe1,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xc7,0xc7,
 35.1514 +   0xc7,0xe1,0x87,0x00,0x00,0x00,0xb3,0x01,0xa0,0xa0,0xa0,0xd1,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x00,0xbb,0xbb,0xbb,0xdc,0x81,0xff,0xff,0xff,0xff,0x81,
 35.1515 +   0x00,0x00,0x00,0xb3,0x82,0xff,0xff,0xff,0xff,0x01,0xd2,0xd2,0xd2,0xe6,0xbb,0xbb,0xbb,0xdc,0x82,0xff,0xff,0xff,0xff,0x02,0x52,0x52,0x52,0xbd,0x00,0x00,0x00,0xb3,
 35.1516 +   0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x02,0x52,0x52,0x52,0xbd,0x00,0x00,0x00,0xb3,0x90,0x90,0x90,0xcc,0x81,0xff,0xff,0xff,0xff,0x00,0x90,0x90,0x90,0xcc,
 35.1517 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xb2,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xa7,0x00,0x00,0x00,0xb3,0x00,0x90,
 35.1518 +   0x90,0x90,0xcc,0x85,0xff,0xff,0xff,0xff,0x01,0x90,0x90,0x90,0xcc,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0xf7,0xf7,0xf7,0xfa,0x83,0xff,0xff,0xff,0xff,
 35.1519 +   0x02,0xa0,0xa0,0xa0,0xd1,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,
 35.1520 +   0xff,0xff,0xff,0xff,0x02,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x87,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,
 35.1521 +   0x81,0xff,0xff,0xff,0xff,0x00,0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0xc7,0xc7,0xc7,0xe1,0x84,0xff,0xff,0xff,
 35.1522 +   0xff,0x03,0xf7,0xf7,0xf7,0xfa,0x52,0x52,0x52,0xbd,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xf7,0xf7,0xf7,0xfa,0x83,0xff,0xff,0xff,
 35.1523 +   0xff,0x00,0xc7,0xc7,0xc7,0xe1,0x86,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x81,
 35.1524 +   0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xf7,0xf7,0xf7,0xfa,0x83,0xff,0xff,0xff,0xff,
 35.1525 +   0x00,0xc7,0xc7,0xc7,0xe1,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x87,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x01,0x33,0x33,0x33,0xb8,0xe6,0xe6,
 35.1526 +   0xe6,0xf0,0x84,0xff,0xff,0xff,0xff,0x00,0xe6,0xe6,0xe6,0xf0,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xe6,0xe6,0xe6,0xf0,
 35.1527 +   0x82,0xff,0xff,0xff,0xff,0x86,0x00,0x00,0x00,0xb3,0x00,0x3e,0x3e,0x3e,0xc1,0x81,0xff,0xff,0xff,0xff,0x00,0xed,0xed,0xed,0xf8,0x87,0x00,0x00,0x00,0xb3,0x02,0xa2,
 35.1528 +   0xa2,0xa2,0xdd,0xac,0xac,0xac,0xe1,0xcf,0xcf,0xcf,0xed,0x81,0xff,0xff,0xff,0xff,0x01,0xc5,0xc5,0xc5,0xe9,0x04,0x04,0x04,0xb4,0x8c,0x00,0x00,0x00,0xb3,0x00,0xaf,
 35.1529 +   0xaf,0xaf,0xd6,0x82,0xff,0xff,0xff,0xff,0x02,0xef,0xef,0xef,0xf5,0xbb,0xbb,0xbb,0xdc,0x6a,0x6a,0x6a,0xc2,0x82,0x00,0x00,0x00,0xb3,0x86,0xff,0xff,0xff,0xff,0x02,
 35.1530 +   0x00,0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,0xe6,0xe6,0xe6,0xf0,0x85,0xff,0xff,0xff,0xff,0x00,0xa0,0xa0,0xa0,0xd1,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,
 35.1531 +   0x81,0xff,0xff,0xff,0xff,0x00,0xf7,0xf7,0xf7,0xfa,0x83,0xff,0xff,0xff,0xff,0x00,0xe6,0xe6,0xe6,0xf0,0x86,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,
 35.1532 +   0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0xbb,0xbb,0xbb,
 35.1533 +   0xdc,0x84,0xff,0xff,0xff,0xff,0x00,0xc7,0xc7,0xc7,0xe1,0x81,0x00,0x00,0x00,0xb3,0x00,0xc7,0xc7,0xc7,0xe1,0x84,0xff,0xff,0xff,0xff,0x01,0xf7,0xf7,0xf7,0xfa,0x52,
 35.1534 +   0x52,0x52,0xbd,0x86,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x01,0xdc,0xdc,0xdc,0xeb,0x7e,0x7e,0x7e,0xc7,0x85,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,
 35.1535 +   0x84,0x00,0x00,0x00,0xb3,0x00,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x00,0x6a,0x6a,0x6a,0xc2,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,
 35.1536 +   0xff,0xff,0xff,0x02,0x6a,0x6a,0x6a,0xc2,0x00,0x00,0x00,0xb3,0xa0,0xa0,0xa0,0xd1,0x85,0xff,0xff,0xff,0xff,0x03,0xe6,0xe6,0xe6,0xf0,0x33,0x33,0x33,0xb8,0x00,0x00,
 35.1537 +   0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x86,
 35.1538 +   0x00,0x00,0x00,0xb3,0x01,0x33,0x33,0x33,0xb8,0xe6,0xe6,0xe6,0xf0,0x84,0xff,0xff,0xff,0xff,0x00,0xe6,0xe6,0xe6,0xf0,0x81,0x00,0x00,0x00,0xb3,0x01,0x33,0x33,0x33,
 35.1539 +   0xb8,0xef,0xef,0xef,0xf5,0x81,0xff,0xff,0xff,0xff,0x01,0x6a,0x6a,0x6a,0xc2,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,
 35.1540 +   0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xf7,0xf7,0xf7,0xfa,0x84,0xff,0xff,0xff,0xff,0x00,0x90,0x90,0x90,0xcc,0x81,0x00,0x00,0x00,0xb3,0x01,0x6a,0x6a,0x6a,0xc2,
 35.1541 +   0xf7,0xf7,0xf7,0xfa,0x84,0xff,0xff,0xff,0xff,0x00,0xbb,0xbb,0xbb,0xdc,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x00,0xe6,0xe6,
 35.1542 +   0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,0x01,0xaf,0xaf,0xaf,0xd6,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x03,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0x33,0x33,
 35.1543 +   0x33,0xb8,0xe6,0xe6,0xe6,0xf0,0x84,0xff,0xff,0xff,0xff,0x00,0xe6,0xe6,0xe6,0xf0,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,
 35.1544 +   0xf7,0xf7,0xf7,0xfa,0x83,0xff,0xff,0xff,0xff,0x00,0xa0,0xa0,0xa0,0xd1,0x81,0x00,0x00,0x00,0xb3,0x01,0x52,0x52,0x52,0xbd,0xf7,0xf7,0xf7,0xfa,0x84,0xff,0xff,0xff,
 35.1545 +   0xff,0x02,0xbb,0xbb,0xbb,0xdc,0x00,0x00,0x00,0xb3,0xc7,0xc7,0xc7,0xe1,0x84,0xff,0xff,0xff,0xff,0x01,0xf7,0xf7,0xf7,0xfa,0x52,0x52,0x52,0xbd,0x86,0x00,0x00,0x00,
 35.1546 +   0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x81,0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,0x00,0xc7,0xc7,0xc7,0xe1,0x81,0x00,0x00,0x00,0xb3,0x81,
 35.1547 +   0xff,0xff,0xff,0xff,0x00,0xf7,0xf7,0xf7,0xfa,0x83,0xff,0xff,0xff,0xff,0x02,0xef,0xef,0xef,0xf5,0x00,0x00,0x00,0xb3,0x52,0x52,0x52,0xbd,0x81,0xff,0xff,0xff,0xff,
 35.1548 +   0x00,0xd2,0xd2,0xd2,0xe6,0x82,0x00,0x00,0x00,0xb3,0x02,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xd2,0xd2,0xd2,0xe6,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
 35.1549 +   0xb3,0xb2,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xa8,0x00,0x00,0x00,0xb3,0x07,0x6a,0x6a,0x6a,0xc2,0xd2,0xd2,0xd2,0xe6,0xf7,0xf7,
 35.1550 +   0xf7,0xfa,0xff,0xff,0xff,0xff,0xef,0xef,0xef,0xf5,0xaf,0xaf,0xaf,0xd6,0x33,0x33,0x33,0xb8,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x04,0xaf,0xaf,0xaf,0xd6,
 35.1551 +   0xdc,0xdc,0xdc,0xeb,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0x6a,0x6a,0x6a,0xc2,0x81,0xdc,0xdc,0xdc,0xeb,0x02,
 35.1552 +   0xa0,0xa0,0xa0,0xd1,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x05,0x90,0x90,0x90,0xcc,
 35.1553 +   0xe6,0xe6,0xe6,0xf0,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0xaf,0xaf,0xaf,0xd6,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0xa0,
 35.1554 +   0xa0,0xa0,0xd1,0x81,0xdc,0xdc,0xdc,0xeb,0x03,0x7e,0x7e,0x7e,0xc7,0xc7,0xc7,0xc7,0xe1,0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x01,0xa0,
 35.1555 +   0xa0,0xa0,0xd1,0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,0x01,0xd2,0xd2,0xd2,0xe6,0x6a,0x6a,0x6a,0xc2,0x81,0x00,0x00,0x00,0xb3,0x00,0x6a,0x6a,0x6a,0xc2,0x81,
 35.1556 +   0xdc,0xdc,0xdc,0xeb,0x01,0xa0,0xa0,0xa0,0xd1,0xbb,0xbb,0xbb,0xdc,0x81,0xff,0xff,0xff,0xff,0x01,0xc7,0xc7,0xc7,0xe1,0x33,0x33,0x33,0xb8,0x86,0x00,0x00,0x00,0xb3,
 35.1557 +   0x00,0xa0,0xa0,0xa0,0xd1,0x81,0xdc,0xdc,0xdc,0xeb,0x00,0x6a,0x6a,0x6a,0xc2,0x81,0x00,0x00,0x00,0xb3,0x81,0xdc,0xdc,0xdc,0xeb,0x02,0xbb,0xbb,0xbb,0xdc,0x00,0x00,
 35.1558 +   0x00,0xb3,0x6a,0x6a,0x6a,0xc2,0x81,0xdc,0xdc,0xdc,0xeb,0x01,0xa0,0xa0,0xa0,0xd1,0xbb,0xbb,0xbb,0xdc,0x81,0xff,0xff,0xff,0xff,0x01,0xc7,0xc7,0xc7,0xe1,0x33,0x33,
 35.1559 +   0x33,0xb8,0x82,0x00,0x00,0x00,0xb3,0x05,0x90,0x90,0x90,0xcc,0xe6,0xe6,0xe6,0xf0,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0xaf,0xaf,0xaf,0xd6,0xdc,0xdc,0xdc,0xeb,
 35.1560 +   0x81,0xff,0xff,0xff,0xff,0x82,0x00,0x00,0x00,0xb3,0x06,0x33,0x33,0x33,0xb8,0xaf,0xaf,0xaf,0xd6,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0xc7,
 35.1561 +   0xc7,0xc7,0xe1,0x33,0x33,0x33,0xb8,0x81,0x00,0x00,0x00,0xb3,0x00,0x6a,0x6a,0x6a,0xc2,0x81,0xdc,0xdc,0xdc,0xeb,0x03,0xa0,0xa0,0xa0,0xd1,0xaf,0xaf,0xaf,0xd6,0xf7,
 35.1562 +   0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0x84,0x00,0x00,0x00,0xb3,0x02,0x50,0x50,0x50,0xc6,0x63,0x63,0x63,0xcb,0x86,0x86,0x86,0xd5,0x81,0xff,0xff,0xff,0xff,0x00,0xed,
 35.1563 +   0xed,0xed,0xf8,0x8a,0x00,0x00,0x00,0xb3,0x00,0xba,0xba,0xba,0xe5,0x81,0xff,0xff,0xff,0xff,0x00,0x72,0x72,0x72,0xcf,0x8c,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,
 35.1564 +   0xeb,0x81,0xff,0xff,0xff,0xff,0x00,0xbb,0xbb,0xbb,0xdc,0x85,0x00,0x00,0x00,0xb3,0x01,0xdc,0xdc,0xdc,0xeb,0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,0x00,0xef,
 35.1565 +   0xef,0xef,0xf5,0x81,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x02,0x33,0x33,0x33,0xb8,0xaf,0xaf,0xaf,0xd6,0xef,0xef,0xef,0xf5,0x81,0xff,0xff,0xff,0xff,0x01,
 35.1566 +   0xd2,0xd2,0xd2,0xe6,0x7e,0x7e,0x7e,0xc7,0x82,0x00,0x00,0x00,0xb3,0x00,0xa0,0xa0,0xa0,0xd1,0x81,0xdc,0xdc,0xdc,0xeb,0x05,0x6a,0x6a,0x6a,0xc2,0xdc,0xdc,0xdc,0xeb,
 35.1567 +   0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0xbb,0xbb,0xbb,0xdc,0x33,0x33,0x33,0xb8,0x86,0x00,0x00,0x00,0xb3,0x00,0x6a,0x6a,0x6a,0xc2,0x81,0xdc,0xdc,0xdc,0xeb,0x00,
 35.1568 +   0xa0,0xa0,0xa0,0xd1,0x81,0x00,0x00,0x00,0xb3,0x00,0xbb,0xbb,0xbb,0xdc,0x81,0xdc,0xdc,0xdc,0xeb,0x82,0x00,0x00,0x00,0xb3,0x01,0xaf,0xaf,0xaf,0xd6,0xef,0xef,0xef,
 35.1569 +   0xf5,0x81,0xff,0xff,0xff,0xff,0x01,0xd2,0xd2,0xd2,0xe6,0x7e,0x7e,0x7e,0xc7,0x82,0x00,0x00,0x00,0xb3,0x01,0xa0,0xa0,0xa0,0xd1,0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,
 35.1570 +   0xff,0xff,0x01,0xd2,0xd2,0xd2,0xe6,0x6a,0x6a,0x6a,0xc2,0x87,0x00,0x00,0x00,0xb3,0x81,0xdc,0xdc,0xdc,0xeb,0x03,0xbb,0xbb,0xbb,0xdc,0x6a,0x6a,0x6a,0xc2,0xdc,0xdc,
 35.1571 +   0xdc,0xeb,0xef,0xef,0xef,0xf5,0x81,0xff,0xff,0xff,0xff,0x02,0xe6,0xe6,0xe6,0xf0,0xdc,0xdc,0xdc,0xeb,0x6a,0x6a,0x6a,0xc2,0x83,0x00,0x00,0x00,0xb3,0x00,0x33,0x33,
 35.1572 +   0x33,0xb8,0x81,0xdc,0xdc,0xdc,0xeb,0x00,0xc7,0xc7,0xc7,0xe1,0x82,0x00,0x00,0x00,0xb3,0x00,0x52,0x52,0x52,0xbd,0x81,0xdc,0xdc,0xdc,0xeb,0x00,0xaf,0xaf,0xaf,0xd6,
 35.1573 +   0x81,0x00,0x00,0x00,0xb3,0x01,0x7e,0x7e,0x7e,0xc7,0xd2,0xd2,0xd2,0xe6,0x81,0xff,0xff,0xff,0xff,0x02,0xef,0xef,0xef,0xf5,0xaf,0xaf,0xaf,0xd6,0x33,0x33,0x33,0xb8,
 35.1574 +   0x81,0x00,0x00,0x00,0xb3,0x00,0x6a,0x6a,0x6a,0xc2,0x81,0xdc,0xdc,0xdc,0xeb,0x00,0xa0,0xa0,0xa0,0xd1,0x81,0x00,0x00,0x00,0xb3,0x00,0xbb,0xbb,0xbb,0xdc,0x81,0xdc,
 35.1575 +   0xdc,0xdc,0xeb,0x87,0x00,0x00,0x00,0xb3,0x06,0x33,0x33,0x33,0xb8,0xaf,0xaf,0xaf,0xd6,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0xc7,0xc7,0xc7,
 35.1576 +   0xe1,0x33,0x33,0x33,0xb8,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xdc,0xdc,0xdc,0xeb,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0xc7,
 35.1577 +   0xc7,0xc7,0xe1,0x81,0xdc,0xdc,0xdc,0xeb,0x01,0x52,0x52,0x52,0xbd,0x00,0x00,0x00,0xb3,0x81,0xdc,0xdc,0xdc,0xeb,0x05,0xa0,0xa0,0xa0,0xd1,0xaf,0xaf,0xaf,0xd6,0xf7,
 35.1578 +   0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xe6,0xe6,0xe6,0xf0,0x7e,0x7e,0x7e,0xc7,0x83,0x00,0x00,0x00,0xb3,0x05,0x52,0x52,0x52,0xbd,0xc7,0xc7,0xc7,0xe1,0xf7,0xf7,0xf7,
 35.1579 +   0xfa,0xff,0xff,0xff,0xff,0xef,0xef,0xef,0xf5,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,0x00,0xbb,0xbb,0xbb,0xdc,0x81,0xdc,0xdc,0xdc,0xeb,0x04,0x6a,0x6a,0x6a,
 35.1580 +   0xc2,0xdc,0xdc,0xdc,0xeb,0xff,0xff,0xff,0xff,0xaf,0xaf,0xaf,0xd6,0x6a,0x6a,0x6a,0xc2,0x81,0xdc,0xdc,0xdc,0xeb,0x00,0xa0,0xa0,0xa0,0xd1,0x81,0x00,0x00,0x00,0xb3,
 35.1581 +   0x06,0x33,0x33,0x33,0xb8,0xaf,0xaf,0xaf,0xd6,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0xc7,0xc7,0xc7,0xe1,0x33,0x33,0x33,0xb8,0x81,0x00,0x00,
 35.1582 +   0x00,0xb3,0x00,0xa0,0xa0,0xa0,0xd1,0x81,0xdc,0xdc,0xdc,0xeb,0x04,0x7e,0x7e,0x7e,0xc7,0xdc,0xdc,0xdc,0xeb,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0xaf,0xaf,0xaf,
 35.1583 +   0xd6,0x83,0x00,0x00,0x00,0xb3,0x06,0x33,0x33,0x33,0xb8,0xc7,0xc7,0xc7,0xe1,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0xc7,0xc7,0xc7,0xe1,0x52,
 35.1584 +   0x52,0x52,0xbd,0x81,0x00,0x00,0x00,0xb3,0x01,0xa0,0xa0,0xa0,0xd1,0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,0x01,0xd2,0xd2,0xd2,0xe6,0x6a,0x6a,0x6a,0xc2,0x88,
 35.1585 +   0x00,0x00,0x00,0xb3,0x01,0xa0,0xa0,0xa0,0xd1,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x02,0xef,0xef,0xef,0xf5,0xbb,0xbb,0xbb,0xdc,0x33,0x33,0x33,0xb8,0x81,
 35.1586 +   0x00,0x00,0x00,0xb3,0x81,0xdc,0xdc,0xdc,0xeb,0x07,0xbb,0xbb,0xbb,0xdc,0xa0,0xa0,0xa0,0xd1,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,0xeb,0x6a,0x6a,
 35.1587 +   0x6a,0xc2,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xdc,0xdc,0xdc,0xeb,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xdc,
 35.1588 +   0xdc,0xdc,0xeb,0x00,0x33,0x33,0x33,0xb8,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xb1,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
 35.1589 +   0xb3,0xaf,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x86,0x00,0x00,0x00,0xb3,0x01,0x52,0x52,0x52,0xbd,0x6a,
 35.1590 +   0x6a,0x6a,0xc2,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x86,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,
 35.1591 +   0xeb,0x81,0xff,0xff,0xff,0xff,0xbd,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x97,0x00,0x00,0x00,0xb3,0x00,0xd7,0xd7,0xd7,0xf0,0x83,
 35.1592 +   0xff,0xff,0xff,0xff,0x00,0xed,0xed,0xed,0xf8,0x84,0x00,0x00,0x00,0xb3,0x02,0x7b,0x7b,0x7b,0xd1,0xa2,0xa2,0xa2,0xdd,0x2c,0x2c,0x2c,0xbd,0x81,0x00,0x00,0x00,0xb3,
 35.1593 +   0x01,0x07,0x07,0x07,0xb5,0xcd,0xcd,0xcd,0xec,0x81,0xff,0xff,0xff,0xff,0x00,0xa3,0xa3,0xa3,0xdd,0x8c,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,
 35.1594 +   0xff,0xff,0x00,0x90,0x90,0x90,0xcc,0x82,0x00,0x00,0x00,0xb3,0x00,0x33,0x33,0x33,0xb8,0x82,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,
 35.1595 +   0x00,0xaf,0xaf,0xaf,0xd6,0xc0,0x00,0x00,0x00,0xb3,0x01,0x33,0x33,0x33,0xb8,0x7e,0x7e,0x7e,0xc7,0x82,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,
 35.1596 +   0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0xdd,0x00,0x00,0x00,0xb3,0x01,0x52,0x52,0x52,0xbd,0x6a,0x6a,0x6a,0xc2,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xfe,
 35.1597 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xaf,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,
 35.1598 +   0x7e,0xc7,0x85,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,
 35.1599 +   0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x86,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0xbd,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,
 35.1600 +   0xeb,0x81,0xff,0xff,0xff,0xff,0x97,0x00,0x00,0x00,0xb3,0x01,0xa7,0xa7,0xa7,0xdf,0xdc,0xdc,0xdc,0xf2,0x82,0xff,0xff,0xff,0xff,0x00,0xed,0xed,0xed,0xf8,0x84,0x00,
 35.1601 +   0x00,0x00,0xb3,0x00,0x91,0x91,0x91,0xd8,0x81,0xff,0xff,0xff,0xff,0x02,0xe8,0xe8,0xe8,0xf6,0xdc,0xdc,0xdc,0xf1,0xf4,0xf4,0xf4,0xfb,0x82,0xff,0xff,0xff,0xff,0x00,
 35.1602 +   0x79,0x79,0x79,0xd1,0x8c,0x00,0x00,0x00,0xb3,0x00,0xa0,0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,0xff,0x05,0xf7,0xf7,0xf7,0xfa,0xbb,0xbb,0xbb,0xdc,0xaf,0xaf,0xaf,0xd6,
 35.1603 +   0xef,0xef,0xef,0xf5,0xe6,0xe6,0xe6,0xf0,0x33,0x33,0x33,0xb8,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,
 35.1604 +   0xbf,0x00,0x00,0x00,0xb3,0x03,0x33,0x33,0x33,0xb8,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,
 35.1605 +   0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0xdc,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0xff,0x00,
 35.1606 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xfd,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xaf,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,
 35.1607 +   0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x85,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,
 35.1608 +   0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x86,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,
 35.1609 +   0xbd,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x99,0x00,0x00,0x00,0xb3,0x00,0x53,0x53,0x53,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xed,
 35.1610 +   0xed,0xed,0xf8,0x84,0x00,0x00,0x00,0xb3,0x00,0x87,0x87,0x87,0xd5,0x86,0xff,0xff,0xff,0xff,0x01,0xbb,0xbb,0xbb,0xe5,0x03,0x03,0x03,0xb4,0x8d,0x00,0x00,0x00,0xb3,
 35.1611 +   0x00,0xdc,0xdc,0xdc,0xeb,0x85,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x00,0x33,0x33,0x33,0xb8,0x81,0x7e,0x7e,0x7e,0xc7,0x00,0x52,
 35.1612 +   0x52,0x52,0xbd,0xbf,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0xa0,0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,
 35.1613 +   0xff,0x02,0xe6,0xe6,0xe6,0xf0,0xaf,0xaf,0xaf,0xd6,0x90,0x90,0x90,0xcc,0xda,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,
 35.1614 +   0xdc,0xeb,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xfd,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xaf,0x00,0x00,0x00,0xb3,
 35.1615 +   0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x85,0x00,0x00,0x00,0xb3,0x05,0x52,0x52,0x52,0xbd,0xef,0xef,0xef,0xf5,0xf7,0xf7,0xf7,
 35.1616 +   0xfa,0x90,0x90,0x90,0xcc,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x86,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,
 35.1617 +   0xeb,0x81,0xff,0xff,0xff,0xff,0xbd,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x9a,0x00,0x00,0x00,0xb3,0x02,0x6e,0x6e,0x6e,0xce,0x79,
 35.1618 +   0x79,0x79,0xd1,0x6e,0x6e,0x6e,0xce,0x85,0x00,0x00,0x00,0xb3,0x06,0x2f,0x2f,0x2f,0xbe,0x74,0x74,0x74,0xcf,0x9e,0x9e,0x9e,0xdc,0xae,0xae,0xae,0xe1,0xa9,0xa9,0xa9,
 35.1619 +   0xdf,0x89,0x89,0x89,0xd6,0x3c,0x3c,0x3c,0xc1,0x90,0x00,0x00,0x00,0xb3,0x01,0xa0,0xa0,0xa0,0xd1,0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,0x02,0xef,0xef,0xef,
 35.1620 +   0xf5,0xc7,0xc7,0xc7,0xe1,0x52,0x52,0x52,0xbd,0xc6,0x00,0x00,0x00,0xb3,0x02,0xdc,0xdc,0xdc,0xeb,0xff,0xff,0xff,0xff,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,
 35.1621 +   0x01,0x33,0x33,0x33,0xb8,0xf7,0xf7,0xf7,0xfa,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0xda,0x00,0x00,0x00,0xb3,0x03,0x52,0x52,0x52,0xbd,0xef,0xef,0xef,
 35.1622 +   0xf5,0xf7,0xf7,0xf7,0xfa,0x90,0x90,0x90,0xcc,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xfd,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
 35.1623 +   0x00,0xb3,0xaf,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xaf,0xaf,0xaf,0xd6,0x00,0x52,0x52,0x52,0xbd,0x8a,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,
 35.1624 +   0x81,0xaf,0xaf,0xaf,0xd6,0x00,0x52,0x52,0x52,0xbd,0x86,0x00,0x00,0x00,0xb3,0x00,0xa0,0xa0,0xa0,0xd1,0x81,0xaf,0xaf,0xaf,0xd6,0xbd,0x00,0x00,0x00,0xb3,0x00,0xa0,
 35.1625 +   0xa0,0xa0,0xd1,0x81,0xaf,0xaf,0xaf,0xd6,0xff,0x00,0x00,0x00,0xb3,0x8f,0x00,0x00,0x00,0xb3,0x01,0x52,0x52,0x52,0xbd,0xbb,0xbb,0xbb,0xdc,0x81,0xdc,0xdc,0xdc,0xeb,
 35.1626 +   0x00,0xa0,0xa0,0xa0,0xd1,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xdc,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
 35.1627 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
 35.1628 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
 35.1629 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
 35.1630 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
 35.1631 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
 35.1632 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
 35.1633 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
 35.1634 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
 35.1635 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
 35.1636 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
 35.1637 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
 35.1638 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xc9,0x00,0x00,0x00,0xb3,0x02,
 35.1639 +   0x6a,0x6a,0x6a,0xc2,0x7e,0x7e,0x7e,0xc7,0x6a,0x6a,0x6a,0xc2,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xb2,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
 35.1640 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xc8,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0xff,
 35.1641 +   0xff,0xff,0xff,0x01,0xef,0xef,0xef,0xf5,0x6a,0x6a,0x6a,0xc2,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xb0,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
 35.1642 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xc8,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x83,0xff,
 35.1643 +   0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xb0,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
 35.1644 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xc8,0x00,0x00,0x00,0xb3,0x81,0x33,0x33,0x33,0xb8,0x01,0x00,0x00,0x00,0xb3,0xc7,
 35.1645 +   0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x00,0x6a,0x6a,0x6a,0xc2,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xaf,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
 35.1646 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xae,0x00,0x00,0x00,0xb3,0x81,0x7e,0x7e,0x7e,0xc7,0x00,0x6a,0x6a,0x6a,0xc2,0x90,0x00,0x00,0x00,0xb3,0x00,0x33,0x33,0x33,0xb8,0x81,
 35.1647 +   0x7e,0x7e,0x7e,0xc7,0x00,0x33,0x33,0x33,0xb8,0x85,0x00,0x00,0x00,0xb3,0x02,0x52,0x52,0x52,0xbd,0x7e,0x7e,0x7e,0xc7,0x52,0x52,0x52,0xbd,0x8c,0x00,0x00,0x00,0xb3,
 35.1648 +   0x02,0x6a,0x6a,0x6a,0xc2,0x7e,0x7e,0x7e,0xc7,0x33,0x33,0x33,0xb8,0x8e,0x00,0x00,0x00,0xb3,0x02,0x52,0x52,0x52,0xbd,0x7e,0x7e,0x7e,0xc7,0x52,0x52,0x52,0xbd,0x87,
 35.1649 +   0x00,0x00,0x00,0xb3,0x81,0x7e,0x7e,0x7e,0xc7,0x00,0x33,0x33,0x33,0xb8,0x8b,0x00,0x00,0x00,0xb3,0x02,0x52,0x52,0x52,0xbd,0x7e,0x7e,0x7e,0xc7,0x6a,0x6a,0x6a,0xc2,
 35.1650 +   0x83,0x00,0x00,0x00,0xb3,0x02,0x52,0x52,0x52,0xbd,0x7e,0x7e,0x7e,0xc7,0x52,0x52,0x52,0xbd,0x92,0x00,0x00,0x00,0xb3,0x02,0x6a,0x6a,0x6a,0xc2,0x7e,0x7e,0x7e,0xc7,
 35.1651 +   0x33,0x33,0x33,0xb8,0x8c,0x00,0x00,0x00,0xb3,0x81,0x7e,0x7e,0x7e,0xc7,0x87,0x00,0x00,0x00,0xb3,0x00,0x33,0x33,0x33,0xb8,0x81,0x7e,0x7e,0x7e,0xc7,0x00,0x33,0x33,
 35.1652 +   0x33,0xb8,0x83,0x00,0x00,0x00,0xb3,0x00,0x33,0x33,0x33,0xb8,0x81,0x7e,0x7e,0x7e,0xc7,0x86,0x00,0x00,0x00,0xb3,0x02,0x52,0x52,0x52,0xbd,0x7e,0x7e,0x7e,0xc7,0x52,
 35.1653 +   0x52,0x52,0xbd,0x94,0x00,0x00,0x00,0xb3,0x02,0x6a,0x6a,0x6a,0xc2,0x7e,0x7e,0x7e,0xc7,0x6a,0x6a,0x6a,0xc2,0x94,0x00,0x00,0x00,0xb3,0x81,0x7e,0x7e,0x7e,0xc7,0x00,
 35.1654 +   0x33,0x33,0x33,0xb8,0x84,0x00,0x00,0x00,0xb3,0x02,0x52,0x52,0x52,0xbd,0x7e,0x7e,0x7e,0xc7,0x52,0x52,0x52,0xbd,0x88,0x00,0x00,0x00,0xb3,0x81,0x7e,0x7e,0x7e,0xc7,
 35.1655 +   0x00,0x33,0x33,0x33,0xb8,0x92,0x00,0x00,0x00,0xb3,0x02,0x33,0x33,0x33,0xb8,0x7e,0x7e,0x7e,0xc7,0x6a,0x6a,0x6a,0xc2,0x86,0x00,0x00,0x00,0xb3,0x00,0x6a,0x6a,0x6a,
 35.1656 +   0xc2,0x81,0x7e,0x7e,0x7e,0xc7,0x87,0x00,0x00,0x00,0xb3,0x81,0x7e,0x7e,0x7e,0xc7,0x00,0x33,0x33,0x33,0xb8,0xa5,0x00,0x00,0x00,0xb3,0x81,0x7e,0x7e,0x7e,0xc7,0x00,
 35.1657 +   0x52,0x52,0x52,0xbd,0x86,0x00,0x00,0x00,0xb3,0x00,0x52,0x52,0x52,0xbd,0x81,0x7e,0x7e,0x7e,0xc7,0x90,0x00,0x00,0x00,0xb3,0x02,0x6a,0x6a,0x6a,0xc2,0x7e,0x7e,0x7e,
 35.1658 +   0xc7,0x6a,0x6a,0x6a,0xc2,0x92,0x00,0x00,0x00,0xb3,0x02,0x52,0x52,0x52,0xbd,0x7e,0x7e,0x7e,0xc7,0x52,0x52,0x52,0xbd,0x86,0x00,0x00,0x00,0xb3,0x00,0x6a,0x6a,0x6a,
 35.1659 +   0xc2,0x81,0x7e,0x7e,0x7e,0xc7,0x86,0x00,0x00,0x00,0xb3,0x00,0x33,0x33,0x33,0xb8,0x81,0x7e,0x7e,0x7e,0xc7,0x8d,0x00,0x00,0x00,0xb3,0x02,0x6a,0x6a,0x6a,0xc2,0x7e,
 35.1660 +   0x7e,0x7e,0xc7,0x33,0x33,0x33,0xb8,0x85,0x00,0x00,0x00,0xb3,0x00,0x33,0x33,0x33,0xb8,0x81,0xff,0xff,0xff,0xff,0x00,0xc7,0xc7,0xc7,0xe1,0xff,0x00,0x00,0x00,0xb3,
 35.1661 +   0xff,0x00,0x00,0x00,0xb3,0xaf,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xac,0x00,0x00,0x00,0xb3,0x01,0xaf,0xaf,0xaf,0xd6,0xf7,0xf7,
 35.1662 +   0xf7,0xfa,0x82,0xff,0xff,0xff,0xff,0x01,0xf7,0xf7,0xf7,0xfa,0xa0,0xa0,0xa0,0xd1,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,
 35.1663 +   0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x01,0x33,0x33,0x33,0xb8,0xc7,0xc7,0xc7,
 35.1664 +   0xe1,0x83,0xff,0xff,0xff,0xff,0x01,0xc7,0xc7,0xc7,0xe1,0x33,0x33,0x33,0xb8,0x82,0x00,0x00,0x00,0xb3,0x00,0xbb,0xbb,0xbb,0xdc,0x82,0xff,0xff,0xff,0xff,0x00,0xa0,
 35.1665 +   0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,
 35.1666 +   0x00,0x00,0x00,0xb3,0x01,0x6a,0x6a,0x6a,0xc2,0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,0x01,0xf7,0xf7,0xf7,0xfa,0xa0,0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,0xff,
 35.1667 +   0x00,0xaf,0xaf,0xaf,0xd6,0x86,0x00,0x00,0x00,0xb3,0x03,0xdc,0xdc,0xdc,0xeb,0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,0xeb,0xbb,0xbb,0xbb,0xdc,0x82,0xff,0xff,0xff,0xff,
 35.1668 +   0x01,0xd2,0xd2,0xd2,0xe6,0x33,0x33,0x33,0xb8,0x82,0x00,0x00,0x00,0xb3,0x02,0x33,0x33,0x33,0xb8,0xbb,0xbb,0xbb,0xdc,0xf7,0xf7,0xf7,0xfa,0x82,0xff,0xff,0xff,0xff,
 35.1669 +   0x01,0xc7,0xc7,0xc7,0xe1,0x33,0x33,0x33,0xb8,0x87,0x00,0x00,0x00,0xb3,0x01,0x7e,0x7e,0x7e,0xc7,0xe6,0xe6,0xe6,0xf0,0x82,0xff,0xff,0xff,0xff,0x03,0xef,0xef,0xef,
 35.1670 +   0xf5,0x90,0x90,0x90,0xcc,0x33,0x33,0x33,0xb8,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x05,0xdc,0xdc,0xdc,0xeb,0xe6,0xe6,0xe6,0xf0,0xff,0xff,0xff,0xff,0xdc,
 35.1671 +   0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,
 35.1672 +   0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x01,0xbb,0xbb,0xbb,0xdc,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,
 35.1673 +   0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x83,0x00,0x00,0x00,0xb3,0x01,0xa0,0xa0,0xa0,0xd1,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x01,0xf7,
 35.1674 +   0xf7,0xf7,0xfa,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x83,0xff,0xff,0xff,0xff,
 35.1675 +   0x81,0x00,0x00,0x00,0xb3,0x01,0x52,0x52,0x52,0xbd,0xd2,0xd2,0xd2,0xe6,0x82,0xff,0xff,0xff,0xff,0x01,0xf7,0xf7,0xf7,0xfa,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,
 35.1676 +   0xb3,0x01,0x33,0x33,0x33,0xb8,0xd2,0xd2,0xd2,0xe6,0x82,0xff,0xff,0xff,0xff,0x03,0xbb,0xbb,0xbb,0xdc,0xdc,0xdc,0xdc,0xeb,0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,0xeb,
 35.1677 +   0x87,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x83,0x00,0x00,0x00,0xb3,0x01,0x90,0x90,0x90,0xcc,0xef,0xef,0xef,0xf5,0x82,0xff,0xff,
 35.1678 +   0xff,0xff,0x01,0xef,0xef,0xef,0xf5,0x90,0x90,0x90,0xcc,0x82,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x89,0x00,0x00,0x00,0xb3,0x02,
 35.1679 +   0x33,0x33,0x33,0xb8,0xbb,0xbb,0xbb,0xdc,0xf7,0xf7,0xf7,0xfa,0x82,0xff,0xff,0xff,0xff,0x04,0xc7,0xc7,0xc7,0xe1,0x33,0x33,0x33,0xb8,0x00,0x00,0x00,0xb3,0x33,0x33,
 35.1680 +   0x33,0xb8,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x03,0xdc,0xdc,0xdc,0xeb,0xe6,0xe6,0xe6,0xf0,0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,
 35.1681 +   0xb3,0x02,0x33,0x33,0x33,0xb8,0xbb,0xbb,0xbb,0xdc,0xf7,0xf7,0xf7,0xfa,0x82,0xff,0xff,0xff,0xff,0x02,0xc7,0xc7,0xc7,0xe1,0x33,0x33,0x33,0xb8,0xdc,0xdc,0xdc,0xeb,
 35.1682 +   0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x86,0x00,0x00,0x00,0xb3,0x01,0xa0,
 35.1683 +   0xa0,0xa0,0xd1,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x01,0xc7,0xc7,0xc7,0xe1,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x02,0x00,0x00,0x00,0xb3,0x90,
 35.1684 +   0x90,0x90,0xcc,0xef,0xef,0xef,0xf5,0x83,0xff,0xff,0xff,0xff,0x00,0xbb,0xbb,0xbb,0xdc,0x82,0x00,0x00,0x00,0xb3,0x02,0x33,0x33,0x33,0xb8,0xbb,0xbb,0xbb,0xdc,0xf7,
 35.1685 +   0xf7,0xf7,0xfa,0x82,0xff,0xff,0xff,0xff,0x03,0xc7,0xc7,0xc7,0xe1,0x33,0x33,0x33,0xb8,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,
 35.1686 +   0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x03,0x52,0x52,0x52,0xbd,0xef,0xef,0xef,0xf5,0xf7,0xf7,0xf7,0xfa,0x90,0x90,0x90,0xcc,0x86,0x00,0x00,0x00,0xb3,0x00,0xdc,
 35.1687 +   0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x84,0x00,0x00,0x00,0xb3,0x00,0xbb,0xbb,0xbb,0xdc,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,
 35.1688 +   0xb3,0x01,0xaf,0xaf,0xaf,0xd6,0xf7,0xf7,0xf7,0xfa,0x82,0xff,0xff,0xff,0xff,0x01,0xdc,0xdc,0xdc,0xeb,0x6a,0x6a,0x6a,0xc2,0x83,0x00,0x00,0x00,0xb3,0x00,0xd2,0xd2,
 35.1689 +   0xd2,0xe6,0x82,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x86,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x83,0x00,0x00,0x00,0xb3,
 35.1690 +   0x01,0x90,0x90,0x90,0xcc,0xef,0xef,0xef,0xf5,0x82,0xff,0xff,0xff,0xff,0x01,0xef,0xef,0xef,0xf5,0x90,0x90,0x90,0xcc,0x82,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,
 35.1691 +   0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x89,0x00,0x00,0x00,0xb3,0x00,0xbb,0xbb,0xbb,0xdc,0x82,0xff,0xff,0xff,0xff,0x00,0xa0,0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,0xff,0x03,
 35.1692 +   0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0x90,0x90,0x90,0xcc,0xef,0xef,0xef,0xf5,0x83,0xff,0xff,0xff,0xff,0x00,0xbb,0xbb,0xbb,0xdc,0x82,0x00,0x00,0x00,0xb3,0x01,
 35.1693 +   0x52,0x52,0x52,0xbd,0xd2,0xd2,0xd2,0xe6,0x82,0xff,0xff,0xff,0xff,0x01,0xf7,0xf7,0xf7,0xfa,0xaf,0xaf,0xaf,0xd6,0x87,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,
 35.1694 +   0x01,0xbb,0xbb,0xbb,0xdc,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x84,0x00,0x00,0x00,0xb3,0x00,0x52,0x52,0x52,0xbd,0x81,0xff,0xff,
 35.1695 +   0xff,0xff,0x00,0xf7,0xf7,0xf7,0xfa,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xaf,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
 35.1696 +   0xac,0x00,0x00,0x00,0xb3,0x04,0xaf,0xaf,0xaf,0xd6,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0xdc,0xdc,0xdc,0xeb,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x02,
 35.1697 +   0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,
 35.1698 +   0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0xe6,0xe6,0xe6,0xf0,0x85,0xff,0xff,0xff,0xff,0x00,0xe6,0xe6,0xe6,0xf0,0x81,0x00,0x00,0x00,0xb3,0x00,0x6a,
 35.1699 +   0x6a,0x6a,0xc2,0x86,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x03,0xaf,0xaf,0xaf,0xd6,0x00,
 35.1700 +   0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,0xf7,0xf7,0xf7,0xfa,0x86,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x86,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x86,
 35.1701 +   0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,
 35.1702 +   0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x86,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x85,0xff,0xff,0xff,0xff,0x01,0xa0,0xa0,0xa0,0xd1,0xc7,0xc7,0xc7,0xe1,0x81,
 35.1703 +   0xff,0xff,0xff,0xff,0x02,0xc7,0xc7,0xc7,0xe1,0xaf,0xaf,0xaf,0xd6,0xef,0xef,0xef,0xf5,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0xdc,
 35.1704 +   0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x87,0xff,0xff,0xff,
 35.1705 +   0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0x00,0x00,0x00,0xb3,0x00,0x52,0x52,0x52,0xbd,0x81,
 35.1706 +   0xff,0xff,0xff,0xff,0x02,0xef,0xef,0xef,0xf5,0xaf,0xaf,0xaf,0xd6,0xc7,0xc7,0xc7,0xe1,0x82,0xff,0xff,0xff,0xff,0x02,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0x52,
 35.1707 +   0x52,0x52,0xbd,0x84,0xff,0xff,0xff,0xff,0x02,0x00,0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x01,0xdc,0xdc,0xdc,0xeb,0xef,
 35.1708 +   0xef,0xef,0xf5,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x86,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,
 35.1709 +   0xeb,0x87,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0x00,0x00,0x00,0xb3,0x00,0x90,0x90,0x90,0xcc,0x86,0xff,0xff,0xff,0xff,0x00,
 35.1710 +   0x90,0x90,0x90,0xcc,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x89,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,
 35.1711 +   0xff,0xff,0x81,0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x02,0xc7,
 35.1712 +   0xc7,0xc7,0xe1,0xaf,0xaf,0xaf,0xd6,0xef,0xef,0xef,0xf5,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x84,
 35.1713 +   0xff,0xff,0xff,0xff,0x02,0xe6,0xe6,0xe6,0xf0,0x33,0x33,0x33,0xb8,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,
 35.1714 +   0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x86,0x00,0x00,0x00,0xb3,0x00,0xf7,0xf7,0xf7,0xfa,0x86,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0xb3,0x6a,0x6a,
 35.1715 +   0x6a,0xc2,0x81,0xff,0xff,0xff,0xff,0x01,0xdc,0xdc,0xdc,0xeb,0xef,0xef,0xef,0xf5,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,
 35.1716 +   0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,
 35.1717 +   0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x86,0x00,
 35.1718 +   0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x83,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x83,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,
 35.1719 +   0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0xbb,0xbb,0xbb,0xdc,0x85,0xff,0xff,0xff,0xff,0x01,0xf7,0xf7,0xf7,0xfa,0x52,0x52,0x52,0xbd,0x81,0x00,0x00,0x00,0xb3,0x00,0xa0,
 35.1720 +   0xa0,0xa0,0xd1,0x83,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x86,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0x00,0x00,0x00,
 35.1721 +   0xb3,0x00,0x90,0x90,0x90,0xcc,0x86,0xff,0xff,0xff,0xff,0x00,0x90,0x90,0x90,0xcc,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x88,
 35.1722 +   0x00,0x00,0x00,0xb3,0x00,0x6a,0x6a,0x6a,0xc2,0x86,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0x6a,0x6a,0x6a,0xc2,0x81,0xff,0xff,0xff,0xff,
 35.1723 +   0x01,0xdc,0xdc,0xdc,0xeb,0xef,0xef,0xef,0xf5,0x81,0xff,0xff,0xff,0xff,0x03,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,0xf7,0xf7,0xf7,0xfa,0x81,
 35.1724 +   0xff,0xff,0xff,0xff,0x01,0xdc,0xdc,0xdc,0xeb,0xef,0xef,0xef,0xf5,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x86,0x00,0x00,0x00,0xb3,0x87,0xff,0xff,0xff,
 35.1725 +   0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x83,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0xff,0xff,0xff,0xff,0x00,0xa0,0xa0,0xa0,0xd1,0xff,0x00,0x00,0x00,0xb3,0xff,
 35.1726 +   0x00,0x00,0x00,0xb3,0xae,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xad,0x00,0x00,0x00,0xb3,0x03,0xaf,0xaf,0xaf,0xd6,0x33,0x33,0x33,
 35.1727 +   0xb8,0x00,0x00,0x00,0xb3,0x90,0x90,0x90,0xcc,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,
 35.1728 +   0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xa0,0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,
 35.1729 +   0xff,0x00,0xe6,0xe6,0xe6,0xf0,0x81,0x90,0x90,0x90,0xcc,0x00,0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,0x02,0xa0,0xa0,0xa0,0xd1,0x00,0x00,0x00,0xb3,0xaf,0xaf,
 35.1730 +   0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x02,0xe6,0xe6,0xe6,0xf0,0x7e,0x7e,0x7e,0xc7,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,
 35.1731 +   0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x03,0xe6,0xe6,
 35.1732 +   0xe6,0xf0,0x90,0x90,0x90,0xcc,0x7e,0x7e,0x7e,0xc7,0xd2,0xd2,0xd2,0xe6,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x86,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,
 35.1733 +   0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x03,0xaf,0xaf,0xaf,0xd6,0x7e,0x7e,0x7e,0xc7,0xa0,0xa0,0xa0,0xd1,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x02,0x6a,0x6a,
 35.1734 +   0x6a,0xc2,0x00,0x00,0x00,0xb3,0xa0,0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x01,0xa0,0xa0,0xa0,0xd1,0xaf,0xaf,
 35.1735 +   0xaf,0xd6,0x87,0x00,0x00,0x00,0xb3,0x00,0xef,0xef,0xef,0xf5,0x81,0xff,0xff,0xff,0xff,0x07,0xaf,0xaf,0xaf,0xd6,0x7e,0x7e,0x7e,0xc7,0xbb,0xbb,0xbb,0xdc,0xa0,0xa0,
 35.1736 +   0xa0,0xd1,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x05,0x33,0x33,0x33,0xb8,0xef,0xef,0xef,0xf5,
 35.1737 +   0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,
 35.1738 +   0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x03,0xf7,0xf7,0xf7,0xfa,0xa0,0xa0,0xa0,0xd1,0x7e,0x7e,0x7e,0xc7,0xaf,0xaf,0xaf,0xd6,0x81,
 35.1739 +   0xff,0xff,0xff,0xff,0x00,0xf7,0xf7,0xf7,0xfa,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,
 35.1740 +   0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x02,0x7e,0x7e,0x7e,0xc7,
 35.1741 +   0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x04,0xd2,0xd2,0xd2,0xe6,0x00,0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,0x00,0x00,0x00,0xb3,0xc7,0xc7,
 35.1742 +   0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x00,0x6a,0x6a,0x6a,0xc2,0x81,0x00,0x00,0x00,0xb3,0x01,0xbb,0xbb,0xbb,0xdc,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x00,
 35.1743 +   0x6a,0x6a,0x6a,0xc2,0x81,0xff,0xff,0xff,0xff,0x03,0xf7,0xf7,0xf7,0xfa,0xa0,0xa0,0xa0,0xd1,0x7e,0x7e,0x7e,0xc7,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,
 35.1744 +   0xdc,0xdc,0xdc,0xeb,0x87,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0x00,0x00,0x00,0xb3,0x00,0xef,0xef,0xef,0xf5,0x81,0xff,0xff,
 35.1745 +   0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x7e,0x7e,0x7e,0xc7,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0xef,0xef,0xef,0xf5,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,
 35.1746 +   0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x88,0x00,0x00,0x00,0xb3,0x00,0xa0,0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,
 35.1747 +   0xb3,0x01,0xa0,0xa0,0xa0,0xd1,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x02,0xdc,0xdc,0xdc,0xeb,0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,
 35.1748 +   0xb3,0x05,0x33,0x33,0x33,0xb8,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0xa0,0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,0xff,0x00,
 35.1749 +   0xe6,0xe6,0xe6,0xf0,0x81,0x90,0x90,0x90,0xcc,0x03,0xd2,0xd2,0xd2,0xe6,0x33,0x33,0x33,0xb8,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,
 35.1750 +   0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x85,0x00,0x00,0x00,0xb3,0x00,0x6a,0x6a,0x6a,0xc2,0x81,0xff,0xff,
 35.1751 +   0xff,0xff,0x02,0xf7,0xf7,0xf7,0xfa,0x90,0x90,0x90,0xcc,0xaf,0xaf,0xaf,0xd6,0x82,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x03,0xa0,0xa0,0xa0,0xd1,0x6a,0x6a,
 35.1752 +   0x6a,0xc2,0x00,0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0xa0,0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,
 35.1753 +   0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x01,0xa0,0xa0,0xa0,0xd1,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,
 35.1754 +   0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x86,0x00,0x00,0x00,
 35.1755 +   0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x83,0x00,0x00,0x00,0xb3,0x00,0xe6,0xe6,0xe6,0xf0,0x83,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,
 35.1756 +   0x00,0x00,0xb3,0x52,0x52,0x52,0xbd,0x81,0xff,0xff,0xff,0xff,0x03,0xf7,0xf7,0xf7,0xfa,0xa0,0xa0,0xa0,0xd1,0x7e,0x7e,0x7e,0xc7,0xd2,0xd2,0xd2,0xe6,0x81,0xff,0xff,
 35.1757 +   0xff,0xff,0x00,0xc7,0xc7,0xc7,0xe1,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0x33,
 35.1758 +   0x33,0x33,0xb8,0x86,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0x00,0x00,0x00,0xb3,0x00,0xef,0xef,0xef,0xf5,0x81,0xff,0xff,0xff,
 35.1759 +   0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x7e,0x7e,0x7e,0xc7,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0xef,0xef,0xef,0xf5,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,
 35.1760 +   0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x88,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x02,0xe6,0xe6,0xe6,0xf0,0x7e,0x7e,0x7e,0xc7,0xc7,
 35.1761 +   0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x03,0xa0,0xa0,0xa0,0xd1,0x6a,0x6a,0x6a,0xc2,0x00,0x00,0x00,0xb3,0x33,
 35.1762 +   0x33,0x33,0xb8,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x00,0x6a,0x6a,0x6a,0xc2,0x81,
 35.1763 +   0x00,0x00,0x00,0xb3,0x01,0xbb,0xbb,0xbb,0xdc,0x7e,0x7e,0x7e,0xc7,0x87,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x03,0xf7,0xf7,0xf7,0xfa,0xa0,0xa0,0xa0,0xd1,
 35.1764 +   0x7e,0x7e,0x7e,0xc7,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0xf7,0xf7,0xf7,0xfa,0x82,0x00,0x00,0x00,0xb3,0x01,0x33,0x33,0x33,0xb8,0xf7,0xf7,0xf7,0xfa,
 35.1765 +   0x82,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xae,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
 35.1766 +   0x00,0x00,0xb3,0xad,0x00,0x00,0x00,0xb3,0x02,0x52,0x52,0x52,0xbd,0xaf,0xaf,0xaf,0xd6,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x02,0xa0,0xa0,0xa0,0xd1,0x00,
 35.1767 +   0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,
 35.1768 +   0x00,0x00,0x00,0xb3,0xd2,0xd2,0xd2,0xe6,0x81,0xff,0xff,0xff,0xff,0x00,0x52,0x52,0x52,0xbd,0x81,0x00,0x00,0x00,0xb3,0x00,0x52,0x52,0x52,0xbd,0x81,0xff,0xff,0xff,
 35.1769 +   0xff,0x02,0xd2,0xd2,0xd2,0xe6,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x02,0x90,0x90,0x90,0xcc,0x00,0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,
 35.1770 +   0x81,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,
 35.1771 +   0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x00,0x52,0x52,0x52,0xbd,0x82,0x00,0x00,0x00,0xb3,0x02,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0xaf,0xaf,0xaf,0xd6,
 35.1772 +   0x86,0x00,0x00,0x00,0xb3,0x02,0xdc,0xdc,0xdc,0xeb,0xff,0xff,0xff,0xff,0xc7,0xc7,0xc7,0xe1,0x82,0x00,0x00,0x00,0xb3,0x00,0xa0,0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,
 35.1773 +   0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xd2,0xd2,0xd2,0xe6,0x81,0xff,0xff,0xff,0xff,0x85,0xaf,0xaf,0xaf,0xd6,0x85,0x00,0x00,0x00,0xb3,0x00,0x6a,0x6a,
 35.1774 +   0x6a,0xc2,0x81,0xff,0xff,0xff,0xff,0x00,0xc7,0xc7,0xc7,0xe1,0x84,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0xbb,0xbb,0xbb,0xdc,
 35.1775 +   0x81,0x7e,0x7e,0x7e,0xc7,0x04,0xe6,0xe6,0xe6,0xf0,0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,
 35.1776 +   0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xa0,0xa0,0xa0,0xd1,0x82,0x00,0x00,
 35.1777 +   0x00,0xb3,0x00,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x01,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x82,
 35.1778 +   0x00,0x00,0x00,0xb3,0x06,0x33,0x33,0x33,0xb8,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xe6,0xe6,0xe6,0xf0,0xa0,0xa0,0xa0,0xd1,0x7e,0x7e,0x7e,0xc7,0xaf,0xaf,0xaf,
 35.1779 +   0xd6,0x81,0xff,0xff,0xff,0xff,0x02,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,
 35.1780 +   0x00,0xb3,0x02,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xef,0xef,0xef,0xf5,0x84,0xaf,0xaf,0xaf,0xd6,0x02,0xa0,0xa0,0xa0,0xd1,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,
 35.1781 +   0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0xa0,0xa0,0xa0,0xd1,0x82,0x00,0x00,0x00,0xb3,0x02,0xc7,0xc7,0xc7,0xe1,0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,0xeb,0x87,0x00,0x00,
 35.1782 +   0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x00,0x6a,0x6a,0x6a,0xc2,0x81,0xff,0xff,0xff,0xff,0x00,0xc7,0xc7,0xc7,0xe1,
 35.1783 +   0x82,0x00,0x00,0x00,0xb3,0x00,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x01,0x6a,0x6a,0x6a,0xc2,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,
 35.1784 +   0xdc,0xeb,0x88,0x00,0x00,0x00,0xb3,0x00,0xd2,0xd2,0xd2,0xe6,0x81,0xff,0xff,0xff,0xff,0x85,0xaf,0xaf,0xaf,0xd6,0x01,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,
 35.1785 +   0xff,0xff,0xff,0xff,0x00,0xbb,0xbb,0xbb,0xdc,0x81,0x7e,0x7e,0x7e,0xc7,0x04,0xe6,0xe6,0xe6,0xf0,0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0xd2,
 35.1786 +   0xd2,0xd2,0xe6,0x81,0xff,0xff,0xff,0xff,0x00,0x52,0x52,0x52,0xbd,0x84,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,
 35.1787 +   0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x85,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,
 35.1788 +   0xbb,0xbb,0xbb,0xdc,0x81,0x00,0x00,0x00,0xb3,0x00,0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x03,0x33,0x33,0x33,0xb8,0xaf,0xaf,0xaf,
 35.1789 +   0xd6,0xd2,0xd2,0xd2,0xe6,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x02,0xc7,0xc7,0xc7,0xe1,0x00,0x00,0x00,0xb3,0xd2,0xd2,0xd2,0xe6,0x81,0xff,0xff,0xff,0xff,
 35.1790 +   0x85,0xaf,0xaf,0xaf,0xd6,0x01,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,0x01,0x52,0x52,
 35.1791 +   0x52,0xbd,0x6a,0x6a,0x6a,0xc2,0x87,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x82,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x84,
 35.1792 +   0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0xa0,0xa0,0xa0,0xd1,0x82,0x00,0x00,0x00,0xb3,
 35.1793 +   0x02,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,
 35.1794 +   0xc7,0x88,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x00,0x6a,0x6a,0x6a,0xc2,0x81,0xff,0xff,0xff,0xff,0x00,
 35.1795 +   0xc7,0xc7,0xc7,0xe1,0x82,0x00,0x00,0x00,0xb3,0x00,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x01,0x6a,0x6a,0x6a,0xc2,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,
 35.1796 +   0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x88,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x02,0x90,0x90,0x90,0xcc,0x00,0x00,0x00,0xb3,0x33,0x33,
 35.1797 +   0x33,0xb8,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x03,0x33,0x33,0x33,0xb8,0xaf,0xaf,0xaf,0xd6,0xd2,0xd2,0xd2,0xe6,0xf7,0xf7,
 35.1798 +   0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x04,0xc7,0xc7,0xc7,0xe1,0x00,0x00,0x00,0xb3,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xef,0xef,0xef,0xf5,0x84,0xaf,0xaf,0xaf,
 35.1799 +   0xd6,0x00,0xa0,0xa0,0xa0,0xd1,0x86,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xa0,0xa0,0xa0,0xd1,0x82,0x00,0x00,0x00,0xb3,0x00,0xc7,0xc7,0xc7,0xe1,0x81,
 35.1800 +   0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x00,0xa0,0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,0xff,0x00,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,
 35.1801 +   0xff,0xff,0x00,0x52,0x52,0x52,0xbd,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xad,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
 35.1802 +   0xac,0x00,0x00,0x00,0xb3,0x01,0x52,0x52,0x52,0xbd,0xf7,0xf7,0xf7,0xfa,0x83,0xff,0xff,0xff,0xff,0x03,0xdc,0xdc,0xdc,0xeb,0x33,0x33,0x33,0xb8,0x00,0x00,0x00,0xb3,
 35.1803 +   0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,
 35.1804 +   0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x83,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,
 35.1805 +   0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0x7e,0x7e,
 35.1806 +   0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x83,0x00,0x00,0x00,0xb3,0x02,0xdc,
 35.1807 +   0xdc,0xdc,0xeb,0xff,0xff,0xff,0xff,0xaf,0xaf,0xaf,0xd6,0x86,0x00,0x00,0x00,0xb3,0x02,0xdc,0xdc,0xdc,0xeb,0xff,0xff,0xff,0xff,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,
 35.1808 +   0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x87,0xff,0xff,0xff,0xff,0x85,0x00,
 35.1809 +   0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x84,0x00,0x00,0x00,0xb3,0x01,0x33,0x33,0x33,0xb8,0xd2,0xd2,0xd2,0xe6,
 35.1810 +   0x85,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,
 35.1811 +   0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,
 35.1812 +   0xff,0xff,0xff,0xff,0x01,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x83,0x00,0x00,0x00,0xb3,0x01,0x90,0x90,0x90,
 35.1813 +   0xcc,0xf7,0xf7,0xf7,0xfa,0x85,0xff,0xff,0xff,0xff,0x02,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,
 35.1814 +   0xd6,0x82,0x00,0x00,0x00,0xb3,0x87,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,
 35.1815 +   0x7e,0xc7,0x82,0x00,0x00,0x00,0xb3,0x02,0xaf,0xaf,0xaf,0xd6,0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,0xeb,0x87,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,
 35.1816 +   0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,
 35.1817 +   0xd6,0x81,0xff,0xff,0xff,0xff,0x01,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x88,0x00,0x00,0x00,0xb3,0x00,0xdc,
 35.1818 +   0xdc,0xdc,0xeb,0x87,0xff,0xff,0xff,0xff,0x02,0x00,0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,0xd2,0xd2,0xd2,0xe6,0x85,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,
 35.1819 +   0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x85,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,
 35.1820 +   0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x85,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,
 35.1821 +   0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0xe6,0xe6,0xe6,0xf0,0x83,0xff,0xff,0xff,
 35.1822 +   0xff,0x03,0xef,0xef,0xef,0xf5,0x6a,0x6a,0x6a,0xc2,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x87,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,
 35.1823 +   0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x8c,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x01,0x52,
 35.1824 +   0x52,0x52,0xbd,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x00,0xbb,0xbb,0xbb,0xdc,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xaf,
 35.1825 +   0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,
 35.1826 +   0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x88,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,
 35.1827 +   0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,
 35.1828 +   0xff,0xff,0x01,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x88,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,
 35.1829 +   0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x00,0xe6,0xe6,
 35.1830 +   0xe6,0xf0,0x83,0xff,0xff,0xff,0xff,0x02,0xef,0xef,0xef,0xf5,0x6a,0x6a,0x6a,0xc2,0x00,0x00,0x00,0xb3,0x87,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x86,0x00,
 35.1831 +   0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,
 35.1832 +   0xc7,0x81,0x00,0x00,0x00,0xb3,0x06,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0xef,0xef,0xef,0xf5,0x00,0x00,0x00,0xb3,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xbb,
 35.1833 +   0xbb,0xbb,0xdc,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xad,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xac,0x00,0x00,0x00,
 35.1834 +   0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x02,0xef,0xef,0xef,0xf5,0xaf,0xaf,0xaf,0xd6,0x6a,0x6a,0x6a,0xc2,0x82,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,
 35.1835 +   0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x02,0x52,0x52,0x52,0xbd,0x00,0x00,0x00,0xb3,0xa0,0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,
 35.1836 +   0x00,0xb3,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x02,
 35.1837 +   0xc7,0xc7,0xc7,0xe1,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,
 35.1838 +   0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xc7,0xc7,0xc7,0xe1,0x81,
 35.1839 +   0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x03,0x33,0x33,0x33,0xb8,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xaf,0xaf,0xaf,0xd6,0x86,
 35.1840 +   0x00,0x00,0x00,0xb3,0x02,0xdc,0xdc,0xdc,0xeb,0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,0xeb,0x82,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,
 35.1841 +   0x02,0xa0,0xa0,0xa0,0xd1,0x00,0x00,0x00,0xb3,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x00,0x90,0x90,0x90,0xcc,0x81,0x7e,0x7e,0x7e,0xc7,0x02,0xe6,0xe6,0xe6,
 35.1842 +   0xf0,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0x85,0x00,0x00,0x00,0xb3,0x00,0x52,0x52,0x52,0xbd,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,
 35.1843 +   0x00,0xb3,0x00,0x33,0x33,0x33,0xb8,0x83,0x00,0x00,0x00,0xb3,0x01,0x52,0x52,0x52,0xbd,0x90,0x90,0x90,0xcc,0x81,0xaf,0xaf,0xaf,0xd6,0x04,0xef,0xef,0xef,0xf5,0xff,
 35.1844 +   0xff,0xff,0xff,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,
 35.1845 +   0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,
 35.1846 +   0xff,0x01,0x52,0x52,0x52,0xbd,0x00,0x00,0x00,0xb3,0x82,0xff,0xff,0xff,0xff,0x00,0x33,0x33,0x33,0xb8,0x84,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xaf,
 35.1847 +   0xaf,0xaf,0xd6,0x00,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x02,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,
 35.1848 +   0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,0x02,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0xef,0xef,0xef,0xf5,0x82,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,
 35.1849 +   0x02,0xd2,0xd2,0xd2,0xe6,0x00,0x00,0x00,0xb3,0xa0,0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,0x02,0xdc,0xdc,0xdc,
 35.1850 +   0xeb,0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,0xeb,0x87,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x00,0x52,0x52,
 35.1851 +   0x52,0xbd,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x01,0x52,0x52,0x52,0xbd,
 35.1852 +   0x00,0x00,0x00,0xb3,0x82,0xff,0xff,0xff,0xff,0x00,0x33,0x33,0x33,0xb8,0x87,0x00,0x00,0x00,0xb3,0x00,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x00,0x90,0x90,
 35.1853 +   0x90,0xcc,0x81,0x7e,0x7e,0x7e,0xc7,0x02,0xe6,0xe6,0xe6,0xf0,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0x82,0x00,0x00,0x00,0xb3,0x01,0x52,0x52,0x52,0xbd,0x90,0x90,
 35.1854 +   0x90,0xcc,0x81,0xaf,0xaf,0xaf,0xd6,0x04,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,
 35.1855 +   0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x00,0x33,0x33,0x33,0xb8,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x02,
 35.1856 +   0x52,0x52,0x52,0xbd,0x00,0x00,0x00,0xb3,0xa0,0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x85,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,
 35.1857 +   0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0xb3,0x7e,0x7e,
 35.1858 +   0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x02,0xf7,0xf7,0xf7,0xfa,0xbb,0xbb,0xbb,0xdc,0x90,0x90,0x90,0xcc,0x82,0x00,0x00,0x00,0xb3,0x00,0xc7,0xc7,0xc7,0xe1,0x81,0xff,
 35.1859 +   0xff,0xff,0xff,0x00,0x90,0x90,0x90,0xcc,0x81,0x7e,0x7e,0x7e,0xc7,0x04,0xe6,0xe6,0xe6,0xf0,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0x00,0x00,0x00,0xb3,0x7e,0x7e,
 35.1860 +   0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xe6,0xe6,0xe6,0xf0,0x8c,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,
 35.1861 +   0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x01,0xdc,0xdc,0xdc,0xeb,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,
 35.1862 +   0xb3,0xa0,0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x03,0x33,0x33,0x33,0xb8,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,
 35.1863 +   0xff,0xef,0xef,0xef,0xf5,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x88,0x00,0x00,0x00,0xb3,0x81,0xff,
 35.1864 +   0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x00,0x52,0x52,0x52,0xbd,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0x00,0x00,0x00,
 35.1865 +   0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x01,0x52,0x52,0x52,0xbd,0x00,0x00,0x00,0xb3,0x82,0xff,0xff,0xff,0xff,0x00,0x33,0x33,0x33,0xb8,0x87,0x00,
 35.1866 +   0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,
 35.1867 +   0xeb,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x02,0xf7,0xf7,0xf7,0xfa,0xbb,0xbb,0xbb,0xdc,0x90,0x90,0x90,0xcc,0x82,0x00,0x00,0x00,0xb3,
 35.1868 +   0x02,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0xef,0xef,0xef,0xf5,0x82,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xd2,0xd2,0xd2,0xe6,0x86,0x00,0x00,0x00,
 35.1869 +   0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x02,0x52,0x52,0x52,0xbd,0x00,
 35.1870 +   0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x04,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xc7,0xc7,0xc7,0xe1,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,
 35.1871 +   0xfa,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xad,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xac,0x00,0x00,0x00,0xb3,0x00,
 35.1872 +   0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x03,0xa0,0xa0,0xa0,0xd1,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x6a,0x6a,0x6a,0xc2,0x81,0x00,0x00,0x00,0xb3,0x00,
 35.1873 +   0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x02,0xe6,0xe6,0xe6,0xf0,0xaf,0xaf,0xaf,0xd6,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x02,0xa0,0xa0,0xa0,0xd1,
 35.1874 +   0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xf7,0xf7,0xf7,0xfa,0x81,0xbb,0xbb,0xbb,0xdc,0x00,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,
 35.1875 +   0xff,0x02,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,
 35.1876 +   0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0x90,0x90,0x90,
 35.1877 +   0xcc,0x81,0xff,0xff,0xff,0xff,0x03,0xf7,0xf7,0xf7,0xfa,0xbb,0xbb,0xbb,0xdc,0xaf,0xaf,0xaf,0xd6,0xef,0xef,0xef,0xf5,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,
 35.1878 +   0xd6,0x86,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0xaf,0xaf,0xaf,0xd6,0xc7,0xc7,0xc7,0xe1,0x82,0xff,0xff,
 35.1879 +   0xff,0xff,0x02,0x52,0x52,0x52,0xbd,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x02,0xc7,0xc7,0xc7,0xe1,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,
 35.1880 +   0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xc7,0xc7,0xc7,0xe1,0x86,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x03,0xdc,0xdc,0xdc,0xeb,0xaf,
 35.1881 +   0xaf,0xaf,0xd6,0xdc,0xdc,0xdc,0xeb,0xc7,0xc7,0xc7,0xe1,0x81,0x00,0x00,0x00,0xb3,0x09,0x33,0x33,0x33,0xb8,0xaf,0xaf,0xaf,0xd6,0x33,0x33,0x33,0xb8,0x00,0x00,0x00,
 35.1882 +   0xb3,0x52,0x52,0x52,0xbd,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,
 35.1883 +   0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x82,0xff,0xff,0xff,0xff,0x02,0xc7,0xc7,0xc7,0xe1,0xaf,0xaf,0xaf,0xd6,
 35.1884 +   0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x00,0xef,0xef,0xef,0xf5,0x81,0x00,0x00,0x00,0xb3,0x82,0xff,0xff,0xff,0xff,0x00,0xef,0xef,0xef,0xf5,0x81,0xaf,0xaf,
 35.1885 +   0xaf,0xd6,0x03,0x52,0x52,0x52,0xbd,0x00,0x00,0x00,0xb3,0xa0,0xa0,0xa0,0xd1,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x00,0xbb,0xbb,0xbb,0xdc,0x81,0xff,0xff,
 35.1886 +   0xff,0xff,0x02,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xaf,0xaf,0xaf,0xd6,0x01,0x00,
 35.1887 +   0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x02,0xa0,0xa0,0xa0,0xd1,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x02,0xa0,
 35.1888 +   0xa0,0xa0,0xd1,0x00,0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,0x82,0xff,0xff,0xff,0xff,0x02,0xc7,0xc7,0xc7,0xe1,0xaf,0xaf,0xaf,0xd6,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,
 35.1889 +   0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x85,0x00,0x00,0x00,0xb3,0x01,0xa0,0xa0,0xa0,0xd1,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x04,0xef,0xef,0xef,0xf5,0xaf,
 35.1890 +   0xaf,0xaf,0xd6,0xa0,0xa0,0xa0,0xd1,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0xaf,0xaf,0xaf,0xd6,0xdc,0xdc,0xdc,
 35.1891 +   0xeb,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x82,0xff,0xff,0xff,0xff,0x00,0xef,0xef,0xef,0xf5,0x81,0xaf,0xaf,0xaf,0xd6,0x00,
 35.1892 +   0x52,0x52,0x52,0xbd,0x84,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x02,0xc7,0xc7,0xc7,0xe1,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,
 35.1893 +   0x81,0xff,0xff,0xff,0xff,0x00,0xc7,0xc7,0xc7,0xe1,0x81,0x00,0x00,0x00,0xb3,0x09,0x33,0x33,0x33,0xb8,0xaf,0xaf,0xaf,0xd6,0x33,0x33,0x33,0xb8,0x00,0x00,0x00,0xb3,
 35.1894 +   0x52,0x52,0x52,0xbd,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xf7,0xf7,
 35.1895 +   0xf7,0xfa,0x81,0xbb,0xbb,0xbb,0xdc,0x03,0xef,0xef,0xef,0xf5,0x6a,0x6a,0x6a,0xc2,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x02,0xe6,0xe6,
 35.1896 +   0xe6,0xf0,0xaf,0xaf,0xaf,0xd6,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x00,0xa0,0xa0,0xa0,0xd1,0x85,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,
 35.1897 +   0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,
 35.1898 +   0x81,0xff,0xff,0xff,0xff,0x03,0xc7,0xc7,0xc7,0xe1,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0xa0,0xa0,0xa0,0xd1,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,
 35.1899 +   0x81,0xff,0xff,0xff,0xff,0x02,0xc7,0xc7,0xc7,0xe1,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x02,0xc7,0xc7,0xc7,0xe1,0x00,0x00,0x00,0xb3,
 35.1900 +   0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xaf,0xaf,0xaf,0xd6,0x89,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,
 35.1901 +   0xff,0xff,0x01,0x00,0x00,0x00,0xb3,0x90,0x90,0x90,0xcc,0x81,0xff,0xff,0xff,0xff,0x02,0xf7,0xf7,0xf7,0xfa,0x52,0x52,0x52,0xbd,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,
 35.1902 +   0xff,0xff,0x03,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x02,0xc7,0xc7,0xc7,0xe1,0xaf,0xaf,0xaf,
 35.1903 +   0xd6,0xef,0xef,0xef,0xf5,0x81,0xff,0xff,0xff,0xff,0x03,0xaf,0xaf,0xaf,0xd6,0x52,0x52,0x52,0xbd,0xaf,0xaf,0xaf,0xd6,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,
 35.1904 +   0x02,0xc7,0xc7,0xc7,0xe1,0xaf,0xaf,0xaf,0xd6,0xa0,0xa0,0xa0,0xd1,0x84,0x00,0x00,0x00,0xb3,0x01,0xa0,0xa0,0xa0,0xd1,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,
 35.1905 +   0x04,0xef,0xef,0xef,0xf5,0xaf,0xaf,0xaf,0xd6,0xa0,0xa0,0xa0,0xd1,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0xaf,
 35.1906 +   0xaf,0xaf,0xd6,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x82,0xff,0xff,0xff,0xff,0x00,0xef,0xef,0xef,0xf5,
 35.1907 +   0x81,0xaf,0xaf,0xaf,0xd6,0x00,0x52,0x52,0x52,0xbd,0x84,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0x00,
 35.1908 +   0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x03,0xc7,0xc7,0xc7,0xe1,0x00,
 35.1909 +   0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0xa0,0xa0,0xa0,0xd1,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x02,0xa0,0xa0,0xa0,0xd1,0x00,
 35.1910 +   0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0xa0,0xa0,0xa0,0xd1,0x86,0x00,0x00,0x00,0xb3,0x82,0xff,0xff,0xff,0xff,0x02,0xc7,0xc7,0xc7,0xe1,
 35.1911 +   0xaf,0xaf,0xaf,0xd6,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x00,0xef,0xef,0xef,0xf5,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,
 35.1912 +   0xff,0x02,0x52,0x52,0x52,0xbd,0x00,0x00,0x00,0xb3,0x90,0x90,0x90,0xcc,0x81,0xff,0xff,0xff,0xff,0x00,0x90,0x90,0x90,0xcc,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
 35.1913 +   0x00,0xb3,0xac,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xac,0x00,0x00,0x00,0xb3,0x01,0x52,0x52,0x52,0xbd,0xf7,0xf7,0xf7,0xfa,0x83,
 35.1914 +   0xff,0xff,0xff,0xff,0x03,0xf7,0xf7,0xf7,0xfa,0x6a,0x6a,0x6a,0xc2,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x00,0xf7,0xf7,0xf7,0xfa,0x83,
 35.1915 +   0xff,0xff,0xff,0xff,0x00,0x52,0x52,0x52,0xbd,0x81,0x00,0x00,0x00,0xb3,0x00,0xc7,0xc7,0xc7,0xe1,0x85,0xff,0xff,0xff,0xff,0x00,0xc7,0xc7,0xc7,0xe1,0x81,0x00,0x00,
 35.1916 +   0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,
 35.1917 +   0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x86,0xff,0xff,0xff,
 35.1918 +   0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x86,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x86,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,0x00,
 35.1919 +   0xc7,0xc7,0xc7,0xe1,0x84,0xff,0xff,0xff,0xff,0x01,0xf7,0xf7,0xf7,0xfa,0x52,0x52,0x52,0xbd,0x86,0x00,0x00,0x00,0xb3,0x01,0x52,0x52,0x52,0xbd,0xf7,0xf7,0xf7,0xfa,
 35.1920 +   0x84,0xff,0xff,0xff,0xff,0x06,0xbb,0xbb,0xbb,0xdc,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0xdc,0xdc,0xdc,0xeb,0xf7,0xf7,
 35.1921 +   0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x02,0x52,0x52,0x52,0xbd,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,
 35.1922 +   0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x87,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,
 35.1923 +   0xff,0x01,0xef,0xef,0xef,0xf5,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x81,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x81,0xe6,0xe6,0xe6,0xf0,0x81,0xff,
 35.1924 +   0xff,0xff,0xff,0x01,0xc7,0xc7,0xc7,0xe1,0x00,0x00,0x00,0xb3,0x86,0xff,0xff,0xff,0xff,0x02,0x00,0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,0xe6,0xe6,0xe6,0xf0,0x84,0xff,
 35.1925 +   0xff,0xff,0xff,0x00,0xe6,0xe6,0xe6,0xf0,0x82,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x86,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x85,0x00,0x00,0x00,
 35.1926 +   0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x84,0xff,0xff,0xff,0xff,0x03,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0x6a,0x6a,0x6a,0xc2,0xf7,0xf7,0xf7,0xfa,0x84,0xff,0xff,0xff,
 35.1927 +   0xff,0x01,0xf7,0xf7,0xf7,0xfa,0x6a,0x6a,0x6a,0xc2,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x01,0xef,0xef,0xef,0xf5,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,
 35.1928 +   0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x85,0x00,0x00,0x00,0xb3,0x00,0xc7,0xc7,0xc7,0xe1,0x84,0xff,0xff,0xff,0xff,0x01,0xf7,0xf7,0xf7,0xfa,0x52,0x52,0x52,0xbd,0x81,
 35.1929 +   0x00,0x00,0x00,0xb3,0x04,0xdc,0xdc,0xdc,0xeb,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0xdc,0xdc,0xdc,0xeb,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x00,0x52,
 35.1930 +   0x52,0x52,0xbd,0x81,0x00,0x00,0x00,0xb3,0x00,0xbb,0xbb,0xbb,0xdc,0x84,0xff,0xff,0xff,0xff,0x02,0xf7,0xf7,0xf7,0xfa,0x52,0x52,0x52,0xbd,0xdc,0xdc,0xdc,0xeb,0x81,
 35.1931 +   0xff,0xff,0xff,0xff,0x00,0xf7,0xf7,0xf7,0xfa,0x83,0xff,0xff,0xff,0xff,0x00,0x52,0x52,0x52,0xbd,0x85,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,
 35.1932 +   0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0xe6,0xe6,0xe6,0xf0,
 35.1933 +   0x84,0xff,0xff,0xff,0xff,0x00,0xa0,0xa0,0xa0,0xd1,0x81,0x00,0x00,0x00,0xb3,0x00,0xc7,0xc7,0xc7,0xe1,0x84,0xff,0xff,0xff,0xff,0x03,0xf7,0xf7,0xf7,0xfa,0x52,0x52,
 35.1934 +   0x52,0xbd,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xe6,0xe6,0xe6,0xf0,0x82,0xff,0xff,0xff,0xff,0x89,0x00,0x00,0x00,0xb3,0x00,0xdc,
 35.1935 +   0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x01,0x33,0x33,0x33,0xb8,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0x7e,
 35.1936 +   0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0xa0,0xa0,0xa0,0xd1,0x85,0xff,0xff,0xff,0xff,0x02,0xe6,0xe6,0xe6,
 35.1937 +   0xf0,0x33,0x33,0x33,0xb8,0x7e,0x7e,0x7e,0xc7,0x85,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x84,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x84,0xff,0xff,
 35.1938 +   0xff,0xff,0x03,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0x6a,0x6a,0x6a,0xc2,0xf7,0xf7,0xf7,0xfa,0x84,0xff,0xff,0xff,0xff,0x01,0xf7,0xf7,0xf7,0xfa,0x6a,0x6a,0x6a,
 35.1939 +   0xc2,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x01,0xef,0xef,0xef,0xf5,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x84,0x00,
 35.1940 +   0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,
 35.1941 +   0xeb,0x81,0x00,0x00,0x00,0xb3,0x00,0xe6,0xe6,0xe6,0xf0,0x84,0xff,0xff,0xff,0xff,0x03,0xa0,0xa0,0xa0,0xd1,0x00,0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,0xe6,0xe6,0xe6,
 35.1942 +   0xf0,0x84,0xff,0xff,0xff,0xff,0x00,0xe6,0xe6,0xe6,0xf0,0x87,0x00,0x00,0x00,0xb3,0x87,0xff,0xff,0xff,0xff,0x02,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0x52,0x52,
 35.1943 +   0x52,0xbd,0x81,0xff,0xff,0xff,0xff,0x00,0xd2,0xd2,0xd2,0xe6,0x82,0x00,0x00,0x00,0xb3,0x02,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xd2,0xd2,0xd2,0xe6,0xff,0x00,
 35.1944 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xac,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xad,0x00,0x00,0x00,0xb3,0x01,0x6a,0x6a,0x6a,
 35.1945 +   0xc2,0xd2,0xd2,0xd2,0xe6,0x81,0xff,0xff,0xff,0xff,0x04,0xef,0xef,0xef,0xf5,0xaf,0xaf,0xaf,0xd6,0x33,0x33,0x33,0xb8,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,
 35.1946 +   0xff,0xff,0xff,0xff,0x04,0x90,0x90,0x90,0xcc,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0xef,0xef,0xef,0xf5,0x90,0x90,0x90,0xcc,0x83,0x00,0x00,0x00,0xb3,0x01,0xa0,
 35.1947 +   0xa0,0xa0,0xd1,0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,0x01,0xe6,0xe6,0xe6,0xf0,0xa0,0xa0,0xa0,0xd1,0x82,0x00,0x00,0x00,0xb3,0x00,0xa0,0xa0,0xa0,0xd1,0x81,
 35.1948 +   0xdc,0xdc,0xdc,0xeb,0x00,0x6a,0x6a,0x6a,0xc2,0x81,0x00,0x00,0x00,0xb3,0x81,0xdc,0xdc,0xdc,0xeb,0x02,0xbb,0xbb,0xbb,0xdc,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,
 35.1949 +   0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x05,0x33,0x33,0x33,0xb8,0xc7,0xc7,0xc7,0xe1,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,
 35.1950 +   0xdc,0xdc,0xdc,0xeb,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x86,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,
 35.1951 +   0xff,0x04,0x90,0x90,0x90,0xcc,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0xef,0xef,0xef,0xf5,0xaf,0xaf,0xaf,0xd6,0x84,0x00,0x00,0x00,0xb3,0x01,0xa0,0xa0,0xa0,0xd1,
 35.1952 +   0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,0x01,0xd2,0xd2,0xd2,0xe6,0x6a,0x6a,0x6a,0xc2,0x88,0x00,0x00,0x00,0xb3,0x0a,0x33,0x33,0x33,0xb8,0xc7,0xc7,0xc7,0xe1,
 35.1953 +   0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0xc7,0xc7,0xc7,0xe1,0x52,0x52,0x52,0xbd,0x00,0x00,0x00,0xb3,0x52,0x52,0x52,0xbd,0xc7,0xc7,0xc7,0xe1,
 35.1954 +   0xef,0xef,0xef,0xf5,0x81,0xff,0xff,0xff,0xff,0x01,0xdc,0xdc,0xdc,0xeb,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,
 35.1955 +   0xff,0x81,0x00,0x00,0x00,0xb3,0x81,0xdc,0xdc,0xdc,0xeb,0x00,0xbb,0xbb,0xbb,0xdc,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x05,0xdc,0xdc,0xdc,0xeb,0xaf,
 35.1956 +   0xaf,0xaf,0xd6,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xe6,0xe6,0xe6,0xf0,0x90,0x90,0x90,0xcc,0x82,0x00,0x00,0x00,0xb3,0x81,0xdc,0xdc,0xdc,0xeb,0x07,0xbb,0xbb,
 35.1957 +   0xbb,0xdc,0x90,0x90,0x90,0xcc,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0xa0,0xa0,0xa0,0xd1,0xdc,0xdc,0xdc,0xeb,0x81,0xff,
 35.1958 +   0xff,0xff,0xff,0x05,0xef,0xef,0xef,0xf5,0xbb,0xbb,0xbb,0xdc,0x33,0x33,0x33,0xb8,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,
 35.1959 +   0xff,0x00,0xef,0xef,0xef,0xf5,0x81,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x06,0x33,0x33,0x33,0xb8,0xaf,0xaf,0xaf,0xd6,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,
 35.1960 +   0xff,0xf7,0xf7,0xf7,0xfa,0xc7,0xc7,0xc7,0xe1,0x33,0x33,0x33,0xb8,0x83,0x00,0x00,0x00,0xb3,0x04,0xaf,0xaf,0xaf,0xd6,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0xef,
 35.1961 +   0xef,0xef,0xf5,0x90,0x90,0x90,0xcc,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x85,0x00,0x00,0x00,0xb3,0x01,0xbb,0xbb,0xbb,0xdc,0xdc,0xdc,0xdc,0xeb,0x81,
 35.1962 +   0xff,0xff,0xff,0xff,0x02,0xf7,0xf7,0xf7,0xfa,0xdc,0xdc,0xdc,0xeb,0xbb,0xbb,0xbb,0xdc,0x81,0x00,0x00,0x00,0xb3,0x06,0x52,0x52,0x52,0xbd,0xc7,0xc7,0xc7,0xe1,0xf7,
 35.1963 +   0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0xc7,0xc7,0xc7,0xe1,0x52,0x52,0x52,0xbd,0x82,0x00,0x00,0x00,0xb3,0x81,0xdc,0xdc,0xdc,0xeb,0x04,0xbb,0xbb,
 35.1964 +   0xbb,0xdc,0x90,0x90,0x90,0xcc,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0x7e,0x7e,0x7e,0xc7,0x86,0x00,0x00,0x00,0xb3,0x01,0xa0,0xa0,0xa0,0xd1,0xe6,0xe6,0xe6,0xf0,
 35.1965 +   0x81,0xff,0xff,0xff,0xff,0x01,0xd2,0xd2,0xd2,0xe6,0x6a,0x6a,0x6a,0xc2,0x82,0x00,0x00,0x00,0xb3,0x02,0x52,0x52,0x52,0xbd,0xc7,0xc7,0xc7,0xe1,0xef,0xef,0xef,0xf5,
 35.1966 +   0x81,0xff,0xff,0xff,0xff,0x01,0xdc,0xdc,0xdc,0xeb,0x7e,0x7e,0x7e,0xc7,0x83,0x00,0x00,0x00,0xb3,0x01,0x90,0x90,0x90,0xcc,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,
 35.1967 +   0xff,0x03,0xe6,0xe6,0xe6,0xf0,0xa0,0xa0,0xa0,0xd1,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x04,0x90,0x90,0x90,0xcc,0xef,0xef,0xef,0xf5,
 35.1968 +   0xff,0xff,0xff,0xff,0xef,0xef,0xef,0xf5,0x90,0x90,0x90,0xcc,0x86,0x00,0x00,0x00,0xb3,0x00,0x6a,0x6a,0x6a,0xc2,0x81,0xdc,0xdc,0xdc,0xeb,0x00,0xa0,0xa0,0xa0,0xd1,
 35.1969 +   0x81,0x00,0x00,0x00,0xb3,0x00,0xbb,0xbb,0xbb,0xdc,0x81,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x06,0x33,0x33,0x33,0xb8,0xc7,0xc7,0xc7,0xe1,0xf7,0xf7,0xf7,
 35.1970 +   0xfa,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0xc7,0xc7,0xc7,0xe1,0x52,0x52,0x52,0xbd,0x82,0x00,0x00,0x00,0xb3,0x01,0xa0,0xa0,0xa0,0xd1,0xe6,0xe6,0xe6,0xf0,0x81,
 35.1971 +   0xff,0xff,0xff,0xff,0x01,0xd2,0xd2,0xd2,0xe6,0x6a,0x6a,0x6a,0xc2,0x81,0x00,0x00,0x00,0xb3,0x00,0x6a,0x6a,0x6a,0xc2,0x81,0xdc,0xdc,0xdc,0xeb,0x03,0xa0,0xa0,0xa0,
 35.1972 +   0xd1,0xaf,0xaf,0xaf,0xd6,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0x89,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x00,0xbb,0xbb,0xbb,
 35.1973 +   0xdc,0x81,0xff,0xff,0xff,0xff,0x00,0xe6,0xe6,0xe6,0xf0,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,
 35.1974 +   0x00,0x00,0x00,0xb3,0x01,0x7e,0x7e,0x7e,0xc7,0xd2,0xd2,0xd2,0xe6,0x81,0xff,0xff,0xff,0xff,0x06,0xef,0xef,0xef,0xf5,0xaf,0xaf,0xaf,0xd6,0x33,0x33,0x33,0xb8,0x00,
 35.1975 +   0x00,0x00,0xb3,0x6a,0x6a,0x6a,0xc2,0xdc,0xdc,0xdc,0xeb,0xef,0xef,0xef,0xf5,0x81,0xff,0xff,0xff,0xff,0x02,0xe6,0xe6,0xe6,0xf0,0xdc,0xdc,0xdc,0xeb,0xbb,0xbb,0xbb,
 35.1976 +   0xdc,0x84,0x00,0x00,0x00,0xb3,0x01,0xbb,0xbb,0xbb,0xdc,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x02,0xf7,0xf7,0xf7,0xfa,0xdc,0xdc,0xdc,0xeb,0xbb,0xbb,0xbb,
 35.1977 +   0xdc,0x81,0x00,0x00,0x00,0xb3,0x06,0x52,0x52,0x52,0xbd,0xc7,0xc7,0xc7,0xe1,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0xc7,0xc7,0xc7,0xe1,0x52,
 35.1978 +   0x52,0x52,0xbd,0x82,0x00,0x00,0x00,0xb3,0x81,0xdc,0xdc,0xdc,0xeb,0x04,0xbb,0xbb,0xbb,0xdc,0x90,0x90,0x90,0xcc,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0x7e,0x7e,
 35.1979 +   0x7e,0xc7,0x84,0x00,0x00,0x00,0xb3,0x00,0xa0,0xa0,0xa0,0xd1,0x81,0xdc,0xdc,0xdc,0xeb,0x00,0x6a,0x6a,0x6a,0xc2,0x81,0x00,0x00,0x00,0xb3,0x81,0xdc,0xdc,0xdc,0xeb,
 35.1980 +   0x00,0xbb,0xbb,0xbb,0xdc,0x81,0x00,0x00,0x00,0xb3,0x06,0x33,0x33,0x33,0xb8,0xc7,0xc7,0xc7,0xe1,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0xc7,
 35.1981 +   0xc7,0xc7,0xe1,0x52,0x52,0x52,0xbd,0x81,0x00,0x00,0x00,0xb3,0x06,0x33,0x33,0x33,0xb8,0xaf,0xaf,0xaf,0xd6,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,
 35.1982 +   0xfa,0xc7,0xc7,0xc7,0xe1,0x33,0x33,0x33,0xb8,0x87,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x05,0xdc,0xdc,0xdc,0xeb,0xaf,0xaf,0xaf,0xd6,0xf7,0xf7,0xf7,0xfa,
 35.1983 +   0xff,0xff,0xff,0xff,0xe6,0xe6,0xe6,0xf0,0x90,0x90,0x90,0xcc,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xdc,0xdc,0xdc,0xeb,0x00,0x7e,0x7e,0x7e,0xc7,
 35.1984 +   0x82,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xdc,0xdc,0xdc,0xeb,0x00,0x33,0x33,0x33,0xb8,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xab,0x00,
 35.1985 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xb5,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x9b,0x00,0x00,0x00,
 35.1986 +   0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x86,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,
 35.1987 +   0xaf,0xaf,0xaf,0xd6,0x86,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0xa9,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,
 35.1988 +   0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x01,0x33,0x33,0x33,0xb8,0x7e,0x7e,0x7e,0xc7,0x82,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x98,
 35.1989 +   0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x93,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,
 35.1990 +   0xdc,0xeb,0x87,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0xb6,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,
 35.1991 +   0xb9,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x84,0xff,0xff,0xff,0xff,0x00,0x6a,0x6a,0x6a,0xc2,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,
 35.1992 +   0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x8c,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x88,0x00,0x00,0x00,
 35.1993 +   0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0xbc,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0xff,0x00,0x00,0x00,0xb3,0xff,
 35.1994 +   0x00,0x00,0x00,0xb3,0xbd,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xb5,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,
 35.1995 +   0xff,0xff,0x9b,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x86,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,
 35.1996 +   0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x86,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0xa9,0x00,0x00,0x00,0xb3,0x00,0xdc,
 35.1997 +   0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x04,0x00,0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,
 35.1998 +   0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x98,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,
 35.1999 +   0x93,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x87,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0xb6,0x00,
 35.2000 +   0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0xb9,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x83,0xff,0xff,0xff,0xff,0x00,0xbb,0xbb,0xbb,
 35.2001 +   0xdc,0x82,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x8c,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,
 35.2002 +   0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x88,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0xbc,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,
 35.2003 +   0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xbd,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
 35.2004 +   0xb5,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x9b,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,
 35.2005 +   0xaf,0xaf,0xd6,0x86,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x86,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,
 35.2006 +   0xeb,0x81,0xff,0xff,0xff,0xff,0xa9,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x82,0xff,
 35.2007 +   0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x98,0x00,0x00,0x00,0xb3,0x00,0x33,0x33,0x33,0xb8,0x81,0x7e,0x7e,0x7e,
 35.2008 +   0xc7,0x00,0x52,0x52,0x52,0xbd,0x93,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x87,0x00,0x00,0x00,0xb3,0x00,0xef,0xef,0xef,0xf5,0x81,
 35.2009 +   0xff,0xff,0xff,0xff,0x81,0xbb,0xbb,0xbb,0xdc,0xb4,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0xb9,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,
 35.2010 +   0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x01,0xef,0xef,0xef,0xf5,0x33,0x33,0x33,0xb8,0x82,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,
 35.2011 +   0xaf,0xaf,0xaf,0xd6,0x8c,0x00,0x00,0x00,0xb3,0x00,0x52,0x52,0x52,0xbd,0x81,0x7e,0x7e,0x7e,0xc7,0x00,0x33,0x33,0x33,0xb8,0x88,0x00,0x00,0x00,0xb3,0x00,0xef,0xef,
 35.2012 +   0xef,0xf5,0x81,0xff,0xff,0xff,0xff,0x81,0xbb,0xbb,0xbb,0xdc,0xba,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0xff,0x00,0x00,0x00,0xb3,
 35.2013 +   0xff,0x00,0x00,0x00,0xb3,0xbd,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xb5,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,
 35.2014 +   0xff,0xff,0xff,0x9b,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x86,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,
 35.2015 +   0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x86,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0xa9,0x00,0x00,0x00,0xb3,0x00,
 35.2016 +   0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x02,0xdc,0xdc,0xdc,0xeb,0xff,0xff,0xff,0xff,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,
 35.2017 +   0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0xb0,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x87,0x00,0x00,0x00,0xb3,0x00,0xaf,
 35.2018 +   0xaf,0xaf,0xd6,0x83,0xff,0xff,0xff,0xff,0xb4,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0xb9,0x00,0x00,0x00,0xb3,0x00,0xbb,0xbb,0xbb,
 35.2019 +   0xdc,0x82,0xdc,0xdc,0xdc,0xeb,0x00,0x90,0x90,0x90,0xcc,0x83,0x00,0x00,0x00,0xb3,0x00,0x6a,0x6a,0x6a,0xc2,0x81,0xdc,0xdc,0xdc,0xeb,0x00,0xa0,0xa0,0xa0,0xd1,0x99,
 35.2020 +   0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x83,0xff,0xff,0xff,0xff,0xba,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0xff,0x00,0x00,
 35.2021 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xbd,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xb5,0x00,0x00,0x00,0xb3,0x00,0xa0,0xa0,0xa0,0xd1,
 35.2022 +   0x81,0xaf,0xaf,0xaf,0xd6,0x9b,0x00,0x00,0x00,0xb3,0x00,0x52,0x52,0x52,0xbd,0x81,0xaf,0xaf,0xaf,0xd6,0x00,0x7e,0x7e,0x7e,0xc7,0x86,0x00,0x00,0x00,0xb3,0x00,0x52,
 35.2023 +   0x52,0x52,0xbd,0x81,0xaf,0xaf,0xaf,0xd6,0x00,0x7e,0x7e,0x7e,0xc7,0x86,0x00,0x00,0x00,0xb3,0x00,0xa0,0xa0,0xa0,0xd1,0x81,0xaf,0xaf,0xaf,0xd6,0xa9,0x00,0x00,0x00,
 35.2024 +   0xb3,0x00,0xa0,0xa0,0xa0,0xd1,0x81,0xaf,0xaf,0xaf,0xd6,0x86,0x00,0x00,0x00,0xb3,0x81,0xaf,0xaf,0xaf,0xd6,0x00,0xa0,0xa0,0xa0,0xd1,0xb0,0x00,0x00,0x00,0xb3,0x81,
 35.2025 +   0xaf,0xaf,0xaf,0xd6,0x00,0xa0,0xa0,0xa0,0xd1,0x88,0x00,0x00,0x00,0xb3,0x01,0xa0,0xa0,0xa0,0xd1,0xd2,0xd2,0xd2,0xe6,0x81,0xdc,0xdc,0xdc,0xeb,0xb4,0x00,0x00,0x00,
 35.2026 +   0xb3,0x00,0xa0,0xa0,0xa0,0xd1,0x81,0xaf,0xaf,0xaf,0xd6,0xe1,0x00,0x00,0x00,0xb3,0x01,0xa0,0xa0,0xa0,0xd1,0xd2,0xd2,0xd2,0xe6,0x81,0xdc,0xdc,0xdc,0xeb,0xba,0x00,
 35.2027 +   0x00,0x00,0xb3,0x81,0xaf,0xaf,0xaf,0xd6,0x00,0xa0,0xa0,0xa0,0xd1,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xbd,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
 35.2028 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
 35.2029 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
 35.2030 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
 35.2031 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
 35.2032 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
 35.2033 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
 35.2034 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
 35.2035 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
 35.2036 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
 35.2037 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
 35.2038 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
 35.2039 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
 35.2040 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
 35.2041 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
 35.2042 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
 35.2043 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
 35.2044 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xc9,0x00,0x00,0x00,0xb3,0x00,0x33,0x33,0x33,0xb8,0x81,0x7e,0x7e,0x7e,0xc7,0x88,0x00,0x00,
 35.2045 +   0x00,0xb3,0x02,0x52,0x52,0x52,0xbd,0x7e,0x7e,0x7e,0xc7,0x52,0x52,0x52,0xbd,0x87,0x00,0x00,0x00,0xb3,0x02,0x33,0x33,0x33,0xb8,0x7e,0x7e,0x7e,0xc7,0x6a,0x6a,0x6a,
 35.2046 +   0xc2,0x88,0x00,0x00,0x00,0xb3,0x00,0x33,0x33,0x33,0xb8,0x81,0x7e,0x7e,0x7e,0xc7,0x86,0x00,0x00,0x00,0xb3,0x02,0x6a,0x6a,0x6a,0xc2,0x7e,0x7e,0x7e,0xc7,0x33,0x33,
 35.2047 +   0x33,0xb8,0xa0,0x00,0x00,0x00,0xb3,0x00,0x33,0x33,0x33,0xb8,0x81,0x7e,0x7e,0x7e,0xc7,0x00,0x33,0x33,0x33,0xb8,0x92,0x00,0x00,0x00,0xb3,0x00,0x52,0x52,0x52,0xbd,
 35.2048 +   0x81,0x7e,0x7e,0x7e,0xc7,0x8f,0x00,0x00,0x00,0xb3,0x81,0x7e,0x7e,0x7e,0xc7,0x00,0x33,0x33,0x33,0xb8,0x99,0x00,0x00,0x00,0xb3,0x02,0x6a,0x6a,0x6a,0xc2,0x7e,0x7e,
 35.2049 +   0x7e,0xc7,0x52,0x52,0x52,0xbd,0x84,0x00,0x00,0x00,0xb3,0x02,0x33,0x33,0x33,0xb8,0x7e,0x7e,0x7e,0xc7,0x6a,0x6a,0x6a,0xc2,0x87,0x00,0x00,0x00,0xb3,0x02,0x52,0x52,
 35.2050 +   0x52,0xbd,0x7e,0x7e,0x7e,0xc7,0x52,0x52,0x52,0xbd,0x86,0x00,0x00,0x00,0xb3,0x00,0x6a,0x6a,0x6a,0xc2,0x81,0x7e,0x7e,0x7e,0xc7,0x86,0x00,0x00,0x00,0xb3,0x00,0x33,
 35.2051 +   0x33,0x33,0xb8,0x81,0x7e,0x7e,0x7e,0xc7,0x86,0x00,0x00,0x00,0xb3,0x00,0x52,0x52,0x52,0xbd,0x81,0x7e,0x7e,0x7e,0xc7,0x8a,0x00,0x00,0x00,0xb3,0x02,0x33,0x33,0x33,
 35.2052 +   0xb8,0x7e,0x7e,0x7e,0xc7,0x6a,0x6a,0x6a,0xc2,0x87,0x00,0x00,0x00,0xb3,0x02,0x6a,0x6a,0x6a,0xc2,0x7e,0x7e,0x7e,0xc7,0x52,0x52,0x52,0xbd,0x8c,0x00,0x00,0x00,0xb3,
 35.2053 +   0x00,0x33,0x33,0x33,0xb8,0x81,0x7e,0x7e,0x7e,0xc7,0x00,0x33,0x33,0x33,0xb8,0x8e,0x00,0x00,0x00,0xb3,0x81,0x7e,0x7e,0x7e,0xc7,0x00,0x33,0x33,0x33,0xb8,0x8a,0x00,
 35.2054 +   0x00,0x00,0xb3,0x02,0x6a,0x6a,0x6a,0xc2,0x7e,0x7e,0x7e,0xc7,0x33,0x33,0x33,0xb8,0x85,0x00,0x00,0x00,0xb3,0x00,0x33,0x33,0x33,0xb8,0x81,0x7e,0x7e,0x7e,0xc7,0x00,
 35.2055 +   0x52,0x52,0x52,0xbd,0x86,0x00,0x00,0x00,0xb3,0x02,0x6a,0x6a,0x6a,0xc2,0x7e,0x7e,0x7e,0xc7,0x52,0x52,0x52,0xbd,0x9f,0x00,0x00,0x00,0xb3,0x81,0x7e,0x7e,0x7e,0xc7,
 35.2056 +   0x00,0x33,0x33,0x33,0xb8,0x84,0x00,0x00,0x00,0xb3,0x02,0x52,0x52,0x52,0xbd,0x7e,0x7e,0x7e,0xc7,0x52,0x52,0x52,0xbd,0x87,0x00,0x00,0x00,0xb3,0x02,0x6a,0x6a,0x6a,
 35.2057 +   0xc2,0x7e,0x7e,0x7e,0xc7,0x33,0x33,0x33,0xb8,0x86,0x00,0x00,0x00,0xb3,0x81,0x7e,0x7e,0x7e,0xc7,0x00,0x6a,0x6a,0x6a,0xc2,0x86,0x00,0x00,0x00,0xb3,0x02,0x52,0x52,
 35.2058 +   0x52,0xbd,0x7e,0x7e,0x7e,0xc7,0x6a,0x6a,0x6a,0xc2,0x86,0x00,0x00,0x00,0xb3,0x02,0x6a,0x6a,0x6a,0xc2,0x7e,0x7e,0x7e,0xc7,0x6a,0x6a,0x6a,0xc2,0xff,0x00,0x00,0x00,
 35.2059 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xb7,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xb7,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,
 35.2060 +   0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,
 35.2061 +   0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x01,0x52,0x52,0x52,0xbd,0xd2,0xd2,0xd2,0xe6,0x82,0xff,0xff,0xff,0xff,0x02,0xf7,0xf7,0xf7,0xfa,0xaf,
 35.2062 +   0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x00,0xbb,0xbb,0xbb,0xdc,0x82,0xff,0xff,0xff,0xff,
 35.2063 +   0x00,0xa0,0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0xff,0xff,0xff,0xff,0x01,0xdc,
 35.2064 +   0xdc,0xdc,0xeb,0xbb,0xbb,0xbb,0xdc,0x81,0xff,0xff,0xff,0xff,0x82,0x00,0x00,0x00,0xb3,0x01,0x52,0x52,0x52,0xbd,0xd2,0xd2,0xd2,0xe6,0x82,0xff,0xff,0xff,0xff,0x01,
 35.2065 +   0xf7,0xf7,0xf7,0xfa,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,0x01,0x6a,0x6a,0x6a,0xc2,0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,0x01,0xf7,0xf7,0xf7,0xfa,
 35.2066 +   0xa0,0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x88,0x00,0x00,0x00,0xb3,0x00,0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,0x00,0x6a,0x6a,
 35.2067 +   0x6a,0xc2,0x81,0x00,0x00,0x00,0xb3,0x00,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x00,0xa0,0xa0,0xa0,0xd1,0x82,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,
 35.2068 +   0x81,0xff,0xff,0xff,0xff,0x82,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x83,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,
 35.2069 +   0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x87,0x00,0x00,0x00,0xb3,0x00,0xd2,0xd2,0xd2,0xe6,
 35.2070 +   0x82,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,
 35.2071 +   0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x02,0x33,0x33,0x33,0xb8,0xbb,0xbb,0xbb,0xdc,0xf7,0xf7,0xf7,0xfa,0x82,0xff,0xff,
 35.2072 +   0xff,0xff,0x01,0xc7,0xc7,0xc7,0xe1,0x33,0x33,0x33,0xb8,0x86,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x84,0x00,0x00,0x00,0xb3,0x00,
 35.2073 +   0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,0x01,0xaf,0xaf,0xaf,0xd6,0xef,0xef,0xef,0xf5,0x82,0xff,0xff,0xff,
 35.2074 +   0xff,0x01,0xdc,0xdc,0xdc,0xeb,0x6a,0x6a,0x6a,0xc2,0x81,0x00,0x00,0x00,0xb3,0x00,0xbb,0xbb,0xbb,0xdc,0x82,0xff,0xff,0xff,0xff,0x01,0xef,0xef,0xef,0xf5,0xd2,0xd2,
 35.2075 +   0xd2,0xe6,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x01,0x33,0x33,0x33,0xb8,0xd2,0xd2,0xd2,0xe6,0x82,0xff,0xff,0xff,0xff,0x06,0xbb,0xbb,0xbb,0xdc,0xdc,
 35.2076 +   0xdc,0xdc,0xeb,0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0x90,0x90,0x90,0xcc,0xef,0xef,0xef,0xf5,0x83,0xff,0xff,0xff,0xff,0x00,0xbb,0xbb,0xbb,
 35.2077 +   0xdc,0x82,0x00,0x00,0x00,0xb3,0x01,0x52,0x52,0x52,0xbd,0xd2,0xd2,0xd2,0xe6,0x82,0xff,0xff,0xff,0xff,0x01,0xf7,0xf7,0xf7,0xfa,0xaf,0xaf,0xaf,0xd6,0x83,0x00,0x00,
 35.2078 +   0x00,0xb3,0x00,0xd2,0xd2,0xd2,0xe6,0x82,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x85,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,
 35.2079 +   0x01,0xa0,0xa0,0xa0,0xd1,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x01,0xe6,0xe6,0xe6,0xf0,0x6a,0x6a,0x6a,0xc2,0x83,0x00,0x00,0x00,0xb3,0x01,0xaf,0xaf,0xaf,
 35.2080 +   0xd6,0xef,0xef,0xef,0xf5,0x82,0xff,0xff,0xff,0xff,0x01,0xdc,0xdc,0xdc,0xeb,0x6a,0x6a,0x6a,0xc2,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,
 35.2081 +   0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,0x01,0x33,0x33,0x33,0xb8,0xc7,0xc7,0xc7,0xe1,0x83,0xff,0xff,0xff,0xff,0x01,0xc7,0xc7,0xc7,0xe1,0x33,
 35.2082 +   0x33,0x33,0xb8,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x83,0x00,0x00,0x00,0xb3,0x02,0x33,0x33,0x33,
 35.2083 +   0xb8,0xbb,0xbb,0xbb,0xdc,0xf7,0xf7,0xf7,0xfa,0x82,0xff,0xff,0xff,0xff,0x01,0xc7,0xc7,0xc7,0xe1,0x33,0x33,0x33,0xb8,0x86,0x00,0x00,0x00,0xb3,0x01,0x33,0x33,0x33,
 35.2084 +   0xb8,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x01,0xf7,0xf7,0xf7,0xfa,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x33,0x33,0x33,
 35.2085 +   0xb8,0xc7,0xc7,0xc7,0xe1,0x83,0xff,0xff,0xff,0xff,0x01,0xef,0xef,0xef,0xf5,0x6a,0x6a,0x6a,0xc2,0x82,0x00,0x00,0x00,0xb3,0x01,0xaf,0xaf,0xaf,0xd6,0xef,0xef,0xef,
 35.2086 +   0xf5,0x82,0xff,0xff,0xff,0xff,0x01,0xdc,0xdc,0xdc,0xeb,0x6a,0x6a,0x6a,0xc2,0x81,0x00,0x00,0x00,0xb3,0x03,0x90,0x90,0x90,0xcc,0xf7,0xf7,0xf7,0xfa,0xef,0xef,0xef,
 35.2087 +   0xf5,0x52,0x52,0x52,0xbd,0x86,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x84,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,
 35.2088 +   0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x02,0x33,0x33,0x33,0xb8,0xbb,0xbb,0xbb,0xdc,0xf7,0xf7,0xf7,0xfa,0x82,0xff,0xff,0xff,0xff,0x04,
 35.2089 +   0xc7,0xc7,0xc7,0xe1,0x33,0x33,0x33,0xb8,0x00,0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x03,0xdc,0xdc,0xdc,0xeb,0xe6,0xe6,
 35.2090 +   0xe6,0xf0,0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x01,0x6a,0x6a,0x6a,0xc2,0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,0x01,0xf7,0xf7,
 35.2091 +   0xf7,0xfa,0xa0,0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,0xff,0x03,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0xf7,0xf7,0xf7,0xfa,0x82,0xff,0xff,0xff,
 35.2092 +   0xff,0x01,0xf7,0xf7,0xf7,0xfa,0xa0,0xa0,0xa0,0xd1,0x82,0x00,0x00,0x00,0xb3,0x01,0x7e,0x7e,0x7e,0xc7,0xe6,0xe6,0xe6,0xf0,0x82,0xff,0xff,0xff,0xff,0x01,0xef,0xef,
 35.2093 +   0xef,0xf5,0x90,0x90,0x90,0xcc,0x82,0x00,0x00,0x00,0xb3,0x01,0x52,0x52,0x52,0xbd,0xe6,0xe6,0xe6,0xf0,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0xff,0x00,
 35.2094 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xb6,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xb7,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,
 35.2095 +   0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,
 35.2096 +   0xff,0xff,0xff,0xff,0x03,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,0xf7,0xf7,0xf7,0xfa,0x84,0xff,0xff,0xff,0xff,0x01,0xc7,0xc7,0xc7,0xe1,0x00,
 35.2097 +   0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0x6a,0x6a,0x6a,0xc2,0x86,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,
 35.2098 +   0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x87,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x01,0x33,0x33,0x33,0xb8,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,
 35.2099 +   0xff,0x01,0xdc,0xdc,0xdc,0xeb,0xef,0xef,0xef,0xf5,0x81,0xff,0xff,0xff,0xff,0x03,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,0xf7,0xf7,0xf7,0xfa,
 35.2100 +   0x86,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x87,0x00,0x00,0x00,0xb3,0x00,0x6a,0x6a,0x6a,0xc2,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,
 35.2101 +   0x00,0x00,0xb3,0x00,0xef,0xef,0xef,0xf5,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,
 35.2102 +   0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0x52,0x52,0x52,0xbd,0x84,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,
 35.2103 +   0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x86,0x00,0x00,0x00,0xb3,0x00,0xa0,0xa0,0xa0,0xd1,0x83,0xff,0xff,0xff,
 35.2104 +   0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,
 35.2105 +   0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,
 35.2106 +   0x00,0xaf,0xaf,0xaf,0xd6,0x86,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x84,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,
 35.2107 +   0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x01,0xef,0xef,0xef,0xf5,0xdc,0xdc,0xdc,0xeb,
 35.2108 +   0x81,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0xa0,0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0xaf,0xaf,0xaf,0xd6,
 35.2109 +   0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x86,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,
 35.2110 +   0xb3,0x6a,0x6a,0x6a,0xc2,0x81,0xff,0xff,0xff,0xff,0x01,0xdc,0xdc,0xdc,0xeb,0xef,0xef,0xef,0xf5,0x81,0xff,0xff,0xff,0xff,0x03,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,
 35.2111 +   0xb3,0x33,0x33,0x33,0xb8,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x01,0xdc,0xdc,0xdc,0xeb,0xef,0xef,0xef,0xf5,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,
 35.2112 +   0xc7,0x81,0x00,0x00,0x00,0xb3,0x00,0xa0,0xa0,0xa0,0xd1,0x83,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x85,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x86,
 35.2113 +   0xff,0xff,0xff,0xff,0x01,0xf7,0xf7,0xf7,0xfa,0x33,0x33,0x33,0xb8,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x01,0xef,0xef,0xef,
 35.2114 +   0xf5,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,
 35.2115 +   0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,0x00,0xe6,0xe6,0xe6,0xf0,0x85,0xff,0xff,0xff,0xff,0x00,0xe6,0xe6,0xe6,0xf0,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,
 35.2116 +   0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x83,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0xe6,0xe6,0xe6,0xf0,0x81,
 35.2117 +   0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x86,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x86,0xff,0xff,0xff,0xff,0x05,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,
 35.2118 +   0xb3,0xd2,0xd2,0xd2,0xe6,0xff,0xff,0xff,0xff,0xef,0xef,0xef,0xf5,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x03,0xf7,0xf7,0xf7,0xfa,0x33,0x33,0x33,0xb8,0x00,
 35.2119 +   0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x01,0xef,0xef,0xef,0xf5,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,
 35.2120 +   0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x86,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,
 35.2121 +   0xdc,0xeb,0x84,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,
 35.2122 +   0x81,0xff,0xff,0xff,0xff,0x81,0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,
 35.2123 +   0xff,0x02,0xc7,0xc7,0xc7,0xe1,0xaf,0xaf,0xaf,0xd6,0xef,0xef,0xef,0xf5,0x81,0xff,0xff,0xff,0xff,0x03,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,
 35.2124 +   0xf7,0xf7,0xf7,0xfa,0x86,0xff,0xff,0xff,0xff,0x06,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0xdc,0xdc,
 35.2125 +   0xdc,0xeb,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x02,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x05,0xf7,0xf7,
 35.2126 +   0xf7,0xfa,0xdc,0xdc,0xdc,0xeb,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0x33,0x33,0x33,0xb8,0x81,0x00,0x00,0x00,0xb3,0x00,0xc7,0xc7,0xc7,0xe1,
 35.2127 +   0x83,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xb6,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
 35.2128 +   0x00,0x00,0xb3,0xb7,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,
 35.2129 +   0xeb,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x02,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,
 35.2130 +   0xff,0xff,0x03,0xd2,0xd2,0xd2,0xe6,0x7e,0x7e,0x7e,0xc7,0xa0,0xa0,0xa0,0xd1,0xc7,0xc7,0xc7,0xe1,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,
 35.2131 +   0xdc,0xeb,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x02,0xe6,0xe6,0xe6,0xf0,0x7e,0x7e,0x7e,0xc7,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,
 35.2132 +   0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x00,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x03,0xaf,0xaf,0xaf,0xd6,0x7e,0x7e,0x7e,0xc7,0xa0,0xa0,
 35.2133 +   0xa0,0xd1,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x00,0x6a,0x6a,0x6a,0xc2,0x81,
 35.2134 +   0x00,0x00,0x00,0xb3,0x01,0xbb,0xbb,0xbb,0xdc,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x03,0xe6,0xe6,0xe6,
 35.2135 +   0xf0,0x90,0x90,0x90,0xcc,0x7e,0x7e,0x7e,0xc7,0xd2,0xd2,0xd2,0xe6,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x87,0x00,0x00,0x00,0xb3,0x00,0xbb,0xbb,0xbb,
 35.2136 +   0xdc,0x82,0xff,0xff,0xff,0xff,0x02,0xe6,0xe6,0xe6,0xf0,0x00,0x00,0x00,0xb3,0x6a,0x6a,0x6a,0xc2,0x83,0xff,0xff,0xff,0xff,0x00,0x52,0x52,0x52,0xbd,0x81,0x00,0x00,
 35.2137 +   0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x04,0xd2,0xd2,0xd2,0xe6,
 35.2138 +   0x00,0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,
 35.2139 +   0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x86,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x04,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,
 35.2140 +   0xb3,0x33,0x33,0x33,0xb8,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,
 35.2141 +   0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xa0,0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x01,0xa0,0xa0,
 35.2142 +   0xa0,0xd1,0xaf,0xaf,0xaf,0xd6,0x87,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x84,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,
 35.2143 +   0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0x52,0x52,0x52,0xbd,0x81,0xff,0xff,0xff,0xff,0x00,0xd2,0xd2,0xd2,0xe6,0x81,0x00,0x00,0x00,0xb3,
 35.2144 +   0x04,0x6a,0x6a,0x6a,0xc2,0xbb,0xbb,0xbb,0xdc,0x33,0x33,0x33,0xb8,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x82,0x00,0x00,0x00,0xb3,0x00,
 35.2145 +   0xd2,0xd2,0xd2,0xe6,0x81,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0xb3,0x6a,0x6a,0x6a,0xc2,0x81,0xff,0xff,0xff,0xff,0x03,0xf7,0xf7,0xf7,0xfa,0xa0,0xa0,0xa0,0xd1,
 35.2146 +   0x7e,0x7e,0x7e,0xc7,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x03,0xa0,0xa0,0xa0,0xd1,0x6a,0x6a,0x6a,0xc2,
 35.2147 +   0x00,0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x00,
 35.2148 +   0x6a,0x6a,0x6a,0xc2,0x81,0x00,0x00,0x00,0xb3,0x01,0xbb,0xbb,0xbb,0xdc,0x7e,0x7e,0x7e,0xc7,0x82,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,
 35.2149 +   0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,0x85,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x03,0xd2,0xd2,
 35.2150 +   0xd2,0xe6,0x7e,0x7e,0x7e,0xc7,0x90,0x90,0x90,0xcc,0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0x52,0x52,0x52,0xbd,
 35.2151 +   0x81,0xff,0xff,0xff,0xff,0x00,0xd2,0xd2,0xd2,0xe6,0x81,0x00,0x00,0x00,0xb3,0x02,0x6a,0x6a,0x6a,0xc2,0xbb,0xbb,0xbb,0xdc,0x33,0x33,0x33,0xb8,0x81,0x00,0x00,0x00,
 35.2152 +   0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0xa0,0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,0xff,0x00,
 35.2153 +   0xe6,0xe6,0xe6,0xf0,0x81,0x90,0x90,0x90,0xcc,0x00,0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,0x02,0xa0,0xa0,0xa0,0xd1,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,
 35.2154 +   0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0x00,0x00,0x00,0xb3,0x00,0xa0,0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,
 35.2155 +   0x00,0x00,0xb3,0x01,0xa0,0xa0,0xa0,0xd1,0xaf,0xaf,0xaf,0xd6,0x87,0x00,0x00,0x00,0xb3,0x00,0xd2,0xd2,0xd2,0xe6,0x81,0xff,0xff,0xff,0xff,0x02,0xc7,0xc7,0xc7,0xe1,
 35.2156 +   0x7e,0x7e,0x7e,0xc7,0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,0x03,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,0xaf,0xaf,0xaf,0xd6,0x81,0x00,
 35.2157 +   0x00,0x00,0xb3,0x00,0xbb,0xbb,0xbb,0xdc,0x81,0xff,0xff,0xff,0xff,0x01,0x7e,0x7e,0x7e,0xc7,0x52,0x52,0x52,0xbd,0x81,0xff,0xff,0xff,0xff,0x00,0xd2,0xd2,0xd2,0xe6,
 35.2158 +   0x81,0x00,0x00,0x00,0xb3,0x02,0x6a,0x6a,0x6a,0xc2,0xbb,0xbb,0xbb,0xdc,0x33,0x33,0x33,0xb8,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,
 35.2159 +   0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x86,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x84,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,
 35.2160 +   0xff,0xff,0xff,0xff,0x02,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0xa0,0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,
 35.2161 +   0x01,0xa0,0xa0,0xa0,0xd1,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x02,0xdc,0xdc,0xdc,0xeb,0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,
 35.2162 +   0x05,0x33,0x33,0x33,0xb8,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x03,0xe6,
 35.2163 +   0xe6,0xe6,0xf0,0x90,0x90,0x90,0xcc,0x7e,0x7e,0x7e,0xc7,0xd2,0xd2,0xd2,0xe6,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x03,0xaf,
 35.2164 +   0xaf,0xaf,0xd6,0x33,0x33,0x33,0xb8,0x00,0x00,0x00,0xb3,0x90,0x90,0x90,0xcc,0x81,0xff,0xff,0xff,0xff,0x09,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xef,0xef,0xef,
 35.2165 +   0xf5,0xff,0xff,0xff,0xff,0xef,0xef,0xef,0xf5,0x33,0x33,0x33,0xb8,0x00,0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,0xc7,0xc7,0xc7,0xe1,0x52,0x52,0x52,0xbd,0x82,0x00,0x00,
 35.2166 +   0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x02,0x6a,0x6a,0x6a,0xc2,0x00,0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
 35.2167 +   0x00,0x00,0xb3,0xb6,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xb7,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,
 35.2168 +   0xff,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x04,
 35.2169 +   0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xef,0xef,0xef,0xf5,0x85,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,
 35.2170 +   0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x02,0x90,0x90,0x90,0xcc,0x00,0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,0x81,0xff,0xff,
 35.2171 +   0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xc7,0xc7,0xc7,0xe1,0x82,0x00,0x00,0x00,0xb3,0x00,0xa0,
 35.2172 +   0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x02,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xef,0xef,0xef,0xf5,0x84,0xaf,0xaf,0xaf,0xd6,0x02,
 35.2173 +   0xa0,0xa0,0xa0,0xd1,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x00,0x52,0x52,0x52,0xbd,0x82,0x00,0x00,0x00,0xb3,0x02,0xef,0xef,0xef,0xf5,
 35.2174 +   0xff,0xff,0xff,0xff,0xaf,0xaf,0xaf,0xd6,0x87,0x00,0x00,0x00,0xb3,0x02,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x06,
 35.2175 +   0x33,0x33,0x33,0xb8,0xbb,0xbb,0xbb,0xdc,0xff,0xff,0xff,0xff,0xef,0xef,0xef,0xf5,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,
 35.2176 +   0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,
 35.2177 +   0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,
 35.2178 +   0xaf,0xd6,0x86,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,
 35.2179 +   0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xd2,0xd2,0xd2,
 35.2180 +   0xe6,0x81,0xff,0xff,0xff,0xff,0x85,0xaf,0xaf,0xaf,0xd6,0x86,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x84,0x00,0x00,0x00,0xb3,0x00,
 35.2181 +   0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0xc7,0xc7,0xc7,0xe1,
 35.2182 +   0x84,0xaf,0xaf,0xaf,0xd6,0x01,0x52,0x52,0x52,0xbd,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x03,0xd2,0xd2,0xd2,0xe6,0x90,0x90,0x90,0xcc,0x7e,0x7e,0x7e,0xc7,
 35.2183 +   0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0xa0,0xa0,0xa0,0xd1,0x82,0x00,0x00,0x00,
 35.2184 +   0xb3,0x02,0xc7,0xc7,0xc7,0xe1,0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x03,0x33,0x33,0x33,0xb8,0xaf,0xaf,0xaf,0xd6,0xd2,0xd2,0xd2,0xe6,
 35.2185 +   0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x04,0xc7,0xc7,0xc7,0xe1,0x00,0x00,0x00,0xb3,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xef,0xef,0xef,0xf5,0x84,0xaf,
 35.2186 +   0xaf,0xaf,0xd6,0x00,0xa0,0xa0,0xa0,0xd1,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x87,0x00,0x00,0x00,
 35.2187 +   0xb3,0x02,0xaf,0xaf,0xaf,0xd6,0xff,0xff,0xff,0xff,0xef,0xef,0xef,0xf5,0x82,0x00,0x00,0x00,0xb3,0x00,0x52,0x52,0x52,0xbd,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,
 35.2188 +   0xdc,0xeb,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0xc7,0xc7,0xc7,0xe1,0x84,0xaf,0xaf,0xaf,0xd6,0x02,0x52,0x52,0x52,0xbd,0x00,0x00,
 35.2189 +   0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0xd2,0xd2,0xd2,0xe6,0x81,0xff,0xff,0xff,0xff,0x00,
 35.2190 +   0x52,0x52,0x52,0xbd,0x81,0x00,0x00,0x00,0xb3,0x00,0x52,0x52,0x52,0xbd,0x81,0xff,0xff,0xff,0xff,0x02,0xd2,0xd2,0xd2,0xe6,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,
 35.2191 +   0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0x00,0x00,0x00,0xb3,0x00,0xd2,0xd2,0xd2,0xe6,0x81,0xff,0xff,0xff,0xff,0x85,0xaf,0xaf,0xaf,0xd6,0x86,0x00,
 35.2192 +   0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x02,0x33,0x33,0x33,0xb8,0x00,0x00,0x00,0xb3,0x90,0x90,0x90,0xcc,0x81,0xff,0xff,0xff,0xff,0x00,
 35.2193 +   0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x02,0x7e,0x7e,0x7e,0xc7,0xbb,0xbb,0xbb,0xdc,0xe6,0xe6,0xe6,0xf0,0x82,0xff,0xff,0xff,0xff,0x01,0x52,0x52,0x52,0xbd,
 35.2194 +   0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0xc7,0xc7,0xc7,0xe1,0x84,0xaf,0xaf,0xaf,0xd6,0x00,0x52,0x52,0x52,0xbd,0x81,0x00,0x00,0x00,0xb3,0x01,0x6a,0x6a,
 35.2195 +   0x6a,0xc2,0x52,0x52,0x52,0xbd,0x87,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x84,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,
 35.2196 +   0xff,0xff,0xff,0xff,0x02,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0xd2,0xd2,0xd2,0xe6,0x81,0xff,0xff,0xff,0xff,0x85,0xaf,0xaf,0xaf,0xd6,0x01,0x00,0x00,0x00,0xb3,
 35.2197 +   0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0xbb,0xbb,0xbb,0xdc,0x81,0x7e,0x7e,0x7e,0xc7,0x04,0xe6,0xe6,0xe6,0xf0,0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,0xeb,
 35.2198 +   0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x00,0x52,0x52,0x52,0xbd,0x82,0x00,0x00,0x00,0xb3,0x02,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,
 35.2199 +   0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x02,0x52,0x52,0x52,0xbd,0xaf,0xaf,0xaf,0xd6,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x01,0xa0,0xa0,0xa0,0xd1,
 35.2200 +   0x6a,0x6a,0x6a,0xc2,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x84,0xaf,0xaf,0xaf,0xd6,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,
 35.2201 +   0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xb9,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
 35.2202 +   0xb7,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0x00,
 35.2203 +   0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x01,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,
 35.2204 +   0x85,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,
 35.2205 +   0xc7,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,
 35.2206 +   0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x87,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,
 35.2207 +   0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x83,0x00,0x00,0x00,0xb3,0x02,0xdc,0xdc,0xdc,0xeb,0xff,0xff,0xff,0xff,0xaf,0xaf,0xaf,0xd6,0x86,
 35.2208 +   0x00,0x00,0x00,0xb3,0x00,0x90,0x90,0x90,0xcc,0x81,0xff,0xff,0xff,0xff,0x09,0xaf,0xaf,0xaf,0xd6,0xe6,0xe6,0xe6,0xf0,0xff,0xff,0xff,0xff,0x90,0x90,0x90,0xcc,0xef,
 35.2209 +   0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0xbb,0xbb,0xbb,0xdc,0xd2,0xd2,0xd2,0xe6,0xff,0xff,0xff,0xff,0xe6,0xe6,0xe6,0xf0,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,
 35.2210 +   0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,0x00,
 35.2211 +   0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x86,0x00,0x00,
 35.2212 +   0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,
 35.2213 +   0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x87,0xff,0xff,0xff,
 35.2214 +   0xff,0x86,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x84,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x02,
 35.2215 +   0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x87,0xff,0xff,0xff,0xff,0x02,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x86,0xff,
 35.2216 +   0xff,0xff,0xff,0x01,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0x00,0x00,0x00,0xb3,0x02,0xaf,0xaf,0xaf,0xd6,
 35.2217 +   0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x00,0xe6,0xe6,0xe6,0xf0,0x83,0xff,0xff,0xff,0xff,0x02,0xef,0xef,0xef,0xf5,0x6a,0x6a,0x6a,0xc2,
 35.2218 +   0x00,0x00,0x00,0xb3,0x87,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,
 35.2219 +   0x7e,0xc7,0x87,0x00,0x00,0x00,0xb3,0x02,0xaf,0xaf,0xaf,0xd6,0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,0xeb,0x83,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,
 35.2220 +   0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x87,0xff,0xff,0xff,0xff,0x02,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,
 35.2221 +   0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x83,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,
 35.2222 +   0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,
 35.2223 +   0xeb,0x87,0xff,0xff,0xff,0xff,0x86,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,
 35.2224 +   0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0x90,0x90,0x90,0xcc,0x84,0xff,0xff,0xff,0xff,0x02,0xbb,0xbb,0xbb,0xdc,0x00,0x00,0x00,0xb3,0xaf,
 35.2225 +   0xaf,0xaf,0xd6,0x87,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x8b,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x84,0x00,0x00,0x00,
 35.2226 +   0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x02,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x87,0xff,0xff,0xff,0xff,0x02,0x00,0x00,
 35.2227 +   0x00,0xb3,0x33,0x33,0x33,0xb8,0xd2,0xd2,0xd2,0xe6,0x85,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,
 35.2228 +   0xff,0x83,0x00,0x00,0x00,0xb3,0x05,0xdc,0xdc,0xdc,0xeb,0xff,0xff,0xff,0xff,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0x52,0x52,0x52,0xbd,0xf7,0xf7,0xf7,0xfa,0x83,
 35.2229 +   0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x33,0x33,0x33,0xb8,0x7e,0x7e,0x7e,0xc7,0x87,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,
 35.2230 +   0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xb9,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
 35.2231 +   0x00,0x00,0xb3,0xb7,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xef,0xef,0xef,
 35.2232 +   0xf5,0x81,0x00,0x00,0x00,0xb3,0x00,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x05,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,
 35.2233 +   0xff,0xf7,0xf7,0xf7,0xfa,0x33,0x33,0x33,0xb8,0x81,0x00,0x00,0x00,0xb3,0x00,0x33,0x33,0x33,0xb8,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,
 35.2234 +   0xdc,0xeb,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,
 35.2235 +   0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0x52,0x52,0x52,0xbd,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,
 35.2236 +   0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x02,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0xef,0xef,0xef,0xf5,0x82,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,
 35.2237 +   0x02,0xd2,0xd2,0xd2,0xe6,0x00,0x00,0x00,0xb3,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x03,0x33,0x33,0x33,
 35.2238 +   0xb8,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xaf,0xaf,0xaf,0xd6,0x86,0x00,0x00,0x00,0xb3,0x00,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x03,0x52,0x52,0x52,
 35.2239 +   0xbd,0xbb,0xbb,0xbb,0xdc,0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x01,0x7e,0x7e,0x7e,0xc7,0xa0,0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,0xff,
 35.2240 +   0x02,0x6a,0x6a,0x6a,0xc2,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,
 35.2241 +   0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x02,0x52,0x52,0x52,0xbd,0x00,0x00,0x00,0xb3,0xa0,0xa0,
 35.2242 +   0xa0,0xd1,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x86,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,
 35.2243 +   0x82,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x02,0x52,0x52,0x52,0xbd,0x00,0x00,0x00,0xb3,0xa0,0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,
 35.2244 +   0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x00,0x90,0x90,0x90,0xcc,0x81,0x7e,0x7e,0x7e,0xc7,0x02,0xe6,0xe6,
 35.2245 +   0xe6,0xf0,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0x86,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x84,0xaf,0xaf,0xaf,0xd6,0x00,0xc7,
 35.2246 +   0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xa0,0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,
 35.2247 +   0x7e,0x7e,0x7e,0xc7,0x00,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x00,0x6a,0x6a,0x6a,0xc2,0x81,0x00,0x00,0x00,0xb3,0x01,0x33,0x33,0x33,0xb8,0x7e,0x7e,0x7e,
 35.2248 +   0xc7,0x81,0xaf,0xaf,0xaf,0xd6,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0xb3,0xa0,0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,
 35.2249 +   0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,0x04,0xdc,0xdc,0xdc,0xeb,0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,
 35.2250 +   0xff,0xff,0x02,0xf7,0xf7,0xf7,0xfa,0xbb,0xbb,0xbb,0xdc,0x90,0x90,0x90,0xcc,0x82,0x00,0x00,0x00,0xb3,0x02,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0xef,0xef,0xef,
 35.2251 +   0xf5,0x82,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xd2,0xd2,0xd2,0xe6,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,
 35.2252 +   0x7e,0x7e,0x7e,0xc7,0x87,0x00,0x00,0x00,0xb3,0x03,0xaf,0xaf,0xaf,0xd6,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0x33,0x33,0x33,0xb8,0x81,0x00,0x00,0x00,0xb3,0x00,
 35.2253 +   0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x02,0xc7,0xc7,0xc7,0xe1,0x00,0x00,0x00,0xb3,0xa0,0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,
 35.2254 +   0x81,0x7e,0x7e,0x7e,0xc7,0x00,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x02,0x6a,0x6a,0x6a,0xc2,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,
 35.2255 +   0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x00,
 35.2256 +   0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x02,0xc7,0xc7,0xc7,0xe1,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0xbb,0xbb,0xbb,0xdc,
 35.2257 +   0x82,0x00,0x00,0x00,0xb3,0x00,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x00,0x90,0x90,0x90,0xcc,0x81,0x7e,0x7e,0x7e,0xc7,0x02,0xe6,0xe6,0xe6,0xf0,0xff,0xff,
 35.2258 +   0xff,0xff,0xf7,0xf7,0xf7,0xfa,0x86,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,
 35.2259 +   0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0xaf,0xaf,0xaf,0xd6,0x52,
 35.2260 +   0x52,0x52,0xbd,0x81,0x00,0x00,0x00,0xb3,0x00,0xa0,0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x7e,0x7e,0x7e,0xc7,0x00,0xc7,0xc7,0xc7,
 35.2261 +   0xe1,0x81,0xff,0xff,0xff,0xff,0x00,0x6a,0x6a,0x6a,0xc2,0x8b,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xef,0xef,0xef,0xf5,0x84,0xaf,0xaf,0xaf,0xd6,0x00,
 35.2262 +   0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x02,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x00,0x90,0x90,0x90,0xcc,
 35.2263 +   0x81,0x7e,0x7e,0x7e,0xc7,0x02,0xe6,0xe6,0xe6,0xf0,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0x82,0x00,0x00,0x00,0xb3,0x01,0x52,0x52,0x52,0xbd,0x90,0x90,0x90,0xcc,
 35.2264 +   0x81,0xaf,0xaf,0xaf,0xd6,0x04,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x00,
 35.2265 +   0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x05,0x33,0x33,0x33,0xb8,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xaf,0xaf,
 35.2266 +   0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x02,0xef,0xef,0xef,0xf5,0xaf,0xaf,0xaf,0xd6,0x6a,0x6a,0x6a,0xc2,0x81,0x00,0x00,0x00,0xb3,0x00,0x52,0x52,0x52,0xbd,0x81,0xff,
 35.2267 +   0xff,0xff,0xff,0x00,0xd2,0xd2,0xd2,0xe6,0x81,0x7e,0x7e,0x7e,0xc7,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,
 35.2268 +   0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xb9,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
 35.2269 +   0x00,0x00,0x00,0xb3,0xb7,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x82,0xff,0xff,0xff,0xff,0x01,0xd2,0xd2,
 35.2270 +   0xd2,0xe6,0xbb,0xbb,0xbb,0xdc,0x82,0xff,0xff,0xff,0xff,0x02,0x52,0x52,0x52,0xbd,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x05,0xef,0xef,
 35.2271 +   0xef,0xf5,0xaf,0xaf,0xaf,0xd6,0xc7,0xc7,0xc7,0xe1,0xe6,0xe6,0xe6,0xf0,0x33,0x33,0x33,0xb8,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,
 35.2272 +   0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,
 35.2273 +   0xeb,0x81,0x00,0x00,0x00,0xb3,0x00,0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0xaf,0xaf,0xaf,0xd6,0xc7,0xc7,0xc7,0xe1,0x82,0xff,0xff,
 35.2274 +   0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x02,0xa0,0xa0,0xa0,0xd1,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,
 35.2275 +   0xff,0xff,0xff,0x02,0xa0,0xa0,0xa0,0xd1,0x00,0x00,0x00,0xb3,0x90,0x90,0x90,0xcc,0x81,0xff,0xff,0xff,0xff,0x03,0xf7,0xf7,0xf7,0xfa,0xbb,0xbb,0xbb,0xdc,0xaf,0xaf,
 35.2276 +   0xaf,0xd6,0xef,0xef,0xef,0xf5,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x85,0x00,0x00,0x00,0xb3,0x00,0x33,0x33,0x33,0xb8,0x81,0xff,0xff,0xff,0xff,0x02,
 35.2277 +   0xe6,0xe6,0xe6,0xf0,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x02,0xf7,0xf7,0xf7,0xfa,0x00,0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,0x81,0xff,
 35.2278 +   0xff,0xff,0xff,0x02,0xbb,0xbb,0xbb,0xdc,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x02,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0xc7,0xc7,
 35.2279 +   0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xaf,0xaf,0xaf,0xd6,0x01,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x02,
 35.2280 +   0xe6,0xe6,0xe6,0xf0,0xaf,0xaf,0xaf,0xd6,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x00,0xa0,0xa0,0xa0,0xd1,0x84,0x00,0x00,0x00,0xb3,0x02,0x52,0x52,0x52,0xbd,
 35.2281 +   0xaf,0xaf,0xaf,0xd6,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x04,0xc7,0xc7,0xc7,0xe1,0xaf,0xaf,0xaf,0xd6,0xa0,0xa0,0xa0,0xd1,0x00,0x00,0x00,0xb3,0xdc,0xdc,
 35.2282 +   0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x02,0xe6,0xe6,0xe6,0xf0,0xaf,0xaf,0xaf,0xd6,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x02,0xa0,0xa0,0xa0,0xd1,0x00,0x00,
 35.2283 +   0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x02,0xc7,0xc7,0xc7,0xe1,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xc7,0xc7,
 35.2284 +   0xc7,0xe1,0x86,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x89,0xff,0xff,0xff,0xff,0x0a,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,0xf7,0xf7,
 35.2285 +   0xf7,0xfa,0xff,0xff,0xff,0xff,0xe6,0xe6,0xe6,0xf0,0x33,0x33,0x33,0xb8,0x52,0x52,0x52,0xbd,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0xef,0xef,0xef,0xf5,0x82,0x00,
 35.2286 +   0x00,0x00,0xb3,0x08,0xaf,0xaf,0xaf,0xd6,0x52,0x52,0x52,0xbd,0x00,0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,0xdc,0xdc,0xdc,0xeb,0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,0xeb,
 35.2287 +   0x00,0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,0x82,0xff,0xff,0xff,0xff,0x02,0xc7,0xc7,0xc7,0xe1,0xaf,0xaf,0xaf,0xd6,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x02,
 35.2288 +   0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x03,0xc7,0xc7,0xc7,0xe1,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0xa0,0xa0,
 35.2289 +   0xa0,0xd1,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x02,0xa0,0xa0,0xa0,0xd1,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,
 35.2290 +   0xff,0xff,0xff,0x03,0xa0,0xa0,0xa0,0xd1,0x52,0x52,0x52,0xbd,0xaf,0xaf,0xaf,0xd6,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x02,0xc7,0xc7,0xc7,0xe1,0xaf,0xaf,
 35.2291 +   0xaf,0xd6,0xa0,0xa0,0xa0,0xd1,0x85,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x03,0xef,0xef,0xef,0xf5,0xaf,0xaf,0xaf,0xd6,0xbb,0xbb,
 35.2292 +   0xbb,0xdc,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x0d,0xa0,0xa0,0xa0,0xd1,0x00,0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,
 35.2293 +   0xe6,0xe6,0xe6,0xf0,0x33,0x33,0x33,0xb8,0x52,0x52,0x52,0xbd,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0xef,0xef,0xef,0xf5,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,
 35.2294 +   0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x01,0xdc,0xdc,0xdc,0xeb,0xaf,0xaf,0xaf,0xd6,0x81,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xf7,0xf7,0xf7,
 35.2295 +   0xfa,0x81,0xbb,0xbb,0xbb,0xdc,0x00,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x02,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x82,0xff,0xff,
 35.2296 +   0xff,0xff,0x03,0xc7,0xc7,0xc7,0xe1,0xaf,0xaf,0xaf,0xd6,0xa0,0xa0,0xa0,0xd1,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x02,0xc7,0xc7,0xc7,0xe1,0x00,0x00,0x00,
 35.2297 +   0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xc7,0xc7,0xc7,0xe1,0x86,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,
 35.2298 +   0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x0d,
 35.2299 +   0x52,0x52,0x52,0xbd,0x33,0x33,0x33,0xb8,0xaf,0xaf,0xaf,0xd6,0x33,0x33,0x33,0xb8,0x00,0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,
 35.2300 +   0xe6,0xe6,0xe6,0xf0,0x33,0x33,0x33,0xb8,0x52,0x52,0x52,0xbd,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0xef,0xef,0xef,0xf5,0x8c,0x00,0x00,0x00,0xb3,0x8a,0xff,0xff,
 35.2301 +   0xff,0xff,0x02,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x02,0xc7,0xc7,0xc7,0xe1,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,
 35.2302 +   0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xc7,0xc7,0xc7,0xe1,0x81,0x00,0x00,0x00,0xb3,0x09,0x33,0x33,0x33,0xb8,0xaf,0xaf,0xaf,0xd6,0x33,0x33,0x33,0xb8,0x00,0x00,0x00,
 35.2303 +   0xb3,0x52,0x52,0x52,0xbd,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0x90,0x90,0x90,0xcc,0x81,0xff,0xff,0xff,0xff,0x03,0xf7,
 35.2304 +   0xf7,0xf7,0xfa,0xbb,0xbb,0xbb,0xdc,0xaf,0xaf,0xaf,0xd6,0xef,0xef,0xef,0xf5,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,
 35.2305 +   0xd6,0x81,0xff,0xff,0xff,0xff,0x03,0xa0,0xa0,0xa0,0xd1,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x6a,0x6a,0x6a,0xc2,0x81,0x00,0x00,0x00,0xb3,0x05,0xdc,0xdc,0xdc,
 35.2306 +   0xeb,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0x6a,0x6a,0x6a,0xc2,0x33,0x33,0x33,0xb8,0xd2,0xd2,0xd2,0xe6,0x81,0xff,0xff,0xff,0xff,0x03,0x52,0x52,0x52,0xbd,0x7e,
 35.2307 +   0x7e,0x7e,0xc7,0xaf,0xaf,0xaf,0xd6,0xef,0xef,0xef,0xf5,0x81,0xff,0xff,0xff,0xff,0x81,0xaf,0xaf,0xaf,0xd6,0x00,0x7e,0x7e,0x7e,0xc7,0xff,0x00,0x00,0x00,0xb3,0xff,
 35.2308 +   0x00,0x00,0x00,0xb3,0xb6,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xb7,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,
 35.2309 +   0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xf7,0xf7,0xf7,0xfa,0x83,0xff,0xff,0xff,0xff,0x00,0xef,0xef,0xef,0xf5,0x82,0x00,0x00,0x00,0xb3,
 35.2310 +   0x00,0xe6,0xe6,0xe6,0xf0,0x84,0xff,0xff,0xff,0xff,0x01,0xe6,0xe6,0xe6,0xf0,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,
 35.2311 +   0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0x00,
 35.2312 +   0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x87,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x01,0x33,0x33,0x33,0xb8,0xe6,0xe6,0xe6,0xf0,0x84,0xff,0xff,0xff,0xff,
 35.2313 +   0x00,0xe6,0xe6,0xe6,0xf0,0x82,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x86,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x85,0x00,0x00,0x00,0xb3,0x00,0xa0,
 35.2314 +   0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x82,0xff,0xff,0xff,0xff,0x00,0xd2,0xd2,0xd2,0xe6,0x81,0x00,0x00,0x00,
 35.2315 +   0xb3,0x04,0xe6,0xe6,0xe6,0xf0,0xff,0xff,0xff,0xff,0xef,0xef,0xef,0xf5,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0xb3,
 35.2316 +   0x86,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x00,0xf7,0xf7,0xf7,0xfa,0x83,0xff,0xff,0xff,0xff,0x00,0x52,0x52,
 35.2317 +   0x52,0xbd,0x84,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x85,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,
 35.2318 +   0xff,0xff,0xff,0x00,0xf7,0xf7,0xf7,0xfa,0x83,0xff,0xff,0xff,0xff,0x00,0x52,0x52,0x52,0xbd,0x81,0x00,0x00,0x00,0xb3,0x00,0xc7,0xc7,0xc7,0xe1,0x84,0xff,0xff,0xff,
 35.2319 +   0xff,0x01,0xf7,0xf7,0xf7,0xfa,0x52,0x52,0x52,0xbd,0x86,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x89,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,
 35.2320 +   0x00,0x00,0xb3,0x00,0xa0,0xa0,0xa0,0xd1,0x85,0xff,0xff,0xff,0xff,0x00,0x90,0x90,0x90,0xcc,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,
 35.2321 +   0xff,0x01,0xdc,0xdc,0xdc,0xeb,0xef,0xef,0xef,0xf5,0x81,0xff,0xff,0xff,0xff,0x00,0xa0,0xa0,0xa0,0xd1,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x86,0xff,
 35.2322 +   0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x00,0xe6,0xe6,0xe6,0xf0,0x84,0xff,0xff,0xff,0xff,0x03,0xa0,0xa0,0xa0,0xd1,0x00,0x00,0x00,0xb3,
 35.2323 +   0x33,0x33,0x33,0xb8,0xe6,0xe6,0xe6,0xf0,0x84,0xff,0xff,0xff,0xff,0x02,0xe6,0xe6,0xe6,0xf0,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x85,0xff,0xff,0xff,0xff,0x00,
 35.2324 +   0xdc,0xdc,0xdc,0xeb,0x85,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x86,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0x00,0x00,0x00,0xb3,0x00,0xa0,0xa0,
 35.2325 +   0xa0,0xd1,0x85,0xff,0xff,0xff,0xff,0x01,0x90,0x90,0x90,0xcc,0x00,0x00,0x00,0xb3,0x85,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xc7,0xc7,
 35.2326 +   0xc7,0xe1,0x85,0xff,0xff,0xff,0xff,0x00,0xc7,0xc7,0xc7,0xe1,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0xe6,0xe6,0xe6,0xf0,
 35.2327 +   0x81,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0xc7,0xc7,0xc7,0xe1,0x84,0xff,0xff,0xff,0xff,0x01,0xf7,0xf7,0xf7,0xfa,0x52,0x52,0x52,0xbd,
 35.2328 +   0x86,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,
 35.2329 +   0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0x90,0x90,0x90,0xcc,0x84,0xff,0xff,0xff,0xff,0x03,0xe6,0xe6,0xe6,0xf0,0x33,0x33,0x33,0xb8,0x00,0x00,0x00,0xb3,0xa0,0xa0,0xa0,
 35.2330 +   0xd1,0x85,0xff,0xff,0xff,0xff,0x00,0x90,0x90,0x90,0xcc,0x8c,0x00,0x00,0x00,0xb3,0x8a,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x00,
 35.2331 +   0xc7,0xc7,0xc7,0xe1,0x84,0xff,0xff,0xff,0xff,0x01,0xf7,0xf7,0xf7,0xfa,0x52,0x52,0x52,0xbd,0x81,0x00,0x00,0x00,0xb3,0x04,0xdc,0xdc,0xdc,0xeb,0xff,0xff,0xff,0xff,
 35.2332 +   0xf7,0xf7,0xf7,0xfa,0xdc,0xdc,0xdc,0xeb,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x00,0x52,0x52,0x52,0xbd,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,
 35.2333 +   0x86,0xff,0xff,0xff,0xff,0x03,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0x52,0x52,0x52,0xbd,0xf7,0xf7,0xf7,0xfa,0x83,0xff,0xff,0xff,0xff,0x04,0xf7,0xf7,0xf7,0xfa,
 35.2334 +   0x6a,0x6a,0x6a,0xc2,0x00,0x00,0x00,0xb3,0x6a,0x6a,0x6a,0xc2,0xf7,0xf7,0xf7,0xfa,0x84,0xff,0xff,0xff,0xff,0x02,0xbb,0xbb,0xbb,0xdc,0x00,0x00,0x00,0xb3,0xaf,0xaf,
 35.2335 +   0xaf,0xd6,0x85,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xb6,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
 35.2336 +   0xff,0x00,0x00,0x00,0xb3,0xb7,0x00,0x00,0x00,0xb3,0x00,0xbb,0xbb,0xbb,0xdc,0x81,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x81,0xdc,0xdc,0xdc,0xeb,0x05,0xbb,
 35.2337 +   0xbb,0xbb,0xdc,0xa0,0xa0,0xa0,0xd1,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,0xeb,0x6a,0x6a,0x6a,0xc2,0x83,0x00,0x00,0x00,0xb3,0x01,0xaf,0xaf,0xaf,
 35.2338 +   0xd6,0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,0x02,0xd2,0xd2,0xd2,0xe6,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,
 35.2339 +   0xeb,0x00,0x00,0x00,0xb3,0xa0,0xa0,0xa0,0xd1,0x81,0xdc,0xdc,0xdc,0xeb,0x00,0x6a,0x6a,0x6a,0xc2,0x81,0x00,0x00,0x00,0xb3,0x81,0xdc,0xdc,0xdc,0xeb,0x00,0xbb,0xbb,
 35.2340 +   0xbb,0xdc,0x82,0x00,0x00,0x00,0xb3,0x05,0x90,0x90,0x90,0xcc,0xe6,0xe6,0xe6,0xf0,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0xaf,0xaf,0xaf,0xd6,0xdc,0xdc,0xdc,0xeb,
 35.2341 +   0x81,0xff,0xff,0xff,0xff,0x82,0x00,0x00,0x00,0xb3,0x06,0x33,0x33,0x33,0xb8,0xaf,0xaf,0xaf,0xd6,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0xc7,
 35.2342 +   0xc7,0xc7,0xe1,0x33,0x33,0x33,0xb8,0x82,0x00,0x00,0x00,0xb3,0x05,0x33,0x33,0x33,0xb8,0xc7,0xc7,0xc7,0xe1,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,
 35.2343 +   0xeb,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x85,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xdc,0xdc,0xdc,0xeb,0x00,0x52,
 35.2344 +   0x52,0x52,0xbd,0x81,0x00,0x00,0x00,0xb3,0x00,0xbb,0xbb,0xbb,0xdc,0x81,0xdc,0xdc,0xdc,0xeb,0x00,0x90,0x90,0x90,0xcc,0x81,0x00,0x00,0x00,0xb3,0x00,0xa0,0xa0,0xa0,
 35.2345 +   0xd1,0x81,0xdc,0xdc,0xdc,0xeb,0x01,0x52,0x52,0x52,0xbd,0xbb,0xbb,0xbb,0xdc,0x81,0xdc,0xdc,0xdc,0xeb,0x02,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0xe6,0xe6,0xe6,
 35.2346 +   0xf0,0x81,0xff,0xff,0xff,0xff,0x00,0xef,0xef,0xef,0xf5,0x81,0xdc,0xdc,0xdc,0xeb,0x01,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x04,0x90,
 35.2347 +   0x90,0x90,0xcc,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0xef,0xef,0xef,0xf5,0x90,0x90,0x90,0xcc,0x85,0x00,0x00,0x00,0xb3,0x02,0x6a,0x6a,0x6a,0xc2,0xdc,0xdc,0xdc,
 35.2348 +   0xeb,0xef,0xef,0xef,0xf5,0x81,0xff,0xff,0xff,0xff,0x04,0xe6,0xe6,0xe6,0xf0,0xdc,0xdc,0xdc,0xeb,0xbb,0xbb,0xbb,0xdc,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,
 35.2349 +   0xff,0xff,0xff,0xff,0x04,0x90,0x90,0x90,0xcc,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0xef,0xef,0xef,0xf5,0x90,0x90,0x90,0xcc,0x83,0x00,0x00,0x00,0xb3,0x01,0xa0,
 35.2350 +   0xa0,0xa0,0xd1,0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,0x01,0xd2,0xd2,0xd2,0xe6,0x6a,0x6a,0x6a,0xc2,0x87,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,
 35.2351 +   0xff,0xff,0xff,0xff,0x84,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,0x01,0x7e,0x7e,
 35.2352 +   0x7e,0xc7,0xd2,0xd2,0xd2,0xe6,0x81,0xff,0xff,0xff,0xff,0x01,0xe6,0xe6,0xe6,0xf0,0x90,0x90,0x90,0xcc,0x82,0x00,0x00,0x00,0xb3,0x02,0x33,0x33,0x33,0xb8,0xaf,0xaf,
 35.2353 +   0xaf,0xd6,0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,0x01,0xe6,0xe6,0xe6,0xf0,0xaf,0xaf,0xaf,0xd6,0x83,0x00,0x00,0x00,0xb3,0x04,0xaf,0xaf,0xaf,0xd6,0xef,0xef,
 35.2354 +   0xef,0xf5,0xff,0xff,0xff,0xff,0xef,0xef,0xef,0xf5,0x90,0x90,0x90,0xcc,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x06,0x33,0x33,
 35.2355 +   0x33,0xb8,0xc7,0xc7,0xc7,0xe1,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0xc7,0xc7,0xc7,0xe1,0x52,0x52,0x52,0xbd,0x81,0x00,0x00,0x00,0xb3,0x0a,
 35.2356 +   0x33,0x33,0x33,0xb8,0xaf,0xaf,0xaf,0xd6,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0xc7,0xc7,0xc7,0xe1,0x33,0x33,0x33,0xb8,0x00,0x00,0x00,0xb3,
 35.2357 +   0x6a,0x6a,0x6a,0xc2,0xdc,0xdc,0xdc,0xeb,0xef,0xef,0xef,0xf5,0x81,0xff,0xff,0xff,0xff,0x02,0xe6,0xe6,0xe6,0xf0,0xdc,0xdc,0xdc,0xeb,0xbb,0xbb,0xbb,0xdc,0x85,0x00,
 35.2358 +   0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x05,0xaf,0xaf,0xaf,0xd6,0xdc,0xdc,0xdc,0xeb,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0xc7,0xc7,
 35.2359 +   0xc7,0xe1,0x33,0x33,0x33,0xb8,0x83,0x00,0x00,0x00,0xb3,0x01,0x7e,0x7e,0x7e,0xc7,0xd2,0xd2,0xd2,0xe6,0x81,0xff,0xff,0xff,0xff,0x01,0xe6,0xe6,0xe6,0xf0,0x90,0x90,
 35.2360 +   0x90,0xcc,0x81,0x00,0x00,0x00,0xb3,0x01,0xdc,0xdc,0xdc,0xeb,0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,0x02,0xef,0xef,0xef,0xf5,0xdc,0xdc,0xdc,0xeb,0xa0,0xa0,
 35.2361 +   0xa0,0xd1,0x81,0x00,0x00,0x00,0xb3,0x01,0xa0,0xa0,0xa0,0xd1,0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,0x01,0xe6,0xe6,0xe6,0xf0,0xa0,0xa0,0xa0,0xd1,0x82,0x00,
 35.2362 +   0x00,0x00,0xb3,0x00,0xa0,0xa0,0xa0,0xd1,0x81,0xdc,0xdc,0xdc,0xeb,0x03,0x7e,0x7e,0x7e,0xc7,0xc7,0xc7,0xc7,0xe1,0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,0xeb,0x81,0x00,
 35.2363 +   0x00,0x00,0xb3,0x01,0xa0,0xa0,0xa0,0xd1,0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,0x01,0xd2,0xd2,0xd2,0xe6,0x6a,0x6a,0x6a,0xc2,0x87,0x00,0x00,0x00,0xb3,0x00,
 35.2364 +   0xbb,0xbb,0xbb,0xdc,0x81,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x00,0x6a,0x6a,0x6a,0xc2,0x81,0xdc,0xdc,0xdc,0xeb,0x00,0xa0,0xa0,0xa0,0xd1,0x81,0x00,0x00,
 35.2365 +   0x00,0xb3,0x01,0x90,0x90,0x90,0xcc,0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,0x01,0xe6,0xe6,0xe6,0xf0,0xa0,0xa0,0xa0,0xd1,0x82,0x00,0x00,0x00,0xb3,0x01,0x7e,
 35.2366 +   0x7e,0x7e,0xc7,0xd2,0xd2,0xd2,0xe6,0x81,0xff,0xff,0xff,0xff,0x01,0xe6,0xe6,0xe6,0xf0,0x90,0x90,0x90,0xcc,0x8d,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,
 35.2367 +   0xdc,0xdc,0xdc,0xeb,0x84,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0x00,0x00,0x00,0xb3,0x01,0xa0,0xa0,
 35.2368 +   0xa0,0xd1,0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,0x01,0xd2,0xd2,0xd2,0xe6,0x6a,0x6a,0x6a,0xc2,0x82,0x00,0x00,0x00,0xb3,0x02,0x52,0x52,0x52,0xbd,0xc7,0xc7,
 35.2369 +   0xc7,0xe1,0xef,0xef,0xef,0xf5,0x81,0xff,0xff,0xff,0xff,0x01,0xdc,0xdc,0xdc,0xeb,0x7e,0x7e,0x7e,0xc7,0x82,0x00,0x00,0x00,0xb3,0x05,0x33,0x33,0x33,0xb8,0xc7,0xc7,
 35.2370 +   0xc7,0xe1,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,0xeb,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,
 35.2371 +   0xb3,0x01,0x6a,0x6a,0x6a,0xc2,0xd2,0xd2,0xd2,0xe6,0x81,0xff,0xff,0xff,0xff,0x02,0xef,0xef,0xef,0xf5,0xaf,0xaf,0xaf,0xd6,0x33,0x33,0x33,0xb8,0x81,0x00,0x00,0x00,
 35.2372 +   0xb3,0x05,0x52,0x52,0x52,0xbd,0xc7,0xc7,0xc7,0xe1,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xef,0xef,0xef,0xf5,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x02,
 35.2373 +   0xa0,0xa0,0xa0,0xd1,0xdc,0xdc,0xdc,0xeb,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x81,0xdc,0xdc,0xdc,0xeb,0x00,0xa0,0xa0,0xa0,0xd1,0xff,0x00,0x00,0x00,0xb3,
 35.2374 +   0xff,0x00,0x00,0x00,0xb3,0xb6,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xb8,0x00,0x00,0x00,0xb3,0x01,0x7e,0x7e,0x7e,0xc7,0x33,0x33,
 35.2375 +   0x33,0xb8,0x94,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x91,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,
 35.2376 +   0x91,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x96,0x00,0x00,0x00,0xb3,0x01,0x7e,0x7e,0x7e,0xc7,0x33,0x33,
 35.2377 +   0x33,0xb8,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,
 35.2378 +   0x81,0xff,0xff,0xff,0xff,0x8c,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0x00,0x00,0x00,0xb3,0x00,0xdc,
 35.2379 +   0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x96,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x84,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,
 35.2380 +   0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x9b,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x94,0x00,0x00,0x00,0xb3,0x00,
 35.2381 +   0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x87,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,
 35.2382 +   0x7e,0xc7,0x91,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0xcb,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,
 35.2383 +   0x00,0xdc,0xdc,0xdc,0xeb,0x84,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x9a,0x00,0x00,0x00,0xb3,0x00,0x7e,
 35.2384 +   0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x94,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,
 35.2385 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xb9,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xb7,0x00,0x00,0x00,0xb3,0x03,0xdc,0xdc,0xdc,0xeb,0xff,
 35.2386 +   0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0x33,0x33,0x33,0xb8,0x93,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x91,0x00,0x00,0x00,0xb3,0x00,
 35.2387 +   0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x91,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x95,0x00,0x00,
 35.2388 +   0x00,0xb3,0x05,0xdc,0xdc,0xdc,0xeb,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0x33,0x33,0x33,0xb8,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,
 35.2389 +   0x00,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x8c,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,
 35.2390 +   0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x96,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,
 35.2391 +   0xeb,0x81,0xff,0xff,0xff,0xff,0x84,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x9b,0x00,0x00,0x00,0xb3,0x81,
 35.2392 +   0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x94,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x87,0x00,0x00,
 35.2393 +   0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x91,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,
 35.2394 +   0x00,0xaf,0xaf,0xaf,0xd6,0xcb,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x84,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,
 35.2395 +   0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x9a,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x94,0x00,0x00,0x00,
 35.2396 +   0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xb9,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
 35.2397 +   0x00,0x00,0x00,0xb3,0xb7,0x00,0x00,0x00,0xb3,0x82,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x93,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,
 35.2398 +   0xdc,0xeb,0x91,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x91,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,
 35.2399 +   0x00,0xaf,0xaf,0xaf,0xd6,0x95,0x00,0x00,0x00,0xb3,0x82,0xff,0xff,0xff,0xff,0x02,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,0x81,0x7e,0x7e,0x7e,
 35.2400 +   0xc7,0x00,0x52,0x52,0x52,0xbd,0x82,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x8c,0x00,0x00,0x00,0xb3,0x00,0x52,0x52,0x52,0xbd,0x81,
 35.2401 +   0x7e,0x7e,0x7e,0xc7,0x00,0x33,0x33,0x33,0xb8,0x82,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x96,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,
 35.2402 +   0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x84,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x9b,0x00,0x00,0x00,0xb3,
 35.2403 +   0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x94,0x00,0x00,0x00,0xb3,0x00,0x52,0x52,0x52,0xbd,0x81,0x7e,0x7e,0x7e,0xc7,0x00,0x33,0x33,0x33,0xb8,0x87,0x00,
 35.2404 +   0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x91,0x00,0x00,0x00,0xb3,0x00,0x52,0x52,0x52,0xbd,0x81,0xff,0xff,0xff,
 35.2405 +   0xff,0x00,0xf7,0xf7,0xf7,0xfa,0x81,0xaf,0xaf,0xaf,0xd6,0xc9,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x84,0x00,0x00,0x00,0xb3,0x00,
 35.2406 +   0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x9a,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,
 35.2407 +   0xaf,0xd6,0x94,0x00,0x00,0x00,0xb3,0x00,0x6a,0x6a,0x6a,0xc2,0x81,0x7e,0x7e,0x7e,0xc7,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xb9,0x00,0x00,0x00,0xb3,
 35.2408 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xb7,0x00,0x00,0x00,0xb3,0x02,0xaf,0xaf,0xaf,0xd6,0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,0xeb,0x94,0x00,0x00,0x00,
 35.2409 +   0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x91,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x91,0x00,0x00,0x00,0xb3,0x00,
 35.2410 +   0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x95,0x00,0x00,0x00,0xb3,0x02,0xaf,0xaf,0xaf,0xd6,0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,0xeb,
 35.2411 +   0x88,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x93,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x96,0x00,
 35.2412 +   0x00,0x00,0xb3,0x00,0xbb,0xbb,0xbb,0xdc,0x81,0xdc,0xdc,0xdc,0xeb,0x84,0x00,0x00,0x00,0xb3,0x00,0x6a,0x6a,0x6a,0xc2,0x81,0xdc,0xdc,0xdc,0xeb,0x00,0xa0,0xa0,0xa0,
 35.2413 +   0xd1,0x9b,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0xa0,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,
 35.2414 +   0x7e,0x7e,0x7e,0xc7,0x92,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0xc9,0x00,0x00,0x00,0xb3,0x81,0xdc,0xdc,
 35.2415 +   0xdc,0xeb,0x00,0xbb,0xbb,0xbb,0xdc,0x84,0x00,0x00,0x00,0xb3,0x00,0xa0,0xa0,0xa0,0xd1,0x81,0xdc,0xdc,0xdc,0xeb,0x00,0x6a,0x6a,0x6a,0xc2,0x9a,0x00,0x00,0x00,0xb3,
 35.2416 +   0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xd1,0x00,0x00,0x00,0xb3,0xff,0x00,
 35.2417 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xcf,0x00,0x00,0x00,0xb3,0x81,0xaf,0xaf,0xaf,0xd6,0x00,0xa0,0xa0,0xa0,0xd1,0x91,0x00,0x00,0x00,0xb3,0x00,0xa0,0xa0,0xa0,
 35.2418 +   0xd1,0x81,0xaf,0xaf,0xaf,0xd6,0x91,0x00,0x00,0x00,0xb3,0x00,0x52,0x52,0x52,0xbd,0x81,0xaf,0xaf,0xaf,0xd6,0x00,0x7e,0x7e,0x7e,0xc7,0xa1,0x00,0x00,0x00,0xb3,0x00,
 35.2419 +   0xa0,0xa0,0xa0,0xd1,0x81,0xaf,0xaf,0xaf,0xd6,0x93,0x00,0x00,0x00,0xb3,0x00,0xa0,0xa0,0xa0,0xd1,0x81,0xaf,0xaf,0xaf,0xd6,0xbe,0x00,0x00,0x00,0xb3,0x81,0xaf,0xaf,
 35.2420 +   0xaf,0xd6,0x00,0xa0,0xa0,0xa0,0xd1,0xa0,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xaf,0xaf,0xaf,0xd6,0x00,0x52,0x52,0x52,0xbd,0x92,0x00,0x00,0x00,0xb3,
 35.2421 +   0x01,0x33,0x33,0x33,0xb8,0xaf,0xaf,0xaf,0xd6,0x81,0xdc,0xdc,0xdc,0xeb,0x00,0xbb,0xbb,0xbb,0xdc,0xf0,0x00,0x00,0x00,0xb3,0x00,0x52,0x52,0x52,0xbd,0x81,0xaf,0xaf,
 35.2422 +   0xaf,0xd6,0x00,0x7e,0x7e,0x7e,0xc7,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xd1,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
 35.2423 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
 35.2424 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
 35.2425 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
 35.2426 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
 35.2427 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
 35.2428 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
 35.2429 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
 35.2430 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
 35.2431 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
 35.2432 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
 35.2433 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
 35.2434 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xa3,0x00,0x00,0x00,0xb3,0x82,0x7e,0x7e,0x7e,0xc7,0xff,0x00,0x00,0x00,
 35.2435 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xd8,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
 35.2436 +   0x00,0x00,0x00,0xb3,0xa0,0x00,0x00,0x00,0xb3,0x01,0x52,0x52,0x52,0xbd,0xd2,0xd2,0xd2,0xe6,0x84,0xff,0xff,0xff,0xff,0x00,0xbb,0xbb,0xbb,0xdc,0xff,0x00,0x00,0x00,
 35.2437 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xd6,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
 35.2438 +   0x00,0x00,0x00,0xb3,0xa0,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x86,0xff,0xff,0xff,0xff,0x00,0xc7,0xc7,0xc7,0xe1,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
 35.2439 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xd5,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
 35.2440 +   0xa1,0x00,0x00,0x00,0xb3,0x05,0xef,0xef,0xef,0xf5,0xe6,0xe6,0xe6,0xf0,0xa0,0xa0,0xa0,0xd1,0x7e,0x7e,0x7e,0xc7,0xa0,0xa0,0xa0,0xd1,0xf7,0xf7,0xf7,0xfa,0x81,0xff,
 35.2441 +   0xff,0xff,0xff,0x00,0x52,0x52,0x52,0xbd,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xd4,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
 35.2442 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xce,0x00,0x00,0x00,0xb3,0x02,0x52,0x52,0x52,0xbd,0x7e,0x7e,0x7e,0xc7,0x6a,0x6a,0x6a,0xc2,0x85,0x00,0x00,0x00,0xb3,0x02,0x6a,0x6a,
 35.2443 +   0x6a,0xc2,0x7e,0x7e,0x7e,0xc7,0x33,0x33,0x33,0xb8,0x86,0x00,0x00,0x00,0xb3,0x02,0x33,0x33,0x33,0xb8,0x7e,0x7e,0x7e,0xc7,0x6a,0x6a,0x6a,0xc2,0x8c,0x00,0x00,0x00,
 35.2444 +   0xb3,0x02,0x52,0x52,0x52,0xbd,0x7e,0x7e,0x7e,0xc7,0x52,0x52,0x52,0xbd,0x91,0x00,0x00,0x00,0xb3,0x02,0x52,0x52,0x52,0xbd,0x7e,0x7e,0x7e,0xc7,0x52,0x52,0x52,0xbd,
 35.2445 +   0x94,0x00,0x00,0x00,0xb3,0x02,0x6a,0x6a,0x6a,0xc2,0x7e,0x7e,0x7e,0xc7,0x6a,0x6a,0x6a,0xc2,0x90,0x00,0x00,0x00,0xb3,0x00,0x52,0x52,0x52,0xbd,0x81,0x7e,0x7e,0x7e,
 35.2446 +   0xc7,0x9a,0x00,0x00,0x00,0xb3,0x02,0x6a,0x6a,0x6a,0xc2,0x7e,0x7e,0x7e,0xc7,0x33,0x33,0x33,0xb8,0xa3,0x00,0x00,0x00,0xb3,0x02,0x52,0x52,0x52,0xbd,0x7e,0x7e,0x7e,
 35.2447 +   0xc7,0x52,0x52,0x52,0xbd,0xa6,0x00,0x00,0x00,0xb3,0x00,0x6a,0x6a,0x6a,0xc2,0x83,0x00,0x00,0x00,0xb3,0x00,0xa0,0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,
 35.2448 +   0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,0x81,0x7e,0x7e,0x7e,0xc7,0x00,0x6a,0x6a,0x6a,0xc2,0x8a,0x00,0x00,0x00,0xb3,0x02,0x6a,0x6a,0x6a,0xc2,0x7e,0x7e,0x7e,0xc7,
 35.2449 +   0x33,0x33,0x33,0xb8,0x91,0x00,0x00,0x00,0xb3,0x02,0x6a,0x6a,0x6a,0xc2,0x7e,0x7e,0x7e,0xc7,0x33,0x33,0x33,0xb8,0x9a,0x00,0x00,0x00,0xb3,0x00,0x6a,0x6a,0x6a,0xc2,
 35.2450 +   0x81,0x7e,0x7e,0x7e,0xc7,0x86,0x00,0x00,0x00,0xb3,0x81,0x7e,0x7e,0x7e,0xc7,0x00,0x52,0x52,0x52,0xbd,0x8a,0x00,0x00,0x00,0xb3,0x81,0x7e,0x7e,0x7e,0xc7,0x88,0x00,
 35.2451 +   0x00,0x00,0xb3,0x00,0x33,0x33,0x33,0xb8,0x81,0x7e,0x7e,0x7e,0xc7,0x84,0x00,0x00,0x00,0xb3,0x00,0x33,0x33,0x33,0xb8,0x81,0x7e,0x7e,0x7e,0xc7,0x00,0x33,0x33,0x33,
 35.2452 +   0xb8,0x88,0x00,0x00,0x00,0xb3,0x02,0x6a,0x6a,0x6a,0xc2,0x7e,0x7e,0x7e,0xc7,0x6a,0x6a,0x6a,0xc2,0x8f,0x00,0x00,0x00,0xb3,0x00,0x52,0x52,0x52,0xbd,0x81,0x7e,0x7e,
 35.2453 +   0x7e,0xc7,0x00,0x33,0x33,0x33,0xb8,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xc1,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
 35.2454 +   0xbf,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,
 35.2455 +   0xff,0xff,0xff,0x00,0xc7,0xc7,0xc7,0xe1,0x81,0x00,0x00,0x00,0xb3,0x01,0x7e,0x7e,0x7e,0xc7,0xe6,0xe6,0xe6,0xf0,0x82,0xff,0xff,0xff,0xff,0x01,0xef,0xef,0xef,0xf5,
 35.2456 +   0x90,0x90,0x90,0xcc,0x81,0x00,0x00,0x00,0xb3,0x01,0x6a,0x6a,0x6a,0xc2,0xef,0xef,0xef,0xf5,0x82,0xff,0xff,0xff,0xff,0x00,0xbb,0xbb,0xbb,0xdc,0x81,0xff,0xff,0xff,
 35.2457 +   0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0xff,0xff,0xff,0xff,0x01,0xdc,0xdc,0xdc,0xeb,0xbb,0xbb,0xbb,0xdc,0x81,0xff,
 35.2458 +   0xff,0xff,0xff,0x86,0x00,0x00,0x00,0xb3,0x01,0x33,0x33,0x33,0xb8,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x05,0xdc,0xdc,0xdc,0xeb,0xe6,0xe6,0xe6,0xf0,0xff,
 35.2459 +   0xff,0xff,0xff,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,
 35.2460 +   0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x01,0x33,0x33,0x33,0xb8,0xd2,0xd2,0xd2,0xe6,0x82,0xff,0xff,0xff,0xff,0x03,0xbb,0xbb,0xbb,0xdc,
 35.2461 +   0xdc,0xdc,0xdc,0xeb,0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,0xeb,0x87,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x83,0x00,0x00,0x00,0xb3,
 35.2462 +   0x01,0x90,0x90,0x90,0xcc,0xef,0xef,0xef,0xf5,0x82,0xff,0xff,0xff,0xff,0x01,0xef,0xef,0xef,0xf5,0x90,0x90,0x90,0xcc,0x82,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,
 35.2463 +   0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x01,0x6a,0x6a,
 35.2464 +   0x6a,0xc2,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x01,0xf7,0xf7,0xf7,0xfa,0xaf,0xaf,0xaf,0xd6,0x84,0x00,0x00,0x00,0xb3,0x00,0xe6,0xe6,0xe6,0xf0,0x81,0xff,
 35.2465 +   0xff,0xff,0xff,0x00,0x6a,0x6a,0x6a,0xc2,0x81,0x00,0x00,0x00,0xb3,0x00,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x00,0xa0,0xa0,0xa0,0xd1,0x87,0x00,0x00,0x00,
 35.2466 +   0xb3,0x01,0x6a,0x6a,0x6a,0xc2,0xef,0xef,0xef,0xf5,0x82,0xff,0xff,0xff,0xff,0x00,0xbb,0xbb,0xbb,0xdc,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,
 35.2467 +   0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x87,0x00,0x00,0x00,0xb3,0x00,
 35.2468 +   0x90,0x90,0x90,0xcc,0x81,0xff,0xff,0xff,0xff,0x00,0xd2,0xd2,0xd2,0xe6,0x81,0x00,0x00,0x00,0xb3,0x00,0x52,0x52,0x52,0xbd,0x81,0xff,0xff,0xff,0xff,0x00,0xef,0xef,
 35.2469 +   0xef,0xf5,0x82,0x00,0x00,0x00,0xb3,0x01,0x33,0x33,0x33,0xb8,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x05,0xdc,0xdc,0xdc,0xeb,0xe6,0xe6,0xe6,0xf0,0xff,0xff,
 35.2470 +   0xff,0xff,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x83,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,
 35.2471 +   0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xaf,
 35.2472 +   0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x02,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,
 35.2473 +   0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x05,0x33,0x33,0x33,0xb8,0xc7,0xc7,0xc7,0xe1,0xf7,0xf7,0xf7,0xfa,
 35.2474 +   0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,0xeb,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x03,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0xf7,0xf7,
 35.2475 +   0xf7,0xfa,0x82,0xff,0xff,0xff,0xff,0x01,0xf7,0xf7,0xf7,0xfa,0xa0,0xa0,0xa0,0xd1,0x86,0x00,0x00,0x00,0xb3,0x01,0x6a,0x6a,0x6a,0xc2,0xef,0xef,0xef,0xf5,0x82,0xff,
 35.2476 +   0xff,0xff,0xff,0x00,0xbb,0xbb,0xbb,0xdc,0x81,0xff,0xff,0xff,0xff,0x01,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,
 35.2477 +   0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x01,0x6a,0x6a,0x6a,0xc2,0xe6,0xe6,
 35.2478 +   0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,0x01,0xf7,0xf7,0xf7,0xfa,0xa0,0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x86,0x00,0x00,0x00,0xb3,0x81,
 35.2479 +   0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,
 35.2480 +   0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x02,0x00,0x00,0x00,0xb3,0x90,0x90,0x90,0xcc,0xef,0xef,0xef,0xf5,0x83,0xff,0xff,0xff,0xff,0x00,0xbb,0xbb,0xbb,
 35.2481 +   0xdc,0x82,0x00,0x00,0x00,0xb3,0x01,0x7e,0x7e,0x7e,0xc7,0xf7,0xf7,0xf7,0xfa,0x82,0xff,0xff,0xff,0xff,0x81,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,
 35.2482 +   0xaf,0xaf,0xd6,0x83,0x00,0x00,0x00,0xb3,0x01,0x6a,0x6a,0x6a,0xc2,0xef,0xef,0xef,0xf5,0x81,0xff,0xff,0xff,0xff,0x01,0xe6,0xe6,0xe6,0xf0,0xbb,0xbb,0xbb,0xdc,0x81,
 35.2483 +   0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x01,0x52,0x52,0x52,0xbd,0xd2,0xd2,0xd2,0xe6,0x82,0xff,0xff,0xff,0xff,0x01,0xf7,0xf7,0xf7,
 35.2484 +   0xfa,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x83,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,
 35.2485 +   0xff,0xff,0x82,0x00,0x00,0x00,0xb3,0x01,0x90,0x90,0x90,0xcc,0xef,0xef,0xef,0xf5,0x82,0xff,0xff,0xff,0xff,0x01,0xef,0xef,0xef,0xf5,0x90,0x90,0x90,0xcc,0x82,0x00,
 35.2486 +   0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x02,0x7e,0x7e,0x7e,
 35.2487 +   0xc7,0x6a,0x6a,0x6a,0xc2,0xdc,0xdc,0xdc,0xeb,0x83,0xff,0xff,0xff,0xff,0x01,0xdc,0xdc,0xdc,0xeb,0x33,0x33,0x33,0xb8,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
 35.2488 +   0xb3,0xbf,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xbf,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,
 35.2489 +   0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x03,0xf7,0xf7,0xf7,0xfa,0x33,0x33,0x33,0xb8,0x00,0x00,0x00,0xb3,
 35.2490 +   0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x09,0xf7,0xf7,0xf7,0xfa,0xdc,0xdc,0xdc,0xeb,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0x33,0x33,
 35.2491 +   0x33,0xb8,0x00,0x00,0x00,0xb3,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0x81,0xbb,0xbb,0xbb,0xdc,0x00,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,
 35.2492 +   0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x87,0xff,0xff,0xff,0xff,0x86,0x00,0x00,0x00,0xb3,0x00,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,
 35.2493 +   0xff,0xff,0x02,0xc7,0xc7,0xc7,0xe1,0xaf,0xaf,0xaf,0xd6,0xef,0xef,0xef,0xf5,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,
 35.2494 +   0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,
 35.2495 +   0xdc,0xdc,0xdc,0xeb,0x86,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x87,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0x00,0x00,
 35.2496 +   0x00,0xb3,0x00,0x90,0x90,0x90,0xcc,0x86,0xff,0xff,0xff,0xff,0x00,0x90,0x90,0x90,0xcc,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,
 35.2497 +   0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x03,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0x52,0x52,0x52,0xbd,0xf7,0xf7,0xf7,0xfa,0x85,0xff,
 35.2498 +   0xff,0xff,0xff,0x00,0xbb,0xbb,0xbb,0xdc,0x82,0x00,0x00,0x00,0xb3,0x00,0x6a,0x6a,0x6a,0xc2,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,
 35.2499 +   0xb3,0x00,0xef,0xef,0xef,0xf5,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x87,0x00,0x00,0x00,0xb3,0x02,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0xf7,0xf7,
 35.2500 +   0xf7,0xfa,0x81,0xbb,0xbb,0xbb,0xdc,0x00,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,
 35.2501 +   0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x87,0x00,0x00,0x00,0xb3,0x00,0xd2,0xd2,0xd2,0xe6,0x82,0xff,0xff,0xff,
 35.2502 +   0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0xa0,0xa0,0xa0,0xd1,0x82,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x00,0xc7,0xc7,0xc7,0xe1,0x81,
 35.2503 +   0xff,0xff,0xff,0xff,0x02,0xc7,0xc7,0xc7,0xe1,0xaf,0xaf,0xaf,0xd6,0xef,0xef,0xef,0xf5,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0xaf,
 35.2504 +   0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x83,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,
 35.2505 +   0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x02,0x7e,0x7e,
 35.2506 +   0x7e,0xc7,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,
 35.2507 +   0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0xe6,0xe6,0xe6,0xf0,0x86,0xff,0xff,0xff,0xff,0x06,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0xff,
 35.2508 +   0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0xdc,0xdc,0xdc,0xeb,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x85,0x00,0x00,0x00,0xb3,0x02,0xef,
 35.2509 +   0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0x81,0xbb,0xbb,0xbb,0xdc,0x00,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x01,0xaf,0xaf,0xaf,0xd6,0x00,
 35.2510 +   0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x03,0x7e,0x7e,0x7e,
 35.2511 +   0xc7,0x00,0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,0xf7,0xf7,0xf7,0xfa,0x86,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x86,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,
 35.2512 +   0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,
 35.2513 +   0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0xb3,0x6a,0x6a,0x6a,0xc2,0x81,0xff,0xff,0xff,0xff,0x01,0xdc,0xdc,0xdc,0xeb,0xef,0xef,0xef,0xf5,0x81,0xff,
 35.2514 +   0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0xef,0xef,0xef,0xf5,0x83,0xff,0xff,0xff,0xff,0x81,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,
 35.2515 +   0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x83,0x00,0x00,0x00,0xb3,0x00,0xd2,0xd2,0xd2,0xe6,0x86,0xff,0xff,0xff,0xff,0x03,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0x33,0x33,
 35.2516 +   0x33,0xb8,0xf7,0xf7,0xf7,0xfa,0x84,0xff,0xff,0xff,0xff,0x02,0xc7,0xc7,0xc7,0xe1,0x00,0x00,0x00,0xb3,0x52,0x52,0x52,0xbd,0x84,0xff,0xff,0xff,0xff,0x01,0x00,0x00,
 35.2517 +   0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0x90,0x90,0x90,0xcc,0x86,0xff,0xff,0xff,0xff,0x00,0x90,0x90,0x90,0xcc,0x81,
 35.2518 +   0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x03,0x7e,0x7e,
 35.2519 +   0x7e,0xc7,0x33,0x33,0x33,0xb8,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0x81,0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0xff,0x00,0x00,
 35.2520 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xbf,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xbf,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,
 35.2521 +   0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,0x00,0xa0,0xa0,0xa0,0xd1,0x81,0x00,
 35.2522 +   0x00,0x00,0xb3,0x07,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0xef,0xef,0xef,0xf5,0x33,0x33,0x33,0xb8,0x00,0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,0xc7,0xc7,0xc7,0xe1,
 35.2523 +   0x52,0x52,0x52,0xbd,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0x6a,0x6a,0x6a,0xc2,0x81,0xff,0xff,
 35.2524 +   0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x03,0xaf,0xaf,0xaf,0xd6,0x7e,0x7e,0x7e,0xc7,0xa0,0xa0,0xa0,
 35.2525 +   0xd1,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x86,0x00,0x00,0x00,0xb3,0x02,0xdc,0xdc,0xdc,0xeb,0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,
 35.2526 +   0xb3,0x05,0x33,0x33,0x33,0xb8,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,
 35.2527 +   0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0x6a,0x6a,0x6a,0xc2,0x81,0xff,0xff,0xff,0xff,
 35.2528 +   0x03,0xf7,0xf7,0xf7,0xfa,0xa0,0xa0,0xa0,0xd1,0x7e,0x7e,0x7e,0xc7,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x87,0x00,0x00,0x00,0xb3,
 35.2529 +   0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0x00,0x00,0x00,0xb3,0x00,0xef,0xef,0xef,0xf5,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x7e,0x7e,
 35.2530 +   0x7e,0xc7,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0xef,0xef,0xef,0xf5,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,
 35.2531 +   0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x02,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x03,0xd2,
 35.2532 +   0xd2,0xd2,0xe6,0x7e,0x7e,0x7e,0xc7,0xa0,0xa0,0xa0,0xd1,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x00,0x52,0x52,0x52,0xbd,0x81,0x00,0x00,0x00,0xb3,0x00,0xbb,
 35.2533 +   0xbb,0xbb,0xdc,0x82,0xff,0xff,0xff,0xff,0x02,0xe6,0xe6,0xe6,0xf0,0x00,0x00,0x00,0xb3,0x6a,0x6a,0x6a,0xc2,0x83,0xff,0xff,0xff,0xff,0x00,0x52,0x52,0x52,0xbd,0x86,
 35.2534 +   0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0x6a,0x6a,0x6a,0xc2,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,
 35.2535 +   0xaf,0xd6,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x86,0x00,
 35.2536 +   0x00,0x00,0xb3,0x00,0x33,0x33,0x33,0xb8,0x83,0xff,0xff,0xff,0xff,0x02,0x90,0x90,0x90,0xcc,0x00,0x00,0x00,0xb3,0xd2,0xd2,0xd2,0xe6,0x82,0xff,0xff,0xff,0xff,0x00,
 35.2537 +   0xc7,0xc7,0xc7,0xe1,0x81,0x00,0x00,0x00,0xb3,0x02,0xdc,0xdc,0xdc,0xeb,0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x05,0x33,0x33,0x33,0xb8,
 35.2538 +   0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x83,0x00,
 35.2539 +   0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,
 35.2540 +   0xd6,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x02,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,
 35.2541 +   0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xa0,0xa0,0xa0,0xd1,0x82,0xff,0xff,0xff,
 35.2542 +   0xff,0x02,0xc7,0xc7,0xc7,0xe1,0xaf,0xaf,0xaf,0xd6,0xef,0xef,0xef,0xf5,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x03,0xaf,0xaf,
 35.2543 +   0xaf,0xd6,0x33,0x33,0x33,0xb8,0x00,0x00,0x00,0xb3,0x90,0x90,0x90,0xcc,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x85,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,
 35.2544 +   0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0x6a,0x6a,0x6a,0xc2,0x81,0xff,0xff,0xff,0xff,0x01,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0x81,
 35.2545 +   0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x02,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,
 35.2546 +   0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x03,0xe6,0xe6,0xe6,0xf0,0x90,0x90,0x90,0xcc,0x7e,0x7e,0x7e,0xc7,0xd2,0xd2,0xd2,0xe6,0x81,0xff,0xff,0xff,0xff,
 35.2547 +   0x00,0xaf,0xaf,0xaf,0xd6,0x86,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,
 35.2548 +   0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x03,0xa0,0xa0,0xa0,0xd1,0x6a,
 35.2549 +   0x6a,0x6a,0xc2,0x00,0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x04,
 35.2550 +   0xef,0xef,0xef,0xf5,0x33,0x33,0x33,0xb8,0x00,0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x83,0x00,
 35.2551 +   0x00,0x00,0xb3,0x00,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x90,0x90,0x90,0xcc,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x02,
 35.2552 +   0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x03,0xd2,0xd2,0xd2,0xe6,0x7e,0x7e,0x7e,0xc7,0xa0,0xa0,0xa0,0xd1,0xc7,0xc7,
 35.2553 +   0xc7,0xe1,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x04,0xd2,0xd2,0xd2,0xe6,0x00,0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,0x00,0x00,
 35.2554 +   0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0xef,0xef,0xef,0xf5,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x7e,
 35.2555 +   0x7e,0x7e,0xc7,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0xef,0xef,0xef,0xf5,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,
 35.2556 +   0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x03,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0x6a,0x6a,0x6a,0xc2,0xa0,0xa0,0xa0,0xd1,
 35.2557 +   0x81,0x00,0x00,0x00,0xb3,0x00,0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xbf,0x00,0x00,0x00,0xb3,0xff,0x00,
 35.2558 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xbf,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,
 35.2559 +   0xa0,0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x00,0x6a,0x6a,0x6a,0xc2,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,
 35.2560 +   0xdc,0xeb,0x84,0xaf,0xaf,0xaf,0xd6,0x05,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0xaf,0xaf,0xaf,0xd6,
 35.2561 +   0x81,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x01,0xaf,0xaf,0xaf,0xd6,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xc7,0xc7,0xc7,0xe1,0x82,0x00,0x00,
 35.2562 +   0x00,0xb3,0x00,0xa0,0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,0xff,0x86,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0xbb,0xbb,0xbb,0xdc,
 35.2563 +   0x81,0x7e,0x7e,0x7e,0xc7,0x04,0xe6,0xe6,0xe6,0xf0,0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,
 35.2564 +   0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,
 35.2565 +   0x00,0xa0,0xa0,0xa0,0xd1,0x82,0x00,0x00,0x00,0xb3,0x02,0xc7,0xc7,0xc7,0xe1,0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,0xeb,0x87,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,
 35.2566 +   0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x00,0x6a,0x6a,0x6a,0xc2,0x81,0xff,0xff,0xff,0xff,0x00,0xc7,0xc7,0xc7,0xe1,0x82,0x00,0x00,0x00,0xb3,0x00,
 35.2567 +   0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x01,0x6a,0x6a,0x6a,0xc2,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,
 35.2568 +   0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x04,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xef,0xef,0xef,0xf5,0x82,0x00,
 35.2569 +   0x00,0x00,0xb3,0x00,0xa0,0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x02,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,
 35.2570 +   0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x06,0x33,0x33,0x33,0xb8,0xbb,0xbb,0xbb,0xdc,0xff,0xff,0xff,0xff,0xef,0xef,0xef,0xf5,0xf7,0xf7,0xf7,0xfa,0xff,0xff,
 35.2571 +   0xff,0xff,0xaf,0xaf,0xaf,0xd6,0x86,0x00,0x00,0x00,0xb3,0x03,0xdc,0xdc,0xdc,0xeb,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0xaf,0xaf,0xaf,0xd6,0x81,0x7e,0x7e,0x7e,
 35.2572 +   0xc7,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,
 35.2573 +   0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x86,0x00,0x00,0x00,0xb3,0x00,0xa0,0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,0xff,0x03,0xdc,0xdc,0xdc,0xeb,0xff,0xff,0xff,0xff,0xbb,
 35.2574 +   0xbb,0xbb,0xdc,0x33,0x33,0x33,0xb8,0x81,0xff,0xff,0xff,0xff,0x02,0xe6,0xe6,0xe6,0xf0,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,
 35.2575 +   0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0xbb,0xbb,0xbb,0xdc,0x81,0x7e,0x7e,0x7e,0xc7,0x04,0xe6,0xe6,0xe6,0xf0,0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,0xeb,0x00,
 35.2576 +   0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x83,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,
 35.2577 +   0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,
 35.2578 +   0xff,0x02,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,
 35.2579 +   0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xd2,0xd2,0xd2,0xe6,0x81,0xff,0xff,0xff,0xff,0x00,0x90,0x90,0x90,0xcc,0x81,0x00,0x00,0x00,0xb3,0x03,0x33,
 35.2580 +   0x33,0x33,0xb8,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x02,0x52,0x52,0x52,0xbd,0xaf,0xaf,0xaf,0xd6,0xdc,0xdc,0xdc,
 35.2581 +   0xeb,0x82,0xff,0xff,0xff,0xff,0x00,0xa0,0xa0,0xa0,0xd1,0x85,0x00,0x00,0x00,0xb3,0x03,0xdc,0xdc,0xdc,0xeb,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0xaf,0xaf,0xaf,
 35.2582 +   0xd6,0x81,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x01,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0x00,
 35.2583 +   0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x02,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x00,
 35.2584 +   0x52,0x52,0x52,0xbd,0x82,0x00,0x00,0x00,0xb3,0x02,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0xaf,0xaf,0xaf,0xd6,0x86,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,
 35.2585 +   0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,
 35.2586 +   0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x03,0x33,0x33,0x33,0xb8,0xaf,0xaf,0xaf,0xd6,0xd2,0xd2,0xd2,0xe6,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,
 35.2587 +   0xff,0x00,0xc7,0xc7,0xc7,0xe1,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,
 35.2588 +   0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x83,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xe6,0xe6,0xe6,0xf0,0x81,0x00,0x00,0x00,0xb3,0x00,0xbb,0xbb,
 35.2589 +   0xbb,0xdc,0x81,0xff,0xff,0xff,0xff,0x04,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xef,0xef,0xef,0xf5,0x85,0x00,0x00,0x00,
 35.2590 +   0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x01,
 35.2591 +   0x00,0x00,0x00,0xb3,0x6a,0x6a,0x6a,0xc2,0x81,0xff,0xff,0xff,0xff,0x00,0xc7,0xc7,0xc7,0xe1,0x82,0x00,0x00,0x00,0xb3,0x00,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,
 35.2592 +   0xff,0x01,0x6a,0x6a,0x6a,0xc2,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,
 35.2593 +   0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x02,0xa0,0xa0,0xa0,0xd1,0xc7,0xc7,0xc7,0xe1,0xef,0xef,0xef,0xf5,0x81,0xff,0xff,0xff,0xff,0x00,
 35.2594 +   0xef,0xef,0xef,0xf5,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xbf,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xbf,0x00,0x00,
 35.2595 +   0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xef,0xef,0xef,0xf5,0x81,0xff,0xff,0xff,0xff,0x00,0x6a,
 35.2596 +   0x6a,0x6a,0xc2,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x87,0xff,0xff,0xff,0xff,0x03,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0x6a,0x6a,0x6a,0xc2,0xe6,
 35.2597 +   0xe6,0xe6,0xf0,0x85,0xff,0xff,0xff,0xff,0x01,0xaf,0xaf,0xaf,0xd6,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,
 35.2598 +   0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x86,0x00,0x00,0x00,0xb3,0x01,0x33,0x33,0x33,0xb8,0xd2,0xd2,0xd2,0xe6,0x85,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,
 35.2599 +   0xdc,0xeb,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,
 35.2600 +   0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0x00,0x00,0x00,0xb3,0x02,0xaf,0xaf,0xaf,0xd6,0xff,
 35.2601 +   0xff,0xff,0xff,0xdc,0xdc,0xdc,0xeb,0x87,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,
 35.2602 +   0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x01,0x7e,0x7e,0x7e,0xc7,0x00,0x00,
 35.2603 +   0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x01,0x7e,0x7e,0x7e,0xc7,0x00,0x00,
 35.2604 +   0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,
 35.2605 +   0x00,0x00,0x00,0xb3,0x90,0x90,0x90,0xcc,0x81,0xff,0xff,0xff,0xff,0x09,0xaf,0xaf,0xaf,0xd6,0xe6,0xe6,0xe6,0xf0,0xff,0xff,0xff,0xff,0x90,0x90,0x90,0xcc,0xef,0xef,
 35.2606 +   0xef,0xf5,0xff,0xff,0xff,0xff,0xbb,0xbb,0xbb,0xdc,0xd2,0xd2,0xd2,0xe6,0xff,0xff,0xff,0xff,0xe6,0xe6,0xe6,0xf0,0x86,0x00,0x00,0x00,0xb3,0x01,0x6a,0x6a,0x6a,0xc2,
 35.2607 +   0xe6,0xe6,0xe6,0xf0,0x85,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,
 35.2608 +   0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x86,0x00,0x00,0x00,0xb3,0x06,0xe6,0xe6,0xe6,0xf0,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0x90,0x90,0x90,0xcc,
 35.2609 +   0xff,0xff,0xff,0xff,0xe6,0xe6,0xe6,0xf0,0xa0,0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x03,0x90,0x90,0x90,0xcc,
 35.2610 +   0x00,0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,0xd2,0xd2,0xd2,0xe6,0x85,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,
 35.2611 +   0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x83,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,
 35.2612 +   0xc7,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x02,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,
 35.2613 +   0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,
 35.2614 +   0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x83,0x00,0x00,0x00,0xb3,0x05,0xdc,0xdc,0xdc,0xeb,0xff,0xff,0xff,0xff,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,
 35.2615 +   0xb3,0x52,0x52,0x52,0xbd,0xf7,0xf7,0xf7,0xfa,0x83,0xff,0xff,0xff,0xff,0x01,0xdc,0xdc,0xdc,0xeb,0x33,0x33,0x33,0xb8,0x85,0x00,0x00,0x00,0xb3,0x01,0x6a,0x6a,0x6a,
 35.2616 +   0xc2,0xe6,0xe6,0xe6,0xf0,0x85,0xff,0xff,0xff,0xff,0x01,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,
 35.2617 +   0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x02,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x83,0x00,
 35.2618 +   0x00,0x00,0xb3,0x02,0xdc,0xdc,0xdc,0xeb,0xff,0xff,0xff,0xff,0xaf,0xaf,0xaf,0xd6,0x86,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,
 35.2619 +   0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,
 35.2620 +   0x81,0x00,0x00,0x00,0xb3,0x00,0xe6,0xe6,0xe6,0xf0,0x83,0xff,0xff,0xff,0xff,0x01,0xef,0xef,0xef,0xf5,0x6a,0x6a,0x6a,0xc2,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,
 35.2621 +   0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x83,0x00,0x00,0x00,0xb3,
 35.2622 +   0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x01,0x7e,0x7e,0x7e,0xc7,0x00,0x00,
 35.2623 +   0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x85,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,
 35.2624 +   0x82,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,
 35.2625 +   0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x01,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,
 35.2626 +   0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x02,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0xbb,0xbb,0xbb,0xdc,
 35.2627 +   0x83,0xff,0xff,0xff,0xff,0x01,0xf7,0xf7,0xf7,0xfa,0xa0,0xa0,0xa0,0xd1,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xbf,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
 35.2628 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xbf,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x85,0xff,0xff,0xff,0xff,0x01,0xf7,0xf7,0xf7,0xfa,0xaf,0xaf,0xaf,0xd6,0x81,
 35.2629 +   0x00,0x00,0x00,0xb3,0x00,0x52,0x52,0x52,0xbd,0x81,0xff,0xff,0xff,0xff,0x00,0xd2,0xd2,0xd2,0xe6,0x81,0x7e,0x7e,0x7e,0xc7,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,
 35.2630 +   0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,0x01,0x6a,0x6a,0x6a,0xc2,0xa0,0xa0,0xa0,0xd1,0x81,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x01,
 35.2631 +   0xaf,0xaf,0xaf,0xd6,0x52,0x52,0x52,0xbd,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,
 35.2632 +   0xff,0x88,0x00,0x00,0x00,0xb3,0x01,0x52,0x52,0x52,0xbd,0x90,0x90,0x90,0xcc,0x81,0xaf,0xaf,0xaf,0xd6,0x04,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,
 35.2633 +   0xeb,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x02,0x52,0x52,0x52,0xbd,0x00,0x00,0x00,0xb3,0xa0,0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,0xff,
 35.2634 +   0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xa0,0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,0x02,0xdc,0xdc,0xdc,
 35.2635 +   0xeb,0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,0xeb,0x87,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x00,0x52,0x52,
 35.2636 +   0x52,0xbd,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x01,0x52,0x52,0x52,0xbd,
 35.2637 +   0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x05,0x7e,0x7e,0x7e,0xc7,
 35.2638 +   0x00,0x00,0x00,0xb3,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0x33,0x33,0x33,0xb8,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,
 35.2639 +   0xff,0xff,0xff,0x02,0xa0,0xa0,0xa0,0xd1,0x00,0x00,0x00,0xb3,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x03,0x52,0x52,0x52,0xbd,0xbb,0xbb,0xbb,0xdc,0xff,0xff,
 35.2640 +   0xff,0xff,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x01,0x7e,0x7e,0x7e,0xc7,0xa0,0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,0xff,0x00,0x6a,0x6a,0x6a,0xc2,0x87,0x00,
 35.2641 +   0x00,0x00,0xb3,0x01,0x6a,0x6a,0x6a,0xc2,0xa0,0xa0,0xa0,0xd1,0x81,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xdc,
 35.2642 +   0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x85,0x00,0x00,0x00,0xb3,0x00,0x52,0x52,0x52,
 35.2643 +   0xbd,0x81,0xff,0xff,0xff,0xff,0x01,0xc7,0xc7,0xc7,0xe1,0x33,0x33,0x33,0xb8,0x81,0xff,0xff,0xff,0xff,0x06,0xdc,0xdc,0xdc,0xeb,0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,
 35.2644 +   0xeb,0x00,0x00,0x00,0xb3,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0xd2,0xd2,0xd2,0xe6,0x82,0x00,0x00,0x00,0xb3,0x01,0x52,0x52,0x52,0xbd,0x90,0x90,0x90,0xcc,0x81,
 35.2645 +   0xaf,0xaf,0xaf,0xd6,0x04,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0xbb,
 35.2646 +   0xbb,0xbb,0xdc,0x83,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x02,0x52,0x52,0x52,0xbd,0x00,0x00,0x00,0xb3,0xa0,0xa0,0xa0,0xd1,0x81,
 35.2647 +   0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x02,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0xdc,
 35.2648 +   0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x02,0x52,0x52,0x52,0xbd,0x00,0x00,0x00,0xb3,0xa0,0xa0,0xa0,0xd1,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,
 35.2649 +   0x00,0x00,0xb3,0xd2,0xd2,0xd2,0xe6,0x81,0xff,0xff,0xff,0xff,0x00,0x90,0x90,0x90,0xcc,0x81,0x00,0x00,0x00,0xb3,0x05,0x33,0x33,0x33,0xb8,0xf7,0xf7,0xf7,0xfa,0xff,
 35.2650 +   0xff,0xff,0xff,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x02,0xef,0xef,0xef,0xf5,0xaf,0xaf,0xaf,0xd6,0x6a,0x6a,0x6a,
 35.2651 +   0xc2,0x89,0x00,0x00,0x00,0xb3,0x01,0x6a,0x6a,0x6a,0xc2,0xa0,0xa0,0xa0,0xd1,0x81,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x01,0xaf,0xaf,0xaf,0xd6,0x00,0x00,
 35.2652 +   0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xef,0xef,0xef,0xf5,0x81,0x00,0x00,0x00,0xb3,0x00,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x02,0x7e,0x7e,0x7e,0xc7,
 35.2653 +   0x00,0x00,0x00,0xb3,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x03,0x33,0x33,0x33,0xb8,0xf7,0xf7,0xf7,0xfa,
 35.2654 +   0xff,0xff,0xff,0xff,0xaf,0xaf,0xaf,0xd6,0x86,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,
 35.2655 +   0xff,0xff,0xff,0xff,0x00,0xc7,0xc7,0xc7,0xe1,0x81,0x00,0x00,0x00,0xb3,0x00,0xef,0xef,0xef,0xf5,0x81,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,
 35.2656 +   0xc7,0x81,0xff,0xff,0xff,0xff,0x02,0xf7,0xf7,0xf7,0xfa,0xbb,0xbb,0xbb,0xdc,0x90,0x90,0x90,0xcc,0x83,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,
 35.2657 +   0xdc,0xeb,0x82,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xe6,0xe6,0xe6,0xf0,0x83,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,
 35.2658 +   0x00,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x05,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0xef,0xef,0xef,
 35.2659 +   0xf5,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0x33,0x33,0x33,0xb8,0x81,0x00,0x00,0x00,0xb3,0x00,0x33,0x33,0x33,0xb8,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,
 35.2660 +   0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0xb3,0x52,
 35.2661 +   0x52,0x52,0xbd,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x01,0x52,0x52,0x52,
 35.2662 +   0xbd,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xef,0xef,0xef,0xf5,0x81,0x00,0x00,0x00,0xb3,0x00,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x01,0x7e,
 35.2663 +   0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0x82,0xff,0xff,0xff,0xff,0x02,0xc7,0xc7,0xc7,0xe1,0xa0,0xa0,0xa0,0xd1,0x33,0x33,0x33,0xb8,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
 35.2664 +   0x00,0x00,0xb3,0xc0,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xbf,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x87,0xff,0xff,0xff,
 35.2665 +   0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x05,0xdc,0xdc,0xdc,0xeb,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0x6a,0x6a,0x6a,0xc2,0x33,0x33,0x33,0xb8,
 35.2666 +   0xd2,0xd2,0xd2,0xe6,0x81,0xff,0xff,0xff,0xff,0x00,0x52,0x52,0x52,0xbd,0x81,0x00,0x00,0x00,0xb3,0x01,0x6a,0x6a,0x6a,0xc2,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,
 35.2667 +   0xb3,0x00,0x90,0x90,0x90,0xcc,0x81,0xff,0xff,0xff,0xff,0x02,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,
 35.2668 +   0xdc,0xeb,0xaf,0xaf,0xaf,0xd6,0xc7,0xc7,0xc7,0xe1,0x82,0xff,0xff,0xff,0xff,0x87,0x00,0x00,0x00,0xb3,0x09,0x33,0x33,0x33,0xb8,0xaf,0xaf,0xaf,0xd6,0x33,0x33,0x33,
 35.2669 +   0xb8,0x00,0x00,0x00,0xb3,0x52,0x52,0x52,0xbd,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,
 35.2670 +   0xff,0xff,0x02,0xe6,0xe6,0xe6,0xf0,0xaf,0xaf,0xaf,0xd6,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x02,0xa0,0xa0,0xa0,0xd1,0x00,0x00,0x00,0xb3,0x33,0x33,0x33,
 35.2671 +   0xb8,0x82,0xff,0xff,0xff,0xff,0x02,0xc7,0xc7,0xc7,0xe1,0xaf,0xaf,0xaf,0xd6,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x85,0x00,0x00,
 35.2672 +   0x00,0xb3,0x01,0xa0,0xa0,0xa0,0xd1,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x04,0xef,0xef,0xef,0xf5,0xaf,0xaf,0xaf,0xd6,0xa0,0xa0,0xa0,0xd1,0x00,0x00,0x00,
 35.2673 +   0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0xaf,0xaf,0xaf,0xd6,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,
 35.2674 +   0xeb,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x02,0x7e,0x7e,
 35.2675 +   0x7e,0xc7,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x02,0xef,0xef,0xef,0xf5,0xaf,0xaf,0xaf,0xd6,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,
 35.2676 +   0xff,0x00,0xf7,0xf7,0xf7,0xfa,0x81,0x33,0x33,0x33,0xb8,0x81,0xff,0xff,0xff,0xff,0x02,0xe6,0xe6,0xe6,0xf0,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,
 35.2677 +   0xff,0xff,0x02,0xf7,0xf7,0xf7,0xfa,0x00,0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,0x81,0xff,0xff,0xff,0xff,0x00,0xbb,0xbb,0xbb,0xdc,0x86,0x00,0x00,0x00,0xb3,0x01,0x6a,
 35.2678 +   0x6a,0x6a,0xc2,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0x90,0x90,0x90,0xcc,0x81,0xff,0xff,0xff,0xff,0x02,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0xdc,
 35.2679 +   0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x85,0x00,0x00,0x00,0xb3,0x00,0xbb,0xbb,0xbb,
 35.2680 +   0xdc,0x81,0xff,0xff,0xff,0xff,0x02,0x90,0x90,0x90,0xcc,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,
 35.2681 +   0xb3,0xbb,0xbb,0xbb,0xdc,0x81,0xff,0xff,0xff,0xff,0x0b,0x33,0x33,0x33,0xb8,0x00,0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,0xaf,0xaf,0xaf,0xd6,0x33,0x33,0x33,0xb8,0x00,
 35.2682 +   0x00,0x00,0xb3,0x52,0x52,0x52,0xbd,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x82,0xff,0xff,0xff,0xff,
 35.2683 +   0x04,0xc7,0xc7,0xc7,0xe1,0xaf,0xaf,0xaf,0xd6,0xa0,0xa0,0xa0,0xd1,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x02,0xe6,0xe6,0xe6,0xf0,0xaf,
 35.2684 +   0xaf,0xaf,0xd6,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x02,0xa0,0xa0,0xa0,0xd1,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x02,0x7e,
 35.2685 +   0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x02,0xe6,0xe6,0xe6,0xf0,0xaf,0xaf,0xaf,0xd6,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,
 35.2686 +   0xff,0xff,0x02,0xa0,0xa0,0xa0,0xd1,0x00,0x00,0x00,0xb3,0xa0,0xa0,0xa0,0xd1,0x82,0xff,0xff,0xff,0xff,0x02,0xc7,0xc7,0xc7,0xe1,0xaf,0xaf,0xaf,0xd6,0xef,0xef,0xef,
 35.2687 +   0xf5,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x03,0xa0,0xa0,0xa0,0xd1,0x00,0x00,0x00,
 35.2688 +   0xb3,0xaf,0xaf,0xaf,0xd6,0x6a,0x6a,0x6a,0xc2,0x87,0x00,0x00,0x00,0xb3,0x01,0x6a,0x6a,0x6a,0xc2,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0x90,0x90,0x90,
 35.2689 +   0xcc,0x81,0xff,0xff,0xff,0xff,0x01,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0x82,0xff,0xff,0xff,0xff,0x01,0xd2,0xd2,0xd2,0xe6,0xbb,0xbb,0xbb,0xdc,0x82,0xff,0xff,
 35.2690 +   0xff,0xff,0x02,0x52,0x52,0x52,0xbd,0x00,0x00,0x00,0xb3,0x90,0x90,0x90,0xcc,0x81,0xff,0xff,0xff,0xff,0x03,0xf7,0xf7,0xf7,0xfa,0xbb,0xbb,0xbb,0xdc,0xaf,0xaf,0xaf,
 35.2691 +   0xd6,0xef,0xef,0xef,0xf5,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x86,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,
 35.2692 +   0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x01,0xbb,0xbb,0xbb,0xdc,0xd2,0xd2,0xd2,0xe6,0x81,0xff,0xff,0xff,0xff,0x02,0xef,0xef,0xef,0xf5,0x00,0x00,
 35.2693 +   0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x06,0xc7,0xc7,0xc7,0xe1,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0xa0,0xa0,0xa0,0xd1,0x00,0x00,0x00,0xb3,
 35.2694 +   0xa0,0xa0,0xa0,0xd1,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0xef,0xef,0xef,0xf5,0x81,0xaf,0xaf,0xaf,0xd6,0x01,0x52,0x52,0x52,0xbd,0x7e,0x7e,0x7e,0xc7,
 35.2695 +   0x82,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0x00,
 35.2696 +   0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x02,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x06,
 35.2697 +   0xef,0xef,0xef,0xf5,0xaf,0xaf,0xaf,0xd6,0xc7,0xc7,0xc7,0xe1,0xe6,0xe6,0xe6,0xf0,0x33,0x33,0x33,0xb8,0xaf,0xaf,0xaf,0xd6,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,
 35.2698 +   0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xaf,0xaf,0xaf,0xd6,0x01,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,
 35.2699 +   0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0xaf,0xaf,0xaf,0xd6,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,
 35.2700 +   0x00,0x00,0x00,0xb3,0x82,0xff,0xff,0xff,0xff,0x01,0xd2,0xd2,0xd2,0xe6,0xbb,0xbb,0xbb,0xdc,0x82,0xff,0xff,0xff,0xff,0x01,0x52,0x52,0x52,0xbd,0x00,0x00,0x00,0xb3,
 35.2701 +   0x81,0xff,0xff,0xff,0xff,0x03,0xe6,0xe6,0xe6,0xf0,0x33,0x33,0x33,0xb8,0x52,0x52,0x52,0xbd,0xaf,0xaf,0xaf,0xd6,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
 35.2702 +   0xc0,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xbf,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,
 35.2703 +   0xdc,0xdc,0xeb,0x81,0xaf,0xaf,0xaf,0xd6,0x00,0xc7,0xc7,0xc7,0xe1,0x82,0xff,0xff,0xff,0xff,0x03,0x90,0x90,0x90,0xcc,0x00,0x00,0x00,0xb3,0x6a,0x6a,0x6a,0xc2,0xf7,
 35.2704 +   0xf7,0xf7,0xfa,0x84,0xff,0xff,0xff,0xff,0x00,0xbb,0xbb,0xbb,0xdc,0x81,0x00,0x00,0x00,0xb3,0x04,0x33,0x33,0x33,0xb8,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xef,
 35.2705 +   0xef,0xef,0xf5,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x00,0xef,0xef,0xef,0xf5,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x87,0xff,0xff,0xff,0xff,
 35.2706 +   0x87,0x00,0x00,0x00,0xb3,0x04,0xdc,0xdc,0xdc,0xeb,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0xdc,0xdc,0xdc,0xeb,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x02,
 35.2707 +   0x52,0x52,0x52,0xbd,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x00,0xf7,0xf7,0xf7,0xfa,0x83,0xff,0xff,0xff,0xff,0x00,0x52,0x52,0x52,0xbd,
 35.2708 +   0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x86,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x85,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x84,0xff,
 35.2709 +   0xff,0xff,0xff,0x03,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0x6a,0x6a,0x6a,0xc2,0xf7,0xf7,0xf7,0xfa,0x84,0xff,0xff,0xff,0xff,0x01,0xf7,0xf7,0xf7,0xfa,0x6a,0x6a,
 35.2710 +   0x6a,0xc2,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x03,0x7e,
 35.2711 +   0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,0xe6,0xe6,0xe6,0xf0,0x85,0xff,0xff,0xff,0xff,0x02,0xa0,0xa0,0xa0,0xd1,0x00,0x00,0x00,0xb3,0xa0,0xa0,0xa0,
 35.2712 +   0xd1,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x82,0xff,0xff,0xff,0xff,0x00,0xd2,0xd2,0xd2,0xe6,0x81,0x00,0x00,0x00,0xb3,0x02,
 35.2713 +   0xe6,0xe6,0xe6,0xf0,0xff,0xff,0xff,0xff,0xef,0xef,0xef,0xf5,0x85,0x00,0x00,0x00,0xb3,0x04,0x33,0x33,0x33,0xb8,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xef,0xef,
 35.2714 +   0xef,0xf5,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x00,0xef,0xef,0xef,0xf5,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,
 35.2715 +   0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x85,0x00,0x00,0x00,0xb3,0x02,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,
 35.2716 +   0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0xff,0xff,0xff,0xff,0x02,0x6a,0x6a,0x6a,0xc2,0x00,0x00,0x00,0xb3,0x90,0x90,0x90,0xcc,0x81,0xff,0xff,0xff,
 35.2717 +   0xff,0x06,0xa0,0xa0,0xa0,0xd1,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0xdc,0xdc,0xdc,0xeb,0xf7,0xf7,0xf7,0xfa,0x81,0xff,
 35.2718 +   0xff,0xff,0xff,0x02,0x52,0x52,0x52,0xbd,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,0x02,
 35.2719 +   0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x00,0xf7,0xf7,0xf7,0xfa,0x83,0xff,0xff,0xff,0xff,0x02,0x52,0x52,0x52,0xbd,
 35.2720 +   0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x02,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x00,
 35.2721 +   0xf7,0xf7,0xf7,0xfa,0x83,0xff,0xff,0xff,0xff,0x00,0x52,0x52,0x52,0xbd,0x81,0x00,0x00,0x00,0xb3,0x00,0xe6,0xe6,0xe6,0xf0,0x83,0xff,0xff,0xff,0xff,0x00,0xf7,0xf7,
 35.2722 +   0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x03,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0x52,0x52,0x52,0xbd,0xf7,0xf7,0xf7,0xfa,0x83,0xff,0xff,0xff,0xff,0x01,0xf7,0xf7,
 35.2723 +   0xf7,0xfa,0x6a,0x6a,0x6a,0xc2,0x85,0x00,0x00,0x00,0xb3,0x04,0x33,0x33,0x33,0xb8,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xef,0xef,0xef,0xf5,0xdc,0xdc,0xdc,0xeb,
 35.2724 +   0x81,0xff,0xff,0xff,0xff,0x00,0xef,0xef,0xef,0xf5,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xf7,0xf7,0xf7,0xfa,0x83,0xff,0xff,0xff,0xff,0x00,0xef,
 35.2725 +   0xef,0xef,0xf5,0x82,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x86,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x86,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,
 35.2726 +   0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xf7,0xf7,0xf7,0xfa,0x83,0xff,0xff,0xff,0xff,0x00,0xc7,0xc7,
 35.2727 +   0xc7,0xe1,0x81,0x00,0x00,0x00,0xb3,0x00,0xe6,0xe6,0xe6,0xf0,0x84,0xff,0xff,0xff,0xff,0x01,0xa0,0xa0,0xa0,0xd1,0xdc,0xdc,0xdc,0xeb,0x85,0xff,0xff,0xff,0xff,0x81,
 35.2728 +   0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xe6,0xe6,0xe6,0xf0,0x82,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,
 35.2729 +   0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x00,0xe6,0xe6,0xe6,0xf0,
 35.2730 +   0x84,0xff,0xff,0xff,0xff,0x00,0xe6,0xe6,0xe6,0xf0,0x86,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,
 35.2731 +   0x00,0xb3,0x01,0x6a,0x6a,0x6a,0xc2,0xf7,0xf7,0xf7,0xfa,0x84,0xff,0xff,0xff,0xff,0x01,0xf7,0xf7,0xf7,0xfa,0x6a,0x6a,0x6a,0xc2,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,
 35.2732 +   0xff,0xff,0xff,0x00,0xf7,0xf7,0xf7,0xfa,0x83,0xff,0xff,0xff,0xff,0x00,0xef,0xef,0xef,0xf5,0x81,0x00,0x00,0x00,0xb3,0x00,0xbb,0xbb,0xbb,0xdc,0x84,0xff,0xff,0xff,
 35.2733 +   0xff,0x00,0xc7,0xc7,0xc7,0xe1,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xbf,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xbf,
 35.2734 +   0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,0x00,0xbb,0xbb,0xbb,0xdc,0x81,0xff,0xff,
 35.2735 +   0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x05,0x52,0x52,0x52,0xbd,0xc7,0xc7,0xc7,0xe1,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xef,0xef,0xef,
 35.2736 +   0xf5,0xaf,0xaf,0xaf,0xd6,0x83,0x00,0x00,0x00,0xb3,0x06,0x7e,0x7e,0x7e,0xc7,0xd2,0xd2,0xd2,0xe6,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0xd2,
 35.2737 +   0xd2,0xd2,0xe6,0x52,0x52,0x52,0xbd,0x82,0x00,0x00,0x00,0xb3,0x05,0x90,0x90,0x90,0xcc,0xe6,0xe6,0xe6,0xf0,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0xaf,0xaf,0xaf,
 35.2738 +   0xd6,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x87,0x00,0x00,0x00,0xb3,0x02,0x52,0x52,0x52,0xbd,0xc7,0xc7,0xc7,0xe1,0xef,0xef,0xef,0xf5,0x81,0xff,0xff,0xff,
 35.2739 +   0xff,0x01,0xdc,0xdc,0xdc,0xeb,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x00,0xbb,0xbb,0xbb,0xdc,0x81,0xdc,0xdc,0xdc,0xeb,0x04,0x6a,0x6a,0x6a,0xc2,0xef,0xef,
 35.2740 +   0xef,0xf5,0xff,0xff,0xff,0xff,0xef,0xef,0xef,0xf5,0x90,0x90,0x90,0xcc,0x83,0x00,0x00,0x00,0xb3,0x04,0xaf,0xaf,0xaf,0xd6,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,
 35.2741 +   0xef,0xef,0xef,0xf5,0x90,0x90,0x90,0xcc,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x85,0x00,0x00,0x00,0xb3,0x01,0xbb,0xbb,0xbb,0xdc,0xdc,0xdc,0xdc,0xeb,
 35.2742 +   0x81,0xff,0xff,0xff,0xff,0x02,0xf7,0xf7,0xf7,0xfa,0xdc,0xdc,0xdc,0xeb,0xbb,0xbb,0xbb,0xdc,0x81,0x00,0x00,0x00,0xb3,0x06,0x52,0x52,0x52,0xbd,0xc7,0xc7,0xc7,0xe1,
 35.2743 +   0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0xc7,0xc7,0xc7,0xe1,0x52,0x52,0x52,0xbd,0x82,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,
 35.2744 +   0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x02,0x33,0x33,0x33,0xb8,0xaf,
 35.2745 +   0xaf,0xaf,0xd6,0xef,0xef,0xef,0xf5,0x81,0xff,0xff,0xff,0xff,0x01,0xd2,0xd2,0xd2,0xe6,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,
 35.2746 +   0xdc,0xdc,0xdc,0xeb,0x00,0x52,0x52,0x52,0xbd,0x81,0x00,0x00,0x00,0xb3,0x00,0xbb,0xbb,0xbb,0xdc,0x81,0xdc,0xdc,0xdc,0xeb,0x00,0x90,0x90,0x90,0xcc,0x81,0x00,0x00,
 35.2747 +   0x00,0xb3,0x00,0xa0,0xa0,0xa0,0xd1,0x81,0xdc,0xdc,0xdc,0xeb,0x00,0x52,0x52,0x52,0xbd,0x85,0x00,0x00,0x00,0xb3,0x06,0x7e,0x7e,0x7e,0xc7,0xd2,0xd2,0xd2,0xe6,0xf7,
 35.2748 +   0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0xd2,0xd2,0xd2,0xe6,0x52,0x52,0x52,0xbd,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,
 35.2749 +   0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x84,0x00,0x00,0x00,0xb3,0x00,0x52,0x52,0x52,0xbd,0x81,0xdc,0xdc,0xdc,0xeb,
 35.2750 +   0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0x6a,0x6a,0x6a,0xc2,0x81,0xdc,0xdc,0xdc,0xeb,0x00,0xd2,0xd2,0xd2,0xe6,0x82,0x00,0x00,0x00,0xb3,0x81,0xdc,
 35.2751 +   0xdc,0xdc,0xeb,0x04,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0x52,0x52,0x52,0xbd,0xc7,0xc7,0xc7,0xe1,0xef,0xef,0xef,0xf5,0x81,0xff,0xff,0xff,0xff,0x01,0xdc,0xdc,
 35.2752 +   0xdc,0xeb,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x00,0xa0,0xa0,0xa0,0xd1,0x81,0xdc,0xdc,0xdc,0xeb,0x05,0x7e,0x7e,0x7e,0xc7,0xc7,0xc7,0xc7,0xe1,0xff,0xff,
 35.2753 +   0xff,0xff,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0xbb,0xbb,0xbb,0xdc,0x81,0xdc,0xdc,0xdc,0xeb,0x04,0x6a,0x6a,0x6a,0xc2,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,
 35.2754 +   0xef,0xef,0xef,0xf5,0x90,0x90,0x90,0xcc,0x81,0x00,0x00,0x00,0xb3,0x00,0xa0,0xa0,0xa0,0xd1,0x81,0xdc,0xdc,0xdc,0xeb,0x02,0x6a,0x6a,0x6a,0xc2,0x00,0x00,0x00,0xb3,
 35.2755 +   0xbb,0xbb,0xbb,0xdc,0x81,0xdc,0xdc,0xdc,0xeb,0x04,0x6a,0x6a,0x6a,0xc2,0xef,0xef,0xef,0xf5,0xff,0xff,0xff,0xff,0xef,0xef,0xef,0xf5,0x90,0x90,0x90,0xcc,0x82,0x00,
 35.2756 +   0x00,0x00,0xb3,0x01,0x33,0x33,0x33,0xb8,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,0xff,0x01,0xd2,0xd2,0xd2,0xe6,0x6a,0x6a,0x6a,0xc2,0x81,0xdc,0xdc,0xdc,0xeb,0x00,
 35.2757 +   0xa0,0xa0,0xa0,0xd1,0x81,0x00,0x00,0x00,0xb3,0x01,0x6a,0x6a,0x6a,0xc2,0xd2,0xd2,0xd2,0xe6,0x81,0xff,0xff,0xff,0xff,0x02,0xef,0xef,0xef,0xf5,0xaf,0xaf,0xaf,0xd6,
 35.2758 +   0x33,0x33,0x33,0xb8,0x86,0x00,0x00,0x00,0xb3,0x06,0x7e,0x7e,0x7e,0xc7,0xd2,0xd2,0xd2,0xe6,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0xd2,0xd2,
 35.2759 +   0xd2,0xe6,0x52,0x52,0x52,0xbd,0x81,0x00,0x00,0x00,0xb3,0x81,0xdc,0xdc,0xdc,0xeb,0x05,0xbb,0xbb,0xbb,0xdc,0xa0,0xa0,0xa0,0xd1,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,
 35.2760 +   0xff,0xdc,0xdc,0xdc,0xeb,0x6a,0x6a,0x6a,0xc2,0x82,0x00,0x00,0x00,0xb3,0x05,0x33,0x33,0x33,0xb8,0xc7,0xc7,0xc7,0xe1,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xdc,
 35.2761 +   0xdc,0xdc,0xeb,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x86,0x00,0x00,0x00,0xb3,0x81,0xdc,0xdc,0xdc,0xeb,0x02,0xbb,0xbb,0xbb,0xdc,
 35.2762 +   0x00,0x00,0x00,0xb3,0x6a,0x6a,0x6a,0xc2,0x81,0xdc,0xdc,0xdc,0xeb,0x01,0xa0,0xa0,0xa0,0xd1,0xbb,0xbb,0xbb,0xdc,0x81,0xff,0xff,0xff,0xff,0x01,0xc7,0xc7,0xc7,0xe1,
 35.2763 +   0x33,0x33,0x33,0xb8,0x81,0x00,0x00,0x00,0xb3,0x08,0x33,0x33,0x33,0xb8,0xc7,0xc7,0xc7,0xe1,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0xc7,0xc7,
 35.2764 +   0xc7,0xe1,0x52,0x52,0x52,0xbd,0xbb,0xbb,0xbb,0xdc,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x00,0xf7,0xf7,0xf7,0xfa,0x81,0xdc,0xdc,0xdc,0xeb,0x81,0x6a,0x6a,
 35.2765 +   0x6a,0xc2,0x81,0xdc,0xdc,0xdc,0xeb,0x04,0xa0,0xa0,0xa0,0xd1,0xaf,0xaf,0xaf,0xd6,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0xb3,0x81,0xdc,0xdc,0xdc,
 35.2766 +   0xeb,0x00,0xbb,0xbb,0xbb,0xdc,0x81,0x00,0x00,0x00,0xb3,0x00,0xa0,0xa0,0xa0,0xd1,0x81,0xdc,0xdc,0xdc,0xeb,0x00,0x6a,0x6a,0x6a,0xc2,0x82,0x00,0x00,0x00,0xb3,0x01,
 35.2767 +   0xaf,0xaf,0xaf,0xd6,0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,0x03,0xd2,0xd2,0xd2,0xe6,0x7e,0x7e,0x7e,0xc7,0xdc,0xdc,0xdc,0xeb,0xe6,0xe6,0xe6,0xf0,0x81,0xff,
 35.2768 +   0xff,0xff,0xff,0x00,0xef,0xef,0xef,0xf5,0x81,0xdc,0xdc,0xdc,0xeb,0x01,0x00,0x00,0x00,0xb3,0xbb,0xbb,0xbb,0xdc,0x81,0xdc,0xdc,0xdc,0xeb,0x82,0x00,0x00,0x00,0xb3,
 35.2769 +   0x06,0x52,0x52,0x52,0xbd,0xc7,0xc7,0xc7,0xe1,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0xc7,0xc7,0xc7,0xe1,0x52,0x52,0x52,0xbd,0x82,0x00,0x00,
 35.2770 +   0x00,0xb3,0x81,0xdc,0xdc,0xdc,0xeb,0x05,0xbb,0xbb,0xbb,0xdc,0xa0,0xa0,0xa0,0xd1,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,0xeb,0x6a,0x6a,0x6a,0xc2,
 35.2771 +   0x82,0x00,0x00,0x00,0xb3,0x01,0xaf,0xaf,0xaf,0xd6,0xef,0xef,0xef,0xf5,0x81,0xff,0xff,0xff,0xff,0x01,0xd2,0xd2,0xd2,0xe6,0x7e,0x7e,0x7e,0xc7,0xff,0x00,0x00,0x00,
 35.2772 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xbf,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xbf,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,
 35.2773 +   0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,0x00,0xd2,0xd2,0xd2,0xe6,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x9a,0x00,0x00,
 35.2774 +   0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0xa1,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x87,0x00,0x00,0x00,0xb3,
 35.2775 +   0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x8d,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,
 35.2776 +   0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0xa9,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x81,
 35.2777 +   0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0xb1,0x00,0x00,0x00,0xb3,0x01,0x6a,0x6a,0x6a,0xc2,0x52,0x52,0x52,0xbd,0xbe,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,
 35.2778 +   0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x86,0x00,0x00,0x00,0xb3,0x01,0x33,0x33,0x33,0xb8,0x7e,0x7e,0x7e,0xc7,0x95,0x00,0x00,0x00,0xb3,0x81,0xff,
 35.2779 +   0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x9d,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x83,0x00,0x00,0x00,
 35.2780 +   0xb3,0x01,0x7e,0x7e,0x7e,0xc7,0x33,0x33,0x33,0xb8,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xdd,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
 35.2781 +   0x00,0x00,0xb3,0xbf,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xef,0xef,0xef,0xf5,0x81,0xdc,0xdc,0xdc,0xeb,0x00,0xef,0xef,0xef,
 35.2782 +   0xf5,0x82,0xff,0xff,0xff,0xff,0x00,0x6a,0x6a,0x6a,0xc2,0x9a,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0xa1,0x00,0x00,0x00,0xb3,0x81,
 35.2783 +   0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x87,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x8d,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,
 35.2784 +   0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0xa9,0x00,0x00,0x00,0xb3,0x00,0xdc,
 35.2785 +   0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0xb0,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,
 35.2786 +   0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0xbd,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x85,
 35.2787 +   0x00,0x00,0x00,0xb3,0x03,0x33,0x33,0x33,0xb8,0xf7,0xf7,0xf7,0xfa,0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,0xeb,0x94,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,
 35.2788 +   0xdc,0xdc,0xdc,0xeb,0x9d,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,0x03,0xdc,0xdc,
 35.2789 +   0xdc,0xeb,0xff,0xff,0xff,0xff,0xf7,0xf7,0xf7,0xfa,0x33,0x33,0x33,0xb8,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xdc,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
 35.2790 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xbf,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x87,0xff,0xff,0xff,0xff,0x00,0xbb,0xbb,0xbb,0xdc,0x9b,0x00,0x00,0x00,0xb3,
 35.2791 +   0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0xa1,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x87,0x00,0x00,0x00,0xb3,0x00,0xef,
 35.2792 +   0xef,0xef,0xf5,0x81,0xff,0xff,0xff,0xff,0x81,0xbb,0xbb,0xbb,0xdc,0x8b,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,
 35.2793 +   0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0xa9,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0x00,0x00,
 35.2794 +   0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0xb0,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,
 35.2795 +   0xbd,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x85,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0xff,
 35.2796 +   0xff,0xff,0xff,0x94,0x00,0x00,0x00,0xb3,0x81,0x7e,0x7e,0x7e,0xc7,0x00,0x6a,0x6a,0x6a,0xc2,0x9d,0x00,0x00,0x00,0xb3,0x00,0x33,0x33,0x33,0xb8,0x81,0x7e,0x7e,0x7e,
 35.2797 +   0xc7,0x00,0x52,0x52,0x52,0xbd,0x82,0x00,0x00,0x00,0xb3,0x82,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xdc,
 35.2798 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xbf,0x00,0x00,0x00,0xb3,0x00,0x6a,0x6a,0x6a,0xc2,0x85,0xdc,0xdc,0xdc,0xeb,0x01,0xbb,0xbb,
 35.2799 +   0xbb,0xdc,0x7e,0x7e,0x7e,0xc7,0x9c,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0xa1,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,
 35.2800 +   0xdc,0xdc,0xdc,0xeb,0x87,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x83,0xff,0xff,0xff,0xff,0x8b,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,
 35.2801 +   0xdc,0xeb,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x81,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0xa9,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,
 35.2802 +   0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x81,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0xb0,0x00,0x00,0x00,0xb3,0x03,0x90,0x90,0x90,0xcc,0xf7,0xf7,0xf7,0xfa,
 35.2803 +   0xef,0xef,0xef,0xf5,0x52,0x52,0x52,0xbd,0xbd,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x86,0x00,0x00,0x00,
 35.2804 +   0xb3,0x02,0xdc,0xdc,0xdc,0xeb,0xff,0xff,0xff,0xff,0xaf,0xaf,0xaf,0xd6,0xbc,0x00,0x00,0x00,0xb3,0x02,0xaf,0xaf,0xaf,0xd6,0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,0xeb,
 35.2805 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xdd,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xe5,0x00,0x00,0x00,0xb3,0x00,0xa0,
 35.2806 +   0xa0,0xa0,0xd1,0x81,0xaf,0xaf,0xaf,0xd6,0xa1,0x00,0x00,0x00,0xb3,0x81,0xaf,0xaf,0xaf,0xd6,0x00,0xa0,0xa0,0xa0,0xd1,0x88,0x00,0x00,0x00,0xb3,0x01,0xa0,0xa0,0xa0,
 35.2807 +   0xd1,0xd2,0xd2,0xd2,0xe6,0x81,0xdc,0xdc,0xdc,0xeb,0x8b,0x00,0x00,0x00,0xb3,0x81,0xaf,0xaf,0xaf,0xd6,0x02,0xa0,0xa0,0xa0,0xd1,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,
 35.2808 +   0xc7,0x81,0xaf,0xaf,0xaf,0xd6,0x00,0x52,0x52,0x52,0xbd,0xa9,0x00,0x00,0x00,0xb3,0x00,0xa0,0xa0,0xa0,0xd1,0x81,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x81,
 35.2809 +   0xaf,0xaf,0xaf,0xd6,0x00,0xa0,0xa0,0xa0,0xd1,0xf2,0x00,0x00,0x00,0xb3,0x00,0x52,0x52,0x52,0xbd,0x81,0xaf,0xaf,0xaf,0xd6,0x00,0x7e,0x7e,0x7e,0xc7,0xff,0x00,0x00,
 35.2810 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xa7,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
 35.2811 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
 35.2812 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
 35.2813 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
 35.2814 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
 35.2815 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
 35.2816 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
 35.2817 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
 35.2818 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
 35.2819 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
 35.2820 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
 35.2821 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
 35.2822 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
 35.2823 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
 35.2824 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
 35.2825 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
 35.2826 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
 35.2827 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
 35.2828 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
 35.2829 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
 35.2830 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
 35.2831 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
 35.2832 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
 35.2833 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
 35.2834 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
 35.2835 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
 35.2836 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
 35.2837 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
 35.2838 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
 35.2839 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
 35.2840 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
 35.2841 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
 35.2842 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
 35.2843 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
 35.2844 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
 35.2845 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
 35.2846 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
 35.2847 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
 35.2848 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
 35.2849 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
 35.2850 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
 35.2851 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
 35.2852 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
 35.2853 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
 35.2854 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
 35.2855 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
 35.2856 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
 35.2857 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
 35.2858 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
 35.2859 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
 35.2860 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
 35.2861 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
 35.2862 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
 35.2863 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
 35.2864 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xbb,0x00,0x00,0x00,0xb3,0x00,0x6a,0x6a,
 35.2865 +   0x6a,0xc2,0x82,0xaf,0xaf,0xaf,0xd6,0x01,0x90,0x90,0x90,0xcc,0x33,0x33,0x33,0xb8,0x87,0x00,0x00,0x00,0xb3,0x00,0x33,0x33,0x33,0xb8,0x89,0x00,0x00,0x00,0xb3,0x01,
 35.2866 +   0x6a,0x6a,0x6a,0xc2,0xa0,0xa0,0xa0,0xd1,0x82,0xaf,0xaf,0xaf,0xd6,0x00,0x6a,0x6a,0x6a,0xc2,0xff,0x00,0x00,0x00,0xb3,0xcb,0x00,0x00,0x00,0xb3,0x01,0x33,0x33,0x33,
 35.2867 +   0xb8,0x7e,0x7e,0x7e,0xc7,0x83,0xaf,0xaf,0xaf,0xd6,0x01,0x7e,0x7e,0x7e,0xc7,0x52,0x52,0x52,0xbd,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xd0,0x00,0x00,
 35.2868 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xd0,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x86,0x00,0x00,0x00,0xb3,
 35.2869 +   0x00,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,0x8b,0xff,0xff,0xff,0xff,0x02,0x7e,0x7e,0x7e,0xc7,0x00,0x00,
 35.2870 +   0x00,0xb3,0xe6,0xe6,0xe6,0xf0,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x87,0x00,0x00,0x00,0xb3,0x00,0x6a,0x6a,0x6a,0xc2,0x83,0xff,0xff,0xff,0xff,0x01,
 35.2871 +   0x52,0x52,0x52,0xbd,0x00,0x00,0x00,0xb3,0x8a,0xff,0xff,0xff,0xff,0x82,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x86,0x00,0x00,0x00,
 35.2872 +   0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x86,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x8a,
 35.2873 +   0x00,0x00,0x00,0xb3,0x01,0x7e,0x7e,0x7e,0xc7,0xef,0xef,0xef,0xf5,0x84,0xff,0xff,0xff,0xff,0x04,0xf7,0xf7,0xf7,0xfa,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0x6a,
 35.2874 +   0x6a,0x6a,0xc2,0xf7,0xf7,0xf7,0xfa,0x82,0xff,0xff,0xff,0xff,0x00,0xc7,0xc7,0xc7,0xe1,0x88,0x00,0x00,0x00,0xb3,0x01,0x90,0x90,0x90,0xcc,0xe6,0xe6,0xe6,0xf0,0x85,
 35.2875 +   0xff,0xff,0xff,0xff,0x01,0xef,0xef,0xef,0xf5,0x7e,0x7e,0x7e,0xc7,0x82,0x00,0x00,0x00,0xb3,0x00,0xe6,0xe6,0xe6,0xf0,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,
 35.2876 +   0xd6,0x87,0x00,0x00,0x00,0xb3,0x00,0x6a,0x6a,0x6a,0xc2,0x83,0xff,0xff,0xff,0xff,0x02,0x52,0x52,0x52,0xbd,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x82,0xff,0xff,
 35.2877 +   0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x89,0x00,0x00,0x00,0xb3,0x8b,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x84,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,
 35.2878 +   0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x8a,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x91,0x00,0x00,0x00,0xb3,0x82,0xff,
 35.2879 +   0xff,0xff,0xff,0x00,0xc7,0xc7,0xc7,0xe1,0x86,0x00,0x00,0x00,0xb3,0x00,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x00,0xe6,0xe6,0xe6,0xf0,0x83,0x00,0x00,0x00,
 35.2880 +   0xb3,0x00,0x90,0x90,0x90,0xcc,0x82,0xff,0xff,0xff,0xff,0x00,0xf7,0xf7,0xf7,0xfa,0x88,0x00,0x00,0x00,0xb3,0x00,0xd2,0xd2,0xd2,0xe6,0x82,0xff,0xff,0xff,0xff,0x02,
 35.2881 +   0xc7,0xc7,0xc7,0xe1,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x83,0x00,0x00,0x00,0xb3,0x01,0x33,0x33,0x33,0xb8,
 35.2882 +   0xf7,0xf7,0xf7,0xfa,0x82,0xff,0xff,0xff,0xff,0x02,0xd2,0xd2,0xd2,0xe6,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,
 35.2883 +   0x85,0x00,0x00,0x00,0xb3,0x01,0x33,0x33,0x33,0xb8,0xf7,0xf7,0xf7,0xfa,0x83,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,
 35.2884 +   0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x86,0x00,0x00,0x00,0xb3,
 35.2885 +   0x00,0xaf,0xaf,0xaf,0xd6,0x84,0xff,0xff,0xff,0xff,0x85,0x00,0x00,0x00,0xb3,0x01,0x52,0x52,0x52,0xbd,0xc7,0xc7,0xc7,0xe1,0x87,0xff,0xff,0xff,0xff,0x02,0xef,0xef,
 35.2886 +   0xef,0xf5,0xbb,0xbb,0xbb,0xdc,0x52,0x52,0x52,0xbd,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xcd,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
 35.2887 +   0x00,0x00,0xb3,0xd0,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x86,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,
 35.2888 +   0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,0x8b,0xff,0xff,0xff,0xff,0x02,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0xa0,0xa0,0xa0,0xd1,0x82,0xff,0xff,
 35.2889 +   0xff,0xff,0x00,0xe6,0xe6,0xe6,0xf0,0x87,0x00,0x00,0x00,0xb3,0x00,0xc7,0xc7,0xc7,0xe1,0x82,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,
 35.2890 +   0x8a,0xff,0xff,0xff,0xff,0x82,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x86,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0xff,
 35.2891 +   0xff,0xff,0xff,0x86,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x89,0x00,0x00,0x00,0xb3,0x00,0x90,0x90,0x90,
 35.2892 +   0xcc,0x88,0xff,0xff,0xff,0xff,0x01,0xd2,0xd2,0xd2,0xe6,0xe6,0xe6,0xe6,0xf0,0x82,0xff,0xff,0xff,0xff,0x00,0xe6,0xe6,0xe6,0xf0,0x88,0x00,0x00,0x00,0xb3,0x00,0xaf,
 35.2893 +   0xaf,0xaf,0xd6,0x89,0xff,0xff,0xff,0xff,0x00,0xa0,0xa0,0xa0,0xd1,0x81,0x00,0x00,0x00,0xb3,0x00,0xa0,0xa0,0xa0,0xd1,0x82,0xff,0xff,0xff,0xff,0x00,0xe6,0xe6,0xe6,
 35.2894 +   0xf0,0x87,0x00,0x00,0x00,0xb3,0x00,0xc7,0xc7,0xc7,0xe1,0x82,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x82,
 35.2895 +   0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x89,0x00,0x00,0x00,0xb3,0x8b,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x84,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,
 35.2896 +   0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x8a,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x90,0x00,0x00,0x00,0xb3,
 35.2897 +   0x00,0x90,0x90,0x90,0xcc,0x82,0xff,0xff,0xff,0xff,0x00,0xf7,0xf7,0xf7,0xfa,0x85,0x00,0x00,0x00,0xb3,0x00,0x6a,0x6a,0x6a,0xc2,0x83,0xff,0xff,0xff,0xff,0x00,0x52,
 35.2898 +   0x52,0x52,0xbd,0x83,0x00,0x00,0x00,0xb3,0x00,0xef,0xef,0xef,0xf5,0x82,0xff,0xff,0xff,0xff,0x00,0x90,0x90,0x90,0xcc,0x86,0x00,0x00,0x00,0xb3,0x00,0x52,0x52,0x52,
 35.2899 +   0xbd,0x83,0xff,0xff,0xff,0xff,0x02,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x83,0x00,0x00,
 35.2900 +   0x00,0xb3,0x00,0xbb,0xbb,0xbb,0xdc,0x82,0xff,0xff,0xff,0xff,0x03,0xf7,0xf7,0xf7,0xfa,0x33,0x33,0x33,0xb8,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,
 35.2901 +   0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x85,0x00,0x00,0x00,0xb3,0x00,0xbb,0xbb,0xbb,0xdc,0x84,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,
 35.2902 +   0x00,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x85,0x00,
 35.2903 +   0x00,0x00,0xb3,0x01,0x52,0x52,0x52,0xbd,0xf7,0xf7,0xf7,0xfa,0x84,0xff,0xff,0xff,0xff,0x84,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x8c,0xff,0xff,0xff,0xff,
 35.2904 +   0x00,0x6a,0x6a,0x6a,0xc2,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xcc,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xd0,0x00,
 35.2905 +   0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x86,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,
 35.2906 +   0xd6,0x82,0x00,0x00,0x00,0xb3,0x8b,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x00,0xf7,0xf7,0xf7,0xfa,0x82,0xff,0xff,0xff,0xff,0x00,
 35.2907 +   0x6a,0x6a,0x6a,0xc2,0x85,0x00,0x00,0x00,0xb3,0x01,0x33,0x33,0x33,0xb8,0xf7,0xf7,0xf7,0xfa,0x82,0xff,0xff,0xff,0xff,0x00,0x90,0x90,0x90,0xcc,0x81,0x00,0x00,0x00,
 35.2908 +   0xb3,0x8a,0xff,0xff,0xff,0xff,0x82,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x86,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x82,
 35.2909 +   0xff,0xff,0xff,0xff,0x86,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x88,0x00,0x00,0x00,0xb3,0x01,0x33,0x33,
 35.2910 +   0x33,0xb8,0xf7,0xf7,0xf7,0xfa,0x83,0xff,0xff,0xff,0xff,0x01,0xdc,0xdc,0xdc,0xeb,0xe6,0xe6,0xe6,0xf0,0x86,0xff,0xff,0xff,0xff,0x01,0xe6,0xe6,0xe6,0xf0,0x33,0x33,
 35.2911 +   0x33,0xb8,0x88,0x00,0x00,0x00,0xb3,0x01,0x52,0x52,0x52,0xbd,0xf7,0xf7,0xf7,0xfa,0x88,0xff,0xff,0xff,0xff,0x01,0xf7,0xf7,0xf7,0xfa,0x52,0x52,0x52,0xbd,0x81,0x00,
 35.2912 +   0x00,0x00,0xb3,0x00,0xf7,0xf7,0xf7,0xfa,0x82,0xff,0xff,0xff,0xff,0x00,0x6a,0x6a,0x6a,0xc2,0x85,0x00,0x00,0x00,0xb3,0x01,0x33,0x33,0x33,0xb8,0xf7,0xf7,0xf7,0xfa,
 35.2913 +   0x82,0xff,0xff,0xff,0xff,0x00,0x90,0x90,0x90,0xcc,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x89,0x00,
 35.2914 +   0x00,0x00,0xb3,0x8b,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x84,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,
 35.2915 +   0xd6,0x8a,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x90,0x00,0x00,0x00,0xb3,0x00,0xbb,0xbb,0xbb,0xdc,0x83,0xff,0xff,0xff,0xff,0x00,
 35.2916 +   0x7e,0x7e,0x7e,0xc7,0x84,0x00,0x00,0x00,0xb3,0x00,0xbb,0xbb,0xbb,0xdc,0x83,0xff,0xff,0xff,0xff,0x00,0xa0,0xa0,0xa0,0xd1,0x83,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,
 35.2917 +   0xaf,0xd6,0x82,0xff,0xff,0xff,0xff,0x00,0xd2,0xd2,0xd2,0xe6,0x86,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0xff,0xff,0xff,0xff,0x00,0xe6,0xe6,0xe6,0xf0,
 35.2918 +   0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,0x00,0x52,0x52,0x52,0xbd,0x83,0xff,
 35.2919 +   0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x84,0x00,0x00,0x00,
 35.2920 +   0xb3,0x00,0x6a,0x6a,0x6a,0xc2,0x85,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x00,
 35.2921 +   0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x85,0x00,0x00,0x00,0xb3,0x00,0xd2,0xd2,0xd2,0xe6,0x85,0xff,0xff,
 35.2922 +   0xff,0xff,0x83,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x8d,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
 35.2923 +   0xcc,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xd0,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x86,0x00,
 35.2924 +   0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,0x82,0xff,0xff,0xff,0xff,0x00,0xef,0xef,0xef,
 35.2925 +   0xf5,0x87,0xaf,0xaf,0xaf,0xd6,0x00,0x52,0x52,0x52,0xbd,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0xff,0xff,0xff,0xff,0x00,0xd2,0xd2,0xd2,0xe6,0x85,
 35.2926 +   0x7e,0x7e,0x7e,0xc7,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0xff,0xff,0xff,0xff,0x00,0xef,0xef,0xef,0xf5,0x82,0x00,0x00,0x00,0xb3,0x82,0xff,0xff,0xff,0xff,0x00,0xef,0xef,
 35.2927 +   0xef,0xf5,0x86,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x86,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,
 35.2928 +   0x82,0xff,0xff,0xff,0xff,0x86,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x88,0x00,0x00,0x00,0xb3,0x00,0xa0,
 35.2929 +   0xa0,0xa0,0xd1,0x82,0xff,0xff,0xff,0xff,0x01,0xf7,0xf7,0xf7,0xfa,0x6a,0x6a,0x6a,0xc2,0x81,0x00,0x00,0x00,0xb3,0x01,0x7e,0x7e,0x7e,0xc7,0xef,0xef,0xef,0xf5,0x83,
 35.2930 +   0xff,0xff,0xff,0xff,0x01,0xe6,0xe6,0xe6,0xf0,0x33,0x33,0x33,0xb8,0x8a,0x00,0x00,0x00,0xb3,0x00,0x6a,0x6a,0x6a,0xc2,0x81,0xf7,0xf7,0xf7,0xfa,0x04,0xa0,0xa0,0xa0,
 35.2931 +   0xd1,0x33,0x33,0x33,0xb8,0x00,0x00,0x00,0xb3,0x6a,0x6a,0x6a,0xc2,0xd2,0xd2,0xd2,0xe6,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,
 35.2932 +   0x00,0xaf,0xaf,0xaf,0xd6,0x82,0xff,0xff,0xff,0xff,0x00,0xd2,0xd2,0xd2,0xe6,0x85,0x7e,0x7e,0x7e,0xc7,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0xff,0xff,0xff,0xff,0x00,0xef,
 35.2933 +   0xef,0xef,0xf5,0x82,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x89,0x00,0x00,0x00,0xb3,0x82,0xff,0xff,0xff,
 35.2934 +   0xff,0x00,0xef,0xef,0xef,0xf5,0x87,0xaf,0xaf,0xaf,0xd6,0x00,0x52,0x52,0x52,0xbd,0x84,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x00,
 35.2935 +   0xaf,0xaf,0xaf,0xd6,0x8a,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x90,0x00,0x00,0x00,0xb3,0x00,0xef,0xef,0xef,0xf5,0x83,0xff,0xff,
 35.2936 +   0xff,0xff,0x00,0xbb,0xbb,0xbb,0xdc,0x84,0x00,0x00,0x00,0xb3,0x00,0xef,0xef,0xef,0xf5,0x83,0xff,0xff,0xff,0xff,0x00,0xd2,0xd2,0xd2,0xe6,0x83,0x00,0x00,0x00,0xb3,
 35.2937 +   0x01,0x33,0x33,0x33,0xb8,0xf7,0xf7,0xf7,0xfa,0x82,0xff,0xff,0xff,0xff,0x00,0x90,0x90,0x90,0xcc,0x85,0x7e,0x7e,0x7e,0xc7,0x00,0xef,0xef,0xef,0xf5,0x82,0xff,0xff,
 35.2938 +   0xff,0xff,0x00,0xa0,0xa0,0xa0,0xd1,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,
 35.2939 +   0x00,0xc7,0xc7,0xc7,0xe1,0x82,0xff,0xff,0xff,0xff,0x00,0xe6,0xe6,0xe6,0xf0,0x82,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,
 35.2940 +   0xaf,0xaf,0xd6,0x84,0x00,0x00,0x00,0xb3,0x00,0xe6,0xe6,0xe6,0xf0,0x85,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,
 35.2941 +   0xc7,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x84,0x00,0x00,0x00,0xb3,0x00,
 35.2942 +   0x90,0x90,0x90,0xcc,0x86,0xff,0xff,0xff,0xff,0x82,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x83,0xff,0xff,0xff,0xff,0x02,0xf7,0xf7,0xf7,0xfa,0xaf,0xaf,0xaf,
 35.2943 +   0xd6,0x52,0x52,0x52,0xbd,0x81,0x00,0x00,0x00,0xb3,0x02,0x6a,0x6a,0x6a,0xc2,0xaf,0xaf,0xaf,0xd6,0xef,0xef,0xef,0xf5,0x82,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,
 35.2944 +   0xc7,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xcc,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xd0,0x00,0x00,0x00,0xb3,0x00,
 35.2945 +   0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x86,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,
 35.2946 +   0x00,0xb3,0x82,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x8a,0x00,0x00,0x00,0xb3,0x00,0x52,0x52,0x52,0xbd,0x8d,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,
 35.2947 +   0x82,0x00,0x00,0x00,0xb3,0x82,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x89,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x86,0x00,
 35.2948 +   0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x86,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,
 35.2949 +   0xd6,0x88,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0xff,0xff,0xff,0xff,0x00,0xbb,0xbb,0xbb,0xdc,0x82,0x00,0x00,0x00,0xb3,0x01,0x33,0x33,0x33,0xb8,0xe6,
 35.2950 +   0xe6,0xe6,0xf0,0x83,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x8c,0x00,0x00,0x00,0xb3,0x01,0x7e,0x7e,0x7e,0xc7,0x6a,0x6a,0x6a,0xc2,0x83,0x00,0x00,0x00,0xb3,
 35.2951 +   0x00,0x33,0x33,0x33,0xb8,0x82,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x00,0x52,0x52,0x52,0xbd,0x8d,0xff,0xff,0xff,0xff,0x00,0xaf,
 35.2952 +   0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x89,0x00,0x00,0x00,0xb3,0x82,0xff,0xff,0xff,
 35.2953 +   0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x8d,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x8a,0x00,0x00,0x00,0xb3,0x00,
 35.2954 +   0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x8f,0x00,0x00,0x00,0xb3,0x00,0x6a,0x6a,0x6a,0xc2,0x84,0xff,0xff,0xff,0xff,0x00,0xef,0xef,0xef,0xf5,0x83,0x00,0x00,
 35.2955 +   0x00,0xb3,0x00,0x6a,0x6a,0x6a,0xc2,0x84,0xff,0xff,0xff,0xff,0x00,0xf7,0xf7,0xf7,0xfa,0x84,0x00,0x00,0x00,0xb3,0x00,0xc7,0xc7,0xc7,0xe1,0x8c,0xff,0xff,0xff,0xff,
 35.2956 +   0x00,0xf7,0xf7,0xf7,0xfa,0x82,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0x6a,
 35.2957 +   0x6a,0x6a,0xc2,0x83,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,
 35.2958 +   0xd6,0x83,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x86,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x82,
 35.2959 +   0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x83,0x00,0x00,0x00,0xb3,0x01,0x33,0x33,
 35.2960 +   0x33,0xb8,0xef,0xef,0xef,0xf5,0x86,0xff,0xff,0xff,0xff,0x82,0x00,0x00,0x00,0xb3,0x00,0xe6,0xe6,0xe6,0xf0,0x82,0xff,0xff,0xff,0xff,0x01,0xe6,0xe6,0xe6,0xf0,0x33,
 35.2961 +   0x33,0x33,0xb8,0x85,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
 35.2962 +   0xb3,0xcc,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xd0,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x86,
 35.2963 +   0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,0x82,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,
 35.2964 +   0xdc,0xeb,0x8b,0x00,0x00,0x00,0xb3,0x00,0xc7,0xc7,0xc7,0xe1,0x8b,0xff,0xff,0xff,0xff,0x01,0xf7,0xf7,0xf7,0xfa,0x33,0x33,0x33,0xb8,0x82,0x00,0x00,0x00,0xb3,0x82,
 35.2965 +   0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x89,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x86,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,
 35.2966 +   0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x86,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x88,0x00,0x00,0x00,0xb3,
 35.2967 +   0x00,0xaf,0xaf,0xaf,0xd6,0x82,0xff,0xff,0xff,0xff,0x00,0xbb,0xbb,0xbb,0xdc,0x82,0x00,0x00,0x00,0xb3,0x00,0xd2,0xd2,0xd2,0xe6,0x85,0xff,0xff,0xff,0xff,0x00,0x7e,
 35.2968 +   0x7e,0x7e,0xc7,0x91,0x00,0x00,0x00,0xb3,0x00,0x52,0x52,0x52,0xbd,0x82,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0x00,0x00,0x00,0xb3,0x00,0xc7,0xc7,0xc7,
 35.2969 +   0xe1,0x8b,0xff,0xff,0xff,0xff,0x01,0xf7,0xf7,0xf7,0xfa,0x33,0x33,0x33,0xb8,0x82,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0xff,0xff,0xff,0xff,0x00,0x7e,
 35.2970 +   0x7e,0x7e,0xc7,0x89,0x00,0x00,0x00,0xb3,0x82,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x8d,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,
 35.2971 +   0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x8a,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x8f,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x85,
 35.2972 +   0xff,0xff,0xff,0xff,0x00,0x6a,0x6a,0x6a,0xc2,0x82,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x85,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x83,0x00,0x00,
 35.2973 +   0x00,0xb3,0x00,0x52,0x52,0x52,0xbd,0x8c,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,
 35.2974 +   0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x00,0xc7,0xc7,0xc7,0xe1,0x83,0x00,0x00,0x00,0xb3,0x00,0x7e,
 35.2975 +   0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,0x01,0x33,0x33,0x33,0xb8,0xf7,0xf7,0xf7,0xfa,0x82,0xff,0xff,0xff,0xff,
 35.2976 +   0x00,0xef,0xef,0xef,0xf5,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,
 35.2977 +   0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x83,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x83,0xff,0xff,0xff,
 35.2978 +   0xff,0x00,0xef,0xef,0xef,0xf5,0x82,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0x6a,0x6a,0x6a,0xc2,0x83,0xff,0xff,0xff,0xff,0x00,0x6a,0x6a,0x6a,0xc2,0x86,
 35.2979 +   0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xcc,0x00,0x00,
 35.2980 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xd0,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x86,0x00,0x00,0x00,0xb3,
 35.2981 +   0x00,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,0x82,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x8b,0x00,
 35.2982 +   0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x8b,0xff,0xff,0xff,0xff,0x00,0xc7,0xc7,0xc7,0xe1,0x83,0x00,0x00,0x00,0xb3,0x82,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,
 35.2983 +   0xeb,0x89,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x86,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x86,
 35.2984 +   0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x88,0x00,0x00,0x00,0xb3,0x00,0x6a,0x6a,0x6a,0xc2,0x82,0xff,0xff,
 35.2985 +   0xff,0xff,0x03,0xf7,0xf7,0xf7,0xfa,0x6a,0x6a,0x6a,0xc2,0x00,0x00,0x00,0xb3,0xc7,0xc7,0xc7,0xe1,0x82,0xff,0xff,0xff,0xff,0x00,0xf7,0xf7,0xf7,0xfa,0x82,0xff,0xff,
 35.2986 +   0xff,0xff,0x01,0xf7,0xf7,0xf7,0xfa,0x33,0x33,0x33,0xb8,0x8f,0x00,0x00,0x00,0xb3,0x01,0xa0,0xa0,0xa0,0xd1,0xef,0xef,0xef,0xf5,0x82,0xff,0xff,0xff,0xff,0x00,0xd2,
 35.2987 +   0xd2,0xd2,0xe6,0x82,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x8b,0xff,0xff,0xff,0xff,0x00,0xc7,0xc7,0xc7,0xe1,0x83,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,
 35.2988 +   0xd6,0x82,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x89,0x00,0x00,0x00,0xb3,0x82,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x8d,0x00,0x00,0x00,0xb3,0x00,
 35.2989 +   0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x8a,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x8f,0x00,0x00,
 35.2990 +   0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x81,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,
 35.2991 +   0x00,0xe6,0xe6,0xe6,0xf0,0x81,0xff,0xff,0xff,0xff,0x01,0xe6,0xe6,0xe6,0xf0,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x00,0xbb,0xbb,0xbb,0xdc,0x84,0x00,0x00,
 35.2992 +   0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x8b,0xff,0xff,0xff,0xff,0x00,0x52,0x52,0x52,0xbd,0x82,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,
 35.2993 +   0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x01,0xf7,0xf7,0xf7,0xfa,0x33,0x33,0x33,0xb8,0x83,0x00,0x00,0x00,0xb3,
 35.2994 +   0x00,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,0x00,0xd2,0xd2,0xd2,0xe6,0x82,0xff,0xff,0xff,0xff,0x01,0xf7,
 35.2995 +   0xf7,0xf7,0xfa,0x90,0x90,0x90,0xcc,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,
 35.2996 +   0x00,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x82,0x00,0x00,0x00,0xb3,0x00,0x6a,0x6a,0x6a,0xc2,0x83,0xff,
 35.2997 +   0xff,0xff,0xff,0x01,0xaf,0xaf,0xaf,0xd6,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0xff,0xff,0xff,0xff,
 35.2998 +   0x00,0xc7,0xc7,0xc7,0xe1,0x87,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
 35.2999 +   0x00,0x00,0xb3,0xcc,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xd0,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,
 35.3000 +   0xff,0x86,0x7e,0x7e,0x7e,0xc7,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,0x82,0xff,0xff,0xff,0xff,0x00,
 35.3001 +   0xf7,0xf7,0xf7,0xfa,0x86,0xdc,0xdc,0xdc,0xeb,0x00,0x6a,0x6a,0x6a,0xc2,0x84,0x00,0x00,0x00,0xb3,0x00,0xef,0xef,0xef,0xf5,0x82,0xff,0xff,0xff,0xff,0x00,0x52,0x52,
 35.3002 +   0x52,0xbd,0x81,0x00,0x00,0x00,0xb3,0x01,0x33,0x33,0x33,0xb8,0xf7,0xf7,0xf7,0xfa,0x82,0xff,0xff,0xff,0xff,0x00,0x52,0x52,0x52,0xbd,0x83,0x00,0x00,0x00,0xb3,0x82,
 35.3003 +   0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x89,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x86,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,
 35.3004 +   0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x86,0x7e,0x7e,0x7e,0xc7,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x89,0x00,0x00,0x00,0xb3,
 35.3005 +   0x00,0xd2,0xd2,0xd2,0xe6,0x83,0xff,0xff,0xff,0xff,0x00,0xe6,0xe6,0xe6,0xf0,0x83,0xff,0xff,0xff,0xff,0x01,0xa0,0xa0,0xa0,0xd1,0xbb,0xbb,0xbb,0xdc,0x82,0xff,0xff,
 35.3006 +   0xff,0xff,0x00,0xd2,0xd2,0xd2,0xe6,0x8c,0x00,0x00,0x00,0xb3,0x02,0x90,0x90,0x90,0xcc,0xc7,0xc7,0xc7,0xe1,0xf7,0xf7,0xf7,0xfa,0x84,0xff,0xff,0xff,0xff,0x00,0xa0,
 35.3007 +   0xa0,0xa0,0xd1,0x83,0x00,0x00,0x00,0xb3,0x00,0xef,0xef,0xef,0xf5,0x82,0xff,0xff,0xff,0xff,0x00,0x52,0x52,0x52,0xbd,0x81,0x00,0x00,0x00,0xb3,0x01,0x33,0x33,0x33,
 35.3008 +   0xb8,0xf7,0xf7,0xf7,0xfa,0x82,0xff,0xff,0xff,0xff,0x00,0x52,0x52,0x52,0xbd,0x83,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x89,0xff,0xff,0xff,0xff,0x00,0xaf,
 35.3009 +   0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,0x82,0xff,0xff,0xff,0xff,0x00,0xf7,0xf7,0xf7,0xfa,0x86,0xdc,0xdc,0xdc,0xeb,0x00,0x6a,0x6a,0x6a,0xc2,0x85,0x00,0x00,0x00,
 35.3010 +   0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x8a,0x00,0x00,0x00,0xb3,0x00,0xe6,0xe6,0xe6,0xf0,0x82,0xff,0xff,0xff,0xff,0x00,
 35.3011 +   0x33,0x33,0x33,0xb8,0x8d,0x00,0x00,0x00,0xb3,0x00,0x33,0x33,0x33,0xb8,0x82,0xff,0xff,0xff,0xff,0x01,0xd2,0xd2,0xd2,0xe6,0xc7,0xc7,0xc7,0xe1,0x81,0xff,0xff,0xff,
 35.3012 +   0xff,0x00,0xe6,0xe6,0xe6,0xf0,0x81,0x00,0x00,0x00,0xb3,0x00,0x52,0x52,0x52,0xbd,0x82,0xff,0xff,0xff,0xff,0x01,0xaf,0xaf,0xaf,0xd6,0xd2,0xd2,0xd2,0xe6,0x81,0xff,
 35.3013 +   0xff,0xff,0xff,0x00,0xef,0xef,0xef,0xf5,0x84,0x00,0x00,0x00,0xb3,0x00,0xa0,0xa0,0xa0,0xd1,0x82,0xff,0xff,0xff,0xff,0x00,0xc7,0xc7,0xc7,0xe1,0x82,0x00,0x00,0x00,
 35.3014 +   0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0xff,0xff,0xff,0xff,0x00,0xc7,0xc7,0xc7,0xe1,0x83,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x88,0xff,0xff,0xff,0xff,0x01,
 35.3015 +   0xe6,0xe6,0xe6,0xf0,0x90,0x90,0x90,0xcc,0x83,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,
 35.3016 +   0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x83,0xff,0xff,0xff,0xff,0x01,0xaf,0xaf,0xaf,0xd6,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,
 35.3017 +   0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,
 35.3018 +   0xff,0x82,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x02,0xef,0xef,0xef,0xf5,0x33,0x33,0x33,0xb8,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,
 35.3019 +   0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0xd2,0xd2,0xd2,0xe6,0x82,0xff,0xff,0xff,0xff,0x00,0xa0,0xa0,0xa0,0xd1,0x84,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,
 35.3020 +   0x85,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xcc,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
 35.3021 +   0x00,0x00,0xb3,0xd0,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x8d,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,0x8a,0xff,0xff,0xff,
 35.3022 +   0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x84,0x00,0x00,0x00,0xb3,0x00,0xa0,0xa0,0xa0,0xd1,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,
 35.3023 +   0xa0,0xa0,0xa0,0xd1,0x82,0xff,0xff,0xff,0xff,0x00,0xd2,0xd2,0xd2,0xe6,0x84,0x00,0x00,0x00,0xb3,0x82,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x89,0x00,0x00,
 35.3024 +   0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x86,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x8d,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,
 35.3025 +   0x89,0x00,0x00,0x00,0xb3,0x01,0x33,0x33,0x33,0xb8,0xe6,0xe6,0xe6,0xf0,0x86,0xff,0xff,0xff,0xff,0x00,0xa0,0xa0,0xa0,0xd1,0x81,0x00,0x00,0x00,0xb3,0x00,0xe6,0xe6,
 35.3026 +   0xe6,0xf0,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x89,0x00,0x00,0x00,0xb3,0x01,0x90,0x90,0x90,0xcc,0xef,0xef,0xef,0xf5,0x86,0xff,0xff,0xff,0xff,0x00,
 35.3027 +   0xc7,0xc7,0xc7,0xe1,0x84,0x00,0x00,0x00,0xb3,0x00,0xa0,0xa0,0xa0,0xd1,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0xa0,0xa0,
 35.3028 +   0xa0,0xd1,0x82,0xff,0xff,0xff,0xff,0x00,0xd2,0xd2,0xd2,0xe6,0x84,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x89,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,
 35.3029 +   0x82,0x00,0x00,0x00,0xb3,0x8a,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x85,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,
 35.3030 +   0xaf,0xaf,0xd6,0x89,0x00,0x00,0x00,0xb3,0x00,0x90,0x90,0x90,0xcc,0x83,0xff,0xff,0xff,0xff,0x00,0xbb,0xbb,0xbb,0xdc,0x8d,0x00,0x00,0x00,0xb3,0x00,0xa0,0xa0,0xa0,
 35.3031 +   0xd1,0x82,0xff,0xff,0xff,0xff,0x01,0xaf,0xaf,0xaf,0xd6,0x90,0x90,0x90,0xcc,0x82,0xff,0xff,0xff,0xff,0x02,0x52,0x52,0x52,0xbd,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,
 35.3032 +   0xd6,0x82,0xff,0xff,0xff,0xff,0x01,0x52,0x52,0x52,0xbd,0xaf,0xaf,0xaf,0xd6,0x82,0xff,0xff,0xff,0xff,0x00,0x52,0x52,0x52,0xbd,0x84,0x00,0x00,0x00,0xb3,0x00,0xef,
 35.3033 +   0xef,0xef,0xf5,0x81,0xff,0xff,0xff,0xff,0x01,0xf7,0xf7,0xf7,0xfa,0x33,0x33,0x33,0xb8,0x81,0x00,0x00,0x00,0xb3,0x00,0xef,0xef,0xef,0xf5,0x82,0xff,0xff,0xff,0xff,
 35.3034 +   0x00,0x6a,0x6a,0x6a,0xc2,0x83,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x8a,0xff,0xff,0xff,0xff,0x01,0xdc,0xdc,0xdc,0xeb,0x33,0x33,0x33,0xb8,0x81,0x00,0x00,
 35.3035 +   0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x03,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0x33,0x33,0x33,0xb8,0xef,0xef,0xef,0xf5,0x82,0xff,0xff,
 35.3036 +   0xff,0xff,0x02,0xe6,0xe6,0xe6,0xf0,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,
 35.3037 +   0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,
 35.3038 +   0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x83,0xff,0xff,0xff,0xff,0x02,0x90,0x90,0x90,0xcc,0x00,0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x81,0x00,0x00,
 35.3039 +   0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x84,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x85,0xff,0xff,0xff,0xff,
 35.3040 +   0x00,0x7e,0x7e,0x7e,0xc7,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xcc,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xd0,0x00,
 35.3041 +   0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x8d,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,0x8a,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,
 35.3042 +   0xc7,0x84,0x00,0x00,0x00,0xb3,0x01,0x33,0x33,0x33,0xb8,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x00,0xef,0xef,0xef,0xf5,0x81,0x00,0x00,0x00,0xb3,0x00,0xe6,
 35.3043 +   0xe6,0xe6,0xf0,0x82,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x84,0x00,0x00,0x00,0xb3,0x82,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x89,0x00,0x00,0x00,
 35.3044 +   0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x86,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x8d,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x8b,
 35.3045 +   0x00,0x00,0x00,0xb3,0x00,0xa0,0xa0,0xa0,0xd1,0x84,0xff,0xff,0xff,0xff,0x01,0xf7,0xf7,0xf7,0xfa,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x00,0x52,0x52,0x52,
 35.3046 +   0xbd,0x83,0x7e,0x7e,0x7e,0xc7,0x88,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x86,0xff,0xff,0xff,0xff,0x01,0xf7,0xf7,0xf7,0xfa,0xaf,0xaf,0xaf,0xd6,0x85,0x00,
 35.3047 +   0x00,0x00,0xb3,0x01,0x33,0x33,0x33,0xb8,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x00,0xef,0xef,0xef,0xf5,0x81,0x00,0x00,0x00,0xb3,0x00,0xe6,0xe6,0xe6,0xf0,
 35.3048 +   0x82,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x84,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x89,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0x00,
 35.3049 +   0x00,0x00,0xb3,0x8a,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x85,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,
 35.3050 +   0xd6,0x88,0x00,0x00,0x00,0xb3,0x01,0x33,0x33,0x33,0xb8,0xf7,0xf7,0xf7,0xfa,0x84,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x8c,0x00,0x00,0x00,0xb3,0x00,0xc7,
 35.3051 +   0xc7,0xc7,0xe1,0x82,0xff,0xff,0xff,0xff,0x02,0x6a,0x6a,0x6a,0xc2,0x00,0x00,0x00,0xb3,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,
 35.3052 +   0x00,0x00,0xb3,0xdc,0xdc,0xdc,0xeb,0x81,0xff,0xff,0xff,0xff,0x02,0xe6,0xe6,0xe6,0xf0,0x00,0x00,0x00,0xb3,0x6a,0x6a,0x6a,0xc2,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,
 35.3053 +   0xaf,0xaf,0xd6,0x84,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0xff,0xff,0xff,0xff,0x02,0xa0,0xa0,0xa0,0xd1,0x00,0x00,0x00,0xb3,0x90,0x90,0x90,0xcc,0x82,
 35.3054 +   0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x84,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x8b,0xff,0xff,0xff,0xff,0x00,0xbb,0xbb,0xbb,0xdc,0x81,0x00,0x00,
 35.3055 +   0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xaf,0xaf,0xaf,0xd6,0x83,0xff,0xff,0xff,0xff,0x02,0x6a,
 35.3056 +   0x6a,0x6a,0xc2,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x82,
 35.3057 +   0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x02,0x00,0x00,0x00,0xb3,0x33,0x33,0x33,
 35.3058 +   0xb8,0xf7,0xf7,0xf7,0xfa,0x82,0xff,0xff,0xff,0xff,0x00,0xd2,0xd2,0xd2,0xe6,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x81,0x00,
 35.3059 +   0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x84,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x85,0xff,0xff,0xff,
 35.3060 +   0xff,0x00,0x7e,0x7e,0x7e,0xc7,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xcc,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xd0,
 35.3061 +   0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x8d,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,0x82,0xff,0xff,0xff,0xff,0x00,0xf7,0xf7,
 35.3062 +   0xf7,0xfa,0x86,0xdc,0xdc,0xdc,0xeb,0x00,0x6a,0x6a,0x6a,0xc2,0x85,0x00,0x00,0x00,0xb3,0x00,0xbb,0xbb,0xbb,0xdc,0x82,0xff,0xff,0xff,0xff,0x01,0x7e,0x7e,0x7e,0xc7,
 35.3063 +   0x6a,0x6a,0x6a,0xc2,0x82,0xff,0xff,0xff,0xff,0x00,0xef,0xef,0xef,0xf5,0x85,0x00,0x00,0x00,0xb3,0x82,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x89,0x00,0x00,
 35.3064 +   0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x86,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x8d,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,
 35.3065 +   0x8b,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x86,0xff,0xff,0xff,0xff,0x00,0xa0,0xa0,0xa0,0xd1,0x8d,0x00,0x00,0x00,0xb3,0x00,0x52,0x52,0x52,0xbd,0x84,0xff,
 35.3066 +   0xff,0xff,0xff,0x03,0xf7,0xf7,0xf7,0xfa,0xc7,0xc7,0xc7,0xe1,0x90,0x90,0x90,0xcc,0x33,0x33,0x33,0xb8,0x87,0x00,0x00,0x00,0xb3,0x00,0xbb,0xbb,0xbb,0xdc,0x82,0xff,
 35.3067 +   0xff,0xff,0xff,0x01,0x7e,0x7e,0x7e,0xc7,0x6a,0x6a,0x6a,0xc2,0x82,0xff,0xff,0xff,0xff,0x00,0xef,0xef,0xef,0xf5,0x85,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,
 35.3068 +   0x82,0xff,0xff,0xff,0xff,0x00,0xc7,0xc7,0xc7,0xe1,0x85,0xaf,0xaf,0xaf,0xd6,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0x00,0x00,0x00,0xb3,0x82,0xff,0xff,0xff,0xff,0x00,0xf7,
 35.3069 +   0xf7,0xf7,0xfa,0x86,0xdc,0xdc,0xdc,0xeb,0x00,0x6a,0x6a,0x6a,0xc2,0x85,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,
 35.3070 +   0xd6,0x88,0x00,0x00,0x00,0xb3,0x00,0xd2,0xd2,0xd2,0xe6,0x85,0xff,0xff,0xff,0xff,0x01,0xef,0xef,0xef,0xf5,0x33,0x33,0x33,0xb8,0x8b,0x00,0x00,0x00,0xb3,0x00,0xf7,
 35.3071 +   0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x00,0xf7,0xf7,0xf7,0xfa,0x81,0x00,0x00,0x00,0xb3,0x00,0xd2,0xd2,0xd2,0xe6,0x81,0xff,0xff,0xff,0xff,0x01,0xe6,0xe6,0xe6,
 35.3072 +   0xf0,0x33,0x33,0x33,0xb8,0x82,0xff,0xff,0xff,0xff,0x00,0xbb,0xbb,0xbb,0xdc,0x81,0x00,0x00,0x00,0xb3,0x00,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x00,0xd2,
 35.3073 +   0xd2,0xd2,0xe6,0x84,0x00,0x00,0x00,0xb3,0x00,0x33,0x33,0x33,0xb8,0x82,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0xd2,0xd2,0xd2,0xe6,0x82,
 35.3074 +   0xff,0xff,0xff,0xff,0x00,0xa0,0xa0,0xa0,0xd1,0x84,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x00,0xc7,0xc7,0xc7,0xe1,0x82,0x7e,0x7e,
 35.3075 +   0x7e,0xc7,0x01,0x90,0x90,0x90,0xcc,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x00,0xf7,0xf7,0xf7,0xfa,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x82,
 35.3076 +   0xff,0xff,0xff,0xff,0x01,0xaf,0xaf,0xaf,0xd6,0x52,0x52,0x52,0xbd,0x83,0xff,0xff,0xff,0xff,0x00,0xbb,0xbb,0xbb,0xdc,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,
 35.3077 +   0xc7,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,
 35.3078 +   0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0xb3,0xc7,0xc7,0xc7,0xe1,0x82,0xff,0xff,0xff,0xff,0x01,0xf7,0xf7,0xf7,
 35.3079 +   0xfa,0x52,0x52,0x52,0xbd,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0xc7,0xc7,0xc7,0xe1,0x82,0xff,
 35.3080 +   0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x84,0x00,0x00,0x00,0xb3,0x00,0xa0,0xa0,0xa0,0xd1,0x85,0xaf,0xaf,0xaf,0xd6,0x00,0x52,0x52,0x52,0xbd,0xff,0x00,0x00,0x00,
 35.3081 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xcc,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xd0,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x82,
 35.3082 +   0xff,0xff,0xff,0xff,0x86,0x7e,0x7e,0x7e,0xc7,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,0x82,0xff,0xff,
 35.3083 +   0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x8d,0x00,0x00,0x00,0xb3,0x00,0x52,0x52,0x52,0xbd,0x82,0xff,0xff,0xff,0xff,0x01,0xc7,0xc7,0xc7,0xe1,0xbb,0xbb,0xbb,0xdc,0x82,
 35.3084 +   0xff,0xff,0xff,0xff,0x00,0xa0,0xa0,0xa0,0xd1,0x85,0x00,0x00,0x00,0xb3,0x82,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x89,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,
 35.3085 +   0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x86,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x86,0x7e,0x7e,0x7e,0xc7,0x00,0xaf,0xaf,0xaf,0xd6,
 35.3086 +   0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x8a,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x83,0xff,0xff,0xff,0xff,0x01,0xbb,0xbb,0xbb,0xdc,0xf7,0xf7,
 35.3087 +   0xf7,0xfa,0x82,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x8c,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0xff,0xff,0xff,0xff,0x01,0xf7,0xf7,0xf7,0xfa,
 35.3088 +   0xaf,0xaf,0xaf,0xd6,0x8b,0x00,0x00,0x00,0xb3,0x00,0x52,0x52,0x52,0xbd,0x82,0xff,0xff,0xff,0xff,0x01,0xc7,0xc7,0xc7,0xe1,0xbb,0xbb,0xbb,0xdc,0x82,0xff,0xff,0xff,
 35.3089 +   0xff,0x00,0xa0,0xa0,0xa0,0xd1,0x85,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x89,0x00,0x00,0x00,0xb3,0x82,
 35.3090 +   0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x8d,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x87,0x00,0x00,
 35.3091 +   0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x01,0xef,0xef,0xef,0xf5,0xc7,0xc7,0xc7,0xe1,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x8a,
 35.3092 +   0x00,0x00,0x00,0xb3,0x00,0x6a,0x6a,0x6a,0xc2,0x82,0xff,0xff,0xff,0xff,0x00,0xd2,0xd2,0xd2,0xe6,0x81,0x00,0x00,0x00,0xb3,0x00,0xa0,0xa0,0xa0,0xd1,0x82,0xff,0xff,
 35.3093 +   0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0xff,0xff,0xff,0xff,0x00,0x6a,0x6a,0x6a,0xc2,0x81,0x00,0x00,0x00,0xb3,0x00,0xd2,0xd2,0xd2,0xe6,0x82,0xff,0xff,0xff,0xff,
 35.3094 +   0x85,0x00,0x00,0x00,0xb3,0x00,0xc7,0xc7,0xc7,0xe1,0x82,0xff,0xff,0xff,0xff,0x00,0x6a,0x6a,0x6a,0xc2,0x82,0xff,0xff,0xff,0xff,0x00,0xef,0xef,0xef,0xf5,0x85,0x00,
 35.3095 +   0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x84,0x00,0x00,0x00,0xb3,0x00,0xef,0xef,0xef,0xf5,0x82,0xff,0xff,0xff,
 35.3096 +   0xff,0x02,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x01,0xaf,0xaf,0xaf,0xd6,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,
 35.3097 +   0xff,0x01,0xef,0xef,0xef,0xf5,0x33,0x33,0x33,0xb8,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,
 35.3098 +   0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,
 35.3099 +   0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x83,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x81,
 35.3100 +   0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xd9,0x00,0x00,
 35.3101 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xd0,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x86,0x00,0x00,0x00,0xb3,
 35.3102 +   0x00,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,0x82,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x8e,0x00,
 35.3103 +   0x00,0x00,0xb3,0x00,0xd2,0xd2,0xd2,0xe6,0x82,0xff,0xff,0xff,0xff,0x00,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x01,0xf7,0xf7,0xf7,0xfa,0x33,0x33,0x33,0xb8,
 35.3104 +   0x85,0x00,0x00,0x00,0xb3,0x82,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x89,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x86,0x00,
 35.3105 +   0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x86,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,
 35.3106 +   0xd6,0x8a,0x00,0x00,0x00,0xb3,0x00,0xc7,0xc7,0xc7,0xe1,0x82,0xff,0xff,0xff,0xff,0x03,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0x6a,0x6a,0x6a,0xc2,0xf7,0xf7,0xf7,
 35.3107 +   0xfa,0x81,0xff,0xff,0xff,0xff,0x00,0xe6,0xe6,0xe6,0xf0,0x8c,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0xff,0xff,0xff,0xff,0x00,0xbb,0xbb,0xbb,0xdc,0x8d,
 35.3108 +   0x00,0x00,0x00,0xb3,0x00,0xd2,0xd2,0xd2,0xe6,0x82,0xff,0xff,0xff,0xff,0x00,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x01,0xf7,0xf7,0xf7,0xfa,0x33,0x33,0x33,
 35.3109 +   0xb8,0x85,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x89,0x00,0x00,0x00,0xb3,0x82,0xff,0xff,0xff,0xff,0x00,
 35.3110 +   0xdc,0xdc,0xdc,0xeb,0x8d,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x86,0x00,0x00,0x00,0xb3,0x01,0x33,0x33,
 35.3111 +   0x33,0xb8,0xef,0xef,0xef,0xf5,0x82,0xff,0xff,0xff,0xff,0x02,0xa0,0xa0,0xa0,0xd1,0x52,0x52,0x52,0xbd,0xf7,0xf7,0xf7,0xfa,0x82,0xff,0xff,0xff,0xff,0x00,0x6a,0x6a,
 35.3112 +   0x6a,0xc2,0x89,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0x33,0x33,0x33,0xb8,
 35.3113 +   0x82,0xff,0xff,0xff,0xff,0x00,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x00,0xef,0xef,0xef,0xf5,0x82,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0xff,
 35.3114 +   0xff,0xff,0xff,0x00,0x90,0x90,0x90,0xcc,0x84,0x00,0x00,0x00,0xb3,0x00,0x6a,0x6a,0x6a,0xc2,0x82,0xff,0xff,0xff,0xff,0x00,0xf7,0xf7,0xf7,0xfa,0x82,0xff,0xff,0xff,
 35.3115 +   0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x85,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x84,0x00,0x00,0x00,0xb3,0x00,
 35.3116 +   0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x02,0x7e,0x7e,0x7e,0xc7,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x00,0xef,0xef,0xef,0xf5,
 35.3117 +   0x83,0xff,0xff,0xff,0xff,0x00,0x90,0x90,0x90,0xcc,0x82,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,
 35.3118 +   0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,
 35.3119 +   0xff,0x00,0xef,0xef,0xef,0xf5,0x82,0xff,0xff,0xff,0xff,0x00,0xe6,0xe6,0xe6,0xf0,0x83,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x81,
 35.3120 +   0x00,0x00,0x00,0xb3,0x00,0x52,0x52,0x52,0xbd,0x83,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xd8,0x00,0x00,
 35.3121 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xd0,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x86,0x00,0x00,0x00,0xb3,
 35.3122 +   0x00,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,0x82,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x8e,0x00,
 35.3123 +   0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x85,0xff,0xff,0xff,0xff,0x00,0xbb,0xbb,0xbb,0xdc,0x86,0x00,0x00,0x00,0xb3,0x82,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,
 35.3124 +   0xeb,0x89,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x86,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x86,
 35.3125 +   0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x8a,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,
 35.3126 +   0xff,0xff,0x82,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0xff,0xff,0xff,0xff,0x8c,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0xff,0xff,0xff,0xff,
 35.3127 +   0x00,0xc7,0xc7,0xc7,0xe1,0x83,0x00,0x00,0x00,0xb3,0x01,0x52,0x52,0x52,0xbd,0x33,0x33,0x33,0xb8,0x87,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x85,0xff,0xff,
 35.3128 +   0xff,0xff,0x00,0xbb,0xbb,0xbb,0xdc,0x86,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x89,0x00,0x00,0x00,0xb3,
 35.3129 +   0x82,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x8d,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x86,0x00,
 35.3130 +   0x00,0x00,0xb3,0x00,0xbb,0xbb,0xbb,0xdc,0x82,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0xff,0xff,0xff,
 35.3131 +   0xff,0x00,0xe6,0xe6,0xe6,0xf0,0x89,0x00,0x00,0x00,0xb3,0x00,0xe6,0xe6,0xe6,0xf0,0x82,0xff,0xff,0xff,0xff,0x00,0x6a,0x6a,0x6a,0xc2,0x82,0x00,0x00,0x00,0xb3,0x00,
 35.3132 +   0xd2,0xd2,0xd2,0xe6,0x84,0xff,0xff,0xff,0xff,0x00,0xbb,0xbb,0xbb,0xdc,0x82,0x00,0x00,0x00,0xb3,0x00,0x6a,0x6a,0x6a,0xc2,0x82,0xff,0xff,0xff,0xff,0x00,0xbb,0xbb,
 35.3133 +   0xbb,0xdc,0x85,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x85,0xff,0xff,0xff,0xff,0x00,0x33,0x33,0x33,0xb8,0x85,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,
 35.3134 +   0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x83,0x00,0x00,0x00,0xb3,0x01,0x6a,0x6a,0x6a,0xc2,0xf7,0xf7,0xf7,0xfa,0x82,0xff,0xff,0xff,0xff,0x02,0x6a,0x6a,
 35.3135 +   0x6a,0xc2,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x86,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x83,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0xff,
 35.3136 +   0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,
 35.3137 +   0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x86,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x83,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x82,
 35.3138 +   0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x01,0xf7,0xf7,0xf7,0xfa,0x7e,0x7e,0x7e,0xc7,0x85,0x00,0x00,0x00,0xb3,0x01,0xbb,0xbb,0xbb,
 35.3139 +   0xdc,0xa0,0xa0,0xa0,0xd1,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xcf,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xd0,0x00,
 35.3140 +   0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x86,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,
 35.3141 +   0xd6,0x82,0x00,0x00,0x00,0xb3,0x82,0xff,0xff,0xff,0xff,0x00,0xf7,0xf7,0xf7,0xfa,0x86,0xdc,0xdc,0xdc,0xeb,0x00,0xbb,0xbb,0xbb,0xdc,0x87,0x00,0x00,0x00,0xb3,0x00,
 35.3142 +   0xef,0xef,0xef,0xf5,0x84,0xff,0xff,0xff,0xff,0x00,0x52,0x52,0x52,0xbd,0x86,0x00,0x00,0x00,0xb3,0x82,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x84,0x00,0x00,
 35.3143 +   0x00,0xb3,0x00,0xbb,0xbb,0xbb,0xdc,0x83,0xdc,0xdc,0xdc,0xeb,0x00,0xf7,0xf7,0xf7,0xfa,0x82,0xff,0xff,0xff,0xff,0x84,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,
 35.3144 +   0x00,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x86,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x8a,0x00,
 35.3145 +   0x00,0x00,0xb3,0x00,0xd2,0xd2,0xd2,0xe6,0x82,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,
 35.3146 +   0xff,0x8c,0x00,0x00,0x00,0xb3,0x00,0x52,0x52,0x52,0xbd,0x83,0xff,0xff,0xff,0xff,0x06,0xc7,0xc7,0xc7,0xe1,0x90,0x90,0x90,0xcc,0x7e,0x7e,0x7e,0xc7,0xaf,0xaf,0xaf,
 35.3147 +   0xd6,0xef,0xef,0xef,0xf5,0xe6,0xe6,0xe6,0xf0,0x33,0x33,0x33,0xb8,0x87,0x00,0x00,0x00,0xb3,0x00,0xef,0xef,0xef,0xf5,0x84,0xff,0xff,0xff,0xff,0x00,0x52,0x52,0x52,
 35.3148 +   0xbd,0x86,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0xff,0xff,0xff,0xff,0x00,0xe6,0xe6,0xe6,0xf0,0x86,0xdc,0xdc,0xdc,0xeb,0x00,0x6a,0x6a,0x6a,0xc2,0x81,
 35.3149 +   0x00,0x00,0x00,0xb3,0x82,0xff,0xff,0xff,0xff,0x00,0xf7,0xf7,0xf7,0xfa,0x86,0xdc,0xdc,0xdc,0xeb,0x02,0xbb,0xbb,0xbb,0xdc,0x00,0x00,0x00,0xb3,0x6a,0x6a,0x6a,0xc2,
 35.3150 +   0x83,0xdc,0xdc,0xdc,0xeb,0x00,0xe6,0xe6,0xe6,0xf0,0x82,0xff,0xff,0xff,0xff,0x00,0xef,0xef,0xef,0xf5,0x83,0xdc,0xdc,0xdc,0xeb,0x02,0xa0,0xa0,0xa0,0xd1,0x00,0x00,
 35.3151 +   0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x83,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0x00,0x00,0x00,0xb3,0x00,0xef,0xef,0xef,0xf5,0x82,0xff,0xff,0xff,0xff,0x00,
 35.3152 +   0xaf,0xaf,0xaf,0xd6,0x87,0x00,0x00,0x00,0xb3,0x00,0x52,0x52,0x52,0xbd,0x82,0xff,0xff,0xff,0xff,0x00,0xf7,0xf7,0xf7,0xfa,0x83,0x00,0x00,0x00,0xb3,0x00,0xa0,0xa0,
 35.3153 +   0xa0,0xd1,0x84,0xff,0xff,0xff,0xff,0x00,0x90,0x90,0x90,0xcc,0x83,0x00,0x00,0x00,0xb3,0x00,0xf7,0xf7,0xf7,0xfa,0x81,0xff,0xff,0xff,0xff,0x00,0xef,0xef,0xef,0xf5,
 35.3154 +   0x85,0x00,0x00,0x00,0xb3,0x00,0xa0,0xa0,0xa0,0xd1,0x84,0xff,0xff,0xff,0xff,0x00,0xc7,0xc7,0xc7,0xe1,0x86,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0xff,
 35.3155 +   0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0xaf,0xaf,0xaf,0xd6,0x01,0xc7,0xc7,0xc7,0xe1,0xf7,0xf7,0xf7,0xfa,0x82,0xff,0xff,0xff,0xff,0x00,0xef,0xef,0xef,0xf5,
 35.3156 +   0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x85,0xff,0xff,0xff,0xff,0x01,0xf7,0xf7,0xf7,0xfa,0x52,0x52,0x52,0xbd,0x83,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,
 35.3157 +   0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,
 35.3158 +   0x82,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x85,0xff,0xff,0xff,0xff,0x00,0xbb,0xbb,0xbb,0xdc,0x84,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0xff,
 35.3159 +   0xff,0xff,0xff,0x82,0x00,0x00,0x00,0xb3,0x01,0x52,0x52,0x52,0xbd,0xf7,0xf7,0xf7,0xfa,0x83,0xff,0xff,0xff,0xff,0x01,0xc7,0xc7,0xc7,0xe1,0xa0,0xa0,0xa0,0xd1,0x81,
 35.3160 +   0x7e,0x7e,0x7e,0xc7,0x01,0xaf,0xaf,0xaf,0xd6,0xef,0xef,0xef,0xf5,0x81,0xff,0xff,0xff,0xff,0x00,0x90,0x90,0x90,0xcc,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
 35.3161 +   0xb3,0xce,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xd0,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x86,
 35.3162 +   0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,0x8a,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,
 35.3163 +   0xdc,0xeb,0x87,0x00,0x00,0x00,0xb3,0x00,0xa0,0xa0,0xa0,0xd1,0x83,0xff,0xff,0xff,0xff,0x00,0xd2,0xd2,0xd2,0xe6,0x87,0x00,0x00,0x00,0xb3,0x82,0xff,0xff,0xff,0xff,
 35.3164 +   0x00,0xdc,0xdc,0xdc,0xeb,0x84,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x8c,0xff,0xff,0xff,0xff,0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0xff,
 35.3165 +   0xff,0xff,0xff,0x86,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x8a,0x00,0x00,0x00,0xb3,0x00,0xa0,0xa0,0xa0,
 35.3166 +   0xd1,0x83,0xff,0xff,0xff,0xff,0x01,0xdc,0xdc,0xdc,0xeb,0xef,0xef,0xef,0xf5,0x82,0xff,0xff,0xff,0xff,0x00,0xd2,0xd2,0xd2,0xe6,0x8d,0x00,0x00,0x00,0xb3,0x00,0xbb,
 35.3167 +   0xbb,0xbb,0xdc,0x88,0xff,0xff,0xff,0xff,0x01,0xe6,0xe6,0xe6,0xf0,0x33,0x33,0x33,0xb8,0x86,0x00,0x00,0x00,0xb3,0x00,0xa0,0xa0,0xa0,0xd1,0x83,0xff,0xff,0xff,0xff,
 35.3168 +   0x00,0xd2,0xd2,0xd2,0xe6,0x87,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x8a,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,0x8a,0xff,
 35.3169 +   0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x8c,0xff,0xff,0xff,0xff,0x02,0xaf,0xaf,0xaf,0xd6,0x00,0x00,0x00,0xb3,0xef,0xef,
 35.3170 +   0xef,0xf5,0x82,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x83,0x00,0x00,0x00,0xb3,0x00,0x90,0x90,0x90,0xcc,0x83,0xff,0xff,0xff,0xff,0x00,0x52,0x52,0x52,0xbd,
 35.3171 +   0x86,0x00,0x00,0x00,0xb3,0x00,0xa0,0xa0,0xa0,0xd1,0x82,0xff,0xff,0xff,0xff,0x00,0xd2,0xd2,0xd2,0xe6,0x83,0x00,0x00,0x00,0xb3,0x00,0x33,0x33,0x33,0xb8,0x83,0xff,
 35.3172 +   0xff,0xff,0xff,0x00,0xf7,0xf7,0xf7,0xfa,0x84,0x00,0x00,0x00,0xb3,0x00,0xd2,0xd2,0xd2,0xe6,0x82,0xff,0xff,0xff,0xff,0x00,0x52,0x52,0x52,0xbd,0x85,0x00,0x00,0x00,
 35.3173 +   0xb3,0x00,0xef,0xef,0xef,0xf5,0x83,0xff,0xff,0xff,0xff,0x00,0x6a,0x6a,0x6a,0xc2,0x86,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x8b,0xff,0xff,0xff,0xff,0x00,
 35.3174 +   0x90,0x90,0x90,0xcc,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x85,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x84,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,
 35.3175 +   0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,
 35.3176 +   0x82,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x84,0xff,0xff,0xff,0xff,0x01,0xf7,0xf7,0xf7,0xfa,0x33,0x33,0x33,0xb8,0x84,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,
 35.3177 +   0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x83,0x00,0x00,0x00,0xb3,0x00,0xa0,0xa0,0xa0,0xd1,0x8b,0xff,0xff,0xff,0xff,0x01,0xf7,0xf7,0xf7,0xfa,0x7e,0x7e,0x7e,0xc7,0xff,
 35.3178 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xcd,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xd0,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,
 35.3179 +   0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x86,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0x00,0x00,0x00,0xb3,
 35.3180 +   0x8a,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x87,0x00,0x00,0x00,0xb3,0x01,0x33,0x33,0x33,0xb8,0xf7,0xf7,0xf7,0xfa,0x82,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,
 35.3181 +   0x7e,0xc7,0x87,0x00,0x00,0x00,0xb3,0x82,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x84,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x8c,0xff,0xff,0xff,0xff,
 35.3182 +   0x81,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x86,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,
 35.3183 +   0xaf,0xaf,0xd6,0x8b,0x00,0x00,0x00,0xb3,0x00,0xe6,0xe6,0xe6,0xf0,0x86,0xff,0xff,0xff,0xff,0x01,0xf7,0xf7,0xf7,0xfa,0x6a,0x6a,0x6a,0xc2,0x8e,0x00,0x00,0x00,0xb3,
 35.3184 +   0x00,0xd2,0xd2,0xd2,0xe6,0x88,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x86,0x00,0x00,0x00,0xb3,0x01,0x33,0x33,0x33,0xb8,0xf7,0xf7,0xf7,0xfa,0x82,0xff,0xff,
 35.3185 +   0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x87,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x8a,0xff,0xff,0xff,0xff,0x00,0x7e,0x7e,0x7e,0xc7,0x81,0x00,0x00,0x00,0xb3,
 35.3186 +   0x8a,0xff,0xff,0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0x00,0x00,0x00,0xb3,0x7e,0x7e,0x7e,0xc7,0x8c,0xff,0xff,0xff,0xff,0x81,0xaf,0xaf,0xaf,0xd6,0x83,0xff,0xff,0xff,
 35.3187 +   0xff,0x00,0x52,0x52,0x52,0xbd,0x84,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x86,0x00,0x00,0x00,0xb3,0x00,
 35.3188 +   0xd2,0xd2,0xd2,0xe6,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x84,0x00,0x00,0x00,0xb3,0x00,0xd2,0xd2,0xd2,0xe6,0x82,0xff,0xff,0xff,0xff,0x00,0xc7,0xc7,
 35.3189 +   0xc7,0xe1,0x84,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x85,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,
 35.3190 +   0x82,0xff,0xff,0xff,0xff,0x00,0xdc,0xdc,0xdc,0xeb,0x87,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x89,0xff,0xff,0xff,0xff,0x01,0xf7,0xf7,0xf7,0xfa,0xa0,0xa0,
 35.3191 +   0xa0,0xd1,0x82,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x84,0xff,0xff,0xff,0xff,0x00,0xef,0xef,0xef,0xf5,0x85,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,
 35.3192 +   0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0x00,0x00,0x00,0xb3,0x00,0x7e,0x7e,0x7e,0xc7,0x82,0xff,0xff,0xff,0xff,0x00,0xaf,0xaf,0xaf,0xd6,0x82,0x00,
 35.3193 +   0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x84,0xff,0xff,0xff,0xff,0x00,0xa0,0xa0,0xa0,0xd1,0x85,0x00,0x00,0x00,0xb3,0x00,0xdc,0xdc,0xdc,0xeb,0x82,0xff,0xff,0xff,
 35.3194 +   0xff,0x84,0x00,0x00,0x00,0xb3,0x01,0x7e,0x7e,0x7e,0xc7,0xef,0xef,0xef,0xf5,0x89,0xff,0xff,0xff,0xff,0x01,0xef,0xef,0xef,0xf5,0x6a,0x6a,0x6a,0xc2,0xff,0x00,0x00,
 35.3195 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xcd,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xd0,0x00,0x00,0x00,0xb3,0x00,0xbb,0xbb,0xbb,0xdc,
 35.3196 +   0x82,0xdc,0xdc,0xdc,0xeb,0x86,0x00,0x00,0x00,0xb3,0x00,0x6a,0x6a,0x6a,0xc2,0x82,0xdc,0xdc,0xdc,0xeb,0x00,0xa0,0xa0,0xa0,0xd1,0x82,0x00,0x00,0x00,0xb3,0x8a,0xdc,
 35.3197 +   0xdc,0xdc,0xeb,0x00,0xbb,0xbb,0xbb,0xdc,0x88,0x00,0x00,0x00,0xb3,0x00,0xaf,0xaf,0xaf,0xd6,0x81,0xdc,0xdc,0xdc,0xeb,0x00,0xd2,0xd2,0xd2,0xe6,0x88,0x00,0x00,0x00,
 35.3198 +   0xb3,0x82,0xdc,0xdc,0xdc,0xeb,0x00,0xbb,0xbb,0xbb,0xdc,0x84,0x00,0x00,0x00,0xb3,0x00,0xbb,0xbb,0xbb,0xdc,0x8c,0xdc,0xdc,0xdc,0xeb,0x81,0x00,0x00,0x00,0xb3,0x00,
 35.3199 +   0xbb,0xbb,0xbb,0xdc,0x82,0xdc,0xdc,0xdc,0xeb,0x86,0x00,0x00,0x00,0xb3,0x00,0x6a,0x6a,0x6a,0xc2,0x82,0xdc,0xdc,0xdc,0xeb,0x00,0xa0,0xa0,0xa0,0xd1,0x8b,0x00,0x00,
 35.3200 +   0x00,0xb3,0x02,0x33,0x33,0x33,0xb8,0xaf,0xaf,0xaf,0xd6,0xf7,0xf7,0xf7,0xfa,0x83,0xff,0xff,0xff,0xff,0x01,0xd2,0xd2,0xd2,0xe6,0x6a,0x6a,0x6a,0xc2,0x90,0x00,0x00,
 35.3201 +   0x00,0xb3,0x01,0xa0,0xa0,0xa0,0xd1,0xe6,0xe6,0xe6,0xf0,0x84,0xff,0xff,0xff,0xff,0x01,0xd2,0xd2,0xd2,0xe6,0x7e,0x7e,0x7e,0xc7,0x88,0x00,0x00,0x00,0xb3,0x00,0xaf,
 35.3202 +   0xaf,0xaf,0xd6,0x81,0xdc,0xdc,0xdc,0xeb,0x00,0xd2,0xd2,0xd2,0xe6,0x88,0x00,0x00,0x00,0xb3,0x00,0xa0,0xa0,0xa0,0xd1,0x8a,0xdc,0xdc,0xdc,0xeb,0x00,0x6a,0x6a,0x6a,
 35.3203 +   0xc2,0x81,0x00,0x00,0x00,0xb3,0x8a,0xdc,0xdc,0xdc,0xeb,0x02,0xbb,0xbb,0xbb,0xdc,0x00,0x00,0x00,0xb3,0x6a,0x6a,0x6a,0xc2,0x8c,0xdc,0xdc,0xdc,0xeb,0x00,0xaf,0xaf,
 35.3204 +   0xaf,0xd6,0x83,0xdc,0xdc,0xdc,0xeb,0x00,0xaf,0xaf,0xaf,0xd6,0x85,0x00,0x00,0x00,0xb3,0x00,0x52,0x52,0x52,0xbd,0x83,0xdc,0xdc,0xdc,0xeb,0x00,0x7e,0x7e,0x7e,0xc7,
 35.3205 +   0x85,0x00,0x00,0x00,0xb3,0x00,0xd2,0xd2,0xd2,0xe6,0x82,0xdc,0xdc,0xdc,0xeb,0x00,0x6a,0x6a,0x6a,0xc2,0x84,0x00,0x00,0x00,0xb3,0x00,0x90,0x90,0x90,0xcc,0x82,0xdc,
 35.3206 +   0xdc,0xdc,0xeb,0x00,0x7e,0x7e,0x7e,0xc7,0x84,0x00,0x00,0x00,0xb3,0x00,0x6a,0x6a,0x6a,0xc2,0x82,0xdc,0xdc,0xdc,0xeb,0x00,0xaf,0xaf,0xaf,0xd6,0x85,0x00,0x00,0x00,
 35.3207 +   0xb3,0x00,0x33,0x33,0x33,0xb8,0x82,0xdc,0xdc,0xdc,0xeb,0x00,0x90,0x90,0x90,0xcc,0x87,0x00,0x00,0x00,0xb3,0x00,0x6a,0x6a,0x6a,0xc2,0x87,0xdc,0xdc,0xdc,0xeb,0x02,
 35.3208 +   0xbb,0xbb,0xbb,0xdc,0xa0,0xa0,0xa0,0xd1,0x33,0x33,0x33,0xb8,0x83,0x00,0x00,0x00,0xb3,0x00,0x6a,0x6a,0x6a,0xc2,0x84,0xdc,0xdc,0xdc,0xeb,0x00,0x7e,0x7e,0x7e,0xc7,
 35.3209 +   0x85,0x00,0x00,0x00,0xb3,0x00,0x6a,0x6a,0x6a,0xc2,0x82,0xdc,0xdc,0xdc,0xeb,0x00,0xa0,0xa0,0xa0,0xd1,0x81,0x00,0x00,0x00,0xb3,0x00,0x6a,0x6a,0x6a,0xc2,0x82,0xdc,
 35.3210 +   0xdc,0xdc,0xeb,0x00,0xa0,0xa0,0xa0,0xd1,0x82,0x00,0x00,0x00,0xb3,0x00,0xbb,0xbb,0xbb,0xdc,0x83,0xdc,0xdc,0xdc,0xeb,0x00,0xc7,0xc7,0xc7,0xe1,0x86,0x00,0x00,0x00,
 35.3211 +   0xb3,0x00,0xbb,0xbb,0xbb,0xdc,0x82,0xdc,0xdc,0xdc,0xeb,0x85,0x00,0x00,0x00,0xb3,0x02,0x33,0x33,0x33,0xb8,0xaf,0xaf,0xaf,0xd6,0xe6,0xe6,0xe6,0xf0,0x85,0xff,0xff,
 35.3212 +   0xff,0xff,0x02,0xdc,0xdc,0xdc,0xeb,0xa0,0xa0,0xa0,0xd1,0x33,0x33,0x33,0xb8,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xce,0x00,0x00,0x00,0xb3,0xff,0x00,
 35.3213 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xbd,0x00,0x00,0x00,0xb3,0x00,0x6a,0x6a,0x6a,0xc2,0x81,0x7e,0x7e,0x7e,0xc7,0x00,0x33,0x33,0x33,
 35.3214 +   0xb8,0x94,0x00,0x00,0x00,0xb3,0x00,0x33,0x33,0x33,0xb8,0x82,0x7e,0x7e,0x7e,0xc7,0xff,0x00,0x00,0x00,0xb3,0xcd,0x00,0x00,0x00,0xb3,0x82,0x7e,0x7e,0x7e,0xc7,0x00,
 35.3215 +   0x6a,0x6a,0x6a,0xc2,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xd2,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
 35.3216 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
 35.3217 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
 35.3218 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
 35.3219 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
 35.3220 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
 35.3221 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
 35.3222 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
 35.3223 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
 35.3224 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
 35.3225 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
 35.3226 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
 35.3227 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
 35.3228 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
 35.3229 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
 35.3230 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
 35.3231 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
 35.3232 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
 35.3233 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
 35.3234 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
 35.3235 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
 35.3236 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
 35.3237 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
 35.3238 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
 35.3239 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
 35.3240 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
 35.3241 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
 35.3242 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
 35.3243 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
 35.3244 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
 35.3245 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
 35.3246 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
 35.3247 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
 35.3248 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
 35.3249 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
 35.3250 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
 35.3251 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
 35.3252 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
 35.3253 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
 35.3254 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
 35.3255 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
 35.3256 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
 35.3257 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
 35.3258 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
 35.3259 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
 35.3260 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
 35.3261 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
 35.3262 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
 35.3263 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
 35.3264 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
 35.3265 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
 35.3266 +   0x00,0xb3,0xf2,0x00,0x00,0x00,0xb3,0x02,0x04,0x04,0x13,0xb7,0x20,0x24,0xa9,0xdf,0x26,0x2e,0xd7,0xef,0x91,0x28,0x2f,0xd9,0xf0,0x02,0x26,0x2e,0xd7,0xef,0x1f,0x25,
 35.3267 +   0xa8,0xde,0x04,0x04,0x13,0xb7,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xf4,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
 35.3268 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xf2,0x00,0x00,0x00,0xb3,0x00,0x23,0x28,0xbb,0xe5,0x95,0x2e,0x37,0xff,0xff,0x00,0x22,0x27,0xb6,0xe4,0xff,0x00,0x00,
 35.3269 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xf4,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
 35.3270 +   0xf2,0x00,0x00,0x00,0xb3,0x00,0x2d,0x35,0xf7,0xfb,0x88,0x2e,0x37,0xff,0xff,0x00,0x26,0x2b,0xcb,0xea,0x81,0x20,0x25,0xad,0xe1,0x00,0x26,0x2b,0xcc,0xea,0x88,0x2e,
 35.3271 +   0x37,0xff,0xff,0x00,0x2c,0x34,0xf2,0xf9,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xf4,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
 35.3272 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xf2,0x00,0x00,0x00,0xb3,0x00,0x28,0x30,0xde,0xf1,0x87,0x2e,0x37,0xff,0xff,0x00,0x24,0x2b,0xc4,0xe8,0x83,
 35.3273 +   0x00,0x00,0x00,0xb3,0x00,0x25,0x2a,0xc7,0xea,0x87,0x2e,0x37,0xff,0xff,0x00,0x26,0x2e,0xd7,0xef,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
 35.3274 +   0x00,0xb3,0xf4,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xf2,0x00,0x00,0x00,0xb3,0x00,0x13,0x17,0x68,0xcb,
 35.3275 +   0x87,0x2e,0x37,0xff,0xff,0x00,0x1f,0x25,0xab,0xe0,0x83,0x00,0x00,0x00,0xb3,0x00,0x1f,0x25,0xab,0xe0,0x87,0x2e,0x37,0xff,0xff,0x00,0x13,0x16,0x61,0xca,0xff,0x00,
 35.3276 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xf4,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
 35.3277 +   0xb3,0xf3,0x00,0x00,0x00,0xb3,0x00,0x25,0x2c,0xcd,0xec,0x86,0x2e,0x37,0xff,0xff,0x01,0x26,0x2d,0xd2,0xed,0x01,0x01,0x05,0xb4,0x81,0x00,0x00,0x00,0xb3,0x01,0x01,
 35.3278 +   0x01,0x06,0xb4,0x27,0x2e,0xd6,0xef,0x86,0x2e,0x37,0xff,0xff,0x00,0x26,0x2b,0xcb,0xea,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
 35.3279 +   0xf5,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xf3,0x00,0x00,0x00,0xb3,0x01,0x0d,0x0e,0x40,0xc1,0x2e,0x37,
 35.3280 +   0xfd,0xfe,0x86,0x2e,0x37,0xff,0xff,0x00,0x2b,0x31,0xe9,0xf5,0x81,0x28,0x2f,0xd9,0xf0,0x00,0x2b,0x31,0xe9,0xf6,0x86,0x2e,0x37,0xff,0xff,0x01,0x2d,0x36,0xfc,0xfe,
 35.3281 +   0x0c,0x0d,0x3b,0xc0,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xf5,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
 35.3282 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xf4,0x00,0x00,0x00,0xb3,0x00,0x20,0x26,0xb0,0xe1,0x91,0x2e,0x37,0xff,0xff,0x00,0x20,0x24,0xa9,0xdf,0xff,0x00,0x00,0x00,0xb3,
 35.3283 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xf6,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xf4,0x00,
 35.3284 +   0x00,0x00,0xb3,0x01,0x06,0x07,0x1e,0xb9,0x2c,0x34,0xf4,0xfb,0x84,0x2e,0x37,0xff,0xff,0x01,0x2e,0x37,0xfe,0xff,0x24,0x2b,0xc5,0xe8,0x81,0x20,0x25,0xad,0xe1,0x00,
 35.3285 +   0x25,0x2a,0xc6,0xe9,0x85,0x2e,0x37,0xff,0xff,0x01,0x2c,0x34,0xf2,0xfa,0x05,0x06,0x1b,0xb9,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
 35.3286 +   0xb3,0xf6,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xf5,0x00,0x00,0x00,0xb3,0x00,0x19,0x1f,0x8b,0xd5,0x84,
 35.3287 +   0x2e,0x37,0xff,0xff,0x00,0x24,0x2a,0xc4,0xe8,0x83,0x00,0x00,0x00,0xb3,0x00,0x25,0x2a,0xc7,0xe9,0x84,0x2e,0x37,0xff,0xff,0x00,0x19,0x1d,0x85,0xd4,0xff,0x00,0x00,
 35.3288 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xf7,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
 35.3289 +   0xf5,0x00,0x00,0x00,0xb3,0x01,0x02,0x02,0x09,0xb5,0x2a,0x30,0xe4,0xf4,0x83,0x2e,0x37,0xff,0xff,0x00,0x1f,0x25,0xab,0xe0,0x83,0x00,0x00,0x00,0xb3,0x00,0x1f,0x25,
 35.3290 +   0xab,0xe0,0x83,0x2e,0x37,0xff,0xff,0x01,0x29,0x31,0xe2,0xf3,0x01,0x01,0x06,0xb4,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xf7,
 35.3291 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xf6,0x00,0x00,0x00,0xb3,0x00,0x13,0x16,0x62,0xca,0x83,0x2e,0x37,
 35.3292 +   0xff,0xff,0x00,0x1f,0x25,0xab,0xe0,0x83,0x00,0x00,0x00,0xb3,0x00,0x1f,0x25,0xab,0xe0,0x83,0x2e,0x37,0xff,0xff,0x00,0x11,0x14,0x5c,0xc8,0xff,0x00,0x00,0x00,0xb3,
 35.3293 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xf8,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xf7,0x00,
 35.3294 +   0x00,0x00,0xb3,0x00,0x26,0x2b,0xcc,0xea,0x82,0x2e,0x37,0xff,0xff,0x00,0x1f,0x25,0xab,0xe0,0x83,0x00,0x00,0x00,0xb3,0x00,0x1f,0x25,0xab,0xe0,0x82,0x2e,0x37,0xff,
 35.3295 +   0xff,0x00,0x24,0x2b,0xc5,0xe9,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xf9,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
 35.3296 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xf7,0x00,0x00,0x00,0xb3,0x01,0x0c,0x0d,0x3b,0xc0,0x2d,0x36,0xfc,0xfe,0x81,0x2e,0x37,0xff,0xff,0x00,0x1f,0x25,0xab,
 35.3297 +   0xe0,0x83,0x00,0x00,0x00,0xb3,0x00,0x1f,0x25,0xab,0xe0,0x81,0x2e,0x37,0xff,0xff,0x01,0x2d,0x36,0xfb,0xfe,0x0a,0x0c,0x36,0xbf,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
 35.3298 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xf9,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xf8,0x00,0x00,0x00,
 35.3299 +   0xb3,0x00,0x20,0x24,0xa9,0xdf,0x81,0x2e,0x37,0xff,0xff,0x00,0x21,0x26,0xb2,0xe2,0x83,0x00,0x00,0x00,0xb3,0x00,0x21,0x26,0xb2,0xe2,0x81,0x2e,0x37,0xff,0xff,0x00,
 35.3300 +   0x1f,0x24,0xa4,0xde,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xfa,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
 35.3301 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xf8,0x00,0x00,0x00,0xb3,0x04,0x05,0x06,0x1b,0xb9,0x2c,0x34,0xf3,0xfa,0x2e,0x37,0xff,0xff,0x2c,0x34,0xf3,0xfa,0x14,0x16,0x65,
 35.3302 +   0xcb,0x81,0x0d,0x0f,0x44,0xc2,0x04,0x14,0x17,0x67,0xcb,0x2c,0x34,0xf4,0xfb,0x2e,0x37,0xff,0xff,0x2b,0x33,0xf1,0xf9,0x05,0x05,0x17,0xb8,0xff,0x00,0x00,0x00,0xb3,
 35.3303 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xfa,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xf9,0x00,
 35.3304 +   0x00,0x00,0xb3,0x00,0x19,0x1d,0x85,0xd4,0x87,0x2e,0x37,0xff,0xff,0x00,0x18,0x1c,0x81,0xd2,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
 35.3305 +   0xb3,0xfb,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xf9,0x00,0x00,0x00,0xb3,0x01,0x02,0x02,0x07,0xb4,0x29,
 35.3306 +   0x31,0xe2,0xf3,0x85,0x2e,0x37,0xff,0xff,0x01,0x28,0x30,0xdf,0xf2,0x01,0x01,0x05,0xb4,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
 35.3307 +   0xfb,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xfa,0x00,0x00,0x00,0xb3,0x00,0x12,0x14,0x5d,0xc8,0x85,0x2e,
 35.3308 +   0x37,0xff,0xff,0x00,0x10,0x13,0x56,0xc7,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xfc,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
 35.3309 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xfb,0x00,0x00,0x00,0xb3,0x00,0x25,0x2a,0xc6,0xe9,0x83,0x2e,0x37,0xff,0xff,0x00,0x23,0x2a,0xc2,0xe7,0xff,
 35.3310 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xfd,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
 35.3311 +   0x00,0xb3,0xfb,0x00,0x00,0x00,0xb3,0x01,0x0a,0x0c,0x36,0xbf,0x2e,0x36,0xf9,0xfc,0x81,0x2e,0x37,0xff,0xff,0x01,0x2c,0x35,0xf8,0xfc,0x09,0x0a,0x30,0xbd,0xff,0x00,
 35.3312 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xfd,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
 35.3313 +   0xb3,0xfc,0x00,0x00,0x00,0xb3,0x03,0x10,0x12,0x52,0xc6,0x25,0x2a,0xc7,0xe9,0x25,0x2a,0xc6,0xe9,0x0f,0x10,0x4d,0xc5,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
 35.3314 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xfe,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
 35.3315 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
 35.3316 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
 35.3317 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
 35.3318 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
 35.3319 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
 35.3320 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
 35.3321 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
 35.3322 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
 35.3323 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
 35.3324 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
 35.3325 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
 35.3326 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
 35.3327 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
 35.3328 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
 35.3329 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
 35.3330 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
 35.3331 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
 35.3332 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
 35.3333 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
 35.3334 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
 35.3335 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
 35.3336 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
 35.3337 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
 35.3338 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
 35.3339 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
 35.3340 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
 35.3341 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
 35.3342 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
 35.3343 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
 35.3344 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
 35.3345 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
 35.3346 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
 35.3347 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
 35.3348 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
 35.3349 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
 35.3350 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
 35.3351 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
 35.3352 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
 35.3353 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
 35.3354 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
 35.3355 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
 35.3356 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
 35.3357 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
 35.3358 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
 35.3359 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,
 35.3360 +   0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,
 35.3361 +   0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,
 35.3362 +   0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,
 35.3363 +   0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,
 35.3364 +   0xb3,0xff,0x00,0x00,0x00,0xb3,0xff,0x00,0x00,0x00,0xb3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x54,0x52,0x55,0x45,0x56,0x49,0x53,0x49,0x4f,0x4e,0x2d,0x58,0x46,
 35.3365 +   0x49,0x4c,0x45,0x2e,0x00
 35.3366 +};
    36.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    36.2 +++ b/LibOVR/Src/Displays/OVR_Display.cpp	Wed Jan 14 06:51:16 2015 +0200
    36.3 @@ -0,0 +1,36 @@
    36.4 +/************************************************************************************
    36.5 +
    36.6 +PublicHeader:   None
    36.7 +Filename    :   OVR_Display.cpp
    36.8 +Content     :   Common implementation for display device
    36.9 +Created     :   May 6, 2014
   36.10 +Notes       : 
   36.11 +
   36.12 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   36.13 +
   36.14 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
   36.15 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
   36.16 +which is provided at the time of installation or download, or which 
   36.17 +otherwise accompanies this software in either electronic or hard copy form.
   36.18 +
   36.19 +You may obtain a copy of the License at
   36.20 +
   36.21 +http://www.oculusvr.com/licenses/LICENSE-3.2 
   36.22 +
   36.23 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
   36.24 +distributed under the License is distributed on an "AS IS" BASIS,
   36.25 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   36.26 +See the License for the specific language governing permissions and
   36.27 +limitations under the License.
   36.28 +
   36.29 +************************************************************************************/
   36.30 +
   36.31 +#include "OVR_Display.h"
   36.32 +
   36.33 +namespace OVR {
   36.34 +
   36.35 +
   36.36 +// Place platform-independent code here
   36.37 +
   36.38 +
   36.39 +} // namespace OVR
    37.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    37.2 +++ b/LibOVR/Src/Displays/OVR_Display.h	Wed Jan 14 06:51:16 2015 +0200
    37.3 @@ -0,0 +1,203 @@
    37.4 +/************************************************************************************
    37.5 +
    37.6 +PublicHeader:   None
    37.7 +Filename    :   OVR_Display.h
    37.8 +Content     :   Contains platform independent display management
    37.9 +Created     :   May 6, 2014
   37.10 +Notes       : 
   37.11 +
   37.12 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   37.13 +
   37.14 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
   37.15 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
   37.16 +which is provided at the time of installation or download, or which 
   37.17 +otherwise accompanies this software in either electronic or hard copy form.
   37.18 +
   37.19 +You may obtain a copy of the License at
   37.20 +
   37.21 +http://www.oculusvr.com/licenses/LICENSE-3.2 
   37.22 +
   37.23 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
   37.24 +distributed under the License is distributed on an "AS IS" BASIS,
   37.25 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   37.26 +See the License for the specific language governing permissions and
   37.27 +limitations under the License.
   37.28 +
   37.29 +************************************************************************************/
   37.30 +
   37.31 +#ifndef OVR_Display_h
   37.32 +#define OVR_Display_h
   37.33 +
   37.34 +#include "../Sensors/OVR_DeviceConstants.h" // Required for HmdTypeEnum
   37.35 +
   37.36 +#include "../Kernel/OVR_Types.h"
   37.37 +#include "../Kernel/OVR_Atomic.h"
   37.38 +#include "../Kernel/OVR_RefCount.h"
   37.39 +#include "../Kernel/OVR_Array.h"
   37.40 +#include "../Kernel/OVR_String.h"
   37.41 +#include "../Kernel/OVR_Math.h"
   37.42 +
   37.43 +namespace OVR {
   37.44 +
   37.45 +
   37.46 +class DisplaySearchHandle : virtual public RefCountBaseV<DisplaySearchHandle>
   37.47 +{
   37.48 +public:
   37.49 +	DisplaySearchHandle() {}
   37.50 +
   37.51 +	virtual ~DisplaySearchHandle() {}
   37.52 +
   37.53 +	void operator= (const DisplaySearchHandle&) {}
   37.54 +};
   37.55 +
   37.56 +//-------------------------------------------------------------------------------------
   37.57 +// ***** Display
   37.58 +
   37.59 +// Display object describes an Oculus HMD screen in LibOVR, providing information such
   37.60 +// as EDID serial number and resolution in platform-independent manner.
   37.61 +//
   37.62 +// Display is an abstract base class to support OS and driver specific implementations.
   37.63 +// It support HMD screen enumeration through GetDisplayCount/GetDisplay static functions.
   37.64 +//
   37.65 +// Examples of implementations of Display are the following:
   37.66 +// Display_Win32_Generic - Compatibly mode implementation that maintains operation on
   37.67 +//						   systems without drivers.
   37.68 +// Display_Win32_Driver  - Driver-Based display
   37.69 +// Display_OSX_Generic   - Additional compatibility mode implementation for OS X
   37.70 +
   37.71 +class Display : public RefCountBase<Display>
   37.72 +{
   37.73 +protected:
   37.74 +	enum MirrorMode
   37.75 +	{
   37.76 +		MirrorEnabled = 0,
   37.77 +		MirrorDisabled = 1
   37.78 +	};
   37.79 +
   37.80 +	MirrorMode mirrorMode;
   37.81 +
   37.82 +	Display(
   37.83 +            HmdTypeEnum deviceTypeGuess,
   37.84 +#ifdef OVR_OS_MAC
   37.85 +            uint32_t displayID,
   37.86 +#else
   37.87 +			const String& displayID,
   37.88 +#endif
   37.89 +			const String& modelName,
   37.90 +			const String& editSerial,
   37.91 +            const Sizei& logicalRes,
   37.92 +			const Sizei& nativeRes,
   37.93 +			const Vector2i& displayOffset, 
   37.94 +			const uint64_t devNumber,
   37.95 +			const uint32_t rotation,
   37.96 +			const bool appExclusive):
   37.97 +		mirrorMode(MirrorDisabled),
   37.98 +		DeviceTypeGuess(deviceTypeGuess),
   37.99 +        DisplayID(displayID),
  37.100 +		ModelName(modelName),
  37.101 +		EdidSerialNumber(editSerial),
  37.102 +		LogicalResolutionInPixels(logicalRes),
  37.103 +		NativeResolutionInPixels(nativeRes),
  37.104 +		DesktopDisplayOffset(displayOffset),
  37.105 +		DeviceNumber(devNumber),
  37.106 +		Rotation(rotation),
  37.107 +		ApplicationExclusive(appExclusive)
  37.108 +    {
  37.109 +	}
  37.110 +
  37.111 +    void operator = (const Display&) { } // Quiet warning.
  37.112 +
  37.113 +public:
  37.114 +	virtual ~Display() { }
  37.115 +
  37.116 +	// ----- Platform specific static Display functionality -----
  37.117 +
  37.118 +	// Mandatory function that sets up the display environment with
  37.119 +	// any necessary shimming and function hooks. This should be one
  37.120 +	// of the very first things your application does when it
  37.121 +	// initializes LibOVR
  37.122 +	static bool         Initialize();
  37.123 +
  37.124 +	// Returns a count of the detected displays. These are Rift displays
  37.125 +	// attached directly to an active display port
  37.126 +	static int          GetDisplayCount( DisplaySearchHandle* handle = NULL, bool extended = true, bool applicationOnly = true, bool extendedEDIDSerials = false );
  37.127 +	// Returns a specific index of a display. Displays are sorted in no particular order.
  37.128 +	static Ptr<Display> GetDisplay( int index = 0, DisplaySearchHandle* handle = NULL ); 
  37.129 +
  37.130 +
  37.131 +    // Returns true if we are referencing the same display; useful for matching display
  37.132 +    // objects with the ones already detected.
  37.133 +    bool MatchDisplay(const Display* other)
  37.134 +    {
  37.135 +		// Note this is not checking the DeviceName, which corresponds to which monitor the device is.
  37.136 +		// This allows matching to match a display that has changed how it is plugged in.
  37.137 +		return (DisplayID == other->DisplayID) &&
  37.138 +               (EdidSerialNumber == other->EdidSerialNumber) &&
  37.139 +               (NativeResolutionInPixels == other->NativeResolutionInPixels) &&
  37.140 +               (DesktopDisplayOffset == other->DesktopDisplayOffset) &&
  37.141 +               (ApplicationExclusive == other->ApplicationExclusive);
  37.142 +    }
  37.143 +
  37.144 +
  37.145 +	// ----- Device independent instance based Display functionality -----
  37.146 +
  37.147 +    // Device type guess based on display info.
  37.148 +    const HmdTypeEnum   DeviceTypeGuess;
  37.149 +#if defined(OVR_OS_MAC)
  37.150 +    // CGDirectDisplayID for the rift.
  37.151 +    const uint32_t      DisplayID; 
  37.152 +#else
  37.153 +	// A string denoting the display device name so that apps can recognize the monitor
  37.154 +	const String        DisplayID;
  37.155 +#endif
  37.156 +    // A literal string containing the name of the model, i.e. Rift DK2
  37.157 +    const String        ModelName;
  37.158 +    // Part of the serial number encoded in Edid, used for monitor <-> sensor matching.
  37.159 +    const String        EdidSerialNumber;
  37.160 +    // Logical resolution is the display resolution in presentation terms.
  37.161 +    // That is to say, the resolution that represents the orientation the
  37.162 +    // display is projected to the user. For DK2, while being a portrait display
  37.163 +    // the display is held in landscape and therefore the logical resolution
  37.164 +    // is 1920x1080
  37.165 +    const Sizei         LogicalResolutionInPixels;
  37.166 +    // Native resolution is the resolution reported by the EDID and represents the
  37.167 +    // exact hardware resolution of the Rift. For example, on DK2
  37.168 +    // this is 1080x1920
  37.169 +    // In theory, an OS rotated Rift's native and logical resolutions should match
  37.170 +    const Sizei         NativeResolutionInPixels;
  37.171 +    // For displays that are attached to the desktop, this return value has meaning.
  37.172 +    // Otherwise it should always return origin
  37.173 +    const Vector2i      DesktopDisplayOffset;
  37.174 +	// For Windows machines this value stores the ChildUid used to identify this display
  37.175 +	const uint64_t	    DeviceNumber;
  37.176 +	// Stores the device specific default rotation of the screen
  37.177 +	// E.g. DK2 is rotated 90 degrees as it is a portrait display
  37.178 +	const uint32_t	    Rotation;
  37.179 +	// Is set if the Display is capable in Application-Only mode
  37.180 +	const bool			ApplicationExclusive;
  37.181 +
  37.182 +	// Functionality for rendering within the window
  37.183 +	virtual MirrorMode SetMirrorMode( MirrorMode newMode ) = 0;
  37.184 +
  37.185 +	// Functionality for enabling/disabling display
  37.186 +    virtual bool SetDisplaySleep(bool off)
  37.187 +    {
  37.188 +        // Override to implement if supported
  37.189 +        OVR_UNUSED(off);
  37.190 +        return false;
  37.191 +    }
  37.192 +
  37.193 +    // Check if right now the current rendering application should be in compatibility mode
  37.194 +    static bool InCompatibilityMode( bool displaySearch = true );
  37.195 +
  37.196 +    // Get/set the mode for all applications
  37.197 +    static bool GetDriverMode(bool& driverInstalled, bool& compatMode, bool& hideDK1Mode);
  37.198 +    static bool SetDriverMode(bool compatMode, bool hideDK1Mode);
  37.199 +
  37.200 +    static DisplaySearchHandle* GetDisplaySearchHandle();
  37.201 +};
  37.202 +
  37.203 +
  37.204 +} // namespace OVR
  37.205 +
  37.206 +#endif
    38.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    38.2 +++ b/LibOVR/Src/Displays/OVR_Linux_Display.cpp	Wed Jan 14 06:51:16 2015 +0200
    38.3 @@ -0,0 +1,494 @@
    38.4 +/************************************************************************************
    38.5 +
    38.6 +Filename    :   OVR_Linux_Display.cpp
    38.7 +Content     :   Linux-specific Display declarations
    38.8 +Created     :   July 2, 2014
    38.9 +Authors     :   James Hughes
   38.10 +
   38.11 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   38.12 +
   38.13 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
   38.14 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
   38.15 +which is provided at the time of installation or download, or which 
   38.16 +otherwise accompanies this software in either electronic or hard copy form.
   38.17 +
   38.18 +You may obtain a copy of the License at
   38.19 +
   38.20 +http://www.oculusvr.com/licenses/LICENSE-3.2 
   38.21 +
   38.22 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
   38.23 +distributed under the License is distributed on an "AS IS" BASIS,
   38.24 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   38.25 +See the License for the specific language governing permissions and
   38.26 +limitations under the License.
   38.27 +
   38.28 +*************************************************************************************/
   38.29 +
   38.30 +#include "OVR_Linux_Display.h"
   38.31 +#include "../Kernel/OVR_Log.h"
   38.32 +
   38.33 +#include "../../../3rdParty/EDID/edid.h"
   38.34 +
   38.35 +#include <X11/Xlib.h>
   38.36 +#include <X11/Xutil.h>
   38.37 +#include <X11/extensions/Xrandr.h>
   38.38 +#include <X11/Xatom.h>
   38.39 +
   38.40 +//-------------------------------------------------------------------------------------
   38.41 +// ***** Display enumeration Helpers
   38.42 +
   38.43 +namespace OVR { 
   38.44 +
   38.45 +static const uint8_t edid_v1_header[] = { 0x00, 0xff, 0xff, 0xff,
   38.46 +                                          0xff, 0xff, 0xff, 0x00 };
   38.47 +
   38.48 +static const uint8_t edid_v1_descriptor_flag[] = { 0x00, 0x00 };
   38.49 +
   38.50 +static const int DESCRIPTOR_DATA       =  5;
   38.51 +static const int UNKNOWN_DESCRIPTOR    = -1;
   38.52 +static const int DETAILED_TIMING_BLOCK = -2;
   38.53 +
   38.54 +// The following three functions were pulled from OVR_Linux_Display.cpp
   38.55 +// and modified slightly.
   38.56 +static int blockType(uint8_t* block)
   38.57 +{
   38.58 +  if (!strncmp((const char*)edid_v1_descriptor_flag, (const char*)block, 2))
   38.59 +  {
   38.60 +    if (block[2] != 0)
   38.61 +    {
   38.62 +      return UNKNOWN_DESCRIPTOR;
   38.63 +    }
   38.64 +    else
   38.65 +    {
   38.66 +      return block[3];
   38.67 +    }
   38.68 +  }
   38.69 +  else
   38.70 +  {
   38.71 +    return DETAILED_TIMING_BLOCK;
   38.72 +  }
   38.73 +}
   38.74 +
   38.75 +static char* getMonitorName(const uint8_t* block)
   38.76 +{
   38.77 +  static char     name[13];
   38.78 +  uint8_t const*  ptr = block + DESCRIPTOR_DATA;
   38.79 +
   38.80 +  for (int i = 0; i < 13; i++, ptr++)
   38.81 +  {
   38.82 +    if (*ptr == 0xa)
   38.83 +    {
   38.84 +      name[i] = 0;
   38.85 +      return name;
   38.86 +    }
   38.87 +
   38.88 +    name[i] = *ptr;
   38.89 +  }
   38.90 +
   38.91 +  return name;
   38.92 +}
   38.93 +
   38.94 +// Returns -1 on failure, 0 otherwise.
   38.95 +static int parseEdid(uint8_t* edid, Linux::DisplayEDID& edidResult)
   38.96 +{
   38.97 +  const int EDID_LENGTH                        = 0x80;
   38.98 +  const int EDID_HEADER                        = 0x00;
   38.99 +  const int EDID_HEADER_END                    = 0x07;
  38.100 +
  38.101 +  // const int EDID_STRUCT_VERSION                = 0x12;
  38.102 +  // const int EDID_STRUCT_REVISION               = 0x13;
  38.103 +
  38.104 +  const int MONITOR_NAME                       = 0xfc;
  38.105 +  // const int MONITOR_LIMITS                     = 0xfd;
  38.106 +  const int MONITOR_SERIAL                     = 0xff;
  38.107 +
  38.108 +  // const int ESTABLISHED_TIMING_1               = 0x23;
  38.109 +  // const int ESTABLISHED_TIMING_2               = 0x24;
  38.110 +  // const int MANUFACTURERS_TIMINGS              = 0x25;
  38.111 +
  38.112 +  const int DETAILED_TIMING_DESCRIPTIONS_START = 0x36;
  38.113 +  const int DETAILED_TIMING_DESCRIPTION_SIZE   = 18;
  38.114 +  const int NO_DETAILED_TIMING_DESCRIPTIONS    = 4;
  38.115 +
  38.116 +  // const int DETAILED_TIMING_DESCRIPTION_1      = 0x36;
  38.117 +  // const int DETAILED_TIMING_DESCRIPTION_2      = 0x48;
  38.118 +  // const int DETAILED_TIMING_DESCRIPTION_3      = 0x5a;
  38.119 +  // const int DETAILED_TIMING_DESCRIPTION_4      = 0x6c;
  38.120 +
  38.121 +  const char* monitorName = "Unknown";
  38.122 +  uint8_t*    block       = NULL;
  38.123 +  uint8_t     checksum    = 0;
  38.124 +
  38.125 +  for (int i = 0; i < EDID_LENGTH; i++)
  38.126 +  {
  38.127 +    checksum += edid[i];
  38.128 +  }
  38.129 +
  38.130 +  // Bad checksum, fail EDID
  38.131 +  if (checksum != 0)
  38.132 +  {
  38.133 +    return -1;
  38.134 +  }
  38.135 +
  38.136 +  if (strncmp((const char*)edid + EDID_HEADER,
  38.137 +              (const char*)edid_v1_header, EDID_HEADER_END + 1))
  38.138 +  {
  38.139 +    // First bytes don't match EDID version 1 header
  38.140 +    return -1;
  38.141 +  }
  38.142 +
  38.143 +  // Monitor name and timings
  38.144 +  char serialNumber[14];
  38.145 +  memset(serialNumber, 0, 14);
  38.146 +
  38.147 +  block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
  38.148 +
  38.149 +  for (int i = 0; i < NO_DETAILED_TIMING_DESCRIPTIONS;
  38.150 +       i++, block += DETAILED_TIMING_DESCRIPTION_SIZE)
  38.151 +  {
  38.152 +
  38.153 +    if (blockType(block) == MONITOR_NAME)
  38.154 +    {
  38.155 +      monitorName = getMonitorName(block);
  38.156 +    }
  38.157 +
  38.158 +    if (blockType(block) == MONITOR_SERIAL)
  38.159 +    {
  38.160 +      memcpy(serialNumber, block + 5, 13);
  38.161 +      break;
  38.162 +    }
  38.163 +  }
  38.164 +
  38.165 +  uint8_t vendorString[4] = {0};
  38.166 +
  38.167 +  vendorString[0] = (edid[8] >> 2 & 31) + 64;
  38.168 +  vendorString[1] = (((edid[8] & 3) << 3) | (edid[9] >> 5)) + 64;
  38.169 +  vendorString[2] = (edid[9] & 31) + 64;
  38.170 +
  38.171 +  edidResult.ModelNumber  = *(uint16_t*)&edid[10];
  38.172 +  edidResult.MonitorName  = monitorName;
  38.173 +  edidResult.VendorName   = reinterpret_cast<const char*>(vendorString);
  38.174 +  edidResult.SerialNumber = serialNumber;
  38.175 +
  38.176 +  // FIXME: Get timings as well
  38.177 +
  38.178 +  // std::cout << "# EDID version " << static_cast<int>(edid[EDID_STRUCT_VERSION])
  38.179 +  //           << " revision "      << static_cast<int>(edid[EDID_STRUCT_REVISION])
  38.180 +  //           << std::endl;
  38.181 +
  38.182 +  return 0;
  38.183 +}
  38.184 +
  38.185 +
  38.186 +// Returns -1 in the case of failure, 0 otherwise.
  38.187 +// Parameters:
  38.188 +//  data    OUT This pointer is modified to point to the output from
  38.189 +//              XRRGetOutputProperty. You *must* call XFree on this pointer.
  38.190 +//  dataLen OUT The length of the data returned in 'data'.
  38.191 +static int getXRRProperty(struct _XDisplay* display, RROutput output, Atom atom,
  38.192 +                          uint8_t** data, int* dataLen)
  38.193 +{
  38.194 +  unsigned long nitems;
  38.195 +  unsigned long bytesAfter;
  38.196 +  int           actualFormat;
  38.197 +  Atom          actualType;
  38.198 +
  38.199 +  int ret = XRRGetOutputProperty(display, output, atom, 0, 100,
  38.200 +                                 False, False, AnyPropertyType,
  38.201 +                                 &actualType, &actualFormat, &nitems,
  38.202 +                                 &bytesAfter, data);
  38.203 +
  38.204 +  if (None != ret)
  38.205 +  {
  38.206 +    *dataLen = nitems;
  38.207 +    return 0;
  38.208 +  }
  38.209 +  else
  38.210 +  {
  38.211 +    return -1;
  38.212 +  }
  38.213 +}
  38.214 +
  38.215 +static XRRModeInfo* findModeByXID(XRRScreenResources* screen, RRMode xid)
  38.216 +{
  38.217 +  for (int m = 0; m < screen->nmode; ++m)
  38.218 +  {
  38.219 +    XRRModeInfo* mode = &screen->modes[m];
  38.220 +    if (xid == mode->id)
  38.221 +    {
  38.222 +      return mode;
  38.223 +    }
  38.224 +  }
  38.225 +  return NULL;
  38.226 +}
  38.227 +
  38.228 +static int discoverExtendedRifts(OVR::Linux::DisplayDesc* descriptorArray, int inputArraySize, bool /*edidInfo*/)
  38.229 +{
  38.230 +    int result = 0;
  38.231 +
  38.232 +    struct _XDisplay* display = XOpenDisplay(NULL);
  38.233 +
  38.234 +    if (display == NULL)
  38.235 +    {
  38.236 +        OVR::LogError("[Linux Display] Unable to open X Display!");
  38.237 +        return 0;
  38.238 +    }
  38.239 +
  38.240 +    Atom EDIDAtom = XInternAtom(display, RR_PROPERTY_RANDR_EDID, False);
  38.241 +    int numScreens = XScreenCount(display);
  38.242 +    for (int i = 0; i < numScreens; ++i)
  38.243 +    {
  38.244 +        Window sr                       = XRootWindow(display, i);
  38.245 +        XRRScreenResources* screen      = XRRGetScreenResources(display, sr);
  38.246 +
  38.247 +        for (int ii = 0; ii < screen->ncrtc; ++ii)
  38.248 +        {
  38.249 +            XRRCrtcInfo* crtcInfo = XRRGetCrtcInfo(display, screen, screen->crtcs[ii]);
  38.250 +
  38.251 +            if (0 == crtcInfo->noutput)
  38.252 +            {
  38.253 +                XRRFreeCrtcInfo(crtcInfo);
  38.254 +                continue;
  38.255 +            }
  38.256 +
  38.257 +            bool foundOutput = false;
  38.258 +            RROutput output = crtcInfo->outputs[0];
  38.259 +            for (int k = 0; k < crtcInfo->noutput; ++k)
  38.260 +            {
  38.261 +                XRROutputInfo* outputInfo =
  38.262 +                    XRRGetOutputInfo(display, screen, crtcInfo->outputs[k]);
  38.263 +
  38.264 +                for (int kk = 0; kk < outputInfo->nmode; ++kk)
  38.265 +                {
  38.266 +                    if (outputInfo->modes[kk] == crtcInfo->mode)
  38.267 +                    {
  38.268 +                        output = crtcInfo->outputs[k];
  38.269 +                        foundOutput = true;
  38.270 +                        break;
  38.271 +                    }
  38.272 +                }
  38.273 +                XRRFreeOutputInfo(outputInfo);
  38.274 +                if (foundOutput)
  38.275 +                {
  38.276 +                    break;
  38.277 +                }
  38.278 +            }
  38.279 +
  38.280 +            if (!foundOutput)
  38.281 +            {
  38.282 +                XRRFreeCrtcInfo(crtcInfo);
  38.283 +                continue;
  38.284 +            }
  38.285 +
  38.286 +            XRROutputInfo* outputInfo = XRRGetOutputInfo(display, screen, output);
  38.287 +            if (RR_Connected != outputInfo->connection)
  38.288 +            {
  38.289 +                XRRFreeOutputInfo(outputInfo);
  38.290 +                XRRFreeCrtcInfo(crtcInfo);
  38.291 +                continue;
  38.292 +            }
  38.293 +
  38.294 +            // Read EDID associated with crtc.
  38.295 +            uint8_t* data    = NULL;
  38.296 +            int      dataLen = 0;
  38.297 +            if (getXRRProperty(display, output, EDIDAtom, &data, &dataLen) != 0)
  38.298 +            {
  38.299 +                // Identify rifts based on EDID.
  38.300 +                Linux::DisplayEDID edid;
  38.301 +                parseEdid(data, edid);
  38.302 +                XFree(data);
  38.303 +                data = NULL;
  38.304 +
  38.305 +                // TODO: Remove either this 3rdParty call to read EDID data
  38.306 +                //       or remove our own parsing of the EDID. Probably opt
  38.307 +                //       to remove our parsing.
  38.308 +                MonitorInfo* mi = read_edid_data(display, output);
  38.309 +                if (mi == NULL)
  38.310 +                {
  38.311 +                    XRRFreeOutputInfo(outputInfo);
  38.312 +                    XRRFreeCrtcInfo(crtcInfo);
  38.313 +                    continue;
  38.314 +                }
  38.315 +
  38.316 +                if (edid.VendorName == "OVR")
  38.317 +                {
  38.318 +                    if( result >= inputArraySize )
  38.319 +                    {
  38.320 +                        delete mi;
  38.321 +                        XRRFreeOutputInfo(outputInfo);
  38.322 +                        XRRFreeCrtcInfo(crtcInfo);
  38.323 +                        return result;
  38.324 +                    }
  38.325 +
  38.326 +                    XRRModeInfo* modeInfo = findModeByXID(screen, crtcInfo->mode);
  38.327 +
  38.328 +                    int width = modeInfo->width;
  38.329 +                    int height = modeInfo->height;
  38.330 +
  38.331 +                    if (   crtcInfo->rotation == RR_Rotate_90
  38.332 +                        || crtcInfo->rotation == RR_Rotate_270 )
  38.333 +                    {
  38.334 +                        width  = modeInfo->height;
  38.335 +                        height = modeInfo->width;
  38.336 +                    }
  38.337 +
  38.338 +                    int x = crtcInfo->x;
  38.339 +                    int y = crtcInfo->y;
  38.340 +
  38.341 +                    // Generate a device ID string similar Windows does it
  38.342 +                    char device_id[32];
  38.343 +                    OVR_sprintf(device_id, 32, "%s%04d-%d",
  38.344 +                                mi->manufacturer_code, mi->product_code,
  38.345 +                                screen->crtcs[ii]);
  38.346 +
  38.347 +                    OVR::Linux::DisplayDesc& desc = descriptorArray[result++];
  38.348 +                    desc.DisplayID                 = device_id;
  38.349 +                    desc.ModelName                 = edid.MonitorName;
  38.350 +                    desc.EdidSerialNumber          = edid.SerialNumber;
  38.351 +                    desc.LogicalResolutionInPixels = Sizei(width, height);
  38.352 +                    desc.DesktopDisplayOffset      = Vector2i(x, y);
  38.353 +
  38.354 +                    switch (mi->product_code)
  38.355 +                    {
  38.356 +                        case 3: desc.DeviceTypeGuess = HmdType_DK2;       break;
  38.357 +                        case 2: desc.DeviceTypeGuess = HmdType_DKHDProto; break;
  38.358 +                        case 1: desc.DeviceTypeGuess = HmdType_DK1;       break;
  38.359 +
  38.360 +                        default:
  38.361 +                        case 0: desc.DeviceTypeGuess = HmdType_Unknown;   break;
  38.362 +                    }
  38.363 +
  38.364 +                    // Hard-coded defaults in case the device doesn't have the
  38.365 +                    // data itself. DK2 prototypes (0003) or DK HD Prototypes (0002).
  38.366 +                    if (   desc.DeviceTypeGuess == HmdType_DK2
  38.367 +                        || desc.DeviceTypeGuess == HmdType_DKHDProto)
  38.368 +                    {
  38.369 +                        desc.LogicalResolutionInPixels = Sizei(1920, 1080);
  38.370 +                        desc.NativeResolutionInPixels  = Sizei(1080, 1920);
  38.371 +                    }
  38.372 +                    else
  38.373 +                    {
  38.374 +                        desc.LogicalResolutionInPixels = Sizei(width, height);
  38.375 +                        desc.NativeResolutionInPixels  = Sizei(width, height);
  38.376 +                    }
  38.377 +                }
  38.378 +
  38.379 +                delete mi;
  38.380 +                mi = NULL;
  38.381 +            }
  38.382 +
  38.383 +            XRRFreeOutputInfo(outputInfo);
  38.384 +            XRRFreeCrtcInfo(crtcInfo);
  38.385 +        }
  38.386 +
  38.387 +        XRRFreeScreenResources(screen);
  38.388 +    }
  38.389 +
  38.390 +    XCloseDisplay(display);
  38.391 +
  38.392 +    return result;
  38.393 +}
  38.394 +
  38.395 +
  38.396 +//-------------------------------------------------------------------------------------
  38.397 +// ***** Display 
  38.398 +
  38.399 +bool Display::Initialize()
  38.400 +{
  38.401 +    // Nothing to initialize. OS X only supports compatibility mode.
  38.402 +    return true;
  38.403 +}
  38.404 +
  38.405 +bool Display::GetDriverMode(bool& driverInstalled, bool& compatMode, bool& hideDK1Mode)
  38.406 +{
  38.407 +    driverInstalled = false;
  38.408 +    compatMode = true;
  38.409 +    hideDK1Mode = false;
  38.410 +    return true;
  38.411 +}
  38.412 +
  38.413 +bool Display::SetDriverMode(bool /*compatMode*/, bool /*hideDK1Mode*/)
  38.414 +{
  38.415 +    return false;
  38.416 +}
  38.417 +
  38.418 +DisplaySearchHandle* Display::GetDisplaySearchHandle()
  38.419 +{
  38.420 +	return new Linux::LinuxDisplaySearchHandle();
  38.421 +}
  38.422 +
  38.423 +bool Display::InCompatibilityMode( bool displaySearch )
  38.424 +{
  38.425 +	OVR_UNUSED( displaySearch );
  38.426 +    return true;
  38.427 +}
  38.428 +
  38.429 +int Display::GetDisplayCount(DisplaySearchHandle* handle, bool extended, bool applicationOnly, bool edidInfo)
  38.430 +{
  38.431 +    OVR_UNUSED4(handle, extended, applicationOnly, edidInfo);
  38.432 +
  38.433 +	static int extendedCount = -1;
  38.434 +
  38.435 +	Linux::LinuxDisplaySearchHandle* localHandle = (Linux::LinuxDisplaySearchHandle*)handle;
  38.436 +    if (localHandle == NULL)
  38.437 +    {
  38.438 +        OVR::LogError("[Linux Display] No search handle passed into GetDisplayCount. Return 0 rifts.");
  38.439 +        return 0;
  38.440 +    }
  38.441 +
  38.442 +    if (extendedCount == -1 || extended)
  38.443 +    {
  38.444 +        extendedCount = discoverExtendedRifts(localHandle->cachedDescriptorArray, Linux::LinuxDisplaySearchHandle::DescArraySize, edidInfo);
  38.445 +    }
  38.446 +
  38.447 +	localHandle->extended = true;
  38.448 +	localHandle->extendedDisplayCount = extendedCount;
  38.449 +	int totalCount = extendedCount;
  38.450 +
  38.451 +    /// FIXME: Implement application mode for OS X.
  38.452 +    localHandle->application = false;
  38.453 +    localHandle->applicationDisplayCount = 0;
  38.454 +
  38.455 +    localHandle->displayCount = totalCount;
  38.456 +
  38.457 +    return totalCount;
  38.458 +}
  38.459 +
  38.460 +
  38.461 +Ptr<Display> Display::GetDisplay( int index, DisplaySearchHandle* handle )
  38.462 +{
  38.463 +    Ptr<Display> result = NULL;
  38.464 +
  38.465 +    if (index < 0)
  38.466 +    {
  38.467 +        OVR::LogError("[Linux Display] Invalid index given to GetDisplay.");
  38.468 +        return NULL;
  38.469 +    }
  38.470 +
  38.471 +	Linux::LinuxDisplaySearchHandle* localHandle = (Linux::LinuxDisplaySearchHandle*)handle;
  38.472 +    if (localHandle == NULL)
  38.473 +    {
  38.474 +        OVR::LogError("[Linux Display] No search handle passed into GetDisplay. Return 0 rifts.");
  38.475 +        return NULL;
  38.476 +    }
  38.477 +
  38.478 +    if (localHandle->extended)
  38.479 +    {
  38.480 +        if (index >= 0 && index < (int)localHandle->extendedDisplayCount)
  38.481 +        {
  38.482 +            return *new Linux::LinuxDisplayGeneric(localHandle->cachedDescriptorArray[index]);
  38.483 +        }
  38.484 +
  38.485 +        index -= localHandle->extendedDisplayCount;
  38.486 +    }
  38.487 +
  38.488 +    if (localHandle->application)
  38.489 +    {
  38.490 +        OVR::LogError("[Linux Display] Mac does not support application displays.");
  38.491 +    }
  38.492 +
  38.493 +    return result;
  38.494 +}
  38.495 +
  38.496 +
  38.497 +} // namespace OVR
    39.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    39.2 +++ b/LibOVR/Src/Displays/OVR_Linux_Display.h	Wed Jan 14 06:51:16 2015 +0200
    39.3 @@ -0,0 +1,133 @@
    39.4 +/************************************************************************************
    39.5 +
    39.6 +Filename    :   OVR_Linux_Display.h
    39.7 +Content     :   Linux-specific Display declarations
    39.8 +Created     :   July 2, 2014
    39.9 +Authors     :   James Hughes
   39.10 +
   39.11 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   39.12 +
   39.13 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
   39.14 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
   39.15 +which is provided at the time of installation or download, or which 
   39.16 +otherwise accompanies this software in either electronic or hard copy form.
   39.17 +
   39.18 +You may obtain a copy of the License at
   39.19 +
   39.20 +http://www.oculusvr.com/licenses/LICENSE-3.2 
   39.21 +
   39.22 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
   39.23 +distributed under the License is distributed on an "AS IS" BASIS,
   39.24 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   39.25 +See the License for the specific language governing permissions and
   39.26 +limitations under the License.
   39.27 +
   39.28 +*************************************************************************************/
   39.29 +
   39.30 +#ifndef OVR_Linux_Display_h
   39.31 +#define OVR_Linux_Display_h
   39.32 +
   39.33 +#include "OVR_Display.h"
   39.34 +
   39.35 +namespace OVR { namespace Linux {
   39.36 +
   39.37 +
   39.38 +//-------------------------------------------------------------------------------------
   39.39 +// DisplayDesc
   39.40 +
   39.41 +// Display information enumerable through OS .
   39.42 +// TBD: Should we just move this to public header, so it's a const member of Display?
   39.43 +struct DisplayDesc
   39.44 +{
   39.45 +    HmdTypeEnum DeviceTypeGuess;
   39.46 +    String      DisplayID; // This is the device identifier string from MONITORINFO (for app usage)
   39.47 +    String      ModelName; // This is a "DK2" type string
   39.48 +    String      EdidSerialNumber;
   39.49 +    Sizei       LogicalResolutionInPixels;
   39.50 +    Sizei       NativeResolutionInPixels;
   39.51 +    Vector2i    DesktopDisplayOffset;
   39.52 +};
   39.53 +
   39.54 +
   39.55 +//-------------------------------------------------------------------------------------
   39.56 +// DisplayEDID
   39.57 +
   39.58 +// Describes EDID information as reported from our display driver.
   39.59 +struct DisplayEDID
   39.60 +{
   39.61 +    DisplayEDID() :
   39.62 +        ModelNumber(0)
   39.63 +    {}
   39.64 +
   39.65 +    String MonitorName;
   39.66 +    UInt16 ModelNumber;
   39.67 +    String VendorName;
   39.68 +    String SerialNumber;
   39.69 +};
   39.70 +
   39.71 +
   39.72 +//-------------------------------------------------------------------------------------
   39.73 +// Linux Display Search Handle
   39.74 +class LinuxDisplaySearchHandle : public DisplaySearchHandle
   39.75 +{
   39.76 +public:
   39.77 +    LinuxDisplaySearchHandle() :
   39.78 +        extended(false),
   39.79 +        application(false),
   39.80 +        extendedDisplayCount(0),
   39.81 +        applicationDisplayCount(0),
   39.82 +        displayCount(0)
   39.83 +    {}
   39.84 +    virtual ~LinuxDisplaySearchHandle()   {}
   39.85 +
   39.86 +    static const int DescArraySize = 16;
   39.87 +
   39.88 +    Linux::DisplayDesc  cachedDescriptorArray[DescArraySize];
   39.89 +    bool                extended;
   39.90 +    bool                application;
   39.91 +    int                 extendedDisplayCount;
   39.92 +    int                 applicationDisplayCount;
   39.93 +    int                 displayCount;
   39.94 +};
   39.95 +
   39.96 +//-------------------------------------------------------------------------------------
   39.97 +// LinuxDisplayGeneric
   39.98 +
   39.99 +// Describes Linux display in Compatibility mode, containing basic data
  39.100 +class LinuxDisplayGeneric : public Display
  39.101 +{
  39.102 +public:
  39.103 +    LinuxDisplayGeneric( const DisplayDesc& dd ) :
  39.104 +        Display(dd.DeviceTypeGuess,
  39.105 +                dd.DisplayID,
  39.106 +                dd.ModelName,
  39.107 +                dd.EdidSerialNumber,
  39.108 +                dd.LogicalResolutionInPixels,
  39.109 +                dd.NativeResolutionInPixels,
  39.110 +                dd.DesktopDisplayOffset,
  39.111 +                0,
  39.112 +                0,
  39.113 +				false)
  39.114 +    {
  39.115 +    }
  39.116 +
  39.117 +    virtual ~LinuxDisplayGeneric()
  39.118 +    {
  39.119 +    }
  39.120 +
  39.121 +    virtual bool InCompatibilityMode() const
  39.122 +    {
  39.123 +        return true;
  39.124 +    }
  39.125 +
  39.126 +    // Generic displays are not capable of mirroring
  39.127 +    virtual MirrorMode SetMirrorMode( MirrorMode newMode ) 
  39.128 +    { 
  39.129 +        OVR_UNUSED( newMode ); 
  39.130 +        return MirrorDisabled; 
  39.131 +    } 
  39.132 +};
  39.133 +
  39.134 +}} // namespace OVR::Linux
  39.135 +
  39.136 +#endif // OVR_Linux_Display_h
    40.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    40.2 +++ b/LibOVR/Src/Displays/OVR_Linux_SDKWindow.cpp	Wed Jan 14 06:51:16 2015 +0200
    40.3 @@ -0,0 +1,649 @@
    40.4 +/*******************************************************************************
    40.5 +
    40.6 +Filename    :   OVR_Linux_SDKWindow.cpp
    40.7 +Content     :   SDK generated Linux window.
    40.8 +Created     :   October 1, 2014
    40.9 +Authors     :   James Hughes
   40.10 +
   40.11 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   40.12 +
   40.13 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
   40.14 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
   40.15 +which is provided at the time of installation or download, or which 
   40.16 +otherwise accompanies this software in either electronic or hard copy form.
   40.17 +
   40.18 +You may obtain a copy of the License at
   40.19 +
   40.20 +http://www.oculusvr.com/licenses/LICENSE-3.2 
   40.21 +
   40.22 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
   40.23 +distributed under the License is distributed on an "AS IS" BASIS,
   40.24 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   40.25 +See the License for the specific language governing permissions and
   40.26 +limitations under the License.
   40.27 +
   40.28 +*******************************************************************************/
   40.29 +
   40.30 +#include "OVR_Linux_SDKWindow.h"
   40.31 +#include "../Kernel/OVR_Log.h"
   40.32 +#include "../Kernel/OVR_Log.h"
   40.33 +#include "../../../3rdParty/EDID/edid.h"
   40.34 +
   40.35 +namespace OVR {
   40.36 +
   40.37 +// Forward declarations
   40.38 +static Window       constructWindow(struct _XDisplay* display, int xscreen,
   40.39 +                                    XVisualInfo* xvisual,
   40.40 +                                    const LinuxDeviceScreen& screen);
   40.41 +
   40.42 +static XRRModeInfo* findModeByXID(XRRScreenResources* screen, RRMode xid)
   40.43 +{
   40.44 +  for (int m = 0; m < screen->nmode; ++m)
   40.45 +  {
   40.46 +    XRRModeInfo* mode = &screen->modes[m];
   40.47 +    if (xid == mode->id)
   40.48 +    {
   40.49 +      return mode;
   40.50 +    }
   40.51 +  }
   40.52 +  return NULL;
   40.53 +}
   40.54 +
   40.55 +/// Retrieves a list of available device screens on which we can build
   40.56 +/// SDK windows. Returns number of devices found.
   40.57 +///   screens        Array which this function will populate.
   40.58 +///   maxNumScreens  Maximum number of screens to store in screens.
   40.59 +static int getDeviceScreens(LinuxDeviceScreen* screens, int maxNumDevices)
   40.60 +{
   40.61 +    struct _XDisplay* disp = XOpenDisplay(NULL);
   40.62 +    if (!disp)
   40.63 +    {
   40.64 +        OVR::LogError("[SDKWindow] Unable to open X Display.");
   40.65 +        return 0;
   40.66 +    }
   40.67 +
   40.68 +    int numDevices = 0;
   40.69 +    int numScreens = XScreenCount(disp);
   40.70 +    for (int i = 0; i < numScreens; ++i)
   40.71 +    {
   40.72 +        // Screen root is used to detect what video output the crtc is using.
   40.73 +        Window sr                  = XRootWindow(disp, i);
   40.74 +        XRRScreenResources* screen = XRRGetScreenResources(disp, sr);
   40.75 +
   40.76 +        for (int ii = 0; ii < screen->ncrtc; ++ii)
   40.77 +        {
   40.78 +            XRRCrtcInfo* crtcInfo = XRRGetCrtcInfo(disp, screen, screen->crtcs[ii]);
   40.79 +
   40.80 +            if (0 == crtcInfo->noutput)
   40.81 +            {
   40.82 +                XRRFreeCrtcInfo(crtcInfo);
   40.83 +                continue;
   40.84 +            }
   40.85 +
   40.86 +            bool foundOutput = false;
   40.87 +            RROutput output = crtcInfo->outputs[0];
   40.88 +            for (int k = 0; k < crtcInfo->noutput; ++k)
   40.89 +            {
   40.90 +                XRROutputInfo* outputInfo =
   40.91 +                    XRRGetOutputInfo(disp, screen, crtcInfo->outputs[k]);
   40.92 +                for (int kk = 0 ; kk < outputInfo->nmode; ++kk)
   40.93 +                {
   40.94 +                    if (outputInfo->modes[kk] == crtcInfo->mode)
   40.95 +                    {
   40.96 +                        output = crtcInfo->outputs[k];
   40.97 +                        foundOutput = true;
   40.98 +                        break;
   40.99 +                    }
  40.100 +                }
  40.101 +                XRRFreeOutputInfo(outputInfo);
  40.102 +                if (foundOutput) { break; }
  40.103 +            }
  40.104 +
  40.105 +            if (!foundOutput)
  40.106 +            {
  40.107 +                XRRFreeCrtcInfo(crtcInfo);
  40.108 +                continue;
  40.109 +            }
  40.110 +
  40.111 +            XRROutputInfo* outputInfo = XRRGetOutputInfo(disp, screen, output);
  40.112 +            if (RR_Connected != outputInfo->connection)
  40.113 +            {
  40.114 +                XRRFreeOutputInfo(outputInfo);
  40.115 +                XRRFreeCrtcInfo(crtcInfo);
  40.116 +                continue;
  40.117 +            }
  40.118 +
  40.119 +            // Read EDID associated with crtc.
  40.120 +            MonitorInfo* mi = read_edid_data(disp, output);
  40.121 +            if (mi == NULL)
  40.122 +            {
  40.123 +                XRRFreeOutputInfo(outputInfo);
  40.124 +                XRRFreeCrtcInfo(crtcInfo);
  40.125 +                continue;
  40.126 +            }
  40.127 +
  40.128 +            if (strcmp(mi->manufacturer_code, "OVR") == 0)
  40.129 +            {
  40.130 +                XRRModeInfo* modeInfo = findModeByXID(screen, crtcInfo->mode);
  40.131 +
  40.132 +                DistortionRotation desiredRot = DistRotateNone;
  40.133 +                if (mi->product_code == 3)
  40.134 +                {
  40.135 +                    // This is a DK2, we may have to rotate our output.
  40.136 +                    // If we don't have to, we should alert the user that
  40.137 +                    // rotating the display using the DM or graphics
  40.138 +                    // card settings is highly non-optimal.
  40.139 +                    desiredRot = DistRotateCCW90;
  40.140 +                    if (crtcInfo->rotation != RR_Rotate_0)
  40.141 +                    {
  40.142 +                        OVR::LogError("Please do not rotate your rift's screen.");
  40.143 +
  40.144 +                        if (crtcInfo->rotation == RR_Rotate_90)
  40.145 +                        {
  40.146 +                            // The user has manually rotated the screen.
  40.147 +                            // So apply no rotation on our end.
  40.148 +                            desiredRot = DistRotateNone;
  40.149 +                        }
  40.150 +                    }
  40.151 +                }
  40.152 +                else
  40.153 +                {
  40.154 +                    if (crtcInfo->rotation != RR_Rotate_0)
  40.155 +                    {
  40.156 +                        OVR::LogError("Please do not rotate your rift's screen.");
  40.157 +                    }
  40.158 +                }
  40.159 +
  40.160 +                int width = modeInfo->width;
  40.161 +                int height = modeInfo->height;
  40.162 +
  40.163 +                // Swap width / height if display is rotated (shouldn't be on linux).
  40.164 +                if (   crtcInfo->rotation == RR_Rotate_90
  40.165 +                    || crtcInfo->rotation == RR_Rotate_270)
  40.166 +                {
  40.167 +                    width  = modeInfo->height;
  40.168 +                    height = modeInfo->width;
  40.169 +                }
  40.170 +
  40.171 +                // Push detected monitor.
  40.172 +                screens[numDevices].set(i, screen->crtcs[ii], desiredRot,
  40.173 +                                        mi->product_code, width, height,
  40.174 +                                        crtcInfo->x, crtcInfo->y);
  40.175 +                ++numDevices;
  40.176 +            }
  40.177 +
  40.178 +            delete mi;
  40.179 +
  40.180 +            if (numDevices == maxNumDevices)
  40.181 +            {
  40.182 +                XRRFreeOutputInfo(outputInfo);
  40.183 +                XRRFreeCrtcInfo(crtcInfo);
  40.184 +                XRRFreeScreenResources(screen);
  40.185 +                OVR::LogError("[SDKWindow] Maxed out number of devices..");
  40.186 +                XCloseDisplay(disp);
  40.187 +                return numDevices;
  40.188 +            }
  40.189 +
  40.190 +            XRRFreeOutputInfo(outputInfo);
  40.191 +            XRRFreeCrtcInfo(crtcInfo);
  40.192 +        }
  40.193 +
  40.194 +        XRRFreeScreenResources(screen);
  40.195 +    }
  40.196 +    XCloseDisplay(disp);
  40.197 +    return numDevices;
  40.198 +}
  40.199 +
  40.200 +
  40.201 +LinuxDeviceScreen SDKWindow::findDevScreenForHMD(const ovrHmd& hmd)
  40.202 +{
  40.203 +    return findDevScreenForDevID(hmd->DisplayDeviceName);
  40.204 +}
  40.205 +
  40.206 +LinuxDeviceScreen SDKWindow::findDevScreenForDevID(const char* deviceIDIn)
  40.207 +{
  40.208 +    const int maxNumDevices = 5;
  40.209 +    LinuxDeviceScreen screens[maxNumDevices];
  40.210 +    int numDevices = getDeviceScreens(screens, maxNumDevices);
  40.211 +
  40.212 +    if (numDevices > 0)
  40.213 +    {
  40.214 +        // Identify target for SDK window via hmd info.
  40.215 +        for (int i = 0; i < numDevices; ++i)
  40.216 +        {
  40.217 +            LinuxDeviceScreen& screen = screens[i];
  40.218 +
  40.219 +            char deviceID[32];
  40.220 +            OVR_sprintf(deviceID, 32, "OVR%04d-%d",
  40.221 +                        screen.productCode, screen.crtcid);
  40.222 +
  40.223 +            if (strcmp(deviceIDIn, deviceID) == 0)
  40.224 +            {
  40.225 +                return screen;
  40.226 +            }
  40.227 +        }
  40.228 +    }
  40.229 +
  40.230 +    return LinuxDeviceScreen();
  40.231 +}
  40.232 +
  40.233 +DistortionRotation SDKWindow::getRotation(const ovrHmd& hmd)
  40.234 +{
  40.235 +    LinuxDeviceScreen screen = findDevScreenForHMD(hmd);
  40.236 +    if (screen.isValid())
  40.237 +    {
  40.238 +        return screen.rotation;
  40.239 +    }
  40.240 +    else
  40.241 +    {
  40.242 +        return DistRotateNone;
  40.243 +    }
  40.244 +}
  40.245 +
  40.246 +
  40.247 +bool SDKWindow::getVisualFromDrawable(GLXDrawable drawable, XVisualInfo* vinfoOut)
  40.248 +{
  40.249 +    struct _XDisplay* display = glXGetCurrentDisplay();
  40.250 +
  40.251 +    unsigned int value;
  40.252 +    glXQueryDrawable(display, drawable, GLX_FBCONFIG_ID, &value);
  40.253 +    const int attribs[] = {GLX_FBCONFIG_ID, (int)value, None};
  40.254 +    int screen;
  40.255 +    glXQueryContext(display, glXGetCurrentContext(), GLX_SCREEN, &screen);
  40.256 +    int numElems;
  40.257 +    GLXFBConfig* config = glXChooseFBConfig(display, screen, attribs, &numElems);
  40.258 +    if (numElems > 0)
  40.259 +    {
  40.260 +        XVisualInfo* chosen = glXGetVisualFromFBConfig(display, *config);
  40.261 +        *vinfoOut = *chosen;
  40.262 +        XFree(config);
  40.263 +        return true;
  40.264 +    }
  40.265 +    return false;
  40.266 +}
  40.267 +
  40.268 +SDKWindow::SDKWindow(const ovrHmd& hmd) :
  40.269 +    mXDisplay(NULL),
  40.270 +    mXScreen(-1),
  40.271 +    mXVisual(NULL),
  40.272 +    mXUniqueContext(-1),
  40.273 +    mXWindow(0),
  40.274 +    mFBConfigID(0)
  40.275 +{
  40.276 +    OVR_UNUSED(hmd);
  40.277 +}
  40.278 +
  40.279 +SDKWindow::~SDKWindow()
  40.280 +{
  40.281 +    if (mXWindow)
  40.282 +    {
  40.283 +        XDeleteContext(mXDisplay, mXWindow, mXUniqueContext);
  40.284 +        XUnmapWindow(mXDisplay, mXWindow);
  40.285 +        XDestroyWindow(mXDisplay, mXWindow);
  40.286 +        mXWindow = static_cast<Window>(0);
  40.287 +    }
  40.288 +
  40.289 +    if (mXVisual)
  40.290 +    {
  40.291 +        XFree(mXVisual);
  40.292 +        mXVisual = NULL;
  40.293 +    }
  40.294 +
  40.295 +    if (mXDisplay)
  40.296 +    {
  40.297 +        XCloseDisplay(mXDisplay);
  40.298 +    }
  40.299 +}
  40.300 +
  40.301 +void SDKWindow::buildVisualAndWindow(const LinuxDeviceScreen& devScreen)
  40.302 +{
  40.303 +    mXDisplay       = XOpenDisplay(NULL);
  40.304 +    mXUniqueContext = XUniqueContext();
  40.305 +    mXScreen        = devScreen.screen;
  40.306 +    mFBConfigID     = chooseFBConfigID(mXDisplay, mXScreen);
  40.307 +
  40.308 +    mXVisual = getVisual(mXDisplay, mFBConfigID, mXScreen);
  40.309 +    if (mXVisual != NULL)
  40.310 +    {
  40.311 +        mXWindow = constructWindow(mXDisplay, mXScreen, mXVisual, devScreen);
  40.312 +        mDeviceScreen = devScreen;
  40.313 +    }
  40.314 +}
  40.315 +
  40.316 +// Used in chooseVisual. May need to expose this to the end use so they can
  40.317 +// choose an appropriate framebuffer configuration.
  40.318 +struct FBConfig
  40.319 +{
  40.320 +  FBConfig() :
  40.321 +      redBits(8),
  40.322 +      greenBits(8),
  40.323 +      blueBits(8),
  40.324 +      alphaBits(8),
  40.325 +      depthBits(8),
  40.326 +      stencilBits(-1),
  40.327 +      doubleBuffer(true),
  40.328 +      auxBuffers(-1)
  40.329 +  {}
  40.330 +
  40.331 +  int  redBits;
  40.332 +  int  greenBits;
  40.333 +  int  blueBits;
  40.334 +  int  alphaBits;
  40.335 +  int  depthBits;
  40.336 +  int  stencilBits;
  40.337 +  bool doubleBuffer;
  40.338 +  int  auxBuffers;
  40.339 +
  40.340 +  int xcfg;
  40.341 +};
  40.342 +
  40.343 +static int fbCalcContrib(int desired, int current)
  40.344 +{
  40.345 +    int diff = desired - current;
  40.346 +    if (current != -1) { return diff * diff; }
  40.347 +    else               { return 0; }
  40.348 +}
  40.349 +
  40.350 +// Choose frame buffer configuration and return fbConfigID.
  40.351 +int SDKWindow::chooseFBConfigID(struct _XDisplay* display, int xscreen)
  40.352 +{
  40.353 +    int nativeCount = 0;
  40.354 +    GLXFBConfig* nativeConfigs =
  40.355 +        glXGetFBConfigs(display, xscreen, &nativeCount);
  40.356 +    if (!nativeCount)
  40.357 +    {
  40.358 +        OVR::LogError("[SDKWindow] No valid frame buffer configurations found.");
  40.359 +        return 0;
  40.360 +    }
  40.361 +
  40.362 +    FBConfig* usables = static_cast<FBConfig*>(calloc(nativeCount, sizeof(FBConfig)));
  40.363 +    int numUsables = 0;
  40.364 +
  40.365 +    for (int i = 0; i < nativeCount; ++i)
  40.366 +    {
  40.367 +        GLXFBConfig native = nativeConfigs[i];
  40.368 +        FBConfig* usable   = &usables[numUsables];
  40.369 +        int v              = 0;
  40.370 +
  40.371 +        // Only frame buffer configcs with attached visuals.
  40.372 +        glXGetFBConfigAttrib(display, native, GLX_VISUAL_ID, &v);
  40.373 +        if (!v) { continue; }
  40.374 +
  40.375 +        // Only RGBA frame buffers.
  40.376 +        glXGetFBConfigAttrib(display, native, GLX_RENDER_TYPE, &v);
  40.377 +        if (!(v & GLX_RGBA_BIT)) { continue; }
  40.378 +
  40.379 +        glXGetFBConfigAttrib(display, native, GLX_DRAWABLE_TYPE, &v);
  40.380 +        if (!(v & GLX_WINDOW_BIT)) { continue; }
  40.381 +
  40.382 +        glXGetFBConfigAttrib(display, native, GLX_DEPTH_SIZE,   &usable->depthBits);
  40.383 +        glXGetFBConfigAttrib(display, native, GLX_STENCIL_SIZE, &usable->stencilBits);
  40.384 +
  40.385 +        glXGetFBConfigAttrib(display, native, GLX_RED_SIZE,     &usable->redBits);
  40.386 +        glXGetFBConfigAttrib(display, native, GLX_GREEN_SIZE,   &usable->greenBits);
  40.387 +        glXGetFBConfigAttrib(display, native, GLX_BLUE_SIZE,    &usable->blueBits);
  40.388 +        glXGetFBConfigAttrib(display, native, GLX_ALPHA_SIZE,   &usable->alphaBits);
  40.389 +
  40.390 +        glXGetFBConfigAttrib(display, native, GLX_ALPHA_SIZE,   &usable->auxBuffers);
  40.391 +
  40.392 +        glXGetFBConfigAttrib(display, native, GLX_DOUBLEBUFFER, &v);
  40.393 +        usable->doubleBuffer = v ? true : false;
  40.394 +
  40.395 +        glXGetFBConfigAttrib(display, native, GLX_FBCONFIG_ID, &usable->xcfg);
  40.396 +
  40.397 +        ++numUsables;
  40.398 +    }
  40.399 +
  40.400 +    // We really want std::numeric_limits<int>::max() instead of hardcoded vals.
  40.401 +    const int MostMissing = 100;
  40.402 +    int leastMissing      = MostMissing;
  40.403 +    int leastBias         = MostMissing;
  40.404 +
  40.405 +    const FBConfig* closest = NULL;
  40.406 +    
  40.407 +    // Desired is currently the default config built by constructor.
  40.408 +    FBConfig desired;
  40.409 +
  40.410 +    for (int i = 0; i < numUsables; ++i)
  40.411 +    {
  40.412 +        const FBConfig* cur = &usables[i];
  40.413 +
  40.414 +        if (desired.doubleBuffer != cur->doubleBuffer) { continue; }
  40.415 +
  40.416 +        int missing = 0;
  40.417 +        if (desired.alphaBits > 0 && cur->alphaBits == 0) { ++missing; }
  40.418 +        if (desired.depthBits > 0 && cur->depthBits == 0) { ++missing; }
  40.419 +        if (desired.stencilBits > 0 && cur->stencilBits == 0) { ++missing; }
  40.420 +        if (desired.redBits > 0 && desired.redBits != cur->redBits) { ++missing; }
  40.421 +        if (desired.greenBits > 0 && desired.greenBits != cur->greenBits) { ++missing; }
  40.422 +        if (desired.blueBits > 0 && desired.blueBits != cur->blueBits) { ++missing; }
  40.423 +
  40.424 +        int bias = fbCalcContrib(desired.redBits,     cur->redBits)
  40.425 +                 + fbCalcContrib(desired.greenBits,   cur->greenBits)
  40.426 +                 + fbCalcContrib(desired.blueBits,    cur->blueBits)
  40.427 +                 + fbCalcContrib(desired.alphaBits,   cur->alphaBits)
  40.428 +                 + fbCalcContrib(desired.depthBits,   cur->depthBits)
  40.429 +                 + fbCalcContrib(desired.stencilBits, cur->stencilBits);
  40.430 +
  40.431 +        if (missing < leastMissing)
  40.432 +        {
  40.433 +            closest = cur;
  40.434 +        }
  40.435 +        else if (missing == leastMissing)
  40.436 +        {
  40.437 +            // Now select against squared differences.
  40.438 +            if (bias < leastBias)
  40.439 +            {
  40.440 +                closest = cur;
  40.441 +            }
  40.442 +        }
  40.443 +
  40.444 +        if (closest == cur)
  40.445 +        {
  40.446 +            leastMissing = missing;
  40.447 +            leastBias    = bias;
  40.448 +        }
  40.449 +    }
  40.450 +
  40.451 +    if (closest == NULL)
  40.452 +    {
  40.453 +        OVR::LogError("[SDKWindow] Failed to select appropriate frame buffer.");
  40.454 +        XFree(nativeConfigs);
  40.455 +        free(usables);
  40.456 +        return 0;
  40.457 +    }
  40.458 +
  40.459 +    int retVal = closest->xcfg;
  40.460 +
  40.461 +    XFree(nativeConfigs);
  40.462 +    free(usables);
  40.463 +
  40.464 +    return retVal;
  40.465 +}
  40.466 +
  40.467 +// Obtain visual from frame buffer configuration ID.
  40.468 +XVisualInfo* SDKWindow::getVisual(struct _XDisplay* display,
  40.469 +                                  int fbConfigID, int xscreen)
  40.470 +{
  40.471 +    GLXFBConfig* cfg = getGLXFBConfig(display, fbConfigID, xscreen);
  40.472 +    XVisualInfo* viOut = NULL;
  40.473 +    if (cfg != NULL)
  40.474 +    {
  40.475 +        viOut = glXGetVisualFromFBConfig(display, *cfg);
  40.476 +        XFree(cfg);
  40.477 +        cfg = NULL;
  40.478 +    }
  40.479 +    else
  40.480 +    {
  40.481 +        OVR::LogError("Unable to find fb config ID.");
  40.482 +    }
  40.483 +    return viOut;
  40.484 +}
  40.485 +
  40.486 +// GLXFBConfig pointer from frame buffer configuration ID. You must call
  40.487 +// XFree on the GLXFBConfig pointer.
  40.488 +GLXFBConfig* SDKWindow::getGLXFBConfig(struct _XDisplay* display,
  40.489 +                                       int fbConfigID, int xscreen)
  40.490 +{
  40.491 +    const int attribs[] = {GLX_FBCONFIG_ID, (int)fbConfigID, None};
  40.492 +    int numElems;
  40.493 +
  40.494 +    GLXFBConfig* config = glXChooseFBConfig(display, xscreen, attribs, &numElems);
  40.495 +    if (numElems > 0)
  40.496 +    {
  40.497 +        return config;
  40.498 +    }
  40.499 +    else
  40.500 +    {
  40.501 +        return NULL;
  40.502 +    }
  40.503 +}
  40.504 +
  40.505 +
  40.506 +static int gXLastError = -1;
  40.507 +static int handleXError(struct _XDisplay* display, XErrorEvent* event)
  40.508 +{
  40.509 +  OVR_UNUSED(display);
  40.510 +  gXLastError = event->error_code;
  40.511 +  return 0;
  40.512 +}
  40.513 +
  40.514 +static void obtainXErrorHandler()
  40.515 +{
  40.516 +  gXLastError = Success;
  40.517 +  XSetErrorHandler(handleXError);
  40.518 +}
  40.519 +
  40.520 +static void releaseXErrorHandler(struct _XDisplay* display)
  40.521 +{
  40.522 +  XSync(display, False);
  40.523 +  XSetErrorHandler(NULL);
  40.524 +}
  40.525 +
  40.526 +// Returns 0 on error, otherwise a valid X window is returned.
  40.527 +static Window constructWindow(struct _XDisplay* xDisp, int xScreen,
  40.528 +                              XVisualInfo* xVisual,
  40.529 +                              const LinuxDeviceScreen& devScreen)
  40.530 +{
  40.531 +    XSetWindowAttributes wa;
  40.532 +
  40.533 +    Window root       = XRootWindow(xDisp, xScreen);
  40.534 +    Window xWindowOut = 0;
  40.535 +
  40.536 +    // Create Window
  40.537 +    {
  40.538 +        Colormap xWinColorMapOut = XCreateColormap(
  40.539 +            xDisp, root, xVisual->visual, AllocNone);
  40.540 +        unsigned long wamask = CWBorderPixel | CWColormap | CWEventMask;
  40.541 +
  40.542 +        wa.colormap = xWinColorMapOut;
  40.543 +        wa.border_pixel = 0;
  40.544 +        wa.event_mask = StructureNotifyMask  | ExposureMask    | FocusChangeMask
  40.545 +                      | VisibilityChangeMask | EnterWindowMask | LeaveWindowMask
  40.546 +                      | PropertyChangeMask;
  40.547 +
  40.548 +        obtainXErrorHandler();
  40.549 +
  40.550 +        xWindowOut = XCreateWindow(xDisp, root,
  40.551 +                                   0, 0,
  40.552 +                                   devScreen.width, devScreen.height,
  40.553 +                                   0,
  40.554 +                                   xVisual->depth,
  40.555 +                                   InputOutput,
  40.556 +                                   xVisual->visual,
  40.557 +                                   wamask,
  40.558 +                                   &wa);
  40.559 +
  40.560 +        releaseXErrorHandler(xDisp);
  40.561 +
  40.562 +        if (!xWindowOut)
  40.563 +        {
  40.564 +            OVR::LogError("[SDKWindow] Failed to create SDK window.");
  40.565 +            return 0;
  40.566 +        }
  40.567 +
  40.568 +        XFreeColormap(xDisp, xWinColorMapOut);
  40.569 +    }
  40.570 +
  40.571 +    // OVERRIDE REDIRECT.
  40.572 +    XSetWindowAttributes attributes;
  40.573 +    attributes.override_redirect = True;
  40.574 +    XChangeWindowAttributes(xDisp, xWindowOut,
  40.575 +                            CWOverrideRedirect, &attributes);
  40.576 +
  40.577 +    // Show the window (do this in full screen or windowed).
  40.578 +    XMapRaised(xDisp, xWindowOut);
  40.579 +    XFlush(xDisp);
  40.580 +
  40.581 +    // Position ourselves manually since there should be no WM managing us.
  40.582 +    XRaiseWindow(xDisp, xWindowOut);
  40.583 +    XMoveWindow(xDisp, xWindowOut, devScreen.offsetX, devScreen.offsetY);
  40.584 +    XResizeWindow(xDisp, xWindowOut, devScreen.width, devScreen.height);
  40.585 +
  40.586 +    XFlush(xDisp);
  40.587 +
  40.588 +    // WM Backup in case there still exists a WM managing us...
  40.589 +    Atom NET_WM_BYPASS_COMPOSITOR = 
  40.590 +        XInternAtom(xDisp, "_NET_WM_BYPASS_COMPOSITOR", False);
  40.591 +    Atom NET_WM_STATE =
  40.592 +        XInternAtom(xDisp, "_NET_WM_STATE", False);
  40.593 +    Atom NET_WM_STATE_FULLSCREEN =
  40.594 +        XInternAtom(xDisp, "_NET_WM_STATE_FULLSCREEN", False);
  40.595 +    Atom NET_ACTIVE_WINDOW =
  40.596 +        XInternAtom(xDisp, "_NET_ACTIVE_WINDOW", False);
  40.597 +
  40.598 +    // Bypass compositor if we are under a compositing WM.
  40.599 +    // Just in case a WM ignores our override_redirect.
  40.600 +    if (NET_WM_BYPASS_COMPOSITOR)
  40.601 +    {
  40.602 +        const unsigned long bypass = 1;
  40.603 +        XChangeProperty(xDisp, xWindowOut,
  40.604 +                        NET_WM_BYPASS_COMPOSITOR,
  40.605 +                        XA_CARDINAL, 32, PropModeReplace,
  40.606 +                        (unsigned char*)&bypass, 1);
  40.607 +    }
  40.608 +
  40.609 +    if (NET_WM_STATE && NET_WM_STATE_FULLSCREEN)
  40.610 +    {
  40.611 +        // BACKUP: If we are still managed by a WM we want fullscreen.
  40.612 +        const int EWMH_STATE_ADD    = 1;
  40.613 +
  40.614 +        if (NET_ACTIVE_WINDOW)
  40.615 +        {
  40.616 +            XEvent event;
  40.617 +            memset(&event, 0, sizeof(event));
  40.618 +
  40.619 +            event.type = ClientMessage;
  40.620 +            event.xclient.window = xWindowOut;
  40.621 +            event.xclient.format = 32;
  40.622 +            event.xclient.message_type = NET_ACTIVE_WINDOW;
  40.623 +            event.xclient.data.l[0] = 1;
  40.624 +            event.xclient.data.l[1] = 0;
  40.625 +
  40.626 +            XSendEvent(xDisp, root, False,
  40.627 +                       SubstructureNotifyMask | SubstructureRedirectMask,
  40.628 +                       &event);
  40.629 +        }
  40.630 +
  40.631 +        XEvent event;
  40.632 +        memset(&event, 0, sizeof(event));
  40.633 +
  40.634 +        event.type = ClientMessage;
  40.635 +        event.xclient.window = xWindowOut;
  40.636 +        event.xclient.format = 32;
  40.637 +        event.xclient.message_type = NET_WM_STATE;
  40.638 +        event.xclient.data.l[0] = EWMH_STATE_ADD;
  40.639 +        event.xclient.data.l[1] = NET_WM_STATE_FULLSCREEN;
  40.640 +        event.xclient.data.l[2] = 0;
  40.641 +        event.xclient.data.l[3] = 1;
  40.642 +
  40.643 +        XSendEvent(xDisp, root, False,
  40.644 +                   SubstructureNotifyMask | SubstructureRedirectMask,
  40.645 +                   &event);
  40.646 +    }
  40.647 +
  40.648 +    return xWindowOut;
  40.649 +}
  40.650 +
  40.651 +} // namespace OVR
  40.652 +
    41.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    41.2 +++ b/LibOVR/Src/Displays/OVR_Linux_SDKWindow.h	Wed Jan 14 06:51:16 2015 +0200
    41.3 @@ -0,0 +1,147 @@
    41.4 +/*******************************************************************************
    41.5 +
    41.6 +Filename    :   OVR_Linux_SDKWindow.h
    41.7 +Content     :   SDK generated Linux window.
    41.8 +Created     :   October 1, 2014
    41.9 +Authors     :   James Hughes
   41.10 +
   41.11 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   41.12 +
   41.13 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
   41.14 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
   41.15 +which is provided at the time of installation or download, or which 
   41.16 +otherwise accompanies this software in either electronic or hard copy form.
   41.17 +
   41.18 +You may obtain a copy of the License at
   41.19 +
   41.20 +http://www.oculusvr.com/licenses/LICENSE-3.2 
   41.21 +
   41.22 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
   41.23 +distributed under the License is distributed on an "AS IS" BASIS,
   41.24 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   41.25 +See the License for the specific language governing permissions and
   41.26 +limitations under the License.
   41.27 +
   41.28 +*******************************************************************************/
   41.29 +
   41.30 +#ifndef OVR_Linux_SDKWindow_h
   41.31 +#define OVR_Linux_SDKWindow_h
   41.32 +
   41.33 +#include "../OVR_CAPI.h"
   41.34 +#include "../CAPI/GL/CAPI_GL_Util.h"
   41.35 +
   41.36 +#include <X11/Xlib.h>
   41.37 +#include <X11/Xatom.h>
   41.38 +#include <X11/extensions/Xrandr.h>
   41.39 +#include <X11/Xresource.h>
   41.40 +#include <GL/glx.h>
   41.41 +
   41.42 +namespace OVR {
   41.43 +
   41.44 +enum DistortionRotation
   41.45 +{
   41.46 +    DistRotateNone,
   41.47 +    DistRotateCCW90
   41.48 +};
   41.49 +
   41.50 +struct LinuxDeviceScreen
   41.51 +{
   41.52 +    LinuxDeviceScreen() :
   41.53 +        screen(-1),
   41.54 +        crtcid(0),
   41.55 +        rotation(DistRotateNone),
   41.56 +        productCode(-1),
   41.57 +        width(-1),
   41.58 +        height(-1),
   41.59 +        offsetX(-1),
   41.60 +        offsetY(-1)
   41.61 +    {}
   41.62 +
   41.63 +    void set(int xScreen, XID xid, DistortionRotation rot, int prodCode,
   41.64 +             int w, int h, int x, int y)
   41.65 +    {
   41.66 +        screen      = xScreen;
   41.67 +        crtcid      = xid;
   41.68 +        rotation    = rot;
   41.69 +        productCode = prodCode;
   41.70 +
   41.71 +        width       = w;
   41.72 +        height      = h;
   41.73 +        offsetX     = x;
   41.74 +        offsetY     = y;
   41.75 +    }
   41.76 +
   41.77 +    bool isValid()      {return (screen != -1);}
   41.78 +
   41.79 +    int                 screen;   ///< X Screen this device occupies.
   41.80 +    XID                 crtcid;   ///< XID uniquely identifying this device on XDisplay.
   41.81 +    DistortionRotation  rotation;
   41.82 +    int                 productCode;
   41.83 +
   41.84 +    // Actual width and height of screen.
   41.85 +    int                 width;
   41.86 +    int                 height;
   41.87 +
   41.88 +    // Offset if using twinview
   41.89 +    int                 offsetX;
   41.90 +    int                 offsetY;
   41.91 +};
   41.92 +
   41.93 +class SDKWindow
   41.94 +{
   41.95 +public:
   41.96 +    
   41.97 +    SDKWindow(const ovrHmd& hmd);
   41.98 +    ~SDKWindow();
   41.99 +
  41.100 +    /// Rotation necessary to correctly orient this SDK window.
  41.101 +    DistortionRotation GetDistortionRotation() {return mDeviceScreen.rotation;}
  41.102 +
  41.103 +    struct _XDisplay* GetDisplay()  {return mXDisplay;}
  41.104 +    XVisualInfo* GetVisual()        {return mXVisual;}
  41.105 +    Window GetDrawable()            {return mXWindow;}
  41.106 +    bool HasValidWindow()           {return (mXWindow != 0);}
  41.107 +
  41.108 +    // Choose frame buffer configuration and return fbConfigID. Returns -1 if
  41.109 +    // a failure occurs.
  41.110 +    static int chooseFBConfigID(struct _XDisplay* display, int xscreen);
  41.111 +
  41.112 +    // Obtain visual from frame buffer configuration ID. You must call XFree
  41.113 +    // on the XVisualInfo* pointer.
  41.114 +    static XVisualInfo* getVisual(struct _XDisplay* display,
  41.115 +                                  int fbConfigID, int xscreen);
  41.116 +
  41.117 +    // GLXFBConfig pointer from frame buffer configuration ID. You must call
  41.118 +    // XFree on the GLXFBConfig pointer.
  41.119 +    static GLXFBConfig* getGLXFBConfig(struct _XDisplay* display,
  41.120 +                                       int fbConfigID, int xscreen);
  41.121 +
  41.122 +    static LinuxDeviceScreen findDevScreenForHMD(const ovrHmd& hmd);
  41.123 +    static LinuxDeviceScreen findDevScreenForDevID(const char* deviceID);
  41.124 +
  41.125 +    static DistortionRotation getRotation(const ovrHmd& hmd);
  41.126 +
  41.127 +    // Obtains XVisualInfo for currently bound context. Returns true if a
  41.128 +    // visual was successfully obtained. False otherwise.
  41.129 +    static bool getVisualFromDrawable(GLXDrawable drawable, XVisualInfo* vinfoOut);
  41.130 +
  41.131 +private:
  41.132 +
  41.133 +    /// Constructs SDK window on the given device screen.
  41.134 +    void buildVisualAndWindow(const LinuxDeviceScreen& devScreen);
  41.135 +
  41.136 +    // Added m in front of variables so as to not conflict with X names.
  41.137 +    struct _XDisplay* mXDisplay;
  41.138 +    int               mXScreen;
  41.139 +    XVisualInfo*      mXVisual;
  41.140 +    XContext          mXUniqueContext;
  41.141 +    Window            mXWindow;
  41.142 +    int               mFBConfigID;
  41.143 +
  41.144 +    LinuxDeviceScreen mDeviceScreen;
  41.145 +};
  41.146 +
  41.147 +
  41.148 +} // namespace OVR
  41.149 +
  41.150 +#endif // OVR_Linux_SDKWindow_h
    42.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    42.2 +++ b/LibOVR/Src/Kernel/OVR_Alg.cpp	Wed Jan 14 06:51:16 2015 +0200
    42.3 @@ -0,0 +1,57 @@
    42.4 +/************************************************************************************
    42.5 +
    42.6 +Filename    :   OVR_Alg.cpp
    42.7 +Content     :   Static lookup tables for Alg functions
    42.8 +Created     :   September 19, 2012
    42.9 +Notes       : 
   42.10 +
   42.11 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   42.12 +
   42.13 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
   42.14 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
   42.15 +which is provided at the time of installation or download, or which 
   42.16 +otherwise accompanies this software in either electronic or hard copy form.
   42.17 +
   42.18 +You may obtain a copy of the License at
   42.19 +
   42.20 +http://www.oculusvr.com/licenses/LICENSE-3.2 
   42.21 +
   42.22 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
   42.23 +distributed under the License is distributed on an "AS IS" BASIS,
   42.24 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   42.25 +See the License for the specific language governing permissions and
   42.26 +limitations under the License.
   42.27 +
   42.28 +************************************************************************************/
   42.29 +
   42.30 +#include "OVR_Types.h"
   42.31 +
   42.32 +namespace OVR { namespace Alg {
   42.33 +
   42.34 +//------------------------------------------------------------------------
   42.35 +extern const uint8_t UpperBitTable[256] =
   42.36 +{
   42.37 +    0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
   42.38 +    5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
   42.39 +    6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
   42.40 +    6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
   42.41 +    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
   42.42 +    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
   42.43 +    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
   42.44 +    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
   42.45 +};
   42.46 +
   42.47 +extern const uint8_t LowerBitTable[256] =
   42.48 +{
   42.49 +    8,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
   42.50 +    5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
   42.51 +    6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
   42.52 +    5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
   42.53 +    7,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
   42.54 +    5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
   42.55 +    6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
   42.56 +    5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
   42.57 +};
   42.58 +
   42.59 +
   42.60 +}} // OVE::Alg
    43.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    43.2 +++ b/LibOVR/Src/Kernel/OVR_Alg.h	Wed Jan 14 06:51:16 2015 +0200
    43.3 @@ -0,0 +1,1062 @@
    43.4 +/************************************************************************************
    43.5 +
    43.6 +PublicHeader:   OVR_Kernel.h
    43.7 +Filename    :   OVR_Alg.h
    43.8 +Content     :   Simple general purpose algorithms: Sort, Binary Search, etc.
    43.9 +Created     :   September 19, 2012
   43.10 +Notes       : 
   43.11 +
   43.12 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   43.13 +
   43.14 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
   43.15 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
   43.16 +which is provided at the time of installation or download, or which 
   43.17 +otherwise accompanies this software in either electronic or hard copy form.
   43.18 +
   43.19 +You may obtain a copy of the License at
   43.20 +
   43.21 +http://www.oculusvr.com/licenses/LICENSE-3.2 
   43.22 +
   43.23 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
   43.24 +distributed under the License is distributed on an "AS IS" BASIS,
   43.25 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   43.26 +See the License for the specific language governing permissions and
   43.27 +limitations under the License.
   43.28 +
   43.29 +************************************************************************************/
   43.30 +
   43.31 +#ifndef OVR_Alg_h
   43.32 +#define OVR_Alg_h
   43.33 +
   43.34 +#include "OVR_Types.h"
   43.35 +#include <string.h>
   43.36 +
   43.37 +namespace OVR { namespace Alg {
   43.38 +
   43.39 +
   43.40 +//-----------------------------------------------------------------------------------
   43.41 +// ***** Operator extensions
   43.42 +
   43.43 +template <typename T> OVR_FORCE_INLINE void Swap(T &a, T &b) 
   43.44 +{  T temp(a); a = b; b = temp; }
   43.45 +
   43.46 +
   43.47 +// ***** min/max are not implemented in Visual Studio 6 standard STL
   43.48 +
   43.49 +template <typename T> OVR_FORCE_INLINE const T Min(const T a, const T b)
   43.50 +{ return (a < b) ? a : b; }
   43.51 +
   43.52 +template <typename T> OVR_FORCE_INLINE const T Max(const T a, const T b)
   43.53 +{ return (b < a) ? a : b; }
   43.54 +
   43.55 +template <typename T> OVR_FORCE_INLINE const T Clamp(const T v, const T minVal, const T maxVal)
   43.56 +{ return Max<T>(minVal, Min<T>(v, maxVal)); }
   43.57 +
   43.58 +template <typename T> OVR_FORCE_INLINE int     Chop(T f)
   43.59 +{ return (int)f; }
   43.60 +
   43.61 +template <typename T> OVR_FORCE_INLINE T       Lerp(T a, T b, T f) 
   43.62 +{ return (b - a) * f + a; }
   43.63 +
   43.64 +
   43.65 +// These functions stand to fix a stupid VC++ warning (with /Wp64 on):
   43.66 +// "warning C4267: 'argument' : conversion from 'size_t' to 'const unsigned', possible loss of data"
   43.67 +// Use these functions instead of gmin/gmax if the argument has size
   43.68 +// of the pointer to avoid the warning. Though, functionally they are
   43.69 +// absolutelly the same as regular gmin/gmax.
   43.70 +template <typename T>   OVR_FORCE_INLINE const T PMin(const T a, const T b)
   43.71 +{
   43.72 +    OVR_COMPILER_ASSERT(sizeof(T) == sizeof(size_t));
   43.73 +    return (a < b) ? a : b;
   43.74 +}
   43.75 +template <typename T>   OVR_FORCE_INLINE const T PMax(const T a, const T b)
   43.76 +{
   43.77 +    OVR_COMPILER_ASSERT(sizeof(T) == sizeof(size_t));
   43.78 +    return (b < a) ? a : b;
   43.79 +}
   43.80 +
   43.81 +
   43.82 +template <typename T>   OVR_FORCE_INLINE const T Abs(const T v)
   43.83 +{ return (v>=0) ? v : -v; }
   43.84 +
   43.85 +
   43.86 +//-----------------------------------------------------------------------------------
   43.87 +// ***** OperatorLess
   43.88 +//
   43.89 +template<class T> struct OperatorLess
   43.90 +{
   43.91 +    static bool Compare(const T& a, const T& b)
   43.92 +    {
   43.93 +        return a < b;
   43.94 +    }
   43.95 +};
   43.96 +
   43.97 +
   43.98 +//-----------------------------------------------------------------------------------
   43.99 +// ***** QuickSortSliced
  43.100 +//
  43.101 +// Sort any part of any array: plain, Array, ArrayPaged, ArrayUnsafe.
  43.102 +// The range is specified with start, end, where "end" is exclusive!
  43.103 +// The comparison predicate must be specified.
  43.104 +template<class Array, class Less> 
  43.105 +void QuickSortSliced(Array& arr, size_t start, size_t end, Less less)
  43.106 +{
  43.107 +    enum 
  43.108 +    {
  43.109 +        Threshold = 9
  43.110 +    };
  43.111 +
  43.112 +    if(end - start <  2) return;
  43.113 +
  43.114 +    intptr_t  stack[80];
  43.115 +    intptr_t* top   = stack; 
  43.116 +    intptr_t  base  = (intptr_t)start;
  43.117 +    intptr_t  limit = (intptr_t)end;
  43.118 +
  43.119 +    for(;;)
  43.120 +    {
  43.121 +        intptr_t len = limit - base;
  43.122 +        intptr_t i, j, pivot;
  43.123 +
  43.124 +        if(len > Threshold)
  43.125 +        {
  43.126 +            // we use base + len/2 as the pivot
  43.127 +            pivot = base + len / 2;
  43.128 +            Swap(arr[base], arr[pivot]);
  43.129 +
  43.130 +            i = base + 1;
  43.131 +            j = limit - 1;
  43.132 +
  43.133 +            // now ensure that *i <= *base <= *j 
  43.134 +            if(less(arr[j],    arr[i])) Swap(arr[j],    arr[i]);
  43.135 +            if(less(arr[base], arr[i])) Swap(arr[base], arr[i]);
  43.136 +            if(less(arr[j], arr[base])) Swap(arr[j], arr[base]);
  43.137 +
  43.138 +            for(;;)
  43.139 +            {
  43.140 +                do i++; while( less(arr[i], arr[base]) );
  43.141 +                do j--; while( less(arr[base], arr[j]) );
  43.142 +
  43.143 +                if( i > j )
  43.144 +                {
  43.145 +                    break;
  43.146 +                }
  43.147 +
  43.148 +                Swap(arr[i], arr[j]);
  43.149 +            }
  43.150 +
  43.151 +            Swap(arr[base], arr[j]);
  43.152 +
  43.153 +            // now, push the largest sub-array
  43.154 +            if(j - base > limit - i)
  43.155 +            {
  43.156 +                top[0] = base;
  43.157 +                top[1] = j;
  43.158 +                base   = i;
  43.159 +            }
  43.160 +            else
  43.161 +            {
  43.162 +                top[0] = i;
  43.163 +                top[1] = limit;
  43.164 +                limit  = j;
  43.165 +            }
  43.166 +            top += 2;
  43.167 +        }
  43.168 +        else
  43.169 +        {
  43.170 +            // the sub-array is small, perform insertion sort
  43.171 +            j = base;
  43.172 +            i = j + 1;
  43.173 +
  43.174 +            for(; i < limit; j = i, i++)
  43.175 +            {
  43.176 +                for(; less(arr[j + 1], arr[j]); j--)
  43.177 +                {
  43.178 +                    Swap(arr[j + 1], arr[j]);
  43.179 +                    if(j == base)
  43.180 +                    {
  43.181 +                        break;
  43.182 +                    }
  43.183 +                }
  43.184 +            }
  43.185 +            if(top > stack)
  43.186 +            {
  43.187 +                top  -= 2;
  43.188 +                base  = top[0];
  43.189 +                limit = top[1];
  43.190 +            }
  43.191 +            else
  43.192 +            {
  43.193 +                break;
  43.194 +            }
  43.195 +        }
  43.196 +    }
  43.197 +}
  43.198 +
  43.199 +
  43.200 +//-----------------------------------------------------------------------------------
  43.201 +// ***** QuickSortSliced
  43.202 +//
  43.203 +// Sort any part of any array: plain, Array, ArrayPaged, ArrayUnsafe.
  43.204 +// The range is specified with start, end, where "end" is exclusive!
  43.205 +// The data type must have a defined "<" operator.
  43.206 +template<class Array> 
  43.207 +void QuickSortSliced(Array& arr, size_t start, size_t end)
  43.208 +{
  43.209 +    typedef typename Array::ValueType ValueType;
  43.210 +    QuickSortSliced(arr, start, end, OperatorLess<ValueType>::Compare);
  43.211 +}
  43.212 +
  43.213 +// Same as corresponding G_QuickSortSliced but with checking array limits to avoid
  43.214 +// crash in the case of wrong comparator functor.
  43.215 +template<class Array, class Less> 
  43.216 +bool QuickSortSlicedSafe(Array& arr, size_t start, size_t end, Less less)
  43.217 +{
  43.218 +    enum 
  43.219 +    {
  43.220 +        Threshold = 9
  43.221 +    };
  43.222 +
  43.223 +    if(end - start <  2) return true;
  43.224 +
  43.225 +    intptr_t  stack[80];
  43.226 +    intptr_t* top   = stack; 
  43.227 +    intptr_t  base  = (intptr_t)start;
  43.228 +    intptr_t  limit = (intptr_t)end;
  43.229 +
  43.230 +    for(;;)
  43.231 +    {
  43.232 +        intptr_t len = limit - base;
  43.233 +        intptr_t i, j, pivot;
  43.234 +
  43.235 +        if(len > Threshold)
  43.236 +        {
  43.237 +            // we use base + len/2 as the pivot
  43.238 +            pivot = base + len / 2;
  43.239 +            Swap(arr[base], arr[pivot]);
  43.240 +
  43.241 +            i = base + 1;
  43.242 +            j = limit - 1;
  43.243 +
  43.244 +            // now ensure that *i <= *base <= *j 
  43.245 +            if(less(arr[j],    arr[i])) Swap(arr[j],    arr[i]);
  43.246 +            if(less(arr[base], arr[i])) Swap(arr[base], arr[i]);
  43.247 +            if(less(arr[j], arr[base])) Swap(arr[j], arr[base]);
  43.248 +
  43.249 +            for(;;)
  43.250 +            {
  43.251 +                do 
  43.252 +                {   
  43.253 +                    i++; 
  43.254 +                    if (i >= limit)
  43.255 +                        return false;
  43.256 +                } while( less(arr[i], arr[base]) );
  43.257 +                do 
  43.258 +                {
  43.259 +                    j--; 
  43.260 +                    if (j < 0)
  43.261 +                        return false;
  43.262 +                } while( less(arr[base], arr[j]) );
  43.263 +
  43.264 +                if( i > j )
  43.265 +                {
  43.266 +                    break;
  43.267 +                }
  43.268 +
  43.269 +                Swap(arr[i], arr[j]);
  43.270 +            }
  43.271 +
  43.272 +            Swap(arr[base], arr[j]);
  43.273 +
  43.274 +            // now, push the largest sub-array
  43.275 +            if(j - base > limit - i)
  43.276 +            {
  43.277 +                top[0] = base;
  43.278 +                top[1] = j;
  43.279 +                base   = i;
  43.280 +            }
  43.281 +            else
  43.282 +            {
  43.283 +                top[0] = i;
  43.284 +                top[1] = limit;
  43.285 +                limit  = j;
  43.286 +            }
  43.287 +            top += 2;
  43.288 +        }
  43.289 +        else
  43.290 +        {
  43.291 +            // the sub-array is small, perform insertion sort
  43.292 +            j = base;
  43.293 +            i = j + 1;
  43.294 +
  43.295 +            for(; i < limit; j = i, i++)
  43.296 +            {
  43.297 +                for(; less(arr[j + 1], arr[j]); j--)
  43.298 +                {
  43.299 +                    Swap(arr[j + 1], arr[j]);
  43.300 +                    if(j == base)
  43.301 +                    {
  43.302 +                        break;
  43.303 +                    }
  43.304 +                }
  43.305 +            }
  43.306 +            if(top > stack)
  43.307 +            {
  43.308 +                top  -= 2;
  43.309 +                base  = top[0];
  43.310 +                limit = top[1];
  43.311 +            }
  43.312 +            else
  43.313 +            {
  43.314 +                break;
  43.315 +            }
  43.316 +        }
  43.317 +    }
  43.318 +    return true;
  43.319 +}
  43.320 +
  43.321 +template<class Array> 
  43.322 +bool QuickSortSlicedSafe(Array& arr, size_t start, size_t end)
  43.323 +{
  43.324 +    typedef typename Array::ValueType ValueType;
  43.325 +    return QuickSortSlicedSafe(arr, start, end, OperatorLess<ValueType>::Compare);
  43.326 +}
  43.327 +
  43.328 +//-----------------------------------------------------------------------------------
  43.329 +// ***** QuickSort
  43.330 +//
  43.331 +// Sort an array Array, ArrayPaged, ArrayUnsafe.
  43.332 +// The array must have GetSize() function.
  43.333 +// The comparison predicate must be specified.
  43.334 +template<class Array, class Less> 
  43.335 +void QuickSort(Array& arr, Less less)
  43.336 +{
  43.337 +    QuickSortSliced(arr, 0, arr.GetSize(), less);
  43.338 +}
  43.339 +
  43.340 +// checks for boundaries
  43.341 +template<class Array, class Less> 
  43.342 +bool QuickSortSafe(Array& arr, Less less)
  43.343 +{
  43.344 +    return QuickSortSlicedSafe(arr, 0, arr.GetSize(), less);
  43.345 +}
  43.346 +
  43.347 +
  43.348 +//-----------------------------------------------------------------------------------
  43.349 +// ***** QuickSort
  43.350 +//
  43.351 +// Sort an array Array, ArrayPaged, ArrayUnsafe.
  43.352 +// The array must have GetSize() function.
  43.353 +// The data type must have a defined "<" operator.
  43.354 +template<class Array> 
  43.355 +void QuickSort(Array& arr)
  43.356 +{
  43.357 +    typedef typename Array::ValueType ValueType;
  43.358 +    QuickSortSliced(arr, 0, arr.GetSize(), OperatorLess<ValueType>::Compare);
  43.359 +}
  43.360 +
  43.361 +template<class Array> 
  43.362 +bool QuickSortSafe(Array& arr)
  43.363 +{
  43.364 +    typedef typename Array::ValueType ValueType;
  43.365 +    return QuickSortSlicedSafe(arr, 0, arr.GetSize(), OperatorLess<ValueType>::Compare);
  43.366 +}
  43.367 +
  43.368 +//-----------------------------------------------------------------------------------
  43.369 +// ***** InsertionSortSliced
  43.370 +//
  43.371 +// Sort any part of any array: plain, Array, ArrayPaged, ArrayUnsafe.
  43.372 +// The range is specified with start, end, where "end" is exclusive!
  43.373 +// The comparison predicate must be specified.
  43.374 +// Unlike Quick Sort, the Insertion Sort works much slower in average, 
  43.375 +// but may be much faster on almost sorted arrays. Besides, it guarantees
  43.376 +// that the elements will not be swapped if not necessary. For example, 
  43.377 +// an array with all equal elements will remain "untouched", while 
  43.378 +// Quick Sort will considerably shuffle the elements in this case.
  43.379 +template<class Array, class Less> 
  43.380 +void InsertionSortSliced(Array& arr, size_t start, size_t end, Less less)
  43.381 +{
  43.382 +    size_t j = start;
  43.383 +    size_t i = j + 1;
  43.384 +    size_t limit = end;
  43.385 +
  43.386 +    for(; i < limit; j = i, i++)
  43.387 +    {
  43.388 +        for(; less(arr[j + 1], arr[j]); j--)
  43.389 +        {
  43.390 +            Swap(arr[j + 1], arr[j]);
  43.391 +            if(j <= start)
  43.392 +            {
  43.393 +                break;
  43.394 +            }
  43.395 +        }
  43.396 +    }
  43.397 +}
  43.398 +
  43.399 +
  43.400 +//-----------------------------------------------------------------------------------
  43.401 +// ***** InsertionSortSliced
  43.402 +//
  43.403 +// Sort any part of any array: plain, Array, ArrayPaged, ArrayUnsafe.
  43.404 +// The range is specified with start, end, where "end" is exclusive!
  43.405 +// The data type must have a defined "<" operator.
  43.406 +template<class Array> 
  43.407 +void InsertionSortSliced(Array& arr, size_t start, size_t end)
  43.408 +{
  43.409 +    typedef typename Array::ValueType ValueType;
  43.410 +    InsertionSortSliced(arr, start, end, OperatorLess<ValueType>::Compare);
  43.411 +}
  43.412 +
  43.413 +//-----------------------------------------------------------------------------------
  43.414 +// ***** InsertionSort
  43.415 +//
  43.416 +// Sort an array Array, ArrayPaged, ArrayUnsafe.
  43.417 +// The array must have GetSize() function.
  43.418 +// The comparison predicate must be specified.
  43.419 +
  43.420 +template<class Array, class Less> 
  43.421 +void InsertionSort(Array& arr, Less less)
  43.422 +{
  43.423 +    InsertionSortSliced(arr, 0, arr.GetSize(), less);
  43.424 +}
  43.425 +
  43.426 +//-----------------------------------------------------------------------------------
  43.427 +// ***** InsertionSort
  43.428 +//
  43.429 +// Sort an array Array, ArrayPaged, ArrayUnsafe.
  43.430 +// The array must have GetSize() function.
  43.431 +// The data type must have a defined "<" operator.
  43.432 +template<class Array> 
  43.433 +void InsertionSort(Array& arr)
  43.434 +{
  43.435 +    typedef typename Array::ValueType ValueType;
  43.436 +    InsertionSortSliced(arr, 0, arr.GetSize(), OperatorLess<ValueType>::Compare);
  43.437 +}
  43.438 +
  43.439 +//-----------------------------------------------------------------------------------
  43.440 +// ***** Median
  43.441 +// Returns a median value of the input array.
  43.442 +// Caveats: partially sorts the array, returns a reference to the array element
  43.443 +// TBD: This needs to be optimized and generalized
  43.444 +//
  43.445 +template<class Array> 
  43.446 +typename Array::ValueType& Median(Array& arr)
  43.447 +{
  43.448 +    size_t count = arr.GetSize();
  43.449 +    size_t mid = (count - 1) / 2;
  43.450 +    OVR_ASSERT(count > 0);
  43.451 +
  43.452 +	for (size_t j = 0; j <= mid; j++)
  43.453 +    {
  43.454 +		size_t min = j;
  43.455 +		for (size_t k = j + 1; k < count; k++)
  43.456 +            if (arr[k] < arr[min]) 
  43.457 +                min = k;
  43.458 +        Swap(arr[j], arr[min]);
  43.459 +    }
  43.460 +    return arr[mid];
  43.461 +}
  43.462 +
  43.463 +//-----------------------------------------------------------------------------------
  43.464 +// ***** LowerBoundSliced
  43.465 +//
  43.466 +template<class Array, class Value, class Less>
  43.467 +size_t LowerBoundSliced(const Array& arr, size_t start, size_t end, const Value& val, Less less)
  43.468 +{
  43.469 +    intptr_t first = (intptr_t)start;
  43.470 +    intptr_t len   = (intptr_t)(end - start);
  43.471 +    intptr_t half;
  43.472 +    intptr_t middle;
  43.473 +    
  43.474 +    while(len > 0) 
  43.475 +    {
  43.476 +        half = len >> 1;
  43.477 +        middle = first + half;
  43.478 +        if(less(arr[middle], val)) 
  43.479 +        {
  43.480 +            first = middle + 1;
  43.481 +            len   = len - half - 1;
  43.482 +        }
  43.483 +        else
  43.484 +        {
  43.485 +            len = half;
  43.486 +        }
  43.487 +    }
  43.488 +    return (size_t)first;
  43.489 +}
  43.490 +
  43.491 +
  43.492 +//-----------------------------------------------------------------------------------
  43.493 +// ***** LowerBoundSliced
  43.494 +//
  43.495 +template<class Array, class Value>
  43.496 +size_t LowerBoundSliced(const Array& arr, size_t start, size_t end, const Value& val)
  43.497 +{
  43.498 +    return LowerBoundSliced(arr, start, end, val, OperatorLess<Value>::Compare);
  43.499 +}
  43.500 +
  43.501 +//-----------------------------------------------------------------------------------
  43.502 +// ***** LowerBoundSized
  43.503 +//
  43.504 +template<class Array, class Value>
  43.505 +size_t LowerBoundSized(const Array& arr, size_t size, const Value& val)
  43.506 +{
  43.507 +    return LowerBoundSliced(arr, 0, size, val, OperatorLess<Value>::Compare);
  43.508 +}
  43.509 +
  43.510 +//-----------------------------------------------------------------------------------
  43.511 +// ***** LowerBound
  43.512 +//
  43.513 +template<class Array, class Value, class Less>
  43.514 +size_t LowerBound(const Array& arr, const Value& val, Less less)
  43.515 +{
  43.516 +    return LowerBoundSliced(arr, 0, arr.GetSize(), val, less);
  43.517 +}
  43.518 +
  43.519 +
  43.520 +//-----------------------------------------------------------------------------------
  43.521 +// ***** LowerBound
  43.522 +//
  43.523 +template<class Array, class Value>
  43.524 +size_t LowerBound(const Array& arr, const Value& val)
  43.525 +{
  43.526 +    return LowerBoundSliced(arr, 0, arr.GetSize(), val, OperatorLess<Value>::Compare);
  43.527 +}
  43.528 +
  43.529 +
  43.530 +
  43.531 +//-----------------------------------------------------------------------------------
  43.532 +// ***** UpperBoundSliced
  43.533 +//
  43.534 +template<class Array, class Value, class Less>
  43.535 +size_t UpperBoundSliced(const Array& arr, size_t start, size_t end, const Value& val, Less less)
  43.536 +{
  43.537 +    intptr_t first = (intptr_t)start;
  43.538 +    intptr_t len   = (intptr_t)(end - start);
  43.539 +    intptr_t half;
  43.540 +    intptr_t middle;
  43.541 +    
  43.542 +    while(len > 0) 
  43.543 +    {
  43.544 +        half = len >> 1;
  43.545 +        middle = first + half;
  43.546 +        if(less(val, arr[middle]))
  43.547 +        {
  43.548 +            len = half;
  43.549 +        }
  43.550 +        else 
  43.551 +        {
  43.552 +            first = middle + 1;
  43.553 +            len   = len - half - 1;
  43.554 +        }
  43.555 +    }
  43.556 +    return (size_t)first;
  43.557 +}
  43.558 +
  43.559 +
  43.560 +//-----------------------------------------------------------------------------------
  43.561 +// ***** UpperBoundSliced
  43.562 +//
  43.563 +template<class Array, class Value>
  43.564 +size_t UpperBoundSliced(const Array& arr, size_t start, size_t end, const Value& val)
  43.565 +{
  43.566 +    return UpperBoundSliced(arr, start, end, val, OperatorLess<Value>::Compare);
  43.567 +}
  43.568 +
  43.569 +
  43.570 +//-----------------------------------------------------------------------------------
  43.571 +// ***** UpperBoundSized
  43.572 +//
  43.573 +template<class Array, class Value>
  43.574 +size_t UpperBoundSized(const Array& arr, size_t size, const Value& val)
  43.575 +{
  43.576 +    return UpperBoundSliced(arr, 0, size, val, OperatorLess<Value>::Compare);
  43.577 +}
  43.578 +
  43.579 +
  43.580 +//-----------------------------------------------------------------------------------
  43.581 +// ***** UpperBound
  43.582 +//
  43.583 +template<class Array, class Value, class Less>
  43.584 +size_t UpperBound(const Array& arr, const Value& val, Less less)
  43.585 +{
  43.586 +    return UpperBoundSliced(arr, 0, arr.GetSize(), val, less);
  43.587 +}
  43.588 +
  43.589 +
  43.590 +//-----------------------------------------------------------------------------------
  43.591 +// ***** UpperBound
  43.592 +//
  43.593 +template<class Array, class Value>
  43.594 +size_t UpperBound(const Array& arr, const Value& val)
  43.595 +{
  43.596 +    return UpperBoundSliced(arr, 0, arr.GetSize(), val, OperatorLess<Value>::Compare);
  43.597 +}
  43.598 +
  43.599 +
  43.600 +//-----------------------------------------------------------------------------------
  43.601 +// ***** ReverseArray
  43.602 +//
  43.603 +template<class Array> void ReverseArray(Array& arr)
  43.604 +{
  43.605 +    intptr_t from = 0;
  43.606 +    intptr_t to   = arr.GetSize() - 1;
  43.607 +    while(from < to)
  43.608 +    {
  43.609 +        Swap(arr[from], arr[to]);
  43.610 +        ++from;
  43.611 +        --to;
  43.612 +    }
  43.613 +}
  43.614 +
  43.615 +
  43.616 +// ***** AppendArray
  43.617 +//
  43.618 +template<class CDst, class CSrc> 
  43.619 +void AppendArray(CDst& dst, const CSrc& src)
  43.620 +{
  43.621 +    size_t i;
  43.622 +    for(i = 0; i < src.GetSize(); i++) 
  43.623 +        dst.PushBack(src[i]);
  43.624 +}
  43.625 +
  43.626 +//-----------------------------------------------------------------------------------
  43.627 +// ***** ArrayAdaptor
  43.628 +//
  43.629 +// A simple adapter that provides the GetSize() method and overloads 
  43.630 +// operator []. Used to wrap plain arrays in QuickSort and such.
  43.631 +template<class T> class ArrayAdaptor
  43.632 +{
  43.633 +public:
  43.634 +    typedef T ValueType;
  43.635 +    ArrayAdaptor() : Data(0), Size(0) {}
  43.636 +    ArrayAdaptor(T* ptr, size_t size) : Data(ptr), Size(size) {}
  43.637 +    size_t GetSize() const { return Size; }
  43.638 +	int GetSizeI() const { return (int)GetSize(); }
  43.639 +    const T& operator [] (size_t i) const { return Data[i]; }
  43.640 +          T& operator [] (size_t i)       { return Data[i]; }
  43.641 +private:
  43.642 +    T*      Data;
  43.643 +    size_t  Size;
  43.644 +};
  43.645 +
  43.646 +
  43.647 +//-----------------------------------------------------------------------------------
  43.648 +// ***** GConstArrayAdaptor
  43.649 +//
  43.650 +// A simple const adapter that provides the GetSize() method and overloads 
  43.651 +// operator []. Used to wrap plain arrays in LowerBound and such.
  43.652 +template<class T> class ConstArrayAdaptor
  43.653 +{
  43.654 +public:
  43.655 +    typedef T ValueType;
  43.656 +    ConstArrayAdaptor() : Data(0), Size(0) {}
  43.657 +    ConstArrayAdaptor(const T* ptr, size_t size) : Data(ptr), Size(size) {}
  43.658 +    size_t GetSize() const { return Size; }
  43.659 +	int GetSizeI() const { return (int)GetSize(); }
  43.660 +	const T& operator [] (size_t i) const { return Data[i]; }
  43.661 +private:
  43.662 +    const T* Data;
  43.663 +    size_t   Size;
  43.664 +};
  43.665 +
  43.666 +
  43.667 +
  43.668 +//-----------------------------------------------------------------------------------
  43.669 +extern const uint8_t UpperBitTable[256];
  43.670 +extern const uint8_t LowerBitTable[256];
  43.671 +
  43.672 +
  43.673 +
  43.674 +//-----------------------------------------------------------------------------------
  43.675 +inline uint8_t UpperBit(size_t val)
  43.676 +{
  43.677 +#ifndef OVR_64BIT_POINTERS
  43.678 +
  43.679 +    if (val & 0xFFFF0000)
  43.680 +    {
  43.681 +        return (val & 0xFF000000) ? 
  43.682 +            UpperBitTable[(val >> 24)       ] + 24: 
  43.683 +            UpperBitTable[(val >> 16) & 0xFF] + 16;
  43.684 +    }
  43.685 +    return (val & 0xFF00) ?
  43.686 +        UpperBitTable[(val >> 8) & 0xFF] + 8:
  43.687 +        UpperBitTable[(val     ) & 0xFF];
  43.688 +
  43.689 +#else
  43.690 +
  43.691 +    if (val & 0xFFFFFFFF00000000)
  43.692 +    {
  43.693 +        if (val & 0xFFFF000000000000)
  43.694 +        {
  43.695 +            return (val & 0xFF00000000000000) ?
  43.696 +                UpperBitTable[(val >> 56)       ] + 56: 
  43.697 +                UpperBitTable[(val >> 48) & 0xFF] + 48;
  43.698 +        }
  43.699 +        return (val & 0xFF0000000000) ?
  43.700 +            UpperBitTable[(val >> 40) & 0xFF] + 40:
  43.701 +            UpperBitTable[(val >> 32) & 0xFF] + 32;
  43.702 +    }
  43.703 +    else
  43.704 +    {
  43.705 +        if (val & 0xFFFF0000)
  43.706 +        {
  43.707 +            return (val & 0xFF000000) ? 
  43.708 +                UpperBitTable[(val >> 24)       ] + 24: 
  43.709 +                UpperBitTable[(val >> 16) & 0xFF] + 16;
  43.710 +        }
  43.711 +        return (val & 0xFF00) ?
  43.712 +            UpperBitTable[(val >> 8) & 0xFF] + 8:
  43.713 +            UpperBitTable[(val     ) & 0xFF];
  43.714 +    }
  43.715 +
  43.716 +#endif
  43.717 +}
  43.718 +
  43.719 +//-----------------------------------------------------------------------------------
  43.720 +inline uint8_t LowerBit(size_t val)
  43.721 +{
  43.722 +#ifndef OVR_64BIT_POINTERS
  43.723 +
  43.724 +    if (val & 0xFFFF)
  43.725 +    {
  43.726 +        return (val & 0xFF) ?
  43.727 +            LowerBitTable[ val & 0xFF]:
  43.728 +            LowerBitTable[(val >> 8) & 0xFF] + 8;
  43.729 +    }
  43.730 +    return (val & 0xFF0000) ?
  43.731 +            LowerBitTable[(val >> 16) & 0xFF] + 16:
  43.732 +            LowerBitTable[(val >> 24) & 0xFF] + 24;
  43.733 +
  43.734 +#else
  43.735 +
  43.736 +    if (val & 0xFFFFFFFF)
  43.737 +    {
  43.738 +        if (val & 0xFFFF)
  43.739 +        {
  43.740 +            return (val & 0xFF) ?
  43.741 +                LowerBitTable[ val & 0xFF]:
  43.742 +                LowerBitTable[(val >> 8) & 0xFF] + 8;
  43.743 +        }
  43.744 +        return (val & 0xFF0000) ?
  43.745 +                LowerBitTable[(val >> 16) & 0xFF] + 16:
  43.746 +                LowerBitTable[(val >> 24) & 0xFF] + 24;
  43.747 +    }
  43.748 +    else
  43.749 +    {
  43.750 +        if (val & 0xFFFF00000000)
  43.751 +        {
  43.752 +             return (val & 0xFF00000000) ?
  43.753 +                LowerBitTable[(val >> 32) & 0xFF] + 32:
  43.754 +                LowerBitTable[(val >> 40) & 0xFF] + 40;
  43.755 +        }
  43.756 +        return (val & 0xFF000000000000) ?
  43.757 +            LowerBitTable[(val >> 48) & 0xFF] + 48:
  43.758 +            LowerBitTable[(val >> 56) & 0xFF] + 56;
  43.759 +    }
  43.760 +
  43.761 +#endif
  43.762 +}
  43.763 +
  43.764 +
  43.765 +
  43.766 +// ******* Special (optimized) memory routines
  43.767 +// Note: null (bad) pointer is not tested
  43.768 +class MemUtil
  43.769 +{
  43.770 +public:
  43.771 +                                    
  43.772 +    // Memory compare
  43.773 +    static int      Cmp  (const void* p1, const void* p2, size_t byteCount)      { return memcmp(p1, p2, byteCount); }
  43.774 +    static int      Cmp16(const void* p1, const void* p2, size_t int16Count);
  43.775 +    static int      Cmp32(const void* p1, const void* p2, size_t int32Count);
  43.776 +    static int      Cmp64(const void* p1, const void* p2, size_t int64Count); 
  43.777 +};
  43.778 +
  43.779 +// ** Inline Implementation
  43.780 +
  43.781 +inline int MemUtil::Cmp16(const void* p1, const void* p2, size_t int16Count)
  43.782 +{
  43.783 +    int16_t*  pa  = (int16_t*)p1; 
  43.784 +    int16_t*  pb  = (int16_t*)p2;
  43.785 +    unsigned ic  = 0;
  43.786 +    if (int16Count == 0)
  43.787 +        return 0;
  43.788 +    while (pa[ic] == pb[ic])
  43.789 +        if (++ic==int16Count)
  43.790 +            return 0;
  43.791 +    return pa[ic] > pb[ic] ? 1 : -1;
  43.792 +}
  43.793 +inline int MemUtil::Cmp32(const void* p1, const void* p2, size_t int32Count)
  43.794 +{
  43.795 +    int32_t*  pa  = (int32_t*)p1;
  43.796 +    int32_t*  pb  = (int32_t*)p2;
  43.797 +    unsigned ic  = 0;
  43.798 +    if (int32Count == 0)
  43.799 +        return 0;
  43.800 +    while (pa[ic] == pb[ic])
  43.801 +        if (++ic==int32Count)
  43.802 +            return 0;
  43.803 +    return pa[ic] > pb[ic] ? 1 : -1;
  43.804 +}
  43.805 +inline int MemUtil::Cmp64(const void* p1, const void* p2, size_t int64Count)
  43.806 +{
  43.807 +    int64_t*  pa  = (int64_t*)p1;
  43.808 +    int64_t*  pb  = (int64_t*)p2;
  43.809 +    unsigned ic  = 0;
  43.810 +    if (int64Count == 0)
  43.811 +        return 0;
  43.812 +    while (pa[ic] == pb[ic])
  43.813 +        if (++ic==int64Count)
  43.814 +            return 0;
  43.815 +    return pa[ic] > pb[ic] ? 1 : -1;
  43.816 +}
  43.817 +
  43.818 +// ** End Inline Implementation
  43.819 +
  43.820 +
  43.821 +//-----------------------------------------------------------------------------------
  43.822 +// ******* Byte Order Conversions
  43.823 +namespace ByteUtil {
  43.824 +
  43.825 +    // *** Swap Byte Order
  43.826 +
  43.827 +    // Swap the byte order of a byte array
  43.828 +    inline void     SwapOrder(void* pv, int size)
  43.829 +    {
  43.830 +        uint8_t*  pb = (uint8_t*)pv;
  43.831 +        uint8_t temp;
  43.832 +        for (int i = 0; i < size>>1; i++)
  43.833 +        { 
  43.834 +            temp            = pb[size-1-i];
  43.835 +            pb[size-1-i]    = pb[i];
  43.836 +            pb[i]           = temp; 
  43.837 +        }
  43.838 +    }
  43.839 +
  43.840 +    // Swap the byte order of primitive types
  43.841 +    inline uint8_t  SwapOrder(uint8_t v)    { return v; }
  43.842 +    inline int8_t   SwapOrder(int8_t v)     { return v; }
  43.843 +    inline uint16_t SwapOrder(uint16_t v)   { return uint16_t(v>>8)|uint16_t(v<<8); }
  43.844 +    inline int16_t  SwapOrder(int16_t v)    { return int16_t((uint16_t(v)>>8)|(v<<8)); }
  43.845 +    inline uint32_t SwapOrder(uint32_t v)   { return (v>>24)|((v&0x00FF0000)>>8)|((v&0x0000FF00)<<8)|(v<<24); }
  43.846 +    inline int32_t  SwapOrder(int32_t p)    { return (int32_t)SwapOrder(uint32_t(p)); }
  43.847 +    inline uint64_t SwapOrder(uint64_t v)
  43.848 +    { 
  43.849 +        return   (v>>56) |
  43.850 +                 ((v&uint64_t(0x00FF000000000000ULL))>>40) |
  43.851 +                 ((v&uint64_t(0x0000FF0000000000ULL))>>24) |
  43.852 +                 ((v&uint64_t(0x000000FF00000000ULL))>>8)  |
  43.853 +                 ((v&uint64_t(0x00000000FF000000ULL))<<8)  |
  43.854 +                 ((v&uint64_t(0x0000000000FF0000ULL))<<24) |
  43.855 +                 ((v&uint64_t(0x000000000000FF00ULL))<<40) |
  43.856 +                 (v<<56); 
  43.857 +    }
  43.858 +    inline int64_t  SwapOrder(int64_t v)     { return (int64_t)SwapOrder(uint64_t(v)); }
  43.859 +    inline float    SwapOrder(float p)      
  43.860 +    { 
  43.861 +        union {
  43.862 +            float p;
  43.863 +            uint32_t v;
  43.864 +        } u;
  43.865 +        u.p = p;
  43.866 +        u.v = SwapOrder(u.v);
  43.867 +        return u.p;
  43.868 +    }
  43.869 +
  43.870 +    inline double   SwapOrder(double p)
  43.871 +    { 
  43.872 +        union {
  43.873 +            double p;
  43.874 +            uint64_t v;
  43.875 +        } u;
  43.876 +        u.p = p;
  43.877 +        u.v = SwapOrder(u.v);
  43.878 +        return u.p;
  43.879 +    }
  43.880 +    
  43.881 +    // *** Byte-order conversion
  43.882 +
  43.883 +#if (OVR_BYTE_ORDER == OVR_LITTLE_ENDIAN)
  43.884 +    // Little Endian to System (LE)
  43.885 +    inline uint8_t  LEToSystem(uint8_t v)   { return v; }
  43.886 +    inline int8_t   LEToSystem(int8_t v)    { return v; }
  43.887 +    inline uint16_t LEToSystem(uint16_t v)  { return v; }
  43.888 +    inline int16_t  LEToSystem(int16_t v)   { return v; }
  43.889 +    inline uint32_t LEToSystem(uint32_t v)  { return v; }
  43.890 +    inline int32_t  LEToSystem(int32_t v)   { return v; }
  43.891 +    inline uint64_t LEToSystem(uint64_t v)  { return v; }
  43.892 +    inline int64_t  LEToSystem(int64_t v)    { return v; }
  43.893 +    inline float    LEToSystem(float  v)    { return v; }
  43.894 +    inline double   LEToSystem(double v)    { return v; }
  43.895 +
  43.896 +    // Big Endian to System (LE)
  43.897 +    inline uint8_t  BEToSystem(uint8_t v)   { return SwapOrder(v); }
  43.898 +    inline int8_t   BEToSystem(int8_t v)    { return SwapOrder(v); }
  43.899 +    inline uint16_t BEToSystem(uint16_t v)  { return SwapOrder(v); }
  43.900 +    inline int16_t  BEToSystem(int16_t v)   { return SwapOrder(v); }
  43.901 +    inline uint32_t BEToSystem(uint32_t v)  { return SwapOrder(v); }
  43.902 +    inline int32_t  BEToSystem(int32_t v)   { return SwapOrder(v); }
  43.903 +    inline uint64_t BEToSystem(uint64_t v)  { return SwapOrder(v); }
  43.904 +    inline int64_t  BEToSystem(int64_t v)    { return SwapOrder(v); }
  43.905 +    inline float    BEToSystem(float  v)    { return SwapOrder(v); }
  43.906 +    inline double   BEToSystem(double v)    { return SwapOrder(v); }
  43.907 +
  43.908 +    // System (LE) to Little Endian
  43.909 +    inline uint8_t  SystemToLE(uint8_t v)   { return v; }
  43.910 +    inline int8_t   SystemToLE(int8_t v)    { return v; }
  43.911 +    inline uint16_t SystemToLE(uint16_t v)  { return v; }
  43.912 +    inline int16_t  SystemToLE(int16_t v)   { return v; }
  43.913 +    inline uint32_t SystemToLE(uint32_t v)  { return v; }
  43.914 +    inline int32_t  SystemToLE(int32_t v)   { return v; }
  43.915 +    inline uint64_t SystemToLE(uint64_t v)  { return v; }
  43.916 +    inline int64_t  SystemToLE(int64_t v)    { return v; }
  43.917 +    inline float    SystemToLE(float  v)    { return v; }
  43.918 +    inline double   SystemToLE(double v)    { return v; }   
  43.919 +
  43.920 +    // System (LE) to Big Endian
  43.921 +    inline uint8_t  SystemToBE(uint8_t v)   { return SwapOrder(v); }
  43.922 +    inline int8_t   SystemToBE(int8_t v)    { return SwapOrder(v); }
  43.923 +    inline uint16_t SystemToBE(uint16_t v)  { return SwapOrder(v); }
  43.924 +    inline int16_t  SystemToBE(int16_t v)   { return SwapOrder(v); }
  43.925 +    inline uint32_t SystemToBE(uint32_t v)  { return SwapOrder(v); }
  43.926 +    inline int32_t  SystemToBE(int32_t v)   { return SwapOrder(v); }
  43.927 +    inline uint64_t SystemToBE(uint64_t v)  { return SwapOrder(v); }
  43.928 +    inline int64_t  SystemToBE(int64_t v)    { return SwapOrder(v); }
  43.929 +    inline float    SystemToBE(float  v)    { return SwapOrder(v); }
  43.930 +    inline double   SystemToBE(double v)    { return SwapOrder(v); }
  43.931 +
  43.932 +#elif (OVR_BYTE_ORDER == OVR_BIG_ENDIAN)
  43.933 +    // Little Endian to System (BE)
  43.934 +    inline uint8_t  LEToSystem(uint8_t  v)  { return SwapOrder(v); }
  43.935 +    inline int8_t   LEToSystem(int8_t v)    { return SwapOrder(v); }
  43.936 +    inline uint16_t LEToSystem(uint16_t v)  { return SwapOrder(v); }
  43.937 +    inline int16_t  LEToSystem(int16_t v)   { return SwapOrder(v); }
  43.938 +    inline uint32_t LEToSystem(uint32_t v)  { return SwapOrder(v); }
  43.939 +    inline int32_t  LEToSystem(int32_t v)   { return SwapOrder(v); }
  43.940 +    inline uint64_t LEToSystem(uint64_t v)  { return SwapOrder(v); }
  43.941 +    inline int64_t  LEToSystem(int64_t v)    { return SwapOrder(v); }
  43.942 +    inline float    LEToSystem(float  v)    { return SwapOrder(v); }
  43.943 +    inline double   LEToSystem(double v)    { return SwapOrder(v); }
  43.944 +
  43.945 +    // Big Endian to System (BE)
  43.946 +    inline uint8_t  BEToSystem(uint8_t v)   { return v; }
  43.947 +    inline int8_t   BEToSystem(int8_t v)    { return v; }
  43.948 +    inline uint16_t BEToSystem(uint16_t v)  { return v; }
  43.949 +    inline int16_t  BEToSystem(int16_t v)   { return v; }
  43.950 +    inline uint32_t BEToSystem(uint32_t v)  { return v; }
  43.951 +    inline int32_t  BEToSystem(int32_t v)   { return v; }
  43.952 +    inline uint64_t BEToSystem(uint64_t v)  { return v; }
  43.953 +    inline int64_t  BEToSystem(int64_t v)    { return v; }
  43.954 +    inline float    BEToSystem(float  v)    { return v; }
  43.955 +    inline double   BEToSystem(double v)    { return v; }
  43.956 +
  43.957 +    // System (BE) to Little Endian
  43.958 +    inline uint8_t  SystemToLE(uint8_t v)   { return SwapOrder(v); }
  43.959 +    inline int8_t   SystemToLE(int8_t v)    { return SwapOrder(v); }
  43.960 +    inline uint16_t SystemToLE(uint16_t v)  { return SwapOrder(v); }
  43.961 +    inline int16_t  SystemToLE(int16_t v)   { return SwapOrder(v); }
  43.962 +    inline uint32_t SystemToLE(uint32_t v)  { return SwapOrder(v); }
  43.963 +    inline int32_t  SystemToLE(int32_t v)   { return SwapOrder(v); }
  43.964 +    inline uint64_t SystemToLE(uint64_t v)  { return SwapOrder(v); }
  43.965 +    inline int64_t  SystemToLE(int64_t v)    { return SwapOrder(v); }
  43.966 +    inline float    SystemToLE(float  v)    { return SwapOrder(v); }
  43.967 +    inline double   SystemToLE(double v)    { return SwapOrder(v); }
  43.968 +
  43.969 +    // System (BE) to Big Endian
  43.970 +    inline uint8_t  SystemToBE(uint8_t v)   { return v; }
  43.971 +    inline int8_t   SystemToBE(int8_t v)    { return v; }
  43.972 +    inline uint16_t SystemToBE(uint16_t v)  { return v; }
  43.973 +    inline int16_t  SystemToBE(int16_t v)   { return v; }
  43.974 +    inline uint32_t SystemToBE(uint32_t v)  { return v; }
  43.975 +    inline int32_t  SystemToBE(int32_t v)   { return v; }
  43.976 +    inline uint64_t SystemToBE(uint64_t v)  { return v; }
  43.977 +    inline int64_t  SystemToBE(int64_t v)    { return v; }
  43.978 +    inline float    SystemToBE(float  v)    { return v; }
  43.979 +    inline double   SystemToBE(double v)    { return v; }
  43.980 +
  43.981 +#else
  43.982 +    #error "OVR_BYTE_ORDER must be defined to OVR_LITTLE_ENDIAN or OVR_BIG_ENDIAN"
  43.983 +#endif
  43.984 +
  43.985 +} // namespace ByteUtil
  43.986 +
  43.987 +
  43.988 +
  43.989 +// Used primarily for hardware interfacing such as sensor reports, firmware, etc.
  43.990 +// Reported data is all little-endian.
  43.991 +inline uint16_t DecodeUInt16(const uint8_t* buffer)
  43.992 +{
  43.993 +    return ByteUtil::LEToSystem ( *(const uint16_t*)buffer );
  43.994 +}
  43.995 +
  43.996 +inline int16_t DecodeSInt16(const uint8_t* buffer)
  43.997 +{
  43.998 +    return ByteUtil::LEToSystem ( *(const int16_t*)buffer );
  43.999 +}
 43.1000 +
 43.1001 +inline uint32_t DecodeUInt32(const uint8_t* buffer)
 43.1002 +{    
 43.1003 +    return ByteUtil::LEToSystem ( *(const uint32_t*)buffer );
 43.1004 +}
 43.1005 +
 43.1006 +inline int32_t DecodeSInt32(const uint8_t* buffer)
 43.1007 +{    
 43.1008 +    return ByteUtil::LEToSystem ( *(const int32_t*)buffer );
 43.1009 +}
 43.1010 +
 43.1011 +inline float DecodeFloat(const uint8_t* buffer)
 43.1012 +{
 43.1013 +    union {
 43.1014 +        uint32_t U;
 43.1015 +        float  F;
 43.1016 +    };
 43.1017 +
 43.1018 +    U = DecodeUInt32(buffer);
 43.1019 +    return F;
 43.1020 +}
 43.1021 +
 43.1022 +inline void EncodeUInt16(uint8_t* buffer, uint16_t val)
 43.1023 +{
 43.1024 +    *(uint16_t*)buffer = ByteUtil::SystemToLE ( val );
 43.1025 +}
 43.1026 +
 43.1027 +inline void EncodeSInt16(uint8_t* buffer, int16_t val)
 43.1028 +{
 43.1029 +    *(int16_t*)buffer = ByteUtil::SystemToLE ( val );
 43.1030 +}
 43.1031 +
 43.1032 +inline void EncodeUInt32(uint8_t* buffer, uint32_t val)
 43.1033 +{
 43.1034 +    *(uint32_t*)buffer = ByteUtil::SystemToLE ( val );
 43.1035 +}
 43.1036 +
 43.1037 +inline void EncodeSInt32(uint8_t* buffer, int32_t val)
 43.1038 +{
 43.1039 +    *(int32_t*)buffer = ByteUtil::SystemToLE ( val );
 43.1040 +}
 43.1041 +
 43.1042 +inline void EncodeFloat(uint8_t* buffer, float val)
 43.1043 +{
 43.1044 +    union {
 43.1045 +        uint32_t U;
 43.1046 +        float  F;
 43.1047 +    };
 43.1048 +
 43.1049 +    F = val;
 43.1050 +    EncodeUInt32(buffer, U);
 43.1051 +}
 43.1052 +
 43.1053 +// Converts an 8-bit binary-coded decimal
 43.1054 +inline int8_t DecodeBCD(uint8_t byte)
 43.1055 +{
 43.1056 +    uint8_t digit1 = (byte >> 4) & 0x0f;
 43.1057 +    uint8_t digit2 = byte & 0x0f;
 43.1058 +    int decimal = digit1 * 10 + digit2;   // maximum value = 99
 43.1059 +    return (int8_t)decimal;
 43.1060 +}
 43.1061 +
 43.1062 +
 43.1063 +}} // OVR::Alg
 43.1064 +
 43.1065 +#endif
    44.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    44.2 +++ b/LibOVR/Src/Kernel/OVR_Allocator.cpp	Wed Jan 14 06:51:16 2015 +0200
    44.3 @@ -0,0 +1,141 @@
    44.4 +/************************************************************************************
    44.5 +
    44.6 +Filename    :   OVR_Allocator.cpp
    44.7 +Content     :   Installable memory allocator implementation
    44.8 +Created     :   September 19, 2012
    44.9 +Notes       : 
   44.10 +
   44.11 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   44.12 +
   44.13 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
   44.14 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
   44.15 +which is provided at the time of installation or download, or which 
   44.16 +otherwise accompanies this software in either electronic or hard copy form.
   44.17 +
   44.18 +You may obtain a copy of the License at
   44.19 +
   44.20 +http://www.oculusvr.com/licenses/LICENSE-3.2 
   44.21 +
   44.22 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
   44.23 +distributed under the License is distributed on an "AS IS" BASIS,
   44.24 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   44.25 +See the License for the specific language governing permissions and
   44.26 +limitations under the License.
   44.27 +
   44.28 +************************************************************************************/
   44.29 +
   44.30 +#include "OVR_Allocator.h"
   44.31 +#ifdef OVR_OS_MAC
   44.32 + #include <stdlib.h>
   44.33 +#else
   44.34 + #include <malloc.h>
   44.35 +#endif
   44.36 +
   44.37 +#if defined(OVR_OS_MS)
   44.38 + #include <Windows.h>
   44.39 +#elif defined(OVR_OS_MAC) || defined(OVR_OS_UNIX)
   44.40 + #include <unistd.h>
   44.41 + #include <sys/mman.h>
   44.42 +#endif
   44.43 +
   44.44 +
   44.45 +namespace OVR {
   44.46 +
   44.47 +//-----------------------------------------------------------------------------------
   44.48 +// ***** Allocator
   44.49 +
   44.50 +Allocator* Allocator::pInstance = 0;
   44.51 +
   44.52 +// Default AlignedAlloc implementation will delegate to Alloc/Free after doing rounding.
   44.53 +void* Allocator::AllocAligned(size_t size, size_t align)
   44.54 +{
   44.55 +    OVR_ASSERT((align & (align-1)) == 0);
   44.56 +    align = (align > sizeof(size_t)) ? align : sizeof(size_t);
   44.57 +    size_t p = (size_t)Alloc(size+align);
   44.58 +    size_t aligned = 0;
   44.59 +    if (p)
   44.60 +    {
   44.61 +        aligned = (size_t(p) + align-1) & ~(align-1);
   44.62 +        if (aligned == p) 
   44.63 +            aligned += align;
   44.64 +        *(((size_t*)aligned)-1) = aligned-p;
   44.65 +    }
   44.66 +    return (void*)aligned;
   44.67 +}
   44.68 +
   44.69 +void Allocator::FreeAligned(void* p)
   44.70 +{
   44.71 +    size_t src = size_t(p) - *(((size_t*)p)-1);
   44.72 +    Free((void*)src);
   44.73 +}
   44.74 +
   44.75 +
   44.76 +//------------------------------------------------------------------------
   44.77 +// ***** Default Allocator
   44.78 +
   44.79 +// This allocator is created and used if no other allocator is installed.
   44.80 +// Default allocator delegates to system malloc.
   44.81 +
   44.82 +void* DefaultAllocator::Alloc(size_t size)
   44.83 +{
   44.84 +    return malloc(size);
   44.85 +}
   44.86 +void* DefaultAllocator::AllocDebug(size_t size, const char* file, unsigned line)
   44.87 +{
   44.88 +	OVR_UNUSED2(file, line); // should be here for debugopt config
   44.89 +#if defined(OVR_CC_MSVC) && defined(_CRTDBG_MAP_ALLOC)
   44.90 +    return _malloc_dbg(size, _NORMAL_BLOCK, file, line);
   44.91 +#else
   44.92 +    return malloc(size);
   44.93 +#endif
   44.94 +}
   44.95 +
   44.96 +void* DefaultAllocator::Realloc(void* p, size_t newSize)
   44.97 +{
   44.98 +    return realloc(p, newSize);
   44.99 +}
  44.100 +void DefaultAllocator::Free(void *p)
  44.101 +{
  44.102 +    return free(p);
  44.103 +}
  44.104 +
  44.105 +
  44.106 +
  44.107 +
  44.108 +void* MMapAlloc(size_t size)
  44.109 +{
  44.110 +    #if defined(OVR_OS_MS)
  44.111 +        return VirtualAlloc(NULL, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); // size is rounded up to a page. // Returned memory is 0-filled.
  44.112 +
  44.113 +    #elif defined(OVR_OS_MAC) || defined(OVR_OS_UNIX)
  44.114 +        #if !defined(MAP_FAILED)
  44.115 +            #define MAP_FAILED ((void*)-1)
  44.116 +        #endif
  44.117 +
  44.118 +        void* result = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); // Returned memory is 0-filled.
  44.119 +        if(result == MAP_FAILED) // mmap returns MAP_FAILED (-1) upon failure.
  44.120 +            result = NULL;
  44.121 +        return result;
  44.122 +    #endif
  44.123 +}
  44.124 +
  44.125 +
  44.126 +
  44.127 +
  44.128 +void MMapFree(void* memory, size_t size)
  44.129 +{
  44.130 +    #if defined(OVR_OS_MS)
  44.131 +        OVR_UNUSED(size);
  44.132 +        VirtualFree(memory, 0, MEM_RELEASE);
  44.133 +
  44.134 +    #elif defined(OVR_OS_MAC) || defined(OVR_OS_UNIX)
  44.135 +        size_t pageSize = getpagesize();
  44.136 +        size = (((size + (pageSize - 1)) / pageSize) * pageSize);
  44.137 +        munmap(memory, size); // Must supply the size to munmap.
  44.138 +    #endif
  44.139 +}
  44.140 +
  44.141 +
  44.142 +
  44.143 +
  44.144 +} // OVR
    45.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    45.2 +++ b/LibOVR/Src/Kernel/OVR_Allocator.h	Wed Jan 14 06:51:16 2015 +0200
    45.3 @@ -0,0 +1,360 @@
    45.4 +/************************************************************************************
    45.5 +
    45.6 +PublicHeader:   OVR_Kernel.h
    45.7 +Filename    :   OVR_Allocator.h
    45.8 +Content     :   Installable memory allocator
    45.9 +Created     :   September 19, 2012
   45.10 +Notes       : 
   45.11 +
   45.12 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   45.13 +
   45.14 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
   45.15 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
   45.16 +which is provided at the time of installation or download, or which 
   45.17 +otherwise accompanies this software in either electronic or hard copy form.
   45.18 +
   45.19 +You may obtain a copy of the License at
   45.20 +
   45.21 +http://www.oculusvr.com/licenses/LICENSE-3.2 
   45.22 +
   45.23 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
   45.24 +distributed under the License is distributed on an "AS IS" BASIS,
   45.25 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   45.26 +See the License for the specific language governing permissions and
   45.27 +limitations under the License.
   45.28 +
   45.29 +************************************************************************************/
   45.30 +
   45.31 +#ifndef OVR_Allocator_h
   45.32 +#define OVR_Allocator_h
   45.33 +
   45.34 +#include "OVR_Types.h"
   45.35 +
   45.36 +//-----------------------------------------------------------------------------------
   45.37 +
   45.38 +// ***** Disable template-unfriendly MS VC++ warnings
   45.39 +#if defined(OVR_CC_MSVC)
   45.40 +// Pragma to prevent long name warnings in in VC++
   45.41 +#pragma warning(disable : 4503)
   45.42 +#pragma warning(disable : 4786)
   45.43 +// In MSVC 7.1, warning about placement new POD default initializer
   45.44 +#pragma warning(disable : 4345)
   45.45 +#endif
   45.46 +
   45.47 +// Un-define new so that placement constructors work
   45.48 +#undef new
   45.49 +
   45.50 +
   45.51 +//-----------------------------------------------------------------------------------
   45.52 +// ***** Placement new overrides
   45.53 +
   45.54 +// Calls constructor on own memory created with "new(ptr) type"
   45.55 +#ifndef __PLACEMENT_NEW_INLINE
   45.56 +#define __PLACEMENT_NEW_INLINE
   45.57 +
   45.58 +#   if defined(OVR_CC_MWERKS) || defined(OVR_CC_BORLAND) || defined(OVR_CC_GNU)
   45.59 +#      include <new>
   45.60 +#   else
   45.61 +    // Useful on MSVC
   45.62 +    OVR_FORCE_INLINE void* operator new     (size_t n, void *ptr) { OVR_UNUSED(n); return ptr; }
   45.63 +    OVR_FORCE_INLINE void  operator delete  (void *, void *)     { }
   45.64 +#   endif
   45.65 +
   45.66 +#endif // __PLACEMENT_NEW_INLINE
   45.67 +
   45.68 +
   45.69 +
   45.70 +//------------------------------------------------------------------------
   45.71 +// ***** Macros to redefine class new/delete operators
   45.72 +
   45.73 +// Types specifically declared to allow disambiguation of address in
   45.74 +// class member operator new.
   45.75 +
   45.76 +#define OVR_MEMORY_REDEFINE_NEW_IMPL(class_name, check_delete)                          \
   45.77 +    void*   operator new(size_t sz)                                                      \
   45.78 +    { void *p = OVR_ALLOC_DEBUG(sz, __FILE__, __LINE__); return p; }                                              \
   45.79 +    void*   operator new(size_t sz, const char* file, int line)                          \
   45.80 +    { void* p = OVR_ALLOC_DEBUG(sz, file, line); OVR_UNUSED2(file, line); return p; }   \
   45.81 +    void    operator delete(void *p)                                                    \
   45.82 +    { check_delete(class_name, p); OVR_FREE(p); }                                       \
   45.83 +    void    operator delete(void *p, const char*, int)                                  \
   45.84 +    { check_delete(class_name, p); OVR_FREE(p); }                          
   45.85 +
   45.86 +#define OVR_MEMORY_DEFINE_PLACEMENT_NEW                                                 \
   45.87 +    void*   operator new        (size_t n, void *ptr)    { OVR_UNUSED(n); return ptr; }  \
   45.88 +    void    operator delete     (void *ptr, void *ptr2) { OVR_UNUSED2(ptr,ptr2); }
   45.89 +
   45.90 +
   45.91 +#define OVR_MEMORY_CHECK_DELETE_NONE(class_name, p)
   45.92 +
   45.93 +// Redefined all delete/new operators in a class without custom memory initialization
   45.94 +#define OVR_MEMORY_REDEFINE_NEW(class_name) \
   45.95 +    OVR_MEMORY_REDEFINE_NEW_IMPL(class_name, OVR_MEMORY_CHECK_DELETE_NONE)
   45.96 +
   45.97 +
   45.98 +namespace OVR {
   45.99 +
  45.100 +//-----------------------------------------------------------------------------------
  45.101 +// ***** Construct / Destruct
  45.102 +
  45.103 +// Construct/Destruct functions are useful when new is redefined, as they can
  45.104 +// be called instead of placement new constructors.
  45.105 +
  45.106 +
  45.107 +template <class T>
  45.108 +OVR_FORCE_INLINE T*  Construct(void *p)
  45.109 +{
  45.110 +    return ::new(p) T();
  45.111 +}
  45.112 +
  45.113 +template <class T>
  45.114 +OVR_FORCE_INLINE T*  Construct(void *p, const T& source)
  45.115 +{
  45.116 +    return ::new(p) T(source);
  45.117 +}
  45.118 +
  45.119 +// Same as above, but allows for a different type of constructor.
  45.120 +template <class T, class S>
  45.121 +OVR_FORCE_INLINE T*  ConstructAlt(void *p, const S& source)
  45.122 +{
  45.123 +    return ::new(p) T(source);
  45.124 +}
  45.125 +
  45.126 +template <class T, class S1, class S2>
  45.127 +OVR_FORCE_INLINE T*  ConstructAlt(void *p, const S1& src1, const S2& src2)
  45.128 +{
  45.129 +    return ::new(p) T(src1, src2);
  45.130 +}
  45.131 +
  45.132 +template <class T>
  45.133 +OVR_FORCE_INLINE void ConstructArray(void *p, size_t count)
  45.134 +{
  45.135 +    uint8_t *pdata = (uint8_t*)p;
  45.136 +    for (size_t i=0; i< count; ++i, pdata += sizeof(T))
  45.137 +    {
  45.138 +        Construct<T>(pdata);
  45.139 +    }
  45.140 +}
  45.141 +
  45.142 +template <class T>
  45.143 +OVR_FORCE_INLINE void ConstructArray(void *p, size_t count, const T& source)
  45.144 +{
  45.145 +    uint8_t *pdata = (uint8_t*)p;
  45.146 +    for (size_t i=0; i< count; ++i, pdata += sizeof(T))
  45.147 +    {
  45.148 +        Construct<T>(pdata, source);
  45.149 +    }
  45.150 +}
  45.151 +
  45.152 +template <class T>
  45.153 +OVR_FORCE_INLINE void Destruct(T *pobj)
  45.154 +{
  45.155 +    pobj->~T();
  45.156 +    OVR_UNUSED1(pobj); // Fix incorrect 'unused variable' MSVC warning.
  45.157 +}
  45.158 +
  45.159 +template <class T>
  45.160 +OVR_FORCE_INLINE void DestructArray(T *pobj, size_t count)
  45.161 +{   
  45.162 +    for (size_t i=0; i<count; ++i, ++pobj)
  45.163 +        pobj->~T();
  45.164 +}
  45.165 +
  45.166 +
  45.167 +//-----------------------------------------------------------------------------------
  45.168 +// ***** Allocator
  45.169 +
  45.170 +// Allocator defines a memory allocation interface that developers can override
  45.171 +// to to provide memory for OVR; an instance of this class is typically created on
  45.172 +// application startup and passed into System or OVR::System constructor.
  45.173 +// 
  45.174 +//
  45.175 +// Users implementing this interface must provide three functions: Alloc, Free,
  45.176 +// and Realloc. Implementations of these functions must honor the requested alignment.
  45.177 +// Although arbitrary alignment requests are possible, requested alignment will
  45.178 +// typically be small, such as 16 bytes or less.
  45.179 +
  45.180 +class Allocator
  45.181 +{
  45.182 +    friend class System;
  45.183 +public:
  45.184 +    virtual ~Allocator(){}
  45.185 +
  45.186 +    // *** Standard Alignment Alloc/Free
  45.187 +
  45.188 +    // Allocate memory of specified size with default alignment.
  45.189 +    // Alloc of size==0 will allocate a tiny block & return a valid pointer;
  45.190 +    // this makes it suitable for new operator.
  45.191 +    virtual void*   Alloc(size_t size) = 0;
  45.192 +    // Same as Alloc, but provides an option of passing debug data.
  45.193 +    virtual void*   AllocDebug(size_t size, const char* file, unsigned line)
  45.194 +    { OVR_UNUSED2(file, line); return Alloc(size); }
  45.195 +
  45.196 +    // Reallocate memory block to a new size, copying data if necessary. Returns the pointer to
  45.197 +    // new memory block, which may be the same as original pointer. Will return 0 if reallocation
  45.198 +    // failed, in which case previous memory is still valid.
  45.199 +    // Realloc to decrease size will never fail.
  45.200 +    // Realloc of pointer == 0 is equivalent to Alloc
  45.201 +    // Realloc to size == 0, shrinks to the minimal size, pointer remains valid and requires Free().
  45.202 +    virtual void*   Realloc(void* p, size_t newSize) = 0;
  45.203 +
  45.204 +    // Frees memory allocated by Alloc/Realloc.
  45.205 +    // Free of null pointer is valid and will do nothing.
  45.206 +    virtual void    Free(void *p) = 0;
  45.207 +
  45.208 +
  45.209 +    // *** Standard Alignment Alloc/Free
  45.210 +
  45.211 +    // Allocate memory of specified alignment.
  45.212 +    // Memory allocated with AllocAligned MUST be freed with FreeAligned.
  45.213 +    // Default implementation will delegate to Alloc/Free after doing rounding.
  45.214 +    virtual void*   AllocAligned(size_t size, size_t align);    
  45.215 +    // Frees memory allocated with AllocAligned.
  45.216 +    virtual void    FreeAligned(void* p);
  45.217 +    
  45.218 +    // Returns the pointer to the current globally installed Allocator instance.
  45.219 +    // This pointer is used for most of the memory allocations.
  45.220 +    static Allocator* GetInstance() { return pInstance; }
  45.221 +
  45.222 +
  45.223 +protected:
  45.224 +    // onSystemShutdown is called on the allocator during System::Shutdown.
  45.225 +    // At this point, all allocations should've been freed.
  45.226 +    virtual void    onSystemShutdown() { }
  45.227 +
  45.228 +public:
  45.229 +    static  void    setInstance(Allocator* palloc)    
  45.230 +    {
  45.231 +        OVR_ASSERT((pInstance == 0) || (palloc == 0));
  45.232 +        pInstance = palloc;
  45.233 +    }
  45.234 +
  45.235 +private:
  45.236 +
  45.237 +    static Allocator* pInstance;
  45.238 +};
  45.239 +
  45.240 +
  45.241 +
  45.242 +//------------------------------------------------------------------------
  45.243 +// ***** Allocator_SingletonSupport
  45.244 +
  45.245 +// Allocator_SingletonSupport is a Allocator wrapper class that implements
  45.246 +// the InitSystemSingleton static function, used to create a global singleton
  45.247 +// used for the OVR::System default argument initialization.
  45.248 +//
  45.249 +// End users implementing custom Allocator interface don't need to make use of this base
  45.250 +// class; they can just create an instance of their own class on stack and pass it to System.
  45.251 +
  45.252 +template<class D>
  45.253 +class Allocator_SingletonSupport : public Allocator
  45.254 +{
  45.255 +    struct AllocContainer
  45.256 +    {        
  45.257 +        size_t Data[(sizeof(D) + sizeof(size_t)-1) / sizeof(size_t)];
  45.258 +        bool  Initialized;
  45.259 +        AllocContainer() : Initialized(0) { }
  45.260 +    };
  45.261 +
  45.262 +    AllocContainer* pContainer;
  45.263 +
  45.264 +public:
  45.265 +    Allocator_SingletonSupport() : pContainer(0) { }
  45.266 +
  45.267 +    // Creates a singleton instance of this Allocator class used
  45.268 +    // on OVR_DEFAULT_ALLOCATOR during System initialization.
  45.269 +    static  D*  InitSystemSingleton()
  45.270 +    {
  45.271 +        static AllocContainer Container;
  45.272 +        OVR_ASSERT(Container.Initialized == false);
  45.273 +
  45.274 +        Allocator_SingletonSupport<D> *presult = Construct<D>((void*)Container.Data);
  45.275 +        presult->pContainer   = &Container;
  45.276 +        Container.Initialized = true;
  45.277 +        return (D*)presult;
  45.278 +    }
  45.279 +
  45.280 +protected:
  45.281 +    virtual void onSystemShutdown()
  45.282 +    {
  45.283 +        Allocator::onSystemShutdown();
  45.284 +        if (pContainer)
  45.285 +        {
  45.286 +            pContainer->Initialized = false;
  45.287 +            Destruct((D*)this);
  45.288 +            pContainer = 0;
  45.289 +        }
  45.290 +    }
  45.291 +};
  45.292 +
  45.293 +//------------------------------------------------------------------------
  45.294 +// ***** Default Allocator
  45.295 +
  45.296 +// This allocator is created and used if no other allocator is installed.
  45.297 +// Default allocator delegates to system malloc.
  45.298 +
  45.299 +class DefaultAllocator : public Allocator_SingletonSupport<DefaultAllocator>
  45.300 +{
  45.301 +public:
  45.302 +    virtual void*   Alloc(size_t size);
  45.303 +    virtual void*   AllocDebug(size_t size, const char* file, unsigned line);
  45.304 +    virtual void*   Realloc(void* p, size_t newSize);
  45.305 +    virtual void    Free(void *p);
  45.306 +};
  45.307 +
  45.308 +
  45.309 +//------------------------------------------------------------------------
  45.310 +// ***** Memory Allocation Macros
  45.311 +
  45.312 +// These macros should be used for global allocation. In the future, these
  45.313 +// macros will allows allocation to be extended with debug file/line information
  45.314 +// if necessary.
  45.315 +
  45.316 +#define OVR_REALLOC(p,s)        OVR::Allocator::GetInstance()->Realloc((p),(s))
  45.317 +#define OVR_FREE(p)             OVR::Allocator::GetInstance()->Free((p))
  45.318 +#define OVR_ALLOC_ALIGNED(s,a)  OVR::Allocator::GetInstance()->AllocAligned((s),(a))
  45.319 +#define OVR_FREE_ALIGNED(p)     OVR::Allocator::GetInstance()->FreeAligned((p))
  45.320 +
  45.321 +#ifdef OVR_BUILD_DEBUG
  45.322 +#define OVR_ALLOC(s)            OVR::Allocator::GetInstance()->AllocDebug((s), __FILE__, __LINE__)
  45.323 +#define OVR_ALLOC_DEBUG(s,f,l)  OVR::Allocator::GetInstance()->AllocDebug((s), f, l)
  45.324 +#else
  45.325 +#define OVR_ALLOC(s)            OVR::Allocator::GetInstance()->Alloc((s))
  45.326 +#define OVR_ALLOC_DEBUG(s,f,l)  OVR::Allocator::GetInstance()->Alloc((s))
  45.327 +#endif
  45.328 +
  45.329 +//------------------------------------------------------------------------
  45.330 +
  45.331 +// Base class that overrides the new and delete operators.
  45.332 +// Deriving from this class, even as a multiple base, incurs no space overhead.
  45.333 +class NewOverrideBase
  45.334 +{
  45.335 +public:
  45.336 +
  45.337 +    // Redefine all new & delete operators.
  45.338 +    OVR_MEMORY_REDEFINE_NEW(NewOverrideBase)
  45.339 +};
  45.340 +
  45.341 +
  45.342 +//------------------------------------------------------------------------
  45.343 +// ***** Mapped memory allocation
  45.344 +//
  45.345 +// Equates to VirtualAlloc/VirtualFree on Windows, mmap/munmap on Unix.
  45.346 +// These are useful for when you need system-supplied memory pages. 
  45.347 +// These are also useful for when you need to allocate memory in a way 
  45.348 +// that doesn't affect the application heap.
  45.349 +
  45.350 +void* MMapAlloc(size_t size);
  45.351 +void  MMapFree(void* memory, size_t size);
  45.352 +
  45.353 +
  45.354 +} // OVR
  45.355 +
  45.356 +
  45.357 +// Redefine operator 'new' if necessary.
  45.358 +#if defined(OVR_DEFINE_NEW)
  45.359 +#define new OVR_DEFINE_NEW
  45.360 +#endif
  45.361 +
  45.362 +
  45.363 +#endif // OVR_Memory
    46.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    46.2 +++ b/LibOVR/Src/Kernel/OVR_Array.h	Wed Jan 14 06:51:16 2015 +0200
    46.3 @@ -0,0 +1,837 @@
    46.4 +/************************************************************************************
    46.5 +
    46.6 +PublicHeader:   OVR_Kernel.h
    46.7 +Filename    :   OVR_Array.h
    46.8 +Content     :   Template implementation for Array
    46.9 +Created     :   September 19, 2012
   46.10 +Notes       : 
   46.11 +
   46.12 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   46.13 +
   46.14 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
   46.15 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
   46.16 +which is provided at the time of installation or download, or which 
   46.17 +otherwise accompanies this software in either electronic or hard copy form.
   46.18 +
   46.19 +You may obtain a copy of the License at
   46.20 +
   46.21 +http://www.oculusvr.com/licenses/LICENSE-3.2 
   46.22 +
   46.23 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
   46.24 +distributed under the License is distributed on an "AS IS" BASIS,
   46.25 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   46.26 +See the License for the specific language governing permissions and
   46.27 +limitations under the License.
   46.28 +
   46.29 +************************************************************************************/
   46.30 +
   46.31 +#ifndef OVR_Array_h
   46.32 +#define OVR_Array_h
   46.33 +
   46.34 +#include "OVR_ContainerAllocator.h"
   46.35 +
   46.36 +namespace OVR {
   46.37 +
   46.38 +//-----------------------------------------------------------------------------------
   46.39 +// ***** ArrayDefaultPolicy
   46.40 +//
   46.41 +// Default resize behavior. No minimal capacity, Granularity=4, 
   46.42 +// Shrinking as needed. ArrayConstPolicy actually is the same as 
   46.43 +// ArrayDefaultPolicy, but parametrized with constants. 
   46.44 +// This struct is used only in order to reduce the template "matroska".
   46.45 +struct ArrayDefaultPolicy
   46.46 +{
   46.47 +    ArrayDefaultPolicy() : Capacity(0) {}
   46.48 +    ArrayDefaultPolicy(const ArrayDefaultPolicy&) : Capacity(0) {}
   46.49 +
   46.50 +    size_t GetMinCapacity() const { return 0; }
   46.51 +    size_t GetGranularity() const { return 4; }
   46.52 +    bool  NeverShrinking() const { return 0; }
   46.53 +
   46.54 +    size_t GetCapacity()    const      { return Capacity; }
   46.55 +    void  SetCapacity(size_t capacity) { Capacity = capacity; }
   46.56 +private:
   46.57 +    size_t Capacity;
   46.58 +};
   46.59 +
   46.60 +
   46.61 +//-----------------------------------------------------------------------------------
   46.62 +// ***** ArrayConstPolicy
   46.63 +//
   46.64 +// Statically parametrized resizing behavior:
   46.65 +// MinCapacity, Granularity, and Shrinking flag.
   46.66 +template<int MinCapacity=0, int Granularity=4, bool NeverShrink=false>
   46.67 +struct ArrayConstPolicy
   46.68 +{
   46.69 +    typedef ArrayConstPolicy<MinCapacity, Granularity, NeverShrink> SelfType;
   46.70 +
   46.71 +    ArrayConstPolicy() : Capacity(0) {}
   46.72 +    ArrayConstPolicy(const SelfType&) : Capacity(0) {}
   46.73 +
   46.74 +    size_t GetMinCapacity() const { return MinCapacity; }
   46.75 +    size_t GetGranularity() const { return Granularity; }
   46.76 +    bool  NeverShrinking() const { return NeverShrink; }
   46.77 +
   46.78 +    size_t GetCapacity()    const      { return Capacity; }
   46.79 +    void  SetCapacity(size_t capacity) { Capacity = capacity; }
   46.80 +private:
   46.81 +    size_t Capacity;
   46.82 +};
   46.83 +
   46.84 +//-----------------------------------------------------------------------------------
   46.85 +// ***** ArrayDataBase
   46.86 +//
   46.87 +// Basic operations with array data: Reserve, Resize, Free, ArrayPolicy.
   46.88 +// For internal use only: ArrayData,ArrayDataCC and others.
   46.89 +template<class T, class Allocator, class SizePolicy>
   46.90 +struct ArrayDataBase
   46.91 +{
   46.92 +    typedef T                                           ValueType;
   46.93 +    typedef Allocator                                   AllocatorType;
   46.94 +    typedef SizePolicy                                  SizePolicyType;
   46.95 +    typedef ArrayDataBase<T, Allocator, SizePolicy>     SelfType;
   46.96 +
   46.97 +    ArrayDataBase()
   46.98 +        : Data(0), Size(0), Policy() {}
   46.99 +
  46.100 +    ArrayDataBase(const SizePolicy& p)
  46.101 +        : Data(0), Size(0), Policy(p) {}
  46.102 +
  46.103 +    ~ArrayDataBase() 
  46.104 +    {
  46.105 +        Allocator::DestructArray(Data, Size);
  46.106 +        Allocator::Free(Data);
  46.107 +    }
  46.108 +
  46.109 +    size_t GetCapacity() const 
  46.110 +    { 
  46.111 +        return Policy.GetCapacity(); 
  46.112 +    }
  46.113 +
  46.114 +    void ClearAndRelease()
  46.115 +    {
  46.116 +        Allocator::DestructArray(Data, Size);
  46.117 +        Allocator::Free(Data);
  46.118 +        Data = 0;
  46.119 +        Size = 0;
  46.120 +        Policy.SetCapacity(0);
  46.121 +    }
  46.122 +
  46.123 +    void Reserve(size_t newCapacity)
  46.124 +    {
  46.125 +        if (Policy.NeverShrinking() && newCapacity < GetCapacity())
  46.126 +            return;
  46.127 +
  46.128 +        if (newCapacity < Policy.GetMinCapacity())
  46.129 +            newCapacity = Policy.GetMinCapacity();
  46.130 +
  46.131 +        // Resize the buffer.
  46.132 +        if (newCapacity == 0)
  46.133 +        {
  46.134 +            if (Data)
  46.135 +            {
  46.136 +                Allocator::Free(Data);
  46.137 +                Data = 0;
  46.138 +            }
  46.139 +            Policy.SetCapacity(0);
  46.140 +        }
  46.141 +        else
  46.142 +        {
  46.143 +            size_t gran = Policy.GetGranularity();
  46.144 +            newCapacity = (newCapacity + gran - 1) / gran * gran;
  46.145 +            if (Data)
  46.146 +            {
  46.147 +                if (Allocator::IsMovable())
  46.148 +                {
  46.149 +                    Data = (T*)Allocator::Realloc(Data, sizeof(T) * newCapacity);
  46.150 +                }
  46.151 +                else
  46.152 +                {
  46.153 +                    T* newData = (T*)Allocator::Alloc(sizeof(T) * newCapacity);
  46.154 +                    size_t i, s;
  46.155 +                    s = (Size < newCapacity) ? Size : newCapacity;
  46.156 +                    for (i = 0; i < s; ++i)
  46.157 +                    {
  46.158 +                        Allocator::Construct(&newData[i], Data[i]);
  46.159 +                        Allocator::Destruct(&Data[i]);
  46.160 +                    }
  46.161 +                    for (i = s; i < Size; ++i)
  46.162 +                    {
  46.163 +                        Allocator::Destruct(&Data[i]);
  46.164 +                    }
  46.165 +                    Allocator::Free(Data);
  46.166 +                    Data = newData;
  46.167 +                }
  46.168 +            }
  46.169 +            else
  46.170 +            {
  46.171 +                Data = (T*)Allocator::Alloc(sizeof(T) * newCapacity);
  46.172 +                //memset(Buffer, 0, (sizeof(ValueType) * newSize)); // Do we need this?
  46.173 +            }
  46.174 +            Policy.SetCapacity(newCapacity);
  46.175 +            // OVR_ASSERT(Data); // need to throw (or something) on alloc failure!
  46.176 +        }
  46.177 +    }
  46.178 +
  46.179 +    // This version of Resize DOES NOT construct the elements.
  46.180 +    // It's done to optimize PushBack, which uses a copy constructor 
  46.181 +    // instead of the default constructor and assignment
  46.182 +    void ResizeNoConstruct(size_t newSize)
  46.183 +    {
  46.184 +        size_t oldSize = Size;
  46.185 +
  46.186 +        if (newSize < oldSize)
  46.187 +        {
  46.188 +            Allocator::DestructArray(Data + newSize, oldSize - newSize);
  46.189 +            if (newSize < (Policy.GetCapacity() >> 1))
  46.190 +            {
  46.191 +                Reserve(newSize);
  46.192 +            }
  46.193 +        }
  46.194 +        else if(newSize >= Policy.GetCapacity())
  46.195 +        {
  46.196 +            Reserve(newSize + (newSize >> 2));
  46.197 +        }
  46.198 +        //! IMPORTANT to modify Size only after Reserve completes, because garbage collectable
  46.199 +        // array may use this array and may traverse it during Reserve (in the case, if 
  46.200 +        // collection occurs because of heap limit exceeded).
  46.201 +        Size = newSize;
  46.202 +    }
  46.203 +
  46.204 +    ValueType*  Data;
  46.205 +    size_t      Size;
  46.206 +    SizePolicy  Policy;
  46.207 +};
  46.208 +
  46.209 +
  46.210 +
  46.211 +//-----------------------------------------------------------------------------------
  46.212 +// ***** ArrayData
  46.213 +//
  46.214 +// General purpose array data.
  46.215 +// For internal use only in Array, ArrayLH, ArrayPOD and so on.
  46.216 +template<class T, class Allocator, class SizePolicy>
  46.217 +struct ArrayData : ArrayDataBase<T, Allocator, SizePolicy>
  46.218 +{
  46.219 +    typedef T ValueType;
  46.220 +    typedef Allocator                                   AllocatorType;
  46.221 +    typedef SizePolicy                                  SizePolicyType;
  46.222 +    typedef ArrayDataBase<T, Allocator, SizePolicy>     BaseType;
  46.223 +    typedef ArrayData    <T, Allocator, SizePolicy>     SelfType;
  46.224 +
  46.225 +    ArrayData()
  46.226 +        : BaseType() { }
  46.227 +
  46.228 +    ArrayData(size_t size)
  46.229 +        : BaseType() { Resize(size); }
  46.230 +
  46.231 +    ArrayData(const SelfType& a)
  46.232 +        : BaseType(a.Policy) { Append(a.Data, a.Size); }
  46.233 +
  46.234 +
  46.235 +    void Resize(size_t newSize)
  46.236 +    {
  46.237 +        size_t oldSize = this->Size;
  46.238 +        BaseType::ResizeNoConstruct(newSize);
  46.239 +        if(newSize > oldSize)
  46.240 +            Allocator::ConstructArray(this->Data + oldSize, newSize - oldSize);
  46.241 +    }
  46.242 +
  46.243 +    void PushBack(const ValueType& val)
  46.244 +    {
  46.245 +        BaseType::ResizeNoConstruct(this->Size + 1);
  46.246 +        OVR_ASSERT(this->Data != NULL);
  46.247 +        Allocator::Construct(this->Data + this->Size - 1, val);
  46.248 +    }
  46.249 +
  46.250 +    template<class S>
  46.251 +    void PushBackAlt(const S& val)
  46.252 +    {
  46.253 +        BaseType::ResizeNoConstruct(this->Size + 1);
  46.254 +        Allocator::ConstructAlt(this->Data + this->Size - 1, val);
  46.255 +    }
  46.256 +
  46.257 +    // Append the given data to the array.
  46.258 +    void Append(const ValueType other[], size_t count)
  46.259 +    {
  46.260 +        if (count)
  46.261 +        {
  46.262 +            size_t oldSize = this->Size;
  46.263 +            BaseType::ResizeNoConstruct(this->Size + count);
  46.264 +            Allocator::ConstructArray(this->Data + oldSize, count, other);
  46.265 +        }
  46.266 +    }
  46.267 +};
  46.268 +
  46.269 +
  46.270 +
  46.271 +//-----------------------------------------------------------------------------------
  46.272 +// ***** ArrayDataCC
  46.273 +//
  46.274 +// A modification of ArrayData that always copy-constructs new elements
  46.275 +// using a specified DefaultValue. For internal use only in ArrayCC.
  46.276 +template<class T, class Allocator, class SizePolicy>
  46.277 +struct ArrayDataCC : ArrayDataBase<T, Allocator, SizePolicy>
  46.278 +{
  46.279 +    typedef T                                           ValueType;
  46.280 +    typedef Allocator                                   AllocatorType;
  46.281 +    typedef SizePolicy                                  SizePolicyType;
  46.282 +    typedef ArrayDataBase<T, Allocator, SizePolicy>     BaseType;
  46.283 +    typedef ArrayDataCC  <T, Allocator, SizePolicy>     SelfType;
  46.284 +
  46.285 +    ArrayDataCC(const ValueType& defval)
  46.286 +        : BaseType(), DefaultValue(defval) { }
  46.287 +
  46.288 +    ArrayDataCC(const ValueType& defval, size_t size)
  46.289 +        : BaseType(), DefaultValue(defval) { Resize(size); }
  46.290 +
  46.291 +    ArrayDataCC(const SelfType& a)
  46.292 +        : BaseType(a.Policy), DefaultValue(a.DefaultValue) { Append(a.Data, a.Size); }
  46.293 +
  46.294 +
  46.295 +    void Resize(size_t newSize)
  46.296 +    {
  46.297 +        size_t oldSize = this->Size;
  46.298 +        BaseType::ResizeNoConstruct(newSize);
  46.299 +        if(newSize > oldSize)
  46.300 +            Allocator::ConstructArray(this->Data + oldSize, newSize - oldSize, DefaultValue);
  46.301 +    }
  46.302 +
  46.303 +    void PushBack(const ValueType& val)
  46.304 +    {
  46.305 +        BaseType::ResizeNoConstruct(this->Size + 1);
  46.306 +        Allocator::Construct(this->Data + this->Size - 1, val);
  46.307 +    }
  46.308 +
  46.309 +    template<class S>
  46.310 +    void PushBackAlt(const S& val)
  46.311 +    {
  46.312 +        BaseType::ResizeNoConstruct(this->Size + 1);
  46.313 +        Allocator::ConstructAlt(this->Data + this->Size - 1, val);
  46.314 +    }
  46.315 +
  46.316 +    // Append the given data to the array.
  46.317 +    void Append(const ValueType other[], size_t count)
  46.318 +    {
  46.319 +        if (count)
  46.320 +        {
  46.321 +            size_t oldSize = this->Size;
  46.322 +            BaseType::ResizeNoConstruct(this->Size + count);
  46.323 +            Allocator::ConstructArray(this->Data + oldSize, count, other);
  46.324 +        }
  46.325 +    }
  46.326 +
  46.327 +    ValueType   DefaultValue;
  46.328 +};
  46.329 +
  46.330 +
  46.331 +
  46.332 +
  46.333 +
  46.334 +//-----------------------------------------------------------------------------------
  46.335 +// ***** ArrayBase
  46.336 +//
  46.337 +// Resizable array. The behavior can be POD (suffix _POD) and 
  46.338 +// Movable (no suffix) depending on the allocator policy.
  46.339 +// In case of _POD the constructors and destructors are not called.
  46.340 +// 
  46.341 +// Arrays can't handle non-movable objects! Don't put anything in here 
  46.342 +// that can't be moved around by bitwise copy. 
  46.343 +// 
  46.344 +// The addresses of elements are not persistent! Don't keep the address 
  46.345 +// of an element; the array contents will move around as it gets resized.
  46.346 +template<class ArrayData>
  46.347 +class ArrayBase
  46.348 +{
  46.349 +public:
  46.350 +    typedef typename ArrayData::ValueType       ValueType;
  46.351 +    typedef typename ArrayData::AllocatorType   AllocatorType;
  46.352 +    typedef typename ArrayData::SizePolicyType  SizePolicyType;
  46.353 +    typedef ArrayBase<ArrayData>                SelfType;
  46.354 +
  46.355 +
  46.356 +#undef new
  46.357 +    OVR_MEMORY_REDEFINE_NEW(ArrayBase)
  46.358 +// Redefine operator 'new' if necessary.
  46.359 +#if defined(OVR_DEFINE_NEW)
  46.360 +#define new OVR_DEFINE_NEW
  46.361 +#endif
  46.362 +
  46.363 +
  46.364 +    ArrayBase()
  46.365 +        : Data() {}
  46.366 +    ArrayBase(size_t size)
  46.367 +        : Data(size) {}
  46.368 +    ArrayBase(const SelfType& a)
  46.369 +        : Data(a.Data) {}
  46.370 +
  46.371 +    ArrayBase(const ValueType& defval)
  46.372 +        : Data(defval) {}
  46.373 +    ArrayBase(const ValueType& defval, size_t size)
  46.374 +        : Data(defval, size) {}
  46.375 +  
  46.376 +    SizePolicyType* GetSizePolicy() const                  { return Data.Policy; }
  46.377 +    void            SetSizePolicy(const SizePolicyType& p) { Data.Policy = p; }
  46.378 +
  46.379 +    bool    NeverShrinking()const       { return Data.Policy.NeverShrinking(); }
  46.380 +	size_t  GetSize()       const       { return Data.Size; }
  46.381 +	int     GetSizeI()      const       { return (int)Data.Size; }
  46.382 +	bool    IsEmpty()       const       { return Data.Size == 0; }
  46.383 +    size_t  GetCapacity()   const       { return Data.GetCapacity(); }
  46.384 +    size_t  GetNumBytes()   const       { return Data.GetCapacity() * sizeof(ValueType); }
  46.385 +
  46.386 +    void    ClearAndRelease()           { Data.ClearAndRelease(); }
  46.387 +    void    Clear()                     { Data.Resize(0); }
  46.388 +    void    Resize(size_t newSize)       { Data.Resize(newSize); }
  46.389 +
  46.390 +    // Reserve can only increase the capacity
  46.391 +    void    Reserve(size_t newCapacity)  
  46.392 +    { 
  46.393 +        if (newCapacity > Data.GetCapacity())
  46.394 +            Data.Reserve(newCapacity); 
  46.395 +    }
  46.396 +
  46.397 +    // Basic access.
  46.398 +    ValueType& At(size_t index)
  46.399 +    {
  46.400 +        OVR_ASSERT((Data.Data) && (index < Data.Size)); // Asserting that Data.Data is valid helps static analysis tools.
  46.401 +        return Data.Data[index];
  46.402 +    }
  46.403 +    const ValueType& At(size_t index) const
  46.404 +    {
  46.405 +        OVR_ASSERT((Data.Data) && (index < Data.Size));
  46.406 +        return Data.Data[index];
  46.407 +    }
  46.408 +
  46.409 +    ValueType ValueAt(size_t index) const
  46.410 +    {
  46.411 +        OVR_ASSERT((Data.Data) && (index < Data.Size));
  46.412 +        return Data.Data[index];
  46.413 +    }
  46.414 +
  46.415 +    // Basic access.
  46.416 +    ValueType& operator [] (size_t index)
  46.417 +    {
  46.418 +        OVR_ASSERT((Data.Data) && (index < Data.Size));
  46.419 +        return Data.Data[index]; 
  46.420 +    }
  46.421 +    const ValueType& operator [] (size_t index) const
  46.422 +    {
  46.423 +        OVR_ASSERT((Data.Data) && (index < Data.Size));
  46.424 +        return Data.Data[index];
  46.425 +    }
  46.426 +
  46.427 +    // Raw pointer to the data. Use with caution!
  46.428 +    const ValueType* GetDataPtr() const { return Data.Data; }
  46.429 +          ValueType* GetDataPtr()       { return Data.Data; }
  46.430 +
  46.431 +    // Insert the given element at the end of the array.
  46.432 +    void    PushBack(const ValueType& val)
  46.433 +    {
  46.434 +        // DO NOT pass elements of your own vector into
  46.435 +        // push_back()!  Since we're using references,
  46.436 +        // resize() may munge the element storage!
  46.437 +        // OVR_ASSERT(&val < &Buffer[0] || &val > &Buffer[BufferSize]);
  46.438 +        Data.PushBack(val);
  46.439 +    }
  46.440 +
  46.441 +    template<class S>
  46.442 +    void PushBackAlt(const S& val)
  46.443 +    {
  46.444 +        Data.PushBackAlt(val);
  46.445 +    }
  46.446 +
  46.447 +    // Remove the last element.
  46.448 +    void    PopBack(size_t count = 1)
  46.449 +    {
  46.450 +        OVR_ASSERT(Data.Size >= count);
  46.451 +        Data.Resize(Data.Size - count);
  46.452 +    }
  46.453 +
  46.454 +    ValueType& PushDefault()
  46.455 +    {
  46.456 +        Data.PushBack(ValueType());
  46.457 +        return Back();
  46.458 +    }
  46.459 +
  46.460 +    ValueType Pop()
  46.461 +    {
  46.462 +        OVR_ASSERT((Data.Data) && (Data.Size > 0));
  46.463 +        ValueType t = Back();
  46.464 +        PopBack();
  46.465 +        return t;
  46.466 +    }
  46.467 +
  46.468 +
  46.469 +    // Access the first element.
  46.470 +    ValueType&          Front()         { return At(0); }
  46.471 +    const ValueType&    Front() const   { return At(0); }
  46.472 +
  46.473 +    // Access the last element.
  46.474 +    ValueType&          Back()          { return At(Data.Size - 1); }
  46.475 +    const ValueType&    Back() const    { return At(Data.Size - 1); }
  46.476 +
  46.477 +    // Array copy.  Copies the contents of a into this array.
  46.478 +    const SelfType& operator = (const SelfType& a)   
  46.479 +    {
  46.480 +        Resize(a.GetSize());
  46.481 +        OVR_ASSERT((Data.Data != NULL) || (Data.Size == 0));
  46.482 +        for (size_t i = 0; i < Data.Size; i++) {
  46.483 +            *(Data.Data + i) = a[i];
  46.484 +        }
  46.485 +        return *this;
  46.486 +    }
  46.487 +
  46.488 +    // Removing multiple elements from the array.
  46.489 +    void    RemoveMultipleAt(size_t index, size_t num)
  46.490 +    {
  46.491 +        OVR_ASSERT(index + num <= Data.Size);
  46.492 +        if (Data.Size == num)
  46.493 +        {
  46.494 +            Clear();
  46.495 +        }
  46.496 +        else
  46.497 +        {
  46.498 +            AllocatorType::DestructArray(Data.Data + index, num);
  46.499 +            AllocatorType::CopyArrayForward(
  46.500 +                Data.Data + index, 
  46.501 +                Data.Data + index + num,
  46.502 +                Data.Size - num - index);
  46.503 +            Data.Size -= num;
  46.504 +        }
  46.505 +    }
  46.506 +
  46.507 +    // Removing an element from the array is an expensive operation!
  46.508 +    // It compacts only after removing the last element.
  46.509 +    // If order of elements in the array is not important then use 
  46.510 +    // RemoveAtUnordered, that could be much faster than the regular
  46.511 +    // RemoveAt.
  46.512 +    void    RemoveAt(size_t index)
  46.513 +    {
  46.514 +        OVR_ASSERT((Data.Data) && (index < Data.Size));
  46.515 +        if (Data.Size == 1)
  46.516 +        {
  46.517 +            Clear();
  46.518 +        }
  46.519 +        else
  46.520 +        {
  46.521 +            AllocatorType::Destruct(Data.Data + index);
  46.522 +            AllocatorType::CopyArrayForward(
  46.523 +                Data.Data + index, 
  46.524 +                Data.Data + index + 1,
  46.525 +                Data.Size - 1 - index);
  46.526 +            --Data.Size;
  46.527 +        }
  46.528 +    }
  46.529 +
  46.530 +    // Removes an element from the array without respecting of original order of 
  46.531 +    // elements for better performance. Do not use on array where order of elements
  46.532 +    // is important, otherwise use it instead of regular RemoveAt().
  46.533 +    void    RemoveAtUnordered(size_t index)
  46.534 +    {
  46.535 +        OVR_ASSERT((Data.Data) && (index < Data.Size));
  46.536 +        if (Data.Size == 1)
  46.537 +        {
  46.538 +            Clear();
  46.539 +        }
  46.540 +        else
  46.541 +        {
  46.542 +            // copy the last element into the 'index' position 
  46.543 +            // and decrement the size (instead of moving all elements
  46.544 +            // in [index + 1 .. size - 1] range).
  46.545 +            const size_t lastElemIndex = Data.Size - 1;
  46.546 +            if (index < lastElemIndex)
  46.547 +            {
  46.548 +                AllocatorType::Destruct(Data.Data + index);
  46.549 +                AllocatorType::Construct(Data.Data + index, Data.Data[lastElemIndex]);
  46.550 +            }
  46.551 +            AllocatorType::Destruct(Data.Data + lastElemIndex);
  46.552 +            --Data.Size;
  46.553 +        }
  46.554 +    }
  46.555 +
  46.556 +    // Insert the given object at the given index shifting all the elements up.
  46.557 +    void    InsertAt(size_t index, const ValueType& val = ValueType())
  46.558 +    {
  46.559 +        OVR_ASSERT(index <= Data.Size);
  46.560 +
  46.561 +        Data.Resize(Data.Size + 1);
  46.562 +        if (index < Data.Size - 1)
  46.563 +        {
  46.564 +            AllocatorType::CopyArrayBackward(
  46.565 +                Data.Data + index + 1, 
  46.566 +                Data.Data + index, 
  46.567 +                Data.Size - 1 - index);
  46.568 +        }
  46.569 +        AllocatorType::Construct(Data.Data + index, val);
  46.570 +    }
  46.571 +
  46.572 +    // Insert the given object at the given index shifting all the elements up.
  46.573 +    void    InsertMultipleAt(size_t index, size_t num, const ValueType& val = ValueType())
  46.574 +    {
  46.575 +        OVR_ASSERT(index <= Data.Size);
  46.576 +
  46.577 +        Data.Resize(Data.Size + num);
  46.578 +        if (index < Data.Size - num)
  46.579 +        {
  46.580 +            AllocatorType::CopyArrayBackward(
  46.581 +                Data.Data + index + num,
  46.582 +                Data.Data + index,
  46.583 +                Data.Size - num - index);
  46.584 +        }
  46.585 +        for (size_t i = 0; i < num; ++i)
  46.586 +            AllocatorType::Construct(Data.Data + index + i, val);
  46.587 +    }
  46.588 +
  46.589 +    // Append the given data to the array.
  46.590 +    void    Append(const SelfType& other)
  46.591 +    {
  46.592 +        Append(other.Data.Data, other.GetSize());
  46.593 +    }
  46.594 +
  46.595 +    // Append the given data to the array.
  46.596 +    void    Append(const ValueType other[], size_t count)
  46.597 +    {
  46.598 +        Data.Append(other, count);
  46.599 +    }
  46.600 +
  46.601 +    class Iterator
  46.602 +    {
  46.603 +        SelfType*       pArray;
  46.604 +        intptr_t        CurIndex;
  46.605 +
  46.606 +    public:
  46.607 +        Iterator() : pArray(0), CurIndex(-1) {}
  46.608 +        Iterator(SelfType* parr, intptr_t idx = 0) : pArray(parr), CurIndex(idx) {}
  46.609 +
  46.610 +        bool operator==(const Iterator& it) const { return pArray == it.pArray && CurIndex == it.CurIndex; }
  46.611 +        bool operator!=(const Iterator& it) const { return pArray != it.pArray || CurIndex != it.CurIndex; }
  46.612 +
  46.613 +        Iterator& operator++()
  46.614 +        {
  46.615 +            if (pArray)
  46.616 +            {
  46.617 +                if (CurIndex < (intptr_t)pArray->GetSize())
  46.618 +                    ++CurIndex;
  46.619 +            }
  46.620 +            return *this;
  46.621 +        }
  46.622 +        Iterator operator++(int)
  46.623 +        {
  46.624 +            Iterator it(*this);
  46.625 +            operator++();
  46.626 +            return it;
  46.627 +        }
  46.628 +        Iterator& operator--()
  46.629 +        {
  46.630 +            if (pArray)
  46.631 +            {
  46.632 +                if (CurIndex >= 0)
  46.633 +                    --CurIndex;
  46.634 +            }
  46.635 +            return *this;
  46.636 +        }
  46.637 +        Iterator operator--(int)
  46.638 +        {
  46.639 +            Iterator it(*this);
  46.640 +            operator--();
  46.641 +            return it;
  46.642 +        }
  46.643 +        Iterator operator+(int delta) const
  46.644 +        {
  46.645 +            return Iterator(pArray, CurIndex + delta);
  46.646 +        }
  46.647 +        Iterator operator-(int delta) const
  46.648 +        {
  46.649 +            return Iterator(pArray, CurIndex - delta);
  46.650 +        }
  46.651 +        intptr_t operator-(const Iterator& right) const
  46.652 +        {
  46.653 +            OVR_ASSERT(pArray == right.pArray);
  46.654 +            return CurIndex - right.CurIndex;
  46.655 +        }
  46.656 +        ValueType& operator*() const    { OVR_ASSERT(pArray); return  (*pArray)[CurIndex]; }
  46.657 +        ValueType* operator->() const   { OVR_ASSERT(pArray); return &(*pArray)[CurIndex]; }
  46.658 +        ValueType* GetPtr() const       { OVR_ASSERT(pArray); return &(*pArray)[CurIndex]; }
  46.659 +
  46.660 +        bool IsFinished() const { return !pArray || CurIndex < 0 || CurIndex >= (int)pArray->GetSize(); }
  46.661 +
  46.662 +        void Remove()
  46.663 +        {
  46.664 +            if (!IsFinished())
  46.665 +                pArray->RemoveAt(CurIndex);
  46.666 +        }
  46.667 +
  46.668 +        intptr_t GetIndex() const { return CurIndex; }
  46.669 +    };
  46.670 +
  46.671 +    Iterator Begin() { return Iterator(this); }
  46.672 +    Iterator End()   { return Iterator(this, (intptr_t)GetSize()); }
  46.673 +    Iterator Last()  { return Iterator(this, (intptr_t)GetSize() - 1); }
  46.674 +
  46.675 +    class ConstIterator
  46.676 +    {
  46.677 +        const SelfType* pArray;
  46.678 +        intptr_t        CurIndex;
  46.679 +
  46.680 +    public:
  46.681 +        ConstIterator() : pArray(0), CurIndex(-1) {}
  46.682 +        ConstIterator(const SelfType* parr, intptr_t idx = 0) : pArray(parr), CurIndex(idx) {}
  46.683 +
  46.684 +        bool operator==(const ConstIterator& it) const { return pArray == it.pArray && CurIndex == it.CurIndex; }
  46.685 +        bool operator!=(const ConstIterator& it) const { return pArray != it.pArray || CurIndex != it.CurIndex; }
  46.686 +
  46.687 +        ConstIterator& operator++()
  46.688 +        {
  46.689 +            if (pArray)
  46.690 +            {
  46.691 +                if (CurIndex < (int)pArray->GetSize())
  46.692 +                    ++CurIndex;
  46.693 +            }
  46.694 +            return *this;
  46.695 +        }
  46.696 +        ConstIterator operator++(int)
  46.697 +        {
  46.698 +            ConstIterator it(*this);
  46.699 +            operator++();
  46.700 +            return it;
  46.701 +        }
  46.702 +        ConstIterator& operator--()
  46.703 +        {
  46.704 +            if (pArray)
  46.705 +            {
  46.706 +                if (CurIndex >= 0)
  46.707 +                    --CurIndex;
  46.708 +            }
  46.709 +            return *this;
  46.710 +        }
  46.711 +        ConstIterator operator--(int)
  46.712 +        {
  46.713 +            ConstIterator it(*this);
  46.714 +            operator--();
  46.715 +            return it;
  46.716 +        }
  46.717 +        ConstIterator operator+(int delta) const
  46.718 +        {
  46.719 +            return ConstIterator(pArray, CurIndex + delta);
  46.720 +        }
  46.721 +        ConstIterator operator-(int delta) const
  46.722 +        {
  46.723 +            return ConstIterator(pArray, CurIndex - delta);
  46.724 +        }
  46.725 +        intptr_t operator-(const ConstIterator& right) const
  46.726 +        {
  46.727 +            OVR_ASSERT(pArray == right.pArray);
  46.728 +            return CurIndex - right.CurIndex;
  46.729 +        }
  46.730 +        const ValueType& operator*() const  { OVR_ASSERT(pArray); return  (*pArray)[CurIndex]; }
  46.731 +        const ValueType* operator->() const { OVR_ASSERT(pArray); return &(*pArray)[CurIndex]; }
  46.732 +        const ValueType* GetPtr() const     { OVR_ASSERT(pArray); return &(*pArray)[CurIndex]; }
  46.733 +
  46.734 +        bool IsFinished() const { return !pArray || CurIndex < 0 || CurIndex >= (int)pArray->GetSize(); }
  46.735 +
  46.736 +        intptr_t GetIndex()  const { return CurIndex; }
  46.737 +    };
  46.738 +    ConstIterator Begin() const { return ConstIterator(this); }
  46.739 +    ConstIterator End() const   { return ConstIterator(this, (intptr_t)GetSize()); }
  46.740 +    ConstIterator Last() const  { return ConstIterator(this, (intptr_t)GetSize() - 1); }
  46.741 +
  46.742 +protected:
  46.743 +    ArrayData   Data;
  46.744 +};
  46.745 +
  46.746 +
  46.747 +
  46.748 +//-----------------------------------------------------------------------------------
  46.749 +// ***** Array
  46.750 +//
  46.751 +// General purpose array for movable objects that require explicit 
  46.752 +// construction/destruction.
  46.753 +template<class T, class SizePolicy=ArrayDefaultPolicy>
  46.754 +class Array : public ArrayBase<ArrayData<T, ContainerAllocator<T>, SizePolicy> >
  46.755 +{
  46.756 +public:
  46.757 +    typedef T                                                           ValueType;
  46.758 +    typedef ContainerAllocator<T>                                       AllocatorType;
  46.759 +    typedef SizePolicy                                                  SizePolicyType;
  46.760 +    typedef Array<T, SizePolicy>                                        SelfType;
  46.761 +    typedef ArrayBase<ArrayData<T, ContainerAllocator<T>, SizePolicy> > BaseType;
  46.762 +
  46.763 +    Array() : BaseType() {}
  46.764 +    Array(size_t size) : BaseType(size) {}
  46.765 +    Array(const SizePolicyType& p) : BaseType() { SetSizePolicy(p); }
  46.766 +    Array(const SelfType& a) : BaseType(a) {}
  46.767 +    const SelfType& operator=(const SelfType& a) { BaseType::operator=(a); return *this; }
  46.768 +};
  46.769 +
  46.770 +// ***** ArrayPOD
  46.771 +//
  46.772 +// General purpose array for movable objects that DOES NOT require  
  46.773 +// construction/destruction. Constructors and destructors are not called! 
  46.774 +// Global heap is in use.
  46.775 +template<class T, class SizePolicy=ArrayDefaultPolicy>
  46.776 +class ArrayPOD : public ArrayBase<ArrayData<T, ContainerAllocator_POD<T>, SizePolicy> >
  46.777 +{
  46.778 +public:
  46.779 +    typedef T                                                               ValueType;
  46.780 +    typedef ContainerAllocator_POD<T>                                       AllocatorType;
  46.781 +    typedef SizePolicy                                                      SizePolicyType;
  46.782 +    typedef ArrayPOD<T, SizePolicy>                                         SelfType;
  46.783 +    typedef ArrayBase<ArrayData<T, ContainerAllocator_POD<T>, SizePolicy> > BaseType;
  46.784 +
  46.785 +    ArrayPOD() : BaseType() {}
  46.786 +    ArrayPOD(size_t size) : BaseType(size) {}
  46.787 +    ArrayPOD(const SizePolicyType& p) : BaseType() { SetSizePolicy(p); }
  46.788 +    ArrayPOD(const SelfType& a) : BaseType(a) {}
  46.789 +    const SelfType& operator=(const SelfType& a) { BaseType::operator=(a); return *this; }
  46.790 +};
  46.791 +
  46.792 +
  46.793 +// ***** ArrayCPP
  46.794 +//
  46.795 +// General purpose, fully C++ compliant array. Can be used with non-movable data.
  46.796 +// Global heap is in use.
  46.797 +template<class T, class SizePolicy=ArrayDefaultPolicy>
  46.798 +class ArrayCPP : public ArrayBase<ArrayData<T, ContainerAllocator_CPP<T>, SizePolicy> >
  46.799 +{
  46.800 +public:
  46.801 +    typedef T                                                               ValueType;
  46.802 +    typedef ContainerAllocator_CPP<T>                                       AllocatorType;
  46.803 +    typedef SizePolicy                                                      SizePolicyType;
  46.804 +    typedef ArrayCPP<T, SizePolicy>                                         SelfType;
  46.805 +    typedef ArrayBase<ArrayData<T, ContainerAllocator_CPP<T>, SizePolicy> > BaseType;
  46.806 +
  46.807 +    ArrayCPP() : BaseType() {}
  46.808 +    ArrayCPP(size_t size) : BaseType(size) {}
  46.809 +    ArrayCPP(const SizePolicyType& p) : BaseType() { SetSizePolicy(p); }
  46.810 +    ArrayCPP(const SelfType& a) : BaseType(a) {}
  46.811 +    const SelfType& operator=(const SelfType& a) { BaseType::operator=(a); return *this; }
  46.812 +};
  46.813 +
  46.814 +
  46.815 +// ***** ArrayCC
  46.816 +//
  46.817 +// A modification of the array that uses the given default value to
  46.818 +// construct the elements. The constructors and destructors are 
  46.819 +// properly called, the objects must be movable.
  46.820 +
  46.821 +template<class T, class SizePolicy=ArrayDefaultPolicy>
  46.822 +class ArrayCC : public ArrayBase<ArrayDataCC<T, ContainerAllocator<T>, SizePolicy> >
  46.823 +{
  46.824 +public:
  46.825 +    typedef T                                                               ValueType;
  46.826 +    typedef ContainerAllocator<T>                                           AllocatorType;
  46.827 +    typedef SizePolicy                                                      SizePolicyType;
  46.828 +    typedef ArrayCC<T, SizePolicy>                                          SelfType;
  46.829 +    typedef ArrayBase<ArrayDataCC<T, ContainerAllocator<T>, SizePolicy> >   BaseType;
  46.830 +
  46.831 +    ArrayCC(const ValueType& defval) : BaseType(defval) {}
  46.832 +    ArrayCC(const ValueType& defval, size_t size) : BaseType(defval, size) {}
  46.833 +    ArrayCC(const ValueType& defval, const SizePolicyType& p) : BaseType(defval) { SetSizePolicy(p); }
  46.834 +    ArrayCC(const SelfType& a) : BaseType(a) {}
  46.835 +    const SelfType& operator=(const SelfType& a) { BaseType::operator=(a); return *this; }
  46.836 +};
  46.837 +
  46.838 +} // OVR
  46.839 +
  46.840 +#endif
    47.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    47.2 +++ b/LibOVR/Src/Kernel/OVR_Atomic.cpp	Wed Jan 14 06:51:16 2015 +0200
    47.3 @@ -0,0 +1,139 @@
    47.4 +/************************************************************************************
    47.5 +
    47.6 +Filename    :   OVR_Atomic.cpp
    47.7 +Content     :   Contains atomic operations and inline fastest locking
    47.8 +                functionality. Will contain #ifdefs for OS efficiency.
    47.9 +                Have non-thread-safe implementation if not available.
   47.10 +Created     :   September 19, 2012
   47.11 +Notes       : 
   47.12 +
   47.13 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   47.14 +
   47.15 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
   47.16 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
   47.17 +which is provided at the time of installation or download, or which 
   47.18 +otherwise accompanies this software in either electronic or hard copy form.
   47.19 +
   47.20 +You may obtain a copy of the License at
   47.21 +
   47.22 +http://www.oculusvr.com/licenses/LICENSE-3.2 
   47.23 +
   47.24 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
   47.25 +distributed under the License is distributed on an "AS IS" BASIS,
   47.26 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   47.27 +See the License for the specific language governing permissions and
   47.28 +limitations under the License.
   47.29 +
   47.30 +************************************************************************************/
   47.31 +
   47.32 +#include "OVR_Atomic.h"
   47.33 +#include "OVR_Allocator.h"
   47.34 +
   47.35 +#ifdef OVR_ENABLE_THREADS
   47.36 +
   47.37 +// Include Windows 8-Metro compatible Synchronization API
   47.38 +#if defined(OVR_OS_MS) && defined(NTDDI_WIN8) && (NTDDI_VERSION >= NTDDI_WIN8)
   47.39 +#include <synchapi.h>
   47.40 +#endif
   47.41 +
   47.42 +
   47.43 +namespace OVR {
   47.44 +
   47.45 +// ***** Windows Lock implementation
   47.46 +
   47.47 +#if defined(OVR_OS_MS)
   47.48 +
   47.49 +// ***** Standard Win32 Lock implementation
   47.50 +
   47.51 +// Constructors
   47.52 +Lock::Lock(unsigned spinCount)
   47.53 +{
   47.54 +    #if defined(NTDDI_WIN8) && (NTDDI_VERSION >= NTDDI_WIN8)
   47.55 +       // On Windows 8 we use InitializeCriticalSectionEx due to Metro-Compatibility
   47.56 +       InitializeCriticalSectionEx(&cs, (DWORD)spinCount,
   47.57 +                                   OVR_DEBUG_SELECT(NULL, CRITICAL_SECTION_NO_DEBUG_INFO));
   47.58 +    #else
   47.59 +        ::InitializeCriticalSectionAndSpinCount(&cs, (DWORD)spinCount); // This is available with WindowsXP+.
   47.60 +    #endif
   47.61 +}
   47.62 +
   47.63 +
   47.64 +Lock::~Lock()
   47.65 +{
   47.66 +    DeleteCriticalSection(&cs);
   47.67 +}
   47.68 +
   47.69 +
   47.70 +#endif
   47.71 +
   47.72 +
   47.73 +//-------------------------------------------------------------------------------------
   47.74 +// ***** SharedLock
   47.75 +
   47.76 +// This is a general purpose globally shared Lock implementation that should probably be
   47.77 +// moved to Kernel.
   47.78 +// May in theory busy spin-wait if we hit contention on first lock creation,
   47.79 +// but this shouldn't matter in practice since Lock* should be cached.
   47.80 +
   47.81 +
   47.82 +enum { LockInitMarker = 0xFFFFFFFF };
   47.83 +
   47.84 +Lock* SharedLock::GetLockAddRef()
   47.85 +{
   47.86 +    int oldUseCount;
   47.87 +
   47.88 +    do {
   47.89 +        oldUseCount = UseCount;
   47.90 +        if (oldUseCount == (int)LockInitMarker)
   47.91 +            continue;
   47.92 +
   47.93 +        if (oldUseCount == 0)
   47.94 +        {
   47.95 +            // Initialize marker
   47.96 +            if (AtomicOps<int>::CompareAndSet_Sync(&UseCount, 0, LockInitMarker))
   47.97 +            {
   47.98 +                Construct<Lock>(Buffer);
   47.99 +                do { }
  47.100 +                while (!AtomicOps<int>::CompareAndSet_Sync(&UseCount, LockInitMarker, 1));
  47.101 +                return toLock();
  47.102 +            }
  47.103 +            continue;
  47.104 +        }
  47.105 +
  47.106 +    } while (!AtomicOps<int>::CompareAndSet_NoSync(&UseCount, oldUseCount, oldUseCount + 1));
  47.107 +
  47.108 +    return toLock();
  47.109 +}
  47.110 +
  47.111 +void SharedLock::ReleaseLock(Lock* plock)
  47.112 +{
  47.113 +    OVR_UNUSED(plock);
  47.114 +    OVR_ASSERT(plock == toLock());
  47.115 +
  47.116 +    int oldUseCount;
  47.117 +
  47.118 +    do {
  47.119 +        oldUseCount = UseCount;
  47.120 +        OVR_ASSERT(oldUseCount != (int)LockInitMarker);
  47.121 +
  47.122 +        if (oldUseCount == 1)
  47.123 +        {
  47.124 +            // Initialize marker
  47.125 +            if (AtomicOps<int>::CompareAndSet_Sync(&UseCount, 1, LockInitMarker))
  47.126 +            {
  47.127 +                Destruct<Lock>(toLock());
  47.128 +
  47.129 +                do { }
  47.130 +                while (!AtomicOps<int>::CompareAndSet_Sync(&UseCount, LockInitMarker, 0));
  47.131 +
  47.132 +                return;
  47.133 +            }
  47.134 +            continue;
  47.135 +        }
  47.136 +
  47.137 +    } while (!AtomicOps<int>::CompareAndSet_NoSync(&UseCount, oldUseCount, oldUseCount - 1));
  47.138 +}
  47.139 +
  47.140 +} // OVR
  47.141 +
  47.142 +#endif // OVR_ENABLE_THREADS
    48.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    48.2 +++ b/LibOVR/Src/Kernel/OVR_Atomic.h	Wed Jan 14 06:51:16 2015 +0200
    48.3 @@ -0,0 +1,915 @@
    48.4 +/************************************************************************************
    48.5 +
    48.6 +PublicHeader:   OVR_Kernel.h
    48.7 +Filename    :   OVR_Atomic.h
    48.8 +Content     :   Contains atomic operations and inline fastest locking
    48.9 +                functionality. Will contain #ifdefs for OS efficiency.
   48.10 +                Have non-thread-safe implementaion if not available.
   48.11 +Created     :   September 19, 2012
   48.12 +Notes       : 
   48.13 +
   48.14 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   48.15 +
   48.16 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
   48.17 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
   48.18 +which is provided at the time of installation or download, or which 
   48.19 +otherwise accompanies this software in either electronic or hard copy form.
   48.20 +
   48.21 +You may obtain a copy of the License at
   48.22 +
   48.23 +http://www.oculusvr.com/licenses/LICENSE-3.2 
   48.24 +
   48.25 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
   48.26 +distributed under the License is distributed on an "AS IS" BASIS,
   48.27 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   48.28 +See the License for the specific language governing permissions and
   48.29 +limitations under the License.
   48.30 +
   48.31 +************************************************************************************/
   48.32 +
   48.33 +#ifndef OVR_Atomic_h
   48.34 +#define OVR_Atomic_h
   48.35 +
   48.36 +#include "OVR_Types.h"
   48.37 +
   48.38 +// Include System thread functionality.
   48.39 +#if defined(OVR_OS_MS) && !defined(OVR_OS_MS_MOBILE)
   48.40 +#ifndef WIN32_LEAN_AND_MEAN
   48.41 +#define WIN32_LEAN_AND_MEAN
   48.42 +#endif
   48.43 +#include <Windows.h>
   48.44 +#else
   48.45 +#include <pthread.h>
   48.46 +#endif
   48.47 +
   48.48 +#ifdef OVR_CC_MSVC
   48.49 +#include <intrin.h>
   48.50 +#pragma intrinsic(_ReadBarrier, _WriteBarrier, _ReadWriteBarrier)
   48.51 +#endif
   48.52 +
   48.53 +namespace OVR {
   48.54 +
   48.55 +
   48.56 +// ****** Declared classes
   48.57 +
   48.58 +// If there is NO thread support we implement AtomicOps and
   48.59 +// Lock objects as no-ops. The other classes are not defined.
   48.60 +template<class C> class AtomicOps;
   48.61 +template<class T> class AtomicInt;
   48.62 +template<class T> class AtomicPtr;
   48.63 +
   48.64 +class Lock;
   48.65 +
   48.66 +
   48.67 +//-----------------------------------------------------------------------------------
   48.68 +// ***** AtomicOps
   48.69 +
   48.70 +// Atomic operations are provided by the AtomicOps templates class,
   48.71 +// implemented through system-specific AtomicOpsRaw specializations.
   48.72 +// It provides several fundamental operations such as Exchange, ExchangeAdd
   48.73 +// CompareAndSet, and Store_Release. Each function includes several memory
   48.74 +// synchronization versions, important for multiprocessing CPUs with weak
   48.75 +// memory consistency. The following memory fencing strategies are supported:
   48.76 +//
   48.77 +//  - NoSync.  No memory synchronization is done for atomic op.
   48.78 +//  - Release. All other memory writes are completed before atomic op
   48.79 +//             writes its results.
   48.80 +//  - Acquire. Further memory reads are forced to wait until atomic op
   48.81 +//             executes, guaranteeing that the right values will be seen.
   48.82 +//  - Sync.    A combination of Release and Acquire.
   48.83 +
   48.84 +
   48.85 +// *** AtomicOpsRaw
   48.86 +
   48.87 +// AtomicOpsRaw is a specialized template that provides atomic operations 
   48.88 +// used by AtomicOps. This class has two fundamental qualities: (1) it
   48.89 +// defines a type T of correct size, and (2) provides operations that work
   48.90 +// atomically, such as Exchange_Sync and CompareAndSet_Release.
   48.91 +
   48.92 +// AtomicOpsRawBase class contains shared constants/classes for AtomicOpsRaw.
   48.93 +// The primary thing is does is define sync class objects, whose destructor and
   48.94 +// constructor provide places to insert appropriate synchronization calls, on 
   48.95 +// systems where such calls are necessary. So far, the breakdown is as follows:
   48.96 +// 
   48.97 +//  - X86 systems don't need custom syncs, since their exchange/atomic
   48.98 +//    instructions are implicitly synchronized.
   48.99 +//  - PowerPC requires lwsync/isync instructions that can use this mechanism.
  48.100 +//  - If some other systems require a mechanism where syncing type is associated
  48.101 +//    with a particular instruction, the default implementation (which implements
  48.102 +//    all Sync, Acquire, and Release modes in terms of NoSync and fence) may not
  48.103 +//    work. Ii that case it will need to be #ifdef-ed conditionally.
  48.104 +
  48.105 +struct AtomicOpsRawBase
  48.106 +{
  48.107 +#if !defined(OVR_ENABLE_THREADS) || defined(OVR_CPU_X86) || defined(OVR_CPU_X86_64)
  48.108 +    // Need to have empty constructor to avoid class 'unused' variable warning.
  48.109 +    struct FullSync { inline FullSync() { } };
  48.110 +    struct AcquireSync { inline AcquireSync() { } };
  48.111 +    struct ReleaseSync { inline ReleaseSync() { } };
  48.112 +
  48.113 +#elif defined(OVR_CPU_PPC64) || defined(OVR_CPU_PPC)
  48.114 +    struct FullSync { inline FullSync() { asm volatile("sync\n"); } ~FullSync() { asm volatile("isync\n"); } };
  48.115 +    struct AcquireSync { inline AcquireSync() { } ~AcquireSync() { asm volatile("isync\n"); } };
  48.116 +    struct ReleaseSync { inline ReleaseSync() { asm volatile("sync\n"); } };
  48.117 +
  48.118 +#elif defined(OVR_CPU_MIPS)
  48.119 +    struct FullSync { inline FullSync() { asm volatile("sync\n"); } ~FullSync() { asm volatile("sync\n"); } };
  48.120 +    struct AcquireSync { inline AcquireSync() { } ~AcquireSync() { asm volatile("sync\n"); } };
  48.121 +    struct ReleaseSync { inline ReleaseSync() { asm volatile("sync\n"); } };
  48.122 +
  48.123 +#elif defined(OVR_CPU_ARM) // Includes Android and iOS.
  48.124 +    struct FullSync { inline FullSync() { asm volatile("dmb\n"); } ~FullSync() { asm volatile("dmb\n"); } };
  48.125 +    struct AcquireSync { inline AcquireSync() { } ~AcquireSync() { asm volatile("dmb\n"); } };
  48.126 +    struct ReleaseSync { inline ReleaseSync() { asm volatile("dmb\n"); } };
  48.127 +
  48.128 +#elif defined(OVR_CC_GNU) && (__GNUC__ >= 4)
  48.129 +    // __sync functions are already full sync
  48.130 +    struct FullSync { inline FullSync() { } };
  48.131 +    struct AcquireSync { inline AcquireSync() { } };
  48.132 +    struct ReleaseSync { inline ReleaseSync() { } };
  48.133 +#endif
  48.134 +};
  48.135 +
  48.136 +
  48.137 +// 4-Byte raw data atomic op implementation class.
  48.138 +struct AtomicOpsRaw_4ByteImpl : public AtomicOpsRawBase
  48.139 +{
  48.140 +#if !defined(OVR_ENABLE_THREADS)
  48.141 +
  48.142 +    // Provide a type for no-thread-support cases. Used by AtomicOpsRaw_DefImpl.
  48.143 +    typedef uint32_t T;   
  48.144 +
  48.145 +    // *** Thread - Safe Atomic Versions.
  48.146 +
  48.147 +#elif defined(OVR_OS_MS) 
  48.148 +
  48.149 +    // Use special defined for VC6, where volatile is not used and
  48.150 +    // InterlockedCompareExchange is declared incorrectly.
  48.151 +    typedef LONG T;      
  48.152 +#if defined(OVR_CC_MSVC) && (OVR_CC_MSVC < 1300)
  48.153 +    typedef T* InterlockTPtr;
  48.154 +    typedef LPVOID ET;
  48.155 +    typedef ET* InterlockETPtr;
  48.156 +#else
  48.157 +    typedef volatile T* InterlockTPtr;
  48.158 +    typedef T ET;
  48.159 +    typedef InterlockTPtr InterlockETPtr;
  48.160 +#endif
  48.161 +    inline static T     Exchange_NoSync(volatile T* p, T val)            { return InterlockedExchange((InterlockTPtr)p, val); }
  48.162 +    inline static T     ExchangeAdd_NoSync(volatile T* p, T val)         { return InterlockedExchangeAdd((InterlockTPtr)p, val); }
  48.163 +    inline static bool  CompareAndSet_NoSync(volatile T* p, T c, T val)  { return InterlockedCompareExchange((InterlockETPtr)p, (ET)val, (ET)c) == (ET)c; }
  48.164 +
  48.165 +#elif defined(OVR_CPU_PPC64) || defined(OVR_CPU_PPC)
  48.166 +    typedef uint32_t T;
  48.167 +    static inline uint32_t Exchange_NoSync(volatile uint32_t *i, uint32_t j)
  48.168 +    {
  48.169 +        uint32_t ret;
  48.170 +
  48.171 +        asm volatile("1:\n\t"
  48.172 +                     "lwarx  %[r],0,%[i]\n\t"
  48.173 +                     "stwcx. %[j],0,%[i]\n\t"
  48.174 +                     "bne-   1b\n"
  48.175 +                     : "+m" (*i), [r] "=&b" (ret) : [i] "b" (i), [j] "b" (j) : "cc", "memory");
  48.176 +
  48.177 +        return ret;
  48.178 +    }
  48.179 +
  48.180 +    static inline uint32_t ExchangeAdd_NoSync(volatile uint32_t *i, uint32_t j)
  48.181 +    {
  48.182 +        uint32_t dummy, ret;
  48.183 +
  48.184 +        asm volatile("1:\n\t"
  48.185 +                     "lwarx  %[r],0,%[i]\n\t"
  48.186 +                     "add    %[o],%[r],%[j]\n\t"
  48.187 +                     "stwcx. %[o],0,%[i]\n\t"
  48.188 +                     "bne-   1b\n"
  48.189 +                     : "+m" (*i), [r] "=&b" (ret), [o] "=&r" (dummy) : [i] "b" (i), [j] "b" (j) : "cc", "memory");
  48.190 +
  48.191 +        return ret;
  48.192 +    }
  48.193 +
  48.194 +    static inline bool     CompareAndSet_NoSync(volatile uint32_t *i, uint32_t c, uint32_t value)
  48.195 +    {
  48.196 +        uint32_t ret;
  48.197 +
  48.198 +        asm volatile("1:\n\t"
  48.199 +                     "lwarx  %[r],0,%[i]\n\t"
  48.200 +                     "cmpw   0,%[r],%[cmp]\n\t"
  48.201 +                     "mfcr   %[r]\n\t"
  48.202 +                     "bne-   2f\n\t"
  48.203 +                     "stwcx. %[val],0,%[i]\n\t"
  48.204 +                     "bne-   1b\n\t"
  48.205 +                     "2:\n"
  48.206 +                     : "+m" (*i), [r] "=&b" (ret) : [i] "b" (i), [cmp] "b" (c), [val] "b" (value) : "cc", "memory");
  48.207 +
  48.208 +        return (ret & 0x20000000) ? 1 : 0;
  48.209 +    }
  48.210 +
  48.211 +#elif defined(OVR_CPU_MIPS)
  48.212 +    typedef uint32_t T;
  48.213 +
  48.214 +    static inline uint32_t Exchange_NoSync(volatile uint32_t *i, uint32_t j)
  48.215 +    {
  48.216 +        uint32_t ret;
  48.217 +
  48.218 +        asm volatile("1:\n\t"
  48.219 +                     "ll     %[r],0(%[i])\n\t"
  48.220 +                     "sc     %[j],0(%[i])\n\t"
  48.221 +                     "beq    %[j],$0,1b\n\t"
  48.222 +                     "nop    \n"
  48.223 +                     : "+m" (*i), [r] "=&d" (ret) : [i] "d" (i), [j] "d" (j) : "cc", "memory");
  48.224 +
  48.225 +        return ret;
  48.226 +    }
  48.227 +
  48.228 +    static inline uint32_t ExchangeAdd_NoSync(volatile uint32_t *i, uint32_t j)
  48.229 +    {
  48.230 +        uint32_t ret;
  48.231 +
  48.232 +        asm volatile("1:\n\t"
  48.233 +                     "ll     %[r],0(%[i])\n\t"
  48.234 +                     "addu   %[j],%[r],%[j]\n\t"
  48.235 +                     "sc     %[j],0(%[i])\n\t"
  48.236 +                     "beq    %[j],$0,1b\n\t"
  48.237 +                     "nop    \n"
  48.238 +                     : "+m" (*i), [r] "=&d" (ret) : [i] "d" (i), [j] "d" (j) : "cc", "memory");
  48.239 +
  48.240 +        return ret;
  48.241 +    }
  48.242 +
  48.243 +    static inline bool     CompareAndSet_NoSync(volatile uint32_t *i, uint32_t c, uint32_t value)
  48.244 +    {
  48.245 +        uint32_t ret, dummy;
  48.246 +
  48.247 +        asm volatile("1:\n\t"
  48.248 +                     "move   %[r],$0\n\t"
  48.249 +                     "ll     %[o],0(%[i])\n\t"
  48.250 +                     "bne    %[o],%[c],2f\n\t"
  48.251 +                     "move   %[r],%[v]\n\t"
  48.252 +                     "sc     %[r],0(%[i])\n\t"
  48.253 +                     "beq    %[r],$0,1b\n\t"
  48.254 +                     "nop    \n\t"
  48.255 +                     "2:\n"
  48.256 +                     : "+m" (*i),[r] "=&d" (ret), [o] "=&d" (dummy) : [i] "d" (i), [c] "d" (c), [v] "d" (value)
  48.257 +                     : "cc", "memory");
  48.258 +
  48.259 +        return ret;
  48.260 +    }
  48.261 +
  48.262 +#elif defined(OVR_CPU_ARM) && defined(OVR_CC_ARM)
  48.263 +    typedef uint32_t T;
  48.264 +
  48.265 +    static inline uint32_t Exchange_NoSync(volatile uint32_t *i, uint32_t j)
  48.266 +    {
  48.267 +        for(;;)
  48.268 +        {
  48.269 +            T r = __ldrex(i);
  48.270 +            if (__strex(j, i) == 0)
  48.271 +                return r;
  48.272 +        }
  48.273 +    }
  48.274 +    static inline uint32_t ExchangeAdd_NoSync(volatile uint32_t *i, uint32_t j)
  48.275 +    {
  48.276 +        for(;;)
  48.277 +        {
  48.278 +            T r = __ldrex(i);
  48.279 +            if (__strex(r + j, i) == 0)
  48.280 +                return r;
  48.281 +        }
  48.282 +    }
  48.283 +
  48.284 +    static inline bool     CompareAndSet_NoSync(volatile uint32_t *i, uint32_t c, uint32_t value)
  48.285 +    {
  48.286 +        for(;;)
  48.287 +        {
  48.288 +            T r = __ldrex(i);
  48.289 +            if (r != c)
  48.290 +                return 0;
  48.291 +            if (__strex(value, i) == 0)
  48.292 +                return 1;
  48.293 +        }
  48.294 +    }
  48.295 +
  48.296 +#elif defined(OVR_CPU_ARM)
  48.297 +    typedef uint32_t T;
  48.298 +
  48.299 +    static inline uint32_t Exchange_NoSync(volatile uint32_t *i, uint32_t j)
  48.300 +    {
  48.301 +        uint32_t ret, dummy;
  48.302 +
  48.303 +        asm volatile("1:\n\t"
  48.304 +            "ldrex  %[r],[%[i]]\n\t"
  48.305 +            "strex  %[t],%[j],[%[i]]\n\t"
  48.306 +            "cmp    %[t],#0\n\t"
  48.307 +            "bne    1b\n\t"
  48.308 +            : "+m" (*i), [r] "=&r" (ret), [t] "=&r" (dummy) : [i] "r" (i), [j] "r" (j) : "cc", "memory");
  48.309 +
  48.310 +        return ret;
  48.311 +    }
  48.312 +
  48.313 +    static inline uint32_t ExchangeAdd_NoSync(volatile uint32_t *i, uint32_t j)
  48.314 +    {
  48.315 +        uint32_t ret, dummy, test;
  48.316 +
  48.317 +        asm volatile("1:\n\t"
  48.318 +            "ldrex  %[r],[%[i]]\n\t"
  48.319 +            "add    %[o],%[r],%[j]\n\t"
  48.320 +            "strex  %[t],%[o],[%[i]]\n\t"
  48.321 +            "cmp    %[t],#0\n\t"
  48.322 +            "bne    1b\n\t"
  48.323 +            : "+m" (*i), [r] "=&r" (ret), [o] "=&r" (dummy), [t] "=&r" (test)  : [i] "r" (i), [j] "r" (j) : "cc", "memory");
  48.324 +
  48.325 +        return ret;
  48.326 +    }
  48.327 +
  48.328 +    static inline bool     CompareAndSet_NoSync(volatile uint32_t *i, uint32_t c, uint32_t value)
  48.329 +    {
  48.330 +        uint32_t ret = 1, dummy, test;
  48.331 +
  48.332 +        asm volatile("1:\n\t"
  48.333 +            "ldrex  %[o],[%[i]]\n\t"
  48.334 +            "cmp    %[o],%[c]\n\t"
  48.335 +            "bne    2f\n\t"
  48.336 +            "strex  %[r],%[v],[%[i]]\n\t"
  48.337 +            "cmp    %[r],#0\n\t"
  48.338 +            "bne    1b\n\t"
  48.339 +            "2:\n"
  48.340 +            : "+m" (*i),[r] "=&r" (ret), [o] "=&r" (dummy), [t] "=&r" (test) : [i] "r" (i), [c] "r" (c), [v] "r" (value)
  48.341 +            : "cc", "memory");
  48.342 +
  48.343 +        return !ret;
  48.344 +    }
  48.345 +
  48.346 +#elif defined(OVR_CPU_X86)
  48.347 +    typedef uint32_t T;
  48.348 +
  48.349 +    static inline uint32_t Exchange_NoSync(volatile uint32_t *i, uint32_t j)
  48.350 +    {
  48.351 +        asm volatile("xchgl %1,%[i]\n"
  48.352 +                     : "+m" (*i), "=q" (j) : [i] "m" (*i), "1" (j) : "cc", "memory");
  48.353 +
  48.354 +        return j;
  48.355 +    }
  48.356 +
  48.357 +    static inline uint32_t ExchangeAdd_NoSync(volatile uint32_t *i, uint32_t j)
  48.358 +    {
  48.359 +        asm volatile("lock; xaddl %1,%[i]\n"
  48.360 +                     : "+m" (*i), "+q" (j) : [i] "m" (*i) : "cc", "memory");
  48.361 +
  48.362 +        return j;
  48.363 +    }
  48.364 +
  48.365 +    static inline bool     CompareAndSet_NoSync(volatile uint32_t *i, uint32_t c, uint32_t value)
  48.366 +    {
  48.367 +        uint32_t ret;
  48.368 +
  48.369 +        asm volatile("lock; cmpxchgl %[v],%[i]\n"
  48.370 +                     : "+m" (*i), "=a" (ret) : [i] "m" (*i), "1" (c), [v] "q" (value) : "cc", "memory");
  48.371 +
  48.372 +        return (ret == c);
  48.373 +    }
  48.374 +
  48.375 +#elif defined(OVR_CC_GNU) && (__GNUC__ >= 4 && __GNUC_MINOR__ >= 1)
  48.376 +
  48.377 +    typedef uint32_t T;
  48.378 +
  48.379 +    static inline T   Exchange_NoSync(volatile T *i, T j)
  48.380 +    {
  48.381 +        T v;
  48.382 +        do {
  48.383 +            v = *i;
  48.384 +        } while (!__sync_bool_compare_and_swap(i, v, j));
  48.385 +        return v;
  48.386 +    }
  48.387 +
  48.388 +    static inline T   ExchangeAdd_NoSync(volatile T *i, T j)
  48.389 +    {
  48.390 +        return __sync_fetch_and_add(i, j);
  48.391 +    }
  48.392 +
  48.393 +    static inline bool     CompareAndSet_NoSync(volatile T *i, T c, T value)
  48.394 +    {
  48.395 +        return __sync_bool_compare_and_swap(i, c, value);
  48.396 +    }
  48.397 +
  48.398 +#endif // OS
  48.399 +};
  48.400 +
  48.401 +
  48.402 +// 8-Byte raw data data atomic op implementation class.
  48.403 +// Currently implementation is provided only on systems with 64-bit pointers.
  48.404 +struct AtomicOpsRaw_8ByteImpl : public AtomicOpsRawBase
  48.405 +{    
  48.406 +#if !defined(OVR_64BIT_POINTERS) || !defined(OVR_ENABLE_THREADS)
  48.407 +
  48.408 +    // Provide a type for no-thread-support cases. Used by AtomicOpsRaw_DefImpl.
  48.409 +    typedef uint64_t T;
  48.410 +
  48.411 +    // *** Thread - Safe OS specific versions.
  48.412 +#elif defined(OVR_OS_MS)
  48.413 +
  48.414 +    // This is only for 64-bit systems.
  48.415 +    typedef LONG64      T;
  48.416 +    typedef volatile T* InterlockTPtr;    
  48.417 +    inline static T     Exchange_NoSync(volatile T* p, T val)            { return InterlockedExchange64((InterlockTPtr)p, val); }
  48.418 +    inline static T     ExchangeAdd_NoSync(volatile T* p, T val)         { return InterlockedExchangeAdd64((InterlockTPtr)p, val); }
  48.419 +    inline static bool  CompareAndSet_NoSync(volatile T* p, T c, T val)  { return InterlockedCompareExchange64((InterlockTPtr)p, val, c) == c; }
  48.420 +
  48.421 +#elif defined(OVR_CPU_PPC64)
  48.422 + 
  48.423 +    typedef uint64_t T;
  48.424 +
  48.425 +    static inline uint64_t Exchange_NoSync(volatile uint64_t *i, uint64_t j)
  48.426 +    {
  48.427 +        uint64_t dummy, ret;
  48.428 +
  48.429 +        asm volatile("1:\n\t"
  48.430 +                     "ldarx  %[r],0,%[i]\n\t"
  48.431 +                     "mr     %[o],%[j]\n\t"
  48.432 +                     "stdcx. %[o],0,%[i]\n\t"
  48.433 +                     "bne-   1b\n"
  48.434 +                     : "+m" (*i), [r] "=&b" (ret), [o] "=&r" (dummy) : [i] "b" (i), [j] "b" (j) : "cc");
  48.435 +
  48.436 +        return ret;
  48.437 +    }
  48.438 +
  48.439 +    static inline uint64_t ExchangeAdd_NoSync(volatile uint64_t *i, uint64_t j)
  48.440 +    {
  48.441 +        uint64_t dummy, ret;
  48.442 +
  48.443 +        asm volatile("1:\n\t"
  48.444 +                     "ldarx  %[r],0,%[i]\n\t"
  48.445 +                     "add    %[o],%[r],%[j]\n\t"
  48.446 +                     "stdcx. %[o],0,%[i]\n\t"
  48.447 +                     "bne-   1b\n"
  48.448 +                     : "+m" (*i), [r] "=&b" (ret), [o] "=&r" (dummy) : [i] "b" (i), [j] "b" (j) : "cc");
  48.449 +
  48.450 +        return ret;
  48.451 +    }
  48.452 +
  48.453 +    static inline bool     CompareAndSet_NoSync(volatile uint64_t *i, uint64_t c, uint64_t value)
  48.454 +    {
  48.455 +        uint64_t ret, dummy;
  48.456 +
  48.457 +        asm volatile("1:\n\t"
  48.458 +                     "ldarx  %[r],0,%[i]\n\t"
  48.459 +                     "cmpw   0,%[r],%[cmp]\n\t"
  48.460 +                     "mfcr   %[r]\n\t"
  48.461 +                     "bne-   2f\n\t"
  48.462 +                     "stdcx. %[val],0,%[i]\n\t"
  48.463 +                     "bne-   1b\n\t"
  48.464 +                     "2:\n"
  48.465 +                     : "+m" (*i), [r] "=&b" (ret), [o] "=&r" (dummy) : [i] "b" (i), [cmp] "b" (c), [val] "b" (value) : "cc");
  48.466 +
  48.467 +        return (ret & 0x20000000) ? 1 : 0;
  48.468 +    }
  48.469 +
  48.470 +#elif defined(OVR_CC_GNU) && (__GNUC__ >= 4 && __GNUC_MINOR__ >= 1)
  48.471 +
  48.472 +    typedef uint64_t T;
  48.473 +
  48.474 +    static inline T   Exchange_NoSync(volatile T *i, T j)
  48.475 +    {
  48.476 +        T v;
  48.477 +        do {
  48.478 +            v = *i;
  48.479 +        } while (!__sync_bool_compare_and_swap(i, v, j));
  48.480 +        return v;
  48.481 +    }
  48.482 +
  48.483 +    static inline T   ExchangeAdd_NoSync(volatile T *i, T j)
  48.484 +    {
  48.485 +        return __sync_fetch_and_add(i, j);
  48.486 +    }
  48.487 +
  48.488 +    static inline bool     CompareAndSet_NoSync(volatile T *i, T c, T value)
  48.489 +    {
  48.490 +        return __sync_bool_compare_and_swap(i, c, value);
  48.491 +    }
  48.492 +
  48.493 +#endif // OS
  48.494 +};
  48.495 +
  48.496 +
  48.497 +// Default implementation for AtomicOpsRaw; provides implementation of mem-fenced
  48.498 +// atomic operations where fencing is done with a sync object wrapped around a NoSync
  48.499 +// operation implemented in the base class. If such implementation is not possible
  48.500 +// on a given platform, #ifdefs can be used to disable it and then op functions can be
  48.501 +// implemented individually in the appropriate AtomicOpsRaw<size> class.
  48.502 +
  48.503 +template<class O>
  48.504 +struct AtomicOpsRaw_DefImpl : public O
  48.505 +{
  48.506 +    typedef typename O::T O_T;
  48.507 +    typedef typename O::FullSync    O_FullSync;
  48.508 +    typedef typename O::AcquireSync O_AcquireSync;
  48.509 +    typedef typename O::ReleaseSync O_ReleaseSync;
  48.510 +
  48.511 +    // If there is no thread support, provide the default implementation. In this case,
  48.512 +    // the base class (0) must still provide the T declaration.
  48.513 +#ifndef OVR_ENABLE_THREADS
  48.514 +
  48.515 +    // Atomic exchange of val with argument. Returns old val.
  48.516 +    inline static O_T   Exchange_NoSync(volatile O_T* p, O_T val)           { O_T old = *p; *p = val; return old; }
  48.517 +    // Adds a new val to argument; returns its old val.
  48.518 +    inline static O_T   ExchangeAdd_NoSync(volatile O_T* p, O_T val)        { O_T old = *p; *p += val; return old; }
  48.519 +    // Compares the argument data with 'c' val.
  48.520 +    // If succeeded, stores val int '*p' and returns true; otherwise returns false.
  48.521 +    inline static bool  CompareAndSet_NoSync(volatile O_T* p, O_T c, O_T val) { if (*p==c) { *p = val; return 1; } return 0; }
  48.522 +
  48.523 +#endif
  48.524 +
  48.525 +    // If NoSync wrapped implementation may not be possible, it this block should be
  48.526 +    //  replaced with per-function implementation in O.
  48.527 +    // "AtomicOpsRaw_DefImpl<O>::" prefix in calls below.
  48.528 +    inline static O_T   Exchange_Sync(volatile O_T* p, O_T val)                { O_FullSync    sync; OVR_UNUSED(sync); return AtomicOpsRaw_DefImpl<O>::Exchange_NoSync(p, val); }
  48.529 +    inline static O_T   Exchange_Release(volatile O_T* p, O_T val)             { O_ReleaseSync sync; OVR_UNUSED(sync); return AtomicOpsRaw_DefImpl<O>::Exchange_NoSync(p, val); }
  48.530 +    inline static O_T   Exchange_Acquire(volatile O_T* p, O_T val)             { O_AcquireSync sync; OVR_UNUSED(sync); return AtomicOpsRaw_DefImpl<O>::Exchange_NoSync(p, val); }  
  48.531 +    inline static O_T   ExchangeAdd_Sync(volatile O_T* p, O_T val)             { O_FullSync    sync; OVR_UNUSED(sync); return AtomicOpsRaw_DefImpl<O>::ExchangeAdd_NoSync(p, val); }
  48.532 +    inline static O_T   ExchangeAdd_Release(volatile O_T* p, O_T val)          { O_ReleaseSync sync; OVR_UNUSED(sync); return AtomicOpsRaw_DefImpl<O>::ExchangeAdd_NoSync(p, val); }
  48.533 +    inline static O_T   ExchangeAdd_Acquire(volatile O_T* p, O_T val)          { O_AcquireSync sync; OVR_UNUSED(sync); return AtomicOpsRaw_DefImpl<O>::ExchangeAdd_NoSync(p, val); }
  48.534 +    inline static bool  CompareAndSet_Sync(volatile O_T* p, O_T c, O_T val)    { O_FullSync    sync; OVR_UNUSED(sync); return AtomicOpsRaw_DefImpl<O>::CompareAndSet_NoSync(p,c,val); }
  48.535 +    inline static bool  CompareAndSet_Release(volatile O_T* p, O_T c, O_T val) { O_ReleaseSync sync; OVR_UNUSED(sync); return AtomicOpsRaw_DefImpl<O>::CompareAndSet_NoSync(p,c,val); }
  48.536 +    inline static bool  CompareAndSet_Acquire(volatile O_T* p, O_T c, O_T val) { O_AcquireSync sync; OVR_UNUSED(sync); return AtomicOpsRaw_DefImpl<O>::CompareAndSet_NoSync(p,c,val); }
  48.537 +
  48.538 +    // Loads and stores with memory fence. These have only the relevant versions.
  48.539 +#ifdef OVR_CPU_X86
  48.540 +    // On X86, Store_Release is implemented as exchange. Note that we can also
  48.541 +    // consider 'sfence' in the future, although it is not as compatible with older CPUs.
  48.542 +    inline static void  Store_Release(volatile O_T* p, O_T val)  { Exchange_Release(p, val); }
  48.543 +#else
  48.544 +    inline static void  Store_Release(volatile O_T* p, O_T val)  { O_ReleaseSync sync; OVR_UNUSED(sync); *p = val; }
  48.545 +#endif
  48.546 +    inline static O_T   Load_Acquire(const volatile O_T* p)
  48.547 +    {
  48.548 +        O_AcquireSync sync;
  48.549 +        OVR_UNUSED(sync);
  48.550 +
  48.551 +#if defined(OVR_CC_MSVC)
  48.552 +        _ReadBarrier(); // Compiler fence and load barrier
  48.553 +#elif defined(OVR_CC_INTEL)
  48.554 +        __memory_barrier(); // Compiler fence
  48.555 +#else
  48.556 +        // GCC-compatible:
  48.557 +        asm volatile ("" : : : "memory"); // Compiler fence
  48.558 +#endif
  48.559 +
  48.560 +        return *p;
  48.561 +    }
  48.562 +};
  48.563 +
  48.564 +
  48.565 +template<int size>
  48.566 +struct AtomicOpsRaw : public AtomicOpsRawBase { };
  48.567 +
  48.568 +template<>
  48.569 +struct AtomicOpsRaw<4> : public AtomicOpsRaw_DefImpl<AtomicOpsRaw_4ByteImpl>
  48.570 +{   
  48.571 +    // Ensure that assigned type size is correct.
  48.572 +    AtomicOpsRaw()
  48.573 +    { OVR_COMPILER_ASSERT(sizeof(AtomicOpsRaw_DefImpl<AtomicOpsRaw_4ByteImpl>::T) == 4); }
  48.574 +};
  48.575 +template<>
  48.576 +struct AtomicOpsRaw<8> : public AtomicOpsRaw_DefImpl<AtomicOpsRaw_8ByteImpl>
  48.577 +{
  48.578 +    AtomicOpsRaw()
  48.579 +    { OVR_COMPILER_ASSERT(sizeof(AtomicOpsRaw_DefImpl<AtomicOpsRaw_8ByteImpl>::T) == 8); }
  48.580 +};
  48.581 +
  48.582 +
  48.583 +// *** AtomicOps - implementation of atomic Ops for specified class
  48.584 +
  48.585 +// Implements atomic ops on a class, provided that the object is either
  48.586 +// 4 or 8 bytes in size (depending on the AtomicOpsRaw specializations
  48.587 +// available). Relies on AtomicOpsRaw for much of implementation.
  48.588 +
  48.589 +template<class C>
  48.590 +class AtomicOps
  48.591 +{
  48.592 +    typedef AtomicOpsRaw<sizeof(C)>       Ops;
  48.593 +    typedef typename Ops::T               T;
  48.594 +    typedef volatile typename Ops::T*     PT;
  48.595 +    // We cast through unions to (1) avoid pointer size compiler warnings
  48.596 +    // and (2) ensure that there are no problems with strict pointer aliasing.
  48.597 +    union C2T_union { C c; T t; };
  48.598 +
  48.599 +public:
  48.600 +    // General purpose implementation for standard syncs.    
  48.601 +    inline static C     Exchange_Sync(volatile C* p, C val)             { C2T_union u; u.c = val; u.t = Ops::Exchange_Sync((PT)p, u.t); return u.c; }
  48.602 +    inline static C     Exchange_Release(volatile C* p, C val)          { C2T_union u; u.c = val; u.t = Ops::Exchange_Release((PT)p, u.t); return u.c; }
  48.603 +    inline static C     Exchange_Acquire(volatile C* p, C val)          { C2T_union u; u.c = val; u.t = Ops::Exchange_Acquire((PT)p, u.t); return u.c; }
  48.604 +    inline static C     Exchange_NoSync(volatile C* p, C val)           { C2T_union u; u.c = val; u.t = Ops::Exchange_NoSync((PT)p, u.t); return u.c; }
  48.605 +    inline static C     ExchangeAdd_Sync(volatile C* p, C val)          { C2T_union u; u.c = val; u.t = Ops::ExchangeAdd_Sync((PT)p, u.t); return u.c; }
  48.606 +    inline static C     ExchangeAdd_Release(volatile C* p, C val)       { C2T_union u; u.c = val; u.t = Ops::ExchangeAdd_Release((PT)p, u.t); return u.c; }
  48.607 +    inline static C     ExchangeAdd_Acquire(volatile C* p, C val)       { C2T_union u; u.c = val; u.t = Ops::ExchangeAdd_Acquire((PT)p, u.t); return u.c; }
  48.608 +    inline static C     ExchangeAdd_NoSync(volatile C* p, C val)        { C2T_union u; u.c = val; u.t = Ops::ExchangeAdd_NoSync((PT)p, u.t); return u.c; }
  48.609 +    inline static bool  CompareAndSet_Sync(volatile C* p, C c, C val)   { C2T_union u,cu; u.c = val; cu.c = c; return Ops::CompareAndSet_Sync((PT)p, cu.t, u.t); }
  48.610 +    inline static bool  CompareAndSet_Release(volatile C* p, C c, C val){ C2T_union u,cu; u.c = val; cu.c = c; return Ops::CompareAndSet_Release((PT)p, cu.t, u.t); }
  48.611 +    inline static bool  CompareAndSet_Acquire(volatile C* p, C c, C val){ C2T_union u,cu; u.c = val; cu.c = c; return Ops::CompareAndSet_Acquire((PT)p, cu.t, u.t); }
  48.612 +    inline static bool  CompareAndSet_NoSync(volatile C* p, C c, C val) { C2T_union u,cu; u.c = val; cu.c = c; return Ops::CompareAndSet_NoSync((PT)p, cu.t, u.t); }
  48.613 +
  48.614 +    // Loads and stores with memory fence. These have only the relevant versions.    
  48.615 +    inline static void  Store_Release(volatile C* p, C val)             { C2T_union u; u.c = val; Ops::Store_Release((PT)p, u.t); }    
  48.616 +    inline static C     Load_Acquire(const volatile C* p)               { C2T_union u; u.t = Ops::Load_Acquire((PT)p); return u.c; }
  48.617 +
  48.618 +    // Deprecated typo error:
  48.619 +    inline static bool  CompareAndSet_Relse(volatile C* p, C c, C val){ C2T_union u,cu; u.c = val; cu.c = c; return Ops::CompareAndSet_Acquire((PT)p, cu.t, u.t); }
  48.620 +};
  48.621 +
  48.622 +
  48.623 +
  48.624 +// Atomic value base class - implements operations shared for integers and pointers.
  48.625 +template<class T>
  48.626 +class AtomicValueBase
  48.627 +{
  48.628 +protected:
  48.629 +    typedef AtomicOps<T> Ops;
  48.630 +public:
  48.631 +
  48.632 +    volatile T  Value;
  48.633 +
  48.634 +    inline AtomicValueBase()                  { }
  48.635 +    explicit inline AtomicValueBase(T val)    { Ops::Store_Release(&Value, val); }
  48.636 +
  48.637 +    // Most libraries (TBB and Joshua Scholar's) library do not do Load_Acquire
  48.638 +    // here, since most algorithms do not require atomic loads. Needs some research.    
  48.639 +    inline operator T() const { return Value; }
  48.640 +
  48.641 +    // *** Standard Atomic inlines
  48.642 +    inline T     Exchange_Sync(T val)               { return Ops::Exchange_Sync(&Value,  val); }
  48.643 +    inline T     Exchange_Release(T val)            { return Ops::Exchange_Release(&Value, val); }
  48.644 +    inline T     Exchange_Acquire(T val)            { return Ops::Exchange_Acquire(&Value, val); }
  48.645 +    inline T     Exchange_NoSync(T val)             { return Ops::Exchange_NoSync(&Value, val); }
  48.646 +    inline bool  CompareAndSet_Sync(T c, T val)     { return Ops::CompareAndSet_Sync(&Value, c, val); }
  48.647 +    inline bool  CompareAndSet_Release(T c, T val)  { return Ops::CompareAndSet_Release(&Value, c, val); }
  48.648 +    inline bool  CompareAndSet_Acquire(T c, T val)  { return Ops::CompareAndSet_Acquire(&Value, c, val); }
  48.649 +    inline bool  CompareAndSet_NoSync(T c, T val)   { return Ops::CompareAndSet_NoSync(&Value, c, val); }
  48.650 +    // Load & Store.
  48.651 +    inline void  Store_Release(T val)               { Ops::Store_Release(&Value, val); }
  48.652 +    inline T     Load_Acquire() const               { return Ops::Load_Acquire(&Value);  }
  48.653 +};
  48.654 +
  48.655 +
  48.656 +// ***** AtomicPtr - Atomic pointer template
  48.657 +
  48.658 +// This pointer class supports atomic assignments with release,
  48.659 +// increment / decrement operations, and conditional compare + set.
  48.660 +
  48.661 +template<class T>
  48.662 +class AtomicPtr : public AtomicValueBase<T*>
  48.663 +{
  48.664 +    typedef typename AtomicValueBase<T*>::Ops Ops;
  48.665 +
  48.666 +public:
  48.667 +    // Initialize pointer value to 0 by default; use Store_Release only with explicit constructor.
  48.668 +    inline AtomicPtr() : AtomicValueBase<T*>()                     { this->Value = 0; }
  48.669 +    explicit inline AtomicPtr(T* val) : AtomicValueBase<T*>(val)   { }
  48.670 +        
  48.671 +    // Pointer access.
  48.672 +    inline T* operator -> () const     { return this->Load_Acquire(); }
  48.673 +
  48.674 +    // It looks like it is convenient to have Load_Acquire characteristics
  48.675 +    // for this, since that is convenient for algorithms such as linked
  48.676 +    // list traversals that can be added to bu another thread.
  48.677 +    inline operator T* () const        { return this->Load_Acquire(); }
  48.678 +
  48.679 +
  48.680 +    // *** Standard Atomic inlines (applicable to pointers)
  48.681 +
  48.682 +    // ExhangeAdd considers pointer size for pointers.
  48.683 +    template<class I>
  48.684 +    inline T*     ExchangeAdd_Sync(I incr)      { return Ops::ExchangeAdd_Sync(&this->Value, ((T*)0) + incr); }
  48.685 +    template<class I>
  48.686 +    inline T*     ExchangeAdd_Release(I incr)   { return Ops::ExchangeAdd_Release(&this->Value, ((T*)0) + incr); }
  48.687 +    template<class I>
  48.688 +    inline T*     ExchangeAdd_Acquire(I incr)   { return Ops::ExchangeAdd_Acquire(&this->Value, ((T*)0) + incr); }
  48.689 +    template<class I>
  48.690 +    inline T*     ExchangeAdd_NoSync(I incr)    { return Ops::ExchangeAdd_NoSync(&this->Value, ((T*)0) + incr); }
  48.691 +
  48.692 +    // *** Atomic Operators
  48.693 +
  48.694 +    inline T* operator = (T* val)  { this->Store_Release(val); return val; }
  48.695 +
  48.696 +    template<class I>
  48.697 +    inline T* operator += (I val) { return ExchangeAdd_Sync(val) + val; }
  48.698 +    template<class I>
  48.699 +    inline T* operator -= (I val) { return operator += (-val); }
  48.700 +
  48.701 +    inline T* operator ++ ()      { return ExchangeAdd_Sync(1) + 1; }
  48.702 +    inline T* operator -- ()      { return ExchangeAdd_Sync(-1) - 1; }
  48.703 +    inline T* operator ++ (int)   { return ExchangeAdd_Sync(1); }
  48.704 +    inline T* operator -- (int)   { return ExchangeAdd_Sync(-1); }
  48.705 +};
  48.706 +
  48.707 +
  48.708 +// ***** AtomicInt - Atomic integer template
  48.709 +
  48.710 +// Implements an atomic integer type; the exact type to use is provided 
  48.711 +// as an argument. Supports atomic Acquire / Release semantics, atomic
  48.712 +// arithmetic operations, and atomic conditional compare + set.
  48.713 +
  48.714 +template<class T>
  48.715 +class AtomicInt : public AtomicValueBase<T>
  48.716 +{
  48.717 +    typedef typename AtomicValueBase<T>::Ops Ops;
  48.718 +
  48.719 +public:
  48.720 +    inline AtomicInt() : AtomicValueBase<T>()                     { }
  48.721 +    explicit inline AtomicInt(T val) : AtomicValueBase<T>(val)    { }
  48.722 +
  48.723 +
  48.724 +    // *** Standard Atomic inlines (applicable to int)   
  48.725 +    inline T     ExchangeAdd_Sync(T val)            { return Ops::ExchangeAdd_Sync(&this->Value, val); }
  48.726 +    inline T     ExchangeAdd_Release(T val)         { return Ops::ExchangeAdd_Release(&this->Value, val); }
  48.727 +    inline T     ExchangeAdd_Acquire(T val)         { return Ops::ExchangeAdd_Acquire(&this->Value, val); }
  48.728 +    inline T     ExchangeAdd_NoSync(T val)          { return Ops::ExchangeAdd_NoSync(&this->Value, val); }
  48.729 +    // These increments could be more efficient because they don't return a value.
  48.730 +    inline void  Increment_Sync()                   { ExchangeAdd_Sync((T)1); }
  48.731 +    inline void  Increment_Release()                { ExchangeAdd_Release((T)1); }
  48.732 +    inline void  Increment_Acquire()                { ExchangeAdd_Acquire((T)1); }    
  48.733 +    inline void  Increment_NoSync()                 { ExchangeAdd_NoSync((T)1); }
  48.734 +
  48.735 +    // *** Atomic Operators
  48.736 +
  48.737 +    inline T operator = (T val)  { this->Store_Release(val); return val; }
  48.738 +    inline T operator += (T val) { return ExchangeAdd_Sync(val) + val; }
  48.739 +    inline T operator -= (T val) { return ExchangeAdd_Sync(0 - val) - val; }
  48.740 +
  48.741 +    inline T operator ++ ()      { return ExchangeAdd_Sync((T)1) + 1; }
  48.742 +    inline T operator -- ()      { return ExchangeAdd_Sync(((T)0)-1) - 1; }
  48.743 +    inline T operator ++ (int)   { return ExchangeAdd_Sync((T)1); }
  48.744 +    inline T operator -- (int)   { return ExchangeAdd_Sync(((T)0)-1); }
  48.745 +
  48.746 +    // More complex atomic operations. Leave it to compiler whether to optimize them or not.
  48.747 +    T operator &= (T arg)
  48.748 +    {
  48.749 +        T comp, newVal;
  48.750 +        do {
  48.751 +            comp   = this->Value;
  48.752 +            newVal = comp & arg;
  48.753 +        } while(!this->CompareAndSet_Sync(comp, newVal));
  48.754 +        return newVal;
  48.755 +    }
  48.756 +
  48.757 +    T operator |= (T arg)
  48.758 +    {
  48.759 +        T comp, newVal;
  48.760 +        do {
  48.761 +            comp   = this->Value;
  48.762 +            newVal = comp | arg;
  48.763 +        } while(!this->CompareAndSet_Sync(comp, newVal));
  48.764 +        return newVal;
  48.765 +    }
  48.766 +
  48.767 +    T operator ^= (T arg)
  48.768 +    {
  48.769 +        T comp, newVal;
  48.770 +        do {
  48.771 +            comp   = this->Value;
  48.772 +            newVal = comp ^ arg;
  48.773 +        } while(!this->CompareAndSet_Sync(comp, newVal));
  48.774 +        return newVal;
  48.775 +    }
  48.776 +
  48.777 +    T operator *= (T arg)
  48.778 +    {
  48.779 +        T comp, newVal;
  48.780 +        do {
  48.781 +            comp   = this->Value;
  48.782 +            newVal = comp * arg;
  48.783 +        } while(!this->CompareAndSet_Sync(comp, newVal));
  48.784 +        return newVal;
  48.785 +    }
  48.786 +
  48.787 +    T operator /= (T arg)
  48.788 +    {
  48.789 +        T comp, newVal;
  48.790 +        do {
  48.791 +            comp   = this->Value;
  48.792 +            newVal = comp / arg;
  48.793 +        } while(!CompareAndSet_Sync(comp, newVal));
  48.794 +        return newVal;
  48.795 +    }
  48.796 +
  48.797 +    T operator >>= (unsigned bits)
  48.798 +    {
  48.799 +        T comp, newVal;
  48.800 +        do {
  48.801 +            comp   = this->Value;
  48.802 +            newVal = comp >> bits;
  48.803 +        } while(!CompareAndSet_Sync(comp, newVal));
  48.804 +        return newVal;
  48.805 +    }
  48.806 +
  48.807 +    T operator <<= (unsigned bits)
  48.808 +    {
  48.809 +        T comp, newVal;
  48.810 +        do {
  48.811 +            comp   = this->Value;
  48.812 +            newVal = comp << bits;
  48.813 +        } while(!this->CompareAndSet_Sync(comp, newVal));
  48.814 +        return newVal;
  48.815 +    }
  48.816 +};
  48.817 +
  48.818 +
  48.819 +//-----------------------------------------------------------------------------------
  48.820 +// ***** Lock
  48.821 +
  48.822 +// Lock is a simplest and most efficient mutual-exclusion lock class.
  48.823 +// Unlike Mutex, it cannot be waited on.
  48.824 +
  48.825 +class Lock
  48.826 +{
  48.827 +    // NOTE: Locks are not allocatable and they themselves should not allocate 
  48.828 +    // memory by standard means. This is the case because StandardAllocator
  48.829 +    // relies on this class.
  48.830 +    // Make 'delete' private. Don't do this for 'new' since it can be redefined.  
  48.831 +    void    operator delete(void*) {}
  48.832 +
  48.833 +
  48.834 +    // *** Lock implementation for various platforms.
  48.835 +    
  48.836 +#if !defined(OVR_ENABLE_THREADS)
  48.837 +
  48.838 +public:
  48.839 +    // With no thread support, lock does nothing.
  48.840 +    inline Lock() { }
  48.841 +    inline Lock(unsigned) { }
  48.842 +    inline ~Lock() { }    
  48.843 +    inline void DoLock() { }
  48.844 +    inline void Unlock() { }
  48.845 +
  48.846 +   // Windows.   
  48.847 +#elif defined(OVR_OS_MS)
  48.848 +
  48.849 +    CRITICAL_SECTION cs;
  48.850 +public:   
  48.851 +    Lock(unsigned spinCount = 10000);   // Mutexes with non-zero spin counts usually result in better performance.
  48.852 +    ~Lock();
  48.853 +    // Locking functions.
  48.854 +    inline void DoLock()    { ::EnterCriticalSection(&cs); }
  48.855 +    inline void Unlock()    { ::LeaveCriticalSection(&cs); }
  48.856 +
  48.857 +#else
  48.858 +    pthread_mutex_t mutex;
  48.859 +
  48.860 +public:
  48.861 +    static pthread_mutexattr_t RecursiveAttr;
  48.862 +    static bool                RecursiveAttrInit;
  48.863 +
  48.864 +    Lock (unsigned spinCount = 0) // To do: Support spin count, probably via a custom lock implementation.
  48.865 +    {
  48.866 +        OVR_UNUSED(spinCount);
  48.867 +        if (!RecursiveAttrInit)
  48.868 +        {
  48.869 +            pthread_mutexattr_init(&RecursiveAttr);
  48.870 +            pthread_mutexattr_settype(&RecursiveAttr, PTHREAD_MUTEX_RECURSIVE);
  48.871 +            RecursiveAttrInit = 1;
  48.872 +        }
  48.873 +        pthread_mutex_init(&mutex,&RecursiveAttr);
  48.874 +    }
  48.875 +    ~Lock ()                { pthread_mutex_destroy(&mutex); }
  48.876 +    inline void DoLock()    { pthread_mutex_lock(&mutex); }
  48.877 +    inline void Unlock()    { pthread_mutex_unlock(&mutex); }
  48.878 +
  48.879 +#endif // OVR_ENABLE_THREDS
  48.880 +
  48.881 +
  48.882 +public:
  48.883 +    // Locker class, used for automatic locking
  48.884 +    class Locker
  48.885 +    {
  48.886 +    public:     
  48.887 +        Lock *pLock;
  48.888 +        inline Locker(Lock *plock)
  48.889 +        { pLock = plock; pLock->DoLock(); }
  48.890 +        inline ~Locker()
  48.891 +        { pLock->Unlock();  }
  48.892 +    };
  48.893 +};
  48.894 +
  48.895 +
  48.896 +//-------------------------------------------------------------------------------------
  48.897 +// Globally shared Lock implementation used for MessageHandlers, etc.
  48.898 +
  48.899 +class SharedLock
  48.900 +{    
  48.901 +public:
  48.902 +    SharedLock() : UseCount(0) {}
  48.903 +
  48.904 +    Lock* GetLockAddRef();
  48.905 +    void  ReleaseLock(Lock* plock);
  48.906 +   
  48.907 +private:
  48.908 +    Lock* toLock() { return (Lock*)Buffer; }
  48.909 +
  48.910 +    // UseCount and max alignment.
  48.911 +    volatile int    UseCount;
  48.912 +    uint64_t        Buffer[(sizeof(Lock)+sizeof(uint64_t)-1)/sizeof(uint64_t)];
  48.913 +};
  48.914 +
  48.915 +
  48.916 +} // OVR
  48.917 +
  48.918 +#endif
    49.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    49.2 +++ b/LibOVR/Src/Kernel/OVR_CRC32.cpp	Wed Jan 14 06:51:16 2015 +0200
    49.3 @@ -0,0 +1,85 @@
    49.4 +/************************************************************************************
    49.5 +
    49.6 +Filename    :   OVR_CRC32.cpp
    49.7 +Content     :   CRC-32 with polynomial used for sensor devices
    49.8 +Created     :   June 20, 2014
    49.9 +Author      :   Chris Taylor
   49.10 +
   49.11 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   49.12 +
   49.13 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
   49.14 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
   49.15 +which is provided at the time of installation or download, or which 
   49.16 +otherwise accompanies this software in either electronic or hard copy form.
   49.17 +
   49.18 +You may obtain a copy of the License at
   49.19 +
   49.20 +http://www.oculusvr.com/licenses/LICENSE-3.2 
   49.21 +
   49.22 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
   49.23 +distributed under the License is distributed on an "AS IS" BASIS,
   49.24 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   49.25 +See the License for the specific language governing permissions and
   49.26 +limitations under the License.
   49.27 +
   49.28 +************************************************************************************/
   49.29 +
   49.30 +#include "OVR_CRC32.h"
   49.31 +
   49.32 +namespace OVR {
   49.33 +
   49.34 +
   49.35 +static const uint32_t CRC_Table[256] = {
   49.36 +	0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005,
   49.37 +	0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61, 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
   49.38 +	0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
   49.39 +	0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd,
   49.40 +	0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039, 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5,
   49.41 +	0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
   49.42 +	0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
   49.43 +	0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d,
   49.44 +	0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
   49.45 +	0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca,
   49.46 +	0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde, 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02,
   49.47 +	0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
   49.48 +	0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692,
   49.49 +	0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6, 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a,
   49.50 +	0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
   49.51 +	0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a,
   49.52 +	0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637, 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
   49.53 +	0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
   49.54 +	0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b,
   49.55 +	0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff, 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623,
   49.56 +	0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
   49.57 +	0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
   49.58 +	0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b,
   49.59 +	0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
   49.60 +	0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c,
   49.61 +	0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8, 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24,
   49.62 +	0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
   49.63 +	0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654,
   49.64 +	0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0, 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c,
   49.65 +	0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
   49.66 +	0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c,
   49.67 +	0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668, 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
   49.68 +};
   49.69 +
   49.70 +
   49.71 +//// CRC-32
   49.72 +
   49.73 +uint32_t CRC32_Calculate(const void* data, int bytes, uint32_t accumulator)
   49.74 +{
   49.75 +	const uint8_t* inputBytes = reinterpret_cast<const uint8_t*>( data );
   49.76 +
   49.77 +	for (int j = 0; j < bytes; ++j)
   49.78 +	{
   49.79 +		int i = ((uint32_t)(accumulator >> 24) ^ *inputBytes++) & 0xFF;
   49.80 +
   49.81 +		accumulator = (accumulator << 8) ^ CRC_Table[i];
   49.82 +	}
   49.83 +
   49.84 +	return ~accumulator;
   49.85 +}
   49.86 +
   49.87 +
   49.88 +} // OVR
    50.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    50.2 +++ b/LibOVR/Src/Kernel/OVR_CRC32.h	Wed Jan 14 06:51:16 2015 +0200
    50.3 @@ -0,0 +1,45 @@
    50.4 +/************************************************************************************
    50.5 +
    50.6 +PublicHeader:   OVR
    50.7 +Filename    :   OVR_CRC32.h
    50.8 +Content     :   CRC-32 with polynomial used for sensor devices
    50.9 +Created     :   June 20, 2014
   50.10 +Author      :   Chris Taylor
   50.11 +
   50.12 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   50.13 +
   50.14 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
   50.15 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
   50.16 +which is provided at the time of installation or download, or which 
   50.17 +otherwise accompanies this software in either electronic or hard copy form.
   50.18 +
   50.19 +You may obtain a copy of the License at
   50.20 +
   50.21 +http://www.oculusvr.com/licenses/LICENSE-3.2 
   50.22 +
   50.23 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
   50.24 +distributed under the License is distributed on an "AS IS" BASIS,
   50.25 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   50.26 +See the License for the specific language governing permissions and
   50.27 +limitations under the License.
   50.28 +
   50.29 +************************************************************************************/
   50.30 +
   50.31 +#ifndef OVR_CRC32_h
   50.32 +#define OVR_CRC32_h
   50.33 +
   50.34 +#include "OVR_Types.h"
   50.35 +
   50.36 +namespace OVR {
   50.37 +
   50.38 +
   50.39 +//-----------------------------------------------------------------------------------
   50.40 +// ***** CRC-32
   50.41 +
   50.42 +// Polynomial used and algorithm details are proprietary to our sensor board
   50.43 +uint32_t CRC32_Calculate(const void* data, int bytes, uint32_t prevCRC = 0);
   50.44 +
   50.45 +
   50.46 +} // namespace OVR
   50.47 +
   50.48 +#endif
    51.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    51.2 +++ b/LibOVR/Src/Kernel/OVR_Color.h	Wed Jan 14 06:51:16 2015 +0200
    51.3 @@ -0,0 +1,73 @@
    51.4 +/************************************************************************************
    51.5 +
    51.6 +PublicHeader:   OVR_Kernel.h
    51.7 +Filename    :   OVR_Color.h
    51.8 +Content     :   Contains color struct.
    51.9 +Created     :   February 7, 2013
   51.10 +Notes       : 
   51.11 +
   51.12 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   51.13 +
   51.14 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
   51.15 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
   51.16 +which is provided at the time of installation or download, or which 
   51.17 +otherwise accompanies this software in either electronic or hard copy form.
   51.18 +
   51.19 +You may obtain a copy of the License at
   51.20 +
   51.21 +http://www.oculusvr.com/licenses/LICENSE-3.2 
   51.22 +
   51.23 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
   51.24 +distributed under the License is distributed on an "AS IS" BASIS,
   51.25 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   51.26 +See the License for the specific language governing permissions and
   51.27 +limitations under the License.
   51.28 +
   51.29 +************************************************************************************/
   51.30 +#ifndef OVR_Color_h
   51.31 +#define OVR_Color_h
   51.32 +
   51.33 +#include "OVR_Types.h"
   51.34 +
   51.35 +namespace OVR {
   51.36 +
   51.37 +
   51.38 +struct Color
   51.39 +{
   51.40 +    uint8_t R,G,B,A;
   51.41 +
   51.42 +    Color()
   51.43 +    {
   51.44 +        #if defined(OVR_BUILD_DEBUG)
   51.45 +            R = G = B = A = 0;
   51.46 +        #endif
   51.47 +    }
   51.48 +
   51.49 +    // Constructs color by channel. Alpha is set to 0xFF (fully visible)
   51.50 +    // if not specified.
   51.51 +    Color(unsigned char r,unsigned char g,unsigned char b, unsigned char a = 0xFF)
   51.52 +        : R(r), G(g), B(b), A(a) { }
   51.53 +
   51.54 +    // 0xAARRGGBB - Common HTML color Hex layout
   51.55 +    Color(unsigned c)
   51.56 +        : R((unsigned char)(c>>16)), G((unsigned char)(c>>8)),
   51.57 +        B((unsigned char)c), A((unsigned char)(c>>24)) { }
   51.58 +
   51.59 +    bool operator==(const Color& b) const
   51.60 +    {
   51.61 +        return R == b.R && G == b.G && B == b.B && A == b.A;
   51.62 +    }
   51.63 +
   51.64 +    void  GetRGBA(float *r, float *g, float *b, float* a) const
   51.65 +    {
   51.66 +        *r = R / 255.0f;
   51.67 +        *g = G / 255.0f;
   51.68 +        *b = B / 255.0f;
   51.69 +        *a = A / 255.0f;
   51.70 +    }
   51.71 +};
   51.72 +
   51.73 +
   51.74 +} // namespace OVR
   51.75 +
   51.76 +#endif
    52.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    52.2 +++ b/LibOVR/Src/Kernel/OVR_Compiler.h	Wed Jan 14 06:51:16 2015 +0200
    52.3 @@ -0,0 +1,1524 @@
    52.4 +/************************************************************************************
    52.5 +
    52.6 +PublicHeader:   OVR.h
    52.7 +Filename    :   OVR_Compiler.h
    52.8 +Content     :   Compiler-specific feature identification and utilities
    52.9 +Created     :   June 19, 2014
   52.10 +Notes       : 
   52.11 +
   52.12 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   52.13 +
   52.14 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
   52.15 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
   52.16 +which is provided at the time of installation or download, or which 
   52.17 +otherwise accompanies this software in either electronic or hard copy form.
   52.18 +
   52.19 +You may obtain a copy of the License at
   52.20 +
   52.21 +http://www.oculusvr.com/licenses/LICENSE-3.2 
   52.22 +
   52.23 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
   52.24 +distributed under the License is distributed on an "AS IS" BASIS,
   52.25 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   52.26 +See the License for the specific language governing permissions and
   52.27 +limitations under the License.
   52.28 +
   52.29 +************************************************************************************/
   52.30 +
   52.31 +
   52.32 +#ifndef OVR_Compiler_h
   52.33 +#define OVR_Compiler_h
   52.34 +
   52.35 +#pragma once
   52.36 +
   52.37 +
   52.38 +// References
   52.39 +//    https://gcc.gnu.org/projects/cxx0x.html
   52.40 +//    https://gcc.gnu.org/projects/cxx1y.html
   52.41 +//    http://clang.llvm.org/cxx_status.html
   52.42 +//    http://msdn.microsoft.com/en-us/library/hh567368.aspx
   52.43 +//    https://docs.google.com/spreadsheet/pub?key=0AoBblDsbooe4dHZuVTRoSTFBejk5eFBfVk1GWlE5UlE&output=html
   52.44 +//    http://nadeausoftware.com/articles/2012/10/c_c_tip_how_detect_compiler_name_and_version_using_compiler_predefined_macros
   52.45 +
   52.46 +
   52.47 +//-----------------------------------------------------------------------------------
   52.48 +// ***** Compiler
   52.49 +//
   52.50 +//  The following compilers are defined: (OVR_CC_x)
   52.51 +//
   52.52 +//     MSVC     - Microsoft Visual C/C++
   52.53 +//     INTEL    - Intel C++ for Linux / Windows
   52.54 +//     GNU      - GNU C++
   52.55 +//     ARM      - ARM C/C++
   52.56 +
   52.57 +#if defined(__INTEL_COMPILER)
   52.58 +// Intel 4.0                    = 400
   52.59 +// Intel 5.0                    = 500
   52.60 +// Intel 6.0                    = 600
   52.61 +// Intel 8.0                    = 800
   52.62 +// Intel 9.0                    = 900
   52.63 +#  define OVR_CC_INTEL       __INTEL_COMPILER
   52.64 +
   52.65 +#elif defined(_MSC_VER)
   52.66 +// MSVC 5.0                     = 1100
   52.67 +// MSVC 6.0                     = 1200
   52.68 +// MSVC 7.0 (VC2002)            = 1300
   52.69 +// MSVC 7.1 (VC2003)            = 1310
   52.70 +// MSVC 8.0 (VC2005)            = 1400
   52.71 +// MSVC 9.0 (VC2008)            = 1500
   52.72 +// MSVC 10.0 (VC2010)           = 1600
   52.73 +// MSVC 11.0 (VC2012) = 1700
   52.74 +// MSVC 12.0 (VC2013)           = 1800
   52.75 +#  define OVR_CC_MSVC        _MSC_VER
   52.76 +
   52.77 +#if _MSC_VER == 0x1600
   52.78 +#  if _MSC_FULL_VER < 160040219
   52.79 +#     error "Oculus does not support VS2010 without SP1 installed."
   52.80 +#  endif
   52.81 +#endif
   52.82 +
   52.83 +#elif defined(__GNUC__)
   52.84 +#  define OVR_CC_GNU
   52.85 +
   52.86 +#elif defined(__clang__)
   52.87 +#  define OVR_CC_CLANG
   52.88 +
   52.89 +#elif defined(__CC_ARM)
   52.90 +#  define OVR_CC_ARM
   52.91 +
   52.92 +#else
   52.93 +#  error "Oculus does not support this Compiler"
   52.94 +#endif
   52.95 +
   52.96 +
   52.97 +//-----------------------------------------------------------------------------------
   52.98 +// ***** OVR_CC_VERSION
   52.99 +//
  52.100 +//    M = major version
  52.101 +//    m = minor version
  52.102 +//    p = patch release
  52.103 +//    b = build number
  52.104 +//
  52.105 +//    Compiler      Format   Example
  52.106 +//    ----------------------------
  52.107 +//    OVR_CC_GNU    Mmm      408 means GCC 4.8
  52.108 +//    OVR_CC_CLANG  Mmm      305 means clang 3.5 
  52.109 +//    OVR_CC_MSVC   MMMM     1700 means VS2012
  52.110 +//    OVR_CC_ARM    Mmpbbb   401677 means 4.0, patch 1, build 677
  52.111 +//    OVR_CC_INTEL  MMmm     1210 means 12.10
  52.112 +//    OVR_CC_EDG    Mmm      407 means EDG 4.7
  52.113 +//
  52.114 +#if defined(OVR_CC_GNU)
  52.115 +    #define OVR_CC_VERSION ((__GNUC__ * 100) + __GNUC_MINOR__)
  52.116 +#elif defined(OVR_CC_CLANG)
  52.117 +    #define OVR_CC_VERSION ((__clang_major__ * 100) + __clang_minor__)
  52.118 +#elif defined(OVR_CC_MSVC)
  52.119 +    #define OVR_CC_VERSION _MSC_VER // Question: Should we recognize _MSC_FULL_VER?
  52.120 +#elif defined(OVR_CC_ARM)
  52.121 +    #define OVR_CC_VERSION __ARMCC_VERSION
  52.122 +#elif defined(OVR_CC_INTEL)
  52.123 +    #if defined(__INTEL_COMPILER)
  52.124 +        #define OVR_CC_VERSION __INTEL_COMPILER
  52.125 +    #elif defined(__ICL)
  52.126 +        #define OVR_CC_VERSION __ICL
  52.127 +    #elif defined(__ICC)
  52.128 +        #define OVR_CC_VERSION __ICC
  52.129 +    #elif defined(__ECC)
  52.130 +        #define OVR_CC_VERSION __ECC
  52.131 +    #endif
  52.132 +#elif defined(OVR_CC_EDG)
  52.133 +    #define OVR_CC_VERSION __EDG_VERSION__  // This is a generic fallback for EDG-based compilers which aren't specified above (e.g. as OVR_CC_ARM)
  52.134 +#endif
  52.135 +
  52.136 +
  52.137 +
  52.138 +// -----------------------------------------------------------------------------------
  52.139 +// ***** OVR_DISABLE_OPTIMIZATION / OVR_RESTORE_OPTIMIZATION
  52.140 +//
  52.141 +// Allows for the dynamic disabling and restoring of compiler optimizations in code.
  52.142 +// This is useful for helping deal with potential compiler code generation problems.
  52.143 +// With VC++ the usage must be outside of function bodies. This can be used only to
  52.144 +// temporarily disable optimization for a block of code and not to temporarily enable
  52.145 +// optimization for a block of code.
  52.146 +//
  52.147 +// Clang doesn't support this as of June 2014, though function __attribute__((optimize(0))
  52.148 +// is supposedly supported by clang in addition to GCC. To consider: Make a wrapper for
  52.149 +// this attribute-based functionality.
  52.150 +//
  52.151 +// Example usage:
  52.152 +//     OVR_DISABLE_OPTIMIZATION()
  52.153 +//     void Test() { ... }
  52.154 +//     OVR_RESTORE_OPTIMIZATION()
  52.155 +//
  52.156 +#if !defined(OVR_DISABLE_OPTIMIZATION)
  52.157 +    #if defined(OVR_CC_GNU) && (OVR_CC_VERSION > 404) && (defined(OVR_CPU_X86) || defined(OVR_CPU_X86_64))
  52.158 +        #define OVR_DISABLE_OPTIMIZATION() \
  52.159 +            _Pragma("GCC push_options")    \
  52.160 +            _Pragma("GCC optimize 0")
  52.161 +    #elif defined(OVR_CC_MSVC)
  52.162 +        #define OVR_DISABLE_OPTIMIZATION() __pragma(optimize("", off))
  52.163 +    #else
  52.164 +        #define OVR_DISABLE_OPTIMIZATION()
  52.165 +    #endif
  52.166 +#endif
  52.167 +
  52.168 +#if !defined(OVR_RESTORE_OPTIMIZATION)
  52.169 +    #if defined(OVR_CC_GNU) && (OVR_CC_VERSION > 404) && (defined(OVR_CPU_X86) || defined(OVR_CPU_X86_64))
  52.170 +        #define OVR_RESTORE_OPTIMIZATION() _Pragma("GCC pop_options")
  52.171 +    #elif defined(OVR_CC_MSVC)
  52.172 +        #define OVR_RESTORE_OPTIMIZATION() __pragma(optimize("", on))
  52.173 +    #else
  52.174 +        #define OVR_RESTORE_OPTIMIZATION()
  52.175 +    #endif
  52.176 +#endif
  52.177 +
  52.178 +
  52.179 +// -----------------------------------------------------------------------------------
  52.180 +// *****  OVR_DISABLE_GNU_WARNING / OVR_RESTORE_GNU_WARNING
  52.181 +//
  52.182 +// Portable wrapper for disabling GCC compiler warnings, one at a time. See example
  52.183 +// usage for usage by example.
  52.184 +//
  52.185 +// Example usage:
  52.186 +//     OVR_DISABLE_GNU_WARNING(-Wmissing-braces)  // Only one warning per usage.
  52.187 +//     OVR_DISABLE_GNU_WARNING(-Wunused-variable)
  52.188 +//     <code>
  52.189 +//     OVR_RESTORE_GNU_WARNINGS()
  52.190 +//     OVR_RESTORE_GNU_WARNINGS()                 // Must match each disable with a restore.
  52.191 +//
  52.192 +#if !defined(OVR_DISABLE_GNU_WARNING)
  52.193 +    #if defined(OVR_CC_GNU)
  52.194 +        #define ODGW1(x) #x
  52.195 +        #define ODGW2(x) ODGW1(GCC diagnostic ignored x)
  52.196 +        #define ODGW3(x) ODGW2(#x)
  52.197 +    #endif
  52.198 +
  52.199 +    #if defined(OVR_CC_GNU) && (OVR_CC_VERSION >= 406)
  52.200 +        #define OVR_DISABLE_GNU_WARNING(w)  \
  52.201 +            _Pragma("GCC diagnostic push")  \
  52.202 +            _Pragma(ODGW3(w))
  52.203 +    #elif defined(OVR_CC_GNU) && (OVR_CC_VERSION >= 404)  // GCC 4.4 doesn't support diagnostic push, but supports disabling warnings.
  52.204 +        #define OVR_DISABLE_GNU_WARNING(w)  \
  52.205 +            _Pragma(ODGW3(w))
  52.206 +    #else
  52.207 +        #define OVR_DISABLE_GNU_WARNING(w)
  52.208 +    #endif
  52.209 +#endif
  52.210 +
  52.211 +#if !defined(OVR_RESTORE_GNU_WARNING)
  52.212 +    #if defined(OVR_CC_GNU) && (OVR_CC_VERSION >= 4006)
  52.213 +        #define OVR_RESTORE_GNU_WARNINGS()  \
  52.214 +            _Pragma("GCC diagnostic pop")
  52.215 +    #else
  52.216 +        #define OVR_RESTORE_GNU_WARNING()
  52.217 +    #endif
  52.218 +#endif
  52.219 +
  52.220 +
  52.221 +
  52.222 +// -----------------------------------------------------------------------------------
  52.223 +// *****  OVR_DISABLE_CLANG_WARNING / OVR_RESTORE_CLANG_WARNING
  52.224 +//
  52.225 +// Portable wrapper for disabling GCC compiler warnings, one at a time. See example
  52.226 +// usage for usage by example.
  52.227 +//
  52.228 +// Example usage:
  52.229 +//     OVR_DISABLE_CLANG_WARNING(-Wmissing-braces)  // Only one warning per usage.
  52.230 +//     OVR_DISABLE_CLANG_WARNING(-Wunused-variable)
  52.231 +//     <code>
  52.232 +//     OVR_RESTORE_CLANG_WARNINGS()
  52.233 +//     OVR_RESTORE_CLANG_WARNINGS()                 // Must match each disable with a restore.
  52.234 +//
  52.235 +//
  52.236 +#if !defined(OVR_DISABLE_CLANG_WARNING)
  52.237 +    #if defined(OVR_CC_CLANG)
  52.238 +        #define ODCW1(x) #x
  52.239 +        #define ODCW2(x) ODCW1(clang diagnostic ignored x)
  52.240 +        #define ODCW3(x) ODCW2(#x)
  52.241 +
  52.242 +        #define OVR_DISABLE_CLANG_WARNING(w)   \
  52.243 +            _Pragma("clang diagnostic push")  \
  52.244 +            _Pragma(ODCW3(w))
  52.245 +    #else
  52.246 +        #define OVR_DISABLE_CLANG_WARNING(w)
  52.247 +    #endif
  52.248 +#endif
  52.249 +
  52.250 +#if !defined(OVR_RESTORE_CLANG_WARNING)
  52.251 +    #if defined(OVR_CC_CLANG)
  52.252 +        #define OVR_RESTORE_CLANG_WARNING()    \
  52.253 +            _Pragma("clang diagnostic pop")
  52.254 +    #else
  52.255 +        #define OVR_RESTORE_CLANG_WARNING()
  52.256 +    #endif
  52.257 +#endif
  52.258 +
  52.259 +
  52.260 +// -----------------------------------------------------------------------------------
  52.261 +// ***** OVR_DISABLE_MSVC_WARNING / OVR_RESTORE_MSVC_WARNING
  52.262 +//
  52.263 +// Portable wrapper for disabling VC++ compiler warnings. See example usage for usage
  52.264 +// by example.
  52.265 +//
  52.266 +// Example usage:
  52.267 +//     OVR_DISABLE_MSVC_WARNING(4556 4782 4422)
  52.268 +//     <code>
  52.269 +//     OVR_RESTORE_MSVC_WARNING()
  52.270 +//
  52.271 +#if !defined(OVR_DISABLE_MSVC_WARNING)
  52.272 +    #if defined(OVR_CC_MSVC)
  52.273 +        #define OVR_DISABLE_MSVC_WARNING(w) \
  52.274 +            __pragma(warning(push))         \
  52.275 +            __pragma(warning(disable:w))
  52.276 +    #else
  52.277 +        #define OVR_DISABLE_MSVC_WARNING(w)
  52.278 +    #endif
  52.279 +#endif
  52.280 +
  52.281 +#if !defined(OVR_RESTORE_MSVC_WARNING)
  52.282 +    #if defined(OVR_CC_MSVC)
  52.283 +        #define OVR_RESTORE_MSVC_WARNING() \
  52.284 +            __pragma(warning(pop))
  52.285 +    #else
  52.286 +        #define OVR_RESTORE_MSVC_WARNING()
  52.287 +    #endif
  52.288 +#endif
  52.289 +
  52.290 +
  52.291 +// -----------------------------------------------------------------------------------
  52.292 +// ***** OVR_DISABLE_ALL_MSVC_WARNINGS / OVR_RESTORE_ALL_MSVC_WARNINGS
  52.293 +//
  52.294 +// Portable wrapper for disabling all VC++ compiler warnings.
  52.295 +// OVR_RESTORE_ALL_MSVC_WARNINGS restores warnings that were disabled by 
  52.296 +// OVR_DISABLE_ALL_MSVC_WARNINGS. Any previously enabled warnings will still be 
  52.297 +// enabled after OVR_RESTORE_ALL_MSVC_WARNINGS.
  52.298 +//
  52.299 +// Example usage:
  52.300 +//     OVR_DISABLE_ALL_MSVC_WARNINGS()
  52.301 +//     <code>
  52.302 +//     OVR_RESTORE_ALL_MSVC_WARNINGS()
  52.303 +
  52.304 +#if !defined(OVR_DISABLE_ALL_MSVC_WARNINGS)
  52.305 +    #if defined(OVR_CC_MSVC)
  52.306 +        #define OVR_DISABLE_ALL_MSVC_WARNINGS() \
  52.307 +            __pragma(warning(push, 0))
  52.308 +    #else
  52.309 +        #define OVR_DISABLE_ALL_MSVC_WARNINGS()
  52.310 +    #endif
  52.311 +#endif
  52.312 +
  52.313 +#if !defined(OVR_RESTORE_ALL_MSVC_WARNINGS)
  52.314 +    #if defined(OVR_CC_MSVC)
  52.315 +        #define OVR_RESTORE_ALL_MSVC_WARNINGS() \
  52.316 +            __pragma(warning(pop))
  52.317 +    #else
  52.318 +        #define OVR_RESTORE_ALL_MSVC_WARNINGS()
  52.319 +    #endif
  52.320 +#endif
  52.321 +
  52.322 +
  52.323 +//-----------------------------------------------------------------------------------
  52.324 +// ***** OVR_CC_HAS_FEATURE
  52.325 +//
  52.326 +// This is a portable way to use compile-time feature identification available 
  52.327 +// with some compilers in a clean way. Direct usage of __has_feature in preprocessing
  52.328 +// statements of non-supporting compilers results in a preprocessing error.
  52.329 +//
  52.330 +// Example usage:
  52.331 +//     #if OVR_CC_HAS_FEATURE(is_pod)
  52.332 +//         if(__is_pod(T)) // If the type is plain data then we can safely memcpy it.
  52.333 +//             memcpy(&destObject, &srcObject, sizeof(object));
  52.334 +//     #endif
  52.335 +//
  52.336 +#if !defined(OVR_CC_HAS_FEATURE)
  52.337 +    #if defined(__clang__) // http://clang.llvm.org/docs/LanguageExtensions.html#id2
  52.338 +        #define OVR_CC_HAS_FEATURE(x) __has_feature(x)
  52.339 +    #else
  52.340 +        #define OVR_CC_HAS_FEATURE(x) 0
  52.341 +    #endif
  52.342 +#endif
  52.343 +
  52.344 +
  52.345 +//-----------------------------------------------------------------------------------
  52.346 +// ***** OVR_CC_HAS_BUILTIN
  52.347 +//
  52.348 +//
  52.349 +// This is a portable way to use compile-time builtin identification available 
  52.350 +// with some compilers in a clean way. Direct usage of __has_builtin in preprocessing
  52.351 +// statements of non-supporting compilers results in a preprocessing error.
  52.352 +//
  52.353 +// Example usage:
  52.354 +//     #if OVR_CC_HAS_BUILTIN(__builtin_trap)
  52.355 +//         #define DEBUG_BREAK __builtin_trap
  52.356 +//     #endif
  52.357 +//  
  52.358 +#if !defined(OVR_CC_HAS_BUILTIN)
  52.359 +    #if defined(__clang__) 
  52.360 +        #define OVR_CC_HAS_BUILTIN(x) __has_builtin(x) // http://clang.llvm.org/docs/LanguageExtensions.html#id2
  52.361 +    #else
  52.362 +        #define OVR_CC_HAS_BUILTIN(x) 0
  52.363 +    #endif
  52.364 +#endif
  52.365 +
  52.366 +
  52.367 +//-----------------------------------------------------------------------------------
  52.368 +// ***** OVR_CPP11_ENABLED / OVR_CPP_CPP14_ENABLED
  52.369 +//
  52.370 +// Defined as 1 if the compiler has its available C++11 support enabled, else undefined.
  52.371 +// This does not mean that all of C++11 or any particular feature of C++11 is supported
  52.372 +// by the compiler. It means that whatever C++11 support the compiler has is enabled.
  52.373 +// This also includes existing and older compilers that still identify C++11 as C++0x.
  52.374 +//
  52.375 +#if !defined(OVR_CPP11_ENABLED) && defined(__cplusplus)
  52.376 +    #if defined(__GNUC__) && defined(__GXX_EXPERIMENTAL_CXX0X__)
  52.377 +        #define OVR_CPP11_ENABLED 1
  52.378 +    #elif defined(_MSC_VER) && (_MSC_VER >= 1500)   // VS2010+, the first version with any significant C++11 support. 
  52.379 +        #define OVR_CPP11_ENABLED 1
  52.380 +    #elif (__cplusplus >= 201103L)                  // 201103 is the first C++11 version.
  52.381 +        #define OVR_CPP11_ENABLED 1
  52.382 +    #else
  52.383 +        // Leave undefined
  52.384 +    #endif
  52.385 +#endif
  52.386 +
  52.387 +#if !defined(OVR_CPP_CPP14_ENABLED) && defined(__cplusplus)
  52.388 +    #if defined(_MSC_VER) && (_MSC_VER >= 1800)     // VS2013+, the first version with any significant C++14 support. 
  52.389 +        #define OVR_CPP_CPP14_ENABLED 1
  52.390 +    #elif (__cplusplus > 201103L)
  52.391 +        #define OVR_CPP_CPP14_ENABLED 1
  52.392 +    #else
  52.393 +        // Leave undefined
  52.394 +    #endif
  52.395 +#endif
  52.396 +
  52.397 +
  52.398 +//-----------------------------------------------------------------------------------
  52.399 +// ***** OVR_CPP_NO_EXCEPTIONS / OVR_CPP_NO_UNWIND
  52.400 +//
  52.401 +// OVR_CPP_NO_EXCEPTIONS is defined as 1 if the compiler doesn't support C++ 
  52.402 +// exceptions or is configured to disable support for them. Else not defined.
  52.403 +// If OVR_CPP_NO_EXCEPTIONS is defined then attempts to use try/catch
  52.404 +// related C++ statements result in a compilation error with many
  52.405 +// compilers.
  52.406 +//
  52.407 +// OVR_CPP_NO_UNWIND is defined as 1 if the compiler supports exceptions but 
  52.408 +// doesn't support stack unwinding in the presence of an exception. Else not defined.
  52.409 +// For the Microsoft compiler, disabling exceptions means disabling stack unwinding
  52.410 +// and not disabling exceptions themselves.
  52.411 +//
  52.412 +// Example usage:
  52.413 +//     void Test() {
  52.414 +//         #if !defined(OVR_CPP_NO_EXCEPTIONS)
  52.415 +//             try {
  52.416 +//         #endif
  52.417 +//             void* ptr = new Object;
  52.418 +//         #if !defined(OVR_CPP_NO_EXCEPTIONS)
  52.419 +//             catch(...) { ... }
  52.420 +//         #endif
  52.421 +
  52.422 +#if !defined(OVR_CPP_NO_EXCEPTIONS)
  52.423 +    #if defined(OVR_CPP_GNUC) && defined(_NO_EX)
  52.424 +        #define OVR_CPP_NO_EXCEPTIONS 1
  52.425 +    #elif (defined(OVR_CC_GNU) || defined(OVR_CC_CLANG) || defined(OVR_CC_INTEL) || defined(OVR_CC_ARM)) && !defined(__EXCEPTIONS)
  52.426 +        #define OVR_CPP_NO_EXCEPTIONS 1
  52.427 +    #elif defined(OVR_CC_MSVC) && !defined(_CPPUNWIND)
  52.428 +        #define OVR_CPP_NO_UNWIND 1
  52.429 +    #endif
  52.430 +#endif
  52.431 +
  52.432 +
  52.433 +//-----------------------------------------------------------------------------------
  52.434 +// ***** OVR_CPP_NO_RTTI
  52.435 +//
  52.436 +// Defined as 1 if C++ run-time type information support is unavailable or disabled
  52.437 +// by the compiler. Else undefined. Allows you to write portable code in the face
  52.438 +// of the possibility that RTTI is disabled.
  52.439 +//
  52.440 +// Example usage:
  52.441 +//     #if !OVR_CPP_NO_RTTI
  52.442 +//         #include <typeinfo>
  52.443 +//         int x = std::dynamic_cast<int>(3.4f);
  52.444 +//     #endif
  52.445 +
  52.446 +#if defined(__clang__) && !OVR_CC_HAS_FEATURE(cxx_rtti)
  52.447 +    #define OVR_CPP_NO_RTTI 1
  52.448 +#elif defined(__GNUC__) && !defined(__GXX_RTTI)
  52.449 +    #define OVR_CPP_NO_RTTI 1
  52.450 +#elif defined(_MSC_VER) && !defined(_CPPRTTI)
  52.451 +    #define OVR_CPP_NO_RTTI 1
  52.452 +#elif defined(__CC_ARM) && defined(__TARGET_CPU_MPCORE) && !defined(__RTTI)
  52.453 +    #define OVR_CPP_NO_RTTI 1
  52.454 +#endif
  52.455 +
  52.456 +
  52.457 +//-----------------------------------------------------------------------------------
  52.458 +// ***** OVR_CPP_NO_STATIC_ASSERT
  52.459 +//
  52.460 +// Defined as 1 if C++ run-time type information support is available and enabled
  52.461 +// by the compiler. Else undefined.
  52.462 +//
  52.463 +// Example usage:
  52.464 +//     #if OVR_CPP_NO_STATIC_ASSERT
  52.465 +//         #define MY_ASSERT(x) { int zero = 0; switch(zero) {case 0: case (x):;} }
  52.466 +//     #else
  52.467 +//         #define MY_ASSERT(x) static_assert((x), #x)
  52.468 +//     #endif
  52.469 +
  52.470 +#if !defined(OVR_CPP_NO_STATIC_ASSERT)
  52.471 +    #if !(defined(__GNUC__) && (defined(__GXX_EXPERIMENTAL_CXX0X__) || (defined(__cplusplus) && (__cplusplus >= 201103L)))) && \
  52.472 +        !(defined(__clang__) && defined(__cplusplus) && OVR_CC_HAS_FEATURE(cxx_static_assert)) &&                              \
  52.473 +        !(defined(_MSC_VER) && (_MSC_VER >= 1600) && defined(__cplusplus)) &&                 /* VS2010+  */                   \
  52.474 +        !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 401) && defined(OVR_CPP11_ENABLED)) /* EDG 4.1+ */
  52.475 +	    #define OVR_CPP_NO_STATIC_ASSERT 1
  52.476 +    #endif
  52.477 +#endif
  52.478 +
  52.479 +
  52.480 +//-----------------------------------------------------------------------------------
  52.481 +// ***** OVR_CPP_NO_NULLPTR
  52.482 +//
  52.483 +// Defined as 1 if the compiler doesn't support C++11 nullptr built in type. 
  52.484 +// Otherwise undefined. Does not identify if the standard library defines 
  52.485 +// std::nullptr_t, as some standard libraries are further behind in standardization 
  52.486 +// than the compilers using them (e.g. Apple clang with the supplied libstdc++). 
  52.487 +//
  52.488 +// OVR_Nullptr.h provides a portable nullptr and std::nullptr_t for when the 
  52.489 +// compiler or standard library do not.
  52.490 +
  52.491 +#if !defined(OVR_CPP_NO_NULLPTR)
  52.492 +    #if !defined(OVR_CPP11_ENABLED) || \
  52.493 +        (!(defined(__clang__) && OVR_CC_HAS_FEATURE(cxx_nullptr))  /* clang     */ && \
  52.494 +         !(defined(__GNUC__) && (OVR_CC_VERSION >= 406))           /* GCC 4.6+  */ && \
  52.495 +         !(defined(_MSC_VER) && (_MSC_VER >= 1600))                /* VS2010+   */ && \
  52.496 +         !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 403)))  /* EDG 4.3+  */    
  52.497 +        #define OVR_CPP_NO_NULLPTR 1
  52.498 +    #endif
  52.499 +#endif  
  52.500 +
  52.501 +
  52.502 +//-----------------------------------------------------------------------------------
  52.503 +// ***** OVR_CPP_NO_RVALUE_REFERENCES
  52.504 +//
  52.505 +// Defined as 1 if the compiler doesn't support C++11 rvalue references and move semantics.
  52.506 +// Otherwise undefined.
  52.507 +
  52.508 +#if !defined(OVR_CPP_NO_RVALUE_REFERENCES)
  52.509 +    #if !defined(OVR_CPP11_ENABLED) || \
  52.510 +        (!(defined(__clang__) && OVR_CC_HAS_FEATURE(cxx_rvalue_references)) /* clang    */ && \
  52.511 +         !(defined(__GNUC__) && (OVR_CC_VERSION >= 405))                    /* GCC 4.5+ */ && \
  52.512 +         !(defined(_MSC_VER) && (_MSC_VER >= 1600))                         /* VS2010+  */ && \
  52.513 +         !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 403)))           /* EDG 4.3+ */    
  52.514 +        #define OVR_CPP_NO_RVALUE_REFERENCES 1
  52.515 +    #endif
  52.516 +#endif
  52.517 +
  52.518 +
  52.519 +//-----------------------------------------------------------------------------------
  52.520 +// ***** OVR_CPP_NO_AUTO
  52.521 +// 
  52.522 +// Defined as 1 if the compiler doesn't support C++11 auto keyword. Otherwise undefined.
  52.523 +
  52.524 +#if !defined(OVR_CPP_NO_AUTO)
  52.525 +    #if !defined(OVR_CPP11_ENABLED) || \
  52.526 +        (!(defined(__clang__) && OVR_CC_HAS_FEATURE(cxx_auto_type))  /* clang     */ && \
  52.527 +         !(defined(__GNUC__) && (OVR_CC_VERSION >= 404))             /* GCC 4.4+  */ && \
  52.528 +         !(defined(_MSC_VER) && (_MSC_VER >= 1600))                  /* VS2010+   */ && \
  52.529 +         !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 309)))    /* EDG 3.9+  */  
  52.530 +        #define OVR_CPP_NO_AUTO 1
  52.531 +    #endif
  52.532 +#endif
  52.533 +
  52.534 +
  52.535 +//-----------------------------------------------------------------------------------
  52.536 +// ***** OVR_CPP_NO_RANGE_BASED_FOR_LOOP
  52.537 +//
  52.538 +// Defined as 1 if the compiler doesn't support C++11 range-based for loops.
  52.539 +// Otherwise undefined.
  52.540 +
  52.541 +#if !defined(OVR_CPP_NO_RANGE_BASED_FOR_LOOP)
  52.542 +    #if !defined(OVR_CPP11_ENABLED) || \
  52.543 +        (!(defined(__clang__) && OVR_CC_HAS_FEATURE(cxx_range_for)) /* clang    */ && \
  52.544 +         !(defined(__GNUC__) && (OVR_CC_VERSION >= 406))            /* GCC 4.6+ */ && \
  52.545 +         !(defined(_MSC_VER) && (_MSC_VER >= 1700))                 /* VS2012+  */ && \
  52.546 +         !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 405)))   /* EDG 4.5+ */    
  52.547 +        #define OVR_CPP_NO_RANGE_BASED_FOR_LOOP 1
  52.548 +    #endif
  52.549 +#endif
  52.550 +
  52.551 +
  52.552 +//-----------------------------------------------------------------------------------
  52.553 +// ***** OVR_CPP_NO_CONSTEXPR / OVR_CPP_NO_RELAXED_CONSTEXPR
  52.554 +//
  52.555 +// OVR_CPP_NO_CONSTEXPR is defined as 1 if the compiler doesn't support C++11 constexpr.
  52.556 +// OVR_CPP_NO_RELAXED_CONSTEXPR is defined as 1 if the compiler doesn't support C++14 constexpr.
  52.557 +// Otherwise undefined.
  52.558 +// See the OVR_CONSTEXPR / OVR_CONSTEXPR_OR_CONST macros for portable wrappers of this functionality.
  52.559 +
  52.560 +#if !defined(OVR_CPP_NO_CONSTEXPR)
  52.561 +    #if !defined(OVR_CPP11_ENABLED) || \
  52.562 +        (!(defined(__clang__) && OVR_CC_HAS_FEATURE(cxx_constexpr))  /* clang    */ && \
  52.563 +         !(defined(__GNUC__) && (OVR_CC_VERSION >= 406))             /* GCC 4.6+ */ && \
  52.564 +         !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 406)))    /* EDG 4.6+ */    
  52.565 +        // Not supported by VC++ through at least VS2013.
  52.566 +        #define OVR_CPP_NO_CONSTEXPR 1
  52.567 +    #endif
  52.568 +#endif
  52.569 +
  52.570 +#if !defined(OVR_CPP_NO_RELAXED_CONSTEXPR)
  52.571 +    #if !defined(OVR_CPP14_ENABLED) || \
  52.572 +        !(defined(__clang__) && OVR_CC_HAS_FEATURE(cxx_relaxed_constexpr)) /* clang */
  52.573 +        // Supported only by clang as of this writing.
  52.574 +        #define OVR_CPP_NO_RELAXED_CONSTEXPR 1
  52.575 +    #endif
  52.576 +#endif
  52.577 +
  52.578 +
  52.579 +//-----------------------------------------------------------------------------------
  52.580 +// ***** OVR_CPP_NO_LAMBDA_EXPRESSIONS
  52.581 +//
  52.582 +// Defined as 1 if the compiler doesn't support C++11 lambda expressions. Otherwise undefined.
  52.583 +// Some compilers have slightly crippled versions of this.
  52.584 +
  52.585 +#if !defined(OVR_CPP_NO_LAMBDA_EXPRESSIONS)
  52.586 +    #if !defined(OVR_CPP11_ENABLED) || \
  52.587 +        (!(defined(__clang__) && OVR_CC_HAS_FEATURE(cxx_lambdas))  /* clang     */ && \
  52.588 +         !(defined(__GNUC__) && (OVR_CC_VERSION >= 404))           /* GCC 4.4+  */ && \
  52.589 +         !(defined(_MSC_VER) && (_MSC_VER >= 1600))                /* VS2010+   */ && \
  52.590 +         !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 401)))  /* EDG 4.1+  */ 
  52.591 +        // Conversion of lambdas to function pointers is not supported until EDG 4.5.
  52.592 +        #define OVR_CPP_NO_LAMBDA_EXPRESSIONS 1
  52.593 +    #endif
  52.594 +#endif
  52.595 +
  52.596 +
  52.597 +//-----------------------------------------------------------------------------------
  52.598 +// ***** OVR_CPP_NO_ALIGNOF
  52.599 +//
  52.600 +// Defined as 1 if the compiler supports C++11 alignof. Otherwise undefined.
  52.601 +// Some compilers support __alignof__ instead of alignof, so for portability you 
  52.602 +// should use OVR_ALIGNOF instead of directly using C++11 alignof.
  52.603 +
  52.604 +#if !defined(OVR_CPP_NO_ALIGNOF)
  52.605 +    #if !defined(OVR_CPP11_ENABLED) || \
  52.606 +        (!(defined(__clang__) && !defined(__APPLE__) && (__clang__ >= 209))  /* clang 2.9+       */ && \
  52.607 +         !(defined(__clang__) &&  defined(__APPLE__) && (__clang__ >= 300))  /* Apple clang 3.0+ */ && \
  52.608 +         !(defined(__GNUC__) && (OVR_CC_VERSION >= 401))                     /* GCC 4.1+         */ && \
  52.609 +         !(defined(_MSC_VER) && (_MSC_VER >= 1900))                          /* VS2014+          */ && \
  52.610 +         !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 400)))            /* EDG 4.0+         */
  52.611 +        #define OVR_CPP_NO_ALIGNOF 1
  52.612 +    #endif
  52.613 +#endif
  52.614 +
  52.615 +
  52.616 +//-----------------------------------------------------------------------------------
  52.617 +// ***** OVR_CPP_NO_ALIGNAS
  52.618 +//
  52.619 +// Defined as 1 if the compiler supports C++11 alignas. Otherwise undefined.
  52.620 +// See the OVR_ALIGNAS for a portable wrapper for alignas functionality.
  52.621 +
  52.622 +#if !defined(OVR_CPP_NO_ALIGNAS)
  52.623 +    #if !defined(OVR_CPP11_ENABLED) || \
  52.624 +        (!(defined(__clang__) && !defined(__APPLE__) && (__clang__ >= 300))  /* clang 3.0+       */ && \
  52.625 +         !(defined(__clang__) &&  defined(__APPLE__) && (__clang__ >= 401))  /* Apple clang 4.1+ */ && \
  52.626 +         !(defined(__GNUC__) && (OVR_CC_VERSION >= 408))                     /* GCC 4.8+         */ && \
  52.627 +         !(defined(_MSC_VER) && (_MSC_VER >= 1900))                          /* VS2014+          */ && \
  52.628 +         !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 408)))            /* EDG 4.8+         */
  52.629 +        #define OVR_CPP_NO_ALIGNAS 1
  52.630 +    #endif
  52.631 +#endif
  52.632 +
  52.633 +
  52.634 +//-----------------------------------------------------------------------------------
  52.635 +// ***** OVR_CPP_NO_OVERRIDE
  52.636 +//
  52.637 +// Defined as 1 if the compiler doesn't support C++11 override. Otherwise undefined.
  52.638 +// See the OVR_OVERRIDE and OVR_FINALOVERRIDE macros for a portable wrapper.
  52.639 +
  52.640 +#if !defined(OOVR_CPP_NO_OVERRIDE)
  52.641 +    #if !defined(OVR_CPP11_ENABLED) || \
  52.642 +        (!(defined(__clang__) && !defined(__APPLE__) && (__clang__ >= 209)) /* clang 2.9+       */ && \
  52.643 +         !(defined(__clang__) &&  defined(__APPLE__) && (__clang__ >= 400)) /* Apple clang 4.0+ */ && \
  52.644 +         !(defined(__GNUC__) && (OVR_CC_VERSION >= 407))                    /* GCC 4.7+         */ && \
  52.645 +         !(defined(_MSC_VER) && (_MSC_VER >= 1500))                         /* VS2008+          */ && \
  52.646 +         !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 408)))           /* EDG 4.8+         */     
  52.647 +        #define OVR_CPP_NO_OVERRIDE 1
  52.648 +    #endif
  52.649 +#endif
  52.650 +
  52.651 +
  52.652 +//-----------------------------------------------------------------------------------
  52.653 +// ***** OVR_CPP_NO_FINAL
  52.654 +// 
  52.655 +// Defined as 1 if the compiler doesn't support C++11 final attribute. Otherwise undefined.
  52.656 +// See the OVR_FINAL and OVR_FINALOVERRIDE macros for a portable wrapper.
  52.657 +
  52.658 +#if !defined(OOVR_CPP_NO_FINAL)
  52.659 +    #if !defined(OVR_CPP11_ENABLED) || \
  52.660 +        (!(defined(__clang__) && !defined(__APPLE__) && (__clang__ >= 209))  /* clang 2.9+       */ && \
  52.661 +         !(defined(__clang__) &&  defined(__APPLE__) && (__clang__ >= 400))  /* Apple clang 4.0+ */ && \
  52.662 +         !(defined(__GNUC__) && (OVR_CC_VERSION >= 407))                     /* GCC 4.7+         */ && \
  52.663 +         !(defined(_MSC_VER) && (_MSC_VER >= 1500))                          /* VS2008+          */ && \
  52.664 +         !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 408)))            /* EDG 4.8+         */    
  52.665 +        #define OVR_CPP_NO_FINAL 1
  52.666 +    #endif
  52.667 +#endif
  52.668 +
  52.669 +
  52.670 +//-----------------------------------------------------------------------------------
  52.671 +// ***** OVR_CPP_NO_EXTERN_TEMPLATE
  52.672 +//
  52.673 +// Defined as 1 if the compiler doesn't support C++11 extern template.
  52.674 +// Otherwise undefined. See OVR_EXTERN_TEMPLATE for wrapper macro.
  52.675 +
  52.676 +#if !defined(OVR_CPP_NO_EXTERN_TEMPLATE)
  52.677 +    #if !defined(OVR_CPP11_ENABLED) || \
  52.678 +        (!(defined(__clang__) && !defined(__APPLE__) && (__clang__ >= 209))  /* clang 2.9+       */ && \
  52.679 +         !(defined(__clang__) &&  defined(__APPLE__) && (__clang__ >= 401))  /* Apple clang 4.1+ */ && \
  52.680 +         !(defined(__GNUC__) && (OVR_CC_VERSION >= 406))                     /* GCC 4.6+         */ && \
  52.681 +         !(defined(_MSC_VER) && (_MSC_VER >= 1700))                          /* VS2012+          */ && \
  52.682 +         !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 401)))            /* EDG 4.1+         */ 
  52.683 +        #define OVR_CPP_NO_EXTERN_TEMPLATE 1
  52.684 +    #endif
  52.685 +#endif
  52.686 +
  52.687 +
  52.688 +//-----------------------------------------------------------------------------------
  52.689 +// ***** OVR_CPP_NO_VARIADIC_TEMPLATES
  52.690 +//
  52.691 +// Defined as 1 if the compiler doesn't support C++11 variadic templates. Otherwise undefined.
  52.692 +
  52.693 +#if !defined(OVR_CPP_NO_VARIADIC_TEMPLATES)
  52.694 +    #if !defined(OVR_CPP11_ENABLED) || \
  52.695 +        (!(defined(__clang__) && OVR_CC_HAS_FEATURE(cxx_variadic_templates)) /* clang     */ && \
  52.696 +         !(defined(__GNUC__) && (OVR_CC_VERSION >= 404))                     /* GCC 4.4+  */ && \
  52.697 +         !(defined(_MSC_VER) && (_MSC_VER >= 1800))                          /* VS2013+   */ && \
  52.698 +         !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 403)))            /* EDG 4.3+  */   
  52.699 +        #define OVR_CPP_NO_VARIADIC_TEMPLATES 1
  52.700 +    #endif
  52.701 +#endif
  52.702 +
  52.703 +
  52.704 +//-----------------------------------------------------------------------------------
  52.705 +// ***** OVR_CPP_NO_NOEXCEPT
  52.706 +//
  52.707 +// Defined as 1 if the compiler supports C++11 noexcept. Otherwise undefined.
  52.708 +// http://en.cppreference.com/w/cpp/language/noexcept
  52.709 +// See OVR_NOEXCEPT / OVR_NOEXCEPT_IF / OVR_NOEXCEPT_EXPR for a portable wrapper
  52.710 +// for noexcept functionality.
  52.711 +
  52.712 +#if !defined(OVR_CPP_NO_NOEXCEPT)
  52.713 +    #if !defined(OVR_CPP11_ENABLED) || \
  52.714 +        (!(defined(__clang__) && OVR_CC_HAS_FEATURE(cxx_noexcept))  /* clang     */ && \
  52.715 +         !(defined(__GNUC__) && (OVR_CC_VERSION >= 406))            /* GCC 4.6+  */ && \
  52.716 +         !(defined(_MSC_VER) && (_MSC_VER >= 1900))                 /* VS2014+   */ && \
  52.717 +         !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 405)))   /* EDG 4.5+  */
  52.718 +        #define OVR_CPP_NO_NOEXCEPT 1
  52.719 +    #endif
  52.720 +#endif
  52.721 +
  52.722 +
  52.723 +//-----------------------------------------------------------------------------------
  52.724 +// ***** OVR_CPP_NO_DECLTYPE
  52.725 +//
  52.726 +// Defined as 1 if the compiler doesn't support C++11 decltype. Otherwise undefined.
  52.727 +// Some compilers (e.g. VS2012) support most uses of decltype but don't support 
  52.728 +// decltype with incomplete types (which is an uncommon usage seen usually in 
  52.729 +// template metaprogramming).  We don't include this support as a requirement for
  52.730 +// our definition of decltype support here.
  52.731 +
  52.732 +#if !defined(OVR_CPP_NO_DECLTYPE)
  52.733 +    #if !defined(OVR_CPP11_ENABLED) || \
  52.734 +        (!(defined(__clang__) && OVR_CC_HAS_FEATURE(cxx_decltype))  /* clang     */ && \
  52.735 +         !(defined(__GNUC__) && (OVR_CC_VERSION >= 403))            /* GCC 4.3+  */ && \
  52.736 +         !(defined(_MSC_VER) && (_MSC_VER >= 1600))                 /* VS2010+   */ && \
  52.737 +         !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 402)))   /* EDG 4.2+  */       
  52.738 +        // VC++ fails to support decltype for incomplete types until VS2013.
  52.739 +        // EDG fails to support decltype for incomplete types until v4.8.
  52.740 +        #define OVR_CPP_NO_DECLTYPE 1
  52.741 +    #endif
  52.742 +#endif  
  52.743 +
  52.744 +
  52.745 +//-----------------------------------------------------------------------------------
  52.746 +// ***** OVR_CPP_NO_DEFAULTED_FUNCTIONS
  52.747 +// 
  52.748 +// Defined as 1 if the compiler doesn't support C++11 defaulted functions. Otherwise undefined.
  52.749 +// Some compilers have slightly crippled versions of this.
  52.750 +
  52.751 +#if !defined(OVR_CPP_NO_DEFAULTED_FUNCTIONS)
  52.752 +    #if !defined(OVR_CPP11_ENABLED) || \
  52.753 +        (!(defined(__clang__) && OVR_CC_HAS_FEATURE(cxx_defaulted_functions))/* clang    */ && \
  52.754 +         !(defined(__GNUC__) && (OVR_CC_VERSION >= 404))                     /* GCC 4.4+ */ && \
  52.755 +         !(defined(_MSC_VER) && (_MSC_VER >= 1800))                          /* VS2013+  */ && \
  52.756 +         !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 401)))            /* EDG 4.1+ */
  52.757 +        // Up through at least VS2013 it's unsupported for defaulted move constructors and move assignment operators.
  52.758 +        // Until EDG 4.8 it's unsupported for defaulted move constructors and move assigment operators.
  52.759 +        #define OVR_CPP_NO_DEFAULTED_FUNCTIONS 1
  52.760 +    #endif
  52.761 +#endif
  52.762 +
  52.763 +
  52.764 +//-----------------------------------------------------------------------------------
  52.765 +// ***** OVR_CPP_NO_DELETED_FUNCTIONS
  52.766 +// 
  52.767 +// Defined as 1 if the compiler doesn't support C++11 deleted functions. Otherwise undefined.
  52.768 +// Some compilers have slightly crippled versions of this.
  52.769 +
  52.770 +#if !defined(OVR_CPP_NO_DELETED_FUNCTIONS)
  52.771 +    #if !defined(OVR_CPP11_ENABLED) || \
  52.772 +        (!(defined(__clang__) && OVR_CC_HAS_FEATURE(cxx_defaulted_functions)) /* clang    */ && \
  52.773 +         !(defined(__GNUC__) && (OVR_CC_VERSION >= 404))                      /* GCC 4.4+ */ && \
  52.774 +         !(defined(_MSC_VER) && (_MSC_VER >= 1800))                           /* VS2013+  */ && \
  52.775 +         !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 401)))             /* EDG 4.1+ */  
  52.776 +        // Up through at least VS2013 it's unsupported for defaulted move constructors and move assignment operators.
  52.777 +        // Until EDG 4.8 it's unsupported for defaulted move constructors and move assigment operators.
  52.778 +        #define OVR_CPP_NO_DELETED_FUNCTIONS 1
  52.779 +    #endif
  52.780 +#endif
  52.781 +
  52.782 +
  52.783 +//-----------------------------------------------------------------------------------
  52.784 +// ***** OVR_CPP_NO_STANDARD_LAYOUT_TYPES
  52.785 +// 
  52.786 +// Defined as 1 if the compiler doesn't support C++11 standard layout (relaxed POD). Otherwise undefined.
  52.787 +// http://en.cppreference.com/w/cpp/types/is_standard_layout
  52.788 +
  52.789 +#if !defined(OVR_CPP_NO_STANDARD_LAYOUT_TYPES)
  52.790 +    #if !defined(OVR_CPP11_ENABLED) || \
  52.791 +        (!(defined(__clang__) && !defined(__APPLE__) && (__clang__ >= 300)) /* clang 3.0+       */ && \
  52.792 +         !(defined(__clang__) &&  defined(__APPLE__) && (__clang__ >= 401)) /* Apple clang 4.1+ */ && \
  52.793 +         !(defined(__GNUC__) && (OVR_CC_VERSION >= 405))                    /* GCC 4.5+         */ && \
  52.794 +         !(defined(_MSC_VER) && (_MSC_VER >= 1700))                         /* VS2013+          */ && \
  52.795 +         !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 406)))           /* EDG 4.6+         */  
  52.796 +        #define OVR_CPP_NO_STANDARD_LAYOUT_TYPES 1
  52.797 +    #endif
  52.798 +#endif
  52.799 +
  52.800 +
  52.801 +//-----------------------------------------------------------------------------------
  52.802 +// ***** OVR_CPP_NO_FORWARD_DECLARED_ENUMS
  52.803 +//
  52.804 +// Defined as 1 if the compiler doesn't support C++11 forward declared enums. Otherwise undefined.
  52.805 +
  52.806 +#if !defined(OVR_CPP_NO_FORWARD_DECLARED_ENUMS)
  52.807 +    #if !defined(OVR_CPP11_ENABLED) || \
  52.808 +        (!(defined(__clang__) && !defined(__APPLE__) && (__clang__ >= 301))  /* clang 3.1+       */ && \
  52.809 +         !(defined(__clang__) &&  defined(__APPLE__) && (__clang__ >= 401))  /* Apple clang 4.1+ */ && \
  52.810 +         !(defined(__GNUC__) && (OVR_CC_VERSION >= 406))                     /* GCC 4.6+         */ && \
  52.811 +         !(defined(_MSC_VER) && (_MSC_VER >= 1700))                          /* VS2012+          */ && \
  52.812 +         !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 405)))            /* EDG 4.5+         */ 
  52.813 +        #define OVR_CPP_NO_FORWARD_DECLARED_ENUMS 1
  52.814 +    #endif
  52.815 +#endif
  52.816 +
  52.817 +
  52.818 +//-----------------------------------------------------------------------------------
  52.819 +// ***** OVR_CPP_NO_STRONGLY_TYPED_ENUMS
  52.820 +//
  52.821 +// Defined as 1 if the compiler doesn't support C++11 strongly typed enums. Otherwise undefined.
  52.822 +
  52.823 +#if !defined(OVR_CPP_NO_STRONGLY_TYPED_ENUMS)
  52.824 +    #if !defined(OVR_CPP11_ENABLED) || \
  52.825 +        (!(defined(__clang__) && OVR_CC_HAS_FEATURE(cxx_strong_enums))  /* clang     */ && \
  52.826 +         !(defined(__GNUC__) && (OVR_CC_VERSION >= 404))                /* GCC 4.4+  */ && \
  52.827 +         !(defined(_MSC_VER) && (_MSC_VER >= 1700))                     /* VS2012+   */ && \
  52.828 +         !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 400)))       /* EDG 4.0+ */ 
  52.829 +        #define OVR_CPP_NO_STRONGLY_TYPED_ENUMS 1
  52.830 +    #endif
  52.831 +#endif
  52.832 +
  52.833 +
  52.834 +//-----------------------------------------------------------------------------------
  52.835 +// ***** OVR_CPP_NO_TRAILING_RETURN_TYPES
  52.836 +//
  52.837 +// Defined as 1 if the compiler doesn't support C++11 trailing return types. Otherwise undefined.
  52.838 +// http://en.wikipedia.org/wiki/C%2B%2B11#Alternative_function_syntax
  52.839 +
  52.840 +#if !defined(OVR_CPP_NO_TRAILING_RETURN_TYPES)
  52.841 +    #if !defined(OVR_CPP11_ENABLED) || \
  52.842 +        (!(defined(__clang__) && OVR_CC_HAS_FEATURE(cxx_trailing_return)) /* clang     */ && \
  52.843 +         !(defined(__GNUC__) && (OVR_CC_VERSION >= 404))                  /* GCC 4.4+  */ && \
  52.844 +         !(defined(_MSC_VER) && (_MSC_VER >= 1600))                       /* VS2010+   */ && \
  52.845 +         !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 401)))         /* EDG 4.1+ */    
  52.846 +        #define OVR_CPP_NO_TRAILING_RETURN_TYPES 1
  52.847 +    #endif
  52.848 +#endif
  52.849 +
  52.850 +
  52.851 +//-----------------------------------------------------------------------------------
  52.852 +// ***** OVR_CPP_NO_TEMPLATE_ALIASES
  52.853 +//
  52.854 +// Defined as 1 if the compiler doesn't support C++11 template aliases. Otherwise undefined.
  52.855 +
  52.856 +#if !defined(OVR_CPP_NO_TEMPLATE_ALIASES)
  52.857 +    #if !defined(OVR_CPP11_ENABLED) || \
  52.858 +        (!(defined(__clang__) && OVR_CC_HAS_FEATURE(cxx_alias_templates)) /* clang     */ && \
  52.859 +         !(defined(__GNUC__) && (OVR_CC_VERSION >= 407))                  /* GCC 4.7+  */ && \
  52.860 +         !(defined(_MSC_VER) && (_MSC_VER >= 1800))                       /* VS2013+   */ && \
  52.861 +         !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 402)))         /* EDG 4.2+  */ 
  52.862 +        #define OVR_CPP_NO_TEMPLATE_ALIASES 1
  52.863 +    #endif
  52.864 +#endif
  52.865 +
  52.866 +
  52.867 +//-----------------------------------------------------------------------------------
  52.868 +// ***** OVR_CPP_NO_INITIALIZER_LISTS
  52.869 +//
  52.870 +// Defined as 1 if the compiler doesn't support C++11 initializer lists. Otherwise undefined.
  52.871 +// This refers to the compiler support for this and not the Standard Library support for std::initializer_list,
  52.872 +// as a new compiler with an old standard library (e.g. Apple clang with libstdc++) may not support std::initializer_list.
  52.873 +
  52.874 +#if !defined(OVR_CPP_NO_INITIALIZER_LISTS)
  52.875 +    #if !defined(OVR_CPP11_ENABLED) || \
  52.876 +        (!(defined(__clang__) && OVR_CC_HAS_FEATURE(cxx_generalized_initializers)) /* clang     */ && \
  52.877 +         !(defined(__GNUC__) && (OVR_CC_VERSION >= 404))                           /* GCC 4.4+  */ && \
  52.878 +         !(defined(_MSC_VER) && (_MSC_VER >= 1800))                                /* VS2013+   */ && \
  52.879 +         !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 405)))                  /* EDG 4.5+  */
  52.880 +        #define OVR_CPP_NO_INITIALIZER_LISTS 1
  52.881 +    #endif
  52.882 +#endif
  52.883 +
  52.884 +
  52.885 +//-----------------------------------------------------------------------------------
  52.886 +// ***** OVR_CPP_NO_NORETURN
  52.887 +//
  52.888 +// Defined as 1 if the compiler doesn't support the C++11 noreturn attribute. Otherwise undefined.
  52.889 +// http://en.cppreference.com/w/cpp/language/attributes
  52.890 +//
  52.891 +#if !defined(OVR_CPP_NO_NORETURN)
  52.892 +    #if !defined(OVR_CPP11_ENABLED) || \
  52.893 +        (!(defined(__clang__) && !defined(__APPLE__) && (__clang__ >= 301))  /* clang 3.1+       */ && \
  52.894 +         !(defined(__clang__) &&  defined(__APPLE__) && (__clang__ >= 401))  /* Apple clang 4.1+ */ && \
  52.895 +         !(defined(__GNUC__) && (OVR_CC_VERSION >= 408))                     /* GCC 4.8+         */ && \
  52.896 +         !(defined(_MSC_VER) && (_MSC_VER >= 1500))                          /* VS2008+          */ && \
  52.897 +         !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 402)))            /* EDG 4.2+         */
  52.898 +        // Supported with VC++ only via __declspec(noreturn) (see OVR_NORETURN).
  52.899 +        #define OVR_CPP_NO_NORETURN 1
  52.900 +    #endif
  52.901 +#endif
  52.902 +
  52.903 +
  52.904 +//-----------------------------------------------------------------------------------
  52.905 +// ***** OVR_CPP_NO_NONSTATIC_MEMBER_INITIALIZERS
  52.906 +//
  52.907 +// Defined as 1 if the compiler doesn't support C++11 in-class non-static member initializers. Otherwise undefined.
  52.908 +// http://en.cppreference.com/w/cpp/language/data_members
  52.909 +
  52.910 +#if !defined(OVR_CPP_NO_NONSTATIC_MEMBER_INITIALIZERS)
  52.911 +    #if !defined(OVR_CPP11_ENABLED) || \
  52.912 +        (!(defined(__clang__) && !defined(__APPLE__) && (__clang__ >= 301))  /* clang 3.1+       */ && \
  52.913 +         !(defined(__clang__) &&  defined(__APPLE__) && (__clang__ >= 401))  /* Apple clang 4.1+ */ && \
  52.914 +         !(defined(__GNUC__) && (OVR_CC_VERSION >= 407))                     /* GCC 4.7+         */ && \
  52.915 +         !(defined(_MSC_VER) && (_MSC_VER >= 1800))                          /* VS2013+          */ && \
  52.916 +         !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 406)))            /* EDG 4.6+         */
  52.917 +        #define OVR_CPP_NO_NONSTATIC_MEMBER_INITIALIZERS 1
  52.918 +    #endif
  52.919 +#endif
  52.920 +
  52.921 +
  52.922 +//-----------------------------------------------------------------------------------
  52.923 +// ***** OVR_CPP_NO_DOUBLE_TEMPLATE_BRACKETS
  52.924 +//
  52.925 +// Defined as 1 if the compiler supports nested template declarations with >>, 
  52.926 +// as supported by C++11. Otherwise undefined.
  52.927 +
  52.928 +#if !defined(OVR_CPP_NO_DOUBLE_TEMPLATE_ANGLE_BRACKETS)
  52.929 +    #if !defined(OVR_CPP11_ENABLED) || \
  52.930 +        (!(defined(__clang__) && !defined(__APPLE__) && (__clang__ >= 209))  /* clang 2.9+       */ && \
  52.931 +         !(defined(__clang__) &&  defined(__APPLE__) && (__clang__ >= 400))  /* Apple clang 4.0+ */ && \
  52.932 +         !(defined(__GNUC__) && (OVR_CC_VERSION >= 403))                     /* GCC 4.3+         */ && \
  52.933 +         !(defined(_MSC_VER) && (_MSC_VER >= 1600))                          /* VS2010+          */ && \
  52.934 +         !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 401)))            /* EDG 4.1+         */
  52.935 +        #define OVR_CPP_NO_DOUBLE_TEMPLATE_BRACKETS 1
  52.936 +    #endif
  52.937 +#endif
  52.938 +
  52.939 +
  52.940 +
  52.941 +//-----------------------------------------------------------------------------------
  52.942 +// ***** OVR_CPP_NO_INHERITING_CONSTRUCTORS
  52.943 +//
  52.944 +// Defined as 1 if the compiler supports C++11 inheriting constructors. Otherwise undefined.
  52.945 +// Example usage:
  52.946 +//     struct A { explicit A(int x){} };
  52.947 +//     struct B : public A { using A::A; }; // As if B redeclared A::A(int).
  52.948 +
  52.949 +#if !defined(OVR_CPP_NO_INHERITING_CONSTRUCTORS)
  52.950 +    #if !defined(OVR_CPP11_ENABLED) || \
  52.951 +        (!(defined(__clang__) && OVR_CC_HAS_FEATURE(cxx_inheriting_constructors))  /* clang     */ && \
  52.952 +         !(defined(__GNUC__) && (OVR_CC_VERSION >= 408))                           /* GCC 4.8+  */ && \
  52.953 +         !(defined(_MSC_VER) && (_MSC_VER >= 1900))                                /* VS2014+   */ && \
  52.954 +         !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 408)))                  /* EDG 4.8+  */
  52.955 +        #define OVR_CPP_NO_INHERITING_CONSTRUCTORS 1
  52.956 +    #endif
  52.957 +#endif
  52.958 +
  52.959 +
  52.960 +//-----------------------------------------------------------------------------------
  52.961 +// ***** OVR_CPP_NO_DELEGATING_CONSTRUCTORS
  52.962 +//
  52.963 +// Defined as 1 if the compiler supports C++11 delegating constructors. Otherwise undefined.
  52.964 +
  52.965 +#if !defined(OVR_CPP_NO_DELEGATING_CONSTRUCTORS)
  52.966 +    #if !defined(OVR_CPP11_ENABLED) || \
  52.967 +        (!(defined(__clang__) && !defined(__APPLE__) && (__clang__ >= 300))  /* clang 3.0+       */ && \
  52.968 +         !(defined(__clang__) &&  defined(__APPLE__) && (__clang__ >= 401))  /* Apple clang 4.1+ */ && \
  52.969 +         !(defined(__GNUC__) && (OVR_CC_VERSION >= 407))                     /* GCC 4.7+         */ && \
  52.970 +         !(defined(_MSC_VER) && (_MSC_VER >= 1800))                          /* VS2013+          */ && \
  52.971 +         !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 407)))            /* EDG 4.7+         */
  52.972 +        #define OVR_CPP_NO_DELEGATING_CONSTRUCTORS 1
  52.973 +    #endif
  52.974 +#endif
  52.975 +
  52.976 +
  52.977 +//-----------------------------------------------------------------------------------
  52.978 +// ***** OVR_CPP_NO_FUNCTION_TEMPLATE_DEFAULT_ARGS
  52.979 +//  
  52.980 +// Defined as 1 if the compiler supports C++11 function template default arguments. Otherwise undefined.
  52.981 +
  52.982 +#if !defined(OVR_CPP_NO_FUNCTION_TEMPLATE_DEFAULT_ARGS)
  52.983 +    #if !defined(OVR_CPP11_ENABLED) || \
  52.984 +        (!(defined(__clang__) && !defined(__APPLE__) && (__clang__ >= 209))  /* clang 2.9+       */ && \
  52.985 +         !(defined(__clang__) &&  defined(__APPLE__) && (__clang__ >= 401))  /* Apple clang 4.0+ */ && \
  52.986 +         !(defined(__GNUC__) && (OVR_CC_VERSION >= 403))                     /* GCC 4.3+         */ && \
  52.987 +         !(defined(_MSC_VER) && (_MSC_VER >= 1800))                          /* VS2013+          */ && \
  52.988 +         !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 403)))            /* EDG 4.3+         */
  52.989 +        #define OVR_CPP_NO_FUNCTION_TEMPLATE_DEFAULT_ARGS 1
  52.990 +    #endif
  52.991 +#endif
  52.992 +
  52.993 +
  52.994 +//-----------------------------------------------------------------------------------
  52.995 +// ***** OVR_CPP_NO_UNRESTRICTED_UNIONS
  52.996 +//
  52.997 +// Defined as 1 if the compiler supports C++11 unrestricted unions. Otherwise undefined.
  52.998 +
  52.999 +#if !defined(OVR_CPP_NO_UNRESTRICTED_UNIONS)
 52.1000 +    #if !defined(OVR_CPP11_ENABLED) || \
 52.1001 +        (!(defined(__clang__) && !defined(__APPLE__) && (__clang__ >= 301))  /* clang 3.1+       */ && \
 52.1002 +         !(defined(__clang__) &&  defined(__APPLE__) && (__clang__ >= 401))  /* Apple clang 4.1+ */ && \
 52.1003 +         !(defined(__GNUC__) && (OVR_CC_VERSION >= 406))                     /* GCC 4.6+         */ && \
 52.1004 +         !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 406)))            /* EDG 4.6+         */
 52.1005 +        // Not supported by VC++ as of VS2013.
 52.1006 +        #define OVR_CPP_NO_UNRESTRICTED_UNIONS 1
 52.1007 +    #endif
 52.1008 +#endif
 52.1009 +
 52.1010 +
 52.1011 +
 52.1012 +//-----------------------------------------------------------------------------------
 52.1013 +// ***** OVR_CPP_NO_EXTENDED_SIZEOF
 52.1014 +//
 52.1015 +// Defined as 1 if the compiler supports C++11 class sizeof extensions (e.g. sizeof SomeClass::someMember). 
 52.1016 +// Otherwise undefined.
 52.1017 +
 52.1018 +#if !defined(OVR_CPP_NO_EXTENDED_SIZEOF)
 52.1019 +    #if !defined(OVR_CPP11_ENABLED) || \
 52.1020 +        (!(defined(__clang__) && !defined(__APPLE__) && (__clang__ >= 301))  /* clang 3.1+       */ && \
 52.1021 +         !(defined(__clang__) &&  defined(__APPLE__) && (__clang__ >= 401))  /* Apple clang 4.1+ */ && \
 52.1022 +         !(defined(__GNUC__) && (OVR_CC_VERSION >= 405))                     /* GCC 4.5+         */ && \
 52.1023 +         !(defined(_MSC_VER) && (_MSC_VER >= 1900))                          /* VS2014+          */ && \
 52.1024 +         !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 405)))            /* EDG 4.5+         */
 52.1025 +        #define OVR_CPP_NO_EXTENDED_SIZEOF 1
 52.1026 +    #endif
 52.1027 +#endif
 52.1028 +
 52.1029 +
 52.1030 +//-----------------------------------------------------------------------------------
 52.1031 +// ***** OVR_CPP_NO_INLINE_NAMESPACES
 52.1032 +//
 52.1033 +// Defined as 1 if the compiler supports C++11 inlined namespaces. Otherwise undefined.
 52.1034 +// http://en.cppreference.com/w/cpp/language/namespace#Inline_namespaces
 52.1035 +
 52.1036 +#if !defined(OVR_CPP_NO_INLINE_NAMESPACES)
 52.1037 +    #if !defined(OVR_CPP11_ENABLED) || \
 52.1038 +        (!(defined(__clang__) && !defined(__APPLE__) && (__clang__ >= 209))  /* clang 2.9+       */ && \
 52.1039 +         !(defined(__clang__) &&  defined(__APPLE__) && (__clang__ >= 400))  /* Apple clang 4.0+ */ && \
 52.1040 +         !(defined(__GNUC__) && (OVR_CC_VERSION >= 404))                     /* GCC 4.4+         */ && \
 52.1041 +         !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 405)))            /* EDG 4.5+         */
 52.1042 +        // Not supported by VC++ as of VS2013.
 52.1043 +        #define OVR_CPP_NO_INLINE_NAMESPACES 1
 52.1044 +    #endif
 52.1045 +#endif
 52.1046 +
 52.1047 +
 52.1048 +//-----------------------------------------------------------------------------------
 52.1049 +// ***** OVR_CPP_NO_EXPLICIT_CONVERSION_OPERATORS
 52.1050 +//
 52.1051 +// Defined as 1 if the compiler supports C++11 explicit conversion operators. Otherwise undefined.
 52.1052 +// http://en.cppreference.com/w/cpp/language/explicit
 52.1053 +
 52.1054 +#if !defined(OVR_CPP_NO_EXPLICIT_CONVERSION_OPERATORS)
 52.1055 +    #if !defined(OVR_CPP11_ENABLED) || \
 52.1056 +        (!(defined(__clang__) && OVR_CC_HAS_FEATURE(cxx_explicit_conversions))  /* clang     */ && \
 52.1057 +         !(defined(__GNUC__) && (OVR_CC_VERSION >= 405))                        /* GCC 4.5+  */ && \
 52.1058 +         !(defined(_MSC_VER) && (_MSC_VER >= 1800))                             /* VS2013+   */ && \
 52.1059 +         !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 404)))               /* EDG 4.4+  */
 52.1060 +        #define OVR_CPP_NO_EXPLICIT_CONVERSION_OPERATORS 1
 52.1061 +    #endif
 52.1062 +#endif
 52.1063 +
 52.1064 +
 52.1065 +//-----------------------------------------------------------------------------------
 52.1066 +// ***** OVR_CPP_NO_LOCAL_CLASS_TEMPLATE_PARAMETERS
 52.1067 +//
 52.1068 +// Defined as 1 if the compiler supports C++11 local class template parameters. Otherwise undefined.
 52.1069 +// Example:
 52.1070 +//     void Test() {   
 52.1071 +//         struct LocalClass{ };
 52.1072 +//         SomeTemplateClass<LocalClass> t; // Allowed only in C++11
 52.1073 +//     }
 52.1074 +
 52.1075 +#if !defined(OVR_CPP_NO_LOCAL_CLASS_TEMPLATE_PARAMETERS) 
 52.1076 +    #if !defined(OVR_CPP11_ENABLED) || \
 52.1077 +        (!(defined(__clang__) && OVR_CC_HAS_FEATURE(cxx_local_type_template_args))  /* clang     */ && \
 52.1078 +         !(defined(__GNUC__) && (OVR_CC_VERSION >= 405))                            /* GCC 4.5+  */ && \
 52.1079 +         !(defined(_MSC_VER) && (_MSC_VER >= 1600))                                 /* VS2010+   */ && \
 52.1080 +         !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 402)))                   /* EDG 4.2+  */
 52.1081 +        #define OVR_CPP_NO_LOCAL_CLASS_TEMPLATE_PARAMETERS 1
 52.1082 +    #endif
 52.1083 +#endif
 52.1084 +
 52.1085 +
 52.1086 +//-----------------------------------------------------------------------------------
 52.1087 +// ***** OVR_CPP_NO_NEW_CHARACTER_TYPES
 52.1088 +//
 52.1089 +// Defined as 1 if the compiler natively supports C++11 char16_t and char32_t. Otherwise undefined.
 52.1090 +// VC++ through at least VS2013 defines char16_t as unsigned short in its standard library,
 52.1091 +// but it is not a native type or unique type, nor can you for a string literal with it.
 52.1092 +
 52.1093 +#if !defined(OVR_CPP_NO_NEW_CHARACTER_TYPES)
 52.1094 +    #if !defined(OVR_CPP11_ENABLED) || \
 52.1095 +        (!(defined(__clang__) && OVR_CC_HAS_FEATURE(cxx_unicode_literals))  /* clang     */ && \
 52.1096 +         !(defined(__GNUC__) && (OVR_CC_VERSION >= 404))                    /* GCC 4.4+  */ && \
 52.1097 +         !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 407)))           /* EDG 4.7+  */
 52.1098 +        // Not supported by VC++ as of VS2013.
 52.1099 +        #define OVR_CPP_NO_NEW_CHARACTER_TYPES 1
 52.1100 +    #endif
 52.1101 +#endif
 52.1102 +
 52.1103 +
 52.1104 +//-----------------------------------------------------------------------------------
 52.1105 +// ***** OVR_CPP_NO_UNICODE_CHAR_NAME_LITERALS
 52.1106 +//
 52.1107 +// Defined as 1 if the compiler supports C++11 \u and \U character literals for 
 52.1108 +// native char16_t and char32_t types.
 52.1109 +//
 52.1110 +#if !defined(OVR_CPP_NO_UNICODE_CHAR_NAME_LITERALS)
 52.1111 +    #if !defined(OVR_CPP11_ENABLED) || \
 52.1112 +        (!(defined(__clang__) && !defined(__APPLE__) && (__clang__ >= 301))  /* clang 3.1+       */ && \
 52.1113 +         !(defined(__clang__) &&  defined(__APPLE__) && (__clang__ >= 401))  /* Apple clang 4.1+ */ && \
 52.1114 +         !(defined(__GNUC__) && (OVR_CC_VERSION >= 405))                     /* GCC 4.5+         */ && \
 52.1115 +         !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 408)))            /* EDG 4.8+         */
 52.1116 +        // Not supported by VC++ as of VS2013. VC++'s existing \U and \u are non-conforming.
 52.1117 +        #define OVR_CPP_NO_UNICODE_CHAR_NAME_LITERALS 1
 52.1118 +    #endif
 52.1119 +#endif
 52.1120 +
 52.1121 +
 52.1122 +//-----------------------------------------------------------------------------------
 52.1123 +// ***** OVR_CPP_NO_USER_DEFINED_LITERALS
 52.1124 +//
 52.1125 +// Defined as 1 if the compiler supports C++11 user-defined literals. Otherwise undefined.
 52.1126 +
 52.1127 +#if !defined(OVR_CPP_NO_USER_DEFINED_LITERALS)
 52.1128 +    #if !defined(OVR_CPP11_ENABLED) || \
 52.1129 +        (!(defined(__clang__) && !defined(__APPLE__) && (__clang__ >= 301))  /* clang 3.1+       */ && \
 52.1130 +         !(defined(__clang__) &&  defined(__APPLE__) && (__clang__ >= 401))  /* Apple clang 4.1+ */ && \
 52.1131 +         !(defined(__GNUC__) && (OVR_CC_VERSION >= 407))                     /* GCC 4.7+         */ && \
 52.1132 +         !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 408)))            /* EDG 4.8+         */
 52.1133 +        // Not supported by VC++ as of VS2013.
 52.1134 +        #define OVR_CPP_NO_USER_DEFINED_LITERALS 1
 52.1135 +    #endif
 52.1136 +#endif
 52.1137 +
 52.1138 +
 52.1139 +//-----------------------------------------------------------------------------------
 52.1140 +// ***** OVR_CPP_NO_UNICODE_STRING_LITERALS
 52.1141 +//
 52.1142 +// Defined as 1 if the compiler supports C++11 Unicode string literals. Otherwise undefined.
 52.1143 +// http://en.wikipedia.org/wiki/C%2B%2B11#New_string_literals
 52.1144 +
 52.1145 +#if !defined(OVR_CPP_NO_UNICODE_STRING_LITERALS)
 52.1146 +    #if !defined(OVR_CPP11_ENABLED) || \
 52.1147 +        (!(defined(__clang__) && OVR_CC_HAS_FEATURE(cxx_unicode_literals))  /* clang     */ && \
 52.1148 +         !(defined(__GNUC__) && (OVR_CC_VERSION >= 404))                    /* GCC 4.4+  */ && \
 52.1149 +         !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 407)))           /* EDG 4.7+  */
 52.1150 +        // Not supported by VC++ as of VS2013.
 52.1151 +        #define OVR_CPP_NO_UNICODE_STRING_LITERALS 1
 52.1152 +    #endif
 52.1153 +#endif
 52.1154 +
 52.1155 +
 52.1156 +//-----------------------------------------------------------------------------------
 52.1157 +// ***** OVR_CPP_NO_RAW_STRING_LITERALS
 52.1158 +//
 52.1159 +// Defined as 1 if the compiler supports C++11 raw literals. Otherwise undefined.
 52.1160 +// http://en.wikipedia.org/wiki/C%2B%2B11#New_string_literals
 52.1161 +
 52.1162 +#if !defined(OVR_CPP_NO_RAW_STRING_LITERALS)
 52.1163 +    #if !defined(OVR_CPP11_ENABLED) || \
 52.1164 +        (!(defined(__clang__) && OVR_CC_HAS_FEATURE(cxx_raw_string_literals))  /* clang     */ && \
 52.1165 +         !(defined(__GNUC__) && (OVR_CC_VERSION >= 405))                       /* GCC 4.5+  */ && \
 52.1166 +         !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 407)))              /* EDG 4.7+  */
 52.1167 +        // Not supported by VC++ as of VS2013.
 52.1168 +        #define OVR_CPP_NO_RAW_STRING_LITERALS 1
 52.1169 +    #endif
 52.1170 +#endif
 52.1171 +
 52.1172 +
 52.1173 +//-----------------------------------------------------------------------------------
 52.1174 +// ***** OVR_CPP_NO_UNIFIED_INITIALIZATION_SYNTAX
 52.1175 +//
 52.1176 +// Defined as 1 if the compiler supports C++11 unified initialization.
 52.1177 +// http://en.wikipedia.org/wiki/C%2B%2B11#Uniform_initialization
 52.1178 +
 52.1179 +#if !defined(OVR_CPP_NO_UNIFIED_INITIALIZATION_SYNTAX)
 52.1180 +    #if !defined(OVR_CPP11_ENABLED) || \
 52.1181 +        (!(defined(__clang__) && OVR_CC_HAS_FEATURE(cxx_generalized_initializers))  /* clang     */ && \
 52.1182 +         !(defined(__GNUC__) && (OVR_CC_VERSION >= 404))                            /* GCC 4.4+  */ && \
 52.1183 +         !(defined(_MSC_VER) && (_MSC_VER >= 1800))                                 /* VS2013+   */ && \
 52.1184 +         !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 406)))                   /* EDG 4.6+  */
 52.1185 +        #define OVR_CPP_NO_UNIFIED_INITIALIZATION_SYNTAX 1
 52.1186 +    #endif
 52.1187 +#endif
 52.1188 +
 52.1189 +
 52.1190 +//-----------------------------------------------------------------------------------
 52.1191 +// ***** OVR_CPP_NO_EXTENDED_FRIEND_DECLARATIONS
 52.1192 +//
 52.1193 +// Defined as 1 if the compiler supports C++11 extended friends.
 52.1194 +
 52.1195 +#if !defined(OVR_CPP_NO_EXTENDED_FRIEND_DECLARATIONS)
 52.1196 +    #if !defined(OVR_CPP11_ENABLED) || \
 52.1197 +        (!(defined(__clang__) && !defined(__APPLE__) && (__clang__ >= 209))  /* clang 2.9+       */ && \
 52.1198 +         !(defined(__clang__) &&  defined(__APPLE__) && (__clang__ >= 400))  /* Apple clang 4.0+ */ && \
 52.1199 +         !(defined(__GNUC__) && (OVR_CC_VERSION >= 407))                     /* GCC 4.7+         */ && \
 52.1200 +         !(defined(_MSC_VER) && (_MSC_VER >= 1600))                          /* VS2010+          */ && \
 52.1201 +         !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 401)))            /* EDG 4.1+         */
 52.1202 +        #define OVR_CPP_NO_EXTENDED_FRIEND_DECLARATIONS 1
 52.1203 +    #endif
 52.1204 +#endif
 52.1205 +
 52.1206 +
 52.1207 +//-----------------------------------------------------------------------------------
 52.1208 +// ***** OVR_CPP_NO_THREAD_LOCAL
 52.1209 +//
 52.1210 +// Defined as 1 if the compiler supports C++11 thread_local. Else undefined. Does not
 52.1211 +// indicate if the compiler supports C thread-local compiler extensions such as __thread
 52.1212 +// and declspec(thread). Use OVR_THREAD_LOCAL if you want to declare a thread-local 
 52.1213 +// variable that supports C++11 thread_local when available but the C extension when 
 52.1214 +// it's available. The primary difference between C++11 thread_local and C extensions is
 52.1215 +// that C++11 thread_local supports non-PODs and calls their constructors and destructors.
 52.1216 +//
 52.1217 +// Note that thread_local requires both compiler and linker support, and so it's possible
 52.1218 +// that the compiler may support thread_local but the linker does not.
 52.1219 +
 52.1220 +#if !defined(OVR_CPP_NO_THREAD_LOCAL)
 52.1221 +    #if !defined(OVR_CPP11_ENABLED) || \
 52.1222 +        (!(defined(__clang__) && OVR_CC_HAS_FEATURE(cxx_thread_local))  /* clang     */ && \
 52.1223 +         !(defined(__GNUC__) && (OVR_CC_VERSION >= 408))                /* GCC 4.8+  */ && \
 52.1224 +         !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 408)))       /* EDG 4.8+  */
 52.1225 +        #define OVR_CPP_NO_THREAD_LOCAL 1
 52.1226 +    #endif
 52.1227 +#endif
 52.1228 +
 52.1229 +
 52.1230 +// -----------------------------------------------------------------------------------
 52.1231 +// ***** OVR_ALIGNAS / OVR_ALIGNOF
 52.1232 +//
 52.1233 +//    OVR_ALIGNAS(n)        // Specifies a size_t power of two alignment for a type or instance.
 52.1234 +//    OVR_ALIGNOF(type)     // Returns the size_t alignment of a type or instance.
 52.1235 +//
 52.1236 +// Example usage:
 52.1237 +//    OVR_ALIGNAS(8) char c = 'c';                      // Specifies that the instance c be aligned to an 8 byte boundary.
 52.1238 +//    typedef OVR_ALIGNAS(8) char C;                    // Specifies that the type C be aligned to an 8 byte boundary.
 52.1239 +//    struct OVR_ALIGNAS(64) S{ char array[16]; };      // Specfies that the struct S have a natural alignment of 64.
 52.1240 +//    OVR_ALIGNAS(32) S s;                              // Specifies that the instance s of struct S be aligned to an 32 byte boundary.
 52.1241 +//    OVR_ALIGNAS(32) struct T{ char array[16]; } t;    // Specfies that the instance t of struct T have a natural alignment of 32.
 52.1242 +//    struct OVR_ALIGNAS(T) U{};                        // Specifes that U be aligned the same as T. Supported only by C++11 compilers (see OVR_CPP_NO_ALIGNAS).
 52.1243 +//
 52.1244 +//    size_t a = OVR_ALIGNOF(double);                   // Returns the natural alignment of the double type.
 52.1245 +//    size_t a = OVR_ALIGNOF(S);                        // Returns the natural alignment of the struct S type.
 52.1246 +//
 52.1247 +// Note: If C++11 alignas is supported, then alignas/OVR_ALIGNAS may take a const expression in addition to a constant.
 52.1248 +// Note: The C11 Standard species the _Alignas keyword and alignas as a macro for it in <stdalign.h>
 52.1249 +
 52.1250 +#if !defined(OVR_ALIGNAS)
 52.1251 +    #if defined(OVR_CC_GNU) && !defined(OVR_CPP_NO_ALIGNAS)     // If C++11 alignas is supported...
 52.1252 +        #define OVR_ALIGNAS(n) alignas(n)
 52.1253 +    #elif defined(__clang__) && !defined(OVR_CPP_NO_ALIGNAS)
 52.1254 +        #define OVR_ALIGNAS(n) alignas(n)
 52.1255 +    #elif defined(OVR_CC_GNU) || defined(__clang__)
 52.1256 +        #define OVR_ALIGNAS(n) __attribute__((aligned(n)))
 52.1257 +    #elif defined(OVR_CC_MSVC) || defined(OVR_CC_INTEL)
 52.1258 +        #define OVR_ALIGNAS(n) __declspec(align(n))             // For Microsoft the alignment must be a literal integer.
 52.1259 +    #elif defined(OVR_CC_ARM)
 52.1260 +        #define OVR_ALIGNAS(n) __align(n)
 52.1261 +    #else
 52.1262 +        #error Need to define OVR_ALIGNAS
 52.1263 +    #endif
 52.1264 +#endif
 52.1265 +
 52.1266 +#if !defined(OVR_ALIGNOF)
 52.1267 +    #if defined(OVR_CC_GNU) && !defined(OVR_CPP_NO_ALIGNOF)     // If C++11 alignof is supported...
 52.1268 +        #define OVR_ALIGNOF(type) alignof(type)
 52.1269 +    #elif defined(__clang__) && !defined(OVR_CPP_NO_ALIGNOF)
 52.1270 +        #define OVR_ALIGNOF(type) alignof(type)
 52.1271 +    #elif defined(OVR_CC_GNU) || defined(__clang__)
 52.1272 +        #define OVR_ALIGNOF(type) ((size_t)__alignof__(type))
 52.1273 +    #elif defined(OVR_CC_MSVC) || defined(OVR_CC_INTEL)
 52.1274 +        #define OVR_ALIGNOF(type) ((size_t)__alignof(type))
 52.1275 +    #elif defined(OVR_CC_ARM)
 52.1276 +        #define OVR_ALIGNOF(type) ((size_t)__ALIGNOF__(type))
 52.1277 +    #else
 52.1278 +        #error Need to define OVR_ALIGNOF
 52.1279 +    #endif
 52.1280 +#endif
 52.1281 +
 52.1282 +
 52.1283 +// -----------------------------------------------------------------------------------
 52.1284 +// ***** OVR_ASSUME / OVR_ANALYSIS_ASSUME
 52.1285 +//
 52.1286 +// This is a portable wrapper for VC++'s __assume and __analysis_assume.
 52.1287 +// __analysis_assume is typically used to quell VC++ static analysis warnings.
 52.1288 +//
 52.1289 +// Example usage:
 52.1290 +//    void Test(char c){
 52.1291 +//       switch(c){
 52.1292 +//          case 'a':
 52.1293 +//          case 'b':
 52.1294 +//          case 'c':
 52.1295 +//          case 'd':
 52.1296 +//             break;
 52.1297 +//          default:
 52.1298 +//             OVR_ASSUME(0); // Unreachable code.
 52.1299 +//       }
 52.1300 +//    }
 52.1301 +//
 52.1302 +//    size_t Test(char* str){
 52.1303 +//       OVR_ANALYSIS_ASSUME(str != nullptr);
 52.1304 +//       return strlen(str);
 52.1305 +//    }
 52.1306 +
 52.1307 +#if !defined(OVR_ASSUME)
 52.1308 +    #if defined(OVR_CC_MSVC)
 52.1309 +        #define OVR_ASSUME(x)          __assume(x)
 52.1310 +        #define OVR_ANALYSIS_ASSUME(x) __analysis_assume(!!(x))
 52.1311 +    #else
 52.1312 +        #define OVR_ASSUME(x)
 52.1313 +        #define OVR_ANALYSIS_ASSUME(x)
 52.1314 +    #endif
 52.1315 +#endif
 52.1316 +
 52.1317 +
 52.1318 +// -----------------------------------------------------------------------------------
 52.1319 +// ***** OVR_RESTRICT
 52.1320 +//
 52.1321 +// Wraps the C99 restrict keyword in a portable way.
 52.1322 +// C++11 and C++14 don't have restrict but this functionality is supported by 
 52.1323 +// all C++ compilers.
 52.1324 +//
 52.1325 +// Example usage:
 52.1326 +//    void* memcpy(void* OVR_RESTRICT s1, const void* OVR_RESTRICT s2, size_t n);
 52.1327 +
 52.1328 +#if !defined(OVR_RESTRICT)
 52.1329 +    #define OVR_RESTRICT __restrict // Currently supported by all compilers of significance to us.
 52.1330 +#endif
 52.1331 +
 52.1332 +
 52.1333 +// -----------------------------------------------------------------------------------
 52.1334 +// ***** OVR_NOEXCEPT / OVR_NOEXCEPT_IF(predicate) / OVR_NOEXCEPT_EXPR(expression)
 52.1335 +//
 52.1336 +// Implements a portable wrapper for C++11 noexcept.
 52.1337 +// http://en.cppreference.com/w/cpp/language/noexcept
 52.1338 +//
 52.1339 +// Example usage:
 52.1340 +//     void Test() OVR_NOEXCEPT {} // This function doesn't throw.
 52.1341 +//
 52.1342 +//     template <typename T>
 52.1343 +//     void DoNothing() OVR_NOEXCEPT_IF(OVR_NOEXCEPT_EXPR(T())) // Throws an if and only if T::T(int) throws.
 52.1344 +//         { T t(3); }
 52.1345 +//
 52.1346 +#if !defined(OVR_NOEXCEPT)
 52.1347 +    #if defined(OVR_CPP_NOEXCEPT)
 52.1348 +        #define OVR_NOEXCEPT
 52.1349 +        #define OVR_NOEXCEPT_IF(predicate)
 52.1350 +        #define OVR_NOEXCEPT_EXPR(expression) false
 52.1351 +    #else
 52.1352 +        #define OVR_NOEXCEPT noexcept
 52.1353 +        #define OVR_NOEXCEPT_IF(predicate) noexcept((predicate))
 52.1354 +        #define OVR_NOEXCEPT_EXPR(expression) noexcept((expression))
 52.1355 +    #endif
 52.1356 +#endif
 52.1357 +
 52.1358 +
 52.1359 +// -----------------------------------------------------------------------------------
 52.1360 +// ***** OVR_FINAL
 52.1361 +//
 52.1362 +// Wraps the C++11 final keyword in a portable way.
 52.1363 +// http://en.cppreference.com/w/cpp/language/final
 52.1364 +//
 52.1365 +// Example usage:
 52.1366 +//     struct Test { virtual int GetValue() OVR_FINAL; };
 52.1367 +
 52.1368 +#if !defined(OVR_FINAL)
 52.1369 +    #if defined(OVR_CC_MSVC) && (OVR_CC_VERSION < 1700) // VC++ 2012 and earlier
 52.1370 +        #define OVR_FINAL sealed
 52.1371 +    #elif defined(OVR_CPP_INHERITANCE_FINAL)
 52.1372 +        #define OVR_FINAL
 52.1373 +    #else
 52.1374 +        #define OVR_FINAL final
 52.1375 +    #endif
 52.1376 +#endif
 52.1377 +
 52.1378 +
 52.1379 +// -----------------------------------------------------------------------------------
 52.1380 +// ***** OVR_OVERRIDE
 52.1381 +//
 52.1382 +// Wraps the C++11 override keyword in a portable way.
 52.1383 +// http://en.cppreference.com/w/cpp/language/override
 52.1384 +//
 52.1385 +// Example usage:
 52.1386 +//        struct Parent { virtual void Func(int); };
 52.1387 +//        struct Child : public Parent { void Func(int) OVR_OVERRIDE; };
 52.1388 +
 52.1389 +#if !defined(OVR_CPP11_ENABLED)
 52.1390 +#define OVR_OVERRIDE
 52.1391 +#elif !defined(OVR_OVERRIDE)
 52.1392 +    #if defined(OVR_CPP_OVERRIDE)
 52.1393 +        #define OVR_OVERRIDE
 52.1394 +    #else
 52.1395 +        #if (defined(_MSC_VER) && (_MSC_VER <= 1600))
 52.1396 +            #pragma warning(disable : 4481)
 52.1397 +        #endif
 52.1398 +        #define OVR_OVERRIDE override
 52.1399 +    #endif
 52.1400 +#endif
 52.1401 +
 52.1402 +
 52.1403 +// -----------------------------------------------------------------------------------
 52.1404 +// ***** OVR_FINAL_OVERRIDE
 52.1405 +//
 52.1406 +// Wraps the C++11 final+override keywords (a common combination) in a portable way.
 52.1407 +//
 52.1408 +// Example usage:
 52.1409 +//     struct Parent { virtual void Func(); };
 52.1410 +//     struct Child : public Parent { virtual void Func() OVR_FINAL_OVERRIDE; };
 52.1411 +
 52.1412 +#if !defined(OVR_FINAL_OVERRIDE)
 52.1413 +    #define OVR_FINAL_OVERRIDE OVR_FINAL OVR_OVERRIDE
 52.1414 +#endif
 52.1415 +
 52.1416 +
 52.1417 +// -----------------------------------------------------------------------------------
 52.1418 +// ***** OVR_EXTERN_TEMPLATE
 52.1419 +//
 52.1420 +// Portable wrapper for C++11 extern template. This tells the compiler to not instantiate
 52.1421 +// the template in the current translation unit, which can significantly speed up 
 52.1422 +// compilation and avoid problems due to two translation units compiling code with 
 52.1423 +// different settings.
 52.1424 +//
 52.1425 +// Example usage:
 52.1426 +//     OVR_EXTERN_TEMPLATE(class basic_string<char>); // Nothing to do for non-C++11 compilers.
 52.1427 +
 52.1428 +#if !defined(OVR_EXTERN_TEMPLATE)
 52.1429 +    #if defined(OVR_CPP_EXTERN_TEMPLATE)
 52.1430 +        #define OVR_EXTERN_TEMPLATE(decl)
 52.1431 +    #else
 52.1432 +        #define OVR_EXTERN_TEMPLATE(decl) extern template decl
 52.1433 +    #endif
 52.1434 +#endif
 52.1435 +
 52.1436 +
 52.1437 +// -----------------------------------------------------------------------------------
 52.1438 +// ***** OVR_CONSTEXPR  / OVR_CONSTEXPR_OR_CONST
 52.1439 +//
 52.1440 +// Portable wrapper for C++11 constexpr. Doesn't include C++14 relaxed constexpr,
 52.1441 +// for which a different wrapper name is reserved.
 52.1442 +//
 52.1443 +// Example usage:
 52.1444 +//     OVR_CONSTEXPR int Test() { return 15; }          // This can be optimized better by a C++11 compiler that supports constexpr.
 52.1445 +//     OVR_CONSTEXPR_OR_CONST float x = 3.14159f;       // This can be optimized better by a C++11 compiler, but if not then at least make it const.
 52.1446 +
 52.1447 +#if !defined(OVR_CONSTEXPR)
 52.1448 +    #if defined(OVR_CPP_NO_CONSTEXPR)
 52.1449 +        #define OVR_CONSTEXPR
 52.1450 +    #else
 52.1451 +        #define OVR_CONSTEXPR constexpr
 52.1452 +    #endif
 52.1453 +#endif
 52.1454 +
 52.1455 +#if !defined(OVR_CONSTEXPR_OR_CONST)
 52.1456 +    #if defined(OVR_CPP_NO_CONSTEXPR)
 52.1457 +        #define OVR_CONSTEXPR_OR_CONST const
 52.1458 +    #else
 52.1459 +        #define OVR_CONSTEXPR_OR_CONST constexpr
 52.1460 +    #endif
 52.1461 +#endif
 52.1462 +
 52.1463 +
 52.1464 +
 52.1465 +// -----------------------------------------------------------------------------------
 52.1466 +// ***** OVR_FUNCTION_DELETE / OVR_FUNCTION_DEFAULT
 52.1467 +//
 52.1468 +// Wraps the C++11 delete and default keywords in a way that allows for cleaner code
 52.1469 +// while making for a better version of uncallable or default functions.
 52.1470 +//
 52.1471 +// Example usage:
 52.1472 +//     struct Test{
 52.1473 +//         Test() OVR_FUNCTION_DEFAULT;            // Non-C++11 compilers will require a separate definition for Test().
 52.1474 +//     private:                                   // Users should put OVR_FUNCTION_DELETE usage in a private 
 52.1475 +//         void Uncallable() OVR_FUNCTION_DELETE;  // area for compatibility with pre-C++11 compilers.
 52.1476 +//     };
 52.1477 +
 52.1478 +#if defined(OVR_CPP_NO_DELETED_FUNCTIONS)
 52.1479 +    #define OVR_FUNCTION_DELETE
 52.1480 +#else
 52.1481 +    #define OVR_FUNCTION_DELETE = delete
 52.1482 +#endif
 52.1483 +
 52.1484 +#if defined(OVR_CPP_NO_DEFAULTED_FUNCTIONS)
 52.1485 +    #define OVR_FUNCTION_DEFAULT
 52.1486 +#else
 52.1487 +    #define OVR_FUNCTION_DEFAULT = default
 52.1488 +#endif
 52.1489 +
 52.1490 +
 52.1491 +
 52.1492 +// -----------------------------------------------------------------------------------
 52.1493 +// ***** OVR_NON_COPYABLE
 52.1494 +//
 52.1495 +// Allows you to specify a class as being neither copy-constructible nor assignable,
 52.1496 +// which is a commonly needed pattern in C++ programming. Classes with this declaration
 52.1497 +// are required to be default constructible (as are most classes). For pre-C++11
 52.1498 +// compilers this macro declares a private section for the class, which will be
 52.1499 +// inherited by whatever code is directly below the macro invocation by default.
 52.1500 +//
 52.1501 +// Example usage:
 52.1502 +//    struct Test {
 52.1503 +//       Test();
 52.1504 +//       ...
 52.1505 +//       OVR_NON_COPYABLE(Test)
 52.1506 +//    };
 52.1507 +
 52.1508 +#if !defined(OVR_NON_COPYABLE)
 52.1509 +    #if defined(OVR_CPP_NO_DELETED_FUNCTIONS)
 52.1510 +        #define OVR_NON_COPYABLE(Type)   \
 52.1511 +            private:                     \
 52.1512 +            Type(const Type&);           \
 52.1513 +            void operator=(const Type&);
 52.1514 +    #else
 52.1515 +        #define OVR_NON_COPYABLE(Type)   \
 52.1516 +            Type(const Type&) = delete;  \
 52.1517 +            void operator=(const Type&) = delete;
 52.1518 +    #endif
 52.1519 +#endif
 52.1520 +
 52.1521 +
 52.1522 +
 52.1523 +#endif  // header include guard
 52.1524 +
 52.1525 +
 52.1526 +
 52.1527 +
    53.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    53.2 +++ b/LibOVR/Src/Kernel/OVR_ContainerAllocator.h	Wed Jan 14 06:51:16 2015 +0200
    53.3 @@ -0,0 +1,267 @@
    53.4 +/************************************************************************************
    53.5 +
    53.6 +PublicHeader:   OVR_Kernel.h
    53.7 +Filename    :   OVR_ContainerAllocator.h
    53.8 +Content     :   Template allocators and constructors for containers.
    53.9 +Created     :   September 19, 2012
   53.10 +Notes       : 
   53.11 +
   53.12 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   53.13 +
   53.14 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
   53.15 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
   53.16 +which is provided at the time of installation or download, or which 
   53.17 +otherwise accompanies this software in either electronic or hard copy form.
   53.18 +
   53.19 +You may obtain a copy of the License at
   53.20 +
   53.21 +http://www.oculusvr.com/licenses/LICENSE-3.2 
   53.22 +
   53.23 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
   53.24 +distributed under the License is distributed on an "AS IS" BASIS,
   53.25 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   53.26 +See the License for the specific language governing permissions and
   53.27 +limitations under the License.
   53.28 +
   53.29 +************************************************************************************/
   53.30 +
   53.31 +#ifndef OVR_ContainerAllocator_h
   53.32 +#define OVR_ContainerAllocator_h
   53.33 +
   53.34 +#include "OVR_Allocator.h"
   53.35 +#include <string.h>
   53.36 +
   53.37 +
   53.38 +namespace OVR {
   53.39 +
   53.40 +
   53.41 +//-----------------------------------------------------------------------------------
   53.42 +// ***** Container Allocator
   53.43 +
   53.44 +// ContainerAllocator serves as a template argument for allocations done by
   53.45 +// containers, such as Array and Hash; replacing it could allow allocator
   53.46 +// substitution in containers.
   53.47 +
   53.48 +class ContainerAllocatorBase
   53.49 +{
   53.50 +public:
   53.51 +    static void* Alloc(size_t size)                { return OVR_ALLOC(size); }
   53.52 +    static void* Realloc(void* p, size_t newSize)  { return OVR_REALLOC(p, newSize); }
   53.53 +    static void  Free(void *p)                    { OVR_FREE(p); }
   53.54 +};
   53.55 +
   53.56 +
   53.57 +
   53.58 +//-----------------------------------------------------------------------------------
   53.59 +// ***** Constructors, Destructors, Copiers
   53.60 +
   53.61 +// Plain Old Data - movable, no special constructors/destructor.
   53.62 +template<class T> 
   53.63 +class ConstructorPOD
   53.64 +{
   53.65 +public:
   53.66 +    static void Construct(void *) {}
   53.67 +    static void Construct(void *p, const T& source) 
   53.68 +    { 
   53.69 +        *(T*)p = source;
   53.70 +    }
   53.71 +
   53.72 +    // Same as above, but allows for a different type of constructor.
   53.73 +    template <class S> 
   53.74 +    static void ConstructAlt(void *p, const S& source)
   53.75 +    {
   53.76 +        *(T*)p = source;
   53.77 +    }
   53.78 +
   53.79 +    static void ConstructArray(void*, size_t) {}
   53.80 +
   53.81 +    static void ConstructArray(void* p, size_t count, const T& source)
   53.82 +    {
   53.83 +        uint8_t *pdata = (uint8_t*)p;
   53.84 +        for (size_t i=0; i< count; ++i, pdata += sizeof(T))
   53.85 +            *(T*)pdata = source;
   53.86 +    }
   53.87 +
   53.88 +    static void ConstructArray(void* p, size_t count, const T* psource)
   53.89 +    {
   53.90 +        memcpy(p, psource, sizeof(T) * count);
   53.91 +    }
   53.92 +
   53.93 +    static void Destruct(T*) {}
   53.94 +    static void DestructArray(T*, size_t) {}
   53.95 +
   53.96 +    static void CopyArrayForward(T* dst, const T* src, size_t count)
   53.97 +    {
   53.98 +        memmove(dst, src, count * sizeof(T));
   53.99 +    }
  53.100 +
  53.101 +    static void CopyArrayBackward(T* dst, const T* src, size_t count)
  53.102 +    {
  53.103 +        memmove(dst, src, count * sizeof(T));
  53.104 +    }
  53.105 +
  53.106 +    static bool IsMovable() { return true; }
  53.107 +};
  53.108 +
  53.109 +
  53.110 +//-----------------------------------------------------------------------------------
  53.111 +// ***** ConstructorMov
  53.112 +//
  53.113 +// Correct C++ construction and destruction for movable objects
  53.114 +template<class T> 
  53.115 +class ConstructorMov
  53.116 +{
  53.117 +public:
  53.118 +    static void Construct(void* p) 
  53.119 +    { 
  53.120 +        OVR::Construct<T>(p);
  53.121 +    }
  53.122 +
  53.123 +    static void Construct(void* p, const T& source) 
  53.124 +    { 
  53.125 +        OVR::Construct<T>(p, source);
  53.126 +    }
  53.127 +
  53.128 +    // Same as above, but allows for a different type of constructor.
  53.129 +    template <class S> 
  53.130 +    static void ConstructAlt(void* p, const S& source)
  53.131 +    {
  53.132 +        OVR::ConstructAlt<T,S>(p, source);
  53.133 +    }
  53.134 +
  53.135 +    static void ConstructArray(void* p, size_t count)
  53.136 +    {
  53.137 +        uint8_t* pdata = (uint8_t*)p;
  53.138 +        for (size_t i=0; i< count; ++i, pdata += sizeof(T))
  53.139 +            Construct(pdata);
  53.140 +    }
  53.141 +
  53.142 +    static void ConstructArray(void* p, size_t count, const T& source)
  53.143 +    {
  53.144 +        uint8_t* pdata = (uint8_t*)p;
  53.145 +        for (size_t i=0; i< count; ++i, pdata += sizeof(T))
  53.146 +            Construct(pdata, source);
  53.147 +    }
  53.148 +
  53.149 +    static void ConstructArray(void* p, size_t count, const T* psource)
  53.150 +    {
  53.151 +        uint8_t* pdata = (uint8_t*)p;
  53.152 +        for (size_t i=0; i< count; ++i, pdata += sizeof(T))
  53.153 +            Construct(pdata, *psource++);
  53.154 +    }
  53.155 +
  53.156 +    static void Destruct(T* p)
  53.157 +    {
  53.158 +        p->~T();
  53.159 +        OVR_UNUSED(p); // Suppress silly MSVC warning
  53.160 +    }
  53.161 +
  53.162 +    static void DestructArray(T* p, size_t count)
  53.163 +    {   
  53.164 +        p += count - 1;
  53.165 +        for (size_t i=0; i<count; ++i, --p)
  53.166 +            p->~T();
  53.167 +    }
  53.168 +
  53.169 +    static void CopyArrayForward(T* dst, const T* src, size_t count)
  53.170 +    {
  53.171 +        memmove(dst, src, count * sizeof(T));
  53.172 +    }
  53.173 +
  53.174 +    static void CopyArrayBackward(T* dst, const T* src, size_t count)
  53.175 +    {
  53.176 +        memmove(dst, src, count * sizeof(T));
  53.177 +    }
  53.178 +
  53.179 +    static bool IsMovable() { return true; }
  53.180 +};
  53.181 +
  53.182 +
  53.183 +//-----------------------------------------------------------------------------------
  53.184 +// ***** ConstructorCPP
  53.185 +//
  53.186 +// Correct C++ construction and destruction for movable objects
  53.187 +template<class T> 
  53.188 +class ConstructorCPP
  53.189 +{
  53.190 +public:
  53.191 +    static void Construct(void* p) 
  53.192 +    { 
  53.193 +        OVR::Construct<T>(p);        
  53.194 +    }
  53.195 +
  53.196 +    static void Construct(void* p, const T& source) 
  53.197 +    { 
  53.198 +        OVR::Construct<T>(p, source);        
  53.199 +    }
  53.200 +
  53.201 +    // Same as above, but allows for a different type of constructor.
  53.202 +    template <class S> 
  53.203 +    static void ConstructAlt(void* p, const S& source)
  53.204 +    {
  53.205 +        OVR::ConstructAlt<T,S>(p, source);        
  53.206 +    }
  53.207 +
  53.208 +    static void ConstructArray(void* p, size_t count)
  53.209 +    {
  53.210 +        uint8_t* pdata = (uint8_t*)p;
  53.211 +        for (size_t i=0; i< count; ++i, pdata += sizeof(T))
  53.212 +            Construct(pdata);
  53.213 +    }
  53.214 +
  53.215 +    static void ConstructArray(void* p, size_t count, const T& source)
  53.216 +    {
  53.217 +        uint8_t* pdata = (uint8_t*)p;
  53.218 +        for (size_t i=0; i< count; ++i, pdata += sizeof(T))
  53.219 +            Construct(pdata, source);
  53.220 +    }
  53.221 +
  53.222 +    static void ConstructArray(void* p, size_t count, const T* psource)
  53.223 +    {
  53.224 +        uint8_t* pdata = (uint8_t*)p;
  53.225 +        for (size_t i=0; i< count; ++i, pdata += sizeof(T))
  53.226 +            Construct(pdata, *psource++);
  53.227 +    }
  53.228 +
  53.229 +    static void Destruct(T* p)
  53.230 +    {
  53.231 +        p->~T();
  53.232 +        OVR_UNUSED(p); // Suppress silly MSVC warning
  53.233 +    }
  53.234 +
  53.235 +    static void DestructArray(T* p, size_t count)
  53.236 +    {   
  53.237 +        p += count - 1;
  53.238 +        for (size_t i=0; i<count; ++i, --p)
  53.239 +            p->~T();
  53.240 +    }
  53.241 +
  53.242 +    static void CopyArrayForward(T* dst, const T* src, size_t count)
  53.243 +    {
  53.244 +        for(size_t i = 0; i < count; ++i)
  53.245 +            dst[i] = src[i];
  53.246 +    }
  53.247 +
  53.248 +    static void CopyArrayBackward(T* dst, const T* src, size_t count)
  53.249 +    {
  53.250 +        for(size_t i = count; i; --i)
  53.251 +            dst[i-1] = src[i-1];
  53.252 +    }
  53.253 +
  53.254 +    static bool IsMovable() { return false; }
  53.255 +};
  53.256 +
  53.257 +
  53.258 +//-----------------------------------------------------------------------------------
  53.259 +// ***** Container Allocator with movement policy
  53.260 +//
  53.261 +// Simple wraps as specialized allocators
  53.262 +template<class T> struct ContainerAllocator_POD : ContainerAllocatorBase, ConstructorPOD<T> {};
  53.263 +template<class T> struct ContainerAllocator     : ContainerAllocatorBase, ConstructorMov<T> {};
  53.264 +template<class T> struct ContainerAllocator_CPP : ContainerAllocatorBase, ConstructorCPP<T> {};
  53.265 +
  53.266 +
  53.267 +} // OVR
  53.268 +
  53.269 +
  53.270 +#endif
    54.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    54.2 +++ b/LibOVR/Src/Kernel/OVR_DebugHelp.cpp	Wed Jan 14 06:51:16 2015 +0200
    54.3 @@ -0,0 +1,3926 @@
    54.4 +/************************************************************************************
    54.5 +
    54.6 +Filename    :   ExceptionHandler.cpp
    54.7 +Content     :   Platform-independent exception handling interface
    54.8 +Created     :   October 6, 2014
    54.9 +
   54.10 +Copyright   :   Copyright 2014 Oculus VR, LLC. All Rights reserved.
   54.11 +
   54.12 +Licensed under the Apache License, Version 2.0 (the "License");
   54.13 +you may not use this file except in compliance with the License.
   54.14 +You may obtain a copy of the License at
   54.15 +
   54.16 +http://www.apache.org/licenses/LICENSE-2.0
   54.17 +
   54.18 +Unless required by applicable law or agreed to in writing, software
   54.19 +distributed under the License is distributed on an "AS IS" BASIS,
   54.20 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   54.21 +See the License for the specific language governing permissions and
   54.22 +limitations under the License.
   54.23 +
   54.24 +************************************************************************************/
   54.25 +
   54.26 +
   54.27 +#include "OVR_DebugHelp.h"
   54.28 +#include "OVR_Types.h"
   54.29 +#include "OVR_UTF8Util.h"
   54.30 +#include "../OVR_CAPI.h"
   54.31 +#include "../OVR_CAPI_Keys.h"
   54.32 +#include "../CAPI/CAPI_HMDState.h"
   54.33 +#include <stdlib.h>
   54.34 +
   54.35 +#if defined(OVR_OS_WIN32) || defined(OVR_OS_WIN64)
   54.36 +    #pragma warning(push, 0)
   54.37 +    #include <Windows.h>
   54.38 +    #include <WinNT.h>
   54.39 +    #include <DbgHelp.h>
   54.40 +    #include <WinVer.h>
   54.41 +    #include <share.h>
   54.42 +    #include <Psapi.h>
   54.43 +    #include <TlHelp32.h>
   54.44 +    #include <comutil.h>
   54.45 +    #include <Wbemcli.h>
   54.46 +    #include <Wbemidl.h>
   54.47 +    #include <ShlObj.h>
   54.48 +    #include <ObjBase.h>
   54.49 +    #pragma warning(pop)
   54.50 +
   54.51 +    #pragma comment(lib, "Psapi.lib")   // To consider: It may be a problem to statically link to these libraries if the application at runtime intends to dynamically
   54.52 +    #pragma comment(lib, "ole32.lib")   // link to a different version of the same library, and we are statically linked into that application instead of being a DLL.
   54.53 +    #pragma comment(lib, "shell32.lib")
   54.54 +
   54.55 +    // NtQueryInformation and THREAD_BASIC_INFORMATION are undocumented but frequently needed for digging into thread information.
   54.56 +    typedef LONG (WINAPI *NtQueryInformationThreadFunc)(HANDLE, int, PVOID, ULONG, PULONG);
   54.57 +
   54.58 +    struct THREAD_BASIC_INFORMATION
   54.59 +    {
   54.60 +        LONG  ExitStatus;
   54.61 +        PVOID TebBaseAddress;
   54.62 +        PVOID UniqueProcessId;
   54.63 +        PVOID UniqueThreadId;
   54.64 +        PVOID Priority;
   54.65 +        PVOID BasePriority;
   54.66 +    };
   54.67 +
   54.68 +    #ifndef UNW_FLAG_NHANDLER // Older Windows SDKs don't support this.
   54.69 +        #define UNW_FLAG_NHANDLER 0
   54.70 +    #endif
   54.71 +
   54.72 +#elif defined(OVR_OS_MAC)
   54.73 +    #include <unistd.h>
   54.74 +    #include <sys/sysctl.h>
   54.75 +    #include <sys/utsname.h>
   54.76 +    #include <sys/types.h>
   54.77 +    #include <sys/mman.h>
   54.78 +    #include <stdlib.h>
   54.79 +    #include <stdio.h>
   54.80 +    #include <pthread.h>
   54.81 +    #include <mach/mach.h>
   54.82 +    #include <mach/mach_error.h>
   54.83 +    #include <mach/thread_status.h>
   54.84 +    #include <mach/exception.h>
   54.85 +    #include <mach/task.h>
   54.86 +    #include <mach/thread_act.h>
   54.87 +    #include <mach-o/dyld.h>
   54.88 +    #include <mach-o/dyld_images.h>
   54.89 +    #include <libproc.h>
   54.90 +    #include <libgen.h>
   54.91 +    #include <execinfo.h>
   54.92 +    #include <cxxabi.h>
   54.93 +    #include "OVR_mach_exc_OSX.h"
   54.94 +
   54.95 +    #if defined(__LP64__)
   54.96 +        typedef struct mach_header_64     MachHeader;
   54.97 +        typedef struct segment_command_64 SegmentCommand;
   54.98 +        typedef struct section_64         Section;
   54.99 +        #define kLCSegment                LC_SEGMENT_64
  54.100 +    #else
  54.101 +        typedef struct mach_header        MachHeader;
  54.102 +        typedef struct segment_command    SegmentCommand;
  54.103 +        typedef struct section            Section;
  54.104 +        #define kLCSegment                LC_SEGMENT
  54.105 +    #endif
  54.106 +
  54.107 +    extern "C" const struct dyld_all_image_infos* _dyld_get_all_image_infos(); // From libdyld.dylib
  54.108 +
  54.109 +#elif defined(OVR_OS_UNIX)
  54.110 +	#include <unistd.h>
  54.111 +	#include <sys/sysctl.h>
  54.112 +	#include <sys/utsname.h>
  54.113 +	#include <sys/types.h>
  54.114 +	#include <sys/ptrace.h>
  54.115 +	#include <sys/wait.h>
  54.116 +	#include <sys/mman.h>
  54.117 +	#include <stdlib.h>
  54.118 +	#include <stdio.h>
  54.119 +	#include <pthread.h>
  54.120 +	#include <libgen.h>
  54.121 +	#include <execinfo.h>
  54.122 +	#include <cxxabi.h>
  54.123 +  //#include <libunwind.h> // Can't use this until we can ensure that we have an installed version of it.
  54.124 +#endif
  54.125 +
  54.126 +#if !defined(MIN)
  54.127 +    #define MIN(X,Y) ((X) < (Y) ? (X) : (Y))
  54.128 +    #define MAX(X,Y) ((X) > (Y) ? (X) : (Y))
  54.129 +#endif
  54.130 +
  54.131 +
  54.132 +OVR_DISABLE_MSVC_WARNING(4351) // new behavior: elements of array will be default initialized
  54.133 +OVR_DISABLE_MSVC_WARNING(4996) // This function or variable may be unsafe
  54.134 +
  54.135 +
  54.136 +
  54.137 +
  54.138 +#if defined(OVR_OS_APPLE)
  54.139 +    static OVR::ExceptionHandler* sExceptionHandler = nullptr;
  54.140 +    const uint32_t sMachCancelMessageType = 0x0ca9ce11;  // This is a made-up value of our own choice.
  54.141 +
  54.142 +    extern "C"
  54.143 +    {
  54.144 +        kern_return_t catch_mach_exception_raise_OVR(mach_port_t /*exceptionPort*/, mach_port_t /*threadSysId*/,
  54.145 +                                        mach_port_t /*machTask*/, exception_type_t /*machExceptionType*/,
  54.146 +                                        mach_exception_data_t /*machExceptionData*/, mach_msg_type_number_t /*machExceptionDataCount*/)
  54.147 +        {    
  54.148 +            return KERN_FAILURE;
  54.149 +        }
  54.150 +
  54.151 +        kern_return_t catch_mach_exception_raise_state_OVR(mach_port_t /*exceptionPort*/, exception_type_t /*exceptionType*/,
  54.152 +                                        const mach_exception_data_t /*machExceptionData*/, mach_msg_type_number_t /*machExceptionDataCount*/,
  54.153 +                                        int* /*pMachExceptionFlavor*/, const thread_state_t /*threadStatePrev*/, mach_msg_type_number_t /*threaStatePrevCount*/,
  54.154 +                                        thread_state_t /*threadStateNew*/, mach_msg_type_number_t* /*pThreadStateNewCount*/)
  54.155 +        {    
  54.156 +            return KERN_FAILURE;
  54.157 +        }
  54.158 +
  54.159 +        kern_return_t catch_mach_exception_raise_state_identity_OVR(mach_port_t exceptionPort, mach_port_t threadSysId, mach_port_t machTask,
  54.160 +                                            exception_type_t exceptionType, mach_exception_data_type_t* machExceptionData,
  54.161 +                                            mach_msg_type_number_t machExceptionDataCount, int* pMachExceptionFlavor,
  54.162 +                                            thread_state_t threadStatePrev, mach_msg_type_number_t threadStatePrevCount,
  54.163 +                                            thread_state_t threadStateNew, mach_msg_type_number_t* pThreadStateNewCount)
  54.164 +        {
  54.165 +            return sExceptionHandler->HandleMachException(exceptionPort, threadSysId, machTask, exceptionType, machExceptionData,
  54.166 +                                                machExceptionDataCount, pMachExceptionFlavor, threadStatePrev, threadStatePrevCount,
  54.167 +                                                threadStateNew, pThreadStateNewCount);
  54.168 +        }
  54.169 +
  54.170 +        void* MachHandlerThreadFunctionStatic(void* pExceptionHandlerVoid)
  54.171 +        {
  54.172 +            return static_cast<OVR::ExceptionHandler*>(pExceptionHandlerVoid)->MachHandlerThreadFunction();
  54.173 +        }
  54.174 +    
  54.175 +    } // extern "C"
  54.176 +#endif
  54.177 +
  54.178 +
  54.179 +
  54.180 +
  54.181 +namespace OVR {
  54.182 +
  54.183 +
  54.184 +void GetInstructionPointer(void*& pInstruction)
  54.185 +{
  54.186 +    #if defined(OVR_CC_MSVC)
  54.187 +        pInstruction = _ReturnAddress();
  54.188 +    #else // GCC, clang
  54.189 +        pInstruction = __builtin_return_address(0);
  54.190 +    #endif
  54.191 +}
  54.192 +
  54.193 +
  54.194 +static size_t SprintfAddress(char* threadHandleStr, size_t threadHandleStrCapacity, const void* pAddress)
  54.195 +{
  54.196 +    #if defined(OVR_CC_MSVC)
  54.197 +        #if (OVR_PTR_SIZE >= 8)
  54.198 +            return OVR_snprintf(threadHandleStr, threadHandleStrCapacity, "0x%016I64x", pAddress);  // e.g. 0x0123456789abcdef
  54.199 +        #else
  54.200 +            return OVR_snprintf(threadHandleStr, threadHandleStrCapacity, "0x%08x", pAddress);      // e.g. 0x89abcdef
  54.201 +        #endif
  54.202 +    #else
  54.203 +        #if (OVR_PTR_SIZE >= 8)
  54.204 +            return OVR_snprintf(threadHandleStr, threadHandleStrCapacity, "%016llx", pAddress);     // e.g. 0x0123456789abcdef
  54.205 +        #else
  54.206 +            return OVR_snprintf(threadHandleStr, threadHandleStrCapacity, "%08x", pAddress);        // e.g. 0x89abcdef
  54.207 +        #endif
  54.208 +    #endif
  54.209 +}
  54.210 +
  54.211 +
  54.212 +static size_t SprintfThreadHandle(char* threadHandleStr, size_t threadHandleStrCapacity, const ThreadHandle& threadHandle)
  54.213 +{
  54.214 +    return SprintfAddress(threadHandleStr, threadHandleStrCapacity, threadHandle);
  54.215 +}
  54.216 +
  54.217 +
  54.218 +static size_t SprintfThreadSysId(char* threadSysIdStr, size_t threadSysIdStrCapacity, const ThreadSysId& threadSysId)
  54.219 +{
  54.220 +    #if defined(OVR_CC_MSVC) // Somebody could conceivably use VC++ with a different standard library that supports %ll. And VS2012+ also support %ll.
  54.221 +        return OVR_snprintf(threadSysIdStr, threadSysIdStrCapacity, "%I64u", (uint64_t)threadSysId);        
  54.222 +    #else
  54.223 +        return OVR_snprintf(threadSysIdStr, threadSysIdStrCapacity, "%llu", (uint64_t)threadSysId);        
  54.224 +    #endif
  54.225 +}
  54.226 +
  54.227 +
  54.228 +
  54.229 +
  54.230 +
  54.231 +void GetThreadStackBounds(void*& pStackBase, void*& pStackLimit, ThreadHandle threadHandle)
  54.232 +{
  54.233 +    #if defined(OVR_OS_WIN64) || defined(OVR_OS_WIN32) || (defined(OVR_OS_MS) && defined(OVR_OS_CONSOLE))
  54.234 +        ThreadSysId threadSysIdCurrent = (ThreadSysId)GetCurrentThreadId();
  54.235 +        ThreadSysId threadSysId;
  54.236 +        NT_TIB*     pTIB = nullptr;
  54.237 +
  54.238 +        if(threadHandle == OVR_THREADHANDLE_INVALID)
  54.239 +            threadSysId = threadSysIdCurrent;
  54.240 +        else
  54.241 +            threadSysId = ConvertThreadHandleToThreadSysId(threadHandle);
  54.242 +
  54.243 +        if(threadSysId == threadSysIdCurrent)
  54.244 +        {
  54.245 +            #if (OVR_PTR_SIZE == 4)
  54.246 +                // Need to use __asm__("movl %%fs:0x18, %0" : "=r" (pTIB) : : ); under gcc/clang.
  54.247 +                __asm {
  54.248 +                    mov eax, fs:[18h]
  54.249 +                    mov pTIB, eax
  54.250 +                }
  54.251 +            #else
  54.252 +                pTIB = (NT_TIB*)NtCurrentTeb();
  54.253 +            #endif
  54.254 +        }
  54.255 +        else
  54.256 +        {
  54.257 +            #if (OVR_PTR_SIZE == 4)
  54.258 +                // It turns out we don't need to suspend the thread when getting SegFs/SegGS, as that's 
  54.259 +                // constant per thread and doesn't require the thread to be suspended.
  54.260 +                //SuspendThread((HANDLE)threadHandle); 
  54.261 +                CONTEXT context;
  54.262 +                memset(&context, 0, sizeof(context));
  54.263 +                context.ContextFlags = CONTEXT_SEGMENTS;
  54.264 +                GetThreadContext((HANDLE)threadHandle, &context); // Requires THREAD_QUERY_INFORMATION privileges.
  54.265 +
  54.266 +                LDT_ENTRY ldtEntry;
  54.267 +                if(GetThreadSelectorEntry(threadHandle, context.SegFs, &ldtEntry)) // Requires THREAD_QUERY_INFORMATION
  54.268 +                    pTIB = (NT_TIB*)((ldtEntry.HighWord.Bits.BaseHi << 24 ) | (ldtEntry.HighWord.Bits.BaseMid << 16) | ldtEntry.BaseLow);
  54.269 +
  54.270 +                //ResumeThread((HANDLE)threadHandle);
  54.271 +            #else
  54.272 +                // We cannot use GetThreadSelectorEntry or Wow64GetThreadSelectorEntry on Win64.
  54.273 +                // We need to read the SegGs qword at offset 0x30. We can't use pTIB = (NT_TIB*)__readgsqword(0x30) because that reads only the current setGs offset.
  54.274 +                //    mov rax, qword ptr gs:[30h]  
  54.275 +                //    mov qword ptr [pTIB],rax
  54.276 +                // In the meantime we rely on the NtQueryInformationThread function.
  54.277 +
  54.278 +                static NtQueryInformationThreadFunc spNtQueryInformationThread = nullptr;
  54.279 +
  54.280 +                if(!spNtQueryInformationThread)
  54.281 +                {
  54.282 +                    HMODULE hNTDLL = GetModuleHandleA("ntdll.dll");
  54.283 +                    spNtQueryInformationThread = (NtQueryInformationThreadFunc)(uintptr_t)GetProcAddress(hNTDLL, "NtQueryInformationThread");
  54.284 +                }
  54.285 +
  54.286 +                if(spNtQueryInformationThread)
  54.287 +                {
  54.288 +                    THREAD_BASIC_INFORMATION tbi;
  54.289 +
  54.290 +                    memset(&tbi, 0, sizeof(tbi));
  54.291 +                    LONG result = spNtQueryInformationThread(threadHandle, 0, &tbi, sizeof(tbi), nullptr); // Requires THREAD_QUERY_INFORMATION privileges
  54.292 +                    if(result == 0)
  54.293 +                        pTIB = (NT_TIB*)tbi.TebBaseAddress;
  54.294 +                }
  54.295 +            #endif
  54.296 +        }
  54.297 +
  54.298 +        if(pTIB)
  54.299 +        {
  54.300 +            pStackBase  = (void*)pTIB->StackBase;
  54.301 +            pStackLimit = (void*)pTIB->StackLimit;
  54.302 +        }
  54.303 +        else
  54.304 +        {
  54.305 +            pStackBase  = nullptr;
  54.306 +            pStackLimit = nullptr;
  54.307 +        }
  54.308 +
  54.309 +    #elif defined(OVR_OS_APPLE)
  54.310 +        if(!threadHandle)
  54.311 +            threadHandle = pthread_self();
  54.312 +    
  54.313 +        pStackBase = pthread_get_stackaddr_np((pthread_t)threadHandle);
  54.314 +        size_t stackSize = pthread_get_stacksize_np((pthread_t)threadHandle);
  54.315 +        pStackLimit = (void*)((size_t)pStackBase - stackSize);
  54.316 +    
  54.317 +    #elif defined(OVR_OS_UNIX)
  54.318 +        pStackBase  = nullptr;
  54.319 +        pStackLimit = nullptr;
  54.320 +
  54.321 +        pthread_attr_t threadAttr;
  54.322 +        pthread_attr_init(&threadAttr);
  54.323 +    
  54.324 +        #if defined(OVR_OS_LINUX)
  54.325 +            int result = pthread_getattr_np((pthread_t)threadHandle, &threadAttr);
  54.326 +        #else
  54.327 +            int result = pthread_attr_get_np((pthread_t)threadHandle, &threadAttr);
  54.328 +        #endif
  54.329 +    
  54.330 +        if(result == 0)
  54.331 +        {
  54.332 +            size_t stackSize = 0;
  54.333 +            result = pthread_attr_getstack(&threadAttr, &pStackLimit, &stackSize);
  54.334 +            
  54.335 +            if(result == 0)
  54.336 +                pStackBase = (void*)((uintptr_t)pStackLimit + stackSize); // We assume the stack grows downward.
  54.337 +        }
  54.338 +
  54.339 +    #endif
  54.340 +}
  54.341 +
  54.342 +
  54.343 +bool OVRIsDebuggerPresent()
  54.344 +{
  54.345 +    #if defined(OVR_OS_MS)
  54.346 +        return ::IsDebuggerPresent() != 0;
  54.347 +
  54.348 +    #elif defined(OVR_OS_APPLE)
  54.349 +        int               mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, getpid() };
  54.350 +        struct kinfo_proc info;
  54.351 +        size_t            size = sizeof(info);
  54.352 +
  54.353 +        info.kp_proc.p_flag = 0;
  54.354 +        sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, nullptr, 0);
  54.355 +
  54.356 +        return ((info.kp_proc.p_flag & P_TRACED) != 0);
  54.357 +
  54.358 +    #elif (defined(OVR_OS_LINUX) || defined(OVR_OS_BSD)) && !defined(OVR_OS_ANDROID)
  54.359 +        // This works better than the PT_TRACE_ME approach.
  54.360 +        // However, it presents a problem: 
  54.361 +        //     http://pubs.opengroup.org/onlinepubs/009695399/functions/fork.html
  54.362 +        //     When the application calls fork() from a signal handler and any of the
  54.363 +        //     fork handlers registered by pthread_atfork() calls a function that is
  54.364 +        //     not asynch-signal-safe, the behavior is undefined.
  54.365 +        // We may need to provide two pathways within this function, one of which 
  54.366 +        // doesn't fork and instead uses PT_TRACE_ME.
  54.367 +        int  pid = fork();
  54.368 +        int  status;
  54.369 +        bool present = false;
  54.370 +
  54.371 +        if (pid == -1) // If fork failed...
  54.372 +        {
  54.373 +            // perror("fork");
  54.374 +        }
  54.375 +        else if (pid == 0) // If we are the child process...
  54.376 +        {
  54.377 +            int ppid = getppid();
  54.378 +
  54.379 +          #if defined(OVR_OS_LINUX)
  54.380 +            if (ptrace(PTRACE_ATTACH, ppid, nullptr, nullptr) == 0)
  54.381 +          #else
  54.382 +            if (ptrace(PT_ATTACH, ppid, nullptr, nullptr) == 0)
  54.383 +          #endif
  54.384 +            {
  54.385 +                waitpid(ppid, nullptr, 0);
  54.386 +
  54.387 +              #if defined(OVR_OS_LINUX)
  54.388 +                ptrace(PTRACE_CONT, getppid(), nullptr, nullptr);
  54.389 +                ptrace(PTRACE_DETACH, getppid(), nullptr, nullptr);
  54.390 +              #else
  54.391 +                ptrace(PT_CONTINUE, getppid(), nullptr, nullptr);
  54.392 +                ptrace(PT_DETACH, getppid(), nullptr, nullptr);
  54.393 +              #endif
  54.394 +            }
  54.395 +            else
  54.396 +            {
  54.397 +                // ptrace failed so the debugger is present.
  54.398 +                present = true;
  54.399 +            }
  54.400 +
  54.401 +            exit(present ? 1 : 0); // The WEXITSTATUS call below will read this exit value.
  54.402 +        }
  54.403 +        else // Else we are the original process.
  54.404 +        {
  54.405 +            waitpid(pid, &status, 0);
  54.406 +            present = WEXITSTATUS(status) ? true : false; // Read the exit value from the child's call to exit.
  54.407 +        }
  54.408 +
  54.409 +        return present;
  54.410 +
  54.411 +    #elif defined(PT_TRACE_ME) && !defined(OVR_OS_ANDROID)
  54.412 +        return (ptrace(PT_TRACE_ME, 0, 1, 0) < 0);
  54.413 +
  54.414 +    #else
  54.415 +        return false;
  54.416 +    #endif
  54.417 +}
  54.418 +
  54.419 +
  54.420 +// Exits the process with the given exit code.
  54.421 +void ExitProcess(intptr_t processReturnValue)
  54.422 +{
  54.423 +    exit((int)processReturnValue);
  54.424 +}
  54.425 +
  54.426 +
  54.427 +void* SafeMMapAlloc(size_t size)
  54.428 +{
  54.429 +    #if defined(OVR_OS_MS)
  54.430 +        return VirtualAlloc(nullptr, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); // size is rounded up to a page. // Returned memory is 0-filled.
  54.431 +
  54.432 +    #elif defined(OVR_OS_MAC) || defined(OVR_OS_UNIX)
  54.433 +        #if !defined(MAP_FAILED)
  54.434 +            #define MAP_FAILED ((void*)-1)
  54.435 +        #endif
  54.436 +
  54.437 +        void* result = mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); // Returned memory is 0-filled.
  54.438 +        if(result == MAP_FAILED) // mmap returns MAP_FAILED (-1) upon failure.
  54.439 +            result = nullptr;
  54.440 +        return result;
  54.441 +    #endif
  54.442 +}
  54.443 +
  54.444 +
  54.445 +void SafeMMapFree(const void* memory, size_t size)
  54.446 +{
  54.447 +    #if defined(OVR_OS_MS)
  54.448 +        OVR_UNUSED(size);
  54.449 +        VirtualFree(const_cast<void*>(memory), 0, MEM_RELEASE);
  54.450 +
  54.451 +    #elif defined(OVR_OS_MAC) || defined(OVR_OS_UNIX)
  54.452 +        size_t pageSize = getpagesize();
  54.453 +        size = (((size + (pageSize - 1)) / pageSize) * pageSize);
  54.454 +        munmap(const_cast<void*>(memory), size); // Must supply the size to munmap.
  54.455 +    #endif
  54.456 +}
  54.457 +
  54.458 +
  54.459 +// Note that we can't just return sizeof(void*) == 8, as we may have the case of a
  54.460 +// 32 bit app running on a 64 bit operating system.
  54.461 +static bool Is64BitOS()
  54.462 +{
  54.463 +    #if (OVR_PTR_SIZE >= 8)
  54.464 +        return true;
  54.465 +
  54.466 +    #elif defined(OVR_OS_WIN32) || defined(OVR_OS_WIN64)
  54.467 +        BOOL is64BitOS = FALSE;
  54.468 +        bool IsWow64ProcessPresent = (GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "IsWow64Process") != nullptr);
  54.469 +        return (IsWow64ProcessPresent && IsWow64Process(GetCurrentProcess(), &is64BitOS) && is64BitOS);
  54.470 +
  54.471 +    #elif defined(OVR_OS_MAC) || defined(OVR_OS_UNIX)
  54.472 +        utsname utsName;
  54.473 +        memset(&utsName, 0, sizeof(utsName));
  54.474 +        return (uname(&utsName) == 0) && (strcmp(utsName.machine, "x86_64") == 0);
  54.475 +
  54.476 +    #else
  54.477 +        return false;
  54.478 +    #endif
  54.479 +}
  54.480 +
  54.481 +
  54.482 +// The output will always be 0-terminated.
  54.483 +// Returns the required strlen of the output.
  54.484 +// Returns (size_t)-1 on failure.
  54.485 +size_t SpawnShellCommand(const char* shellCommand, char* output, size_t outputCapacity)
  54.486 +{
  54.487 +    #if defined(OVR_OS_UNIX) || defined(OVR_OS_APPLE)
  54.488 +        FILE* pFile = popen(shellCommand, "r");
  54.489 +    
  54.490 +        if(pFile)
  54.491 +        {
  54.492 +            size_t requiredLength = 0;
  54.493 +            char buffer[256];
  54.494 +        
  54.495 +            while(fgets(buffer, sizeof(buffer), pFile)) // fgets 0-terminates the buffer.
  54.496 +            {
  54.497 +                size_t length = OVR_strlen(buffer);
  54.498 +                requiredLength += length;
  54.499 +            
  54.500 +                if(outputCapacity)
  54.501 +                {
  54.502 +                    OVR_strlcpy(output, buffer, outputCapacity);
  54.503 +                    length = MIN(outputCapacity, length);
  54.504 +                }
  54.505 +
  54.506 +                output         += length;
  54.507 +                outputCapacity -= length;
  54.508 +            }
  54.509 +        
  54.510 +            pclose(pFile);
  54.511 +            return requiredLength;
  54.512 +        }
  54.513 +    #else
  54.514 +        // To do. Properly solving this on Windows requires a bit of code.
  54.515 +        OVR_UNUSED(shellCommand);
  54.516 +        OVR_UNUSED(output);
  54.517 +        OVR_UNUSED(outputCapacity);
  54.518 +    #endif
  54.519 +
  54.520 +    return (size_t)-1;
  54.521 +}
  54.522 +
  54.523 +
  54.524 +// Retrieves a directory path which ends with a path separator.
  54.525 +// Returns the required strlen of the path.
  54.526 +// Guarantees the presence of the directory upon returning true.
  54.527 +static size_t GetUserDocumentsDirectory(char* directoryPath, size_t directoryPathCapacity)
  54.528 +{
  54.529 +    #if defined(OVR_OS_MS)
  54.530 +        wchar_t pathW[MAX_PATH + 1]; // +1 because we append a path separator.
  54.531 +        HRESULT hr = SHGetFolderPathW(nullptr, CSIDL_APPDATA | CSIDL_FLAG_CREATE, nullptr, SHGFP_TYPE_CURRENT, pathW);
  54.532 +
  54.533 +        if(SUCCEEDED(hr))
  54.534 +        {
  54.535 +            OVR_UNUSED(directoryPathCapacity);
  54.536 +
  54.537 +            intptr_t requiredUTF8Length = OVR::UTF8Util::GetEncodeStringSize(pathW); // Returns required strlen.
  54.538 +            if(requiredUTF8Length < MAX_PATH) // We need space for a trailing path separator.
  54.539 +            {
  54.540 +                OVR::UTF8Util::EncodeString(directoryPath, pathW, -1);
  54.541 +                OVR::OVR_strlcat(directoryPath, "\\", directoryPathCapacity);
  54.542 +            }        
  54.543 +
  54.544 +            return (requiredUTF8Length + 1);
  54.545 +        }
  54.546 +
  54.547 +    #elif defined(OVR_OS_MAC)
  54.548 +        // This is the same location that Apple puts its OS-generated .crash files.
  54.549 +        const char* home = getenv("HOME");
  54.550 +        size_t requiredStrlen = OVR::OVR_snprintf(directoryPath, directoryPathCapacity, "%s/Library/Logs/DiagnosticReports/", home ? home : "/Users/Shared/Logs/DiagnosticReports/");
  54.551 +        // To do: create the directory if it doesn't already exist.
  54.552 +        return requiredStrlen;
  54.553 +    
  54.554 +    #elif defined(OVR_OS_UNIX) || defined(OVR_OS_MAC)
  54.555 +        const char* home = getenv("HOME");
  54.556 +        size_t requiredStrlen = OVR::OVR_snprintf(directoryPath, directoryPathCapacity, "%s/Library/", home ? home : "/Users/Shared/");
  54.557 +        // To do: create the directory if it doesn't already exist.
  54.558 +        return requiredStrlen;
  54.559 +    #endif
  54.560 +
  54.561 +    return 0;
  54.562 +}
  54.563 +
  54.564 +
  54.565 +// Retrieves the name of the given thread.
  54.566 +// To do: Move this to OVR_Threads.h
  54.567 +bool GetThreadName(OVR::ThreadHandle threadHandle, char* threadName, size_t threadNameCapacity)
  54.568 +{
  54.569 +    #if defined(OVR_OS_APPLE) || defined(OVR_OS_LINUX)
  54.570 +        int result = pthread_getname_np((pthread_t)threadHandle, threadName, threadNameCapacity);
  54.571 +        if(result == 0)
  54.572 +            return true;
  54.573 +    #else
  54.574 +        // This is not currently possible on Windows, as only the debugger stores the thread name. We could potentially use a vectored 
  54.575 +        // exception handler to catch all thread name exceptions (0x406d1388) and record them in a static list at runtime. To detect
  54.576 +        // thread exit we could use WMI Win32_ThreadStopTrace. Maintain a list of thread names between these two events.
  54.577 +        OVR_UNUSED(threadHandle);
  54.578 +        OVR_UNUSED(threadNameCapacity);
  54.579 +    #endif
  54.580 +
  54.581 +    if(threadNameCapacity)
  54.582 +        threadName[0] = 0;
  54.583 +
  54.584 +    return false;
  54.585 +}
  54.586 +
  54.587 +
  54.588 +OVR::ThreadSysId ConvertThreadHandleToThreadSysId(OVR::ThreadHandle threadHandle)
  54.589 +{
  54.590 +    #if defined(OVR_OS_WIN64)
  54.591 +        return (OVR::ThreadSysId)::GetThreadId(threadHandle); // Requires THREAD_QUERY_INFORMATION privileges.
  54.592 +
  54.593 +    #elif defined(OVR_OS_WIN32)
  54.594 +        typedef DWORD (WINAPI *GetThreadIdFunc)(HANDLE);
  54.595 +
  54.596 +        static volatile bool sInitialized = false;
  54.597 +        static GetThreadIdFunc spGetThreadIdFunc = nullptr;
  54.598 +        static NtQueryInformationThreadFunc spNtQueryInformationThread = nullptr;
  54.599 +
  54.600 +        if(!sInitialized)
  54.601 +        {
  54.602 +            HMODULE hKernel32 = GetModuleHandleA("kernel32.dll");
  54.603 +            if(hKernel32)
  54.604 +                spGetThreadIdFunc = (GetThreadIdFunc)(uintptr_t)GetProcAddress(hKernel32, "GetThreadId");
  54.605 +
  54.606 +            if(!spGetThreadIdFunc)
  54.607 +            {
  54.608 +                HMODULE hNTDLL = GetModuleHandleA("ntdll.dll");
  54.609 +
  54.610 +                if(hNTDLL)
  54.611 +                    spNtQueryInformationThread = (NtQueryInformationThreadFunc)(uintptr_t)GetProcAddress(hNTDLL, "NtQueryInformationThread");
  54.612 +            }
  54.613 +
  54.614 +            sInitialized = true;
  54.615 +        }
  54.616 +
  54.617 +        if(spGetThreadIdFunc)
  54.618 +            return (OVR::ThreadSysId)spGetThreadIdFunc(threadHandle);
  54.619 +
  54.620 +        if(spNtQueryInformationThread)
  54.621 +        {
  54.622 +            THREAD_BASIC_INFORMATION tbi;
  54.623 +
  54.624 +            if(spNtQueryInformationThread(threadHandle, 0, &tbi, sizeof(tbi), nullptr) == 0)
  54.625 +                return (OVR::ThreadSysId)tbi.UniqueThreadId;
  54.626 +        }
  54.627 +
  54.628 +        return OVR_THREADSYSID_INVALID;
  54.629 +    
  54.630 +    #elif defined(OVR_OS_APPLE)
  54.631 +        mach_port_t threadSysId = pthread_mach_thread_np((pthread_t)threadHandle);  // OS 10.4 and later.
  54.632 +        return (ThreadSysId)threadSysId;
  54.633 +
  54.634 +    #elif defined(OVR_OS_LINUX)
  54.635 +
  54.636 +        // I believe we can usually (though not portably) intepret the pthread_t as a pointer to a struct whose first member is a lwp id.
  54.637 +        OVR_UNUSED(threadHandle);
  54.638 +        return OVR_THREADSYSID_INVALID;
  54.639 +
  54.640 +    #else
  54.641 +        OVR_UNUSED(threadHandle);
  54.642 +        return OVR_THREADSYSID_INVALID;
  54.643 +    #endif
  54.644 +}
  54.645 +
  54.646 +
  54.647 +OVR::ThreadHandle ConvertThreadSysIdToThreadHandle(OVR::ThreadSysId threadSysId)
  54.648 +{
  54.649 +    #if defined(OVR_OS_MS)
  54.650 +        // We currently request the given rights because that's what users of this function typically need it for. Ideally there would 
  54.651 +        // be a way to specify the requested rights in order to avoid the problem if we need only a subset of them but can't get it.
  54.652 +        // The solution we use below to try opening with successively reduced rights will work for our uses here but isn't a good general solution to this.
  54.653 +        OVR::ThreadHandle threadHandle = ::OpenThread(THREAD_SUSPEND_RESUME | THREAD_GET_CONTEXT | THREAD_QUERY_INFORMATION, TRUE, (DWORD)threadSysId);
  54.654 +
  54.655 +        if(threadHandle == OVR_THREADHANDLE_INVALID)
  54.656 +        {
  54.657 +            threadHandle = ::OpenThread(THREAD_GET_CONTEXT | THREAD_QUERY_INFORMATION, TRUE, (DWORD)threadSysId);
  54.658 +
  54.659 +            if(threadHandle == OVR_THREADHANDLE_INVALID)
  54.660 +                threadHandle = ::OpenThread(THREAD_QUERY_INFORMATION, TRUE, (DWORD)threadSysId);
  54.661 +        }
  54.662 +
  54.663 +        return threadHandle;
  54.664 +    #elif defined(OVR_OS_MAC)
  54.665 +        return (ThreadHandle)pthread_from_mach_thread_np((mach_port_t)threadSysId);
  54.666 +    #else
  54.667 +        return (ThreadHandle)threadSysId;
  54.668 +    #endif
  54.669 +}
  54.670 +
  54.671 +
  54.672 +void FreeThreadHandle(OVR::ThreadHandle threadHandle)
  54.673 +{
  54.674 +    #if defined(OVR_OS_MS)
  54.675 +        if(threadHandle != OVR_THREADHANDLE_INVALID)
  54.676 +            ::CloseHandle(threadHandle);
  54.677 +    #else
  54.678 +        OVR_UNUSED(threadHandle);
  54.679 +    #endif
  54.680 +}
  54.681 +
  54.682 +
  54.683 +OVR::ThreadSysId GetCurrentThreadSysId()
  54.684 +{
  54.685 +    #if defined(OVR_OS_MS)
  54.686 +        return ::GetCurrentThreadId();
  54.687 +    #elif defined(OVR_OS_APPLE)
  54.688 +        return (ThreadSysId)mach_thread_self();
  54.689 +    #else
  54.690 +        return (ThreadSysId)pthread_self();
  54.691 +    #endif
  54.692 +}
  54.693 +
  54.694 +
  54.695 +
  54.696 +static void GetCurrentProcessFilePath(char* appPath, size_t appPathCapacity)
  54.697 +{
  54.698 +    appPath[0] = 0;
  54.699 +
  54.700 +    #if defined(OVR_OS_MS)
  54.701 +        wchar_t pathW[MAX_PATH];
  54.702 +        GetModuleFileNameW(0, pathW, (DWORD)OVR_ARRAY_COUNT(pathW));
  54.703 +    
  54.704 +        size_t requiredUTF8Length = (size_t)OVR::UTF8Util::GetEncodeStringSize(pathW); // Returns required strlen.
  54.705 +    
  54.706 +        if(requiredUTF8Length < appPathCapacity)
  54.707 +        {
  54.708 +            OVR::UTF8Util::EncodeString(appPath, pathW, -1);
  54.709 +        }
  54.710 +        else
  54.711 +        {
  54.712 +            appPath[0] = 0;
  54.713 +        }
  54.714 +    
  54.715 +    #elif defined(OVR_OS_APPLE)
  54.716 +        struct BunderFolder
  54.717 +        {
  54.718 +            // Returns true if pStr ends with pFind, case insensitively.
  54.719 +            // To do: Move OVR_striend to OVRKernel/Std.h
  54.720 +            static bool OVR_striend(const char* pStr, const char* pFind, size_t strLength = (size_t)-1, size_t findLength = (size_t)-1)
  54.721 +            {
  54.722 +                if(strLength == (size_t)-1)
  54.723 +                    strLength = OVR_strlen(pStr);
  54.724 +                if(findLength == (size_t)-1)
  54.725 +                    findLength = OVR_strlen(pFind);
  54.726 +                if(strLength >= findLength)
  54.727 +                    return (OVR_stricmp(pStr + strLength - findLength, pFind) == 0);
  54.728 +                return false;
  54.729 +            }
  54.730 +            
  54.731 +            static bool IsBundleFolder(const char* filePath)
  54.732 +            {
  54.733 +                // https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/AboutBundles/AboutBundles.html#//apple_ref/doc/uid/10000123i-CH100-SW1
  54.734 +                static const char* extensionArray[] = { ".app", ".bundle", ".framework", ".plugin", ".kext" };
  54.735 +                
  54.736 +                for(size_t i = 0; i < OVR_ARRAY_COUNT(extensionArray); i++)
  54.737 +                {
  54.738 +                    if(OVR_striend(filePath, extensionArray[i]))
  54.739 +                        return true;
  54.740 +                }
  54.741 +                
  54.742 +                return false;
  54.743 +            }
  54.744 +        };
  54.745 +    
  54.746 +        char     appPathTemp[PATH_MAX];
  54.747 +        uint32_t appPathTempCapacity32 = PATH_MAX;
  54.748 +        size_t   requiredStrlen = appPathCapacity;
  54.749 +    
  54.750 +        if(_NSGetExecutablePath(appPathTemp, &appPathTempCapacity32) == 0)
  54.751 +        {
  54.752 +            char appPathTempReal[PATH_MAX];
  54.753 +
  54.754 +            if(realpath(appPathTemp, appPathTempReal))  // If the path is a symbolic link, this converts it to the real path.
  54.755 +            {
  54.756 +                // To consider: Enable reading the internal bundle executable path. An application on Mac may in
  54.757 +                // fact be within a file bundle, which is an private file system within a file. With Objective C
  54.758 +                // we could use: [[NSWorkspace sharedWorkspace] isFilePackageAtPath:fullPath];
  54.759 +                bool shouldReadTheBunderPath = false;
  54.760 +                
  54.761 +                if(shouldReadTheBunderPath)
  54.762 +                {
  54.763 +                    // We recursively call dirname() until we find .app/.bundle/.plugin as a directory name.
  54.764 +                    OVR_strlcpy(appPathTemp, appPathTempReal, OVR_ARRAY_COUNT(appPathTemp));
  54.765 +                    bool found = BunderFolder::IsBundleFolder(appPathTemp);
  54.766 + 
  54.767 +                    while(!found && OVR_strcmp(appPathTemp, ".") && OVR_strcmp(appPathTemp, "/"))
  54.768 +                    {
  54.769 +                        OVR_strlcpy(appPathTemp, dirname(appPathTemp), OVR_ARRAY_COUNT(appPathTemp));
  54.770 +                        found = BunderFolder::IsBundleFolder(appPathTemp);
  54.771 +                    }
  54.772 +
  54.773 +                    if(found) // If somewhere above we found a parent bundle container...
  54.774 +                        requiredStrlen = OVR_strlcpy(appPath, appPathTemp, appPathCapacity);
  54.775 +                    else
  54.776 +                        requiredStrlen = OVR_strlcpy(appPath, appPathTempReal, appPathCapacity);
  54.777 +                }
  54.778 +                else
  54.779 +                {
  54.780 +                    requiredStrlen = OVR_strlcpy(appPath, appPathTempReal, appPathCapacity);
  54.781 +                }
  54.782 +            }
  54.783 +        }
  54.784 +    
  54.785 +        if(requiredStrlen >= appPathCapacity)
  54.786 +            appPath[0] = '\0';
  54.787 +    
  54.788 +    #elif defined(OVR_OS_LINUX)
  54.789 +        ssize_t length = readlink("/proc/self/exe", appPath, appPathCapacity);
  54.790 +    
  54.791 +        if((length != -1) && ((size_t)length < (appPathCapacity - 1)))
  54.792 +        {
  54.793 +            appPath[length] = '\0';
  54.794 +        }
  54.795 +    #endif
  54.796 +}
  54.797 +
  54.798 +
  54.799 +static const char* GetFileNameFromPath(const char* filePath)
  54.800 +{
  54.801 +    #if defined(OVR_OS_MS)
  54.802 +    const char* lastPathSeparator = max(strrchr(filePath, '\\'), strrchr(filePath, '/')); // Microsoft APIs are inconsistent with respect to allowing / as a path separator.
  54.803 +    #else
  54.804 +    const char* lastPathSeparator = strrchr(filePath, '/');
  54.805 +    #endif
  54.806 +    
  54.807 +    if(lastPathSeparator)
  54.808 +        return lastPathSeparator + 1;
  54.809 +    
  54.810 +    return filePath;
  54.811 +}
  54.812 +
  54.813 +
  54.814 +
  54.815 +static void FormatDateTime(char* buffer, size_t bufferCapacity, time_t timeValue, bool getDate, bool getTime, bool localDateTime, bool fileNameSafeCharacters = false)
  54.816 +{
  54.817 +    char      temp[128];
  54.818 +    const tm* pTime = localDateTime ? localtime(&timeValue) : gmtime(&timeValue);
  54.819 +    
  54.820 +    if(bufferCapacity)
  54.821 +        buffer[0] = 0;
  54.822 +
  54.823 +    if(getDate)
  54.824 +    {
  54.825 +        const char* format = fileNameSafeCharacters ? "%Y-%m-%d" : "%Y/%m/%d";
  54.826 +        strftime(temp, OVR_ARRAY_COUNT(temp), format, pTime);
  54.827 +        OVR::OVR_strlcpy(buffer, temp, bufferCapacity);
  54.828 +    }
  54.829 +
  54.830 +    if(getTime)
  54.831 +    {
  54.832 +        const char* format = fileNameSafeCharacters ? " %H.%M.%S" : " %H:%M:%S";
  54.833 +        strftime(temp, OVR_ARRAY_COUNT(temp), (getDate ? format : format + 1), pTime);
  54.834 +        OVR::OVR_strlcat(buffer, temp, bufferCapacity);
  54.835 +    }
  54.836 +}
  54.837 +
  54.838 +
  54.839 +static void GetOSVersionName(char* versionName, size_t versionNameCapacity)
  54.840 +{
  54.841 +    #if defined(OVR_OS_MS)
  54.842 +        const char* name = "unknown";
  54.843 +
  54.844 +        OSVERSIONINFOEXW vi;
  54.845 +        memset(&vi, 0, sizeof(vi));
  54.846 +        vi.dwOSVersionInfoSize = sizeof(vi);
  54.847 +
  54.848 +        if(GetVersionExW((LPOSVERSIONINFOW)&vi))
  54.849 +        {
  54.850 +            if(vi.dwMajorVersion >= 7)
  54.851 +            {
  54.852 +                // Unknown recent version.
  54.853 +            }
  54.854 +            if(vi.dwMajorVersion >= 6)
  54.855 +            {
  54.856 +                if(vi.dwMinorVersion >= 4)
  54.857 +                    name = "Windows 10";
  54.858 +                else if(vi.dwMinorVersion >= 3)
  54.859 +                {
  54.860 +                    if(vi.wProductType == VER_NT_WORKSTATION)
  54.861 +						name = "Windows 8.1";
  54.862 +					else
  54.863 +						name = "Windows Server 2012 R2";
  54.864 +                }
  54.865 +                else if(vi.dwMinorVersion >= 2)
  54.866 +                {
  54.867 +                    if(vi.wProductType == VER_NT_WORKSTATION)
  54.868 +						name = "Windows 8";
  54.869 +					else
  54.870 +						name = "Windows Server 2012";
  54.871 +                }
  54.872 +                else if(vi.dwMinorVersion >= 1)
  54.873 +                {
  54.874 +                    if(vi.wProductType == VER_NT_WORKSTATION)
  54.875 +                        name = "Windows 7";
  54.876 +                    else
  54.877 +                        name = "Windows Server 2008 R2";
  54.878 +                }
  54.879 +                else
  54.880 +                {
  54.881 +                    if(vi.wProductType == VER_NT_WORKSTATION)
  54.882 +                        name = "Windows Vista";
  54.883 +                    else
  54.884 +                        name = "Windows Server 2008";
  54.885 +                }
  54.886 +            }
  54.887 +            else if(vi.dwMajorVersion >= 5)
  54.888 +            {
  54.889 +                if(vi.dwMinorVersion == 0)
  54.890 +                    name = "Windows 2000";
  54.891 +                else if(vi.dwMinorVersion == 1)
  54.892 +                    name = "Windows XP";
  54.893 +                else // vi.dwMinorVersion == 2
  54.894 +                {
  54.895 +                    if(GetSystemMetrics(SM_SERVERR2) != 0)
  54.896 +                        name = "Windows Server 2003 R2";
  54.897 +                    else if(vi.wSuiteMask & VER_SUITE_WH_SERVER)
  54.898 +                        name = "Windows Home Server";
  54.899 +                    if(GetSystemMetrics(SM_SERVERR2) == 0)
  54.900 +                        name = "Windows Server 2003";
  54.901 +                    else
  54.902 +                        name = "Windows XP Professional x64 Edition";
  54.903 +                }
  54.904 +            }
  54.905 +            else
  54.906 +                name = "Windows 98 or earlier";
  54.907 +        }
  54.908 +
  54.909 +        OVR_strlcpy(versionName, name, versionNameCapacity);
  54.910 +
  54.911 +    #elif defined(OVR_OS_UNIX) || defined(OVR_OS_APPLE)
  54.912 +        utsname utsName;
  54.913 +        memset(&utsName, 0, sizeof(utsName));
  54.914 +
  54.915 +        if(uname(&utsName) == 0)
  54.916 +            OVR_snprintf(versionName, versionNameCapacity, "%s %s %s %s", utsName.sysname, utsName.release, utsName.version, utsName.machine);
  54.917 +        else
  54.918 +            OVR_snprintf(versionName, versionNameCapacity, "Unix");
  54.919 +    #endif
  54.920 +}
  54.921 +
  54.922 +
  54.923 +
  54.924 +
  54.925 +void CreateException(CreateExceptionType exceptionType)
  54.926 +{
  54.927 +    char buffer[1024] = {};
  54.928 +
  54.929 +    switch(exceptionType)
  54.930 +    {
  54.931 +        case kCETAccessViolation:
  54.932 +        {
  54.933 +            int* pNullPtr = reinterpret_cast<int*>((rand() / 2) / RAND_MAX);
  54.934 +            pNullPtr[0] = 0;    // This line should generate an exception.
  54.935 +            sprintf(buffer, "%p", pNullPtr);
  54.936 +            break;
  54.937 +        }
  54.938 +
  54.939 +        case kCETDivideByZero:
  54.940 +        {
  54.941 +            int smallValue = 1;
  54.942 +            int largeValue = (1000 * exceptionType);
  54.943 +            int divByZero = (smallValue / largeValue); // This line should generate a div/0 exception.
  54.944 +            sprintf(buffer, "%d", divByZero);
  54.945 +            break;
  54.946 +        }
  54.947 +
  54.948 +        case kCETIllegalInstruction:
  54.949 +        {
  54.950 +            #if defined(OVR_CPU_X86) || (defined(OVR_CPU_X86_64) && !defined(OVR_CC_MSVC)) // (if x86) or (if x64 and any computer but VC++)...
  54.951 +                #if defined(OVR_CC_MSVC)
  54.952 +                    __asm ud2
  54.953 +                #else // e.g. GCC
  54.954 +                    asm volatile("ud2");
  54.955 +                #endif
  54.956 +
  54.957 +            #elif defined(OVR_CPU_X86_64) && (defined(OVR_OS_MS) && defined(PAGE_EXECUTE_READWRITE))
  54.958 +                // VC++ for x64 doesn't support inline asm.
  54.959 +                void*   pVoid          = _AddressOfReturnAddress();
  54.960 +                void**  ppVoid         = reinterpret_cast<void**>(pVoid);
  54.961 +                void*   pReturnAddress = *ppVoid;
  54.962 +                DWORD   dwProtectPrev  = 0;
  54.963 +
  54.964 +                if(VirtualProtect(pReturnAddress, 2, PAGE_EXECUTE_READWRITE, &dwProtectPrev)) // If we can set the memory to be executable...
  54.965 +                {
  54.966 +                    // Modify the code we return to.
  54.967 +                    uint8_t asm_ud2[] = { 0x0f, 0x0b };
  54.968 +                    memcpy(pReturnAddress, asm_ud2, sizeof(asm_ud2));
  54.969 +                    VirtualProtect(pReturnAddress, 2, dwProtectPrev, &dwProtectPrev);
  54.970 +                }
  54.971 +                else
  54.972 +                {
  54.973 +                    // To do: Fix this.
  54.974 +                }
  54.975 +
  54.976 +            #else
  54.977 +                // To do: Fix this.
  54.978 +            #endif
  54.979 +
  54.980 +            break;
  54.981 +        }
  54.982 +
  54.983 +        case kCETStackCorruption:
  54.984 +        {
  54.985 +            size_t size = (sizeof(buffer) * 16) - (rand() % 16);
  54.986 +            char*  pOutsizeStack = buffer - ((sizeof(buffer) * 16) + (rand() % 16));
  54.987 +
  54.988 +            memset(buffer, 0, size); 
  54.989 +            memset(pOutsizeStack, 0, size); // This line should generate an exception, or an exception will be generated upon return from this function.
  54.990 +            break;
  54.991 +        }
  54.992 +
  54.993 +        case kCETStackOverflow:
  54.994 +        {
  54.995 +            CreateException(exceptionType);             // Call ourselves recursively. This line should generate a div/0 exception.
  54.996 +            sprintf(buffer, "%d", exceptionType);
  54.997 +            break;
  54.998 +        }
  54.999 +
 54.1000 +        case kCETAlignment:
 54.1001 +        {
 54.1002 +            // Not all platforms generate alignment exceptions. Some internally handle it.
 54.1003 +            void*     pAligned      = malloc(16);
 54.1004 +            char*     pMisaligned   = (char*)pAligned + 1;
 54.1005 +            uint64_t* pMisaligned64 = reinterpret_cast<uint64_t*>(pMisaligned);
 54.1006 +
 54.1007 +            *pMisaligned64 = 0; // This line should generate an exception.
 54.1008 +            free(pAligned);
 54.1009 +            break;
 54.1010 +        }
 54.1011 +
 54.1012 +        case kCETFPU:
 54.1013 +            // Platforms usually have FPU exceptions disabled. In order to test FPU exceptions we will need to at least
 54.1014 +            // temporarily disable them before executing code here to generate such exceptions.
 54.1015 +            // To do.
 54.1016 +            break;
 54.1017 +
 54.1018 +        case kCETTrap:
 54.1019 +            // To do. This is hardware-specific.
 54.1020 +            break;
 54.1021 +    }
 54.1022 +}
 54.1023 +
 54.1024 +
 54.1025 +
 54.1026 +
 54.1027 +#if defined(OVR_OS_MS)
 54.1028 +    typedef BOOL    (WINAPI * StackWalk64Type)(DWORD MachineType, HANDLE hProcess, HANDLE hThread, LPSTACKFRAME64 StackFrame, PVOID ContextRecord, PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine, PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine, PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine, PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress);
 54.1029 +    typedef PVOID   (WINAPI * SymFunctionTableAccess64Type)(HANDLE hProcess, DWORD64 dwAddr);
 54.1030 +    typedef DWORD64 (WINAPI * SymGetModuleBase64Type)(HANDLE hProcess, DWORD64 dwAddr);
 54.1031 +    typedef DWORD   (WINAPI * SymSetOptionsType)(DWORD SymOptions);
 54.1032 +    typedef BOOL    (WINAPI * SymInitializeWType)(HANDLE hProcess, PCWSTR UserSearchPath, BOOL fInvadeProcess);
 54.1033 +    typedef BOOL    (WINAPI * SymCleanupType)(HANDLE hProcess);
 54.1034 +    typedef DWORD64 (WINAPI * SymLoadModule64Type)(HANDLE hProcess, HANDLE hFile, PCSTR ImageName, PCSTR ModuleName, DWORD64 BaseOfDll, DWORD SizeOfDll);
 54.1035 +    typedef BOOL    (WINAPI * SymFromAddrType)(HANDLE hProcess, DWORD64 Address, PDWORD64 Displacement, PSYMBOL_INFO Symbol);
 54.1036 +    typedef BOOL    (WINAPI * SymGetLineFromAddr64Type)(HANDLE hProcess, DWORD64 qwAddr, PDWORD pdwDisplacement, PIMAGEHLP_LINE64 Line64);
 54.1037 +
 54.1038 +    StackWalk64Type              pStackWalk64;
 54.1039 +    SymFunctionTableAccess64Type pSymFunctionTableAccess64;
 54.1040 +    SymGetModuleBase64Type       pSymGetModuleBase64;
 54.1041 +    SymSetOptionsType            pSymSetOptions;
 54.1042 +    SymInitializeWType           pSymInitializeW;
 54.1043 +    SymCleanupType               pSymCleanup;
 54.1044 +    SymLoadModule64Type          pSymLoadModule64;
 54.1045 +    SymFromAddrType              pSymFromAddr;
 54.1046 +    SymGetLineFromAddr64Type     pSymGetLineFromAddr64;
 54.1047 +#endif
 54.1048 +
 54.1049 +
 54.1050 +
 54.1051 +SymbolLookup::SymbolLookup()
 54.1052 +  : initialized(false),
 54.1053 +    allowMemoryAllocation(true),
 54.1054 +    moduleListUpdated(false),
 54.1055 +    moduleInfoArray(),
 54.1056 +    moduleInfoArraySize(0)
 54.1057 +{
 54.1058 +}
 54.1059 +
 54.1060 +SymbolLookup::~SymbolLookup()
 54.1061 +{
 54.1062 +    Shutdown();
 54.1063 +}
 54.1064 +
 54.1065 +void SymbolLookup::AddSourceCodeDirectory(const char* pDirectory)
 54.1066 +{
 54.1067 +    OVR_UNUSED(pDirectory);
 54.1068 +}
 54.1069 +
 54.1070 +bool SymbolLookup::Initialize()
 54.1071 +{
 54.1072 +    if(!initialized)
 54.1073 +    {
 54.1074 +        #if defined(OVR_OS_MS)
 54.1075 +            // http://msdn.microsoft.com/en-us/library/windows/desktop/ms679294%28v=vs.85%29.aspx
 54.1076 +            HANDLE  hProcess = GetCurrentProcess();
 54.1077 +            HMODULE hDbgHelp = LoadLibraryW(L"DbgHelp.dll"); // It's best if the application supplies a recent version of this.
 54.1078 +
 54.1079 +            if(hDbgHelp)
 54.1080 +            {
 54.1081 +                pStackWalk64              = (StackWalk64Type)(uintptr_t)::GetProcAddress(hDbgHelp, "StackWalk64");
 54.1082 +                pSymFunctionTableAccess64 = (SymFunctionTableAccess64Type)(uintptr_t)::GetProcAddress(hDbgHelp, "SymFunctionTableAccess64");
 54.1083 +                pSymGetModuleBase64       = (SymGetModuleBase64Type)(uintptr_t)::GetProcAddress(hDbgHelp, "SymGetModuleBase64");
 54.1084 +                pSymSetOptions            = (SymSetOptionsType)(uintptr_t)::GetProcAddress(hDbgHelp, "SymSetOptions");
 54.1085 +                pSymInitializeW           = (SymInitializeWType)(uintptr_t)::GetProcAddress(hDbgHelp, "SymInitializeW");
 54.1086 +                pSymCleanup               = (SymCleanupType)(uintptr_t)::GetProcAddress(hDbgHelp, "SymCleanup");
 54.1087 +                pSymLoadModule64          = (SymLoadModule64Type)(uintptr_t)::GetProcAddress(hDbgHelp, "SymLoadModule64");
 54.1088 +                pSymFromAddr              = (SymFromAddrType)(uintptr_t)::GetProcAddress(hDbgHelp, "SymFromAddr");
 54.1089 +                pSymGetLineFromAddr64     = (SymGetLineFromAddr64Type)(uintptr_t)::GetProcAddress(hDbgHelp, "SymGetLineFromAddr64");
 54.1090 +            }
 54.1091 +
 54.1092 +            pSymSetOptions(SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS);
 54.1093 +
 54.1094 +            // To consider: Use a manually created search path:
 54.1095 +            // wchar_t searchPathW[4096]; // Semicolon-separated strings.
 54.1096 +            //     The current working directory of the application.
 54.1097 +            //     The directory of the application itself (GetModuleFileName).
 54.1098 +            //     The _NT_SYMBOL_PATH environment variable.
 54.1099 +            //     The _NT_ALTERNATE_SYMBOL_PATH environment variable.
 54.1100 +
 54.1101 +            if(pSymInitializeW(hProcess, nullptr /*searchPathW*/, FALSE))
 54.1102 +            {
 54.1103 +                initialized = true;
 54.1104 +            }
 54.1105 +        #endif
 54.1106 +    }
 54.1107 +
 54.1108 +    return true;
 54.1109 +}
 54.1110 +
 54.1111 +void SymbolLookup::Shutdown()
 54.1112 +{
 54.1113 +    if(initialized)
 54.1114 +    {
 54.1115 +        initialized = false;
 54.1116 +
 54.1117 +        #if defined(OVR_OS_MS)
 54.1118 +            HANDLE hProcess = GetCurrentProcess();
 54.1119 +
 54.1120 +            // SymCleanup should handle this for us.
 54.1121 +            //if(moduleListUpdated)
 54.1122 +            //{
 54.1123 +            //    for(size_t i = 0; i < moduleInfoArraySize; i++)
 54.1124 +            //        pSymUnloadModule64(hProcess, moduleInfoArray[i].baseAddress);
 54.1125 +            //}
 54.1126 +
 54.1127 +            moduleInfoArraySize = 0;
 54.1128 +
 54.1129 +            pSymCleanup(hProcess);
 54.1130 +        #endif
 54.1131 +    }
 54.1132 +}
 54.1133 +
 54.1134 +
 54.1135 +void SymbolLookup::EnableMemoryAllocation(bool enabled)
 54.1136 +{
 54.1137 +    allowMemoryAllocation = enabled;
 54.1138 +}
 54.1139 +
 54.1140 +
 54.1141 +OVR_DISABLE_MSVC_WARNING(4740) // flow in or out of inline asm code suppresses global optimization
 54.1142 +OVR_DISABLE_MSVC_WARNING(4748) // /GS can not protect parameters and local variables from local buffer overrun because optimizations are disabled in function
 54.1143 +
 54.1144 +
 54.1145 +size_t SymbolLookup::GetBacktrace(void* addressArray[], size_t addressArrayCapacity, size_t skipCount, void* platformThreadContext, OVR::ThreadSysId threadSysIdHelp)
 54.1146 +{
 54.1147 +    #if defined(OVR_OS_WIN64) || (defined(OVR_OS_MS) && defined(OVR_OS_CONSOLE))
 54.1148 +        OVR_UNUSED(threadSysIdHelp);
 54.1149 +    
 54.1150 +        if(platformThreadContext == nullptr)
 54.1151 +            return RtlCaptureStackBackTrace(1, (ULONG)addressArrayCapacity, addressArray, nullptr);
 54.1152 +
 54.1153 +        // We need to get the call stack of another thread.
 54.1154 +        size_t            frameIndex = 0;
 54.1155 +        CONTEXT           context;
 54.1156 +        PRUNTIME_FUNCTION pRuntimeFunction;
 54.1157 +        ULONG64           imageBase = 0;
 54.1158 +        ULONG64           imageBasePrev = 0;
 54.1159 +
 54.1160 +        memcpy(&context, (CONTEXT*)platformThreadContext, sizeof(CONTEXT));
 54.1161 +        context.ContextFlags = CONTEXT_CONTROL;
 54.1162 +
 54.1163 +        if(context.Rip && (frameIndex < addressArrayCapacity))
 54.1164 +            addressArray[frameIndex++] = (void*)(uintptr_t)context.Rip;
 54.1165 +
 54.1166 +        while(context.Rip && (frameIndex < addressArrayCapacity))
 54.1167 +        {
 54.1168 +            imageBasePrev = imageBase;
 54.1169 +            pRuntimeFunction = (PRUNTIME_FUNCTION)RtlLookupFunctionEntry(context.Rip, &imageBase, nullptr);
 54.1170 +
 54.1171 +            if(pRuntimeFunction)
 54.1172 +            {
 54.1173 +                VOID*   handlerData = nullptr;
 54.1174 +                ULONG64 establisherFramePointers[2] = { 0, 0 };
 54.1175 +                RtlVirtualUnwind(UNW_FLAG_NHANDLER, imageBase, context.Rip, pRuntimeFunction, &context, &handlerData,  establisherFramePointers, nullptr);                        
 54.1176 +            }
 54.1177 +            else
 54.1178 +            {
 54.1179 +                context.Rip  = (ULONG64)(*(PULONG64)context.Rsp);
 54.1180 +                context.Rsp += 8;
 54.1181 +            }
 54.1182 +
 54.1183 +            if(context.Rip && (frameIndex < addressArrayCapacity))
 54.1184 +            {
 54.1185 +                if(skipCount)
 54.1186 +                    --skipCount;
 54.1187 +                else
 54.1188 +                    addressArray[frameIndex++] = (void*)(uintptr_t)context.Rip;
 54.1189 +            }
 54.1190 +        }
 54.1191 +
 54.1192 +        return frameIndex;
 54.1193 +
 54.1194 +    #elif defined(OVR_OS_WIN32)
 54.1195 +        OVR_UNUSED(threadSysIdHelp);
 54.1196 +    
 54.1197 +        size_t frameIndex = 0;
 54.1198 +
 54.1199 +        if(pStackWalk64)
 54.1200 +        {
 54.1201 +            CONTEXT context;
 54.1202 +
 54.1203 +            if(platformThreadContext)
 54.1204 +            {
 54.1205 +                memcpy(&context, platformThreadContext, sizeof(context));
 54.1206 +                context.ContextFlags = CONTEXT_CONTROL;
 54.1207 +            }
 54.1208 +            else
 54.1209 +            {
 54.1210 +                memset(&context, 0, sizeof(context));
 54.1211 +                context.ContextFlags = CONTEXT_CONTROL;
 54.1212 +
 54.1213 +                __asm {
 54.1214 +                    mov context.Ebp, EBP
 54.1215 +                    mov context.Esp, ESP
 54.1216 +                    call GetEIP
 54.1217 +                    GetEIP:
 54.1218 +                    pop context.Eip
 54.1219 +                }
 54.1220 +            }
 54.1221 +
 54.1222 +            STACKFRAME64 sf;
 54.1223 +            memset(&sf, 0, sizeof(sf));
 54.1224 +            sf.AddrPC.Offset     = context.Eip;
 54.1225 +            sf.AddrPC.Mode       = AddrModeFlat;
 54.1226 +            sf.AddrStack.Offset  = context.Esp;
 54.1227 +            sf.AddrStack.Mode    = AddrModeFlat;
 54.1228 +            sf.AddrFrame.Offset  = context.Ebp;
 54.1229 +            sf.AddrFrame.Mode    = AddrModeFlat;
 54.1230 +
 54.1231 +            const HANDLE hCurrentProcess = ::GetCurrentProcess();
 54.1232 +            const HANDLE hCurrentThread  = ::GetCurrentThread();
 54.1233 +
 54.1234 +            if(!platformThreadContext) // If we are reading the current thread's call stack then we ignore this current function.
 54.1235 +                skipCount++;
 54.1236 +
 54.1237 +            while(frameIndex < addressArrayCapacity)
 54.1238 +            {
 54.1239 +                if(!pStackWalk64(IMAGE_FILE_MACHINE_I386, hCurrentProcess, hCurrentThread, &sf, &context, nullptr, pSymFunctionTableAccess64, pSymGetModuleBase64, nullptr))
 54.1240 +                    break;
 54.1241 +
 54.1242 +                if(sf.AddrFrame.Offset == 0)
 54.1243 +                    break;
 54.1244 +
 54.1245 +                if(skipCount)
 54.1246 +                    --skipCount;
 54.1247 +                else
 54.1248 +                    addressArray[frameIndex++] = ((void*)(uintptr_t)sf.AddrPC.Offset);
 54.1249 +            }
 54.1250 +        }
 54.1251 +
 54.1252 +        return frameIndex;
 54.1253 +
 54.1254 +    #elif defined(OVR_OS_APPLE)
 54.1255 +        struct StackFrame
 54.1256 +        {
 54.1257 +            StackFrame* pParentStackFrame;
 54.1258 +            void*       pReturnPC;
 54.1259 +        };
 54.1260 +        
 54.1261 +        void*       pInstruction;
 54.1262 +        StackFrame* pStackFrame;
 54.1263 +        size_t      frameIndex = 0;
 54.1264 +
 54.1265 +        if(platformThreadContext)
 54.1266 +        {
 54.1267 +            #if defined(OVR_CPU_ARM)
 54.1268 +                arm_thread_state_t* pThreadState = (arm_thread_state_t*)platformThreadContext;
 54.1269 +                pStackFrame  = (StackFrame*)pThreadState->__fp;
 54.1270 +                pInstruction = (void*)      pThreadState->__pc;
 54.1271 +                #define FrameIsAligned(pStackFrame) ((((uintptr_t)pStackFrame) & 0x1) == 0)
 54.1272 +            #elif defined(OVR_CPU_X86_64)
 54.1273 +                x86_thread_state_t* pThreadState = (x86_thread_state_t*)platformThreadContext;
 54.1274 +                pInstruction = (void*)      pThreadState->uts.ts64.__rip;
 54.1275 +                pStackFrame  = (StackFrame*)pThreadState->uts.ts64.__rbp;
 54.1276 +                #define FrameIsAligned(pStackFrame) ((((uintptr_t)pStackFrame) & 0xf) == 0)
 54.1277 +            #elif defined(OVR_CPU_X86)
 54.1278 +                x86_thread_state_t* pThreadState = (x86_thread_state_t*)platformThreadContext;
 54.1279 +                pInstruction = (void*)      pThreadState->uts.ts32.__eip;
 54.1280 +                pStackFrame  = (StackFrame*)pThreadState->uts.ts32.__ebp;
 54.1281 +                #define FrameIsAligned(pStackFrame) ((((uintptr_t)pStackFrame) & 0xf) == 8)
 54.1282 +            #endif
 54.1283 +
 54.1284 +            if(frameIndex < addressArrayCapacity)
 54.1285 +                addressArray[frameIndex++] = pInstruction;
 54.1286 +        }
 54.1287 +        else // Else get the current values...
 54.1288 +        {
 54.1289 +            pStackFrame = (StackFrame*)__builtin_frame_address(0);
 54.1290 +            GetInstructionPointer(pInstruction);
 54.1291 +        }
 54.1292 +
 54.1293 +        pthread_t   threadSelf         = pthread_self();
 54.1294 +        void*       pCurrentStackBase  = pthread_get_stackaddr_np(threadSelf);
 54.1295 +        void*       pCurrentStackLimit = (void*)((uintptr_t)pCurrentStackBase - pthread_get_stacksize_np(threadSelf));
 54.1296 +        bool        threadIsCurrent    = (platformThreadContext == nullptr) || (((void*)pStackFrame > pCurrentStackLimit) && ((void*)pStackFrame <= pCurrentStackBase));
 54.1297 +        StackFrame* pStackBase;
 54.1298 +        StackFrame* pStackLimit;
 54.1299 +    
 54.1300 +        if(threadIsCurrent)
 54.1301 +        {
 54.1302 +            pStackBase  = (StackFrame*)pCurrentStackBase;
 54.1303 +            pStackLimit = (StackFrame*)pCurrentStackLimit;
 54.1304 +        }
 54.1305 +        else if(threadSysIdHelp)
 54.1306 +        {
 54.1307 +            pthread_t threadHandle = pthread_from_mach_thread_np((mach_port_t)threadSysIdHelp);
 54.1308 +            pStackBase  = (StackFrame*)pthread_get_stackaddr_np(threadHandle);
 54.1309 +            pStackLimit = (StackFrame*)((uintptr_t)pStackBase - pthread_get_stacksize_np(threadHandle));
 54.1310 +        }
 54.1311 +        else
 54.1312 +        {   // We guess what the limits are.
 54.1313 +            pStackBase  = pStackFrame + ((384 * 1024) / sizeof(StackFrame));
 54.1314 +            pStackLimit = pStackFrame - ((384 * 1024) / sizeof(StackFrame));
 54.1315 +        }
 54.1316 +
 54.1317 +        if((frameIndex < addressArrayCapacity) && pStackFrame && FrameIsAligned(pStackFrame))
 54.1318 +        {
 54.1319 +            addressArray[frameIndex++] = pStackFrame->pReturnPC;
 54.1320 +
 54.1321 +            while(pStackFrame && pStackFrame->pReturnPC && (frameIndex < addressArrayCapacity))
 54.1322 +            {
 54.1323 +                pStackFrame = pStackFrame->pParentStackFrame;
 54.1324 +
 54.1325 +                if(pStackFrame && FrameIsAligned(pStackFrame) && pStackFrame->pReturnPC && (pStackFrame > pStackLimit) && (pStackFrame < pStackBase))
 54.1326 +                {
 54.1327 +                    if(skipCount)
 54.1328 +                        --skipCount;
 54.1329 +                    else
 54.1330 +                        addressArray[frameIndex++] = pStackFrame->pReturnPC;
 54.1331 +                }
 54.1332 +                else
 54.1333 +                    break;
 54.1334 +            }
 54.1335 +        }
 54.1336 +
 54.1337 +        return frameIndex;
 54.1338 +
 54.1339 +    #elif defined(OVR_OS_LINUX) && (defined( __LIBUNWIND__) || defined(LIBUNWIND_AVAIL))
 54.1340 +        // Libunwind-based solution. Requires installation of libunwind package.
 54.1341 +        // Libunwind isn't always safe for threads that are in signal handlers.
 54.1342 +        // An approach to get the callstack of another thread is to use signal injection into the target thread.
 54.1343 +    
 54.1344 +        OVR_UNUSED(platformThreadContext);
 54.1345 +        OVR_UNUSED(threadSysIdHelp);
 54.1346 +    
 54.1347 +        size_t        frameIndex = 0;
 54.1348 +        unw_cursor_t  cursor;
 54.1349 +        unw_context_t uc;
 54.1350 +        unw_word_t    ip, sp;
 54.1351 +
 54.1352 +        unw_getcontext(&uc);            // This gets the current thread's context. We could alternatively initialize another thread's context with it.
 54.1353 +        unw_init_local(&cursor, &uc);
 54.1354 +    
 54.1355 +        while((unw_step(&cursor) > 0) && (frameIndex < addressArrayCapacity))
 54.1356 +        {
 54.1357 +            // We can get the function name here too on some platforms with unw_get_proc_info() and unw_get_proc_name().
 54.1358 +            
 54.1359 +            if(skipCount)
 54.1360 +                --skipCount;
 54.1361 +            else
 54.1362 +            {
 54.1363 +                unw_get_reg(&cursor, UNW_REG_IP, &ip);
 54.1364 +                addressArray[frameIndex++] = (void*)ip;
 54.1365 +            }
 54.1366 +        }
 54.1367 +    
 54.1368 +        return frameIndex;
 54.1369 +	#else
 54.1370 +        OVR_UNUSED(addressArray);
 54.1371 +        OVR_UNUSED(addressArrayCapacity);
 54.1372 +        OVR_UNUSED(skipCount);
 54.1373 +        OVR_UNUSED(platformThreadContext);
 54.1374 +        OVR_UNUSED(threadSysIdHelp);
 54.1375 +
 54.1376 +        return 0;
 54.1377 +    #endif
 54.1378 +}
 54.1379 +
 54.1380 +
 54.1381 +size_t SymbolLookup::GetBacktraceFromThreadHandle(void* addressArray[], size_t addressArrayCapacity, size_t skipCount, OVR::ThreadHandle threadHandle)
 54.1382 +{
 54.1383 +    #if defined(OVR_OS_MS)
 54.1384 +        size_t count = 0;
 54.1385 +        DWORD  threadSysId = (DWORD)ConvertThreadHandleToThreadSysId(threadHandle);
 54.1386 +
 54.1387 +        // Compare to 0, compare to the self 'pseudohandle' and compare to the self id.
 54.1388 +        if((threadHandle == OVR_THREADHANDLE_INVALID) || (threadHandle == ::GetCurrentThread()) || (threadSysId == ::GetCurrentThreadId())) // If threadSysId refers to the current thread...
 54.1389 +            return GetBacktrace(addressArray, addressArrayCapacity, skipCount, nullptr);
 54.1390 +
 54.1391 +        // We are working with another thread. We need to suspend it and get its CONTEXT.
 54.1392 +        // Suspending other threads is risky, as they may be in some state that cannot be safely blocked.
 54.1393 +        BOOL  result = false;
 54.1394 +        DWORD suspendResult = ::SuspendThread(threadHandle); // Requires that the handle have THREAD_SUSPEND_RESUME rights.
 54.1395 +
 54.1396 +        if(suspendResult != (DWORD)-1) // Returns previous suspend count, or -1 if failed.
 54.1397 +        {
 54.1398 +            CONTEXT context;
 54.1399 +            context.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER; // Requires that the handle have THREAD_GET_CONTEXT rights.
 54.1400 +            result = ::GetThreadContext(threadHandle, &context);
 54.1401 +            count = GetBacktrace(addressArray, addressArrayCapacity, skipCount, &context);
 54.1402 +            suspendResult = ::ResumeThread(threadHandle);
 54.1403 +            OVR_ASSERT_AND_UNUSED(suspendResult != (DWORD)-1, suspendResult);
 54.1404 +        }
 54.1405 +
 54.1406 +        return count;
 54.1407 +
 54.1408 +    #elif defined(OVR_OS_APPLE)
 54.1409 +        mach_port_t threadSysID = pthread_mach_thread_np((pthread_t)threadHandle); // Convert pthread_t to mach thread id.
 54.1410 +        return GetBacktraceFromThreadSysId(addressArray, addressArrayCapacity, skipCount, (OVR::ThreadSysId)threadSysID);
 54.1411 +        
 54.1412 +    #elif defined(OVR_OS_LINUX)
 54.1413 +        // To do.
 54.1414 +        OVR_UNUSED(addressArray);
 54.1415 +        OVR_UNUSED(addressArrayCapacity);
 54.1416 +        OVR_UNUSED(skipCount);
 54.1417 +        OVR_UNUSED(threadHandle);
 54.1418 +        return 0;
 54.1419 +    #endif
 54.1420 +}
 54.1421 +
 54.1422 +
 54.1423 +size_t SymbolLookup::GetBacktraceFromThreadSysId(void* addressArray[], size_t addressArrayCapacity, size_t skipCount, OVR::ThreadSysId threadSysId)
 54.1424 +{
 54.1425 +    #if defined(OVR_OS_MS)
 54.1426 +        OVR::ThreadHandle threadHandle = ConvertThreadSysIdToThreadHandle(threadSysId);
 54.1427 +        if(threadHandle)
 54.1428 +        {
 54.1429 +            size_t count = GetBacktraceFromThreadHandle(addressArray, addressArrayCapacity, skipCount, threadHandle);
 54.1430 +            FreeThreadHandle(threadHandle);
 54.1431 +            return count;
 54.1432 +        }
 54.1433 +        return 0;
 54.1434 +
 54.1435 +    #elif defined(OVR_OS_APPLE)
 54.1436 +        mach_port_t threadCurrent = pthread_mach_thread_np(pthread_self());
 54.1437 +        mach_port_t thread = (mach_port_t)threadSysId;
 54.1438 +    
 54.1439 +        if(thread == threadCurrent)
 54.1440 +        {
 54.1441 +            return GetBacktrace(addressArray, addressArrayCapacity, skipCount, nullptr);
 54.1442 +        }
 54.1443 +        else
 54.1444 +        {
 54.1445 +            kern_return_t result = thread_suspend(thread);    // Do we need to do this if it's an thread who exception is being handled?
 54.1446 +            size_t        count  = 0;
 54.1447 +
 54.1448 +            if(result == KERN_SUCCESS)
 54.1449 +            {
 54.1450 +                #if defined(OVR_CPU_X86) || defined(OVR_CPU_X86_64)
 54.1451 +                    x86_thread_state_t threadState;
 54.1452 +                #elif defined(OVR_CPU_ARM)
 54.1453 +                    arm_thread_state_t threadState;
 54.1454 +                #endif
 54.1455 +                mach_msg_type_number_t stateCount = MACHINE_THREAD_STATE_COUNT;
 54.1456 +
 54.1457 +                result = thread_get_state(thread, MACHINE_THREAD_STATE, (natural_t*)(uintptr_t)&threadState, &stateCount);
 54.1458 +
 54.1459 +                if(result == KERN_SUCCESS)
 54.1460 +                    count = GetBacktrace(addressArray, addressArrayCapacity, skipCount, &threadState, threadSysId);
 54.1461 +
 54.1462 +                thread_resume(thread);
 54.1463 +                
 54.1464 +                return count;
 54.1465 +            }
 54.1466 +        }
 54.1467 +    
 54.1468 +        return 0;
 54.1469 +    
 54.1470 +    #elif defined(OVR_OS_LINUX)
 54.1471 +        // To do.
 54.1472 +        OVR_UNUSED(addressArray);
 54.1473 +        OVR_UNUSED(addressArrayCapacity);
 54.1474 +        OVR_UNUSED(skipCount);
 54.1475 +        OVR_UNUSED(threadSysId);
 54.1476 +        return 0;
 54.1477 +    #endif
 54.1478 +}
 54.1479 +
 54.1480 +
 54.1481 +// We need to return the required moduleInfoArrayCapacity.
 54.1482 +size_t SymbolLookup::GetModuleInfoArray(ModuleInfo* pModuleInfoArray, size_t moduleInfoArrayCapacity)
 54.1483 +{
 54.1484 +    #if defined(OVR_OS_MS)
 54.1485 +        size_t       moduleCountRequired = 0;         // The count we would copy to pModuleInfoArray if moduleInfoArrayCapacity was enough.
 54.1486 +        size_t       moduleCount = 0;                 // The count we actually copy to pModuleInfoArray. Will be <= moduleInfoArrayCapacity.
 54.1487 +        HANDLE       hProcess = GetCurrentProcess();
 54.1488 +        HMODULE      hModuleArray[200];
 54.1489 +        DWORD        cbNeeded = 0;
 54.1490 +        MODULEINFO   mi;
 54.1491 +
 54.1492 +        if(EnumProcessModules(hProcess, hModuleArray, sizeof(hModuleArray), &cbNeeded))
 54.1493 +        {
 54.1494 +            moduleCountRequired = ((cbNeeded / sizeof(HMODULE)) < OVR_ARRAY_COUNT(hModuleArray)) ? (cbNeeded / sizeof(HMODULE)) : OVR_ARRAY_COUNT(hModuleArray);
 54.1495 +            moduleCount         = MIN(moduleCountRequired, OVR_ARRAY_COUNT(hModuleArray));
 54.1496 +            moduleCount         = MIN(moduleCount, moduleInfoArrayCapacity);
 54.1497 +
 54.1498 +            for(size_t i = 0; i < moduleCount; i++)
 54.1499 +            {
 54.1500 +                ModuleInfo& moduleInfo = pModuleInfoArray[i];
 54.1501 +
 54.1502 +                memset(&mi, 0, sizeof(mi));
 54.1503 +                BOOL result = GetModuleInformation(hProcess, hModuleArray[i], &mi, sizeof(mi));
 54.1504 +
 54.1505 +                if(result)
 54.1506 +                {
 54.1507 +                    wchar_t pathW[MAX_PATH];
 54.1508 +                    char    pathA[MAX_PATH * 3]; // *3 to handle UTF8 multibyte encoding.
 54.1509 +
 54.1510 +                    moduleInfo.handle      = hModuleArray[i];
 54.1511 +                    moduleInfo.baseAddress = (uintptr_t)mi.lpBaseOfDll;
 54.1512 +                    moduleInfo.size        = mi.SizeOfImage;
 54.1513 +
 54.1514 +                    GetModuleFileNameW(hModuleArray[i], pathW, OVR_ARRAY_COUNT(pathW));
 54.1515 +                    OVR::UTF8Util::EncodeString(pathA, pathW, -1); // Problem: DecodeString provides no way to specify the destination capacity.
 54.1516 +                    OVR::OVR_strlcpy(moduleInfo.filePath, pathA, OVR_ARRAY_COUNT(moduleInfo.filePath));
 54.1517 +
 54.1518 +                    const char* fileName = GetFileNameFromPath(pathA);
 54.1519 +                    OVR::OVR_strlcpy(moduleInfo.name, fileName, OVR_ARRAY_COUNT(moduleInfo.name));
 54.1520 +                }
 54.1521 +                else
 54.1522 +                {
 54.1523 +                    moduleInfo.handle = 0;
 54.1524 +                    moduleInfo.baseAddress = 0;
 54.1525 +                    moduleInfo.size = 0;
 54.1526 +                    moduleInfo.filePath[0] = 0;
 54.1527 +                    moduleInfo.name[0] = 0;
 54.1528 +                }
 54.1529 +            }
 54.1530 +        }
 54.1531 +
 54.1532 +        return moduleCountRequired;
 54.1533 +    
 54.1534 +    #elif defined(OVR_OS_MAC)
 54.1535 +        size_t moduleCountRequired = 0;
 54.1536 +        size_t moduleCount = 0;
 54.1537 +    
 54.1538 +        struct MacModuleInfo // This struct exists solely so we can have a local function within this function..
 54.1539 +        {
 54.1540 +            static void AddMacModuleInfo(ModuleInfo* pModuleInfoArrayL, size_t& moduleCountRequiredL, size_t& moduleCountL, size_t moduleInfoArrayCapacityL,
 54.1541 +                                        const char* pTypeFilterL, const char* pModulePath, uintptr_t currentSegmentPos, const MachHeader* pMachHeader, uint64_t offset)
 54.1542 +            {
 54.1543 +                for(size_t i = 0; i < pMachHeader->ncmds; i++)
 54.1544 +                {
 54.1545 +                    const SegmentCommand* pSegmentCommand = reinterpret_cast<const SegmentCommand*>(currentSegmentPos);
 54.1546 +                    
 54.1547 +                    if(pSegmentCommand->cmd == kLCSegment)
 54.1548 +                    {
 54.1549 +                        const size_t segnameSize = (sizeof(pSegmentCommand->segname) + 1); // +1 so we can have a trailing '\0'.
 54.1550 +                        char segname[segnameSize];
 54.1551 +                        
 54.1552 +                        memcpy(segname, pSegmentCommand->segname, sizeof(pSegmentCommand->segname));
 54.1553 +                        segname[segnameSize - 1] = '\0';
 54.1554 +                        
 54.1555 +                        if(!pTypeFilterL || OVR_strncmp(segname, pTypeFilterL, sizeof(segname)))
 54.1556 +                        {
 54.1557 +                            moduleCountRequiredL++;
 54.1558 +                            
 54.1559 +                            if(moduleCountL < moduleInfoArrayCapacityL)
 54.1560 +                            {
 54.1561 +                                ModuleInfo& info = pModuleInfoArrayL[moduleCountL++];
 54.1562 +                                
 54.1563 +                                info.baseAddress = (uint64_t)(pSegmentCommand->vmaddr + offset);
 54.1564 +                                info.handle      = reinterpret_cast<ModuleHandle>((uintptr_t)info.baseAddress);
 54.1565 +                                info.size        = (uint64_t)pSegmentCommand->vmsize;
 54.1566 +                                OVR_strlcpy(info.filePath, pModulePath, OVR_ARRAY_COUNT(info.filePath));
 54.1567 +                                OVR_strlcpy(info.name, GetFileNameFromPath(pModulePath), OVR_ARRAY_COUNT(info.name));
 54.1568 +                                
 54.1569 +                                info.permissions[0] = (pSegmentCommand->initprot & VM_PROT_READ)    ? 'r' : '-';
 54.1570 +                                info.permissions[1] = (pSegmentCommand->initprot & VM_PROT_WRITE)   ? 'w' : '-';
 54.1571 +                                info.permissions[2] = (pSegmentCommand->initprot & VM_PROT_EXECUTE) ? 'x' : '-';
 54.1572 +                                info.permissions[3] = '/';
 54.1573 +                                info.permissions[4] = (pSegmentCommand->maxprot  & VM_PROT_READ)    ? 'r' : '-';
 54.1574 +                                info.permissions[5] = (pSegmentCommand->maxprot  & VM_PROT_WRITE)   ? 'w' : '-';
 54.1575 +                                info.permissions[6] = (pSegmentCommand->maxprot  & VM_PROT_EXECUTE) ? 'x' : '-';
 54.1576 +                                info.permissions[7] = '\0';
 54.1577 +                                
 54.1578 +                                OVR_strlcpy(info.type, pSegmentCommand->segname, OVR_ARRAY_COUNT(info.type));
 54.1579 +                            }
 54.1580 +                        }
 54.1581 +                    }
 54.1582 +                    
 54.1583 +                    currentSegmentPos += pSegmentCommand->cmdsize;
 54.1584 +                }
 54.1585 +            }
 54.1586 +        };
 54.1587 +
 54.1588 +        // Iterate dyld_all_image_infos->infoArray
 54.1589 +        const struct dyld_all_image_infos* pAllImageInfos = _dyld_get_all_image_infos();
 54.1590 +        
 54.1591 +        for(uint32_t i = 0; i < pAllImageInfos->infoArrayCount; i++)
 54.1592 +        {
 54.1593 +            const char* pModulePath = pAllImageInfos->infoArray[i].imageFilePath;
 54.1594 +            
 54.1595 +            if(pModulePath && *pModulePath)
 54.1596 +            {
 54.1597 +                uintptr_t         currentSegmentPos = (uintptr_t)pAllImageInfos->infoArray[i].imageLoadAddress;
 54.1598 +                const MachHeader* pMachHeader       = reinterpret_cast<const MachHeader*>(currentSegmentPos);
 54.1599 +                uint64_t          offset            = (uint64_t)_dyld_get_image_vmaddr_slide(i);
 54.1600 +
 54.1601 +                currentSegmentPos += sizeof(*pMachHeader);
 54.1602 +
 54.1603 +                MacModuleInfo::AddMacModuleInfo(pModuleInfoArray, moduleCountRequired, moduleCount, moduleInfoArrayCapacity,
 54.1604 +                                                nullptr /*"__TEXT"*/, pModulePath, currentSegmentPos, pMachHeader, offset);
 54.1605 +            }
 54.1606 +        }
 54.1607 +
 54.1608 +        // In addition to iterating dyld_all_image_infos->infoArray we need to also iterate /usr/lib/dyld entries.
 54.1609 +        const MachHeader* pMachHeader = (const MachHeader*)pAllImageInfos->dyldImageLoadAddress;
 54.1610 +        uintptr_t         currentSegmentPos = (uintptr_t)pMachHeader + sizeof(*pMachHeader);
 54.1611 +        char              modulePath[OVR_MAX_PATH] = "";
 54.1612 +        pid_t             pid = getpid();
 54.1613 +        int               filenameLen = proc_regionfilename((int)pid, currentSegmentPos, modulePath, (uint32_t)sizeof(modulePath));
 54.1614 +    
 54.1615 +        if(filenameLen > 0)
 54.1616 +            MacModuleInfo::AddMacModuleInfo(pModuleInfoArray, moduleCountRequired, moduleCount, moduleInfoArrayCapacity,
 54.1617 +                                                "__TEXT", modulePath, currentSegmentPos, pMachHeader, 0);
 54.1618 +
 54.1619 +        return moduleCountRequired;
 54.1620 +    
 54.1621 +    #elif defined(EA_PLATFORM_LINUX)
 54.1622 +        // One approach is to read /proc/self/maps, which is supported by Linux (though not BSD).
 54.1623 +        // Linux glibc dladdr() can tell us what module an arbitrary function address comes from, but can't tell us the list of modules.
 54.1624 +        OVR_UNUSED(pModuleInfoArray);
 54.1625 +        OVR_UNUSED(moduleInfoArrayCapacity);
 54.1626 +        return 0;
 54.1627 +
 54.1628 +    #else
 54.1629 +        OVR_UNUSED(pModuleInfoArray);
 54.1630 +        OVR_UNUSED(moduleInfoArrayCapacity);
 54.1631 +        return 0;
 54.1632 +    #endif
 54.1633 +}
 54.1634 +
 54.1635 +
 54.1636 +size_t SymbolLookup::GetThreadList(ThreadHandle* threadHandleArray, ThreadSysId* threadSysIdArray, size_t threadArrayCapacity)
 54.1637 +{
 54.1638 +    size_t countRequired = 0;
 54.1639 +    size_t count = 0;
 54.1640 +
 54.1641 +    #if defined(OVR_OS_MS)
 54.1642 +        // Print a list of threads.
 54.1643 +        DWORD  currentProcessId = GetCurrentProcessId();
 54.1644 +        HANDLE hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, currentProcessId); // ICreateToolhelp32Snapshot actually ignores currentProcessId.
 54.1645 +
 54.1646 +        if(hThreadSnap != INVALID_HANDLE_VALUE) 
 54.1647 +        {
 54.1648 +            THREADENTRY32 te32;
 54.1649 +            te32.dwSize = sizeof(THREADENTRY32); 
 54.1650 +
 54.1651 +            if(Thread32First(hThreadSnap, &te32)) 
 54.1652 +            {
 54.1653 +                do
 54.1654 +                {
 54.1655 +                    if(te32.th32OwnerProcessID == currentProcessId)
 54.1656 +                    {
 54.1657 +                        HANDLE hThread = ConvertThreadSysIdToThreadHandle(te32.th32ThreadID);
 54.1658 +
 54.1659 +                        if(hThread)
 54.1660 +                        {
 54.1661 +                            ++countRequired;
 54.1662 +
 54.1663 +                            if((threadHandleArray || threadSysIdArray) && (count < threadArrayCapacity))
 54.1664 +                            {
 54.1665 +                                if(threadHandleArray)
 54.1666 +                                    threadHandleArray[count] = hThread; // The caller must call CloseHandle on this thread, or call DoneThreadList on the returned array.
 54.1667 +                                if(threadSysIdArray)
 54.1668 +                                    threadSysIdArray[count] = ConvertThreadHandleToThreadSysId(hThread);
 54.1669 +                                ++count;
 54.1670 +                            }
 54.1671 +
 54.1672 +                            if(!threadHandleArray) // If we aren't giving this back to the user...
 54.1673 +                                FreeThreadHandle(hThread);
 54.1674 +                        }
 54.1675 +                    }
 54.1676 +                } while(Thread32Next(hThreadSnap, &te32));
 54.1677 +            }
 54.1678 +            
 54.1679 +            CloseHandle(hThreadSnap);
 54.1680 +        }
 54.1681 +
 54.1682 +    #elif defined(OVR_OS_APPLE)
 54.1683 +        mach_port_t             taskSelf   = mach_task_self();
 54.1684 +        thread_act_port_array_t threadArray;
 54.1685 +        mach_msg_type_number_t  threadCount;
 54.1686 +        
 54.1687 +        kern_return_t result = task_threads(taskSelf, &threadArray, &threadCount);
 54.1688 +        
 54.1689 +        if(result == KERN_SUCCESS)
 54.1690 +        {
 54.1691 +            for(mach_msg_type_number_t i = 0; i < threadCount; i++)
 54.1692 +            {
 54.1693 +                ++countRequired;
 54.1694 +
 54.1695 +                if((threadHandleArray || threadSysIdArray) && (count < threadArrayCapacity))
 54.1696 +                {
 54.1697 +                    if(threadHandleArray)
 54.1698 +                        threadHandleArray[count] = pthread_from_mach_thread_np(threadArray[i]);
 54.1699 +                    if(threadSysIdArray)
 54.1700 +                        threadSysIdArray[count] = threadArray[i];
 54.1701 +                    ++count;
 54.1702 +                }
 54.1703 +            }
 54.1704 +            
 54.1705 +            vm_deallocate(taskSelf, (vm_address_t)threadArray, threadCount * sizeof(thread_act_t));
 54.1706 +        }
 54.1707 +
 54.1708 +    #elif defined(OVR_OS_LINUX)
 54.1709 +        // To do.
 54.1710 +        OVR_UNUSED(count);
 54.1711 +        OVR_UNUSED(threadHandleArray);
 54.1712 +        OVR_UNUSED(threadSysIdArray);
 54.1713 +        OVR_UNUSED(threadArrayCapacity);
 54.1714 +    #endif
 54.1715 +
 54.1716 +    return countRequired;
 54.1717 +}
 54.1718 +
 54.1719 +
 54.1720 +void SymbolLookup::DoneThreadList(ThreadHandle* threadHandleArray, ThreadSysId* threadSysIdArray, size_t threadArrayCount)
 54.1721 +{
 54.1722 +    #if defined(OVR_OS_MS)
 54.1723 +        for(size_t i = 0; i != threadArrayCount; ++i)
 54.1724 +        {
 54.1725 +            if(threadHandleArray[i])
 54.1726 +            {
 54.1727 +                CloseHandle(threadHandleArray[i]);
 54.1728 +                threadHandleArray[i] = OVR_THREADHANDLE_INVALID;
 54.1729 +            }
 54.1730 +        }
 54.1731 +
 54.1732 +        OVR_UNUSED(threadSysIdArray);
 54.1733 +    #else
 54.1734 +        OVR_UNUSED(threadHandleArray);
 54.1735 +        OVR_UNUSED(threadSysIdArray);
 54.1736 +        OVR_UNUSED(threadArrayCount);
 54.1737 +    #endif
 54.1738 +}
 54.1739 +
 54.1740 +
 54.1741 +// Writes a given thread's callstack wity symbols to the given output.
 54.1742 +// It may not be safe to call this from an exception handler, as sOutput allocates memory.
 54.1743 +bool SymbolLookup::ReportThreadCallstack(OVR::String& sOutput, size_t skipCount, ThreadSysId threadSysId)
 54.1744 +{
 54.1745 +    if(!threadSysId)
 54.1746 +        threadSysId = GetCurrentThreadSysId();
 54.1747 +
 54.1748 +    void*  addressArray[64];
 54.1749 +    size_t addressCount = GetBacktraceFromThreadSysId(addressArray, OVR_ARRAY_COUNT(addressArray), skipCount, threadSysId);
 54.1750 +
 54.1751 +    // Print the header
 54.1752 +    char         headerBuffer[256];
 54.1753 +    char         threadName[32];
 54.1754 +    char         threadHandleStr[24];
 54.1755 +    char         threadSysIdStr[24];
 54.1756 +    char         stackBaseStr[24];
 54.1757 +    char         stackLimitStr[24];
 54.1758 +    void*        pStackBase;
 54.1759 +    void*        pStackLimit;
 54.1760 +  //void*        pStackCurrent;  // Current stack pointer. To do: support reporting this.
 54.1761 +    ThreadHandle threadHandle = ConvertThreadSysIdToThreadHandle(threadSysId);
 54.1762 +    OVR::GetThreadStackBounds(pStackBase, pStackLimit, threadHandle);
 54.1763 +
 54.1764 +    Thread::GetThreadName(threadName, OVR_ARRAY_COUNT(threadName), threadName);
 54.1765 +    SprintfThreadHandle(threadHandleStr, OVR_ARRAY_COUNT(threadHandleStr), threadHandle);
 54.1766 +    SprintfThreadSysId(threadSysIdStr, OVR_ARRAY_COUNT(threadSysIdStr), threadSysId);
 54.1767 +    SprintfAddress(stackBaseStr, OVR_ARRAY_COUNT(stackBaseStr), pStackBase);
 54.1768 +    SprintfAddress(stackLimitStr, OVR_ARRAY_COUNT(stackLimitStr), pStackLimit);
 54.1769 +
 54.1770 +    if(threadName[0])
 54.1771 +        OVR_snprintf(headerBuffer, OVR_ARRAY_COUNT(headerBuffer), "Thread \"%s\" handle: %s, id: %s, stack base: %s, stack limit: %s\r\n", threadName, threadHandleStr, threadSysIdStr, stackBaseStr, stackLimitStr);
 54.1772 +    else
 54.1773 +        OVR_snprintf(headerBuffer, OVR_ARRAY_COUNT(headerBuffer), "Thread handle: %s, id: %s, stack base: %s, stack limit: %s\r\n", threadHandleStr, threadSysIdStr, stackBaseStr, stackLimitStr);
 54.1774 +
 54.1775 +    sOutput += headerBuffer;
 54.1776 +
 54.1777 +    // Print the backtrace info
 54.1778 +    char        backtraceBuffer[1024];  // Sometimes function symbol names are very long.
 54.1779 +    SymbolInfo  symbolInfo;
 54.1780 +    const char* pModuleName;
 54.1781 +
 54.1782 +    if(addressCount == 0)
 54.1783 +    {
 54.1784 +        sOutput += "<Unable to read backtrace>\r\n";
 54.1785 +    }
 54.1786 +    else
 54.1787 +    {
 54.1788 +        for(size_t i = 0; i < addressCount; ++i)
 54.1789 +        {
 54.1790 +            LookupSymbol((uint64_t)addressArray[i], symbolInfo);
 54.1791 +
 54.1792 +            if(symbolInfo.pModuleInfo && symbolInfo.pModuleInfo->name[0])
 54.1793 +                pModuleName = symbolInfo.pModuleInfo->name;
 54.1794 +            else
 54.1795 +                pModuleName = "(unknown module)";
 54.1796 +
 54.1797 +            char addressStr[24];
 54.1798 +            SprintfAddress(addressStr, OVR_ARRAY_COUNT(addressStr), addressArray[i]);
 54.1799 +
 54.1800 +            if(symbolInfo.filePath[0])
 54.1801 +                OVR_snprintf(backtraceBuffer, OVR_ARRAY_COUNT(backtraceBuffer), "%-2u %-24s %s %s+%d %s:%d\r\n", (unsigned)i, pModuleName, addressStr, symbolInfo.function, symbolInfo.functionOffset, symbolInfo.filePath, symbolInfo.fileLineNumber);
 54.1802 +            else
 54.1803 +                OVR_snprintf(backtraceBuffer, OVR_ARRAY_COUNT(backtraceBuffer), "%-2u %-24s %s %s+%d\r\n", (unsigned)i, pModuleName, addressStr, symbolInfo.function, symbolInfo.functionOffset);
 54.1804 +
 54.1805 +            sOutput += backtraceBuffer;
 54.1806 +        }
 54.1807 +    }
 54.1808 +
 54.1809 +    FreeThreadHandle(threadHandle);
 54.1810 +
 54.1811 +    return (addressCount > 0);
 54.1812 +}
 54.1813 +
 54.1814 +
 54.1815 +// Writes all thread's callstacks with symbols to the given output.
 54.1816 +// It may not be safe to call this from an exception handler, as sOutput allocates memory.
 54.1817 +bool SymbolLookup::ReportThreadCallstacks(OVR::String& sOutput, size_t skipCount)
 54.1818 +{
 54.1819 +    ThreadSysId threadSysIdArray[64];
 54.1820 +    size_t      threadSysIdCount = GetThreadList(nullptr, threadSysIdArray, OVR_ARRAY_COUNT(threadSysIdArray));
 54.1821 +
 54.1822 +    if(threadSysIdCount > OVR_ARRAY_COUNT(threadSysIdArray))
 54.1823 +        threadSysIdCount = OVR_ARRAY_COUNT(threadSysIdArray);
 54.1824 +
 54.1825 +    for(size_t i = 0; i < threadSysIdCount; i++)
 54.1826 +    {
 54.1827 +        String sTemp;
 54.1828 +        ReportThreadCallstack(sTemp, skipCount, threadSysIdArray[i]);
 54.1829 +        if(i > 0)
 54.1830 +            sOutput += "\r\n";
 54.1831 +        sOutput += sTemp;
 54.1832 +    }
 54.1833 +
 54.1834 +    return (threadSysIdCount > 0);
 54.1835 +}
 54.1836 +
 54.1837 +
 54.1838 +bool SymbolLookup::RefreshModuleList()
 54.1839 +{
 54.1840 +    if(!moduleListUpdated)
 54.1841 +    {
 54.1842 +        #if defined(OVR_OS_MS)
 54.1843 +            // We can't rely on SymRefreshModuleList because it's present in DbgHelp 6.5, 
 54.1844 +            // which doesn't distribute with Windows 7.
 54.1845 +
 54.1846 +            // Currently we support only refreshing the list once ever. With a little effort we could revise this code to 
 54.1847 +            // support re-refreshing the list at runtime to account for the possibility that modules have recently been
 54.1848 +            // added or removed.
 54.1849 +            if(pSymLoadModule64)
 54.1850 +            {
 54.1851 +                const size_t requiredCount = GetModuleInfoArray(moduleInfoArray, OVR_ARRAY_COUNT(moduleInfoArray));
 54.1852 +                moduleInfoArraySize = MIN(requiredCount, OVR_ARRAY_COUNT(moduleInfoArray));
 54.1853 +
 54.1854 +                HANDLE hProcess = GetCurrentProcess();
 54.1855 +
 54.1856 +                for(size_t i = 0; i < moduleInfoArraySize; i++)
 54.1857 +                    pSymLoadModule64(hProcess, nullptr, moduleInfoArray[i].filePath, nullptr, moduleInfoArray[i].baseAddress, (DWORD)moduleInfoArray[i].size);
 54.1858 +
 54.1859 +                moduleListUpdated = true;
 54.1860 +            }
 54.1861 +        #else
 54.1862 +            const size_t requiredCount = GetModuleInfoArray(moduleInfoArray, OVR_ARRAY_COUNT(moduleInfoArray));
 54.1863 +            moduleInfoArraySize = MIN(requiredCount, OVR_ARRAY_COUNT(moduleInfoArray));
 54.1864 +            moduleListUpdated = true;
 54.1865 +        #endif
 54.1866 +    }
 54.1867 +    
 54.1868 +    return true;
 54.1869 +}
 54.1870 +
 54.1871 +
 54.1872 +bool SymbolLookup::LookupSymbol(uint64_t address, SymbolInfo& symbolInfo)
 54.1873 +{
 54.1874 +    return LookupSymbols(&address, &symbolInfo, 1);
 54.1875 +}
 54.1876 +
 54.1877 +
 54.1878 +bool SymbolLookup::LookupSymbols(uint64_t* addressArray, SymbolInfo* pSymbolInfoArray, size_t arraySize)
 54.1879 +{
 54.1880 +    if(!moduleListUpdated)
 54.1881 +    {
 54.1882 +        RefreshModuleList();
 54.1883 +    }
 54.1884 +
 54.1885 +    #if defined(OVR_OS_MS)
 54.1886 +        union SYMBOL_INFO_UNION
 54.1887 +        {
 54.1888 +            SYMBOL_INFO msSymbolInfo;
 54.1889 +            char        suffixPadding[sizeof(SYMBOL_INFO) + 1024];
 54.1890 +        };
 54.1891 +
 54.1892 +        for(size_t i = 0; i < arraySize; i++)
 54.1893 +        {
 54.1894 +            uint64_t&   address    = addressArray[i];
 54.1895 +            SymbolInfo& symbolInfo = pSymbolInfoArray[i];
 54.1896 +
 54.1897 +            // Copy the address and ModuleInfo
 54.1898 +            symbolInfo.address     = addressArray[i];
 54.1899 +            symbolInfo.pModuleInfo = GetModuleInfoForAddress(address); // We could also use siu.msSymbolInfo.ModBase to get the module slightly faster.
 54.1900 +
 54.1901 +            // Get the function/offset.
 54.1902 +            SYMBOL_INFO_UNION siu;
 54.1903 +            memset(&siu, 0, sizeof(siu));
 54.1904 +            siu.msSymbolInfo.SizeOfStruct = sizeof(siu.msSymbolInfo);
 54.1905 +            siu.msSymbolInfo.MaxNameLen   = sizeof(siu.suffixPadding) - sizeof(SYMBOL_INFO) + 1; // +1 because SYMBOL_INFO itself has Name[1].
 54.1906 +
 54.1907 +            HANDLE  hProcess = GetCurrentProcess();
 54.1908 +            DWORD64 displacement64 = 0;
 54.1909 +            bool    bResult = (pSymFromAddr != nullptr) && (pSymFromAddr(hProcess, address, &displacement64, &siu.msSymbolInfo) != FALSE);
 54.1910 +
 54.1911 +            if(bResult)
 54.1912 +            {
 54.1913 +                symbolInfo.size = siu.msSymbolInfo.Size;
 54.1914 +                OVR_strlcpy(symbolInfo.function, siu.msSymbolInfo.Name, OVR_ARRAY_COUNT(symbolInfo.function));
 54.1915 +                symbolInfo.functionOffset = (int32_t)displacement64;
 54.1916 +            }
 54.1917 +            else
 54.1918 +            {
 54.1919 +                symbolInfo.size = kMISizeInvalid;
 54.1920 +                symbolInfo.function[0] = 0;
 54.1921 +                symbolInfo.functionOffset = kMIFunctionOffsetInvalid;
 54.1922 +            }
 54.1923 +
 54.1924 +            // Get the file/line
 54.1925 +            IMAGEHLP_LINE64 iLine64;
 54.1926 +            DWORD displacement = 0;
 54.1927 +            memset(&iLine64, 0, sizeof(iLine64));
 54.1928 +            iLine64.SizeOfStruct = sizeof(iLine64);
 54.1929 +
 54.1930 +            bResult = (pSymGetLineFromAddr64 != nullptr) && (pSymGetLineFromAddr64(hProcess, address, &displacement, &iLine64) != FALSE);
 54.1931 +
 54.1932 +            if(bResult)
 54.1933 +            {
 54.1934 +                OVR_strlcpy(symbolInfo.filePath, iLine64.FileName, OVR_ARRAY_COUNT(symbolInfo.filePath));
 54.1935 +                symbolInfo.fileLineNumber = (int32_t)iLine64.LineNumber;
 54.1936 +            }
 54.1937 +            else
 54.1938 +            {
 54.1939 +                symbolInfo.filePath[0] = 0;
 54.1940 +                symbolInfo.fileLineNumber = kMILineNumberInvalid;
 54.1941 +            }
 54.1942 +
 54.1943 +            // To do: get the source code when possible. We need to use the user-registered directory paths and the symbolInfo.filePath
 54.1944 +            // and find the given file in the tree(s), then open the file and find the symbolInfo.fileLineNumber line (and surrounding lines).
 54.1945 +            // symbolInfo.sourceCode[1024]
 54.1946 +            symbolInfo.sourceCode[0] = '\0';
 54.1947 +        }
 54.1948 +    
 54.1949 +    #elif defined(OVR_OS_APPLE)
 54.1950 +        // Apple has an internal CoreSymbolication library which could help with this.
 54.1951 +        // Third party implementations of the CoreSymbolication header are available and could be used
 54.1952 +        // to get file/line info better than other means. It used Objective C, so we'll need a .m or .mm file.
 54.1953 +    
 54.1954 +        memset(pSymbolInfoArray, 0, arraySize * sizeof(SymbolInfo));
 54.1955 +
 54.1956 +        for(size_t i = 0; i < arraySize; i++)
 54.1957 +        {
 54.1958 +            pSymbolInfoArray[i].address = addressArray[i];
 54.1959 +            pSymbolInfoArray[i].pModuleInfo = GetModuleInfoForAddress(addressArray[i]);
 54.1960 +        }
 54.1961 +
 54.1962 +        // Problem: backtrace_symbols allocates memory from malloc. If you got into a SIGSEGV due to
 54.1963 +        // malloc arena corruption (quite common) you will likely fault in backtrace_symbols.
 54.1964 +        // To do: Use allowMemoryAllocation here.
 54.1965 +    
 54.1966 +        #if (OVR_PTR_SIZE == 4)
 54.1967 +            // backtrace_symbols takes a void* array, but we have a uint64_t array. So for 32 bit we
 54.1968 +            // need to convert the 64 bit array to 32 bit temporarily for the backtrace_symbols call.
 54.1969 +            void* ptr32Array[256]; // To do: Remove this limit.
 54.1970 +            for(size_t i = 0, iEnd = MIN(arraySize, OVR_ARRAY_COUNT(ptr32Array)); i < iEnd; i++)
 54.1971 +                ptr32Array[i] = reinterpret_cast<void*>(addressArray[i]);
 54.1972 +            char** symbolArray = backtrace_symbols(reinterpret_cast<void**>(ptr32Array), (int)arraySize);
 54.1973 +        #else
 54.1974 +            char** symbolArray = backtrace_symbols(reinterpret_cast<void**>(addressArray), (int)arraySize);
 54.1975 +        #endif
 54.1976 +
 54.1977 +        if(symbolArray)
 54.1978 +        {
 54.1979 +            for(size_t i = 0; i < arraySize; i++)
 54.1980 +            {
 54.1981 +
 54.1982 +                // Generates a string like this: "0 OculusWorldDemo 0x000000010000cfd5 _ZN18OculusWorldDemoApp9OnStartupEiPPKc + 213"
 54.1983 +                static_assert(OVR_ARRAY_COUNT(pSymbolInfoArray[i].function) == 128, "Need to change the string format size below");
 54.1984 +                
 54.1985 +                sscanf(symbolArray[i], "%*d %*s %*x %128s + %d", pSymbolInfoArray[i].function, &pSymbolInfoArray[i].functionOffset);
 54.1986 +                
 54.1987 +                if(allowMemoryAllocation)
 54.1988 +                {
 54.1989 +                    int   status = 0;
 54.1990 +                    char* strDemangled = abi::__cxa_demangle(pSymbolInfoArray[i].function, nullptr, nullptr, &status);
 54.1991 +                    
 54.1992 +                    if(strDemangled)
 54.1993 +                    {
 54.1994 +                        OVR_strlcpy(pSymbolInfoArray[i].function, strDemangled, OVR_ARRAY_COUNT(pSymbolInfoArray[i].function));
 54.1995 +                        free(strDemangled);
 54.1996 +                    }
 54.1997 +                }
 54.1998 +            }
 54.1999 +
 54.2000 +            free(symbolArray);
 54.2001 +        }
 54.2002 +
 54.2003 +        // To consider: use CoreSybolication to get file/line info instead. atos is a bit slow and cumbersome.
 54.2004 +        // https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man1/atos.1.html
 54.2005 +        // atos -p <pid> <addr> <addr> ...
 54.2006 +        // atos -o <binary image path> -l <load-address> <addr> <addr> ...
 54.2007 +        // Generates output like this: "OVR::CreateException(OVR::CreateExceptionType) (in OculusWorldDemo) (ExceptionHandler.cpp:598)"
 54.2008 +        for(size_t i = 0; i < arraySize; i++)
 54.2009 +        {
 54.2010 +            struct stat statStruct;
 54.2011 +
 54.2012 +            if(pSymbolInfoArray[i].pModuleInfo && pSymbolInfoArray[i].pModuleInfo->filePath[0] && (stat(pSymbolInfoArray[i].pModuleInfo->filePath, &statStruct) == 0))
 54.2013 +            {
 54.2014 +                char command[PATH_MAX * 2];   // Problem: We can't unilaterally use pSymbolInfoArray[0] for all addresses. We need to match addresses to the corresponding modules.
 54.2015 +                OVR_snprintf(command, OVR_ARRAY_COUNT(command), "atos -o %s -l 0x%llx 0x%llx",
 54.2016 +                            pSymbolInfoArray[i].pModuleInfo->filePath, (int64_t)pSymbolInfoArray[i].pModuleInfo->baseAddress, (int64_t)pSymbolInfoArray[i].address);
 54.2017 +
 54.2018 +                char output[512];
 54.2019 +                if(SpawnShellCommand(command, output, OVR_ARRAY_COUNT(output)) != (size_t)-1)
 54.2020 +                {
 54.2021 +                    char* pLastOpenParen = strrchr(output, '(');
 54.2022 +                    char* pColon = strrchr(output, ':');
 54.2023 +                    
 54.2024 +                    if(pLastOpenParen && (pColon > pLastOpenParen))
 54.2025 +                    {
 54.2026 +                        *pColon = '\0';
 54.2027 +                        OVR_strlcpy(pSymbolInfoArray[i].filePath, pLastOpenParen + 1, OVR_ARRAY_COUNT(pSymbolInfoArray[i].filePath));
 54.2028 +                    }
 54.2029 +                }
 54.2030 +            }
 54.2031 +        }
 54.2032 +
 54.2033 +    #elif defined(OVR_OS_LINUX)
 54.2034 +        // We can use libunwind's unw_get_proc_name to try to get function name info. It can work regardless of relocation.
 54.2035 +        // Use backtrace_symbols and addr2line. Need to watch out for module load-time relocation.
 54.2036 +        // Ned to pass the -rdynamic flag to the linker. It will cause the linker to out in the link
 54.2037 +        // tables the name of all the none static functions in your code, not just the exported ones.
 54.2038 +        OVR_UNUSED(addressArray);
 54.2039 +        OVR_UNUSED(pSymbolInfoArray);
 54.2040 +        OVR_UNUSED(arraySize);
 54.2041 +    #endif
 54.2042 +
 54.2043 +    return true; // To do: Return true only if something was found.
 54.2044 +}
 54.2045 +
 54.2046 +
 54.2047 +const ModuleInfo* SymbolLookup::GetModuleInfoForAddress(uint64_t address)
 54.2048 +{
 54.2049 +    // This is a linear seach. To consider: it would be significantly faster to search by 
 54.2050 +    // address if we ordered it by base address and did a binary search.
 54.2051 +    for(size_t i = 0; i < moduleInfoArraySize; ++i)
 54.2052 +    {
 54.2053 +        const ModuleInfo& mi = moduleInfoArray[i];
 54.2054 +
 54.2055 +        if((mi.baseAddress <= address) && (address < (mi.baseAddress + mi.size)))
 54.2056 +            return &mi;
 54.2057 +    }
 54.2058 +
 54.2059 +    return nullptr;
 54.2060 +}
 54.2061 +
 54.2062 +
 54.2063 +
 54.2064 +
 54.2065 +ExceptionInfo::ExceptionInfo()
 54.2066 +  : time()
 54.2067 +  , timeVal(0)
 54.2068 +  , backtrace()
 54.2069 +  , backtraceCount(0)
 54.2070 +  , threadHandle(OVR_THREADHANDLE_INVALID)
 54.2071 +  , threadSysId(OVR_THREADSYSID_INVALID)
 54.2072 +  , threadName()
 54.2073 +  , pExceptionInstructionAddress(nullptr)
 54.2074 +  , pExceptionMemoryAddress(nullptr)
 54.2075 +  , cpuContext()
 54.2076 +  , exceptionDescription()
 54.2077 +  , symbolInfo()
 54.2078 + #if defined(OVR_OS_MS)
 54.2079 +  , exceptionRecord()
 54.2080 + #elif defined(OVR_OS_APPLE)
 54.2081 +  , exceptionType(0)
 54.2082 +  , cpuExceptionId(0)
 54.2083 +  , cpuExceptionIdError(0)
 54.2084 +  , machExceptionDetail()
 54.2085 +  , machExceptionDetailCount(0)
 54.2086 + #endif
 54.2087 +{
 54.2088 +}
 54.2089 +
 54.2090 +
 54.2091 +
 54.2092 +ExceptionHandler::ExceptionHandler()
 54.2093 +  : enabled(false)
 54.2094 +  , reportPrivacyEnabled(true)
 54.2095 +  , exceptionResponse(kERHandle)
 54.2096 +  , exceptionListener(nullptr)
 54.2097 +  , exceptionListenerUserValue(0)
 54.2098 +  , appDescription()
 54.2099 +  , codeBasePathArray()
 54.2100 +  , reportFilePath()
 54.2101 +  , miniDumpFlags(0)
 54.2102 +  , miniDumpFilePath()
 54.2103 +  , file(nullptr)
 54.2104 +  , scratchBuffer()
 54.2105 +  , exceptionOccurred(false)
 54.2106 +  , handlingBusy(0)
 54.2107 +  , reportFilePathActual()
 54.2108 +  , minidumpFilePathActual()
 54.2109 +  , terminateReturnValue(0)
 54.2110 +  , exceptionInfo()
 54.2111 + #if defined(OVR_OS_MS)
 54.2112 +  , vectoredHandle(nullptr)
 54.2113 +  , previousFilter(nullptr)
 54.2114 +  , pExceptionPointers(nullptr)
 54.2115 + #elif defined(OVR_OS_MAC)
 54.2116 +  , machHandlerInitialized(false)
 54.2117 +  , machExceptionPort(0)
 54.2118 +  , machExceptionPortsSaved()
 54.2119 +  , machThreadShouldContinue(false)
 54.2120 +  , machThreadExecuting(false)
 54.2121 +  , machThread((pthread_t)OVR_THREADHANDLE_INVALID)
 54.2122 + #endif
 54.2123 +{
 54.2124 +	SetExceptionPaths("default", "default");
 54.2125 +}
 54.2126 +
 54.2127 +
 54.2128 +ExceptionHandler::~ExceptionHandler()
 54.2129 +{
 54.2130 +    if(enabled)
 54.2131 +    {
 54.2132 +        Enable(false);
 54.2133 +    } 
 54.2134 +}
 54.2135 +
 54.2136 +
 54.2137 +#if defined(OVR_OS_MS)
 54.2138 +    static ExceptionHandler* sExceptionHandler = nullptr;
 54.2139 +
 54.2140 +    LONG WINAPI Win32ExceptionFilter(LPEXCEPTION_POINTERS pExceptionPointers)
 54.2141 +    {
 54.2142 +        if(sExceptionHandler)
 54.2143 +            return (LONG)sExceptionHandler->ExceptionFilter(pExceptionPointers);
 54.2144 +        return EXCEPTION_CONTINUE_SEARCH;
 54.2145 +    }
 54.2146 +
 54.2147 +    LONG ExceptionHandler::ExceptionFilter(LPEXCEPTION_POINTERS pExceptionPointers)
 54.2148 +    {
 54.2149 +        // Exception codes < 0x80000000 are not true exceptions but rather are debugger notifications. They include DBG_TERMINATE_THREAD, 
 54.2150 +        // DBG_TERMINATE_PROCESS, DBG_CONTROL_BREAK, DBG_COMMAND_EXCEPTION, DBG_CONTROL_C, DBG_PRINTEXCEPTION_C, DBG_RIPEXCEPTION, 
 54.2151 +        // and 0x406d1388 (thread named, http://blogs.msdn.com/b/stevejs/archive/2005/12/19/505815.aspx).
 54.2152 +
 54.2153 +        if(pExceptionPointers->ExceptionRecord->ExceptionCode < 0x80000000)
 54.2154 +            return EXCEPTION_CONTINUE_SEARCH;
 54.2155 +
 54.2156 +        // VC++ C++ exceptions use code 0xe06d7363 ('Emsc')
 54.2157 +        // http://support.microsoft.com/kb/185294 
 54.2158 +        // http://blogs.msdn.com/b/oldnewthing/archive/2010/07/30/10044061.aspx
 54.2159 +        if(pExceptionPointers->ExceptionRecord->ExceptionCode == 0xe06d7363)
 54.2160 +            return EXCEPTION_CONTINUE_SEARCH;
 54.2161 +
 54.2162 +        if(handlingBusy.CompareAndSet_Acquire(0, 1)) // If we can successfully change it from 0 to 1.
 54.2163 +        {
 54.2164 +            exceptionOccurred = true;
 54.2165 +
 54.2166 +            this->pExceptionPointers = pExceptionPointers;
 54.2167 +
 54.2168 +            // Disable the handler while we do this processing.
 54.2169 +            ULONG result = RemoveVectoredExceptionHandler(vectoredHandle);
 54.2170 +            OVR_ASSERT_AND_UNUSED(result != 0, result);
 54.2171 +
 54.2172 +            // Time
 54.2173 +            exceptionInfo.timeVal = time(nullptr);
 54.2174 +            exceptionInfo.time = *gmtime(&exceptionInfo.timeVal);
 54.2175 +
 54.2176 +            // Thread id
 54.2177 +            // This is the thread id of the current thread and not the exception thread.
 54.2178 +            if(!DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &exceptionInfo.threadHandle, 0, true, DUPLICATE_SAME_ACCESS))
 54.2179 +                exceptionInfo.threadHandle = 0;
 54.2180 +            exceptionInfo.threadSysId = ConvertThreadHandleToThreadSysId(exceptionInfo.threadHandle);
 54.2181 +
 54.2182 +            OVR::GetThreadName(exceptionInfo.threadHandle, exceptionInfo.threadName, OVR_ARRAY_COUNT(exceptionInfo.threadName));
 54.2183 +
 54.2184 +            // Backtraces
 54.2185 +            exceptionInfo.backtraceCount = symbolLookup.GetBacktrace(exceptionInfo.backtrace, OVR_ARRAY_COUNT(exceptionInfo.backtrace));
 54.2186 +
 54.2187 +            // Context
 54.2188 +            exceptionInfo.cpuContext = *pExceptionPointers->ContextRecord;
 54.2189 +            exceptionInfo.exceptionRecord = *pExceptionPointers->ExceptionRecord;
 54.2190 +            exceptionInfo.pExceptionInstructionAddress  = exceptionInfo.exceptionRecord.ExceptionAddress;
 54.2191 +            if((exceptionInfo.exceptionRecord.ExceptionCode == EXCEPTION_ACCESS_VIOLATION) || (exceptionInfo.exceptionRecord.ExceptionCode == EXCEPTION_IN_PAGE_ERROR))
 54.2192 +                exceptionInfo.pExceptionMemoryAddress = (void*)exceptionInfo.exceptionRecord.ExceptionInformation[1]; // ExceptionInformation[0] indicates if it was a read (0), write (1), or data execution attempt (8).
 54.2193 +            else
 54.2194 +                exceptionInfo.pExceptionMemoryAddress = pExceptionPointers->ExceptionRecord->ExceptionAddress;
 54.2195 +
 54.2196 +            WriteExceptionDescription();
 54.2197 +
 54.2198 +            if(miniDumpFilePath[0])
 54.2199 +                WriteMiniDump();
 54.2200 +
 54.2201 +            if(reportFilePath[0])
 54.2202 +                WriteReport();
 54.2203 +
 54.2204 +            if(exceptionListener)
 54.2205 +                exceptionListener->HandleException(exceptionListenerUserValue, this, &exceptionInfo, reportFilePathActual);
 54.2206 +
 54.2207 +            if(exceptionInfo.threadHandle)
 54.2208 +            {
 54.2209 +                CloseHandle(exceptionInfo.threadHandle);
 54.2210 +                exceptionInfo.threadHandle = 0;
 54.2211 +            }
 54.2212 +
 54.2213 +            // Restore the handler that we temporarily disabled above.
 54.2214 +            vectoredHandle = AddVectoredExceptionHandler(1, Win32ExceptionFilter);
 54.2215 +
 54.2216 +            handlingBusy.Store_Release(0);
 54.2217 +        }
 54.2218 +
 54.2219 +        if(exceptionResponse == ExceptionHandler::kERTerminate)
 54.2220 +        {
 54.2221 +            TerminateProcess(GetCurrentProcess(), (UINT)terminateReturnValue);
 54.2222 +            return terminateReturnValue;
 54.2223 +        }
 54.2224 +        else if(exceptionResponse == ExceptionHandler::kERThrow)
 54.2225 +            return EXCEPTION_CONTINUE_SEARCH;
 54.2226 +        else if(exceptionResponse == ExceptionHandler::kERContinue)
 54.2227 +            return EXCEPTION_CONTINUE_EXECUTION;
 54.2228 +        return EXCEPTION_EXECUTE_HANDLER;
 54.2229 +    }
 54.2230 +
 54.2231 +#endif // defined(OVR_OS_MS)
 54.2232 +
 54.2233 +
 54.2234 +#if defined(OVR_OS_APPLE)
 54.2235 +    // http://www.opensource.apple.com/source/xnu/xnu-2050.22.13/
 54.2236 +    // http://www.opensource.apple.com/source/xnu/xnu-2050.22.13/osfmk/man/
 54.2237 +    // http://www.opensource.apple.com/source/Libc/Libc-825.26/
 54.2238 +    // https://mikeash.com/pyblog/friday-qa-2013-01-11-mach-exception-handlers.html
 54.2239 +    
 54.2240 +    void* ExceptionHandler::MachHandlerThreadFunction()
 54.2241 +    {
 54.2242 +        __Request__mach_exception_raise_state_identity_t msg;
 54.2243 +        __Reply__mach_exception_raise_state_identity_t reply;
 54.2244 +        mach_msg_return_t result;
 54.2245 +
 54.2246 +        machThreadExecuting = true;
 54.2247 +        pthread_setname_np("ExceptionHandler");
 54.2248 +        
 54.2249 +        while(machThreadShouldContinue)
 54.2250 +        {
 54.2251 +            mach_msg_option_t options = MACH_RCV_MSG | MACH_RCV_LARGE;
 54.2252 +            natural_t         timeout = 0; // Would be better to support a non-zero time.
 54.2253 +
 54.2254 +            if(timeout)
 54.2255 +                options |= MACH_RCV_TIMEOUT;
 54.2256 +            
 54.2257 +            result = mach_msg(&msg.Head, options, 0, sizeof(msg), machExceptionPort, timeout, MACH_PORT_NULL);
 54.2258 +
 54.2259 +            if(msg.Head.msgh_id != sMachCancelMessageType)
 54.2260 +            {
 54.2261 +                if(result == MACH_MSG_SUCCESS)
 54.2262 +                {
 54.2263 +                    if(mach_exc_server_OVR(&msg.Head, &reply.Head) == 0)  //This will call our HandleMachException function.
 54.2264 +                        result = ~MACH_MSG_SUCCESS;
 54.2265 +                }
 54.2266 +
 54.2267 +                // Send the reply
 54.2268 +                if(result == MACH_MSG_SUCCESS)
 54.2269 +                {
 54.2270 +                    result = mach_msg(&reply.Head, MACH_SEND_MSG, reply.Head.msgh_size, 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
 54.2271 +                    
 54.2272 +                    if(result != MACH_MSG_SUCCESS)
 54.2273 +                    {
 54.2274 +                        // Failure.
 54.2275 +                    }
 54.2276 +                }
 54.2277 +            }
 54.2278 +        }
 54.2279 +
 54.2280 +        machThreadExecuting = false;
 54.2281 +
 54.2282 +        return nullptr;
 54.2283 +    }
 54.2284 +
 54.2285 +    
 54.2286 +    kern_return_t ExceptionHandler::HandleMachException(mach_port_t /*machPort*/, mach_port_t threadSysId, mach_port_t machTask,
 54.2287 +                                            exception_type_t machExceptionType, mach_exception_data_type_t* pExceptionDetail,
 54.2288 +                                            mach_msg_type_number_t exceptionDetailCount, int* /*pMachExceptionFlavor*/, thread_state_t threadStatePrev,
 54.2289 +                                            mach_msg_type_number_t /*threadStatePrevCount*/, thread_state_t /*threadStateNew*/,
 54.2290 +                                            mach_msg_type_number_t* /*pThreadStateNewCount*/)
 54.2291 +    {
 54.2292 +        // We don't want to handle exceptions for other processes.
 54.2293 +        if(machTask != mach_task_self())
 54.2294 +            return ForwardMachException(threadSysId, machTask, machExceptionType, pExceptionDetail, exceptionDetailCount);
 54.2295 +
 54.2296 +        if(handlingBusy.CompareAndSet_Acquire(0, 1)) // If we can successfully change it from 0 to 1.
 54.2297 +        {
 54.2298 +            exceptionOccurred = true;
 54.2299 +
 54.2300 +            // Disable the handler while we do this processing.
 54.2301 +            // To do.
 54.2302 +
 54.2303 +            // Time
 54.2304 +            exceptionInfo.timeVal = time(nullptr);
 54.2305 +            exceptionInfo.time = *gmtime(&exceptionInfo.timeVal);
 54.2306 +
 54.2307 +            // Thread id
 54.2308 +            exceptionInfo.threadHandle = pthread_from_mach_thread_np(threadSysId);
 54.2309 +            exceptionInfo.threadSysId  = threadSysId;
 54.2310 +            pthread_getname_np((pthread_t)exceptionInfo.threadHandle, exceptionInfo.threadName, sizeof(exceptionInfo.threadName));
 54.2311 +
 54.2312 +            // Backtraces
 54.2313 +            exceptionInfo.backtraceCount = symbolLookup.GetBacktraceFromThreadSysId(exceptionInfo.backtrace, OVR_ARRAY_COUNT(exceptionInfo.backtrace), 0, threadSysId);
 54.2314 +
 54.2315 +            // Context
 54.2316 +            #if defined(OVR_CPU_X86) || defined(OVR_CPU_X86_64)
 54.2317 +                // We can read x86_THREAD_STATE directly fromk threadStatePrev.
 54.2318 +                exceptionInfo.cpuContext.threadState = *reinterpret_cast<x86_thread_state_t*>(threadStatePrev);
 54.2319 +            
 54.2320 +                mach_msg_type_number_t stateCount = x86_FLOAT_STATE_COUNT;
 54.2321 +                thread_get_state(threadSysId, x86_FLOAT_STATE, (natural_t*)&exceptionInfo.cpuContext.floatState, &stateCount);
 54.2322 +            
 54.2323 +                stateCount = x86_DEBUG_STATE_COUNT;
 54.2324 +                thread_get_state(threadSysId, x86_DEBUG_STATE, (natural_t*)&exceptionInfo.cpuContext.debugState, &stateCount);
 54.2325 +            
 54.2326 +                stateCount = x86_AVX_STATE_COUNT;
 54.2327 +                thread_get_state(threadSysId, x86_AVX_STATE, (natural_t*)&exceptionInfo.cpuContext.avxState, &stateCount);
 54.2328 +            
 54.2329 +                stateCount = x86_EXCEPTION_STATE_COUNT;
 54.2330 +                thread_get_state(threadSysId, x86_EXCEPTION_STATE, (natural_t*)&exceptionInfo.cpuContext.exceptionState, &stateCount);
 54.2331 +
 54.2332 +                #if defined(OVR_CPU_X86)
 54.2333 +                    exceptionInfo.pExceptionInstructionAddress = (void*)exceptionInfo.cpuContext.threadState.uts.ts32.__eip;
 54.2334 +                    exceptionInfo.pExceptionMemoryAddress      = (void*)exceptionInfo.cpuContext.exceptionState.ues.es32.__faultvaddr;
 54.2335 +                    exceptionInfo.cpuExceptionId               = exceptionInfo.cpuContext.exceptionState.ues.es32.__trapno;
 54.2336 +                    exceptionInfo.cpuExceptionIdError          = exceptionInfo.cpuContext.exceptionState.ues.es32.__err;
 54.2337 +                #else
 54.2338 +                    exceptionInfo.pExceptionInstructionAddress = (void*)exceptionInfo.cpuContext.threadState.uts.ts64.__rip;
 54.2339 +                    exceptionInfo.pExceptionMemoryAddress      = (void*)exceptionInfo.cpuContext.exceptionState.ues.es64.__faultvaddr;
 54.2340 +                    exceptionInfo.cpuExceptionId               = exceptionInfo.cpuContext.exceptionState.ues.es64.__trapno;
 54.2341 +                    exceptionInfo.cpuExceptionIdError          = exceptionInfo.cpuContext.exceptionState.ues.es64.__err;
 54.2342 +                #endif
 54.2343 +            #endif
 54.2344 +            
 54.2345 +            exceptionInfo.exceptionType = machExceptionType;
 54.2346 +
 54.2347 +            exceptionInfo.machExceptionDetailCount = MIN(exceptionDetailCount, OVR_ARRAY_COUNT(exceptionInfo.machExceptionDetail));
 54.2348 +            for(int i = 0; i < exceptionInfo.machExceptionDetailCount; i++)
 54.2349 +                exceptionInfo.machExceptionDetail[i] = pExceptionDetail[i];
 54.2350 +
 54.2351 +            WriteExceptionDescription();
 54.2352 +
 54.2353 +            if(reportFilePath[0])
 54.2354 +                WriteReport();
 54.2355 +
 54.2356 +            if(miniDumpFilePath[0])
 54.2357 +                WriteMiniDump();
 54.2358 + 
 54.2359 +            if(exceptionListener)
 54.2360 +                exceptionListener->HandleException(exceptionListenerUserValue, this, &exceptionInfo, reportFilePathActual);
 54.2361 +
 54.2362 +            // Re-restore the handler.
 54.2363 +            // To do.
 54.2364 +
 54.2365 +            handlingBusy.Store_Release(0);
 54.2366 +        }
 54.2367 +
 54.2368 +        kern_return_t result = KERN_FAILURE; // By default pass on the exception to another handler after we are done here.
 54.2369 +
 54.2370 +        if(exceptionResponse == ExceptionHandler::kERTerminate)
 54.2371 +            ::exit(terminateReturnValue);
 54.2372 +        else if(exceptionResponse == ExceptionHandler::kERThrow)
 54.2373 +            ForwardMachException(threadSysId, machTask, machExceptionType, pExceptionDetail, exceptionDetailCount);
 54.2374 +        else if(exceptionResponse == ExceptionHandler::kERDefault)
 54.2375 +            ::exit(terminateReturnValue);
 54.2376 +        else if(exceptionResponse == ExceptionHandler::kERContinue)
 54.2377 +            result = KERN_SUCCESS; // This will trigger a re-execution of the function.
 54.2378 +
 54.2379 +        return result;
 54.2380 +    }
 54.2381 +
 54.2382 +
 54.2383 +    bool ExceptionHandler::InitMachExceptionHandler()
 54.2384 +    {
 54.2385 +        if(!machHandlerInitialized)
 54.2386 +        {
 54.2387 +            mach_port_t      machTaskSelf = mach_task_self();
 54.2388 +            kern_return_t    result = MACH_MSG_SUCCESS;
 54.2389 +            exception_mask_t mask = EXC_MASK_BAD_ACCESS | EXC_MASK_BAD_INSTRUCTION | EXC_MASK_ARITHMETIC | EXC_MASK_CRASH;
 54.2390 +            
 54.2391 +            if(machExceptionPort == MACH_PORT_NULL)
 54.2392 +            {
 54.2393 +                result = mach_port_allocate(machTaskSelf, MACH_PORT_RIGHT_RECEIVE, &machExceptionPort);
 54.2394 +                
 54.2395 +                if(result == MACH_MSG_SUCCESS)
 54.2396 +                {
 54.2397 +                    result = mach_port_insert_right(machTaskSelf, machExceptionPort, machExceptionPort, MACH_MSG_TYPE_MAKE_SEND);
 54.2398 +
 54.2399 +                    if(result == MACH_MSG_SUCCESS)
 54.2400 +                        result = task_get_exception_ports(machTaskSelf, mask, machExceptionPortsSaved.masks, &machExceptionPortsSaved.count,
 54.2401 +                                                          machExceptionPortsSaved.ports, machExceptionPortsSaved.behaviors, machExceptionPortsSaved.flavors);
 54.2402 +                }
 54.2403 +            }
 54.2404 +            
 54.2405 +            if(result == MACH_MSG_SUCCESS)
 54.2406 +            {
 54.2407 +                result = task_set_exception_ports(machTaskSelf, mask, machExceptionPort, EXCEPTION_STATE_IDENTITY | MACH_EXCEPTION_CODES, MACHINE_THREAD_STATE);
 54.2408 +
 54.2409 +                if(result == MACH_MSG_SUCCESS)
 54.2410 +                {
 54.2411 +                    machThreadShouldContinue = true;
 54.2412 +
 54.2413 +                    pthread_attr_t attr;
 54.2414 +                    pthread_attr_init(&attr);
 54.2415 +                    
 54.2416 +                    result = pthread_create(&machThread, &attr, MachHandlerThreadFunctionStatic, (void*)this);
 54.2417 +                    pthread_attr_destroy(&attr);
 54.2418 +                    
 54.2419 +                    machHandlerInitialized = (result == 0);
 54.2420 +                }
 54.2421 +            }
 54.2422 +            
 54.2423 +            if(!machHandlerInitialized)
 54.2424 +                ShutdownMachExceptionHandler();
 54.2425 +        }
 54.2426 +        
 54.2427 +        return machHandlerInitialized;
 54.2428 +    }
 54.2429 +
 54.2430 +
 54.2431 +    void ExceptionHandler::ShutdownMachExceptionHandler()
 54.2432 +    {
 54.2433 +        if(machThreadExecuting)
 54.2434 +        {
 54.2435 +            machThreadShouldContinue = false; // Tell it to stop.
 54.2436 +
 54.2437 +            // Cancel the current exception handler thread (which is probably blocking in a call to mach_msg) by sending it a cencel message.
 54.2438 +            struct CancelMessage
 54.2439 +            {
 54.2440 +                mach_msg_header_t msgHeader;
 54.2441 +            };
 54.2442 +            
 54.2443 +            CancelMessage msg;
 54.2444 +            memset(&msg.msgHeader, 0, sizeof(CancelMessage));
 54.2445 +            msg.msgHeader.msgh_id          = sMachCancelMessageType;
 54.2446 +            msg.msgHeader.msgh_size        = sizeof(CancelMessage);
 54.2447 +            msg.msgHeader.msgh_bits        = MACH_MSGH_BITS_REMOTE(MACH_MSG_TYPE_MAKE_SEND);
 54.2448 +            msg.msgHeader.msgh_remote_port = machExceptionPort;
 54.2449 +            msg.msgHeader.msgh_local_port  = MACH_PORT_NULL;
 54.2450 +            
 54.2451 +            mach_msg_return_t result = mach_msg(&msg.msgHeader, MACH_SEND_MSG, msg.msgHeader.msgh_size, 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
 54.2452 +            
 54.2453 +            if(result == MACH_MSG_SUCCESS)
 54.2454 +            {
 54.2455 +                const double threeSecondsLater = ovr_GetTimeInSeconds() + 3.f;
 54.2456 +                
 54.2457 +                while(machThreadExecuting && (ovr_GetTimeInSeconds() < threeSecondsLater))
 54.2458 +                {
 54.2459 +                    timespec ts = { 0, 1000000000 };
 54.2460 +                    nanosleep(&ts, nullptr);
 54.2461 +                }
 54.2462 +            }
 54.2463 +
 54.2464 +            void* joinResult = nullptr;
 54.2465 +            pthread_join(machThread, &joinResult);
 54.2466 +            machThread = 0;
 54.2467 +        }
 54.2468 +
 54.2469 +        if(machExceptionPort != MACH_PORT_NULL)
 54.2470 +        {
 54.2471 +            // Restore the previous ports
 54.2472 +            kern_return_t result = KERN_SUCCESS;
 54.2473 +            mach_port_t   machTaskSelf = mach_task_self();
 54.2474 +            
 54.2475 +            for(unsigned i = 0; (i < machExceptionPortsSaved.count) && (result == KERN_SUCCESS); i++)
 54.2476 +            {
 54.2477 +                result = task_set_exception_ports(machTaskSelf, machExceptionPortsSaved.masks[i], machExceptionPortsSaved.ports[i],
 54.2478 +                              machExceptionPortsSaved.behaviors[i], machExceptionPortsSaved.flavors[i]);
 54.2479 +            }
 54.2480 +
 54.2481 +            mach_port_deallocate(machTaskSelf, machExceptionPort);
 54.2482 +            machExceptionPort = MACH_PORT_NULL;
 54.2483 +        }
 54.2484 +        
 54.2485 +        machHandlerInitialized = false;
 54.2486 +    }
 54.2487 +
 54.2488 +
 54.2489 +    kern_return_t ExceptionHandler::ForwardMachException(mach_port_t thread, mach_port_t task, exception_type_t exceptionType,
 54.2490 +                                                mach_exception_data_t pExceptionDetail, mach_msg_type_number_t exceptionDetailCount)
 54.2491 +    {
 54.2492 +        kern_return_t result = KERN_FAILURE;
 54.2493 +        mach_msg_type_number_t i;
 54.2494 +
 54.2495 +        for(i = 0; i < machExceptionPortsSaved.count; i++)
 54.2496 +        {
 54.2497 +            if(machExceptionPortsSaved.masks[i] & (1 << exceptionType))
 54.2498 +                break;
 54.2499 +        }
 54.2500 +        
 54.2501 +        if(i < machExceptionPortsSaved.count)
 54.2502 +        {
 54.2503 +            mach_port_t            port             = machExceptionPortsSaved.ports[i];
 54.2504 +            exception_behavior_t   behavior         = machExceptionPortsSaved.behaviors[i];
 54.2505 +            thread_state_flavor_t  flavor           = machExceptionPortsSaved.flavors[i];
 54.2506 +            mach_msg_type_number_t threadStateCount = THREAD_STATE_MAX;
 54.2507 +            thread_state_data_t    threadState;
 54.2508 +
 54.2509 +            if(behavior != EXCEPTION_DEFAULT)
 54.2510 +                thread_get_state(thread, flavor, threadState, &threadStateCount);
 54.2511 +            
 54.2512 +            switch(behavior)
 54.2513 +            {
 54.2514 +                case EXCEPTION_DEFAULT:
 54.2515 +                    result = mach_exception_raise_OVR(port, thread, task, exceptionType, pExceptionDetail, exceptionDetailCount);
 54.2516 +                    break;
 54.2517 +                    
 54.2518 +                case EXCEPTION_STATE:
 54.2519 +                    result = mach_exception_raise_state_OVR(port, exceptionType, pExceptionDetail, exceptionDetailCount,
 54.2520 +                                       &flavor, threadState, threadStateCount, threadState, &threadStateCount);
 54.2521 +                    break;
 54.2522 +
 54.2523 +                case EXCEPTION_STATE_IDENTITY:
 54.2524 +                    result = mach_exception_raise_state_identity_OVR(port, thread, task, exceptionType, pExceptionDetail,
 54.2525 +                                    exceptionDetailCount, &flavor, threadState, threadStateCount, threadState, &threadStateCount);
 54.2526 +                    break;
 54.2527 +                    
 54.2528 +                default:
 54.2529 +                    result = KERN_FAILURE;
 54.2530 +                    break;
 54.2531 +            }
 54.2532 +            
 54.2533 +            if(behavior != EXCEPTION_DEFAULT)
 54.2534 +                result = thread_set_state(thread, flavor, threadState, threadStateCount);
 54.2535 +        }
 54.2536 +        
 54.2537 +        return result;
 54.2538 +    }
 54.2539 +
 54.2540 +
 54.2541 +#endif // OVR_OS_APPLE
 54.2542 +
 54.2543 +
 54.2544 +bool ExceptionHandler::Enable(bool enable)
 54.2545 +{
 54.2546 +    #if defined(OVR_OS_MS)
 54.2547 +        if(enable && !enabled)
 54.2548 +        {
 54.2549 +            OVR_ASSERT(vectoredHandle == nullptr);
 54.2550 +            vectoredHandle = AddVectoredExceptionHandler(1, Win32ExceptionFilter); // Windows call.
 54.2551 +            enabled = (vectoredHandle != nullptr);
 54.2552 +            OVR_ASSERT(enabled);
 54.2553 +            sExceptionHandler = this;
 54.2554 +            return enabled;
 54.2555 +        }
 54.2556 +        else if(!enable && enabled)
 54.2557 +        {
 54.2558 +            if(sExceptionHandler == this)
 54.2559 +                sExceptionHandler = nullptr;
 54.2560 +            OVR_ASSERT(vectoredHandle != nullptr);
 54.2561 +            ULONG result = RemoveVectoredExceptionHandler(vectoredHandle); // Windows call.
 54.2562 +            OVR_ASSERT_AND_UNUSED(result != 0, result);
 54.2563 +            vectoredHandle = nullptr;
 54.2564 +            enabled = false;
 54.2565 +            return true;
 54.2566 +        }
 54.2567 +    
 54.2568 +    #elif defined(OVR_OS_APPLE)
 54.2569 +    
 54.2570 +        if(enable && !enabled)
 54.2571 +        {
 54.2572 +            enabled = InitMachExceptionHandler();
 54.2573 +            OVR_ASSERT(enabled);
 54.2574 +            sExceptionHandler = this;
 54.2575 +            return enabled;
 54.2576 +        }
 54.2577 +        else if(!enable && enabled)
 54.2578 +        {
 54.2579 +            if(sExceptionHandler == this)
 54.2580 +                sExceptionHandler = nullptr;
 54.2581 +            ShutdownMachExceptionHandler();
 54.2582 +            enabled = false;
 54.2583 +            return true;
 54.2584 +        }
 54.2585 +	#else
 54.2586 +        OVR_UNUSED(enable);
 54.2587 +    #endif
 54.2588 +
 54.2589 +    return true;
 54.2590 +}
 54.2591 +
 54.2592 +
 54.2593 +void ExceptionHandler::EnableReportPrivacy(bool enable)
 54.2594 +{
 54.2595 +    reportPrivacyEnabled = enable;
 54.2596 +}
 54.2597 +
 54.2598 +void ExceptionHandler::WriteExceptionDescription()
 54.2599 +{
 54.2600 +    #if defined(OVR_OS_MS)
 54.2601 +        // There is some extra information available for AV exception.
 54.2602 +        if(exceptionInfo.exceptionRecord.ExceptionCode == EXCEPTION_ACCESS_VIOLATION)
 54.2603 +        {
 54.2604 +            const char* error = (exceptionInfo.exceptionRecord.ExceptionInformation[0] == 0) ? "reading" : 
 54.2605 +                               ((exceptionInfo.exceptionRecord.ExceptionInformation[0] == 1) ? "writing" : "executing");
 54.2606 +
 54.2607 +            char addressStr[24];
 54.2608 +            SprintfAddress(addressStr, OVR_ARRAY_COUNT(addressStr), exceptionInfo.pExceptionMemoryAddress);
 54.2609 +            OVR::OVR_snprintf(exceptionInfo.exceptionDescription, OVR_ARRAY_COUNT(exceptionInfo.exceptionDescription), "ACCESS_VIOLATION %s address %s", error, addressStr);
 54.2610 +        }
 54.2611 +        else
 54.2612 +        {
 54.2613 +            exceptionInfo.exceptionDescription[0] = 0;
 54.2614 +
 54.2615 +            // Process "standard" exceptions, other than 'access violation'
 54.2616 +            #define FORMAT_EXCEPTION(x)           \
 54.2617 +                case EXCEPTION_##x:               \
 54.2618 +                    OVR::OVR_strlcpy(exceptionInfo.exceptionDescription, #x, OVR_ARRAY_COUNT(exceptionInfo.exceptionDescription)); \
 54.2619 +                    break;
 54.2620 +
 54.2621 +            switch(exceptionInfo.exceptionRecord.ExceptionCode)
 54.2622 +            {
 54.2623 +              //FORMAT_EXCEPTION(ACCESS_VIOLATION) Already handled above.
 54.2624 +                FORMAT_EXCEPTION(DATATYPE_MISALIGNMENT)
 54.2625 +                FORMAT_EXCEPTION(BREAKPOINT)
 54.2626 +                FORMAT_EXCEPTION(SINGLE_STEP)
 54.2627 +                FORMAT_EXCEPTION(ARRAY_BOUNDS_EXCEEDED)
 54.2628 +                FORMAT_EXCEPTION(FLT_DENORMAL_OPERAND)
 54.2629 +                FORMAT_EXCEPTION(FLT_DIVIDE_BY_ZERO)
 54.2630 +                FORMAT_EXCEPTION(FLT_INEXACT_RESULT)
 54.2631 +                FORMAT_EXCEPTION(FLT_INVALID_OPERATION)
 54.2632 +                FORMAT_EXCEPTION(FLT_OVERFLOW)
 54.2633 +                FORMAT_EXCEPTION(FLT_STACK_CHECK)
 54.2634 +                FORMAT_EXCEPTION(FLT_UNDERFLOW)
 54.2635 +                FORMAT_EXCEPTION(INT_DIVIDE_BY_ZERO)
 54.2636 +                FORMAT_EXCEPTION(INT_OVERFLOW)
 54.2637 +                FORMAT_EXCEPTION(PRIV_INSTRUCTION)
 54.2638 +                FORMAT_EXCEPTION(IN_PAGE_ERROR)
 54.2639 +                FORMAT_EXCEPTION(ILLEGAL_INSTRUCTION)
 54.2640 +                FORMAT_EXCEPTION(NONCONTINUABLE_EXCEPTION)
 54.2641 +                FORMAT_EXCEPTION(STACK_OVERFLOW)
 54.2642 +                FORMAT_EXCEPTION(INVALID_DISPOSITION)
 54.2643 +                FORMAT_EXCEPTION(GUARD_PAGE)
 54.2644 +                FORMAT_EXCEPTION(INVALID_HANDLE)
 54.2645 +              #if defined(EXCEPTION_POSSIBLE_DEADLOCK) && defined(STATUS_POSSIBLE_DEADLOCK) // This type seems to be non-existant in practice.
 54.2646 +                FORMAT_EXCEPTION(POSSIBLE_DEADLOCK)
 54.2647 +              #endif
 54.2648 +            }
 54.2649 +
 54.2650 +            // If not one of the "known" exceptions, try to get the string from NTDLL.DLL's message table.
 54.2651 +            if(exceptionInfo.exceptionDescription[0] == 0)
 54.2652 +            {
 54.2653 +                char addressStr[24];
 54.2654 +                SprintfAddress(addressStr, OVR_ARRAY_COUNT(addressStr), exceptionInfo.pExceptionMemoryAddress);
 54.2655 +
 54.2656 +                #if !defined(OVR_OS_CONSOLE) // If FormatMessage is supported...
 54.2657 +                    char  buffer[384];
 54.2658 +                    DWORD capacity = OVR_ARRAY_COUNT(buffer);
 54.2659 +
 54.2660 +                    const size_t length = (size_t)FormatMessageA(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_HMODULE, 
 54.2661 +                                                       GetModuleHandleW(L"NTDLL.DLL"), exceptionInfo.exceptionRecord.ExceptionCode, 0, buffer, capacity, nullptr);
 54.2662 +                    if(length)
 54.2663 +                        OVR::OVR_snprintf(exceptionInfo.exceptionDescription, OVR_ARRAY_COUNT(exceptionInfo.exceptionDescription),
 54.2664 +                                          "%s at instruction %s", buffer, addressStr);
 54.2665 +                #endif
 54.2666 +
 54.2667 +                // If everything else failed just show the hex code.
 54.2668 +                if(exceptionInfo.exceptionDescription[0] == 0)
 54.2669 +                    OVR::OVR_snprintf(exceptionInfo.exceptionDescription, OVR_ARRAY_COUNT(exceptionInfo.exceptionDescription), 
 54.2670 +                                      "Unknown exception 0x%08x at instruction %s", exceptionInfo.exceptionRecord.ExceptionCode, addressStr);
 54.2671 +            }
 54.2672 +        }
 54.2673 +
 54.2674 +    #elif defined(OVR_OS_APPLE)
 54.2675 +        struct MachExceptionInfo
 54.2676 +        {
 54.2677 +            static const char* GetCPUExceptionIdString(uint32_t cpuExceptionId)
 54.2678 +            {
 54.2679 +                const char* id;
 54.2680 +
 54.2681 +                #if defined(OVR_CPU_X86) || defined(OVR_CPU_X86_64)
 54.2682 +                    switch (cpuExceptionId)
 54.2683 +                    {
 54.2684 +                        case  0: id = "integer div/0";               break;
 54.2685 +                        case  1: id = "breakpoint fault";            break;
 54.2686 +                        case  2: id = "non-maskable interrupt";      break;
 54.2687 +                        case  3: id = "int 3";                       break;
 54.2688 +                        case  4: id = "overflow";                    break;
 54.2689 +                        case  5: id = "bounds check failure";        break;
 54.2690 +                        case  6: id = "invalid instruction";         break;
 54.2691 +                        case  7: id = "coprocessor unavailable";     break;
 54.2692 +                        case  8: id = "exception within exception";  break;
 54.2693 +                        case  9: id = "coprocessor segment overrun"; break;
 54.2694 +                        case 10: id = "invalid task switch";         break;
 54.2695 +                        case 11: id = "segment not present";         break;
 54.2696 +                        case 12: id = "stack exception";             break;
 54.2697 +                        case 13: id = "general protection fault";    break;
 54.2698 +                        case 14: id = "page fault";                  break;
 54.2699 +                        case 16: id = "coprocessor error";           break;
 54.2700 +                        default: id = "<unknown>";                   break;
 54.2701 +                    }
 54.2702 +                #else
 54.2703 +                    // To do: Support ARM or others.
 54.2704 +                #endif
 54.2705 +                
 54.2706 +                return id;
 54.2707 +            }
 54.2708 +
 54.2709 +            static const char* GetMachExceptionTypeString(uint64_t exceptionCause)
 54.2710 +            {
 54.2711 +                switch (exceptionCause)
 54.2712 +                {
 54.2713 +                    case EXC_ARITHMETIC:      return "EXC_ARITHMETIC";
 54.2714 +                    case EXC_BAD_ACCESS:      return "EXC_BAD_ACCESS";
 54.2715 +                    case EXC_BAD_INSTRUCTION: return "EXC_BAD_INSTRUCTION";
 54.2716 +                    case EXC_BREAKPOINT:      return "EXC_BREAKPOINT";
 54.2717 +                    case EXC_CRASH:           return "EXC_CRASH";
 54.2718 +                    case EXC_EMULATION:       return "EXC_EMULATION";
 54.2719 +                    case EXC_MACH_SYSCALL:    return "EXC_MACH_SYSCALL";
 54.2720 +                    case EXC_RPC_ALERT:       return "EXC_RPC_ALERT";
 54.2721 +                    case EXC_SOFTWARE:        return "EXC_SOFTWARE";
 54.2722 +                    case EXC_SYSCALL:         return "EXC_SYSCALL";
 54.2723 +                };
 54.2724 +
 54.2725 +                return "EXC_<unknown>";
 54.2726 +            }
 54.2727 +            
 54.2728 +            static const char* GetMachExceptionIdString(uint64_t machExceptionId, uint64_t code0)
 54.2729 +            {
 54.2730 +                const char* id = "<unknown>";
 54.2731 +
 54.2732 +                #if defined(OVR_CPU_X86) || defined(OVR_CPU_X86_64)
 54.2733 +                    switch (machExceptionId)
 54.2734 +                    {
 54.2735 +                        case EXC_ARITHMETIC:
 54.2736 +                            switch (code0)
 54.2737 +                            {
 54.2738 +                                case EXC_I386_BOUND:     id = "EXC_I386_BOUND";     break;
 54.2739 +                                case EXC_I386_DIV:       id = "EXC_I386_DIV";       break;
 54.2740 +                                case EXC_I386_EMERR:     id = "EXC_I386_EMERR";     break;
 54.2741 +                                case EXC_I386_EXTERR:    id = "EXC_I386_EXTERR";    break;
 54.2742 +                                case EXC_I386_EXTOVR:    id = "EXC_I386_EXTOVR";    break;
 54.2743 +                                case EXC_I386_INTO:      id = "EXC_I386_INTO";      break;
 54.2744 +                                case EXC_I386_NOEXT:     id = "EXC_I386_NOEXT";     break;
 54.2745 +                                case EXC_I386_SSEEXTERR: id = "EXC_I386_SSEEXTERR"; break;
 54.2746 +                            }
 54.2747 +                            break;
 54.2748 +                            
 54.2749 +                        case EXC_BAD_INSTRUCTION:
 54.2750 +                            if(code0 == EXC_I386_INVOP)
 54.2751 +                                id = "EXC_I386_INVOP";
 54.2752 +                            break;
 54.2753 +                            
 54.2754 +                        case EXC_BREAKPOINT:
 54.2755 +                            if(code0 == EXC_I386_BPT)
 54.2756 +                                id = "EXC_I386_BPT";
 54.2757 +                            else if(code0 == EXC_I386_SGL)
 54.2758 +                                id = "EXC_I386_SGL";
 54.2759 +                            break;
 54.2760 +                    };
 54.2761 +                #else
 54.2762 +                    // To do.
 54.2763 +                #endif
 54.2764 +
 54.2765 +                return id;
 54.2766 +            }
 54.2767 +        };
 54.2768 +    
 54.2769 +        OVR::OVR_snprintf(exceptionInfo.exceptionDescription, OVR_ARRAY_COUNT(exceptionInfo.exceptionDescription), 
 54.2770 +                            "Mach exception type: %llu (%s)\r\n", exceptionInfo.exceptionType, MachExceptionInfo::GetMachExceptionTypeString(exceptionInfo.exceptionType));
 54.2771 +    
 54.2772 +        OVR::OVR_snprintf(scratchBuffer, OVR_ARRAY_COUNT(scratchBuffer), "CPU exception info: exception id: %u (%s), exception id error: %u, fault memory address: %p\r\n",
 54.2773 +                            exceptionInfo.cpuExceptionId, MachExceptionInfo::GetCPUExceptionIdString(exceptionInfo.cpuExceptionId), exceptionInfo.cpuExceptionIdError, exceptionInfo.pExceptionMemoryAddress);
 54.2774 +        OVR::OVR_strlcat(exceptionInfo.exceptionDescription, scratchBuffer, OVR_ARRAY_COUNT(exceptionInfo.exceptionDescription));
 54.2775 +
 54.2776 +
 54.2777 +        OVR::OVR_snprintf(scratchBuffer, OVR_ARRAY_COUNT(scratchBuffer), "Mach exception info: exception id: %llu (%s), 0x%llx (%llu)\r\n", (uint64_t)exceptionInfo.machExceptionDetail[0],
 54.2778 +                           MachExceptionInfo::GetMachExceptionIdString(exceptionInfo.exceptionType, exceptionInfo.machExceptionDetail[0]),
 54.2779 +                           (uint64_t)exceptionInfo.machExceptionDetail[1], (uint64_t)exceptionInfo.machExceptionDetail[1]);
 54.2780 +        OVR::OVR_strlcat(exceptionInfo.exceptionDescription, scratchBuffer, OVR_ARRAY_COUNT(exceptionInfo.exceptionDescription));
 54.2781 +    #else
 54.2782 +        // To do.
 54.2783 +        exceptionInfo.exceptionDescription[0] = 0;
 54.2784 +    #endif
 54.2785 +}
 54.2786 +
 54.2787 +
 54.2788 +void ExceptionHandler::WriteReportLine(const char* pLine)
 54.2789 +{
 54.2790 +    fwrite(pLine, strlen(pLine), 1, file);
 54.2791 +}
 54.2792 +
 54.2793 +
 54.2794 +void ExceptionHandler::WriteReportLineF(const char* format, ...)
 54.2795 +{
 54.2796 +    va_list args;
 54.2797 +    va_start(args, format);
 54.2798 +    int length = OVR_vsnprintf(scratchBuffer, OVR_ARRAY_COUNT(scratchBuffer), format, args);
 54.2799 +    if(length >= (int)OVR_ARRAY_COUNT(scratchBuffer))     // If we didn't have enough space...
 54.2800 +        length = (OVR_ARRAY_COUNT(scratchBuffer) - 1);    // ... use what we have.
 54.2801 +    va_end(args);
 54.2802 +    
 54.2803 +    fwrite(scratchBuffer, length, 1, file);
 54.2804 +}
 54.2805 +
 54.2806 +
 54.2807 +// Thread <name> <handle> <id>
 54.2808 +// 0   <module> <address> <function> <file>:<line>
 54.2809 +// 1   <module> <address> <function> <file>:<line>
 54.2810 +// . . .
 54.2811 +//
 54.2812 +void ExceptionHandler::WriteThreadCallstack(ThreadHandle threadHandle, ThreadSysId threadSysId, const char* additionalInfo)
 54.2813 +{
 54.2814 +    // We intentionally do not directly use the SymbolInfo::ReportThreadCallstack function because that function allocates memory, 
 54.2815 +    // which we cannot do due to possibly being within an exception handler.
 54.2816 +
 54.2817 +    // Print the header
 54.2818 +    char    threadName[32];
 54.2819 +    char    threadHandleStr[32];
 54.2820 +    char    threadSysIdStr[32];
 54.2821 +    char    stackBaseStr[24];
 54.2822 +    char    stackLimitStr[24];
 54.2823 +    char    stackCurrentStr[24];
 54.2824 +    void*   pStackBase;
 54.2825 +    void*   pStackLimit;
 54.2826 +    bool    isExceptionThread = (threadSysId == exceptionInfo.threadSysId);
 54.2827 +
 54.2828 +    #if defined(OVR_OS_MS) && (OVR_PTR_SIZE == 8)
 54.2829 +      void* pStackCurrent = (threadSysId == exceptionInfo.threadSysId) ? (void*)exceptionInfo.cpuContext.Rsp : nullptr; // We would need to suspend the thread, get its context, resume it, then read the rsp register. It turns out we are already doing that suspend/resume below in the backtrace call. 
 54.2830 +    #elif defined(OVR_OS_MS)
 54.2831 +      void* pStackCurrent = (threadSysId == exceptionInfo.threadSysId) ? (void*)exceptionInfo.cpuContext.Esp : nullptr;
 54.2832 +    #elif defined(OVR_OS_MAC) && (OVR_PTR_SIZE == 8)
 54.2833 +      void* pStackCurrent = (threadSysId == exceptionInfo.threadSysId) ? (void*)exceptionInfo.cpuContext.threadState.uts.ts64.__rsp : nullptr;
 54.2834 +    #elif defined(OVR_OS_MAC)
 54.2835 +      void* pStackCurrent = (threadSysId == exceptionInfo.threadSysId) ? (void*)exceptionInfo.cpuContext.threadState.uts.ts32.__esp : nullptr;
 54.2836 +    #elif defined(OVR_OS_LINUX)
 54.2837 +      void* pStackCurrent = nullptr; // To do.
 54.2838 +    #endif
 54.2839 +
 54.2840 +    OVR::GetThreadStackBounds(pStackBase, pStackLimit, threadHandle);
 54.2841 +
 54.2842 +    OVR::Thread::GetThreadName(threadName, OVR_ARRAY_COUNT(threadName), threadName);
 54.2843 +    SprintfThreadHandle(threadHandleStr,  OVR_ARRAY_COUNT(threadHandleStr), threadHandle);
 54.2844 +    SprintfThreadSysId(threadSysIdStr, OVR_ARRAY_COUNT(threadSysIdStr), threadSysId);
 54.2845 +    SprintfAddress(stackBaseStr, OVR_ARRAY_COUNT(stackBaseStr), pStackBase);
 54.2846 +    SprintfAddress(stackLimitStr, OVR_ARRAY_COUNT(stackLimitStr), pStackLimit);
 54.2847 +    SprintfAddress(stackCurrentStr, OVR_ARRAY_COUNT(stackCurrentStr), pStackCurrent);
 54.2848 +
 54.2849 +    if(threadName[0])
 54.2850 +        WriteReportLineF("Thread \"%s\" handle: %s, id: %s, stack base: %s, stack limit: %s, stack current: %s, %s\r\n", threadName, threadHandleStr, threadSysIdStr, stackBaseStr, stackLimitStr, stackCurrentStr, additionalInfo ? additionalInfo : "");
 54.2851 +    else
 54.2852 +        WriteReportLineF("Thread handle: %s, id: %s, stack base: %s, stack limit: %s, stack current: %s, %s\r\n", threadHandleStr, threadSysIdStr, stackBaseStr, stackLimitStr, stackCurrentStr, additionalInfo ? additionalInfo : "");
 54.2853 +
 54.2854 +    // Print the backtrace info
 54.2855 +    void*       addressArray[64];
 54.2856 +    size_t      addressCount = symbolLookup.GetBacktraceFromThreadSysId(addressArray, OVR_ARRAY_COUNT(addressArray), 0, threadSysId);
 54.2857 +    SymbolInfo  symbolInfo;
 54.2858 +    const char* pModuleName;
 54.2859 +    size_t      backtraceSkipCount = 0;
 54.2860 +
 54.2861 +    if(isExceptionThread)
 54.2862 +    {
 54.2863 +        // If this thread is the exception thread, skip some frames.
 54.2864 +        #if defined(OVR_OS_MS)
 54.2865 +            size_t i, iEnd = MIN(16, addressCount);
 54.2866 +
 54.2867 +            for(i = 0; i < iEnd; i++)
 54.2868 +            {
 54.2869 +                symbolLookup.LookupSymbol((uint64_t)addressArray[i], symbolInfo);
 54.2870 +                if(strstr(symbolInfo.function, "UserExceptionDispatcher") != nullptr)
 54.2871 +                    break;
 54.2872 +            }
 54.2873 +
 54.2874 +            if(i < iEnd) // If found...
 54.2875 +                backtraceSkipCount = i;
 54.2876 +            else if(addressCount >= 9)      // Else default to 9, which is coincidentally what works.
 54.2877 +                backtraceSkipCount = 9;
 54.2878 +            else
 54.2879 +                backtraceSkipCount = 0;
 54.2880 +
 54.2881 +            addressArray[backtraceSkipCount] = exceptionInfo.pExceptionInstructionAddress;
 54.2882 +        #endif
 54.2883 +    }
 54.2884 +
 54.2885 +    if(addressCount == 0)
 54.2886 +    {
 54.2887 +        WriteReportLine("<Unable to read backtrace>\r\n\r\n");
 54.2888 +    }
 54.2889 +    else
 54.2890 +    {
 54.2891 +        for(size_t i = backtraceSkipCount; i < addressCount; ++i)
 54.2892 +        {
 54.2893 +            symbolLookup.LookupSymbol((uint64_t)addressArray[i], symbolInfo);
 54.2894 +
 54.2895 +            if(symbolInfo.pModuleInfo && symbolInfo.pModuleInfo->name[0])
 54.2896 +                pModuleName = symbolInfo.pModuleInfo->name;
 54.2897 +            else
 54.2898 +                pModuleName = "(unknown module)";
 54.2899 +
 54.2900 +            char addressStr[24];
 54.2901 +            SprintfAddress(addressStr, OVR_ARRAY_COUNT(addressStr), addressArray[i]);
 54.2902 +
 54.2903 +            if(symbolInfo.filePath[0])
 54.2904 +                WriteReportLineF("%-2u %-24s %s %s+%d %s:%d\r\n%s", (unsigned)i, pModuleName, addressStr,
 54.2905 +                                    symbolInfo.function, symbolInfo.functionOffset, symbolInfo.filePath,
 54.2906 +                                    symbolInfo.fileLineNumber, (i + 1) == addressCount ? "\r\n" : "");
 54.2907 +            else
 54.2908 +                WriteReportLineF("%-2u %-24s %s %s+%d\r\n%s", (unsigned)i, pModuleName, addressStr,
 54.2909 +                                    symbolInfo.function, symbolInfo.functionOffset, (i + 1) == addressCount ? "\r\n" : ""); // If this is the last line, append another \r\n.
 54.2910 +        }
 54.2911 +    }
 54.2912 +}
 54.2913 +
 54.2914 +
 54.2915 +void ExceptionHandler::WriteReport()
 54.2916 +{
 54.2917 +    // It's important that we don't allocate any memory here if we can help it.
 54.2918 +    using namespace OVR;
 54.2919 +
 54.2920 +    if(strstr(reportFilePath, "%s")) // If the user-specified file path includes a date/time component...
 54.2921 +    {
 54.2922 +        char dateTimeBuffer[64];
 54.2923 +        FormatDateTime(dateTimeBuffer, OVR_ARRAY_COUNT(dateTimeBuffer), exceptionInfo.timeVal, true, true, false, true);
 54.2924 +        OVR_snprintf(reportFilePathActual, OVR_ARRAY_COUNT(reportFilePathActual), reportFilePath, dateTimeBuffer);
 54.2925 +    }
 54.2926 +    else
 54.2927 +    {
 54.2928 +        OVR_strlcpy(reportFilePathActual, reportFilePath, OVR_ARRAY_COUNT(reportFilePathActual));
 54.2929 +    }
 54.2930 +
 54.2931 +    file = fopen(reportFilePathActual, "w");
 54.2932 +    OVR_ASSERT(file != nullptr);
 54.2933 +    if(!file)
 54.2934 +        return;
 54.2935 +
 54.2936 +    symbolLookup.Initialize();
 54.2937 +
 54.2938 +    {
 54.2939 +        // Exception information
 54.2940 +        WriteReportLine("Exception Info\r\n");
 54.2941 +
 54.2942 +        WriteReportLineF("Exception report file: %s\r\n", reportFilePathActual);
 54.2943 +
 54.2944 +        #if defined(OVR_OS_MS)
 54.2945 +            if(miniDumpFilePath[0])
 54.2946 +                WriteReportLineF("Exception minidump file: %s\r\n", minidumpFilePathActual);
 54.2947 +        #endif
 54.2948 +
 54.2949 +        char dateTimeBuffer[64];
 54.2950 +        FormatDateTime(dateTimeBuffer, OVR_ARRAY_COUNT(dateTimeBuffer), exceptionInfo.timeVal, true, true, false, false);
 54.2951 +        WriteReportLineF("Time (GMT): %s\r\n", dateTimeBuffer);
 54.2952 +
 54.2953 +        FormatDateTime(dateTimeBuffer, OVR_ARRAY_COUNT(scratchBuffer), exceptionInfo.timeVal, true, true, true, false);
 54.2954 +        WriteReportLineF("Time (local): %s\r\n", dateTimeBuffer);
 54.2955 +        WriteReportLineF("Thread name: %s\r\n", exceptionInfo.threadName[0] ? exceptionInfo.threadName : "(not available)"); // It's never possible on Windows to get thread names, as they are stored in the debugger at runtime.
 54.2956 +
 54.2957 +        SprintfThreadHandle(scratchBuffer, OVR_ARRAY_COUNT(scratchBuffer), exceptionInfo.threadHandle);
 54.2958 +        OVR_strlcat(scratchBuffer, "\r\n", OVR_ARRAY_COUNT(scratchBuffer));
 54.2959 +        WriteReportLine("Thread handle: ");
 54.2960 +        WriteReportLine(scratchBuffer);
 54.2961 +
 54.2962 +        SprintfThreadSysId(scratchBuffer, OVR_ARRAY_COUNT(scratchBuffer), exceptionInfo.threadSysId);
 54.2963 +        OVR_strlcat(scratchBuffer, "\r\n", OVR_ARRAY_COUNT(scratchBuffer));
 54.2964 +        WriteReportLine("Thread sys id: ");
 54.2965 +        WriteReportLine(scratchBuffer);
 54.2966 +
 54.2967 +        char addressStr[24];
 54.2968 +        SprintfAddress(addressStr, OVR_ARRAY_COUNT(addressStr), exceptionInfo.pExceptionInstructionAddress);
 54.2969 +        WriteReportLineF("Exception instruction address: %s (see callstack below)\r\n", addressStr);
 54.2970 +        WriteReportLineF("Exception description: %s\r\n", exceptionInfo.exceptionDescription);
 54.2971 +
 54.2972 +        if(symbolLookup.LookupSymbol((uint64_t)exceptionInfo.pExceptionInstructionAddress, exceptionInfo.symbolInfo))
 54.2973 +        {
 54.2974 +            if(exceptionInfo.symbolInfo.filePath[0])
 54.2975 +                WriteReportLineF("Exception location: %s (%d)\r\n", exceptionInfo.symbolInfo.filePath, exceptionInfo.symbolInfo.fileLineNumber);
 54.2976 +            else
 54.2977 +                WriteReportLineF("Exception location: %s (%d)\r\n", exceptionInfo.symbolInfo.function, exceptionInfo.symbolInfo.functionOffset);
 54.2978 +        }
 54.2979 +
 54.2980 +        // To consider: print exceptionInfo.cpuContext registers 
 54.2981 +    }
 54.2982 +
 54.2983 +    // OVR information
 54.2984 +    WriteReportLine("\r\nOVR Info\r\n");
 54.2985 +    WriteReportLineF("OVR time: %f\r\n", ovr_GetTimeInSeconds());
 54.2986 +    WriteReportLineF("OVR version: %s\r\n", ovr_GetVersionString());
 54.2987 +
 54.2988 +    // OVR util information
 54.2989 +    // The following would be useful to use if they didn't allocate memory, which we can't do.
 54.2990 +    // To do: see if we can have versions of the functions below which don't allocate memory
 54.2991 +    // or allocate it safely (e.g. use an alternative heap).
 54.2992 +    // String OVR::GetDisplayDriverVersion();
 54.2993 +    // String OVR::GetCameraDriverVersion();
 54.2994 +
 54.2995 +    // OVR HMD information
 54.2996 +    WriteReportLine("\r\nOVR HMD Info\r\n");
 54.2997 +
 54.2998 +    const OVR::List<OVR::CAPI::HMDState>& hmdStateList = OVR::CAPI::HMDState::GetHMDStateList();
 54.2999 +    const OVR::CAPI::HMDState* pHMDState = hmdStateList.GetFirst();
 54.3000 +    
 54.3001 +    if(hmdStateList.IsNull(pHMDState))
 54.3002 +    {
 54.3003 +        WriteReportLine("No HMDs found.\r\n");
 54.3004 +    }
 54.3005 +
 54.3006 +    while(!hmdStateList.IsNull(pHMDState))
 54.3007 +    {
 54.3008 +        if(pHMDState->pProfile)
 54.3009 +        {
 54.3010 +            const char* user = pHMDState->pProfile->GetValue(OVR_KEY_USER);
 54.3011 +            
 54.3012 +            if(user)
 54.3013 +                WriteReportLineF("Profile user: %s\r\n", reportPrivacyEnabled ? "<disabled by report privacy settings>" : user);
 54.3014 +            else
 54.3015 +                WriteReportLine("Null profile user\r\n");
 54.3016 +
 54.3017 +            float NeckEyeDistance[2];
 54.3018 +            float EyeToNoseDistance[2];
 54.3019 +            float MaxEyeToPlateDist[2];
 54.3020 +            pHMDState->pProfile->GetFloatValues(OVR_KEY_NECK_TO_EYE_DISTANCE, NeckEyeDistance, 2);
 54.3021 +            pHMDState->pProfile->GetFloatValues(OVR_KEY_EYE_TO_NOSE_DISTANCE, EyeToNoseDistance, 2);
 54.3022 +            pHMDState->pProfile->GetFloatValues(OVR_KEY_MAX_EYE_TO_PLATE_DISTANCE, MaxEyeToPlateDist, 2);
 54.3023 +            
 54.3024 +            WriteReportLineF("Player height: %f, eye height: %f, IPD: %f, Neck eye distance: %f,%f, eye relief dial: %d, eye to nose distance: %f,%f, max eye to plate distance: %f,%f, custom eye render: %s\r\n",
 54.3025 +                        pHMDState->pProfile->GetFloatValue(OVR_KEY_PLAYER_HEIGHT, 0.f),
 54.3026 +                        pHMDState->pProfile->GetFloatValue(OVR_KEY_EYE_HEIGHT, 0.f),
 54.3027 +                        pHMDState->pProfile->GetFloatValue(OVR_KEY_IPD, 0.f),
 54.3028 +                        NeckEyeDistance[0], NeckEyeDistance[1],
 54.3029 +                        pHMDState->pProfile->GetIntValue(OVR_KEY_EYE_RELIEF_DIAL, 0),
 54.3030 +                        EyeToNoseDistance[0], EyeToNoseDistance[1],
 54.3031 +                        MaxEyeToPlateDist[0], MaxEyeToPlateDist[1],
 54.3032 +                        pHMDState->pProfile->GetBoolValue(OVR_KEY_CUSTOM_EYE_RENDER, false) ? "yes" : "no");
 54.3033 +            
 54.3034 +            // Not currently used:
 54.3035 +            // OVR_KEY_NAME
 54.3036 +            // OVR_KEY_GENDER
 54.3037 +            // OVR_KEY_EYE_CUP
 54.3038 +            // OVR_KEY_CAMERA_POSITION
 54.3039 +        }
 54.3040 +        else
 54.3041 +        {
 54.3042 +            WriteReportLine("Null HMD profile\r\n");
 54.3043 +        }
 54.3044 +        
 54.3045 +        if(pHMDState->pHmdDesc) // This should usually be true.
 54.3046 +        {
 54.3047 +            WriteReportLineF("HMD %d: Type: %u ProductName: %s, Manufacturer: %s VendorId: %d, ProductId: %d, SerialNumber: %s, FirmwareMajor: %d, FirmwareMinor: %d, Resolution: %dx%d, DisplayDeviceName: %s, DisplayId: %d\r\n",
 54.3048 +                            0, (unsigned)pHMDState->pHmdDesc->Type, pHMDState->pHmdDesc->ProductName, pHMDState->pHmdDesc->Manufacturer, pHMDState->pHmdDesc->VendorId, 
 54.3049 +                            pHMDState->pHmdDesc->ProductId, pHMDState->pHmdDesc->SerialNumber, pHMDState->pHmdDesc->FirmwareMajor, pHMDState->pHmdDesc->FirmwareMinor, 
 54.3050 +                            pHMDState->pHmdDesc->Resolution.w, pHMDState->pHmdDesc->Resolution.h, pHMDState->pHmdDesc->DisplayDeviceName, pHMDState->pHmdDesc->DisplayId);
 54.3051 +
 54.3052 +            // HSW display state
 54.3053 +            ovrHSWDisplayState hswDS;
 54.3054 +            ovrHmd_GetHSWDisplayState(pHMDState->pHmdDesc, &hswDS);
 54.3055 +            WriteReportLineF("HSW displayed for hmd: %s\r\n", hswDS.Displayed ? "yes" : "no");
 54.3056 +        }
 54.3057 +
 54.3058 +        char threadIdStr[24];
 54.3059 +        SprintfAddress(threadIdStr, OVR_ARRAY_COUNT(threadIdStr), pHMDState->BeginFrameThreadId);
 54.3060 +
 54.3061 +        WriteReportLineF("Hmd Caps: %x, Hmd Service Caps: %x, Latency test active: %s, Last frame time: %f, Last get frame time: %f, Rendering configred: %s, Begin frame called: %s, Begin frame thread id: %s\r\n",
 54.3062 +                    pHMDState->EnabledHmdCaps, pHMDState->EnabledServiceHmdCaps, pHMDState->LatencyTestActive ? "yes" : "no", pHMDState->LastFrameTimeSeconds, pHMDState->LastGetFrameTimeSeconds, pHMDState->RenderingConfigured ? "yes" : "no",
 54.3063 +                    pHMDState->BeginFrameCalled ? "yes" : "no", threadIdStr);
 54.3064 +
 54.3065 +        if(pHMDState->pLastError)
 54.3066 +        {
 54.3067 +            WriteReportLineF("OVR last error for hmd: %s\r\n", pHMDState->pLastError);
 54.3068 +        }
 54.3069 +
 54.3070 +        pHMDState = hmdStateList.GetNext(pHMDState);
 54.3071 +    }
 54.3072 +
 54.3073 +    #if defined(OVR_OS_WIN32)
 54.3074 +        {
 54.3075 +            WriteReportLine("\r\nApp Info\r\n");
 54.3076 +
 54.3077 +            // Print the app path.
 54.3078 +            char appPath[MAX_PATH];
 54.3079 +            GetCurrentProcessFilePath(appPath, OVR_ARRAY_COUNT(appPath));
 54.3080 +            WriteReportLineF("Process path: %s\r\n", appPath);
 54.3081 +
 54.3082 +            #if (OVR_PTR_SIZE == 4)
 54.3083 +                WriteReportLine("App format: 32 bit\r\n");
 54.3084 +            #else
 54.3085 +                WriteReportLine("App format: 64 bit\r\n");
 54.3086 +            #endif
 54.3087 +            
 54.3088 +            // Print the app version
 54.3089 +            wchar_t pathW[MAX_PATH] = {};
 54.3090 +            GetModuleFileNameW(0, pathW, (DWORD)OVR_ARRAY_COUNT(pathW));
 54.3091 +            DWORD dwUnused;
 54.3092 +            DWORD dwSize = GetFileVersionInfoSizeW(pathW, &dwUnused);
 54.3093 +            scratchBuffer[0] = 0;
 54.3094 +
 54.3095 +            if(dwSize > 0)
 54.3096 +            {
 54.3097 +                void* const pVersionData = SafeMMapAlloc(dwSize);
 54.3098 +
 54.3099 +                if(pVersionData)
 54.3100 +                {
 54.3101 +                    if(GetFileVersionInfoW(pathW, 0, dwSize, pVersionData))
 54.3102 +                    {
 54.3103 +                        VS_FIXEDFILEINFO* pFFI;
 54.3104 +                        UINT size;
 54.3105 +
 54.3106 +                        if(VerQueryValueA(pVersionData, "\\", (void**)&pFFI, &size))
 54.3107 +                        {
 54.3108 +                            WriteReportLineF("App version: %u.%u.%u.%u\r\n",
 54.3109 +                                            HIWORD(pFFI->dwFileVersionMS), LOWORD(pFFI->dwFileVersionMS), 
 54.3110 +                                            HIWORD(pFFI->dwFileVersionLS), LOWORD(pFFI->dwFileVersionLS));
 54.3111 +                        }
 54.3112 +                    }
 54.3113 +
 54.3114 +                    SafeMMapFree(pVersionData, dwSize);
 54.3115 +                }
 54.3116 +            }
 54.3117 +
 54.3118 +            if(!scratchBuffer[0]) // If version info couldn't be found or read...
 54.3119 +                WriteReportLine("App version info not present\r\n");
 54.3120 +        }
 54.3121 +
 54.3122 +        {
 54.3123 +            WriteReportLine("\r\nSystem Info\r\n");
 54.3124 +
 54.3125 +            OSVERSIONINFOEXW vi;
 54.3126 +            memset(&vi, 0, sizeof(vi));
 54.3127 +            vi.dwOSVersionInfoSize = sizeof(vi);
 54.3128 +            GetVersionExW((LPOSVERSIONINFOW)&vi); // Cast to the older type.
 54.3129 +
 54.3130 +            char osVersionName[256];
 54.3131 +            GetOSVersionName(osVersionName, OVR_ARRAY_COUNT(osVersionName));
 54.3132 +            WriteReportLineF("OS name: %s, version: %u.%u build %u, %s, platform id: %u, service pack: %ls\r\n",
 54.3133 +                            osVersionName, vi.dwMajorVersion, vi.dwMinorVersion, vi.dwBuildNumber, Is64BitOS() ? "64 bit" : "32 bit",
 54.3134 +                            vi.dwPlatformId, vi.szCSDVersion[0] ? vi.szCSDVersion : L"<none>");
 54.3135 +
 54.3136 +            WriteReportLineF("Debugger present: %s\r\n", OVRIsDebuggerPresent() ? "yes" : "no");
 54.3137 +
 54.3138 +            // System info
 54.3139 +            SYSTEM_INFO systemInfo;
 54.3140 +            GetNativeSystemInfo(&systemInfo);
 54.3141 +            
 54.3142 +            WriteReportLineF("Processor count: %u\r\n", systemInfo.dwNumberOfProcessors);
 54.3143 +
 54.3144 +            // Windows Vista and later:
 54.3145 +            // BOOL WINAPI GetLogicalProcessorInformation(PSYSTEM_LOGICAL_PROCESSOR_INFORMATION Buffer, PDWORD ReturnLength);
 54.3146 +
 54.3147 +            if(systemInfo.wProcessorArchitecture == 0)
 54.3148 +                WriteReportLineF("Processor type: x86\r\n");
 54.3149 +            else if(systemInfo.wProcessorArchitecture == 9)
 54.3150 +                WriteReportLineF("Processor type: x86-64\r\n");
 54.3151 +            else if(systemInfo.wProcessorArchitecture == 10)
 54.3152 +                WriteReportLineF("Processor type: x86 on x86-64\r\n");
 54.3153 +
 54.3154 +            WriteReportLineF("Processor level: %u\r\n", systemInfo.wProcessorLevel);
 54.3155 +            WriteReportLineF("Processor revision: %u\r\n", systemInfo.wProcessorRevision);
 54.3156 +
 54.3157 +            // Memory information
 54.3158 +            MEMORYSTATUSEX memoryStatusEx;
 54.3159 +            memset(&memoryStatusEx, 0, sizeof(memoryStatusEx));
 54.3160 +            memoryStatusEx.dwLength = sizeof(memoryStatusEx);
 54.3161 +            GlobalMemoryStatusEx(&memoryStatusEx);
 54.3162 +
 54.3163 +            WriteReportLineF("Memory load: %d%%\r\n", memoryStatusEx.dwMemoryLoad);
 54.3164 +            WriteReportLineF("Total physical memory: %I64d MiB\r\n", memoryStatusEx.ullTotalPhys / (1024 * 1024)); // Or are Mebibytes equal to (1024 * 1000)
 54.3165 +            WriteReportLineF("Available physical memory: %I64d MiB\r\n", memoryStatusEx.ullAvailPhys / (1024 * 1024));
 54.3166 +            WriteReportLineF("Total page file memory: %I64d MiB\r\n", memoryStatusEx.ullTotalPageFile / (1024 * 1024));
 54.3167 +            WriteReportLineF("Available page file memory: %I64d MiB\r\n", memoryStatusEx.ullAvailPageFile / (1024 * 1024));
 54.3168 +            WriteReportLineF("Total virtual memory: %I64d MiB\r\n", memoryStatusEx.ullTotalVirtual / (1024 * 1024));
 54.3169 +            WriteReportLineF("Free virtual memory: %I64d MiB\r\n", memoryStatusEx.ullAvailVirtual / (1024 * 1024));
 54.3170 +
 54.3171 +            DISPLAY_DEVICE dd; 
 54.3172 +            memset(&dd, 0, sizeof(DISPLAY_DEVICE));
 54.3173 +            dd.cb = sizeof(DISPLAY_DEVICE);
 54.3174 +
 54.3175 +            for(int i = 0; EnumDisplayDevicesW(nullptr, (DWORD)i, &dd, EDD_GET_DEVICE_INTERFACE_NAME); ++i)
 54.3176 +            {
 54.3177 +                WriteReportLineF("Display Device %d name: %ls, context: %ls, primary: %s, mirroring: %s\r\n",
 54.3178 +                             i, dd.DeviceName, dd.DeviceString, (dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) ? "yes" : "no", (dd.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER) ? "yes" : "no");
 54.3179 +            }
 54.3180 +        }
 54.3181 +
 54.3182 +        // Print video card information
 54.3183 +        // http://msdn.microsoft.com/en-us/library/aa394512%28v=vs.85%29.aspx
 54.3184 +        {
 54.3185 +            IWbemLocator*         pIWbemLocator = nullptr;
 54.3186 +            BSTR                  bstrServer = nullptr;
 54.3187 +            IWbemServices*        pIWbemServices = nullptr;
 54.3188 +            BSTR                  bstrWQL  = nullptr;
 54.3189 +            BSTR                  bstrPath = nullptr;
 54.3190 +            IEnumWbemClassObject* pEnum = nullptr;
 54.3191 +
 54.3192 +            CoInitializeEx(nullptr, COINIT_MULTITHREADED);
 54.3193 +
 54.3194 +            HRESULT hr = CoCreateInstance(__uuidof(WbemLocator), nullptr, CLSCTX_INPROC_SERVER, __uuidof(IWbemLocator), (LPVOID*)&pIWbemLocator);
 54.3195 +            if(FAILED(hr))
 54.3196 +                goto End;
 54.3197 +
 54.3198 +            bstrServer = SysAllocString(L"\\\\.\\root\\cimv2");
 54.3199 +            hr = pIWbemLocator->ConnectServer(bstrServer, nullptr, nullptr, 0L, 0L, nullptr, nullptr, &pIWbemServices);
 54.3200 +            if(FAILED(hr))
 54.3201 +                goto End;
 54.3202 +
 54.3203 +            hr = CoSetProxyBlanket(pIWbemServices, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, nullptr, RPC_C_AUTHN_LEVEL_CALL,
 54.3204 +                                    RPC_C_IMP_LEVEL_IMPERSONATE, nullptr, EOAC_DEFAULT);
 54.3205 +            if(FAILED(hr))
 54.3206 +                goto End;
 54.3207 +
 54.3208 +            bstrWQL  = SysAllocString(L"WQL");
 54.3209 +            bstrPath = SysAllocString(L"select * from Win32_VideoController");
 54.3210 +            hr = pIWbemServices->ExecQuery(bstrWQL, bstrPath, WBEM_FLAG_FORWARD_ONLY, nullptr, &pEnum);
 54.3211 +            if(FAILED(hr))
 54.3212 +                goto End;
 54.3213 +
 54.3214 +            ULONG uReturned;
 54.3215 +            IWbemClassObject* pObj = nullptr;
 54.3216 +            hr = pEnum->Next(WBEM_INFINITE, 1, &pObj, &uReturned);
 54.3217 +            if(FAILED(hr))
 54.3218 +                goto End;
 54.3219 +
 54.3220 +            WriteReportLine("\r\nDisplay adapter list\r\n");
 54.3221 +
 54.3222 +            for(unsigned i = 0; SUCCEEDED(hr) && uReturned; i++)
 54.3223 +            {
 54.3224 +                char    sString[256];
 54.3225 +                VARIANT var;
 54.3226 +
 54.3227 +                if(i > 0)
 54.3228 +                    WriteReportLine("\r\n");
 54.3229 +
 54.3230 +                WriteReportLineF("Info for display adapter %u\r\n", i);
 54.3231 +
 54.3232 +                hr = pObj->Get(L"Name", 0, &var, nullptr, nullptr);
 54.3233 +                if(SUCCEEDED(hr))
 54.3234 +                {
 54.3235 +                    WideCharToMultiByte(CP_ACP, 0, var.bstrVal, -1, sString, sizeof(sString), nullptr, nullptr);
 54.3236 +                    WriteReportLineF("Display Adapter Name: %s\r\n", sString);
 54.3237 +                }
 54.3238 +
 54.3239 +                hr = pObj->Get(L"AdapterRAM", 0, &var, nullptr, nullptr);
 54.3240 +                if(SUCCEEDED(hr))
 54.3241 +                {
 54.3242 +                    WriteReportLineF("Display Adapter RAM: %u %s\r\n",
 54.3243 +                            ((uint32_t)var.lVal > (1024*1024*1024) ? (uint32_t)var.lVal/(1024*1024*1024) : (uint32_t)var.lVal/(1024*1024)), ((uint32_t)var.lVal > (1024*1024*1024) ? "GiB" : "MiB"));
 54.3244 +                }
 54.3245 +
 54.3246 +                hr = pObj->Get(L"DeviceID", 0, &var, nullptr, nullptr);
 54.3247 +                if(SUCCEEDED(hr))
 54.3248 +                {
 54.3249 +                    WideCharToMultiByte(CP_ACP, 0, var.bstrVal, -1, sString, sizeof(sString), nullptr, nullptr);
 54.3250 +                    WriteReportLineF("Display Adapter DeviceID: %s\r\n", sString);
 54.3251 +                }
 54.3252 +
 54.3253 +                hr = pObj->Get(L"DriverVersion", 0, &var, nullptr, nullptr);
 54.3254 +                if(SUCCEEDED(hr))
 54.3255 +                {
 54.3256 +                    WideCharToMultiByte(CP_ACP, 0, var.bstrVal, -1, sString, sizeof(sString), nullptr, nullptr);
 54.3257 +                    WriteReportLineF("Display Adapter DriverVersion: %s\r\n", sString);
 54.3258 +                }
 54.3259 +
 54.3260 +                hr = pObj->Get(L"DriverDate", 0, &var, nullptr, nullptr);
 54.3261 +                if(SUCCEEDED(hr))
 54.3262 +                {
 54.3263 +                    // http://technet.microsoft.com/en-us/library/ee156576.aspx
 54.3264 +                    wchar_t year[5] = { var.bstrVal[0], var.bstrVal[1], var.bstrVal[2], var.bstrVal[3], 0 };
 54.3265 +                    wchar_t month[3] = { var.bstrVal[4], var.bstrVal[5], 0 };
 54.3266 +                    wchar_t monthDay[3] = { var.bstrVal[6], var.bstrVal[7], 0 };
 54.3267 +                    
 54.3268 +                    WriteReportLineF("Display Adapter DriverDate (US format): %ls/%ls/%ls\r\n", month, monthDay, year);
 54.3269 +                }
 54.3270 +
 54.3271 +                // VideoProcessor
 54.3272 +                hr = pObj->Get(L"VideoProcessor", 0, &var, nullptr, nullptr);
 54.3273 +                if(SUCCEEDED(hr))
 54.3274 +                {
 54.3275 +                    WideCharToMultiByte(CP_ACP, 0, var.bstrVal, -1, sString, sizeof(sString), nullptr, nullptr);
 54.3276 +                    WriteReportLineF("Display Adapter VideoProcessor %s\r\n", sString);
 54.3277 +                }
 54.3278 +
 54.3279 +                hr = pObj->Get(L"VideoModeDescription", 0, &var, nullptr, nullptr);
 54.3280 +                if(SUCCEEDED(hr))
 54.3281 +                {
 54.3282 +                    WideCharToMultiByte(CP_ACP, 0, var.bstrVal, -1, sString, sizeof(sString), nullptr, nullptr);
 54.3283 +                    WriteReportLineF("Display Adapter VideoModeDescription: %s\r\n", sString);
 54.3284 +                }
 54.3285 +
 54.3286 +                pObj->Release();
 54.3287 +
 54.3288 +                hr = pEnum->Next(WBEM_INFINITE, 1, &pObj, &uReturned);
 54.3289 +            }
 54.3290 +
 54.3291 +            End:
 54.3292 +            if(pEnum)
 54.3293 +                pEnum->Release();
 54.3294 +            if(bstrPath)
 54.3295 +                SysFreeString(bstrPath);
 54.3296 +            if(bstrWQL)
 54.3297 +                SysFreeString(bstrWQL);
 54.3298 +            if(pIWbemServices)
 54.3299 +                pIWbemServices->Release();
 54.3300 +            if(bstrServer)
 54.3301 +                SysFreeString(bstrServer);
 54.3302 +            if(pIWbemLocator)
 54.3303 +                pIWbemLocator->Release();
 54.3304 +
 54.3305 +            CoUninitialize();
 54.3306 +        }
 54.3307 +
 54.3308 +        {
 54.3309 +            // Print a list of threads.
 54.3310 +            DWORD  currentProcessId = GetCurrentProcessId();
 54.3311 +            HANDLE hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, currentProcessId); // ICreateToolhelp32Snapshot actually ignores currentProcessId.
 54.3312 +        
 54.3313 +            if(hThreadSnap != INVALID_HANDLE_VALUE) 
 54.3314 +            {
 54.3315 +                THREADENTRY32 te32;
 54.3316 +                te32.dwSize = sizeof(THREADENTRY32); 
 54.3317 +
 54.3318 +                if(Thread32First(hThreadSnap, &te32)) 
 54.3319 +                {
 54.3320 +                    WriteReportLine("\r\nThread list\r\n");
 54.3321 +
 54.3322 +                    do {
 54.3323 +                        if(te32.th32OwnerProcessID == currentProcessId)
 54.3324 +                        {
 54.3325 +                            HANDLE hThread = ConvertThreadSysIdToThreadHandle(te32.th32ThreadID);
 54.3326 +
 54.3327 +                            if(hThread)
 54.3328 +                            {
 54.3329 +                                char buffer[96]; // Can't use scratchBuffer, because it's used by WriteThreadCallstack.
 54.3330 +                                OVR_snprintf(buffer, OVR_ARRAY_COUNT(buffer), "base priority: %ld, delta priority: %ld", te32.tpBasePri, te32.tpDeltaPri);
 54.3331 + 
 54.3332 +                                bool threadIsExceptionThread = (te32.th32ThreadID == (DWORD)exceptionInfo.threadSysId);
 54.3333 +                                if(threadIsExceptionThread)
 54.3334 +                                    OVR_strlcat(buffer, ", exception thread", OVR_ARRAY_COUNT(buffer));
 54.3335 +
 54.3336 +                                WriteThreadCallstack(hThread, (OVR::ThreadSysId)te32.th32ThreadID, buffer);
 54.3337 +                                FreeThreadHandle(hThread);
 54.3338 +                            }
 54.3339 +                        }
 54.3340 +                    } while(Thread32Next(hThreadSnap, &te32));
 54.3341 +                }
 54.3342 +            
 54.3343 +                CloseHandle(hThreadSnap);
 54.3344 +            }
 54.3345 +        }
 54.3346 +
 54.3347 +        {
 54.3348 +            // Print a list of the current modules within this process.
 54.3349 +            // DbgHelp.dll also provides a EnumerateLoadedModules64 function.
 54.3350 +            // To do: Convert the code below to use the GetModuleInfoArray function which we now have.
 54.3351 +            #if defined(OVR_OS_CONSOLE)
 54.3352 +                struct MODULEINFO {
 54.3353 +                    LPVOID lpBaseOfDll;
 54.3354 +                    DWORD  SizeOfImage;
 54.3355 +                    LPVOID EntryPoint;
 54.3356 +                };
 54.3357 +                HMODULE hModule = LoadLibraryW(L"toolhelpx.dll");
 54.3358 +            #else
 54.3359 +                HMODULE hModule = LoadLibraryW(L"psapi.dll");
 54.3360 +            #endif
 54.3361 +
 54.3362 +            if(hModule)
 54.3363 +            {
 54.3364 +                typedef BOOL  (WINAPI * ENUMPROCESSMODULES)  (HANDLE hProcess, HMODULE* phModule, DWORD cb, LPDWORD lpcbNeeded);
 54.3365 +                typedef DWORD (WINAPI * GETMODULEBASENAME)   (HANDLE hProcess, HMODULE hModule, LPWSTR lpFilename, DWORD nSize);
 54.3366 +                typedef DWORD (WINAPI * GETMODULEFILENAMEEX) (HANDLE hProcess, HMODULE hModule, LPWSTR lpFilename, DWORD nSize);
 54.3367 +                typedef BOOL  (WINAPI * GETMODULEINFORMATION)(HANDLE hProcess, HMODULE hModule, MODULEINFO* pmi, DWORD nSize);
 54.3368 +
 54.3369 +                #if defined(OVR_OS_CONSOLE)
 54.3370 +                    ENUMPROCESSMODULES   pEnumProcessModules   = (ENUMPROCESSMODULES)  (uintptr_t)GetProcAddress(hModule, "K32EnumProcessModules");
 54.3371 +                    GETMODULEBASENAME    pGetModuleBaseName    = (GETMODULEBASENAME)   (uintptr_t)GetProcAddress(hModule, "K32GetModuleBaseNameW");
 54.3372 +                    GETMODULEFILENAMEEX  pGetModuleFileNameEx  = (GETMODULEFILENAMEEX) (uintptr_t)GetProcAddress(hModule, "K32GetModuleFileNameExW");
 54.3373 +                    GETMODULEINFORMATION pGetModuleInformation = (GETMODULEINFORMATION)(uintptr_t)GetProcAddress(hModule, "K32GetModuleInformation");
 54.3374 +                #else
 54.3375 +                    ENUMPROCESSMODULES   pEnumProcessModules   = (ENUMPROCESSMODULES)  (uintptr_t)GetProcAddress(hModule, "EnumProcessModules");
 54.3376 +                    GETMODULEBASENAME    pGetModuleBaseName    = (GETMODULEBASENAME)   (uintptr_t)GetProcAddress(hModule, "GetModuleBaseNameW");
 54.3377 +                    GETMODULEFILENAMEEX  pGetModuleFileNameEx  = (GETMODULEFILENAMEEX) (uintptr_t)GetProcAddress(hModule, "GetModuleFileNameExW");
 54.3378 +                    GETMODULEINFORMATION pGetModuleInformation = (GETMODULEINFORMATION)(uintptr_t)GetProcAddress(hModule, "GetModuleInformation");
 54.3379 +                #endif
 54.3380 +
 54.3381 +                HANDLE  hProcess = GetCurrentProcess();
 54.3382 +                HMODULE hModuleArray[200];
 54.3383 +                DWORD   cbNeeded;
 54.3384 +
 54.3385 +                if(pEnumProcessModules(hProcess, hModuleArray, sizeof(hModuleArray), &cbNeeded))
 54.3386 +                {
 54.3387 +                    size_t actualModuleCount = (cbNeeded / sizeof(HMODULE));
 54.3388 +
 54.3389 +                    if(actualModuleCount > OVR_ARRAY_COUNT(hModuleArray))  //If hModuleArray's capacity was not enough...
 54.3390 +                        actualModuleCount = OVR_ARRAY_COUNT(hModuleArray);
 54.3391 +
 54.3392 +                    // Print a header
 54.3393 +                    WriteReportLine("\r\nModule list\r\n");
 54.3394 +
 54.3395 +                    #if (OVR_PTR_SIZE == 4)
 54.3396 +                        WriteReportLine("Base        Size       Entrypoint Name                     Path\r\n");
 54.3397 +                    #else
 54.3398 +                        WriteReportLine("Base                Size               Entrypoint         Name                     Path\r\n");
 54.3399 +                    #endif
 54.3400 +
 54.3401 +                    // And go through the list one by one
 54.3402 +                    for(size_t i = 0; i < actualModuleCount; i++)
 54.3403 +                    {
 54.3404 +                        MODULEINFO mi;
 54.3405 +                        size_t     length;
 54.3406 +
 54.3407 +                        if(!pGetModuleInformation(hProcess, hModuleArray[i], &mi, sizeof(mi)))
 54.3408 +                        {
 54.3409 +                            mi.EntryPoint  = nullptr;
 54.3410 +                            mi.lpBaseOfDll = nullptr;
 54.3411 +                            mi.SizeOfImage = 0;
 54.3412 +                        }
 54.3413 +
 54.3414 +                        // Write the base name.
 54.3415 +                        wchar_t name[MAX_PATH + 3];
 54.3416 +                        name[0] = '"';
 54.3417 +                        if(pGetModuleBaseName(hProcess, hModuleArray[i], name + 1, MAX_PATH))
 54.3418 +                            length = wcslen(name);
 54.3419 +                        else
 54.3420 +                        {
 54.3421 +                            wcscpy(name + 1, L"(unknown)");
 54.3422 +                            length = 10;
 54.3423 +                        }
 54.3424 +
 54.3425 +                        name[length] = '"';
 54.3426 +                        name[length + 1] = '\0';
 54.3427 +
 54.3428 +                        // Write the path
 54.3429 +                        wchar_t path[MAX_PATH + 3];
 54.3430 +                        path[0] = '"';
 54.3431 +                        if(pGetModuleFileNameEx(hProcess, hModuleArray[i], path + 1, MAX_PATH))
 54.3432 +                            length = wcslen(path);
 54.3433 +                        else
 54.3434 +                        {
 54.3435 +                            wcscpy(path + 1, L"(unknown)");
 54.3436 +                            length = 10;
 54.3437 +                        }
 54.3438 +                        path[length]     = '"';
 54.3439 +                        path[length + 1] = '\0';
 54.3440 +
 54.3441 +                        #if (OVR_PTR_SIZE == 4)
 54.3442 +                            WriteReportLineF("0x%08x, 0x%08x 0x%08x %-24ls %ls\r\n", (uint32_t)mi.lpBaseOfDll, (uint32_t)mi.SizeOfImage, (uint32_t)mi.EntryPoint, name, path);
 54.3443 +                        #else
 54.3444 +                            WriteReportLineF("0x%016I64x 0x%016I64x 0x%016I64x %-24ls %ls\r\n", (uint64_t)mi.lpBaseOfDll, (uint64_t)mi.SizeOfImage, (uint64_t)mi.EntryPoint, name, path);
 54.3445 +                        #endif
 54.3446 +                    }
 54.3447 +                }
 54.3448 +            }
 54.3449 +        }
 54.3450 +
 54.3451 +        {
 54.3452 +            // Print a list of processes.
 54.3453 +            // DbgHelp.dll provides a SymEnumProcesses function, but it's available with DbgHelp.dll v6.2 which doesn't ship with Windows until Windows 8.
 54.3454 +            WriteReportLine("\r\nProcess list\r\n");
 54.3455 +            
 54.3456 +            if(reportPrivacyEnabled)
 54.3457 +                WriteReportLine("Disabled by report privacy settings\r\n");
 54.3458 +            else
 54.3459 +            {
 54.3460 +                HANDLE hProcessSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
 54.3461 +
 54.3462 +                if(hProcessSnapshot != INVALID_HANDLE_VALUE)
 54.3463 +                {
 54.3464 +                    PROCESSENTRY32W pe32;
 54.3465 +                    memset(&pe32, 0, sizeof(pe32));
 54.3466 +                    pe32.dwSize = sizeof(pe32);
 54.3467 +
 54.3468 +                    if(Process32FirstW(hProcessSnapshot, &pe32))
 54.3469 +                    {
 54.3470 +                        WriteReportLine("Process Id File\r\n");
 54.3471 +
 54.3472 +                        do {
 54.3473 +                            // Try to get the full path to the process, as pe32.szExeFile holds only the process file name.
 54.3474 +                            // This will typically fail with a privilege error unless this process has debug privileges: http://support.microsoft.com/kb/131065/en-us
 54.3475 +                            wchar_t filePathW[MAX_PATH];
 54.3476 +                            const wchar_t* pFilePathW = pe32.szExeFile;
 54.3477 +                            HANDLE hProcess = ::OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pe32.th32ProcessID); // With Windows Vista+ we can use PROCESS_QUERY_LIMITED_INFORMATION.
 54.3478 +                            if(hProcess)
 54.3479 +                            {
 54.3480 +                                if(GetProcessImageFileName(hProcess, filePathW, (DWORD)OVR_ARRAY_COUNT(filePathW)))
 54.3481 +                                    pFilePathW = filePathW;
 54.3482 +                            }
 54.3483 +
 54.3484 +                            WriteReportLineF("0x%08x %ls\r\n", pe32.th32ProcessID, pFilePathW);
 54.3485 +                        } while(Process32NextW(hProcessSnapshot, &pe32));
 54.3486 +                    }
 54.3487 +
 54.3488 +                    CloseHandle(hProcessSnapshot);
 54.3489 +                }
 54.3490 +                else
 54.3491 +                {
 54.3492 +                    WriteReportLine("Unable to read process list\r\n");
 54.3493 +                }
 54.3494 +            }
 54.3495 +        }
 54.3496 +
 54.3497 +    #elif defined(OVR_OS_APPLE)    
 54.3498 +
 54.3499 +        WriteReportLine("\r\nApp Info\r\n");
 54.3500 +    
 54.3501 +        // App path
 54.3502 +        const pid_t processId = getpid();
 54.3503 +        WriteReportLineF("Process id: ", "%lld (0x%llx)\r\n", (int64_t)processId, (int64_t)processId);
 54.3504 +
 54.3505 +        char appPath[PATH_MAX];
 54.3506 +        GetCurrentProcessFilePath(appPath, OVR_ARRAY_COUNT(appPath));
 54.3507 +        WriteReportLineF("Process path: %s\r\n", appPath);
 54.3508 +
 54.3509 +        #if (OVR_PTR_SIZE == 4)
 54.3510 +            WriteReportLine("App format: 32 bit\r\n");
 54.3511 +        #else
 54.3512 +            WriteReportLine("App format: 64 bit\r\n");
 54.3513 +        #endif
 54.3514 +            
 54.3515 +        // App version
 54.3516 +        // To do.
 54.3517 +
 54.3518 +        // System Info
 54.3519 +        WriteReportLine("\r\nSystem Info\r\n");
 54.3520 +
 54.3521 +        char osVersionName[256];
 54.3522 +        GetOSVersionName(osVersionName, OVR_ARRAY_COUNT(osVersionName));
 54.3523 +        WriteReportLineF("OS name: %s, %s\r\n", osVersionName, Is64BitOS() ? "64 bit" : "32 bit");
 54.3524 +
 54.3525 +        int     name[2];
 54.3526 +        int     intValue;
 54.3527 +        size_t  length;
 54.3528 +        char    tempBuffer[256];
 54.3529 +
 54.3530 +        name[0] = CTL_KERN;
 54.3531 +        name[1] = KERN_OSTYPE;
 54.3532 +        length = sizeof(tempBuffer);
 54.3533 +        tempBuffer[0] = 0;
 54.3534 +        if(sysctl(name, 2, tempBuffer, &length, nullptr, 0) == 0)
 54.3535 +        {
 54.3536 +            WriteReportLineF("KERN_OSTYPE: %s\r\n", tempBuffer);
 54.3537 +        }
 54.3538 +    
 54.3539 +        name[0] = CTL_KERN;
 54.3540 +        name[1] = KERN_OSREV;
 54.3541 +        length = sizeof(intValue);
 54.3542 +        intValue = 0;
 54.3543 +        if(sysctl(name, 2, &intValue, &length, nullptr, 0) == 0)
 54.3544 +        {
 54.3545 +            WriteReportLineF("KERN_OSREV: %d\r\n", intValue);
 54.3546 +        }
 54.3547 +    
 54.3548 +        name[0] = CTL_KERN;
 54.3549 +        name[1] = KERN_OSRELEASE;
 54.3550 +        length = sizeof(tempBuffer);
 54.3551 +        tempBuffer[0] = 0;
 54.3552 +        if(sysctl(name, 2, tempBuffer, &length, nullptr, 0) == 0)
 54.3553 +            WriteReportLineF("KERN_OSRELEASE: %s\r\n", tempBuffer);
 54.3554 +
 54.3555 +        name[0] = CTL_HW;
 54.3556 +        name[1] = HW_MACHINE;
 54.3557 +        length = sizeof(tempBuffer);
 54.3558 +        tempBuffer[0] = 0;
 54.3559 +        if(sysctl(name, 2, tempBuffer, &length, nullptr, 0) == 0)
 54.3560 +            WriteReportLineF("HW_MACHINE: %s\r\n", tempBuffer);
 54.3561 +
 54.3562 +        name[0] = CTL_HW;
 54.3563 +        name[1] = HW_MODEL;
 54.3564 +        length = sizeof(tempBuffer);
 54.3565 +        tempBuffer[0] = 0;
 54.3566 +        if(sysctl(name, 2, tempBuffer, &length, nullptr, 0) == 0)
 54.3567 +            WriteReportLineF("sHW_MODEL: %s\r\n", tempBuffer);
 54.3568 +
 54.3569 +        name[0] = CTL_HW;
 54.3570 +        name[1] = HW_NCPU;
 54.3571 +        length = sizeof(intValue);
 54.3572 +        intValue = 0;
 54.3573 +        if(sysctl(name, 2, &intValue, &length, nullptr, 0) == 0)
 54.3574 +            WriteReportLineF("HW_NCPU: %d\r\n", intValue);
 54.3575 +
 54.3576 +        length = sizeof(tempBuffer);
 54.3577 +        tempBuffer[0] = 0;
 54.3578 +        if(sysctlbyname("machdep.cpu.brand_string", &tempBuffer, &length, nullptr, 0) == 0)
 54.3579 +            WriteReportLineF("machdep.cpu.brand_string: %s\r\n", tempBuffer);
 54.3580 +
 54.3581 +        length = sizeof(tempBuffer);
 54.3582 +        tempBuffer[0] = 0;
 54.3583 +        if(sysctlbyname("hw.acpi.thermal.tz0.temperature", &tempBuffer, &length, nullptr, 0) == 0)
 54.3584 +            WriteReportLineF("hw.acpi.thermal.tz0.temperature: %s\r\n", tempBuffer);
 54.3585 +
 54.3586 +        host_basic_info_data_t hostinfo;
 54.3587 +        mach_msg_type_number_t count = HOST_BASIC_INFO_COUNT;
 54.3588 +        kern_return_t          kr = host_info(mach_host_self(), HOST_BASIC_INFO, (host_info_t)&hostinfo, &count);
 54.3589 +
 54.3590 +        if(kr == KERN_SUCCESS)
 54.3591 +        {
 54.3592 +            const uint64_t memoryMib = (uint64_t)hostinfo.max_mem / (1024 * 1024);
 54.3593 +            WriteReportLineF("System memory: %lld Mib (%.1f Gib)\r\n", memoryMib, (double)memoryMib / 1024);
 54.3594 +        }
 54.3595 +    
 54.3596 +        // Video card info
 54.3597 +        // To do.
 54.3598 +    
 54.3599 +        // Thread list
 54.3600 +        mach_port_t             taskSelf   = mach_task_self();
 54.3601 +        thread_act_port_array_t threadArray;
 54.3602 +        mach_msg_type_number_t  threadCount;
 54.3603 +        
 54.3604 +        kern_return_t result = task_threads(taskSelf, &threadArray, &threadCount);
 54.3605 +        
 54.3606 +        if(result == KERN_SUCCESS)
 54.3607 +        {
 54.3608 +            WriteReportLine("\r\nThread list\r\n");
 54.3609 +
 54.3610 +            for(mach_msg_type_number_t i = 0; i < threadCount; i++)
 54.3611 +            {
 54.3612 +                union TBIUnion{
 54.3613 +                    natural_t words[THREAD_INFO_MAX];
 54.3614 +                    thread_basic_info tbi;
 54.3615 +                };
 54.3616 +
 54.3617 +                TBIUnion    tbiUnion;
 54.3618 +                mach_port_t thread = threadArray[i];
 54.3619 +                pthread_t   pthread = pthread_from_mach_thread_np(thread); // We assume the thread was created through pthreads.
 54.3620 +
 54.3621 +                char threadState[32] = "unknown";
 54.3622 +                mach_msg_type_number_t threadInfoCount = THREAD_INFO_MAX;
 54.3623 +                result = thread_info(thread, THREAD_BASIC_INFO, (thread_info_t)&tbiUnion, &threadInfoCount);
 54.3624 +
 54.3625 +                if(result == KERN_SUCCESS)
 54.3626 +                {
 54.3627 +                    const char* state;
 54.3628 +                    
 54.3629 +                    switch (tbiUnion.tbi.run_state)
 54.3630 +                    {
 54.3631 +                        case TH_STATE_HALTED:          state = "halted";          break;
 54.3632 +                        case TH_STATE_RUNNING:         state = "running";         break;
 54.3633 +                        case TH_STATE_STOPPED:         state = "stopped";         break;
 54.3634 +                        case TH_STATE_UNINTERRUPTIBLE: state = "uninterruptible"; break;
 54.3635 +                        case TH_STATE_WAITING:         state = "waiting";         break;
 54.3636 +                        default:                       state = "<unknown>";       break;
 54.3637 +                    }
 54.3638 +                    
 54.3639 +                    OVR_snprintf(threadState, OVR_ARRAY_COUNT(threadState), "%s", state);
 54.3640 +                    if(tbiUnion.tbi.flags & TH_FLAGS_IDLE)
 54.3641 +                        OVR_strlcat(threadState, ", idle", sizeof(threadState));
 54.3642 +                    if(tbiUnion.tbi.flags & TH_FLAGS_SWAPPED)
 54.3643 +                        OVR_strlcat(threadState, ", swapped", sizeof(threadState));
 54.3644 +                }
 54.3645 +
 54.3646 +                thread_identifier_info threadIdentifierInfo; 
 54.3647 +                memset(&threadIdentifierInfo, 0, sizeof(threadIdentifierInfo));
 54.3648 +
 54.3649 +                mach_msg_type_number_t threadIdentifierInfoCount = THREAD_IDENTIFIER_INFO_COUNT;
 54.3650 +                thread_info(thread, THREAD_IDENTIFIER_INFO, (thread_info_t)&threadIdentifierInfo, &threadIdentifierInfoCount);
 54.3651 +
 54.3652 +                proc_threadinfo procThreadInfo; 
 54.3653 +                memset(&procThreadInfo, 0, sizeof(procThreadInfo));
 54.3654 +                result = proc_pidinfo(processId, PROC_PIDTHREADINFO, threadIdentifierInfo.thread_handle, &procThreadInfo, sizeof(procThreadInfo));
 54.3655 +                OVR_UNUSED(result);
 54.3656 +                
 54.3657 +                char buffer[256]; // Can't use scratchBuffer, because it's used by WriteThreadCallstack.
 54.3658 +                OVR_snprintf(buffer, OVR_ARRAY_COUNT(buffer), "state: %s, suspend count: %d, kernel priority: %d", threadState, (int)tbiUnion.tbi.suspend_count, (int)procThreadInfo.pth_curpri);
 54.3659 +                
 54.3660 +                bool threadIsExceptionThread = (thread == exceptionInfo.threadSysId);
 54.3661 +                if(threadIsExceptionThread)
 54.3662 +                    OVR_strlcat(buffer, ", exception thread", OVR_ARRAY_COUNT(buffer));
 54.3663 +                
 54.3664 +                WriteThreadCallstack(pthread, thread, buffer);
 54.3665 +            }
 54.3666 +            
 54.3667 +            vm_deallocate(taskSelf, (vm_address_t)threadArray, threadCount * sizeof(thread_act_t));
 54.3668 +        }
 54.3669 +    
 54.3670 +    
 54.3671 +        WriteReportLine("\r\nModule list\r\n");
 54.3672 +
 54.3673 +        const size_t mifCapacity  = 256;
 54.3674 +        const size_t mifAllocSize = mifCapacity * sizeof(ModuleInfo);
 54.3675 +        ModuleInfo* moduleInfoArray = (ModuleInfo*)SafeMMapAlloc(mifAllocSize);
 54.3676 +    
 54.3677 +        if(moduleInfoArray)
 54.3678 +        {
 54.3679 +            #if (OVR_PTR_SIZE == 4)
 54.3680 +                WriteReportLine("Base        Size       Name                     Path\r\n");
 54.3681 +            #else
 54.3682 +                WriteReportLine("Base                Size               Name                     Path\r\n");
 54.3683 +            #endif
 54.3684 +
 54.3685 +            size_t moduleCount = symbolLookup.GetModuleInfoArray(moduleInfoArray, mifCapacity);
 54.3686 +            if(moduleCount > mifCapacity)
 54.3687 +                moduleCount = mifCapacity;
 54.3688 +            
 54.3689 +            for(size_t i = 0; i < moduleCount; i++)
 54.3690 +            {
 54.3691 +                const ModuleInfo& mi = moduleInfoArray[i];
 54.3692 +                
 54.3693 +                #if (OVR_PTR_SIZE == 4)
 54.3694 +                    WriteReportLineF("0x%08x, 0x%08x %-24s %s\r\n", (uint32_t)mi.baseAddress, (uint32_t)mi.size, mi.name, mi.filePath);
 54.3695 +                #else
 54.3696 +                    WriteReportLineF("0x%016llx 0x%016llx %-24s %s\r\n", (uint64_t)mi.baseAddress, (uint64_t)mi.size, mi.name, mi.filePath);
 54.3697 +                #endif
 54.3698 +            }
 54.3699 +            
 54.3700 +            SafeMMapFree(moduleInfoArray, mifAllocSize);
 54.3701 +        }
 54.3702 +    
 54.3703 +    
 54.3704 +        WriteReportLine("\r\nProcess list\r\n");
 54.3705 +    
 54.3706 +        if(reportPrivacyEnabled)
 54.3707 +            WriteReportLine("Disabled by report privacy settings\r\n");
 54.3708 +        else
 54.3709 +        {
 54.3710 +            WriteReportLine("Process Id File\r\n");
 54.3711 +
 54.3712 +            pid_t pidArray[1024];
 54.3713 +            int   processCount = proc_listpids(PROC_ALL_PIDS, 0, pidArray, sizeof(pidArray)); // Important that we use sizeof not OVR_ARRAY_COUNT.
 54.3714 +            char  processFilePath[PATH_MAX];
 54.3715 +
 54.3716 +            for(int i = 0; i < processCount; i++)
 54.3717 +            {
 54.3718 +                if(proc_pidpath(pidArray[i], processFilePath, sizeof(processFilePath)) > 0)
 54.3719 +                    WriteReportLineF("%-10d %s\r\n", pidArray[i], processFilePath);
 54.3720 +            }
 54.3721 +            
 54.3722 +            if(!processCount)
 54.3723 +                WriteReportLine("Unable to read process list\r\n");
 54.3724 +        }
 54.3725 +
 54.3726 +	#elif defined(OVR_OS_UNIX)
 54.3727 +         Is64BitOS();
 54.3728 +         GetCurrentProcessFilePath(nullptr, 0);
 54.3729 +         GetFileNameFromPath(nullptr);
 54.3730 +         GetOSVersionName(nullptr, 0);
 54.3731 +
 54.3732 +    #endif // OVR_OS_MS
 54.3733 +
 54.3734 +    symbolLookup.Shutdown();
 54.3735 +
 54.3736 +    fclose(file);
 54.3737 +    file = nullptr;
 54.3738 +}
 54.3739 +
 54.3740 +
 54.3741 +void ExceptionHandler::WriteMiniDump()
 54.3742 +{
 54.3743 +    if(strstr(miniDumpFilePath, "%s")) // If the user-specified file path includes a date/time component...
 54.3744 +    {
 54.3745 +        char dateTimeBuffer[64];
 54.3746 +        FormatDateTime(dateTimeBuffer, OVR_ARRAY_COUNT(dateTimeBuffer), exceptionInfo.timeVal, true, true, false, true);
 54.3747 +        OVR_snprintf(minidumpFilePathActual, OVR_ARRAY_COUNT(minidumpFilePathActual), miniDumpFilePath, dateTimeBuffer);
 54.3748 +    }
 54.3749 +    else
 54.3750 +    {
 54.3751 +        OVR_strlcpy(minidumpFilePathActual, miniDumpFilePath, OVR_ARRAY_COUNT(minidumpFilePathActual));
 54.3752 +    }
 54.3753 +
 54.3754 +    #if defined(OVR_OS_WIN32) || defined(OVR_OS_WIN64) || (defined(OVR_OS_MS) && defined(OVR_OS_CONSOLE))
 54.3755 +        #if defined(OVR_OS_CONSOLE)
 54.3756 +            typedef BOOL (WINAPI * MINIDUMPWRITEDUMP)(HANDLE hProcess, DWORD ProcessId, HANDLE hFile, MINIDUMP_TYPE dumpType, CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, CONST PVOID                          CallbackParam);
 54.3757 +            HMODULE hModuleDbgHelp = LoadLibraryW(L"toolhelpx.dll");
 54.3758 +        #else
 54.3759 +            typedef BOOL (WINAPI * MINIDUMPWRITEDUMP)(HANDLE hProcess, DWORD ProcessId, HANDLE hFile, MINIDUMP_TYPE dumpType, CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam);
 54.3760 +            HMODULE hModuleDbgHelp = LoadLibraryW(L"DbgHelp.dll");
 54.3761 +        #endif
 54.3762 +
 54.3763 +        MINIDUMPWRITEDUMP pMiniDumpWriteDump = hModuleDbgHelp ? (MINIDUMPWRITEDUMP)(void*)GetProcAddress(hModuleDbgHelp, "MiniDumpWriteDump") : nullptr;
 54.3764 +
 54.3765 +        if(pMiniDumpWriteDump)
 54.3766 +        {
 54.3767 +            wchar_t miniDumpFilePathW[OVR_MAX_PATH];
 54.3768 +            OVR::UTF8Util::DecodeString(miniDumpFilePathW, minidumpFilePathActual, -1); // Problem: DecodeString provides no way to specify the destination capacity.
 54.3769 +
 54.3770 +            HANDLE hFile = CreateFileW(miniDumpFilePathW, GENERIC_READ | GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_FLAG_WRITE_THROUGH, 0);
 54.3771 +
 54.3772 +            if(hFile != INVALID_HANDLE_VALUE)
 54.3773 +            {
 54.3774 +                MINIDUMP_EXCEPTION_INFORMATION minidumpExceptionInfo = { ::GetCurrentThreadId(), pExceptionPointers, TRUE };
 54.3775 +
 54.3776 +                #if defined(OVR_OS_CONSOLE)
 54.3777 +                    BOOL result = pMiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hFile,
 54.3778 +                                                     (MINIDUMP_TYPE)miniDumpType, &exceptionInfo, 
 54.3779 +                                                     (CONST PMINIDUMP_USER_STREAM_INFORMATION)nullptr, nullptr);
 54.3780 +                #else
 54.3781 +                    BOOL result = pMiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hFile,
 54.3782 +                                                     (MINIDUMP_TYPE)miniDumpFlags, &minidumpExceptionInfo, 
 54.3783 +                                                     (CONST PMINIDUMP_USER_STREAM_INFORMATION)nullptr, (CONST PMINIDUMP_CALLBACK_INFORMATION)nullptr);
 54.3784 +                #endif
 54.3785 +
 54.3786 +                OVR_ASSERT_AND_UNUSED(result, result);
 54.3787 +                CloseHandle(hFile);
 54.3788 +                hFile = 0;
 54.3789 +            }
 54.3790 +            else
 54.3791 +            {
 54.3792 +                OVR_ASSERT(pMiniDumpWriteDump);  // OVR_FAIL_F(("ExceptionHandler::WriteMiniDump: Failed to create minidump file at %s", minidumpFilePathActual));
 54.3793 +            } 
 54.3794 +        }
 54.3795 +
 54.3796 +        FreeLibrary(hModuleDbgHelp);
 54.3797 +    #else
 54.3798 +        // Some platforms support various forms or exception reports and core dumps which are automatically generated upon us
 54.3799 +        // returning from our own exception handling. We might want to put something here if we are using a custom version of
 54.3800 +        // this, such as Google Breakpad.
 54.3801 +    #endif
 54.3802 +}
 54.3803 +
 54.3804 +
 54.3805 +void ExceptionHandler::SetExceptionListener(ExceptionListener* pExceptionListener, uintptr_t userValue)
 54.3806 +{
 54.3807 +    exceptionListener = pExceptionListener;
 54.3808 +    exceptionListenerUserValue = userValue;
 54.3809 +}
 54.3810 +
 54.3811 +
 54.3812 +void ExceptionHandler::SetAppDescription(const char* pAppDescription)
 54.3813 +{
 54.3814 +    appDescription = pAppDescription;
 54.3815 +}
 54.3816 +
 54.3817 +
 54.3818 +void ExceptionHandler::SetExceptionPaths(const char* exceptionReportPath, const char* exceptionMiniDumpFilePath)
 54.3819 +{
 54.3820 +    char tempPath[OVR_MAX_PATH];
 54.3821 +
 54.3822 +    if(exceptionReportPath)
 54.3823 +    {
 54.3824 +        if(OVR_stricmp(exceptionReportPath, "default") == 0)
 54.3825 +        {
 54.3826 +            GetUserDocumentsDirectory(tempPath, OVR_ARRAY_COUNT(tempPath));
 54.3827 +            OVR::OVR_strlcat(tempPath, "Exception Report (%s).txt", OVR_ARRAY_COUNT(tempPath));
 54.3828 +            exceptionReportPath = tempPath;
 54.3829 +        }
 54.3830 +
 54.3831 +        OVR_strlcpy(reportFilePath, exceptionReportPath, OVR_ARRAY_COUNT(reportFilePath));
 54.3832 +    }
 54.3833 +    else
 54.3834 +    {
 54.3835 +        reportFilePath[0] = '\0';
 54.3836 +    }
 54.3837 +    
 54.3838 +    if(exceptionMiniDumpFilePath)
 54.3839 +    {
 54.3840 +        if(OVR_stricmp(exceptionMiniDumpFilePath, "default") == 0)
 54.3841 +        {
 54.3842 +            GetUserDocumentsDirectory(tempPath, OVR_ARRAY_COUNT(tempPath));
 54.3843 +            OVR::OVR_strlcat(tempPath, "Exception Minidump (%s).mdmp", OVR_ARRAY_COUNT(tempPath));
 54.3844 +            exceptionMiniDumpFilePath = tempPath;
 54.3845 +        }
 54.3846 +
 54.3847 +        OVR_strlcpy(miniDumpFilePath, exceptionMiniDumpFilePath, OVR_ARRAY_COUNT(miniDumpFilePath));
 54.3848 +    }
 54.3849 +    else
 54.3850 +    {
 54.3851 +        miniDumpFilePath[0] = '\0';
 54.3852 +    }
 54.3853 +}
 54.3854 +
 54.3855 +
 54.3856 +void ExceptionHandler::SetCodeBaseDirectoryPaths(const char* codeBaseDirectoryPathArray[], size_t codeBaseDirectoryPathCount)
 54.3857 +{
 54.3858 +    for(size_t i = 0, iCount = OVR::Alg::Min<size_t>(codeBaseDirectoryPathCount, OVR_ARRAY_COUNT(codeBasePathArray)); i != iCount; ++i)
 54.3859 +    {
 54.3860 +        codeBasePathArray[i] = codeBaseDirectoryPathArray[i];
 54.3861 +    }
 54.3862 +}
 54.3863 +
 54.3864 +const char* ExceptionHandler::GetExceptionUIText(const char* exceptionReportPath)
 54.3865 +{
 54.3866 +	char* uiText = nullptr;
 54.3867 +    OVR::SysFile file(exceptionReportPath, SysFile::Open_Read, SysFile::Mode_ReadWrite);
 54.3868 +
 54.3869 +    if(file.IsValid())
 54.3870 +    {
 54.3871 +        size_t length = (size_t)file.GetLength();
 54.3872 +        uiText = (char*)OVR::SafeMMapAlloc(length + 1);
 54.3873 +
 54.3874 +        if(uiText)
 54.3875 +        {
 54.3876 +            file.Read((uint8_t*)uiText, (int)length);
 54.3877 +            uiText[length] = '\0';
 54.3878 +            file.Close();
 54.3879 +            
 54.3880 +            // Currently on Mac our message box implementation is unable to display arbitrarily large amounts of text.
 54.3881 +            // So we reduce its size to a more summary version before presenting.
 54.3882 +            #if defined(OVR_OS_MAC)
 54.3883 +                struct Find { static char* PreviousChar(char* p, char c){ while(*p != c) p--; return p; } }; // Assumes the given c is present prior to p.
 54.3884 +            
 54.3885 +                // Print that the full report is at <file path>
 54.3886 +                // Exception Info section
 54.3887 +                // Exception thread callstack.
 54.3888 +                char  empty[]               = "";
 54.3889 +                char* pExceptionInfoBegin   = strstr(uiText, "Exception Info") ? strstr(uiText, "Exception Info") : empty;
 54.3890 +                char* pExceptionInfoEnd     = (pExceptionInfoBegin == empty) ? (empty + 1) : strstr(uiText, "\r\n\r\n");
 54.3891 +                char* pExceptionThreadArea  = strstr(uiText, ", exception thread");
 54.3892 +                char* pExceptionThreadBegin = pExceptionThreadArea ? Find::PreviousChar(pExceptionThreadArea, '\n') + 1 : empty;
 54.3893 +                char* pExceptionThreadEnd   = (pExceptionThreadBegin == empty) ? (empty + 1) : strstr(pExceptionThreadArea, "\r\n\r\n");
 54.3894 +            
 54.3895 +                if(!pExceptionInfoEnd)
 54.3896 +                    pExceptionInfoEnd = pExceptionInfoBegin;
 54.3897 +                *pExceptionInfoEnd = '\0';
 54.3898 +
 54.3899 +                if(!pExceptionThreadEnd)
 54.3900 +                    pExceptionThreadEnd = pExceptionThreadBegin;
 54.3901 +                *pExceptionThreadEnd = '\0';
 54.3902 +            
 54.3903 +                size_t uiTextBriefLength = OVR_snprintf(nullptr, 0, "Full report:%s\n\nSummary report:\n%s\n\n%s", exceptionReportPath, pExceptionInfoBegin, pExceptionThreadBegin);
 54.3904 +                char* uiTextBrief = (char*)OVR::SafeMMapAlloc(uiTextBriefLength + 1);
 54.3905 +
 54.3906 +                if(uiTextBrief)
 54.3907 +                {
 54.3908 +                    OVR_snprintf(uiTextBrief, uiTextBriefLength + 1, "Full report:%s\n\nSummary report:\n%s\n\n%s", exceptionReportPath, pExceptionInfoBegin, pExceptionThreadBegin);
 54.3909 +                    OVR::SafeMMapFree(uiText, length);
 54.3910 +					uiText = uiTextBrief;
 54.3911 +                }
 54.3912 +           #endif
 54.3913 +        }
 54.3914 +    }
 54.3915 +
 54.3916 +    return uiText;
 54.3917 +}
 54.3918 +
 54.3919 +void ExceptionHandler::FreeExceptionUIText(const char* messageBoxText)
 54.3920 +{
 54.3921 +	OVR::SafeMMapFree(messageBoxText, OVR_strlen(messageBoxText));
 54.3922 +}
 54.3923 +
 54.3924 +
 54.3925 +} // namespace OVR
 54.3926 +
 54.3927 +
 54.3928 +OVR_RESTORE_MSVC_WARNING()
 54.3929 +
    55.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    55.2 +++ b/LibOVR/Src/Kernel/OVR_DebugHelp.h	Wed Jan 14 06:51:16 2015 +0200
    55.3 @@ -0,0 +1,461 @@
    55.4 +/************************************************************************************
    55.5 +
    55.6 +Filename    :   OVR_DebugHelp.h
    55.7 +Content     :   Platform-independent exception handling interface
    55.8 +Created     :   October 6, 2014
    55.9 +
   55.10 +Copyright   :   Copyright 2014 Oculus VR, LLC. All Rights reserved.
   55.11 +
   55.12 +Licensed under the Apache License, Version 2.0 (the "License");
   55.13 +you may not use this file except in compliance with the License.
   55.14 +You may obtain a copy of the License at
   55.15 +
   55.16 +http://www.apache.org/licenses/LICENSE-2.0
   55.17 +
   55.18 +Unless required by applicable law or agreed to in writing, software
   55.19 +distributed under the License is distributed on an "AS IS" BASIS,
   55.20 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   55.21 +See the License for the specific language governing permissions and
   55.22 +limitations under the License.
   55.23 +
   55.24 +************************************************************************************/
   55.25 +
   55.26 +#ifndef OVR_ExceptionHandler_h
   55.27 +#define OVR_ExceptionHandler_h
   55.28 +
   55.29 +
   55.30 +#include "OVR_Types.h"
   55.31 +#include "OVR_String.h"
   55.32 +#include "OVR_Threads.h"
   55.33 +#include "OVR_Atomic.h"
   55.34 +#include "OVR_Nullptr.h"
   55.35 +#include <stdio.h>
   55.36 +#include <time.h>
   55.37 +
   55.38 +#if defined(OVR_OS_WIN32) || defined(OVR_OS_WIN64)
   55.39 +    #include <Windows.h>
   55.40 +
   55.41 +#elif defined(OVR_OS_APPLE)
   55.42 +    #include <pthread.h>
   55.43 +    #include <mach/thread_status.h>
   55.44 +    #include <mach/mach_types.h>
   55.45 +
   55.46 +    extern "C" void* MachHandlerThreadFunctionStatic(void*);
   55.47 +    extern "C" int   catch_mach_exception_raise_state_identity_OVR(mach_port_t, mach_port_t, mach_port_t, exception_type_t, mach_exception_data_type_t*,
   55.48 +                                       mach_msg_type_number_t, int*, thread_state_t, mach_msg_type_number_t, thread_state_t, mach_msg_type_number_t*);
   55.49 +#elif defined(OVR_OS_LINUX)
   55.50 +    #include <pthread.h>
   55.51 +#endif
   55.52 +
   55.53 +
   55.54 +OVR_DISABLE_MSVC_WARNING(4351) // new behavior: elements of array will be default initialized
   55.55 +
   55.56 +
   55.57 +namespace OVR { 
   55.58 +
   55.59 +    // Thread identifiers
   55.60 +    //typedef void*     ThreadHandle;  // Already defined by OVR Threads. Same as Windows thread handle, Unix pthread_t.
   55.61 +    //typedef void*     ThreadId;      // Already defined by OVR Threads. Used by Windows as DWORD thread id, by Unix as pthread_t. 
   55.62 +    typedef uintptr_t   ThreadSysId;   // System thread identifier. Used by Windows the same as ThreadId (DWORD), thread_act_t on Mac/BSD, lwp id on Linux.
   55.63 +
   55.64 +    // Thread constants
   55.65 +    // To do: Move to OVR Threads
   55.66 +    #define OVR_THREADHANDLE_INVALID ((ThreadHandle*)nullptr)
   55.67 +    #define OVR_THREADID_INVALID     ((ThreadId*)nullptr)
   55.68 +    #define OVR_THREADSYSID_INVALID  ((uintptr_t)0)
   55.69 +
   55.70 +    OVR::ThreadSysId  ConvertThreadHandleToThreadSysId(OVR::ThreadHandle threadHandle);
   55.71 +    OVR::ThreadHandle ConvertThreadSysIdToThreadHandle(OVR::ThreadSysId threadSysId);   // The returned handle must be freed with FreeThreadHandle.
   55.72 +    void              FreeThreadHandle(OVR::ThreadHandle threadHandle);                 // Frees the handle returned by ConvertThreadSysIdToThreadHandle.
   55.73 +    OVR::ThreadSysId  GetCurrentThreadSysId();
   55.74 +
   55.75 +    // CPUContext
   55.76 +    #if defined(OVR_OS_MS)
   55.77 +        typedef CONTEXT CPUContext; 
   55.78 +    #elif defined(OVR_OS_MAC)
   55.79 +        struct CPUContext
   55.80 +        {
   55.81 +            x86_thread_state_t  threadState; // This works for both x86 and x64.
   55.82 +            x86_float_state_t   floatState;
   55.83 +            x86_debug_state_t   debugState;
   55.84 +            x86_avx_state_t     avxState;
   55.85 +            x86_exception_state exceptionState;
   55.86 +            
   55.87 +            CPUContext() { memset(this, 0, sizeof(CPUContext)); }
   55.88 +        };
   55.89 +    #elif defined(OVR_OS_LINUX)
   55.90 +        typedef int CPUContext; // To do.
   55.91 +    #endif
   55.92 +
   55.93 +
   55.94 +    // Tells if the current process appears to be running under a debugger. Does not attempt to 
   55.95 +    // detect the case of sleath debuggers (malware-related for example).
   55.96 +    bool OVRIsDebuggerPresent();
   55.97 +
   55.98 +    // Exits the process with the given exit code.
   55.99 +    #if !defined(OVR_NORETURN)
  55.100 +        #if defined(OVR_CC_MSVC)
  55.101 +            #define OVR_NORETURN __declspec(noreturn)
  55.102 +        #else
  55.103 +            #define OVR_NORETURN __attribute__((noreturn))
  55.104 +        #endif
  55.105 +    #endif
  55.106 +    OVR_NORETURN void ExitProcess(intptr_t processReturnValue);
  55.107 +
  55.108 +    // Returns the instruction pointer of the caller for the position right after the call.
  55.109 +    OVR_NO_INLINE void GetInstructionPointer(void*& pInstruction);
  55.110 +
  55.111 +    // Returns the stack base and limit addresses for the given thread, or for the current thread if the threadHandle is default.
  55.112 +    // The stack limit is a value less than the stack base on most platforms, as stacks usually grow downward.
  55.113 +    // Some platforms (e.g. Microsoft) have dynamically resizing stacks, in which case the stack limit reflects the current limit.
  55.114 +    void GetThreadStackBounds(void*& pStackBase, void*& pStackLimit, ThreadHandle threadHandle = OVR_THREADHANDLE_INVALID);
  55.115 +
  55.116 +
  55.117 +    // Equates to VirtualAlloc/VirtualFree on Windows, mmap/munmap on Unix.
  55.118 +    // These are useful for when you need system-supplied memory pages. 
  55.119 +    // These are also useful for when you need to allocate memory in a way 
  55.120 +    // that doesn't affect the application heap.
  55.121 +    void* SafeMMapAlloc(size_t size);
  55.122 +    void  SafeMMapFree(const void* memory, size_t size);
  55.123 +
  55.124 +
  55.125 +    // OVR_MAX_PATH
  55.126 +    // Max file path length (for most uses).
  55.127 +    // To do: move this to OVR_File.
  55.128 +    #if defined(OVR_OS_MS)         // http://msdn.microsoft.com/en-us/library/windows/desktop/aa365247%28v=vs.85%29.aspx
  55.129 +        #define OVR_MAX_PATH  260  // Windows can use paths longer than this in some cases (network paths, UNC paths).
  55.130 +    #else
  55.131 +        #define OVR_MAX_PATH 1024  // This isn't a strict limit on all Unix-based platforms.
  55.132 +    #endif
  55.133 +
  55.134 +
  55.135 +    // ModuleHandle
  55.136 +    #if defined(OVR_OS_MS)
  55.137 +        typedef void* ModuleHandle;  // from LoadLibrary()
  55.138 +    #elif defined(OVR_OS_APPLE) || defined(OVR_OS_UNIX)
  55.139 +        typedef void* ModuleHandle;  // from dlopen()
  55.140 +    #endif
  55.141 +
  55.142 +    #define OVR_MODULEHANDLE_INVALID ((ModuleHandle*)nullptr)
  55.143 +
  55.144 +
  55.145 +
  55.146 +    // Module info constants
  55.147 +    static const ModuleHandle kMIHandleInvalid          = OVR_MODULEHANDLE_INVALID;
  55.148 +    static const uint64_t     kMIAddressInvalid         = 0xffffffffffffffffull;
  55.149 +    static const uint64_t     kMISizeInvalid            = 0xffffffffffffffffull;
  55.150 +    static const int32_t      kMILineNumberInvalid      = -1;
  55.151 +    static const int32_t      kMIFunctionOffsetInvalid  = -1;
  55.152 +    static const uint64_t     kMIBaseAddressInvalid     = 0xffffffffffffffffull;
  55.153 +    static const uint64_t     kMIBaseAddressUnspecified = 0xffffffffffffffffull;
  55.154 +
  55.155 +    struct ModuleInfo
  55.156 +    {
  55.157 +        ModuleHandle handle;
  55.158 +        uint64_t     baseAddress;           // The actual runtime base address of the module. May be different from the base address specified in the debug symbol file.
  55.159 +        uint64_t     size;
  55.160 +        char         filePath[OVR_MAX_PATH];
  55.161 +        char         name[32];
  55.162 +        char         type[8];               // Unix-specific. e.g. __TEXT
  55.163 +        char         permissions[8];        // Unix specific. e.g. "drwxr-xr-x"
  55.164 +
  55.165 +        ModuleInfo() : handle(kMIHandleInvalid), baseAddress(kMIBaseAddressInvalid), size(0), filePath(), name(){}
  55.166 +    };
  55.167 +
  55.168 +
  55.169 +    // Refers to symbol info for an instruction address. 
  55.170 +    // Info includes function name, source code file/line, and source code itself.
  55.171 +    struct SymbolInfo
  55.172 +    {
  55.173 +        uint64_t          address;
  55.174 +        uint64_t          size;
  55.175 +        const ModuleInfo* pModuleInfo;
  55.176 +        char              filePath[OVR_MAX_PATH];
  55.177 +        int32_t           fileLineNumber;
  55.178 +        char              function[128];            // This is a fixed size because we need to use it during application exceptions.
  55.179 +        int32_t           functionOffset;
  55.180 +        char              sourceCode[1024];         // This is a string representing the code itself and not a file path to the code.
  55.181 +
  55.182 +        SymbolInfo() : address(kMIAddressInvalid), size(kMISizeInvalid), pModuleInfo(nullptr), filePath(), 
  55.183 +                        fileLineNumber(kMILineNumberInvalid), function(), functionOffset(kMIFunctionOffsetInvalid), sourceCode() {}
  55.184 +    };
  55.185 +
  55.186 +
  55.187 +    // Implements support for reading thread lists, module lists, backtraces, and backtrace symbols.
  55.188 +    class SymbolLookup
  55.189 +    {
  55.190 +    public:
  55.191 +        SymbolLookup();
  55.192 +       ~SymbolLookup();
  55.193 +
  55.194 +        void AddSourceCodeDirectory(const char* pDirectory);
  55.195 +
  55.196 +        bool Initialize();
  55.197 +        void Shutdown();
  55.198 +
  55.199 +        // Should be disabled when within an exception handler.
  55.200 +        void EnableMemoryAllocation(bool enabled);
  55.201 +        
  55.202 +        // Retrieves the backtrace (call stack) of the given thread. There may be some per-platform restrictions on this.
  55.203 +        // Returns the number written, which will be <= addressArrayCapacity.
  55.204 +        // This may not work on some platforms unless stack frames are enabled.
  55.205 +        // For Microsoft platforms the platformThreadContext is CONTEXT*.
  55.206 +        // For Apple platforms the platformThreadContext is x86_thread_state_t* or arm_thread_state_t*.
  55.207 +        // If threadSysIdHelp is non-zero, it may be used by the implementation to help produce a better backtrace.
  55.208 +        size_t GetBacktrace(void* addressArray[], size_t addressArrayCapacity, size_t skipCount = 0, void* platformThreadContext = nullptr, OVR::ThreadSysId threadSysIdHelp = OVR_THREADSYSID_INVALID);
  55.209 +
  55.210 +        // Retrieves the backtrace for the given ThreadHandle.
  55.211 +        // Returns the number written, which will be <= addressArrayCapacity.
  55.212 +        size_t GetBacktraceFromThreadHandle(void* addressArray[], size_t addressArrayCapacity, size_t skipCount = 0, OVR::ThreadHandle threadHandle = OVR_THREADHANDLE_INVALID);
  55.213 +
  55.214 +        // Retrieves the backtrace for the given ThreadSysId.
  55.215 +        // Returns the number written, which will be <= addressArrayCapacity.
  55.216 +        size_t GetBacktraceFromThreadSysId(void* addressArray[], size_t addressArrayCapacity, size_t skipCount = 0, OVR::ThreadSysId threadSysId = OVR_THREADSYSID_INVALID);
  55.217 +
  55.218 +        // Gets a list of the modules (e.g. DLLs) present in the current process.
  55.219 +        // Writes as many ModuleInfos as possible to pModuleInfoArray.
  55.220 +        // Returns the required count of ModuleInfos, which will be > moduleInfoArrayCapacity if the capacity needs to be larger.
  55.221 +        size_t GetModuleInfoArray(ModuleInfo* pModuleInfoArray, size_t moduleInfoArrayCapacity);
  55.222 +
  55.223 +        // Retrieves a list of the current threads. Unless the process is paused the list is volatile.
  55.224 +        // Returns the required capacity, which may be larger than threadArrayCapacity.
  55.225 +        // Either array can be NULL to specify that it's not written to.
  55.226 +        // For Windows the caller needs to CloseHandle the returned ThreadHandles. This can be done by calling DoneThreadList.
  55.227 +        size_t GetThreadList(ThreadHandle* threadHandleArray, ThreadSysId* threadSysIdArray, size_t threadArrayCapacity);
  55.228 +
  55.229 +        // Frees any references to thread handles or ids returned by GetThreadList;
  55.230 +        void DoneThreadList(ThreadHandle* threadHandleArray, ThreadSysId* threadSysIdArray, size_t threadArrayCount);
  55.231 +
  55.232 +        // Writes a given thread's callstack with symbols to the given output.
  55.233 +        // It may not be safe to call this from an exception handler, as sOutput allocates memory.
  55.234 +        bool ReportThreadCallstack(OVR::String& sOutput, size_t skipCount = 0, ThreadSysId threadSysId = OVR_THREADSYSID_INVALID);
  55.235 +
  55.236 +        // Writes all thread's callstacks with symbols to the given output.
  55.237 +        // It may not be safe to call this from an exception handler, as sOutput allocates memory.
  55.238 +        bool ReportThreadCallstacks(OVR::String& sOutput, size_t skipCount = 0);
  55.239 +
  55.240 +        // Retrieves symbol info for the given address. 
  55.241 +        bool LookupSymbol(uint64_t address, SymbolInfo& symbolInfo);
  55.242 +        bool LookupSymbols(uint64_t* addressArray, SymbolInfo* pSymbolInfoArray, size_t arraySize);
  55.243 +
  55.244 +        const ModuleInfo* GetModuleInfoForAddress(uint64_t address);  // The returned ModuleInfo points to an internal structure.
  55.245 +
  55.246 +    protected:
  55.247 +        bool RefreshModuleList();
  55.248 +
  55.249 +    protected:
  55.250 +        bool       initialized;
  55.251 +        bool       allowMemoryAllocation;   // True by default. If true then we allow allocating memory (and as a result provide less information). This is useful for when in an exception handler.
  55.252 +        bool       moduleListUpdated;
  55.253 +        ModuleInfo moduleInfoArray[96];     // Cached list of modules we use. This is a fixed size because we need to use it during application exceptions.
  55.254 +        size_t     moduleInfoArraySize;
  55.255 +    };
  55.256 +
  55.257 +
  55.258 +
  55.259 +    // ExceptionInfo
  55.260 +    // We need to be careful to avoid data types that can allocate memory while we are 
  55.261 +    // handling an exception, as the memory system may be corrupted at that point in time.
  55.262 +    struct ExceptionInfo
  55.263 +    {
  55.264 +        tm            time;                             // GM time.
  55.265 +        time_t        timeVal;                          // GM time_t (seconds since 1970).
  55.266 +        void*         backtrace[64];
  55.267 +        size_t        backtraceCount;
  55.268 +        ThreadHandle  threadHandle;                     // 
  55.269 +        ThreadSysId   threadSysId;                      // 
  55.270 +        char          threadName[32];                   // Cannot be an allocating String object.
  55.271 +        void*         pExceptionInstructionAddress;
  55.272 +        void*         pExceptionMemoryAddress;
  55.273 +        CPUContext    cpuContext;
  55.274 +        char          exceptionDescription[1024];       // Cannot be an allocating String object.
  55.275 +        SymbolInfo    symbolInfo;                       // SymbolInfo for the exception location.
  55.276 +
  55.277 +        #if defined(OVR_OS_MS)
  55.278 +            EXCEPTION_RECORD exceptionRecord;           // This is a Windows SDK struct.
  55.279 +        #elif defined(OVR_OS_APPLE)
  55.280 +            uint64_t         exceptionType;             // e.g. EXC_BAD_INSTRUCTION, EXC_BAD_ACCESS, etc.
  55.281 +            uint32_t         cpuExceptionId;            // The x86/x64 CPU trap id.
  55.282 +            uint32_t         cpuExceptionIdError;       // The x86/x64 CPU trap id extra info.
  55.283 +            int64_t          machExceptionDetail[4];    // Kernel exception code info.
  55.284 +            int              machExceptionDetailCount;  // Count of valid entries.
  55.285 +        #endif
  55.286 +
  55.287 +        ExceptionInfo();
  55.288 +    };
  55.289 +
  55.290 +
  55.291 +    // Implments support for asynchronous exception handling and basic exception report generation.
  55.292 +    // If you are implementing exception handling for a commercial application and want auto-uploading
  55.293 +    // functionality you may want to consider using something like Google Breakpad. This exception handler
  55.294 +    // is for in-application debug/diagnostic services, though it can write a report that has similar
  55.295 +    // information to Breakpad or OS-provided reports such as Apple .crash files.
  55.296 +    //
  55.297 +    // Example usage:
  55.298 +    //     ExceptionHandler exceptionHandler;
  55.299 +    //
  55.300 +    //     int main(int, char**)
  55.301 +    //     {
  55.302 +    //          exceptionHandler.Enable(true);
  55.303 +    //          exceptionHandler.SetExceptionListener(pSomeListener, 0);  // Optional listener hook.
  55.304 +    //     }
  55.305 +    // 
  55.306 +    class ExceptionHandler
  55.307 +    {
  55.308 +    public:
  55.309 +        ExceptionHandler();
  55.310 +       ~ExceptionHandler();
  55.311 +
  55.312 +        bool Enable(bool enable);
  55.313 +        
  55.314 +        // Some report info can be considered private information of the user, such as the current process list,
  55.315 +        // computer name, IP address or other identifying info, etc. We should not report this information for
  55.316 +        // external users unless they agree to this.
  55.317 +        void EnableReportPrivacy(bool enable);
  55.318 +
  55.319 +        struct ExceptionListener
  55.320 +        {
  55.321 +            virtual ~ExceptionListener(){}
  55.322 +            virtual int HandleException(uintptr_t userValue, ExceptionHandler* pExceptionHandler, ExceptionInfo* pExceptionInfo, const char* reportFilePath) = 0;
  55.323 +        };
  55.324 +
  55.325 +        void SetExceptionListener(ExceptionListener* pExceptionListener, uintptr_t userValue);
  55.326 +
  55.327 +        // What we do after handling the exception.
  55.328 +        enum ExceptionResponse
  55.329 +        {
  55.330 +            kERContinue,    // Continue execution. Will result in the exception being re-generated unless the application has fixed the cause. Similar to Windows EXCEPTION_CONTINUE_EXECUTION.
  55.331 +            kERHandle,      // Causes the OS to handle the exception as it normally would. Similar to Windows EXCEPTION_EXECUTE_HANDLER.
  55.332 +            kERTerminate,   // Exit the application.
  55.333 +            kERThrow,       // Re-throw the exception. Other handlers may catch it. Similar to Windows EXCEPTION_CONTINUE_SEARCH.
  55.334 +            kERDefault      // Usually set to kERTerminate.
  55.335 +        };
  55.336 +
  55.337 +        void SetExceptionResponse(ExceptionResponse er)
  55.338 +            { exceptionResponse = er; }
  55.339 +
  55.340 +        // Allws you to add an arbitrary description of the current application, which will be added to exception reports.
  55.341 +        void SetAppDescription(const char* appDescription);
  55.342 +
  55.343 +        // If the report path has a "%s" in its name, then assume the path is a sprintf format and write it 
  55.344 +        // with the %s specified as a date/time string.
  55.345 +        // The report path can be "default" to signify that you want to use the default user location.
  55.346 +        // Example usage:
  55.347 +        //     handler.SetExceptionPaths("/Users/Current/Exceptions/Exception %s.txt");
  55.348 +        void SetExceptionPaths(const char* exceptionReportPath, const char* exceptionMinidumpPath = nullptr);
  55.349 +
  55.350 +        // Allows you to specify base directories for code paths, which can be used to associate exception addresses to lines 
  55.351 +        // of code as opposed to just file names and line numbers, or function names plus binary offsets.
  55.352 +        void SetCodeBaseDirectoryPaths(const char* codeBaseDirectoryPathArray[], size_t codeBaseDirectoryPathCount);
  55.353 +
  55.354 +		// Given an exception report at a given file path, returns a string suitable for displaying in a message
  55.355 +		// box or similar user interface during the handling of an exception. The returned string must be passed
  55.356 +		// to FreeMessageBoxText when complete.
  55.357 +		static const char* GetExceptionUIText(const char* exceptionReportPath);
  55.358 +		static void FreeExceptionUIText(const char* messageBoxText);
  55.359 +
  55.360 +    protected:
  55.361 +        void WriteExceptionDescription();
  55.362 +        void WriteReport();
  55.363 +        void WriteReportLine(const char* pLine);
  55.364 +        void WriteReportLineF(const char* format, ...);
  55.365 +        void WriteThreadCallstack(ThreadHandle threadHandle, ThreadSysId threadSysId, const char* additionalInfo);
  55.366 +        void WriteMiniDump();
  55.367 +
  55.368 +        // Runtime constants
  55.369 +        bool               enabled;
  55.370 +        bool               reportPrivacyEnabled;        // Defaults to true.
  55.371 +        ExceptionResponse  exceptionResponse;           // Defaults to kERHandle
  55.372 +        ExceptionListener* exceptionListener;
  55.373 +        uintptr_t          exceptionListenerUserValue;
  55.374 +        String             appDescription;
  55.375 +        String             codeBasePathArray[6];        // 6 is arbitrary.
  55.376 +        char               reportFilePath[OVR_MAX_PATH];// May be an encoded path, in that it has "%s" in it or is named "default". See reporFiletPathActual for the runtime actual report path.
  55.377 +        int                miniDumpFlags;
  55.378 +        char               miniDumpFilePath[OVR_MAX_PATH];
  55.379 +        FILE*              file;                        // Can/should we use OVR Files for this?
  55.380 +        char               scratchBuffer[4096];
  55.381 +        SymbolLookup       symbolLookup;
  55.382 +
  55.383 +        // Runtime variables
  55.384 +        bool                     exceptionOccurred;
  55.385 +        OVR::AtomicInt<uint32_t> handlingBusy;
  55.386 +        char                     reportFilePathActual[OVR_MAX_PATH];
  55.387 +        char                     minidumpFilePathActual[OVR_MAX_PATH];
  55.388 +        int                      terminateReturnValue;
  55.389 +        ExceptionInfo            exceptionInfo;
  55.390 +
  55.391 +        #if defined(OVR_OS_MS)
  55.392 +            void*                        vectoredHandle;
  55.393 +            LPTOP_LEVEL_EXCEPTION_FILTER previousFilter;
  55.394 +            LPEXCEPTION_POINTERS         pExceptionPointers;
  55.395 +
  55.396 +            friend LONG WINAPI Win32ExceptionFilter(LPEXCEPTION_POINTERS pExceptionPointers);
  55.397 +            LONG ExceptionFilter(LPEXCEPTION_POINTERS pExceptionPointers);
  55.398 +
  55.399 +        #elif defined(OVR_OS_APPLE)
  55.400 +            struct SavedExceptionPorts
  55.401 +            {
  55.402 +                SavedExceptionPorts() : count(0) { memset(this, 0, sizeof(SavedExceptionPorts)); }
  55.403 +
  55.404 +                mach_msg_type_number_t count;
  55.405 +                exception_mask_t       masks[6];
  55.406 +                exception_handler_t    ports[6];
  55.407 +                exception_behavior_t   behaviors[6];
  55.408 +                thread_state_flavor_t  flavors[6];
  55.409 +            };
  55.410 +
  55.411 +            friend void* ::MachHandlerThreadFunctionStatic(void*);
  55.412 +            friend int ::catch_mach_exception_raise_state_identity_OVR(mach_port_t, mach_port_t, mach_port_t, exception_type_t,
  55.413 +                                        mach_exception_data_type_t*, mach_msg_type_number_t, int*, thread_state_t,
  55.414 +                                        mach_msg_type_number_t, thread_state_t, mach_msg_type_number_t*);
  55.415 +        
  55.416 +            bool          InitMachExceptionHandler();
  55.417 +            void          ShutdownMachExceptionHandler();
  55.418 +            void*         MachHandlerThreadFunction();
  55.419 +            kern_return_t HandleMachException(mach_port_t port, mach_port_t thread, mach_port_t task, exception_type_t exceptionType,
  55.420 +                                              mach_exception_data_type_t* pExceptionDetail, mach_msg_type_number_t exceptionDetailCount, 
  55.421 +                                              int* pFlavor, thread_state_t pOldState, mach_msg_type_number_t oldStateCount, thread_state_t pNewState,
  55.422 +                                              mach_msg_type_number_t* pNewStateCount);
  55.423 +            kern_return_t ForwardMachException(mach_port_t thread, mach_port_t task, exception_type_t exceptionType,
  55.424 +                                               mach_exception_data_t pExceptionDetail, mach_msg_type_number_t exceptionDetailCount);
  55.425 +
  55.426 +            bool                machHandlerInitialized;
  55.427 +            mach_port_t         machExceptionPort;
  55.428 +            SavedExceptionPorts machExceptionPortsSaved;
  55.429 +            volatile bool       machThreadShouldContinue;
  55.430 +            volatile bool       machThreadExecuting;
  55.431 +            pthread_t           machThread;
  55.432 +
  55.433 +        #elif defined(OVR_OS_LINUX)
  55.434 +            // To do.
  55.435 +        #endif
  55.436 +    };
  55.437 +
  55.438 +
  55.439 +    // Identifies basic exception types for the CreateException function.
  55.440 +    enum CreateExceptionType
  55.441 +    {
  55.442 +        kCETAccessViolation,      // Read or write to inaccessable memory.
  55.443 +        kCETAlignment,            // Misaligned read or write.
  55.444 +        kCETDivideByZero,         // Integer divide by zero.
  55.445 +        kCETFPU,                  // Floating point / VPU exception.
  55.446 +        kCETIllegalInstruction,   // Illegal opcode.
  55.447 +        kCETStackCorruption,      // Stack frame was corrupted.
  55.448 +        kCETStackOverflow,        // Stack ran out of space, often due to infinite recursion.
  55.449 +        kCETTrap                  // System/OS trap (system call).
  55.450 +    };
  55.451 +
  55.452 +
  55.453 +    // Creates an exception of the given type, primarily for testing.
  55.454 +    void CreateException(CreateExceptionType exceptionType);
  55.455 +
  55.456 +
  55.457 +
  55.458 +} // namespace OVR
  55.459 +
  55.460 +
  55.461 +OVR_RESTORE_MSVC_WARNING()
  55.462 +
  55.463 +
  55.464 +#endif // Header include guard
    56.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    56.2 +++ b/LibOVR/Src/Kernel/OVR_Delegates.h	Wed Jan 14 06:51:16 2015 +0200
    56.3 @@ -0,0 +1,541 @@
    56.4 +/************************************************************************************
    56.5 +
    56.6 +Filename    :   OVR_Delegates.h
    56.7 +Content     :   C++ Delegates
    56.8 +Created     :   June 15, 2014
    56.9 +Authors     :   Chris Taylor
   56.10 +
   56.11 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   56.12 +
   56.13 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License");
   56.14 +you may not use the Oculus VR Rift SDK except in compliance with the License,
   56.15 +which is provided at the time of installation or download, or which
   56.16 +otherwise accompanies this software in either electronic or hard copy form.
   56.17 +
   56.18 +You may obtain a copy of the License at
   56.19 +
   56.20 +http://www.oculusvr.com/licenses/LICENSE-3.2
   56.21 +
   56.22 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK
   56.23 +distributed under the License is distributed on an "AS IS" BASIS,
   56.24 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   56.25 +See the License for the specific language governing permissions and
   56.26 +limitations under the License.
   56.27 +
   56.28 +************************************************************************************/
   56.29 +
   56.30 +/*
   56.31 +	Based on The Impossibly Fast C++ Delegates by Sergey Ryazanov from
   56.32 +	http://www.codeproject.com/KB/cpp/ImpossiblyFastCppDelegate.aspx (2005)
   56.33 +*/
   56.34 +
   56.35 +/*
   56.36 +	Usage:
   56.37 +
   56.38 +	Declare a delegate with a void (int) signature, also known as a
   56.39 +	function that returns void and has one parameter that is an int:
   56.40 +		typedef Delegate1<void, int> MyDelegate;
   56.41 +		MyDelegate d;
   56.42 +
   56.43 +	Point the delegate to a member function:
   56.44 +		d.SetMember<A, &A::TestFunctionA>(&a);
   56.45 +		d = MyDelegate::FromMember<A, &A::TestFunctionA>(&a);
   56.46 +
   56.47 +	Point the delegate to a const member function:
   56.48 +		d.SetConstMember<C, &C::TestFunctionA>(&c);
   56.49 +		d = MyDelegate::FromConstMember<C, &C::TestFunctionA>(&c);
   56.50 +
   56.51 +	Point the delegate to a free function:
   56.52 +		d.SetFree<&FreeFunctionX>();
   56.53 +		d = MyDelegate::FromFree<&FreeFunctionX>();
   56.54 +
   56.55 +	Invoke the function via the delegate (works for all 3 cases):
   56.56 +		d(1000);
   56.57 +
   56.58 +	By default the delegates are uninitialized.
   56.59 +	To clear an array of delegates quickly just zero the memory.
   56.60 +
   56.61 +	This implementation is nicer than FastDelegates in my opinion
   56.62 +	because it is simple and easy to read.  It is a little slower
   56.63 +	for virtual functions, but the size of the delegate is small,
   56.64 +	and it will only get better as compilers improve.
   56.65 +*/
   56.66 +
   56.67 +#ifndef OVR_Delegates_h
   56.68 +#define OVR_Delegates_h
   56.69 +
   56.70 +#include "OVR_Types.h"
   56.71 +
   56.72 +namespace OVR {
   56.73 +
   56.74 +
   56.75 +template <class ret_type>
   56.76 +class Delegate0
   56.77 +{
   56.78 +	typedef ret_type (*StubPointer)(void *);
   56.79 +	typedef Delegate0<ret_type> this_type;
   56.80 +
   56.81 +	void *_object;
   56.82 +	StubPointer _stub;
   56.83 +
   56.84 +	OVR_FORCE_INLINE Delegate0(void *object, StubPointer stub)
   56.85 +	{
   56.86 +		_object = object;
   56.87 +		_stub = stub;
   56.88 +	}
   56.89 +
   56.90 +	// Stubs
   56.91 +
   56.92 +	template <ret_type (*F)()>
   56.93 +	static OVR_FORCE_INLINE ret_type FreeStub(void * /*object*/)
   56.94 +	{
   56.95 +		return (F)();
   56.96 +	}
   56.97 +
   56.98 +	template <class T, ret_type (T::*F)()>
   56.99 +	static OVR_FORCE_INLINE ret_type MemberStub(void *object)
  56.100 +	{
  56.101 +		T *p = static_cast<T*>(object);
  56.102 +		return (p->*F)();
  56.103 +	}
  56.104 +
  56.105 +	template <class T, ret_type (T::*F)() const>
  56.106 +	static OVR_FORCE_INLINE ret_type ConstMemberStub(void *object)
  56.107 +	{
  56.108 +		T *p = static_cast<T*>(object);
  56.109 +		return (p->*F)();
  56.110 +	}
  56.111 +
  56.112 +public:
  56.113 +	OVR_FORCE_INLINE Delegate0() : _object(0), _stub(0){}
  56.114 +
  56.115 +	// Function invocation
  56.116 +
  56.117 +	OVR_FORCE_INLINE ret_type operator()() const
  56.118 +	{
  56.119 +		return (*_stub)(_object);
  56.120 +	}
  56.121 +
  56.122 +	// Use stub pointer as a validity flag and equality checker
  56.123 +
  56.124 +	OVR_FORCE_INLINE bool operator==(const this_type &rhs) const
  56.125 +	{
  56.126 +		return _object == rhs._object && _stub == rhs._stub;
  56.127 +	}
  56.128 +
  56.129 +	OVR_FORCE_INLINE bool operator!=(const this_type &rhs) const
  56.130 +	{
  56.131 +		return _object != rhs._object || _stub != rhs._stub;
  56.132 +	}
  56.133 +
  56.134 +	OVR_FORCE_INLINE bool IsValid() const
  56.135 +	{
  56.136 +		return _stub != 0;
  56.137 +	}
  56.138 +
  56.139 +	OVR_FORCE_INLINE bool operator!() const
  56.140 +	{
  56.141 +		return _stub == 0;
  56.142 +	}
  56.143 +
  56.144 +	OVR_FORCE_INLINE void Invalidate()
  56.145 +	{
  56.146 +		_stub = 0;
  56.147 +	}
  56.148 +
  56.149 +	// Delegate creation from a function
  56.150 +
  56.151 +	template <ret_type (*F)()>
  56.152 +	static OVR_FORCE_INLINE this_type FromFree()
  56.153 +	{
  56.154 +		return this_type(0, &FreeStub<F>);
  56.155 +	}
  56.156 +
  56.157 +	template <class T, ret_type (T::*F)()>
  56.158 +	static OVR_FORCE_INLINE this_type FromMember(T *object)
  56.159 +	{
  56.160 +		return this_type(object, &MemberStub<T, F>);
  56.161 +	}
  56.162 +
  56.163 +	template <class T, ret_type (T::*F)() const>
  56.164 +	static OVR_FORCE_INLINE this_type FromConstMember(T const *object)
  56.165 +	{
  56.166 +		return this_type(const_cast<T*>( object ), &ConstMemberStub<T, F>);
  56.167 +	}
  56.168 +
  56.169 +	// In-place assignment to a different function
  56.170 +
  56.171 +	template <ret_type (*F)()>
  56.172 +	OVR_FORCE_INLINE void SetFree()
  56.173 +	{
  56.174 +		*this = FromFree<F>();
  56.175 +	}
  56.176 +
  56.177 +	template <class T, ret_type (T::*F)()>
  56.178 +	OVR_FORCE_INLINE void SetMember(T *object)
  56.179 +	{
  56.180 +		*this = FromMember<T, F>(object);
  56.181 +	}
  56.182 +
  56.183 +	template <class T, ret_type (T::*F)() const>
  56.184 +	OVR_FORCE_INLINE void SetConstMember(T const *object)
  56.185 +	{
  56.186 +		*this = FromConstMember<T, F>(object);
  56.187 +	}
  56.188 +};
  56.189 +
  56.190 +
  56.191 +template <class ret_type, class arg1_type>
  56.192 +class Delegate1
  56.193 +{
  56.194 +	typedef ret_type (*StubPointer)(void *, arg1_type);
  56.195 +	typedef Delegate1<ret_type, arg1_type> this_type;
  56.196 +
  56.197 +	void *_object;
  56.198 +	StubPointer _stub;
  56.199 +
  56.200 +	OVR_FORCE_INLINE Delegate1(void *object, StubPointer stub)
  56.201 +	{
  56.202 +		_object = object;
  56.203 +		_stub = stub;
  56.204 +	}
  56.205 +
  56.206 +	// Stubs
  56.207 +
  56.208 +	template <ret_type (*F)(arg1_type)>
  56.209 +	static OVR_FORCE_INLINE ret_type FreeStub(void * /*object*/, arg1_type a1)
  56.210 +	{
  56.211 +		return (F)(a1);
  56.212 +	}
  56.213 +
  56.214 +	template <class T, ret_type (T::*F)(arg1_type)>
  56.215 +	static OVR_FORCE_INLINE ret_type MemberStub(void *object, arg1_type a1)
  56.216 +	{
  56.217 +		T *p = static_cast<T*>(object);
  56.218 +		return (p->*F)(a1);
  56.219 +	}
  56.220 +
  56.221 +	template <class T, ret_type (T::*F)(arg1_type) const>
  56.222 +	static OVR_FORCE_INLINE ret_type ConstMemberStub(void *object, arg1_type a1)
  56.223 +	{
  56.224 +		T *p = static_cast<T*>(object);
  56.225 +		return (p->*F)(a1);
  56.226 +	}
  56.227 +
  56.228 +public:
  56.229 +	OVR_FORCE_INLINE Delegate1() : _object(0), _stub(0){}
  56.230 +
  56.231 +	// Function invocation
  56.232 +
  56.233 +	OVR_FORCE_INLINE ret_type operator()(arg1_type a1) const
  56.234 +	{
  56.235 +		return (*_stub)(_object, a1);
  56.236 +	}
  56.237 +
  56.238 +	// Use stub pointer as a validity flag and equality checker
  56.239 +
  56.240 +	OVR_FORCE_INLINE bool operator==(const this_type &rhs) const
  56.241 +	{
  56.242 +		return _object == rhs._object && _stub == rhs._stub;
  56.243 +	}
  56.244 +
  56.245 +	OVR_FORCE_INLINE bool operator!=(const this_type &rhs) const
  56.246 +	{
  56.247 +		return _object != rhs._object || _stub != rhs._stub;
  56.248 +	}
  56.249 +
  56.250 +	OVR_FORCE_INLINE bool IsValid() const
  56.251 +	{
  56.252 +		return _stub != 0;
  56.253 +	}
  56.254 +
  56.255 +	OVR_FORCE_INLINE bool operator!() const
  56.256 +	{
  56.257 +		return _stub == 0;
  56.258 +	}
  56.259 +
  56.260 +	OVR_FORCE_INLINE void Invalidate()
  56.261 +	{
  56.262 +		_stub = 0;
  56.263 +	}
  56.264 +
  56.265 +	// Delegate creation from a function
  56.266 +
  56.267 +	template <ret_type (*F)(arg1_type)>
  56.268 +	static OVR_FORCE_INLINE this_type FromFree()
  56.269 +	{
  56.270 +		return this_type(0, &FreeStub<F>);
  56.271 +	}
  56.272 +
  56.273 +	template <class T, ret_type (T::*F)(arg1_type)>
  56.274 +	static OVR_FORCE_INLINE this_type FromMember(T *object)
  56.275 +	{
  56.276 +		return this_type(object, &MemberStub<T, F>);
  56.277 +	}
  56.278 +
  56.279 +	template <class T, ret_type (T::*F)(arg1_type) const>
  56.280 +	static OVR_FORCE_INLINE this_type FromConstMember(T const *object)
  56.281 +	{
  56.282 +		return this_type(const_cast<T*>( object ), &ConstMemberStub<T, F>);
  56.283 +	}
  56.284 +
  56.285 +	// In-place assignment to a different function
  56.286 +
  56.287 +	template <ret_type (*F)(arg1_type)>
  56.288 +	OVR_FORCE_INLINE void SetFree()
  56.289 +	{
  56.290 +		*this = FromFree<F>();
  56.291 +	}
  56.292 +
  56.293 +	template <class T, ret_type (T::*F)(arg1_type)>
  56.294 +	OVR_FORCE_INLINE void SetMember(T *object)
  56.295 +	{
  56.296 +		*this = FromMember<T, F>(object);
  56.297 +	}
  56.298 +
  56.299 +	template <class T, ret_type (T::*F)(arg1_type) const>
  56.300 +	OVR_FORCE_INLINE void SetConstMember(T const *object)
  56.301 +	{
  56.302 +		*this = FromConstMember<T, F>(object);
  56.303 +	}
  56.304 +};
  56.305 +
  56.306 +
  56.307 +template <class ret_type, class arg1_type, class arg2_type>
  56.308 +class Delegate2
  56.309 +{
  56.310 +	typedef ret_type (*StubPointer)(void *, arg1_type, arg2_type);
  56.311 +	typedef Delegate2<ret_type, arg1_type, arg2_type> this_type;
  56.312 +
  56.313 +	void *_object;
  56.314 +	StubPointer _stub;
  56.315 +
  56.316 +	OVR_FORCE_INLINE Delegate2(void *object, StubPointer stub)
  56.317 +	{
  56.318 +		_object = object;
  56.319 +		_stub = stub;
  56.320 +	}
  56.321 +
  56.322 +	// Stubs
  56.323 +
  56.324 +	template <ret_type (*F)(arg1_type, arg2_type)>
  56.325 +	static OVR_FORCE_INLINE ret_type FreeStub(void * /*object*/, arg1_type a1, arg2_type a2)
  56.326 +	{
  56.327 +		return (F)(a1, a2);
  56.328 +	}
  56.329 +
  56.330 +	template <class T, ret_type (T::*F)(arg1_type, arg2_type)>
  56.331 +	static OVR_FORCE_INLINE ret_type MemberStub(void *object, arg1_type a1, arg2_type a2)
  56.332 +	{
  56.333 +		T *p = static_cast<T*>(object);
  56.334 +		return (p->*F)(a1, a2);
  56.335 +	}
  56.336 +
  56.337 +	template <class T, ret_type (T::*F)(arg1_type, arg2_type) const>
  56.338 +	static OVR_FORCE_INLINE ret_type ConstMemberStub(void *object, arg1_type a1, arg2_type a2)
  56.339 +	{
  56.340 +		T *p = static_cast<T*>(object);
  56.341 +		return (p->*F)(a1, a2);
  56.342 +	}
  56.343 +
  56.344 +public:
  56.345 +	OVR_FORCE_INLINE Delegate2() : _object(0), _stub(0){}
  56.346 +
  56.347 +	// Function invocation
  56.348 +
  56.349 +	OVR_FORCE_INLINE ret_type operator()(arg1_type a1, arg2_type a2) const
  56.350 +	{
  56.351 +		return (*_stub)(_object, a1, a2);
  56.352 +	}
  56.353 +
  56.354 +	// Use stub pointer as a validity flag and equality checker
  56.355 +
  56.356 +	OVR_FORCE_INLINE bool operator==(const this_type &rhs) const
  56.357 +	{
  56.358 +		return _object == rhs._object && _stub == rhs._stub;
  56.359 +	}
  56.360 +
  56.361 +	OVR_FORCE_INLINE bool operator!=(const this_type &rhs) const
  56.362 +	{
  56.363 +		return _object != rhs._object || _stub != rhs._stub;
  56.364 +	}
  56.365 +
  56.366 +	OVR_FORCE_INLINE bool IsValid() const
  56.367 +	{
  56.368 +		return _stub != 0;
  56.369 +	}
  56.370 +
  56.371 +	OVR_FORCE_INLINE bool operator!() const
  56.372 +	{
  56.373 +		return _stub == 0;
  56.374 +	}
  56.375 +
  56.376 +	OVR_FORCE_INLINE void Invalidate()
  56.377 +	{
  56.378 +		_stub = 0;
  56.379 +	}
  56.380 +
  56.381 +	// Delegate creation from a function
  56.382 +
  56.383 +	template <ret_type (*F)(arg1_type, arg2_type)>
  56.384 +	static OVR_FORCE_INLINE this_type FromFree()
  56.385 +	{
  56.386 +		return this_type(0, &FreeStub<F>);
  56.387 +	}
  56.388 +
  56.389 +	template <class T, ret_type (T::*F)(arg1_type, arg2_type)>
  56.390 +	static OVR_FORCE_INLINE this_type FromMember(T *object)
  56.391 +	{
  56.392 +		return this_type(object, &MemberStub<T, F>);
  56.393 +	}
  56.394 +
  56.395 +	template <class T, ret_type (T::*F)(arg1_type, arg2_type) const>
  56.396 +	static OVR_FORCE_INLINE this_type FromConstMember(T const *object)
  56.397 +	{
  56.398 +		return this_type(const_cast<T*>( object ), &ConstMemberStub<T, F>);
  56.399 +	}
  56.400 +
  56.401 +	// In-place assignment to a different function
  56.402 +
  56.403 +	template <ret_type (*F)(arg1_type, arg2_type)>
  56.404 +	OVR_FORCE_INLINE void SetFree()
  56.405 +	{
  56.406 +		*this = FromFree<F>();
  56.407 +	}
  56.408 +
  56.409 +	template <class T, ret_type (T::*F)(arg1_type, arg2_type)>
  56.410 +	OVR_FORCE_INLINE void SetMember(T *object)
  56.411 +	{
  56.412 +		*this = FromMember<T, F>(object);
  56.413 +	}
  56.414 +
  56.415 +	template <class T, ret_type (T::*F)(arg1_type, arg2_type) const>
  56.416 +	OVR_FORCE_INLINE void SetConstMember(T const *object)
  56.417 +	{
  56.418 +		*this = FromConstMember<T, F>(object);
  56.419 +	}
  56.420 +};
  56.421 +
  56.422 +
  56.423 +template <class ret_type, class arg1_type, class arg2_type, class arg3_type>
  56.424 +class Delegate3
  56.425 +{
  56.426 +	typedef ret_type (*StubPointer)(void *, arg1_type, arg2_type, arg3_type);
  56.427 +	typedef Delegate3<ret_type, arg1_type, arg2_type, arg3_type> this_type;
  56.428 +
  56.429 +	void *_object;
  56.430 +	StubPointer _stub;
  56.431 +
  56.432 +	OVR_FORCE_INLINE Delegate3(void *object, StubPointer stub)
  56.433 +	{
  56.434 +		_object = object;
  56.435 +		_stub = stub;
  56.436 +	}
  56.437 +
  56.438 +	// Stubs
  56.439 +
  56.440 +	template <ret_type (*F)(arg1_type, arg2_type, arg3_type)>
  56.441 +	static OVR_FORCE_INLINE ret_type FreeStub(void * /*object*/, arg1_type a1, arg2_type a2, arg3_type a3)
  56.442 +	{
  56.443 +		return (F)(a1, a2, a3);
  56.444 +	}
  56.445 +
  56.446 +	template <class T, ret_type (T::*F)(arg1_type, arg2_type, arg3_type)>
  56.447 +	static OVR_FORCE_INLINE ret_type MemberStub(void *object, arg1_type a1, arg2_type a2, arg3_type a3)
  56.448 +	{
  56.449 +		T *p = static_cast<T*>(object);
  56.450 +		return (p->*F)(a1, a2, a3);
  56.451 +	}
  56.452 +
  56.453 +	template <class T, ret_type (T::*F)(arg1_type, arg2_type, arg3_type) const>
  56.454 +	static OVR_FORCE_INLINE ret_type ConstMemberStub(void *object, arg1_type a1, arg2_type a2, arg3_type a3)
  56.455 +	{
  56.456 +		T *p = static_cast<T*>(object);
  56.457 +		return (p->*F)(a1, a2, a3);
  56.458 +	}
  56.459 +
  56.460 +public:
  56.461 +	OVR_FORCE_INLINE Delegate3() : _object(0), _stub(0){}
  56.462 +
  56.463 +	// Function invocation
  56.464 +
  56.465 +	OVR_FORCE_INLINE ret_type operator()(arg1_type a1, arg2_type a2, arg3_type a3) const
  56.466 +	{
  56.467 +		return (*_stub)(_object, a1, a2, a3);
  56.468 +	}
  56.469 +
  56.470 +	// Use stub pointer as a validity flag and equality checker
  56.471 +
  56.472 +	OVR_FORCE_INLINE bool operator==(const this_type &rhs) const
  56.473 +	{
  56.474 +		return _object == rhs._object && _stub == rhs._stub;
  56.475 +	}
  56.476 +
  56.477 +	OVR_FORCE_INLINE bool operator!=(const this_type &rhs) const
  56.478 +	{
  56.479 +		return _object != rhs._object || _stub != rhs._stub;
  56.480 +	}
  56.481 +
  56.482 +	OVR_FORCE_INLINE bool IsValid() const
  56.483 +	{
  56.484 +		return _stub != 0;
  56.485 +	}
  56.486 +
  56.487 +	OVR_FORCE_INLINE bool operator!() const
  56.488 +	{
  56.489 +		return _stub == 0;
  56.490 +	}
  56.491 +
  56.492 +	OVR_FORCE_INLINE void Invalidate()
  56.493 +	{
  56.494 +		_stub = 0;
  56.495 +	}
  56.496 +
  56.497 +	// Delegate creation from a function
  56.498 +
  56.499 +	template <ret_type (*F)(arg1_type, arg2_type, arg3_type)>
  56.500 +	static OVR_FORCE_INLINE this_type FromFree()
  56.501 +	{
  56.502 +		return this_type(0, &FreeStub<F>);
  56.503 +	}
  56.504 +
  56.505 +	template <class T, ret_type (T::*F)(arg1_type, arg2_type, arg3_type)>
  56.506 +	static OVR_FORCE_INLINE this_type FromMember(T *object)
  56.507 +	{
  56.508 +		return this_type(object, &MemberStub<T, F>);
  56.509 +	}
  56.510 +
  56.511 +	template <class T, ret_type (T::*F)(arg1_type, arg2_type, arg3_type) const>
  56.512 +	static OVR_FORCE_INLINE this_type FromConstMember(T const *object)
  56.513 +	{
  56.514 +		return this_type(const_cast<T*>( object ), &ConstMemberStub<T, F>);
  56.515 +	}
  56.516 +
  56.517 +	// In-place assignment to a different function
  56.518 +
  56.519 +	template <ret_type (*F)(arg1_type, arg2_type, arg3_type)>
  56.520 +	OVR_FORCE_INLINE void SetFree()
  56.521 +	{
  56.522 +		*this = FromFree<F>();
  56.523 +	}
  56.524 +
  56.525 +	template <class T, ret_type (T::*F)(arg1_type, arg2_type, arg3_type)>
  56.526 +	OVR_FORCE_INLINE void SetMember(T *object)
  56.527 +	{
  56.528 +		*this = FromMember<T, F>(object);
  56.529 +	}
  56.530 +
  56.531 +	template <class T, ret_type (T::*F)(arg1_type, arg2_type, arg3_type) const>
  56.532 +	OVR_FORCE_INLINE void SetConstMember(T const *object)
  56.533 +	{
  56.534 +		*this = FromConstMember<T, F>(object);
  56.535 +	}
  56.536 +};
  56.537 +
  56.538 +// Add more here if needed, but keep in mind that a short, simple interface
  56.539 +// is rewarded by making the delegates faster...
  56.540 +
  56.541 +
  56.542 +} // namespace OVR
  56.543 +
  56.544 +#endif // OVR_Delegates_h
    57.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    57.2 +++ b/LibOVR/Src/Kernel/OVR_Deque.h	Wed Jan 14 06:51:16 2015 +0200
    57.3 @@ -0,0 +1,316 @@
    57.4 +/************************************************************************************
    57.5 +
    57.6 +Filename    :   OVR_Deque.h
    57.7 +Content     :   Deque container
    57.8 +Created     :   Nov. 15, 2013
    57.9 +Authors     :   Dov Katz
   57.10 +
   57.11 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   57.12 +
   57.13 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
   57.14 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
   57.15 +which is provided at the time of installation or download, or which 
   57.16 +otherwise accompanies this software in either electronic or hard copy form.
   57.17 +
   57.18 +You may obtain a copy of the License at
   57.19 +
   57.20 +http://www.oculusvr.com/licenses/LICENSE-3.2 
   57.21 +
   57.22 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
   57.23 +distributed under the License is distributed on an "AS IS" BASIS,
   57.24 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   57.25 +See the License for the specific language governing permissions and
   57.26 +limitations under the License.
   57.27 +
   57.28 +*************************************************************************************/
   57.29 +
   57.30 +#ifndef OVR_Deque_h
   57.31 +#define OVR_Deque_h
   57.32 +
   57.33 +#include "OVR_ContainerAllocator.h"
   57.34 +
   57.35 +namespace OVR{ 
   57.36 +
   57.37 +template <class Elem, class Allocator = ContainerAllocator<Elem> >
   57.38 +class Deque
   57.39 +{
   57.40 +public:
   57.41 +    enum
   57.42 +    {
   57.43 +        DefaultCapacity = 500
   57.44 +    };
   57.45 +
   57.46 +    Deque(int capacity = DefaultCapacity);
   57.47 +    virtual ~Deque(void);
   57.48 +
   57.49 +    virtual void         PushBack   (const Elem &Item);    // Adds Item to the end
   57.50 +    virtual void         PushFront  (const Elem &Item);    // Adds Item to the beginning
   57.51 +    virtual Elem         PopBack    (void);                // Removes Item from the end
   57.52 +    virtual Elem         PopFront   (void);                // Removes Item from the beginning
   57.53 +    virtual const Elem&  PeekBack   (int count = 0) const; // Returns count-th Item from the end
   57.54 +    virtual const Elem&  PeekFront  (int count = 0) const; // Returns count-th Item from the beginning
   57.55 +
   57.56 +	virtual inline size_t GetSize    (void)          const; // Returns Number of Elements
   57.57 +	OVR_FORCE_INLINE int GetSizeI   (void)          const
   57.58 +	{
   57.59 +		return (int)GetSize();
   57.60 +	}
   57.61 +    virtual inline size_t GetCapacity(void)          const; // Returns the maximum possible number of elements
   57.62 +    virtual void         Clear      (void);				   // Remove all elements
   57.63 +    virtual inline bool  IsEmpty    ()              const;
   57.64 +    virtual inline bool  IsFull     ()              const;
   57.65 +
   57.66 +protected:
   57.67 +    Elem        *Data;          // The actual Data array
   57.68 +    const int   Capacity;       // Deque capacity
   57.69 +    int         Beginning;      // Index of the first element
   57.70 +    int         End;            // Index of the next after last element
   57.71 +
   57.72 +    // Instead of calculating the number of elements, using this variable
   57.73 +    // is much more convenient.
   57.74 +    int         ElemCount;
   57.75 +
   57.76 +private:
   57.77 +    OVR_NON_COPYABLE(Deque);
   57.78 +};
   57.79 +
   57.80 +template <class Elem, class Allocator = ContainerAllocator<Elem> >
   57.81 +class InPlaceMutableDeque : public Deque<Elem, Allocator>
   57.82 +{
   57.83 +    typedef Deque<Elem, Allocator> BaseType;
   57.84 +
   57.85 +public:
   57.86 +    InPlaceMutableDeque( int capacity = BaseType::DefaultCapacity ) : BaseType( capacity ) {}
   57.87 +	virtual ~InPlaceMutableDeque() {};
   57.88 +
   57.89 +    using BaseType::PeekBack;
   57.90 +    using BaseType::PeekFront;
   57.91 +	virtual Elem& PeekBack  (int count = 0); // Returns count-th Item from the end
   57.92 +	virtual Elem& PeekFront (int count = 0); // Returns count-th Item from the beginning
   57.93 +};
   57.94 +
   57.95 +// Same as Deque, but allows to write more elements than maximum capacity
   57.96 +// Old elements are lost as they are overwritten with the new ones
   57.97 +template <class Elem, class Allocator = ContainerAllocator<Elem> >
   57.98 +class CircularBuffer : public InPlaceMutableDeque<Elem, Allocator>
   57.99 +{
  57.100 +    typedef InPlaceMutableDeque<Elem, Allocator> BaseType;
  57.101 +
  57.102 +public:
  57.103 +    CircularBuffer(int MaxSize = BaseType::DefaultCapacity) : BaseType(MaxSize) { };
  57.104 +    virtual ~CircularBuffer(){}
  57.105 +
  57.106 +    // The following methods are inline as a workaround for a VS bug causing erroneous C4505 warnings
  57.107 +    // See: http://stackoverflow.com/questions/3051992/compiler-warning-at-c-template-base-class
  57.108 +    inline virtual void PushBack  (const Elem &Item);    // Adds Item to the end, overwriting the oldest element at the beginning if necessary
  57.109 +    inline virtual void PushFront (const Elem &Item);    // Adds Item to the beginning, overwriting the oldest element at the end if necessary
  57.110 +};
  57.111 +
  57.112 +//----------------------------------------------------------------------------------
  57.113 +
  57.114 +// Deque Constructor function
  57.115 +template <class Elem, class Allocator>
  57.116 +Deque<Elem, Allocator>::Deque(int capacity) :
  57.117 +Capacity( capacity ), Beginning(0), End(0), ElemCount(0)
  57.118 +{
  57.119 +    Data = (Elem*) Allocator::Alloc(Capacity * sizeof(Elem));
  57.120 +}
  57.121 +
  57.122 +// Deque Destructor function
  57.123 +template <class Elem, class Allocator>
  57.124 +Deque<Elem, Allocator>::~Deque(void)
  57.125 +{
  57.126 +    Clear();
  57.127 +    Allocator::Free(Data);
  57.128 +}
  57.129 +
  57.130 +template <class Elem, class Allocator>
  57.131 +void Deque<Elem, Allocator>::Clear()
  57.132 +{
  57.133 +    if (!IsEmpty())
  57.134 +    {
  57.135 +        if (Beginning < End)
  57.136 +        {
  57.137 +            // no wrap-around
  57.138 +            Allocator::DestructArray(Data + Beginning, End - Beginning);
  57.139 +        }
  57.140 +        else
  57.141 +        {
  57.142 +            // wrap-around
  57.143 +            Allocator::DestructArray(Data + Beginning, Capacity - Beginning);
  57.144 +            Allocator::DestructArray(Data, End);
  57.145 +        }
  57.146 +    }
  57.147 +    
  57.148 +    Beginning = 0;
  57.149 +    End       = 0;
  57.150 +    ElemCount = 0;
  57.151 +}
  57.152 +
  57.153 +// Push functions
  57.154 +template <class Elem, class Allocator>
  57.155 +void Deque<Elem, Allocator>::PushBack(const Elem &Item)
  57.156 +{
  57.157 +    // Error Check: Make sure we aren't  
  57.158 +    // exceeding our maximum storage space
  57.159 +    OVR_ASSERT( ElemCount < Capacity );
  57.160 +
  57.161 +    Allocator::Construct(Data + End, Item);
  57.162 +    ++End;
  57.163 +    ++ElemCount;
  57.164 +
  57.165 +    // Check for wrap-around
  57.166 +    if (End >= Capacity)
  57.167 +        End -= Capacity;
  57.168 +}
  57.169 +
  57.170 +template <class Elem, class Allocator>
  57.171 +void Deque<Elem, Allocator>::PushFront(const Elem &Item)
  57.172 +{
  57.173 +    // Error Check: Make sure we aren't  
  57.174 +    // exceeding our maximum storage space
  57.175 +    OVR_ASSERT( ElemCount < Capacity );
  57.176 +
  57.177 +    --Beginning;
  57.178 +    // Check for wrap-around
  57.179 +    if (Beginning < 0)
  57.180 +        Beginning += Capacity;
  57.181 +
  57.182 +    Allocator::Construct(Data + Beginning, Item);
  57.183 +    ++ElemCount;
  57.184 +}
  57.185 +
  57.186 +// Pop functions
  57.187 +template <class Elem, class Allocator>
  57.188 +Elem Deque<Elem, Allocator>::PopFront(void)
  57.189 +{
  57.190 +    // Error Check: Make sure we aren't reading from an empty Deque
  57.191 +    OVR_ASSERT( ElemCount > 0 );
  57.192 +
  57.193 +	Elem ReturnValue = Data[ Beginning ];
  57.194 +    Allocator::Destruct(Data + Beginning);
  57.195 +
  57.196 +	++Beginning;
  57.197 +    --ElemCount;
  57.198 +
  57.199 +    // Check for wrap-around
  57.200 +    if (Beginning >= Capacity)
  57.201 +        Beginning -= Capacity;
  57.202 +
  57.203 +    return ReturnValue;
  57.204 +}
  57.205 +
  57.206 +template <class Elem, class Allocator>
  57.207 +Elem Deque<Elem, Allocator>::PopBack(void)
  57.208 +{
  57.209 +    // Error Check: Make sure we aren't reading from an empty Deque
  57.210 +    OVR_ASSERT( ElemCount > 0 );
  57.211 +
  57.212 +    --End;
  57.213 +    --ElemCount;
  57.214 +
  57.215 +    // Check for wrap-around
  57.216 +    if (End < 0)
  57.217 +        End += Capacity;
  57.218 +
  57.219 +    Elem ReturnValue = Data[ End ];
  57.220 +    Allocator::Destruct(Data + End);
  57.221 +
  57.222 +    return ReturnValue;
  57.223 +}
  57.224 +
  57.225 +// Peek functions
  57.226 +template <class Elem, class Allocator>
  57.227 +const Elem& Deque<Elem, Allocator>::PeekFront(int count) const
  57.228 +{
  57.229 +    // Error Check: Make sure we aren't reading from an empty Deque
  57.230 +    OVR_ASSERT( ElemCount > count );
  57.231 +
  57.232 +    int idx = Beginning + count;
  57.233 +    if (idx >= Capacity)
  57.234 +        idx -= Capacity;
  57.235 +    return Data[ idx ];
  57.236 +}
  57.237 +
  57.238 +template <class Elem, class Allocator>
  57.239 +const Elem& Deque<Elem, Allocator>::PeekBack(int count) const
  57.240 +{
  57.241 +    // Error Check: Make sure we aren't reading from an empty Deque
  57.242 +    OVR_ASSERT( ElemCount > count );
  57.243 +
  57.244 +    int idx = End - count - 1;
  57.245 +    if (idx < 0)
  57.246 +        idx += Capacity;
  57.247 +    return Data[ idx ];
  57.248 +}
  57.249 +
  57.250 +// Mutable Peek functions
  57.251 +template <class Elem, class Allocator>
  57.252 +Elem& InPlaceMutableDeque<Elem, Allocator>::PeekFront(int count)
  57.253 +{
  57.254 +    // Error Check: Make sure we aren't reading from an empty Deque
  57.255 +    OVR_ASSERT( BaseType::ElemCount > count );
  57.256 +
  57.257 +    int idx = BaseType::Beginning + count;
  57.258 +    if (idx >= BaseType::Capacity)
  57.259 +        idx -= BaseType::Capacity;
  57.260 +    return BaseType::Data[ idx ];
  57.261 +}
  57.262 +
  57.263 +template <class Elem, class Allocator>
  57.264 +Elem& InPlaceMutableDeque<Elem, Allocator>::PeekBack(int count)
  57.265 +{
  57.266 +    // Error Check: Make sure we aren't reading from an empty Deque
  57.267 +    OVR_ASSERT( BaseType::ElemCount > count );
  57.268 +
  57.269 +    int idx = BaseType::End - count - 1;
  57.270 +    if (idx < 0)
  57.271 +        idx += BaseType::Capacity;
  57.272 +    return BaseType::Data[ idx ];
  57.273 +}
  57.274 +
  57.275 +template <class Elem, class Allocator>
  57.276 +inline size_t Deque<Elem, Allocator>::GetCapacity(void) const
  57.277 +{
  57.278 +    return Capacity;
  57.279 +}
  57.280 +
  57.281 +template <class Elem, class Allocator>
  57.282 +inline size_t Deque<Elem, Allocator>::GetSize(void) const
  57.283 +{
  57.284 +    return ElemCount;
  57.285 +}
  57.286 +
  57.287 +template <class Elem, class Allocator>
  57.288 +inline bool Deque<Elem, Allocator>::IsEmpty(void) const
  57.289 +{
  57.290 +    return ElemCount == 0;
  57.291 +}
  57.292 +
  57.293 +template <class Elem, class Allocator>
  57.294 +inline bool Deque<Elem, Allocator>::IsFull(void) const
  57.295 +{
  57.296 +    return ElemCount == Capacity;
  57.297 +}
  57.298 +
  57.299 +// ******* CircularBuffer<Elem> *******
  57.300 +// Push functions
  57.301 +template <class Elem, class Allocator>
  57.302 +void CircularBuffer<Elem, Allocator>::PushBack(const Elem &Item)
  57.303 +{
  57.304 +    if (this->IsFull())
  57.305 +        this->PopFront();
  57.306 +    BaseType::PushBack(Item);
  57.307 +}
  57.308 +
  57.309 +template <class Elem, class Allocator>
  57.310 +void CircularBuffer<Elem, Allocator>::PushFront(const Elem &Item)
  57.311 +{
  57.312 +    if (this->IsFull())
  57.313 +        this->PopBack();
  57.314 +    BaseType::PushFront(Item);
  57.315 +}
  57.316 +
  57.317 +};   
  57.318 +
  57.319 +#endif
    58.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    58.2 +++ b/LibOVR/Src/Kernel/OVR_File.cpp	Wed Jan 14 06:51:16 2015 +0200
    58.3 @@ -0,0 +1,585 @@
    58.4 +/**************************************************************************
    58.5 +
    58.6 +Filename    :   OVR_File.cpp
    58.7 +Content     :   File wrapper class implementation (Win32)
    58.8 +
    58.9 +Created     :   April 5, 1999
   58.10 +Authors     :   Michael Antonov
   58.11 +
   58.12 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   58.13 +
   58.14 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
   58.15 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
   58.16 +which is provided at the time of installation or download, or which 
   58.17 +otherwise accompanies this software in either electronic or hard copy form.
   58.18 +
   58.19 +You may obtain a copy of the License at
   58.20 +
   58.21 +http://www.oculusvr.com/licenses/LICENSE-3.2 
   58.22 +
   58.23 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
   58.24 +distributed under the License is distributed on an "AS IS" BASIS,
   58.25 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   58.26 +See the License for the specific language governing permissions and
   58.27 +limitations under the License.
   58.28 +
   58.29 +**************************************************************************/
   58.30 +
   58.31 +#define  GFILE_CXX
   58.32 +
   58.33 +// Standard C library (Captain Obvious guarantees!)
   58.34 +#include <stdio.h>
   58.35 +
   58.36 +#include "OVR_File.h"
   58.37 +
   58.38 +namespace OVR {
   58.39 +
   58.40 +// Buffered file adds buffering to an existing file
   58.41 +// FILEBUFFER_SIZE defines the size of internal buffer, while
   58.42 +// FILEBUFFER_TOLERANCE controls the amount of data we'll effectively try to buffer
   58.43 +#define FILEBUFFER_SIZE         (8192-8)
   58.44 +#define FILEBUFFER_TOLERANCE    4096
   58.45 +
   58.46 +// ** Constructor/Destructor
   58.47 +
   58.48 +// Hidden constructor
   58.49 +// Not supposed to be used
   58.50 +BufferedFile::BufferedFile() : DelegatedFile(0)
   58.51 +{
   58.52 +    pBuffer     = (uint8_t*)OVR_ALLOC(FILEBUFFER_SIZE);
   58.53 +    BufferMode  = NoBuffer;
   58.54 +    FilePos     = 0;
   58.55 +    Pos         = 0;
   58.56 +    DataSize    = 0;
   58.57 +}
   58.58 +
   58.59 +// Takes another file as source
   58.60 +BufferedFile::BufferedFile(File *pfile) : DelegatedFile(pfile)
   58.61 +{
   58.62 +    pBuffer     = (uint8_t*)OVR_ALLOC(FILEBUFFER_SIZE);
   58.63 +    BufferMode  = NoBuffer;
   58.64 +    FilePos     = pfile->LTell();
   58.65 +    Pos         = 0;
   58.66 +    DataSize    = 0;
   58.67 +}
   58.68 +
   58.69 +
   58.70 +// Destructor
   58.71 +BufferedFile::~BufferedFile()
   58.72 +{
   58.73 +    // Flush in case there's data
   58.74 +    if (pFile)
   58.75 +        FlushBuffer();
   58.76 +    // Get rid of buffer
   58.77 +    if (pBuffer)
   58.78 +        OVR_FREE(pBuffer);
   58.79 +}
   58.80 +
   58.81 +/*
   58.82 +bool    BufferedFile::VCopy(const Object &source)
   58.83 +{
   58.84 +    if (!DelegatedFile::VCopy(source))
   58.85 +        return 0;
   58.86 +
   58.87 +    // Data members
   58.88 +    BufferedFile *psource = (BufferedFile*)&source;
   58.89 +
   58.90 +    // Buffer & the mode it's in
   58.91 +    pBuffer         = psource->pBuffer;
   58.92 +    BufferMode      = psource->BufferMode;
   58.93 +    Pos             = psource->Pos;
   58.94 +    DataSize        = psource->DataSize;
   58.95 +    return 1;
   58.96 +}
   58.97 +*/
   58.98 +
   58.99 +// Initializes buffering to a certain mode
  58.100 +bool    BufferedFile::SetBufferMode(BufferModeType mode)
  58.101 +{
  58.102 +    if (!pBuffer)
  58.103 +        return false;
  58.104 +    if (mode == BufferMode)
  58.105 +        return true;
  58.106 +     
  58.107 +    FlushBuffer();
  58.108 +
  58.109 +    // Can't set write mode if we can't write
  58.110 +    if ((mode==WriteBuffer) && (!pFile || !pFile->IsWritable()) )
  58.111 +        return 0;
  58.112 +
  58.113 +    // And SetMode
  58.114 +    BufferMode = mode;
  58.115 +    Pos        = 0;
  58.116 +    DataSize   = 0;
  58.117 +    return 1;
  58.118 +}
  58.119 +
  58.120 +// Flushes buffer
  58.121 +void    BufferedFile::FlushBuffer()
  58.122 +{
  58.123 +    switch(BufferMode)
  58.124 +    {
  58.125 +        case WriteBuffer:
  58.126 +            // Write data in buffer
  58.127 +            FilePos += pFile->Write(pBuffer,Pos);
  58.128 +            Pos = 0;
  58.129 +            break;
  58.130 +
  58.131 +        case ReadBuffer:
  58.132 +            // Seek back & reset buffer data
  58.133 +            if ((DataSize-Pos)>0)
  58.134 +                FilePos = pFile->LSeek(-(int)(DataSize-Pos), Seek_Cur);
  58.135 +            DataSize = 0;
  58.136 +            Pos      = 0;
  58.137 +            break;
  58.138 +        default:
  58.139 +            // not handled!
  58.140 +            break;
  58.141 +    }
  58.142 +}
  58.143 +
  58.144 +// Reloads data for ReadBuffer
  58.145 +void    BufferedFile::LoadBuffer()
  58.146 +{
  58.147 +    if (BufferMode == ReadBuffer)
  58.148 +    {
  58.149 +        // We should only reload once all of pre-loaded buffer is consumed.
  58.150 +        OVR_ASSERT(Pos == DataSize);
  58.151 +
  58.152 +        // WARNING: Right now LoadBuffer() assumes the buffer's empty
  58.153 +        int sz   = pFile->Read(pBuffer,FILEBUFFER_SIZE);
  58.154 +        DataSize = sz<0 ? 0 : (unsigned)sz;
  58.155 +        Pos      = 0;
  58.156 +        FilePos  += DataSize;
  58.157 +    }
  58.158 +}
  58.159 +
  58.160 +
  58.161 +// ** Overridden functions
  58.162 +
  58.163 +// We override all the functions that can possibly
  58.164 +// require buffer mode switch, flush, or extra calculations
  58.165 +
  58.166 +// Tell() requires buffer adjustment
  58.167 +int     BufferedFile::Tell()
  58.168 +{
  58.169 +    if (BufferMode == ReadBuffer)
  58.170 +        return int (FilePos - DataSize + Pos);
  58.171 +
  58.172 +    int pos = pFile->Tell();
  58.173 +    // Adjust position based on buffer mode & data
  58.174 +    if (pos!=-1)
  58.175 +    {
  58.176 +        OVR_ASSERT(BufferMode != ReadBuffer);
  58.177 +        if (BufferMode == WriteBuffer)
  58.178 +            pos += Pos;
  58.179 +    }
  58.180 +    return pos;
  58.181 +}
  58.182 +
  58.183 +int64_t BufferedFile::LTell()
  58.184 +{
  58.185 +    if (BufferMode == ReadBuffer)
  58.186 +        return FilePos - DataSize + Pos;
  58.187 +
  58.188 +    int64_t pos = pFile->LTell();
  58.189 +    if (pos!=-1)
  58.190 +    {
  58.191 +        OVR_ASSERT(BufferMode != ReadBuffer);
  58.192 +        if (BufferMode == WriteBuffer)
  58.193 +            pos += Pos;
  58.194 +    }
  58.195 +    return pos;
  58.196 +}
  58.197 +
  58.198 +int     BufferedFile::GetLength()
  58.199 +{
  58.200 +    int len = pFile->GetLength();
  58.201 +    // If writing through buffer, file length may actually be bigger
  58.202 +    if ((len!=-1) && (BufferMode==WriteBuffer))
  58.203 +    {
  58.204 +        int currPos = pFile->Tell() + Pos;
  58.205 +        if (currPos>len)
  58.206 +            len = currPos;
  58.207 +    }
  58.208 +    return len;
  58.209 +}
  58.210 +int64_t BufferedFile::LGetLength()
  58.211 +{
  58.212 +    int64_t len = pFile->LGetLength();
  58.213 +    // If writing through buffer, file length may actually be bigger
  58.214 +    if ((len!=-1) && (BufferMode==WriteBuffer))
  58.215 +    {
  58.216 +        int64_t currPos = pFile->LTell() + Pos;
  58.217 +        if (currPos>len)
  58.218 +            len = currPos;
  58.219 +    }
  58.220 +    return len;
  58.221 +}
  58.222 +
  58.223 +/*
  58.224 +bool    BufferedFile::Stat(FileStats *pfs)
  58.225 +{
  58.226 +    // Have to fix up length is stat
  58.227 +    if (pFile->Stat(pfs))
  58.228 +    {
  58.229 +        if (BufferMode==WriteBuffer)
  58.230 +        {
  58.231 +            int64_t currPos = pFile->LTell() + Pos;
  58.232 +            if (currPos > pfs->Size)
  58.233 +            {
  58.234 +                pfs->Size   = currPos;
  58.235 +                // ??
  58.236 +                pfs->Blocks = (pfs->Size+511) >> 9;
  58.237 +            }
  58.238 +        }
  58.239 +        return 1;
  58.240 +    }
  58.241 +    return 0;
  58.242 +}
  58.243 +*/
  58.244 +
  58.245 +int     BufferedFile::Write(const uint8_t *psourceBuffer, int numBytes)
  58.246 +{
  58.247 +    if ( (BufferMode==WriteBuffer) || SetBufferMode(WriteBuffer))
  58.248 +    {
  58.249 +        // If not data space in buffer, flush
  58.250 +        if ((FILEBUFFER_SIZE-(int)Pos)<numBytes)
  58.251 +        {
  58.252 +            FlushBuffer();
  58.253 +            // If bigger then tolerance, just write directly
  58.254 +            if (numBytes>FILEBUFFER_TOLERANCE)
  58.255 +            {
  58.256 +                int sz = pFile->Write(psourceBuffer,numBytes);
  58.257 +                if (sz > 0)
  58.258 +                    FilePos += sz;
  58.259 +                return sz;
  58.260 +            }
  58.261 +        }
  58.262 +
  58.263 +        // Enough space in buffer.. so copy to it
  58.264 +        memcpy(pBuffer+Pos, psourceBuffer, numBytes);
  58.265 +        Pos += numBytes;
  58.266 +        return numBytes;
  58.267 +    }
  58.268 +    int sz = pFile->Write(psourceBuffer,numBytes);
  58.269 +    if (sz > 0)
  58.270 +        FilePos += sz;
  58.271 +    return sz;
  58.272 +}
  58.273 +
  58.274 +int     BufferedFile::Read(uint8_t *pdestBuffer, int numBytes)
  58.275 +{
  58.276 +    if ( (BufferMode==ReadBuffer) || SetBufferMode(ReadBuffer))
  58.277 +    {
  58.278 +        // Data in buffer... copy it
  58.279 +        if ((int)(DataSize-Pos) >= numBytes)
  58.280 +        {
  58.281 +            memcpy(pdestBuffer, pBuffer+Pos, numBytes);
  58.282 +            Pos += numBytes;
  58.283 +            return numBytes;
  58.284 +        }
  58.285 +
  58.286 +        // Not enough data in buffer, copy buffer
  58.287 +        int     readBytes = DataSize-Pos;
  58.288 +        memcpy(pdestBuffer, pBuffer+Pos, readBytes);
  58.289 +        numBytes    -= readBytes;
  58.290 +        pdestBuffer += readBytes;
  58.291 +        Pos = DataSize;
  58.292 +
  58.293 +        // Don't reload buffer if more then tolerance
  58.294 +        // (No major advantage, and we don't want to write a loop)
  58.295 +        if (numBytes>FILEBUFFER_TOLERANCE)
  58.296 +        {
  58.297 +            numBytes = pFile->Read(pdestBuffer,numBytes);
  58.298 +            if (numBytes > 0)
  58.299 +            {
  58.300 +                FilePos += numBytes;
  58.301 +                Pos = DataSize = 0;
  58.302 +            }
  58.303 +            return readBytes + ((numBytes==-1) ? 0 : numBytes);
  58.304 +        }
  58.305 +
  58.306 +        // Reload the buffer
  58.307 +        // WARNING: Right now LoadBuffer() assumes the buffer's empty
  58.308 +        LoadBuffer();
  58.309 +        if ((int)(DataSize-Pos) < numBytes)
  58.310 +            numBytes = (int)DataSize-Pos;
  58.311 +
  58.312 +        memcpy(pdestBuffer, pBuffer+Pos, numBytes);
  58.313 +        Pos += numBytes;
  58.314 +        return numBytes + readBytes;
  58.315 +        
  58.316 +        /*
  58.317 +        // Alternative Read implementation. The one above is probably better
  58.318 +        // due to FILEBUFFER_TOLERANCE.
  58.319 +        int     total = 0;
  58.320 +
  58.321 +        do {
  58.322 +            int     bufferBytes = (int)(DataSize-Pos);
  58.323 +            int     copyBytes = (bufferBytes > numBytes) ? numBytes : bufferBytes;
  58.324 +
  58.325 +            memcpy(pdestBuffer, pBuffer+Pos, copyBytes);
  58.326 +            numBytes    -= copyBytes;
  58.327 +            pdestBuffer += copyBytes;
  58.328 +            Pos         += copyBytes;
  58.329 +            total       += copyBytes;
  58.330 +
  58.331 +            if (numBytes == 0)
  58.332 +                break;
  58.333 +            LoadBuffer();
  58.334 +
  58.335 +        } while (DataSize > 0);
  58.336 +
  58.337 +        return total;
  58.338 +        */     
  58.339 +    }
  58.340 +    int sz = pFile->Read(pdestBuffer,numBytes);
  58.341 +    if (sz > 0)
  58.342 +        FilePos += sz;
  58.343 +    return sz;
  58.344 +}
  58.345 +
  58.346 +
  58.347 +int     BufferedFile::SkipBytes(int numBytes)
  58.348 +{
  58.349 +    int skippedBytes = 0;
  58.350 +
  58.351 +    // Special case for skipping a little data in read buffer
  58.352 +    if (BufferMode==ReadBuffer)
  58.353 +    {
  58.354 +        skippedBytes = (((int)DataSize-(int)Pos) >= numBytes) ? numBytes : (DataSize-Pos);
  58.355 +        Pos          += skippedBytes;
  58.356 +        numBytes     -= skippedBytes;
  58.357 +    }
  58.358 +
  58.359 +    if (numBytes)
  58.360 +    {
  58.361 +        numBytes = pFile->SkipBytes(numBytes);
  58.362 +        // Make sure we return the actual number skipped, or error
  58.363 +        if (numBytes!=-1)
  58.364 +        {
  58.365 +            skippedBytes += numBytes;
  58.366 +            FilePos += numBytes;
  58.367 +            Pos = DataSize = 0;
  58.368 +        }
  58.369 +        else if (skippedBytes <= 0)
  58.370 +            skippedBytes = -1;
  58.371 +    }
  58.372 +    return skippedBytes;
  58.373 +}
  58.374 +
  58.375 +int     BufferedFile::BytesAvailable()
  58.376 +{
  58.377 +    int available = pFile->BytesAvailable();
  58.378 +    // Adjust available size based on buffers
  58.379 +    switch(BufferMode)
  58.380 +    {
  58.381 +        case ReadBuffer:
  58.382 +            available += DataSize-Pos;
  58.383 +            break;
  58.384 +        case WriteBuffer:
  58.385 +            available -= Pos;
  58.386 +            if (available<0)
  58.387 +                available= 0;
  58.388 +            break;
  58.389 +        default:
  58.390 +            break;
  58.391 +    }
  58.392 +    return available;
  58.393 +}
  58.394 +
  58.395 +bool    BufferedFile::Flush()
  58.396 +{
  58.397 +    FlushBuffer();
  58.398 +    return pFile->Flush();
  58.399 +}
  58.400 +
  58.401 +// Seeking could be optimized better..
  58.402 +int     BufferedFile::Seek(int offset, int origin)
  58.403 +{    
  58.404 +    if (BufferMode == ReadBuffer)
  58.405 +    {
  58.406 +        if (origin == Seek_Cur)
  58.407 +        {
  58.408 +            // Seek can fall either before or after Pos in the buffer,
  58.409 +            // but it must be within bounds.
  58.410 +            if (((unsigned(offset) + Pos)) <= DataSize)
  58.411 +            {
  58.412 +                Pos += offset;
  58.413 +                return int (FilePos - DataSize + Pos);
  58.414 +            }
  58.415 +
  58.416 +            // Lightweight buffer "Flush". We do this to avoid an extra seek
  58.417 +            // back operation which would take place if we called FlushBuffer directly.
  58.418 +            origin = Seek_Set;
  58.419 +            OVR_ASSERT(((FilePos - DataSize + Pos) + (uint64_t)offset) < ~(uint64_t)0);
  58.420 +            offset = (int)(FilePos - DataSize + Pos) + offset;
  58.421 +            Pos = DataSize = 0;
  58.422 +        }
  58.423 +        else if (origin == Seek_Set)
  58.424 +        {
  58.425 +            if (((unsigned)offset - (FilePos-DataSize)) <= DataSize)
  58.426 +            {
  58.427 +                OVR_ASSERT((FilePos-DataSize) < ~(uint64_t)0);
  58.428 +                Pos = (unsigned)offset - (unsigned)(FilePos-DataSize);
  58.429 +                return offset;
  58.430 +            }
  58.431 +            Pos = DataSize = 0;
  58.432 +        }
  58.433 +        else
  58.434 +        {
  58.435 +            FlushBuffer();
  58.436 +        }
  58.437 +    }
  58.438 +    else
  58.439 +    {
  58.440 +        FlushBuffer();
  58.441 +    }    
  58.442 +
  58.443 +    /*
  58.444 +    // Old Seek Logic
  58.445 +    if (origin == Seek_Cur && offset + Pos < DataSize)
  58.446 +    {
  58.447 +        //OVR_ASSERT((FilePos - DataSize) >= (FilePos - DataSize + Pos + offset));
  58.448 +        Pos += offset;
  58.449 +        OVR_ASSERT(int (Pos) >= 0);
  58.450 +        return int (FilePos - DataSize + Pos);
  58.451 +    }
  58.452 +    else if (origin == Seek_Set && unsigned(offset) >= FilePos - DataSize && unsigned(offset) < FilePos)
  58.453 +    {
  58.454 +        Pos = unsigned(offset - FilePos + DataSize);
  58.455 +        OVR_ASSERT(int (Pos) >= 0);
  58.456 +        return int (FilePos - DataSize + Pos);
  58.457 +    }   
  58.458 +    
  58.459 +    FlushBuffer();
  58.460 +    */
  58.461 +
  58.462 +
  58.463 +    FilePos = pFile->Seek(offset,origin);
  58.464 +    return int (FilePos);
  58.465 +}
  58.466 +
  58.467 +int64_t BufferedFile::LSeek(int64_t offset, int origin)
  58.468 +{
  58.469 +    if (BufferMode == ReadBuffer)
  58.470 +    {
  58.471 +        if (origin == Seek_Cur)
  58.472 +        {
  58.473 +            // Seek can fall either before or after Pos in the buffer,
  58.474 +            // but it must be within bounds.
  58.475 +            if (((unsigned(offset) + Pos)) <= DataSize)
  58.476 +            {
  58.477 +                Pos += (unsigned)offset;
  58.478 +                return int64_t(FilePos - DataSize + Pos);
  58.479 +            }
  58.480 +
  58.481 +            // Lightweight buffer "Flush". We do this to avoid an extra seek
  58.482 +            // back operation which would take place if we called FlushBuffer directly.
  58.483 +            origin = Seek_Set;            
  58.484 +            offset = (int64_t)(FilePos - DataSize + Pos) + offset;
  58.485 +            Pos = DataSize = 0;
  58.486 +        }
  58.487 +        else if (origin == Seek_Set)
  58.488 +        {
  58.489 +            if (((uint64_t)offset - (FilePos-DataSize)) <= DataSize)
  58.490 +            {                
  58.491 +                Pos = (unsigned)((uint64_t)offset - (FilePos-DataSize));
  58.492 +                return offset;
  58.493 +            }
  58.494 +            Pos = DataSize = 0;
  58.495 +        }
  58.496 +        else
  58.497 +        {
  58.498 +            FlushBuffer();
  58.499 +        }
  58.500 +    }
  58.501 +    else
  58.502 +    {
  58.503 +        FlushBuffer();
  58.504 +    }
  58.505 +
  58.506 +/*
  58.507 +    OVR_ASSERT(BufferMode != NoBuffer);
  58.508 +
  58.509 +    if (origin == Seek_Cur && offset + Pos < DataSize)
  58.510 +    {
  58.511 +        Pos += int (offset);
  58.512 +        return FilePos - DataSize + Pos;
  58.513 +    }
  58.514 +    else if (origin == Seek_Set && offset >= int64_t(FilePos - DataSize) && offset < int64_t(FilePos))
  58.515 +    {
  58.516 +        Pos = unsigned(offset - FilePos + DataSize);
  58.517 +        return FilePos - DataSize + Pos;
  58.518 +    }
  58.519 +
  58.520 +    FlushBuffer();
  58.521 +    */
  58.522 +
  58.523 +    FilePos = pFile->LSeek(offset,origin);
  58.524 +    return FilePos;
  58.525 +}
  58.526 +
  58.527 +int     BufferedFile::CopyFromStream(File *pstream, int byteSize)
  58.528 +{
  58.529 +    // We can't rely on overridden Write()
  58.530 +    // because delegation doesn't override virtual pointers
  58.531 +    // So, just re-implement
  58.532 +    uint8_t*  buff = new uint8_t[0x4000];
  58.533 +    int     count = 0;
  58.534 +    int     szRequest, szRead, szWritten;
  58.535 +
  58.536 +    while(byteSize)
  58.537 +    {
  58.538 +        szRequest = (byteSize > int(sizeof(buff))) ? int(sizeof(buff)) : byteSize;
  58.539 +
  58.540 +        szRead    = pstream->Read(buff,szRequest);
  58.541 +        szWritten = 0;
  58.542 +        if (szRead > 0)
  58.543 +            szWritten = Write(buff,szRead);
  58.544 +
  58.545 +        count   +=szWritten;
  58.546 +        byteSize-=szWritten;
  58.547 +        if (szWritten < szRequest)
  58.548 +            break;
  58.549 +    }
  58.550 +
  58.551 +	delete[] buff;
  58.552 +
  58.553 +    return count;
  58.554 +}
  58.555 +
  58.556 +// Closing files
  58.557 +bool    BufferedFile::Close()
  58.558 +{
  58.559 +    switch(BufferMode)
  58.560 +    {
  58.561 +        case WriteBuffer:
  58.562 +            FlushBuffer();
  58.563 +            break;
  58.564 +        case ReadBuffer:
  58.565 +            // No need to seek back on close
  58.566 +            BufferMode = NoBuffer;
  58.567 +            break;
  58.568 +        default:
  58.569 +            break;
  58.570 +    }
  58.571 +    return pFile->Close();
  58.572 +}
  58.573 +
  58.574 +
  58.575 +// ***** Global path helpers
  58.576 +
  58.577 +// Find trailing short filename in a path.
  58.578 +const char* OVR_CDECL GetShortFilename(const char* purl)
  58.579 +{    
  58.580 +    size_t len = OVR_strlen(purl);
  58.581 +    for (size_t i=len; i>0; i--) 
  58.582 +        if (purl[i]=='\\' || purl[i]=='/')
  58.583 +            return purl+i+1;
  58.584 +    return purl;
  58.585 +}
  58.586 +
  58.587 +} // OVR
  58.588 +
    59.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    59.2 +++ b/LibOVR/Src/Kernel/OVR_File.h	Wed Jan 14 06:51:16 2015 +0200
    59.3 @@ -0,0 +1,530 @@
    59.4 +/************************************************************************************
    59.5 +
    59.6 +PublicHeader:   Kernel
    59.7 +Filename    :   OVR_File.h
    59.8 +Content     :   Header for all internal file management - functions and structures
    59.9 +                to be inherited by OS specific subclasses.
   59.10 +Created     :   September 19, 2012
   59.11 +Notes       : 
   59.12 +
   59.13 +Notes       :   errno may not be preserved across use of BaseFile member functions
   59.14 +            :   Directories cannot be deleted while files opened from them are in use
   59.15 +                (For the GetFullName function)
   59.16 +
   59.17 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   59.18 +
   59.19 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
   59.20 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
   59.21 +which is provided at the time of installation or download, or which 
   59.22 +otherwise accompanies this software in either electronic or hard copy form.
   59.23 +
   59.24 +You may obtain a copy of the License at
   59.25 +
   59.26 +http://www.oculusvr.com/licenses/LICENSE-3.2 
   59.27 +
   59.28 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
   59.29 +distributed under the License is distributed on an "AS IS" BASIS,
   59.30 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   59.31 +See the License for the specific language governing permissions and
   59.32 +limitations under the License.
   59.33 +
   59.34 +************************************************************************************/
   59.35 +
   59.36 +#ifndef OVR_File_h
   59.37 +#define OVR_File_h
   59.38 +
   59.39 +#include "OVR_RefCount.h"
   59.40 +#include "OVR_Std.h"
   59.41 +#include "OVR_Alg.h"
   59.42 +
   59.43 +#include <stdio.h>
   59.44 +#include "OVR_String.h"
   59.45 +
   59.46 +namespace OVR {
   59.47 +
   59.48 +// ***** Declared classes
   59.49 +class   FileConstants;
   59.50 +class   File;
   59.51 +class   DelegatedFile;
   59.52 +class   BufferedFile;
   59.53 +
   59.54 +
   59.55 +// ***** Flags for File & Directory accesses
   59.56 +
   59.57 +class FileConstants
   59.58 +{
   59.59 +public:
   59.60 +
   59.61 +    // *** File open flags
   59.62 +    enum OpenFlags
   59.63 +    {
   59.64 +        Open_Read       = 1,
   59.65 +        Open_Write      = 2,
   59.66 +        Open_ReadWrite  = 3,
   59.67 +
   59.68 +        // Opens file and truncates it to zero length
   59.69 +        // - file must have write permission
   59.70 +        // - when used with Create, it opens an existing 
   59.71 +        //   file and empties it or creates a new file
   59.72 +        Open_Truncate   = 4,
   59.73 +
   59.74 +        // Creates and opens new file 
   59.75 +        // - does not erase contents if file already
   59.76 +        //   exists unless combined with Truncate
   59.77 +        Open_Create     = 8,
   59.78 +
   59.79 +         // Returns an error value if the file already exists
   59.80 +        Open_CreateOnly = 24,
   59.81 +
   59.82 +        // Open file with buffering
   59.83 +        Open_Buffered    = 32
   59.84 +    };
   59.85 +
   59.86 +    // *** File Mode flags
   59.87 +    enum Modes
   59.88 +    {
   59.89 +        Mode_Read       = 0444,
   59.90 +        Mode_Write      = 0222,
   59.91 +        Mode_Execute    = 0111,
   59.92 +
   59.93 +        Mode_ReadWrite  = 0666
   59.94 +    };
   59.95 +
   59.96 +    // *** Seek operations
   59.97 +    enum SeekOps
   59.98 +    {
   59.99 +        Seek_Set        = 0,
  59.100 +        Seek_Cur        = 1,
  59.101 +        Seek_End        = 2
  59.102 +    };
  59.103 +
  59.104 +    // *** Errors
  59.105 +    enum Errors
  59.106 +    {
  59.107 +        Error_FileNotFound  = 0x1001,
  59.108 +        Error_Access        = 0x1002,
  59.109 +        Error_IOError       = 0x1003,
  59.110 +        Error_DiskFull      = 0x1004
  59.111 +    };
  59.112 +};
  59.113 +
  59.114 +
  59.115 +//-----------------------------------------------------------------------------------
  59.116 +// ***** File Class
  59.117 +
  59.118 +// The pure virtual base random-access file
  59.119 +// This is a base class to all files
  59.120 +
  59.121 +class File : public RefCountBase<File>, public FileConstants
  59.122 +{   
  59.123 +public:
  59.124 +    File() { }
  59.125 +    // ** Location Information
  59.126 +
  59.127 +    // Returns a file name path relative to the 'reference' directory
  59.128 +    // This is often a path that was used to create a file
  59.129 +    // (this is not a global path, global path can be obtained with help of directory)
  59.130 +    virtual const char* GetFilePath() = 0;
  59.131 +                                                                                        
  59.132 +
  59.133 +    // ** File Information
  59.134 +
  59.135 +    // Return 1 if file's usable (open)
  59.136 +    virtual bool        IsValid() = 0;
  59.137 +    // Return 1 if file's writable, otherwise 0                                         
  59.138 +    virtual bool        IsWritable() = 0;
  59.139 +                                                                                        
  59.140 +    // Return position
  59.141 +    virtual int         Tell() = 0;
  59.142 +    virtual int64_t     LTell() = 0;
  59.143 +    
  59.144 +    // File size                                                                        
  59.145 +    virtual int         GetLength() = 0;
  59.146 +    virtual int64_t     LGetLength() = 0;
  59.147 +                                                                                        
  59.148 +    // Returns file stats                                                               
  59.149 +    // 0 for failure                                                                    
  59.150 +    //virtual bool      Stat(FileStats *pfs) = 0;
  59.151 +                                                                                        
  59.152 +    // Return errno-based error code                                                    
  59.153 +    // Useful if any other function failed                                              
  59.154 +    virtual int         GetErrorCode() = 0;
  59.155 +                                                                                        
  59.156 +                                                                                        
  59.157 +    // ** Stream implementation & I/O
  59.158 +
  59.159 +    // Blocking write, will write in the given number of bytes to the stream
  59.160 +    // Returns : -1 for error
  59.161 +    //           Otherwise number of bytes read 
  59.162 +    virtual int         Write(const uint8_t *pbufer, int numBytes) = 0;
  59.163 +    // Blocking read, will read in the given number of bytes or less from the stream
  59.164 +    // Returns : -1 for error
  59.165 +    //           Otherwise number of bytes read,
  59.166 +    //           if 0 or < numBytes, no more bytes available; end of file or the other side of stream is closed
  59.167 +    virtual int         Read(uint8_t *pbufer, int numBytes) = 0;
  59.168 +
  59.169 +    // Skips (ignores) a given # of bytes
  59.170 +    // Same return values as Read
  59.171 +    virtual int         SkipBytes(int numBytes) = 0;
  59.172 +        
  59.173 +    // Returns the number of bytes available to read from a stream without blocking
  59.174 +    // For a file, this should generally be number of bytes to the end
  59.175 +    virtual int         BytesAvailable() = 0;
  59.176 +
  59.177 +    // Causes any implementation's buffered data to be delivered to destination
  59.178 +    // Return 0 for error
  59.179 +    virtual bool        Flush() = 0;
  59.180 +                                                                                            
  59.181 +
  59.182 +    // Need to provide a more optimized implementation that doe snot necessarily involve a lot of seeking
  59.183 +    inline bool         IsEOF() { return !BytesAvailable(); }
  59.184 +    
  59.185 +
  59.186 +    // Seeking                                                                              
  59.187 +    // Returns new position, -1 for error                                                   
  59.188 +    virtual int         Seek(int offset, int origin=Seek_Set) = 0;
  59.189 +    virtual int64_t     LSeek(int64_t offset, int origin=Seek_Set) = 0;
  59.190 +    // Seek simplification
  59.191 +    int                 SeekToBegin()           {return Seek(0); }
  59.192 +    int                 SeekToEnd()             {return Seek(0,Seek_End); }
  59.193 +    int                 Skip(int numBytes)     {return Seek(numBytes,Seek_Cur); }
  59.194 +                        
  59.195 +
  59.196 +    // Appends other file data from a stream
  59.197 +    // Return -1 for error, else # of bytes written
  59.198 +    virtual int         CopyFromStream(File *pstream, int byteSize) = 0;
  59.199 +
  59.200 +    // Closes the file
  59.201 +    // After close, file cannot be accessed 
  59.202 +    virtual bool        Close() = 0;
  59.203 +
  59.204 +
  59.205 +    // ***** Inlines for convenient primitive type serialization
  59.206 +
  59.207 +    // Read/Write helpers
  59.208 +private:
  59.209 +    uint64_t  PRead64()           { uint64_t v = 0; Read((uint8_t*)&v, 8); return v; }
  59.210 +    uint32_t  PRead32()           { uint32_t v = 0; Read((uint8_t*)&v, 4); return v; }
  59.211 +    uint16_t  PRead16()           { uint16_t v = 0; Read((uint8_t*)&v, 2); return v; }
  59.212 +    uint8_t PRead8()            { uint8_t  v = 0; Read((uint8_t*)&v, 1); return v; }
  59.213 +    void    PWrite64(uint64_t v)  { Write((uint8_t*)&v, 8); }
  59.214 +    void    PWrite32(uint32_t v)  { Write((uint8_t*)&v, 4); }
  59.215 +    void    PWrite16(uint16_t v)  { Write((uint8_t*)&v, 2); }
  59.216 +    void    PWrite8(uint8_t v)  { Write((uint8_t*)&v, 1); }
  59.217 +
  59.218 +public:
  59.219 +
  59.220 +    // Writing primitive types - Little Endian
  59.221 +    inline void    WriteUByte(uint8_t v)       { PWrite8((uint8_t)Alg::ByteUtil::SystemToLE(v));     }
  59.222 +    inline void    WriteSByte(int8_t v)        { PWrite8((uint8_t)Alg::ByteUtil::SystemToLE(v));     }
  59.223 +    inline void    WriteUInt8(uint8_t v)       { PWrite8((uint8_t)Alg::ByteUtil::SystemToLE(v));     }
  59.224 +    inline void    WriteSInt8(int8_t v)        { PWrite8((uint8_t)Alg::ByteUtil::SystemToLE(v));     }
  59.225 +    inline void    WriteUInt16(uint16_t v)       { PWrite16((uint16_t)Alg::ByteUtil::SystemToLE(v));   }
  59.226 +    inline void    WriteSInt16(int16_t v)       { PWrite16((uint16_t)Alg::ByteUtil::SystemToLE(v));   }
  59.227 +    inline void    WriteUInt32(uint32_t v)       { PWrite32((uint32_t)Alg::ByteUtil::SystemToLE(v));   }
  59.228 +    inline void    WriteSInt32(int32_t v)       { PWrite32((uint32_t)Alg::ByteUtil::SystemToLE(v));   }
  59.229 +    inline void    WriteUInt64(uint64_t v)       { PWrite64((uint64_t)Alg::ByteUtil::SystemToLE(v));   }
  59.230 +    inline void    WriteSInt64(int64_t v)       { PWrite64((uint64_t)Alg::ByteUtil::SystemToLE(v));   }
  59.231 +    inline void    WriteFloat(float v)         { v = Alg::ByteUtil::SystemToLE(v); Write((uint8_t*)&v, 4); } 
  59.232 +    inline void    WriteDouble(double v)       { v = Alg::ByteUtil::SystemToLE(v); Write((uint8_t*)&v, 8); }
  59.233 +    // Writing primitive types - Big Endian
  59.234 +    inline void    WriteUByteBE(uint8_t v)     { PWrite8((uint8_t)Alg::ByteUtil::SystemToBE(v));     }
  59.235 +    inline void    WriteSByteBE(int8_t v)      { PWrite8((uint8_t)Alg::ByteUtil::SystemToBE(v));     }
  59.236 +    inline void    WriteUInt8BE(uint16_t v)      { PWrite8((uint8_t)Alg::ByteUtil::SystemToBE(v));     }
  59.237 +    inline void    WriteSInt8BE(int16_t v)      { PWrite8((uint8_t)Alg::ByteUtil::SystemToBE(v));     }
  59.238 +    inline void    WriteUInt16BE(uint16_t v)     { PWrite16((uint16_t)Alg::ByteUtil::SystemToBE(v));   }
  59.239 +    inline void    WriteSInt16BE(uint16_t v)     { PWrite16((uint16_t)Alg::ByteUtil::SystemToBE(v));   }
  59.240 +    inline void    WriteUInt32BE(uint32_t v)     { PWrite32((uint32_t)Alg::ByteUtil::SystemToBE(v));   }
  59.241 +    inline void    WriteSInt32BE(uint32_t v)     { PWrite32((uint32_t)Alg::ByteUtil::SystemToBE(v));   }
  59.242 +    inline void    WriteUInt64BE(uint64_t v)     { PWrite64((uint64_t)Alg::ByteUtil::SystemToBE(v));   }
  59.243 +    inline void    WriteSInt64BE(uint64_t v)     { PWrite64((uint64_t)Alg::ByteUtil::SystemToBE(v));   }
  59.244 +    inline void    WriteFloatBE(float v)       { v = Alg::ByteUtil::SystemToBE(v); Write((uint8_t*)&v, 4); }
  59.245 +    inline void    WriteDoubleBE(double v)     { v = Alg::ByteUtil::SystemToBE(v); Write((uint8_t*)&v, 8); }
  59.246 +        
  59.247 +    // Reading primitive types - Little Endian
  59.248 +    inline uint8_t ReadUByte()                 { return (uint8_t)Alg::ByteUtil::LEToSystem(PRead8());    }
  59.249 +    inline int8_t  ReadSByte()                 { return (int8_t)Alg::ByteUtil::LEToSystem(PRead8());    }
  59.250 +    inline uint8_t ReadUInt8()                 { return (uint8_t)Alg::ByteUtil::LEToSystem(PRead8());    }
  59.251 +    inline int8_t  ReadSInt8()                 { return (int8_t)Alg::ByteUtil::LEToSystem(PRead8());    }
  59.252 +    inline uint16_t  ReadUInt16()                { return (uint16_t)Alg::ByteUtil::LEToSystem(PRead16());  }
  59.253 +    inline int16_t ReadSInt16()                { return (int16_t)Alg::ByteUtil::LEToSystem(PRead16());  }
  59.254 +    inline uint32_t  ReadUInt32()                { return (uint32_t)Alg::ByteUtil::LEToSystem(PRead32());  }
  59.255 +    inline int32_t ReadSInt32()                { return (int32_t)Alg::ByteUtil::LEToSystem(PRead32());  }
  59.256 +    inline uint64_t  ReadUInt64()                { return (uint64_t)Alg::ByteUtil::LEToSystem(PRead64());  }
  59.257 +    inline int64_t ReadSInt64()                { return (int64_t)Alg::ByteUtil::LEToSystem(PRead64());  }
  59.258 +    inline float   ReadFloat()                 { float v = 0.0f; Read((uint8_t*)&v, 4); return Alg::ByteUtil::LEToSystem(v); }
  59.259 +    inline double  ReadDouble()                { double v = 0.0; Read((uint8_t*)&v, 8); return Alg::ByteUtil::LEToSystem(v); }
  59.260 +    // Reading primitive types - Big Endian
  59.261 +    inline uint8_t ReadUByteBE()               { return (uint8_t)Alg::ByteUtil::BEToSystem(PRead8());    }
  59.262 +    inline int8_t  ReadSByteBE()               { return (int8_t)Alg::ByteUtil::BEToSystem(PRead8());    }
  59.263 +    inline uint8_t ReadUInt8BE()               { return (uint8_t)Alg::ByteUtil::BEToSystem(PRead8());    }
  59.264 +    inline int8_t  ReadSInt8BE()               { return (int8_t)Alg::ByteUtil::BEToSystem(PRead8());    }
  59.265 +    inline uint16_t  ReadUInt16BE()              { return (uint16_t)Alg::ByteUtil::BEToSystem(PRead16());  }
  59.266 +    inline int16_t ReadSInt16BE()              { return (int16_t)Alg::ByteUtil::BEToSystem(PRead16());  }
  59.267 +    inline uint32_t  ReadUInt32BE()              { return (uint32_t)Alg::ByteUtil::BEToSystem(PRead32());  }
  59.268 +    inline int32_t ReadSInt32BE()              { return (int32_t)Alg::ByteUtil::BEToSystem(PRead32());  }
  59.269 +    inline uint64_t  ReadUInt64BE()              { return (uint64_t)Alg::ByteUtil::BEToSystem(PRead64());  }
  59.270 +    inline int64_t ReadSInt64BE()              { return (int64_t)Alg::ByteUtil::BEToSystem(PRead64());  }
  59.271 +    inline float   ReadFloatBE()               { float v = 0.0f; Read((uint8_t*)&v, 4); return Alg::ByteUtil::BEToSystem(v); }
  59.272 +    inline double  ReadDoubleBE()              { double v = 0.0; Read((uint8_t*)&v, 8); return Alg::ByteUtil::BEToSystem(v); }
  59.273 +};
  59.274 +
  59.275 +
  59.276 +// *** Delegated File
  59.277 +
  59.278 +class DelegatedFile : public File
  59.279 +{
  59.280 +protected:
  59.281 +    // Delegating file pointer
  59.282 +    Ptr<File>     pFile;
  59.283 +
  59.284 +    // Hidden default constructor
  59.285 +    DelegatedFile() : pFile(0)                             { }
  59.286 +    DelegatedFile(const DelegatedFile &source) : File()    { OVR_UNUSED(source); }
  59.287 +public:
  59.288 +    // Constructors
  59.289 +    DelegatedFile(File *pfile) : pFile(pfile)     { }
  59.290 +
  59.291 +    // ** Location Information  
  59.292 +    virtual const char* GetFilePath()                               { return pFile->GetFilePath(); }    
  59.293 +
  59.294 +    // ** File Information                                                      
  59.295 +    virtual bool        IsValid()                                   { return pFile && pFile->IsValid(); }   
  59.296 +    virtual bool        IsWritable()                                { return pFile->IsWritable(); }
  59.297 +//  virtual bool        IsRecoverable()                             { return pFile->IsRecoverable(); }          
  59.298 +                                                                    
  59.299 +    virtual int         Tell()                                      { return pFile->Tell(); }
  59.300 +    virtual int64_t     LTell()                                     { return pFile->LTell(); }
  59.301 +    
  59.302 +    virtual int         GetLength()                                 { return pFile->GetLength(); }
  59.303 +    virtual int64_t     LGetLength()                                { return pFile->LGetLength(); }
  59.304 +    
  59.305 +    //virtual bool      Stat(FileStats *pfs)                        { return pFile->Stat(pfs); }
  59.306 +    
  59.307 +    virtual int         GetErrorCode()                              { return pFile->GetErrorCode(); }
  59.308 +    
  59.309 +    // ** Stream implementation & I/O
  59.310 +    virtual int         Write(const uint8_t *pbuffer, int numBytes)   { return pFile->Write(pbuffer,numBytes); }  
  59.311 +    virtual int         Read(uint8_t *pbuffer, int numBytes)          { return pFile->Read(pbuffer,numBytes); }   
  59.312 +    
  59.313 +    virtual int         SkipBytes(int numBytes)                     { return pFile->SkipBytes(numBytes); }      
  59.314 +    
  59.315 +    virtual int         BytesAvailable()                            { return pFile->BytesAvailable(); } 
  59.316 +    
  59.317 +    virtual bool        Flush()                                     { return pFile->Flush(); }
  59.318 +                                                                    
  59.319 +    // Seeking                                                      
  59.320 +    virtual int         Seek(int offset, int origin=Seek_Set)       { return pFile->Seek(offset,origin); }
  59.321 +    virtual int64_t     LSeek(int64_t offset, int origin=Seek_Set)   { return pFile->LSeek(offset,origin); }
  59.322 +
  59.323 +    virtual int         CopyFromStream(File *pstream, int byteSize) { return pFile->CopyFromStream(pstream,byteSize); }
  59.324 +                        
  59.325 +    // Closing the file 
  59.326 +    virtual bool        Close()                                     { return pFile->Close(); }    
  59.327 +};
  59.328 +
  59.329 +
  59.330 +//-----------------------------------------------------------------------------------
  59.331 +// ***** Buffered File
  59.332 +
  59.333 +// This file class adds buffering to an existing file
  59.334 +// Buffered file never fails by itself; if there's not
  59.335 +// enough memory for buffer, no buffer's used
  59.336 +
  59.337 +class BufferedFile : public DelegatedFile
  59.338 +{   
  59.339 +protected:  
  59.340 +    enum BufferModeType
  59.341 +    {
  59.342 +        NoBuffer,
  59.343 +        ReadBuffer,
  59.344 +        WriteBuffer
  59.345 +    };
  59.346 +
  59.347 +    // Buffer & the mode it's in
  59.348 +    uint8_t*        pBuffer;
  59.349 +    BufferModeType  BufferMode;
  59.350 +    // Position in buffer
  59.351 +    unsigned        Pos;
  59.352 +    // Data in buffer if reading
  59.353 +    unsigned        DataSize;
  59.354 +    // Underlying file position 
  59.355 +    uint64_t        FilePos;
  59.356 +
  59.357 +    // Initializes buffering to a certain mode
  59.358 +    bool    SetBufferMode(BufferModeType mode);
  59.359 +    // Flushes buffer
  59.360 +    // WriteBuffer - write data to disk, ReadBuffer - reset buffer & fix file position  
  59.361 +    void    FlushBuffer();
  59.362 +    // Loads data into ReadBuffer
  59.363 +    // WARNING: Right now LoadBuffer() assumes the buffer's empty
  59.364 +    void    LoadBuffer();
  59.365 +
  59.366 +    // Hidden constructor
  59.367 +    BufferedFile();
  59.368 +    BufferedFile(const BufferedFile &) : DelegatedFile(), pBuffer(NULL), BufferMode(NoBuffer), Pos(0), DataSize(0), FilePos(0) { }
  59.369 +
  59.370 +public:
  59.371 +
  59.372 +    // Constructor
  59.373 +    // - takes another file as source
  59.374 +    BufferedFile(File *pfile);
  59.375 +    ~BufferedFile();
  59.376 +    
  59.377 +    
  59.378 +    // ** Overridden functions
  59.379 +
  59.380 +    // We override all the functions that can possibly
  59.381 +    // require buffer mode switch, flush, or extra calculations
  59.382 +    virtual int         Tell();
  59.383 +    virtual int64_t     LTell();
  59.384 +
  59.385 +    virtual int         GetLength();
  59.386 +    virtual int64_t     LGetLength();
  59.387 +
  59.388 +//  virtual bool        Stat(GFileStats *pfs);  
  59.389 +
  59.390 +    virtual int         Write(const uint8_t *pbufer, int numBytes);
  59.391 +    virtual int         Read(uint8_t *pbufer, int numBytes);
  59.392 +
  59.393 +    virtual int         SkipBytes(int numBytes);
  59.394 +
  59.395 +    virtual int         BytesAvailable();
  59.396 +
  59.397 +    virtual bool        Flush();
  59.398 +
  59.399 +    virtual int         Seek(int offset, int origin=Seek_Set);
  59.400 +    virtual int64_t     LSeek(int64_t offset, int origin=Seek_Set);
  59.401 +
  59.402 +    virtual int         CopyFromStream(File *pstream, int byteSize);
  59.403 +    
  59.404 +    virtual bool        Close();    
  59.405 +};                          
  59.406 +
  59.407 +
  59.408 +//-----------------------------------------------------------------------------------
  59.409 +// ***** Memory File
  59.410 +
  59.411 +class MemoryFile : public File
  59.412 +{
  59.413 +public:
  59.414 +
  59.415 +    const char* GetFilePath()       { return FilePath.ToCStr(); }
  59.416 +
  59.417 +    bool        IsValid()           { return Valid; }
  59.418 +    bool        IsWritable()        { return false; }
  59.419 +
  59.420 +    bool        Flush()             { return true; }
  59.421 +    int         GetErrorCode()      { return 0; }
  59.422 +
  59.423 +    int         Tell()              { return FileIndex; }
  59.424 +    int64_t     LTell()             { return (int64_t) FileIndex; }
  59.425 +
  59.426 +    int         GetLength()         { return FileSize; }
  59.427 +    int64_t     LGetLength()        { return (int64_t) FileSize; }
  59.428 +
  59.429 +    bool        Close()
  59.430 +    {
  59.431 +        Valid = false;
  59.432 +        return false;
  59.433 +    }
  59.434 +
  59.435 +    int         CopyFromStream(File *pstream, int byteSize)
  59.436 +    {   OVR_UNUSED2(pstream, byteSize);
  59.437 +        return 0;
  59.438 +    }
  59.439 +
  59.440 +    int         Write(const uint8_t *pbuffer, int numBytes)
  59.441 +    {   OVR_UNUSED2(pbuffer, numBytes);
  59.442 +        return 0;
  59.443 +    }
  59.444 +
  59.445 +    int         Read(uint8_t *pbufer, int numBytes)
  59.446 +    {
  59.447 +        if (FileIndex + numBytes > FileSize)
  59.448 +        {
  59.449 +            numBytes = FileSize - FileIndex;
  59.450 +        }
  59.451 +
  59.452 +        if (numBytes > 0)
  59.453 +        {
  59.454 +            ::memcpy (pbufer, &FileData [FileIndex], numBytes);
  59.455 +
  59.456 +            FileIndex += numBytes;
  59.457 +        }
  59.458 +
  59.459 +        return numBytes;
  59.460 +    }
  59.461 +
  59.462 +    int         SkipBytes(int numBytes)
  59.463 +    {
  59.464 +        if (FileIndex + numBytes > FileSize)
  59.465 +        {
  59.466 +            numBytes = FileSize - FileIndex;
  59.467 +        }
  59.468 +
  59.469 +        FileIndex += numBytes;
  59.470 +
  59.471 +        return numBytes;
  59.472 +    }
  59.473 +
  59.474 +    int         BytesAvailable()
  59.475 +    {
  59.476 +        return (FileSize - FileIndex);
  59.477 +    }
  59.478 +
  59.479 +    int         Seek(int offset, int origin = Seek_Set)
  59.480 +    {
  59.481 +        switch (origin)
  59.482 +        {
  59.483 +        case Seek_Set : FileIndex  = offset;               break;
  59.484 +        case Seek_Cur : FileIndex += offset;               break;
  59.485 +        case Seek_End : FileIndex  = FileSize - offset;  break;
  59.486 +        }
  59.487 +
  59.488 +        return FileIndex;
  59.489 +    }
  59.490 +
  59.491 +    int64_t     LSeek(int64_t offset, int origin = Seek_Set)
  59.492 +    {
  59.493 +        return (int64_t) Seek((int) offset, origin);
  59.494 +    }
  59.495 +
  59.496 +public:
  59.497 +
  59.498 +    MemoryFile (const String& fileName, const uint8_t *pBuffer, int buffSize)
  59.499 +        : FilePath(fileName)
  59.500 +    {
  59.501 +        FileData  = pBuffer;
  59.502 +        FileSize  = buffSize;
  59.503 +        FileIndex = 0;
  59.504 +        Valid     = (!fileName.IsEmpty() && pBuffer && buffSize > 0) ? true : false;
  59.505 +    }
  59.506 +
  59.507 +    // pfileName should be encoded as UTF-8 to support international file names.
  59.508 +    MemoryFile (const char* pfileName, const uint8_t *pBuffer, int buffSize)
  59.509 +        : FilePath(pfileName)
  59.510 +    {
  59.511 +        FileData  = pBuffer;
  59.512 +        FileSize  = buffSize;
  59.513 +        FileIndex = 0;
  59.514 +        Valid     = (pfileName && pBuffer && buffSize > 0) ? true : false;
  59.515 +    }
  59.516 +private:
  59.517 +
  59.518 +    String       FilePath;
  59.519 +    const uint8_t *FileData;
  59.520 +    int          FileSize;
  59.521 +    int          FileIndex;
  59.522 +    bool         Valid;
  59.523 +};
  59.524 +
  59.525 +
  59.526 +// ***** Global path helpers
  59.527 +
  59.528 +// Find trailing short filename in a path.
  59.529 +const char* OVR_CDECL GetShortFilename(const char* purl);
  59.530 +
  59.531 +} // OVR
  59.532 +
  59.533 +#endif
    60.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    60.2 +++ b/LibOVR/Src/Kernel/OVR_FileFILE.cpp	Wed Jan 14 06:51:16 2015 +0200
    60.3 @@ -0,0 +1,609 @@
    60.4 +/**************************************************************************
    60.5 +
    60.6 +Filename    :   OVR_FileFILE.cpp
    60.7 +Content     :   File wrapper class implementation (Win32)
    60.8 +
    60.9 +Created     :   April 5, 1999
   60.10 +Authors     :   Michael Antonov
   60.11 +
   60.12 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   60.13 +
   60.14 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
   60.15 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
   60.16 +which is provided at the time of installation or download, or which 
   60.17 +otherwise accompanies this software in either electronic or hard copy form.
   60.18 +
   60.19 +You may obtain a copy of the License at
   60.20 +
   60.21 +http://www.oculusvr.com/licenses/LICENSE-3.2 
   60.22 +
   60.23 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
   60.24 +distributed under the License is distributed on an "AS IS" BASIS,
   60.25 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   60.26 +See the License for the specific language governing permissions and
   60.27 +limitations under the License.
   60.28 +
   60.29 +**************************************************************************/
   60.30 +
   60.31 +#define  GFILE_CXX
   60.32 +
   60.33 +#include "OVR_Types.h"
   60.34 +#include "OVR_Log.h"
   60.35 +
   60.36 +// Standard C library (Captain Obvious guarantees!)
   60.37 +#include <stdio.h>
   60.38 +#ifndef OVR_OS_WINCE
   60.39 +#include <sys/stat.h>
   60.40 +#endif
   60.41 +
   60.42 +#include "OVR_SysFile.h"
   60.43 +
   60.44 +#ifndef OVR_OS_WINCE
   60.45 +#include <errno.h>
   60.46 +#endif
   60.47 +
   60.48 +namespace OVR {
   60.49 +
   60.50 +// ***** File interface
   60.51 +
   60.52 +// ***** FILEFile - C streams file
   60.53 +
   60.54 +static int SFerror ()
   60.55 +{
   60.56 +    if (errno == ENOENT)
   60.57 +        return FileConstants::Error_FileNotFound;
   60.58 +    else if (errno == EACCES || errno == EPERM)
   60.59 +        return FileConstants::Error_Access;
   60.60 +    else if (errno == ENOSPC)
   60.61 +        return FileConstants::Error_DiskFull;
   60.62 +    else
   60.63 +        return FileConstants::Error_IOError;
   60.64 +};
   60.65 +
   60.66 +#if defined(OVR_OS_WIN32)
   60.67 +#define WIN32_LEAN_AND_MEAN
   60.68 +#include "windows.h"
   60.69 +// A simple helper class to disable/enable system error mode, if necessary
   60.70 +// Disabling happens conditionally only if a drive name is involved
   60.71 +class SysErrorModeDisabler
   60.72 +{
   60.73 +    BOOL    Disabled;
   60.74 +    UINT    OldMode;
   60.75 +public:
   60.76 +    SysErrorModeDisabler(const char* pfileName)
   60.77 +    {
   60.78 +        if (pfileName && (pfileName[0]!=0) && pfileName[1]==':')
   60.79 +        {
   60.80 +            Disabled = TRUE;
   60.81 +            OldMode = ::SetErrorMode(SEM_FAILCRITICALERRORS);
   60.82 +        }
   60.83 +        else
   60.84 +        {
   60.85 +            Disabled = 0;
   60.86 +            OldMode = 0;
   60.87 +        }
   60.88 +    }
   60.89 +
   60.90 +    ~SysErrorModeDisabler()
   60.91 +    {
   60.92 +        if (Disabled) 
   60.93 +            ::SetErrorMode(OldMode);
   60.94 +    }
   60.95 +};
   60.96 +#else
   60.97 +class SysErrorModeDisabler
   60.98 +{
   60.99 +public:
  60.100 +    SysErrorModeDisabler(const char* pfileName) { OVR_UNUSED(pfileName); }
  60.101 +};
  60.102 +#endif // OVR_OS_WIN32
  60.103 +
  60.104 +
  60.105 +// This macro enables verification of I/O results after seeks against a pre-loaded
  60.106 +// full file buffer copy. This is generally not necessary, but can been used to debug
  60.107 +// memory corruptions; we've seen this fail due to EAX2/DirectSound corrupting memory
  60.108 +// under FMOD with XP64 (32-bit) and Realtek HA Audio driver.
  60.109 +//#define GFILE_VERIFY_SEEK_ERRORS
  60.110 +
  60.111 +
  60.112 +// This is the simplest possible file implementation, it wraps around the descriptor
  60.113 +// This file is delegated to by SysFile.
  60.114 +
  60.115 +class FILEFile : public File
  60.116 +{
  60.117 +protected:
  60.118 +
  60.119 +    // Allocated filename
  60.120 +    String      FileName;
  60.121 +
  60.122 +    // File handle & open mode
  60.123 +    bool        Opened;
  60.124 +    FILE*       fs;
  60.125 +    int         OpenFlags;
  60.126 +    // Error code for last request
  60.127 +    int         ErrorCode;
  60.128 +
  60.129 +    int         LastOp;
  60.130 +
  60.131 +#ifdef OVR_FILE_VERIFY_SEEK_ERRORS
  60.132 +    uint8_t*      pFileTestBuffer;
  60.133 +    unsigned    FileTestLength;
  60.134 +    unsigned    TestPos; // File pointer position during tests.
  60.135 +#endif
  60.136 +
  60.137 +public:
  60.138 +
  60.139 +    FILEFile() :
  60.140 +        FileName(),
  60.141 +        Opened(false),
  60.142 +        fs(NULL),
  60.143 +        OpenFlags(0),
  60.144 +        ErrorCode(0),
  60.145 +        LastOp(0)
  60.146 +    #ifdef OVR_FILE_VERIFY_SEEK_ERRORS
  60.147 +       ,pFileTestBuffer(NULL)
  60.148 +       ,FileTestLength(0)
  60.149 +       ,TestPos(0)
  60.150 +    #endif
  60.151 +    {
  60.152 +    }
  60.153 +
  60.154 +    // Initialize file by opening it
  60.155 +    FILEFile(const String& fileName, int flags, int Mode);
  60.156 +
  60.157 +    // The 'pfileName' should be encoded as UTF-8 to support international file names.
  60.158 +    FILEFile(const char* pfileName, int flags, int Mode);
  60.159 +
  60.160 +    ~FILEFile()
  60.161 +    {
  60.162 +        if (Opened)
  60.163 +            Close();
  60.164 +    }
  60.165 +
  60.166 +    virtual const char* GetFilePath();
  60.167 +
  60.168 +    // ** File Information
  60.169 +    virtual bool        IsValid();
  60.170 +    virtual bool        IsWritable();
  60.171 +
  60.172 +    // Return position / file size
  60.173 +    virtual int         Tell();
  60.174 +    virtual int64_t     LTell();
  60.175 +    virtual int         GetLength();
  60.176 +    virtual int64_t     LGetLength();
  60.177 +
  60.178 +//  virtual bool        Stat(FileStats *pfs);
  60.179 +    virtual int         GetErrorCode();
  60.180 +
  60.181 +    // ** Stream implementation & I/O
  60.182 +    virtual int         Write(const uint8_t *pbuffer, int numBytes);
  60.183 +    virtual int         Read(uint8_t *pbuffer, int numBytes);
  60.184 +    virtual int         SkipBytes(int numBytes);
  60.185 +    virtual int         BytesAvailable();
  60.186 +    virtual bool        Flush();
  60.187 +    virtual int         Seek(int offset, int origin);
  60.188 +    virtual int64_t     LSeek(int64_t offset, int origin);
  60.189 +    
  60.190 +    virtual int         CopyFromStream(File *pStream, int byteSize);
  60.191 +    virtual bool        Close();    
  60.192 +private:
  60.193 +    void                init();
  60.194 +};
  60.195 +
  60.196 +
  60.197 +// Initialize file by opening it
  60.198 +FILEFile::FILEFile(const String& fileName, int flags, int mode)
  60.199 +  : FileName(fileName), OpenFlags(flags)
  60.200 +{
  60.201 +    OVR_UNUSED(mode);
  60.202 +    init();
  60.203 +}
  60.204 +
  60.205 +// The 'pfileName' should be encoded as UTF-8 to support international file names.
  60.206 +FILEFile::FILEFile(const char* pfileName, int flags, int mode)
  60.207 +  : FileName(pfileName), OpenFlags(flags)
  60.208 +{
  60.209 +    OVR_UNUSED(mode);
  60.210 +    init();
  60.211 +}
  60.212 +
  60.213 +void FILEFile::init()
  60.214 +{
  60.215 +    // Open mode for file's open
  60.216 +    const char *omode = "rb";
  60.217 +
  60.218 +    if (OpenFlags & Open_Truncate)
  60.219 +    {
  60.220 +        if (OpenFlags & Open_Read)
  60.221 +            omode = "w+b";
  60.222 +        else
  60.223 +            omode = "wb";
  60.224 +    }
  60.225 +    else if (OpenFlags & Open_Create)
  60.226 +    {
  60.227 +        if (OpenFlags & Open_Read)
  60.228 +            omode = "a+b";
  60.229 +        else
  60.230 +            omode = "ab";
  60.231 +    }
  60.232 +    else if (OpenFlags & Open_Write)
  60.233 +        omode = "r+b";
  60.234 +
  60.235 +#if defined(OVR_OS_MS)
  60.236 +    SysErrorModeDisabler disabler(FileName.ToCStr());
  60.237 +#endif
  60.238 +
  60.239 +#if defined(OVR_CC_MSVC) && (OVR_CC_MSVC >= 1400)
  60.240 +    wchar_t womode[16];
  60.241 +    wchar_t *pwFileName = (wchar_t*)OVR_ALLOC((UTF8Util::GetLength(FileName.ToCStr())+1) * sizeof(wchar_t));
  60.242 +    UTF8Util::DecodeString(pwFileName, FileName.ToCStr());
  60.243 +    OVR_ASSERT(strlen(omode) < sizeof(womode)/sizeof(womode[0]));
  60.244 +    UTF8Util::DecodeString(womode, omode);
  60.245 +    _wfopen_s(&fs, pwFileName, womode);
  60.246 +    OVR_FREE(pwFileName);
  60.247 +#else
  60.248 +    fs = fopen(FileName.ToCStr(), omode);
  60.249 +#endif
  60.250 +    if (fs)
  60.251 +        rewind (fs);
  60.252 +    Opened = (fs != NULL);
  60.253 +    // Set error code
  60.254 +    if (!Opened)
  60.255 +        ErrorCode = SFerror();
  60.256 +    else
  60.257 +    {
  60.258 +        // If we are testing file seek correctness, pre-load the entire file so
  60.259 +        // that we can do comparison tests later.
  60.260 +#ifdef OVR_FILE_VERIFY_SEEK_ERRORS        
  60.261 +        TestPos         = 0;
  60.262 +        fseek(fs, 0, SEEK_END);
  60.263 +        FileTestLength  = ftell(fs);
  60.264 +        fseek(fs, 0, SEEK_SET);
  60.265 +        pFileTestBuffer = (uint8_t*)OVR_ALLOC(FileTestLength);
  60.266 +        if (pFileTestBuffer)
  60.267 +        {
  60.268 +            OVR_ASSERT(FileTestLength == (unsigned)Read(pFileTestBuffer, FileTestLength));
  60.269 +            Seek(0, Seek_Set);
  60.270 +        }        
  60.271 +#endif
  60.272 +
  60.273 +        ErrorCode = 0;
  60.274 +    }
  60.275 +    LastOp = 0;
  60.276 +}
  60.277 +
  60.278 +
  60.279 +const char* FILEFile::GetFilePath()
  60.280 +{
  60.281 +    return FileName.ToCStr();
  60.282 +}
  60.283 +
  60.284 +
  60.285 +// ** File Information
  60.286 +bool    FILEFile::IsValid()
  60.287 +{
  60.288 +    return Opened;
  60.289 +}
  60.290 +bool    FILEFile::IsWritable()
  60.291 +{
  60.292 +    return IsValid() && (OpenFlags&Open_Write);
  60.293 +}
  60.294 +/*
  60.295 +bool    FILEFile::IsRecoverable()
  60.296 +{
  60.297 +    return IsValid() && ((OpenFlags&OVR_FO_SAFETRUNC) == OVR_FO_SAFETRUNC);
  60.298 +}
  60.299 +*/
  60.300 +
  60.301 +// Return position / file size
  60.302 +int     FILEFile::Tell()
  60.303 +{
  60.304 +    int pos = (int)ftell (fs);
  60.305 +    if (pos < 0)
  60.306 +        ErrorCode = SFerror();
  60.307 +    return pos;
  60.308 +}
  60.309 +
  60.310 +int64_t FILEFile::LTell()
  60.311 +{
  60.312 +    int64_t pos = ftell(fs);
  60.313 +    if (pos < 0)
  60.314 +        ErrorCode = SFerror();
  60.315 +    return pos;
  60.316 +}
  60.317 +
  60.318 +int     FILEFile::GetLength()
  60.319 +{
  60.320 +    int pos = Tell();
  60.321 +    if (pos >= 0)
  60.322 +    {
  60.323 +        Seek (0, Seek_End);
  60.324 +        int size = Tell();
  60.325 +        Seek (pos, Seek_Set);
  60.326 +        return size;
  60.327 +    }
  60.328 +    return -1;
  60.329 +}
  60.330 +int64_t FILEFile::LGetLength()
  60.331 +{
  60.332 +    int64_t pos = LTell();
  60.333 +    if (pos >= 0)
  60.334 +    {
  60.335 +        LSeek (0, Seek_End);
  60.336 +        int64_t size = LTell();
  60.337 +        LSeek (pos, Seek_Set);
  60.338 +        return size;
  60.339 +    }
  60.340 +    return -1;
  60.341 +}
  60.342 +
  60.343 +int     FILEFile::GetErrorCode()
  60.344 +{
  60.345 +    return ErrorCode;
  60.346 +}
  60.347 +
  60.348 +// ** Stream implementation & I/O
  60.349 +int     FILEFile::Write(const uint8_t *pbuffer, int numBytes)
  60.350 +{
  60.351 +    if (LastOp && LastOp != Open_Write)
  60.352 +        fflush(fs);
  60.353 +    LastOp = Open_Write;
  60.354 +    int written = (int) fwrite(pbuffer, 1, numBytes, fs);
  60.355 +    if (written < numBytes)
  60.356 +        ErrorCode = SFerror();
  60.357 +
  60.358 +#ifdef OVR_FILE_VERIFY_SEEK_ERRORS
  60.359 +    if (written > 0)
  60.360 +        TestPos += written;
  60.361 +#endif
  60.362 +
  60.363 +    return written;
  60.364 +}
  60.365 +
  60.366 +int     FILEFile::Read(uint8_t *pbuffer, int numBytes)
  60.367 +{
  60.368 +    if (LastOp && LastOp != Open_Read)
  60.369 +        fflush(fs);
  60.370 +    LastOp = Open_Read;
  60.371 +    int read = (int) fread(pbuffer, 1, numBytes, fs);
  60.372 +    if (read < numBytes)
  60.373 +        ErrorCode = SFerror();
  60.374 +
  60.375 +#ifdef OVR_FILE_VERIFY_SEEK_ERRORS
  60.376 +    if (read > 0)
  60.377 +    {
  60.378 +        // Read-in data must match our pre-loaded buffer data!
  60.379 +        uint8_t* pcompareBuffer = pFileTestBuffer + TestPos;
  60.380 +        for (int i=0; i< read; i++)
  60.381 +        {
  60.382 +            OVR_ASSERT(pcompareBuffer[i] == pbuffer[i]);
  60.383 +        }
  60.384 +
  60.385 +        //OVR_ASSERT(!memcmp(pFileTestBuffer + TestPos, pbuffer, read));
  60.386 +        TestPos += read;
  60.387 +        OVR_ASSERT(ftell(fs) == (int)TestPos);
  60.388 +    }
  60.389 +#endif
  60.390 +
  60.391 +    return read;
  60.392 +}
  60.393 +
  60.394 +// Seeks ahead to skip bytes
  60.395 +int     FILEFile::SkipBytes(int numBytes)
  60.396 +{
  60.397 +    int64_t pos    = LTell();
  60.398 +    int64_t newPos = LSeek(numBytes, Seek_Cur);
  60.399 +
  60.400 +    // Return -1 for major error
  60.401 +    if ((pos==-1) || (newPos==-1))
  60.402 +    {
  60.403 +        return -1;
  60.404 +    }
  60.405 +    //ErrorCode = ((NewPos-Pos)<numBytes) ? errno : 0;
  60.406 +
  60.407 +    return int (newPos-(int)pos);
  60.408 +}
  60.409 +
  60.410 +// Return # of bytes till EOF
  60.411 +int     FILEFile::BytesAvailable()
  60.412 +{
  60.413 +    int64_t pos    = LTell();
  60.414 +    int64_t endPos = LGetLength();
  60.415 +
  60.416 +    // Return -1 for major error
  60.417 +    if ((pos==-1) || (endPos==-1))
  60.418 +    {
  60.419 +        ErrorCode = SFerror();
  60.420 +        return 0;
  60.421 +    }
  60.422 +    else
  60.423 +        ErrorCode = 0;
  60.424 +
  60.425 +    return int (endPos-(int)pos);
  60.426 +}
  60.427 +
  60.428 +// Flush file contents
  60.429 +bool    FILEFile::Flush()
  60.430 +{
  60.431 +    return !fflush(fs);
  60.432 +}
  60.433 +
  60.434 +int     FILEFile::Seek(int offset, int origin)
  60.435 +{
  60.436 +    int newOrigin = 0;
  60.437 +    switch(origin)
  60.438 +    {
  60.439 +    case Seek_Set: newOrigin = SEEK_SET; break;
  60.440 +    case Seek_Cur: newOrigin = SEEK_CUR; break;
  60.441 +    case Seek_End: newOrigin = SEEK_END; break;
  60.442 +    }
  60.443 +
  60.444 +    if (newOrigin == SEEK_SET && offset == Tell())
  60.445 +        return Tell();
  60.446 +
  60.447 +    if (fseek (fs, offset, newOrigin))
  60.448 +    {
  60.449 +#ifdef OVR_FILE_VERIFY_SEEK_ERRORS
  60.450 +        OVR_ASSERT(0);
  60.451 +#endif
  60.452 +        return -1;
  60.453 +    }
  60.454 +    
  60.455 +#ifdef OVR_FILE_VERIFY_SEEK_ERRORS
  60.456 +    // Track file position after seeks for read verification later.
  60.457 +    switch(origin)
  60.458 +    {
  60.459 +    case Seek_Set:  TestPos = offset;       break;
  60.460 +    case Seek_Cur:  TestPos += offset;      break;    
  60.461 +    case Seek_End:  TestPos = FileTestLength + offset; break;
  60.462 +    }
  60.463 +    OVR_ASSERT((int)TestPos == Tell());
  60.464 +#endif
  60.465 +
  60.466 +    return (int)Tell();
  60.467 +}
  60.468 +
  60.469 +int64_t FILEFile::LSeek(int64_t offset, int origin)
  60.470 +{
  60.471 +    return Seek((int)offset,origin);
  60.472 +}
  60.473 +
  60.474 +int FILEFile::CopyFromStream(File *pstream, int byteSize)
  60.475 +{
  60.476 +    uint8_t*  buff = new uint8_t[0x4000];
  60.477 +    int     count = 0;
  60.478 +    int     szRequest, szRead, szWritten;
  60.479 +
  60.480 +    while (byteSize)
  60.481 +    {
  60.482 +        szRequest = (byteSize > int(sizeof(buff))) ? int(sizeof(buff)) : byteSize;
  60.483 +
  60.484 +        szRead    = pstream->Read(buff, szRequest);
  60.485 +        szWritten = 0;
  60.486 +        if (szRead > 0)
  60.487 +            szWritten = Write(buff, szRead);
  60.488 +
  60.489 +        count    += szWritten;
  60.490 +        byteSize -= szWritten;
  60.491 +        if (szWritten < szRequest)
  60.492 +            break;
  60.493 +    }
  60.494 +
  60.495 +	delete[] buff;
  60.496 +
  60.497 +    return count;
  60.498 +}
  60.499 +
  60.500 +
  60.501 +bool FILEFile::Close()
  60.502 +{
  60.503 +#ifdef OVR_FILE_VERIFY_SEEK_ERRORS
  60.504 +    if (pFileTestBuffer)
  60.505 +    {
  60.506 +        OVR_FREE(pFileTestBuffer);
  60.507 +        pFileTestBuffer = 0;
  60.508 +        FileTestLength  = 0;
  60.509 +    }
  60.510 +#endif
  60.511 +
  60.512 +    bool closeRet = !fclose(fs);
  60.513 +
  60.514 +    if (!closeRet)
  60.515 +    {
  60.516 +        ErrorCode = SFerror();
  60.517 +        return 0;
  60.518 +    }
  60.519 +    else
  60.520 +    {
  60.521 +        Opened    = 0;
  60.522 +        fs        = 0;
  60.523 +        ErrorCode = 0;
  60.524 +    }
  60.525 +
  60.526 +    // Handle safe truncate
  60.527 +    /*
  60.528 +    if ((OpenFlags & OVR_FO_SAFETRUNC) == OVR_FO_SAFETRUNC)
  60.529 +    {
  60.530 +        // Delete original file (if it existed)
  60.531 +        DWORD oldAttributes = FileUtilWin32::GetFileAttributes(FileName);
  60.532 +        if (oldAttributes!=0xFFFFFFFF)
  60.533 +            if (!FileUtilWin32::DeleteFile(FileName))
  60.534 +            {
  60.535 +                // Try to remove the readonly attribute
  60.536 +                FileUtilWin32::SetFileAttributes(FileName, oldAttributes & (~FILE_ATTRIBUTE_READONLY) );
  60.537 +                // And delete the file again
  60.538 +                if (!FileUtilWin32::DeleteFile(FileName))
  60.539 +                    return 0;
  60.540 +            }
  60.541 +
  60.542 +        // Rename temp file to real filename
  60.543 +        if (!FileUtilWin32::MoveFile(TempName, FileName))
  60.544 +        {
  60.545 +            //ErrorCode = errno;
  60.546 +            return 0;
  60.547 +        }
  60.548 +    }
  60.549 +    */
  60.550 +    return 1;
  60.551 +}
  60.552 +
  60.553 +/*
  60.554 +bool    FILEFile::CloseCancel()
  60.555 +{
  60.556 +    bool closeRet = (bool)::CloseHandle(fd);
  60.557 +
  60.558 +    if (!closeRet)
  60.559 +    {
  60.560 +        //ErrorCode = errno;
  60.561 +        return 0;
  60.562 +    }
  60.563 +    else
  60.564 +    {
  60.565 +        Opened    = 0;
  60.566 +        fd        = INVALID_HANDLE_VALUE;
  60.567 +        ErrorCode = 0;
  60.568 +    }
  60.569 +
  60.570 +    // Handle safe truncate (delete tmp file, leave original unchanged)
  60.571 +    if ((OpenFlags&OVR_FO_SAFETRUNC) == OVR_FO_SAFETRUNC)
  60.572 +        if (!FileUtilWin32::DeleteFile(TempName))
  60.573 +        {
  60.574 +            //ErrorCode = errno;
  60.575 +            return 0;
  60.576 +        }
  60.577 +    return 1;
  60.578 +}
  60.579 +*/
  60.580 +
  60.581 +Ptr<File> FileFILEOpen(const String& path, int flags, int mode)
  60.582 +{
  60.583 +    Ptr<File> result = *new FILEFile(path, flags, mode);
  60.584 +	return result;
  60.585 +}
  60.586 +
  60.587 +// Helper function: obtain file information time.
  60.588 +bool    SysFile::GetFileStat(FileStat* pfileStat, const String& path)
  60.589 +{
  60.590 +#if defined(OVR_OS_MS)
  60.591 +    // 64-bit implementation on Windows.
  60.592 +    struct __stat64 fileStat;
  60.593 +    // Stat returns 0 for success.
  60.594 +    wchar_t *pwpath = (wchar_t*)OVR_ALLOC((UTF8Util::GetLength(path.ToCStr())+1)*sizeof(wchar_t));
  60.595 +    UTF8Util::DecodeString(pwpath, path.ToCStr());
  60.596 +
  60.597 +    int ret = _wstat64(pwpath, &fileStat);
  60.598 +    OVR_FREE(pwpath);
  60.599 +    if (ret) return false;
  60.600 +#else
  60.601 +    struct stat fileStat;
  60.602 +    // Stat returns 0 for success.
  60.603 +    if (stat(path, &fileStat) != 0)
  60.604 +        return false;
  60.605 +#endif
  60.606 +    pfileStat->AccessTime = fileStat.st_atime;
  60.607 +    pfileStat->ModifyTime = fileStat.st_mtime;
  60.608 +    pfileStat->FileSize   = fileStat.st_size;
  60.609 +    return true;
  60.610 +}
  60.611 +
  60.612 +} // Namespace OVR
    61.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    61.2 +++ b/LibOVR/Src/Kernel/OVR_Hash.h	Wed Jan 14 06:51:16 2015 +0200
    61.3 @@ -0,0 +1,1305 @@
    61.4 +/************************************************************************************
    61.5 +
    61.6 +PublicHeader:   None
    61.7 +Filename    :   OVR_Hash.h
    61.8 +Content     :   Template hash-table/set implementation
    61.9 +Created     :   September 19, 2012
   61.10 +Notes       : 
   61.11 +
   61.12 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   61.13 +
   61.14 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
   61.15 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
   61.16 +which is provided at the time of installation or download, or which 
   61.17 +otherwise accompanies this software in either electronic or hard copy form.
   61.18 +
   61.19 +You may obtain a copy of the License at
   61.20 +
   61.21 +http://www.oculusvr.com/licenses/LICENSE-3.2 
   61.22 +
   61.23 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
   61.24 +distributed under the License is distributed on an "AS IS" BASIS,
   61.25 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   61.26 +See the License for the specific language governing permissions and
   61.27 +limitations under the License.
   61.28 +
   61.29 +************************************************************************************/
   61.30 +
   61.31 +#ifndef OVR_Hash_h
   61.32 +#define OVR_Hash_h
   61.33 +
   61.34 +#include "OVR_ContainerAllocator.h"
   61.35 +#include "OVR_Alg.h"
   61.36 +
   61.37 +// 'new' operator is redefined/used in this file.
   61.38 +#undef new
   61.39 +
   61.40 +namespace OVR {
   61.41 +
   61.42 +//-----------------------------------------------------------------------------------
   61.43 +// ***** Hash Table Implementation
   61.44 +
   61.45 +// HastSet and Hash.
   61.46 +//
   61.47 +// Hash table, linear probing, internal chaining.  One  interesting/nice thing
   61.48 +// about this implementation is that the table itself is a flat chunk of memory
   61.49 +// containing no pointers, only relative indices. If the key and value types
   61.50 +// of the Hash contain no pointers, then the Hash can be serialized using raw IO.
   61.51 +//
   61.52 +// Never shrinks, unless you explicitly Clear() it.  Expands on
   61.53 +// demand, though.  For best results, if you know roughly how big your
   61.54 +// table will be, default it to that size when you create it.
   61.55 +//
   61.56 +// Key usability feature:
   61.57 +//
   61.58 +//   1. Allows node hash values to either be cached or not.
   61.59 +//
   61.60 +//   2. Allows for alternative keys with methods such as GetAlt(). Handy
   61.61 +//      if you need to search nodes by their components; no need to create
   61.62 +//      temporary nodes.
   61.63 +//
   61.64 +
   61.65 +
   61.66 +// *** Hash functors:
   61.67 +//
   61.68 +//  IdentityHash  - use when the key is already a good hash
   61.69 +//  HFixedSizeHash - general hash based on object's in-memory representation.
   61.70 +
   61.71 +
   61.72 +// Hash is just the input value; can use this for integer-indexed hash tables.
   61.73 +template<class C>
   61.74 +class IdentityHash
   61.75 +{
   61.76 +public:
   61.77 +    size_t operator()(const C& data) const
   61.78 +    { return (size_t) data; }
   61.79 +};
   61.80 +
   61.81 +// Computes a hash of an object's representation.
   61.82 +template<class C>
   61.83 +class FixedSizeHash
   61.84 +{
   61.85 +public:
   61.86 +    // Alternative: "sdbm" hash function, suggested at same web page
   61.87 +    // above, http::/www.cs.yorku.ca/~oz/hash.html
   61.88 +    // This is somewhat slower then Bernstein, but it works way better than the above
   61.89 +    // hash function for hashing large numbers of 32-bit ints.
   61.90 +    static OVR_FORCE_INLINE size_t SDBM_Hash(const void* data_in, size_t size, size_t seed = 5381)     
   61.91 +    {
   61.92 +        const uint8_t* data = (const uint8_t*) data_in;
   61.93 +        size_t       h = seed;
   61.94 +        while (size-- > 0)
   61.95 +        {
   61.96 +            #ifndef __clang_analyzer__ // It mistakenly thinks data is garbage.
   61.97 +            h = (h << 16) + (h << 6) - h + (size_t)data[size];
   61.98 +            #endif
   61.99 +        }   
  61.100 +        return h;
  61.101 +    }
  61.102 +
  61.103 +    size_t operator()(const C& data) const
  61.104 +    {
  61.105 +        const unsigned char*  p = (const unsigned char*) &data;
  61.106 +        const size_t size = sizeof(C);
  61.107 +
  61.108 +        return SDBM_Hash(p, size);
  61.109 +    }
  61.110 +};
  61.111 +
  61.112 +
  61.113 +
  61.114 +// *** HashsetEntry Entry types. 
  61.115 +
  61.116 +// Compact hash table Entry type that re-computes hash keys during hash traversal.
  61.117 +// Good to use if the hash function is cheap or the hash value is already cached in C.
  61.118 +template<class C, class HashF>
  61.119 +class HashsetEntry
  61.120 +{
  61.121 +public:
  61.122 +    // Internal chaining for collisions.
  61.123 +    intptr_t    NextInChain;
  61.124 +    C           Value;
  61.125 +
  61.126 +    HashsetEntry()
  61.127 +        : NextInChain(-2) { }
  61.128 +    HashsetEntry(const HashsetEntry& e)
  61.129 +        : NextInChain(e.NextInChain), Value(e.Value) { }
  61.130 +    HashsetEntry(const C& key, intptr_t next)
  61.131 +        : NextInChain(next), Value(key) { }
  61.132 +
  61.133 +    bool    IsEmpty() const          { return NextInChain == -2;  }
  61.134 +    bool    IsEndOfChain() const     { return NextInChain == -1;  }
  61.135 +
  61.136 +    // Cached hash value access - can be optimized bu storing hash locally.
  61.137 +    // Mask value only needs to be used if SetCachedHash is not implemented.
  61.138 +    size_t  GetCachedHash(size_t maskValue) const  { return HashF()(Value) & maskValue; }
  61.139 +    void    SetCachedHash(size_t)                  {}
  61.140 +
  61.141 +    void    Clear()
  61.142 +    {        
  61.143 +        Value.~C(); // placement delete
  61.144 +        NextInChain = -2;
  61.145 +    }
  61.146 +    // Free is only used from dtor of hash; Clear is used during regular operations:
  61.147 +    // assignment, hash reallocations, value reassignments, so on.
  61.148 +    void    Free() { Clear(); }
  61.149 +};
  61.150 +
  61.151 +// Hash table Entry type that caches the Entry hash value for nodes, so that it
  61.152 +// does not need to be re-computed during access.
  61.153 +template<class C, class HashF>
  61.154 +class HashsetCachedEntry
  61.155 +{
  61.156 +public:
  61.157 +    // Internal chaining for collisions.
  61.158 +    intptr_t    NextInChain;
  61.159 +    size_t      HashValue;
  61.160 +    C           Value;
  61.161 +
  61.162 +    HashsetCachedEntry()
  61.163 +        : NextInChain(-2) { }
  61.164 +    HashsetCachedEntry(const HashsetCachedEntry& e)
  61.165 +        : NextInChain(e.NextInChain), HashValue(e.HashValue), Value(e.Value) { }
  61.166 +    HashsetCachedEntry(const C& key, intptr_t next)
  61.167 +        : NextInChain(next), Value(key) { }
  61.168 +
  61.169 +    bool    IsEmpty() const          { return NextInChain == -2;  }
  61.170 +    bool    IsEndOfChain() const     { return NextInChain == -1;  }
  61.171 +
  61.172 +    // Cached hash value access - can be optimized bu storing hash locally.
  61.173 +    // Mask value only needs to be used if SetCachedHash is not implemented.
  61.174 +    size_t  GetCachedHash(size_t maskValue) const  { OVR_UNUSED(maskValue); return HashValue; }
  61.175 +    void    SetCachedHash(size_t hashValue)        { HashValue = hashValue; }
  61.176 +
  61.177 +    void    Clear()
  61.178 +    {
  61.179 +        Value.~C();
  61.180 +        NextInChain = -2;
  61.181 +    }
  61.182 +    // Free is only used from dtor of hash; Clear is used during regular operations:
  61.183 +    // assignment, hash reallocations, value reassignments, so on.
  61.184 +    void    Free() { Clear(); }
  61.185 +};
  61.186 +
  61.187 +
  61.188 +//-----------------------------------------------------------------------------------
  61.189 +// *** HashSet implementation - relies on either cached or regular entries.
  61.190 +//
  61.191 +// Use: Entry = HashsetCachedEntry<C, HashF> if hashes are expensive to
  61.192 +//              compute and thus need caching in entries.
  61.193 +//      Entry = HashsetEntry<C, HashF> if hashes are already externally cached.
  61.194 +//
  61.195 +template<class C, class HashF = FixedSizeHash<C>,
  61.196 +         class AltHashF = HashF, 
  61.197 +         class Allocator = ContainerAllocator<C>,
  61.198 +         class Entry = HashsetCachedEntry<C, HashF> >
  61.199 +class HashSetBase
  61.200 +{
  61.201 +    enum { HashMinSize = 8 };
  61.202 +
  61.203 +public:
  61.204 +    OVR_MEMORY_REDEFINE_NEW(HashSetBase)
  61.205 +
  61.206 +    typedef HashSetBase<C, HashF, AltHashF, Allocator, Entry>    SelfType;
  61.207 +
  61.208 +    HashSetBase() : pTable(NULL)                       {   }
  61.209 +    HashSetBase(int sizeHint) : pTable(NULL)           { SetCapacity(this, sizeHint);  }
  61.210 +    HashSetBase(const SelfType& src) : pTable(NULL)    { Assign(this, src); }
  61.211 +
  61.212 +    ~HashSetBase()                                     
  61.213 +    { 
  61.214 +        if (pTable)
  61.215 +        {
  61.216 +            // Delete the entries.
  61.217 +            for (size_t i = 0, n = pTable->SizeMask; i <= n; i++)
  61.218 +            {
  61.219 +                Entry*  e = &E(i);
  61.220 +                if (!e->IsEmpty())             
  61.221 +                    e->Free();
  61.222 +            }            
  61.223 +
  61.224 +            Allocator::Free(pTable);
  61.225 +            pTable = NULL;
  61.226 +        }
  61.227 +    }
  61.228 +
  61.229 +
  61.230 +    void Assign(const SelfType& src)
  61.231 +    {
  61.232 +        Clear();
  61.233 +        if (src.IsEmpty() == false)
  61.234 +        {
  61.235 +            SetCapacity(src.GetSize());
  61.236 +
  61.237 +            for (ConstIterator it = src.Begin(); it != src.End(); ++it)
  61.238 +            {
  61.239 +                Add(*it);
  61.240 +            }
  61.241 +        }
  61.242 +    }
  61.243 +
  61.244 +
  61.245 +    // Remove all entries from the HashSet table.
  61.246 +    void Clear() 
  61.247 +    {
  61.248 +        if (pTable)
  61.249 +        {
  61.250 +            // Delete the entries.
  61.251 +            for (size_t i = 0, n = pTable->SizeMask; i <= n; i++)
  61.252 +            {
  61.253 +                Entry*  e = &E(i);
  61.254 +                if (!e->IsEmpty())             
  61.255 +                    e->Clear();
  61.256 +            }            
  61.257 +                
  61.258 +            Allocator::Free(pTable);
  61.259 +            pTable = NULL;
  61.260 +        }
  61.261 +    }
  61.262 +
  61.263 +    // Returns true if the HashSet is empty.
  61.264 +    bool IsEmpty() const
  61.265 +    {
  61.266 +        return pTable == NULL || pTable->EntryCount == 0;
  61.267 +    }
  61.268 +
  61.269 +
  61.270 +    // Set a new or existing value under the key, to the value.
  61.271 +    // Pass a different class of 'key' so that assignment reference object
  61.272 +    // can be passed instead of the actual object.
  61.273 +    template<class CRef>
  61.274 +    void Set(const CRef& key)
  61.275 +    {
  61.276 +        size_t hashValue = HashF()(key);
  61.277 +        intptr_t  index     = (intptr_t)-1;
  61.278 +
  61.279 +        if (pTable != NULL)
  61.280 +            index = findIndexCore(key, hashValue & pTable->SizeMask);
  61.281 +
  61.282 +        if (index >= 0)
  61.283 +        {            
  61.284 +            E(index).Value = key;
  61.285 +        }
  61.286 +        else
  61.287 +        {
  61.288 +            // Entry under key doesn't exist.
  61.289 +            add(key, hashValue);
  61.290 +        }
  61.291 +    }
  61.292 +
  61.293 +    template<class CRef>
  61.294 +    inline void Add(const CRef& key)
  61.295 +    {
  61.296 +        size_t hashValue = HashF()(key);
  61.297 +        add(key, hashValue);
  61.298 +    }
  61.299 +
  61.300 +    // Remove by alternative key.
  61.301 +    template<class K>
  61.302 +    void RemoveAlt(const K& key)
  61.303 +    {   
  61.304 +        if (pTable == NULL)
  61.305 +            return;
  61.306 +
  61.307 +        size_t   hashValue = AltHashF()(key);
  61.308 +        intptr_t index     = hashValue & pTable->SizeMask;
  61.309 +
  61.310 +        Entry*  e = &E(index);
  61.311 +
  61.312 +        // If empty node or occupied by collider, we have nothing to remove.
  61.313 +        if (e->IsEmpty() || (e->GetCachedHash(pTable->SizeMask) != (size_t)index))
  61.314 +            return;        
  61.315 +
  61.316 +        // Save index
  61.317 +        intptr_t naturalIndex = index;
  61.318 +        intptr_t prevIndex    = -1;
  61.319 +
  61.320 +        while ((e->GetCachedHash(pTable->SizeMask) != (size_t)naturalIndex) || !(e->Value == key))
  61.321 +        {
  61.322 +            // Keep looking through the chain.
  61.323 +            prevIndex   = index;
  61.324 +            index       = e->NextInChain;
  61.325 +            if (index == -1)
  61.326 +                return; // End of chain, item not found
  61.327 +            e = &E(index);
  61.328 +        }
  61.329 +
  61.330 +        // Found it - our item is at index
  61.331 +        if (naturalIndex == index)
  61.332 +        {
  61.333 +            // If we have a follower, move it to us
  61.334 +            if (!e->IsEndOfChain())
  61.335 +            {               
  61.336 +                Entry*  enext = &E(e->NextInChain);
  61.337 +                e->Clear();
  61.338 +                new (e) Entry(*enext);
  61.339 +                // Point us to the follower's cell that will be cleared
  61.340 +                e = enext;
  61.341 +            }
  61.342 +        }
  61.343 +        else
  61.344 +        {
  61.345 +            // We are not at natural index, so deal with the prev items next index
  61.346 +            E(prevIndex).NextInChain = e->NextInChain;
  61.347 +        }
  61.348 +
  61.349 +        // Clear us, of the follower cell that was moved.
  61.350 +        e->Clear();
  61.351 +        pTable->EntryCount --;
  61.352 +        // Should we check the size to condense hash? ...
  61.353 +    }
  61.354 +
  61.355 +    // Remove by main key.
  61.356 +    template<class CRef>
  61.357 +    void Remove(const CRef& key)
  61.358 +    {
  61.359 +        RemoveAlt(key);
  61.360 +    }
  61.361 +
  61.362 +    // Retrieve the pointer to a value under the given key.
  61.363 +    //  - If there's no value under the key, then return NULL.    
  61.364 +    //  - If there is a value, return the pointer.    
  61.365 +    template<class K>
  61.366 +    C* Get(const K& key)
  61.367 +    {
  61.368 +        intptr_t index = findIndex(key);
  61.369 +        if (index >= 0)        
  61.370 +            return &E(index).Value;        
  61.371 +        return 0;
  61.372 +    }   
  61.373 +
  61.374 +    template<class K>
  61.375 +    const C* Get(const K& key) const
  61.376 +    {
  61.377 +        intptr_t index = findIndex(key);
  61.378 +        if (index >= 0)        
  61.379 +            return &E(index).Value;        
  61.380 +        return 0;
  61.381 +    }
  61.382 +
  61.383 +    // Alternative key versions of Get. Used by Hash.
  61.384 +    template<class K>
  61.385 +    const C* GetAlt(const K& key) const
  61.386 +    {
  61.387 +        intptr_t index = findIndexAlt(key);
  61.388 +        if (index >= 0)        
  61.389 +            return &E(index).Value;
  61.390 +        return 0;
  61.391 +    }
  61.392 +
  61.393 +    template<class K>
  61.394 +    C* GetAlt(const K& key)
  61.395 +    {
  61.396 +        intptr_t index = findIndexAlt(key);
  61.397 +        if (index >= 0)        
  61.398 +            return &E(index).Value;
  61.399 +        return 0;
  61.400 +    }   
  61.401 +
  61.402 +    template<class K>
  61.403 +    bool GetAlt(const K& key, C* pval) const
  61.404 +    {
  61.405 +        intptr_t index = findIndexAlt(key);
  61.406 +        if (index >= 0)
  61.407 +        {
  61.408 +            if (pval)
  61.409 +                *pval = E(index).Value;
  61.410 +            return true;
  61.411 +        }
  61.412 +        return false;
  61.413 +    }
  61.414 +
  61.415 +
  61.416 +    size_t GetSize() const
  61.417 +    {
  61.418 +        return pTable == NULL ? 0 : (size_t)pTable->EntryCount;
  61.419 +    }
  61.420 +	int GetSizeI() const { return (int)GetSize(); }
  61.421 +
  61.422 +
  61.423 +    // Resize the HashSet table to fit one more Entry.  Often this
  61.424 +    // doesn't involve any action.
  61.425 +    void CheckExpand()
  61.426 +    {
  61.427 +        if (pTable == NULL)
  61.428 +        {
  61.429 +            // Initial creation of table.  Make a minimum-sized table.
  61.430 +            setRawCapacity(HashMinSize);
  61.431 +        }
  61.432 +        else if (pTable->EntryCount * 5 > (pTable->SizeMask + 1) * 4)
  61.433 +        {
  61.434 +            // pTable is more than 5/4 ths full.  Expand.
  61.435 +            setRawCapacity((pTable->SizeMask + 1) * 2);
  61.436 +        }
  61.437 +    }
  61.438 +
  61.439 +    // Hint the bucket count to >= n.
  61.440 +    void Resize(size_t n)    
  61.441 +    {
  61.442 +        // Not really sure what this means in relation to
  61.443 +        // STLport's hash_map... they say they "increase the
  61.444 +        // bucket count to at least n" -- but does that mean
  61.445 +        // their real capacity after Resize(n) is more like
  61.446 +        // n*2 (since they do linked-list chaining within
  61.447 +        // buckets?).
  61.448 +        SetCapacity(n);
  61.449 +    }
  61.450 +
  61.451 +    // Size the HashSet so that it can comfortably contain the given
  61.452 +    // number of elements.  If the HashSet already contains more
  61.453 +    // elements than newSize, then this may be a no-op.
  61.454 +    void SetCapacity(size_t newSize)
  61.455 +    {
  61.456 +        size_t newRawSize = (newSize * 5) / 4;
  61.457 +        if (newRawSize <= GetSize())
  61.458 +            return;
  61.459 +        setRawCapacity(newRawSize);
  61.460 +    }
  61.461 +
  61.462 +    // Disable inappropriate 'operator ->' warning on MSVC6.
  61.463 +#ifdef OVR_CC_MSVC
  61.464 +#if (OVR_CC_MSVC < 1300)
  61.465 +# pragma warning(disable : 4284)
  61.466 +#endif
  61.467 +#endif
  61.468 +
  61.469 +    // Iterator API, like STL.
  61.470 +    struct ConstIterator
  61.471 +    {   
  61.472 +        const C&    operator * () const
  61.473 +        {            
  61.474 +            OVR_ASSERT(Index >= 0 && Index <= (intptr_t)pHash->pTable->SizeMask);
  61.475 +            return pHash->E(Index).Value;
  61.476 +        }
  61.477 +
  61.478 +        const C*    operator -> () const
  61.479 +        {
  61.480 +            OVR_ASSERT(Index >= 0 && Index <= (intptr_t)pHash->pTable->SizeMask);
  61.481 +            return &pHash->E(Index).Value;
  61.482 +        }
  61.483 +
  61.484 +        void    operator ++ ()
  61.485 +        {
  61.486 +            // Find next non-empty Entry.
  61.487 +            if (Index <= (intptr_t)pHash->pTable->SizeMask)
  61.488 +            {
  61.489 +                Index++;
  61.490 +                while ((size_t)Index <= pHash->pTable->SizeMask &&
  61.491 +                    pHash->E(Index).IsEmpty())
  61.492 +                {
  61.493 +                    Index++;
  61.494 +                }
  61.495 +            }
  61.496 +        }
  61.497 +
  61.498 +        bool    operator == (const ConstIterator& it) const
  61.499 +        {
  61.500 +            if (IsEnd() && it.IsEnd())
  61.501 +            {
  61.502 +                return true;
  61.503 +            }
  61.504 +            else
  61.505 +            {
  61.506 +                return (pHash == it.pHash) && (Index == it.Index);
  61.507 +            }
  61.508 +        }
  61.509 +
  61.510 +        bool    operator != (const ConstIterator& it) const
  61.511 +        {
  61.512 +            return ! (*this == it);
  61.513 +        }
  61.514 +
  61.515 +
  61.516 +        bool    IsEnd() const
  61.517 +        {
  61.518 +            return (pHash == NULL) || 
  61.519 +                (pHash->pTable == NULL) || 
  61.520 +                (Index > (intptr_t)pHash->pTable->SizeMask);
  61.521 +        }
  61.522 +
  61.523 +        ConstIterator()
  61.524 +            : pHash(NULL), Index(0)
  61.525 +        { }
  61.526 +
  61.527 +    public:
  61.528 +        // Constructor was intentionally made public to allow create
  61.529 +        // iterator with arbitrary index.
  61.530 +        ConstIterator(const SelfType* h, intptr_t index)
  61.531 +            : pHash(h), Index(index)
  61.532 +        { }
  61.533 +
  61.534 +        const SelfType* GetContainer() const
  61.535 +        {
  61.536 +            return pHash;
  61.537 +        }
  61.538 +        intptr_t GetIndex() const
  61.539 +        {
  61.540 +            return Index;
  61.541 +        }
  61.542 +
  61.543 +    protected:
  61.544 +        friend class HashSetBase<C, HashF, AltHashF, Allocator, Entry>;
  61.545 +
  61.546 +        const SelfType* pHash;
  61.547 +        intptr_t        Index;
  61.548 +    };
  61.549 +
  61.550 +    friend struct ConstIterator;
  61.551 +
  61.552 +
  61.553 +    // Non-const Iterator; Get most of it from ConstIterator.
  61.554 +    struct Iterator : public ConstIterator
  61.555 +    {      
  61.556 +        // Allow non-const access to entries.
  61.557 +        C&  operator*() const
  61.558 +        {            
  61.559 +            OVR_ASSERT((ConstIterator::pHash) && ConstIterator::pHash->pTable && (ConstIterator::Index >= 0) && (ConstIterator::Index <= (intptr_t)ConstIterator::pHash->pTable->SizeMask));
  61.560 +            return const_cast<SelfType*>(ConstIterator::pHash)->E(ConstIterator::Index).Value;
  61.561 +        }    
  61.562 +
  61.563 +        C*  operator->() const 
  61.564 +        {
  61.565 +            return &(operator*());
  61.566 +        }
  61.567 +
  61.568 +        Iterator()
  61.569 +            : ConstIterator(NULL, 0)
  61.570 +        { }
  61.571 +
  61.572 +        // Removes current element from Hash
  61.573 +        void Remove()
  61.574 +        {
  61.575 +            RemoveAlt(operator*());
  61.576 +        }
  61.577 +
  61.578 +        template <class K>
  61.579 +        void RemoveAlt(const K& key)
  61.580 +        {
  61.581 +            SelfType*   phash = const_cast<SelfType*>(ConstIterator::pHash);
  61.582 +            //Entry*      ee = &phash->E(ConstIterator::Index);
  61.583 +            //const C&    key = ee->Value;
  61.584 +
  61.585 +            size_t      hashValue = AltHashF()(key);
  61.586 +            intptr_t    index     = hashValue & phash->pTable->SizeMask;
  61.587 +
  61.588 +            Entry*      e = &phash->E(index);
  61.589 +
  61.590 +            // If empty node or occupied by collider, we have nothing to remove.
  61.591 +            if (e->IsEmpty() || (e->GetCachedHash(phash->pTable->SizeMask) != (size_t)index))
  61.592 +                return;        
  61.593 +
  61.594 +            // Save index
  61.595 +            intptr_t   naturalIndex = index;
  61.596 +            intptr_t   prevIndex    = -1;
  61.597 +
  61.598 +            while ((e->GetCachedHash(phash->pTable->SizeMask) != (size_t)naturalIndex) || !(e->Value == key))
  61.599 +            {
  61.600 +                // Keep looking through the chain.
  61.601 +                prevIndex   = index;
  61.602 +                index       = e->NextInChain;
  61.603 +                if (index == -1)
  61.604 +                    return; // End of chain, item not found
  61.605 +                e = &phash->E(index);
  61.606 +            }
  61.607 +
  61.608 +            if (index == (intptr_t)ConstIterator::Index)
  61.609 +            {
  61.610 +                // Found it - our item is at index
  61.611 +                if (naturalIndex == index)
  61.612 +                {
  61.613 +                    // If we have a follower, move it to us
  61.614 +                    if (!e->IsEndOfChain())
  61.615 +                    {               
  61.616 +                        Entry*  enext = &phash->E(e->NextInChain);
  61.617 +                        e->Clear();
  61.618 +                        new (e) Entry(*enext);
  61.619 +                        // Point us to the follower's cell that will be cleared
  61.620 +                        e = enext;
  61.621 +                        --ConstIterator::Index;
  61.622 +                    }
  61.623 +                }
  61.624 +                else
  61.625 +                {
  61.626 +                    // We are not at natural index, so deal with the prev items next index
  61.627 +                    phash->E(prevIndex).NextInChain = e->NextInChain;
  61.628 +                }
  61.629 +
  61.630 +                // Clear us, of the follower cell that was moved.
  61.631 +                e->Clear();
  61.632 +                phash->pTable->EntryCount --;
  61.633 +            }
  61.634 +            else 
  61.635 +                OVR_ASSERT(0); //?
  61.636 +        }
  61.637 +
  61.638 +    private:
  61.639 +        friend class HashSetBase<C, HashF, AltHashF, Allocator, Entry>;
  61.640 +
  61.641 +        Iterator(SelfType* h, intptr_t i0)
  61.642 +            : ConstIterator(h, i0)
  61.643 +        { }
  61.644 +    };
  61.645 +
  61.646 +    friend struct Iterator;
  61.647 +
  61.648 +    Iterator    Begin()
  61.649 +    {
  61.650 +        if (pTable == 0)
  61.651 +            return Iterator(NULL, 0);
  61.652 +
  61.653 +        // Scan till we hit the First valid Entry.
  61.654 +        size_t i0 = 0;
  61.655 +        while (i0 <= pTable->SizeMask && E(i0).IsEmpty())
  61.656 +        {
  61.657 +            i0++;
  61.658 +        }
  61.659 +        return Iterator(this, i0);
  61.660 +    }
  61.661 +    Iterator        End()           { return Iterator(NULL, 0); }
  61.662 +
  61.663 +    ConstIterator   Begin() const   { return const_cast<SelfType*>(this)->Begin();     }
  61.664 +    ConstIterator   End() const     { return const_cast<SelfType*>(this)->End();   }
  61.665 +
  61.666 +    template<class K>
  61.667 +    Iterator Find(const K& key)
  61.668 +    {
  61.669 +        intptr_t index = findIndex(key);
  61.670 +        if (index >= 0)        
  61.671 +            return Iterator(this, index);        
  61.672 +        return Iterator(NULL, 0);
  61.673 +    }
  61.674 +
  61.675 +    template<class K>
  61.676 +    Iterator FindAlt(const K& key)
  61.677 +    {
  61.678 +        intptr_t index = findIndexAlt(key);
  61.679 +        if (index >= 0)        
  61.680 +            return Iterator(this, index);        
  61.681 +        return Iterator(NULL, 0);
  61.682 +    }
  61.683 +
  61.684 +    template<class K>
  61.685 +    ConstIterator Find(const K& key) const       { return const_cast<SelfType*>(this)->Find(key); }
  61.686 +
  61.687 +    template<class K>
  61.688 +    ConstIterator FindAlt(const K& key) const    { return const_cast<SelfType*>(this)->FindAlt(key); }
  61.689 +
  61.690 +private:
  61.691 +    // Find the index of the matching Entry.  If no match, then return -1.
  61.692 +    template<class K>
  61.693 +    intptr_t findIndex(const K& key) const
  61.694 +    {
  61.695 +        if (pTable == NULL)
  61.696 +            return -1;
  61.697 +        size_t hashValue = HashF()(key) & pTable->SizeMask;
  61.698 +        return findIndexCore(key, hashValue);
  61.699 +    }
  61.700 +
  61.701 +    template<class K>
  61.702 +    intptr_t findIndexAlt(const K& key) const
  61.703 +    {
  61.704 +        if (pTable == NULL)
  61.705 +            return -1;
  61.706 +        size_t hashValue = AltHashF()(key) & pTable->SizeMask;
  61.707 +        return findIndexCore(key, hashValue);
  61.708 +    }
  61.709 +
  61.710 +    // Find the index of the matching Entry.  If no match, then return -1.
  61.711 +    template<class K>
  61.712 +    intptr_t findIndexCore(const K& key, size_t hashValue) const
  61.713 +    {
  61.714 +        // Table must exist.
  61.715 +        OVR_ASSERT(pTable != 0);
  61.716 +        // Hash key must be 'and-ed' by the caller.
  61.717 +        OVR_ASSERT((hashValue & ~pTable->SizeMask) == 0);
  61.718 +
  61.719 +        size_t          index = hashValue;
  61.720 +        const Entry*    e     = &E(index);
  61.721 +
  61.722 +        // If empty or occupied by a collider, not found.
  61.723 +        if (e->IsEmpty() || (e->GetCachedHash(pTable->SizeMask) != index))
  61.724 +            return -1;
  61.725 +
  61.726 +        while(1)
  61.727 +        {
  61.728 +            OVR_ASSERT(e->GetCachedHash(pTable->SizeMask) == hashValue);
  61.729 +
  61.730 +            if (e->GetCachedHash(pTable->SizeMask) == hashValue && e->Value == key)
  61.731 +            {
  61.732 +                // Found it.
  61.733 +                return index;
  61.734 +            }
  61.735 +            // Values can not be equal at this point.
  61.736 +            // That would mean that the hash key for the same value differs.
  61.737 +            OVR_ASSERT(!(e->Value == key));
  61.738 +
  61.739 +            // Keep looking through the chain.
  61.740 +            index = e->NextInChain;
  61.741 +            if (index == (size_t)-1)
  61.742 +                break; // end of chain
  61.743 +
  61.744 +            e = &E(index);
  61.745 +            OVR_ASSERT(!e->IsEmpty());
  61.746 +        }
  61.747 +        return -1;
  61.748 +    }
  61.749 +
  61.750 +
  61.751 +    // Add a new value to the HashSet table, under the specified key.
  61.752 +    template<class CRef>
  61.753 +    void add(const CRef& key, size_t hashValue)
  61.754 +    {
  61.755 +        CheckExpand();
  61.756 +        hashValue &= pTable->SizeMask;
  61.757 +
  61.758 +        pTable->EntryCount++;
  61.759 +
  61.760 +        intptr_t   index        = hashValue;
  61.761 +        Entry*  naturalEntry = &(E(index));
  61.762 +
  61.763 +        if (naturalEntry->IsEmpty())
  61.764 +        {
  61.765 +            // Put the new Entry in.
  61.766 +            new (naturalEntry) Entry(key, -1);
  61.767 +        }
  61.768 +        else
  61.769 +        {
  61.770 +            // Find a blank spot.
  61.771 +            intptr_t blankIndex = index;
  61.772 +            do {
  61.773 +                blankIndex = (blankIndex + 1) & pTable->SizeMask;
  61.774 +            } while(!E(blankIndex).IsEmpty());
  61.775 +
  61.776 +            Entry*  blankEntry = &E(blankIndex);
  61.777 +
  61.778 +            if (naturalEntry->GetCachedHash(pTable->SizeMask) == (size_t)index)
  61.779 +            {
  61.780 +                // Collision.  Link into this chain.
  61.781 +
  61.782 +                // Move existing list head.
  61.783 +                new (blankEntry) Entry(*naturalEntry);    // placement new, copy ctor
  61.784 +
  61.785 +                // Put the new info in the natural Entry.
  61.786 +                naturalEntry->Value       = key;
  61.787 +                naturalEntry->NextInChain = blankIndex;
  61.788 +            }
  61.789 +            else
  61.790 +            {
  61.791 +                // Existing Entry does not naturally
  61.792 +                // belong in this slot.  Existing
  61.793 +                // Entry must be moved.
  61.794 +
  61.795 +                // Find natural location of collided element (i.e. root of chain)
  61.796 +                intptr_t collidedIndex = naturalEntry->GetCachedHash(pTable->SizeMask);
  61.797 +                OVR_ASSERT(collidedIndex >= 0 && collidedIndex <= (intptr_t)pTable->SizeMask);
  61.798 +                for (;;)
  61.799 +                {
  61.800 +                    Entry*  e = &E(collidedIndex);
  61.801 +                    if (e->NextInChain == index)
  61.802 +                    {
  61.803 +                        // Here's where we need to splice.
  61.804 +                        new (blankEntry) Entry(*naturalEntry);
  61.805 +                        e->NextInChain = blankIndex;
  61.806 +                        break;
  61.807 +                    }
  61.808 +                    collidedIndex = e->NextInChain;
  61.809 +                    OVR_ASSERT(collidedIndex >= 0 && collidedIndex <= (intptr_t)pTable->SizeMask);
  61.810 +                }
  61.811 +
  61.812 +                // Put the new data in the natural Entry.
  61.813 +                naturalEntry->Value       = key;
  61.814 +                naturalEntry->NextInChain = -1;                
  61.815 +            }            
  61.816 +        }
  61.817 +
  61.818 +        // Record hash value: has effect only if cached node is used.
  61.819 +        naturalEntry->SetCachedHash(hashValue);
  61.820 +    }
  61.821 +
  61.822 +    // Index access helpers.
  61.823 +    Entry& E(size_t index)
  61.824 +    {
  61.825 +        // Must have pTable and access needs to be within bounds.
  61.826 +        OVR_ASSERT(index <= pTable->SizeMask);
  61.827 +        return *(((Entry*) (pTable + 1)) + index);
  61.828 +    }
  61.829 +    const Entry& E(size_t index) const
  61.830 +    {        
  61.831 +        OVR_ASSERT(index <= pTable->SizeMask);
  61.832 +        return *(((Entry*) (pTable + 1)) + index);
  61.833 +    }
  61.834 +
  61.835 +
  61.836 +    // Resize the HashSet table to the given size (Rehash the
  61.837 +    // contents of the current table).  The arg is the number of
  61.838 +    // HashSet table entries, not the number of elements we should
  61.839 +    // actually contain (which will be less than this).
  61.840 +    void    setRawCapacity(size_t newSize)    
  61.841 +    {
  61.842 +        if (newSize == 0)
  61.843 +        {
  61.844 +            // Special case.
  61.845 +            Clear();
  61.846 +            return;
  61.847 +        }
  61.848 +
  61.849 +        // Minimum size; don't incur rehashing cost when expanding
  61.850 +        // very small tables. Not that we perform this check before 
  61.851 +        // 'log2f' call to avoid fp exception with newSize == 1.
  61.852 +        if (newSize < HashMinSize)        
  61.853 +            newSize = HashMinSize;       
  61.854 +        else
  61.855 +        {
  61.856 +            // Force newSize to be a power of two.
  61.857 +            int bits = Alg::UpperBit(newSize-1) + 1; // Chop( Log2f((float)(newSize-1)) + 1);
  61.858 +            OVR_ASSERT((size_t(1) << bits) >= newSize);
  61.859 +            newSize = size_t(1) << bits;
  61.860 +        }
  61.861 +
  61.862 +        SelfType  newHash;
  61.863 +        newHash.pTable = (TableType*)
  61.864 +            Allocator::Alloc(                
  61.865 +                sizeof(TableType) + sizeof(Entry) * newSize);
  61.866 +        // Need to do something on alloc failure!
  61.867 +        OVR_ASSERT(newHash.pTable);
  61.868 +
  61.869 +        newHash.pTable->EntryCount = 0;
  61.870 +        newHash.pTable->SizeMask = newSize - 1;
  61.871 +        size_t i, n;
  61.872 +
  61.873 +        // Mark all entries as empty.
  61.874 +        for (i = 0; i < newSize; i++)
  61.875 +            newHash.E(i).NextInChain = -2;
  61.876 +
  61.877 +        // Copy stuff to newHash
  61.878 +        if (pTable)
  61.879 +        {            
  61.880 +            for (i = 0, n = pTable->SizeMask; i <= n; i++)
  61.881 +            {
  61.882 +                Entry*  e = &E(i);
  61.883 +                if (e->IsEmpty() == false)
  61.884 +                {
  61.885 +                    // Insert old Entry into new HashSet.
  61.886 +                    newHash.Add(e->Value);
  61.887 +                    // placement delete of old element
  61.888 +                    e->Clear();
  61.889 +                }
  61.890 +            }
  61.891 +
  61.892 +            // Delete our old data buffer.
  61.893 +            Allocator::Free(pTable);
  61.894 +        }
  61.895 +
  61.896 +        // Steal newHash's data.
  61.897 +        pTable = newHash.pTable;
  61.898 +        newHash.pTable = NULL;
  61.899 +    }
  61.900 +
  61.901 +    struct TableType
  61.902 +    {
  61.903 +        size_t EntryCount;
  61.904 +        size_t SizeMask;
  61.905 +        // Entry array follows this structure
  61.906 +        // in memory.
  61.907 +    };
  61.908 +    TableType*  pTable;
  61.909 +};
  61.910 +
  61.911 +
  61.912 +
  61.913 +//-----------------------------------------------------------------------------------
  61.914 +template<class C, class HashF = FixedSizeHash<C>,
  61.915 +         class AltHashF = HashF, 
  61.916 +         class Allocator = ContainerAllocator<C>,
  61.917 +         class Entry = HashsetCachedEntry<C, HashF> >
  61.918 +class HashSet : public HashSetBase<C, HashF, AltHashF, Allocator, Entry>
  61.919 +{
  61.920 +public:
  61.921 +    typedef HashSetBase<C, HashF, AltHashF, Allocator, Entry> BaseType;
  61.922 +    typedef HashSet<C, HashF, AltHashF, Allocator, Entry>     SelfType;
  61.923 +
  61.924 +    HashSet()                                      {   }
  61.925 +    HashSet(int sizeHint) : BaseType(sizeHint)     {   }
  61.926 +    HashSet(const SelfType& src) : BaseType(src)   {   }
  61.927 +    ~HashSet()                                     {   }
  61.928 +
  61.929 +    void operator = (const SelfType& src)   { BaseType::Assign(src); }
  61.930 +
  61.931 +    // Set a new or existing value under the key, to the value.
  61.932 +    // Pass a different class of 'key' so that assignment reference object
  61.933 +    // can be passed instead of the actual object.
  61.934 +    template<class CRef>
  61.935 +    void Set(const CRef& key)
  61.936 +    {
  61.937 +        BaseType::Set(key);
  61.938 +    }
  61.939 +
  61.940 +    template<class CRef>
  61.941 +    inline void Add(const CRef& key)
  61.942 +    {
  61.943 +        BaseType::Add(key);
  61.944 +    }
  61.945 +
  61.946 +    // Hint the bucket count to >= n.
  61.947 +    void Resize(size_t n)    
  61.948 +    {
  61.949 +        BaseType::SetCapacity(n);
  61.950 +    }
  61.951 +
  61.952 +    // Size the HashSet so that it can comfortably contain the given
  61.953 +    // number of elements.  If the HashSet already contains more
  61.954 +    // elements than newSize, then this may be a no-op.
  61.955 +    void SetCapacity(size_t newSize)
  61.956 +    {
  61.957 +        BaseType::SetCapacity(newSize);
  61.958 +    }
  61.959 +
  61.960 +};
  61.961 +
  61.962 +// HashSet with uncached hash code; declared for convenience.
  61.963 +template<class C, class HashF = FixedSizeHash<C>,
  61.964 +                  class AltHashF = HashF,
  61.965 +                  class Allocator = ContainerAllocator<C> >
  61.966 +class HashSetUncached : public HashSet<C, HashF, AltHashF, Allocator, HashsetEntry<C, HashF> >
  61.967 +{
  61.968 +public:
  61.969 +    
  61.970 +    typedef HashSetUncached<C, HashF, AltHashF, Allocator>                  SelfType;
  61.971 +    typedef HashSet<C, HashF, AltHashF, Allocator, HashsetEntry<C, HashF> > BaseType;
  61.972 +
  61.973 +    // Delegated constructors.
  61.974 +    HashSetUncached()                                        { }
  61.975 +    HashSetUncached(int sizeHint) : BaseType(sizeHint)       { }
  61.976 +    HashSetUncached(const SelfType& src) : BaseType(src)     { }
  61.977 +    ~HashSetUncached()                                       { }
  61.978 +    
  61.979 +    void    operator = (const SelfType& src)
  61.980 +    {
  61.981 +        BaseType::operator = (src);
  61.982 +    }
  61.983 +};
  61.984 +
  61.985 +
  61.986 +//-----------------------------------------------------------------------------------
  61.987 +// ***** Hash hash table implementation
  61.988 +
  61.989 +// Node for Hash - necessary so that Hash can delegate its implementation
  61.990 +// to HashSet.
  61.991 +template<class C, class U, class HashF>
  61.992 +struct HashNode
  61.993 +{
  61.994 +    typedef HashNode<C, U, HashF>   SelfType;
  61.995 +    typedef C                       FirstType;
  61.996 +    typedef U                       SecondType;
  61.997 +
  61.998 +    C   First;
  61.999 +    U   Second;
 61.1000 +
 61.1001 +    // NodeRef is used to allow passing of elements into HashSet
 61.1002 +    // without using a temporary object.
 61.1003 +    struct NodeRef
 61.1004 +    {
 61.1005 +        const C*   pFirst;
 61.1006 +        const U*   pSecond;
 61.1007 +
 61.1008 +        NodeRef(const C& f, const U& s) : pFirst(&f), pSecond(&s) { }
 61.1009 +        NodeRef(const NodeRef& src)     : pFirst(src.pFirst), pSecond(src.pSecond) { }
 61.1010 +
 61.1011 +        // Enable computation of ghash_node_hashf.
 61.1012 +        inline size_t GetHash() const            { return HashF()(*pFirst); } 
 61.1013 +        // Necessary conversion to allow HashNode::operator == to work.
 61.1014 +        operator const C& () const              { return *pFirst; }
 61.1015 +    };
 61.1016 +
 61.1017 +    // Note: No default constructor is necessary.
 61.1018 +     HashNode(const HashNode& src) : First(src.First), Second(src.Second)    { }
 61.1019 +     HashNode(const NodeRef& src) : First(*src.pFirst), Second(*src.pSecond)  { }
 61.1020 +    void operator = (const NodeRef& src)  { First  = *src.pFirst; Second = *src.pSecond; }
 61.1021 +
 61.1022 +    template<class K>
 61.1023 +    bool operator == (const K& src) const   { return (First == src); }
 61.1024 +
 61.1025 +    template<class K>
 61.1026 +    static size_t CalcHash(const K& data)   { return HashF()(data); }
 61.1027 +    inline size_t GetHash() const           { return HashF()(First); }
 61.1028 +
 61.1029 +    // Hash functors used with this node. A separate functor is used for alternative
 61.1030 +    // key lookup so that it does not need to access the '.First' element.    
 61.1031 +    struct NodeHashF
 61.1032 +    {    
 61.1033 +        template<class K>
 61.1034 +        size_t operator()(const K& data) const { return data.GetHash(); } 
 61.1035 +    };    
 61.1036 +    struct NodeAltHashF
 61.1037 +    {
 61.1038 +        template<class K>
 61.1039 +        size_t operator()(const K& data) const { return HashNode<C,U,HashF>::CalcHash(data); }
 61.1040 +    };
 61.1041 +};
 61.1042 +
 61.1043 +
 61.1044 +
 61.1045 +// **** Extra hashset_entry types to allow NodeRef construction.
 61.1046 +
 61.1047 +// The big difference between the below types and the ones used in hash_set is that
 61.1048 +// these allow initializing the node with 'typename C::NodeRef& keyRef', which
 61.1049 +// is critical to avoid temporary node allocation on stack when using placement new.
 61.1050 +
 61.1051 +// Compact hash table Entry type that re-computes hash keys during hash traversal.
 61.1052 +// Good to use if the hash function is cheap or the hash value is already cached in C.
 61.1053 +template<class C, class HashF>
 61.1054 +class HashsetNodeEntry
 61.1055 +{
 61.1056 +public:
 61.1057 +    // Internal chaining for collisions.
 61.1058 +    intptr_t NextInChain;
 61.1059 +    C     Value;
 61.1060 +
 61.1061 +    HashsetNodeEntry()
 61.1062 +        : NextInChain(-2) { }
 61.1063 +    HashsetNodeEntry(const HashsetNodeEntry& e)
 61.1064 +        : NextInChain(e.NextInChain), Value(e.Value) { }
 61.1065 +    HashsetNodeEntry(const C& key, intptr_t next)
 61.1066 +        : NextInChain(next), Value(key) { }    
 61.1067 +    HashsetNodeEntry(const typename C::NodeRef& keyRef, intptr_t next)
 61.1068 +        : NextInChain(next), Value(keyRef) { }
 61.1069 +
 61.1070 +    bool    IsEmpty() const             { return NextInChain == -2;  }
 61.1071 +    bool    IsEndOfChain() const        { return NextInChain == -1;  }
 61.1072 +    size_t  GetCachedHash(size_t maskValue) const  { return HashF()(Value) & maskValue; }
 61.1073 +    void    SetCachedHash(size_t hashValue)        { OVR_UNUSED(hashValue); }
 61.1074 +
 61.1075 +    void    Clear()
 61.1076 +    {        
 61.1077 +        Value.~C(); // placement delete
 61.1078 +        NextInChain = -2;
 61.1079 +    }
 61.1080 +    // Free is only used from dtor of hash; Clear is used during regular operations:
 61.1081 +    // assignment, hash reallocations, value reassignments, so on.
 61.1082 +    void    Free() { Clear(); }
 61.1083 +};
 61.1084 +
 61.1085 +// Hash table Entry type that caches the Entry hash value for nodes, so that it
 61.1086 +// does not need to be re-computed during access.
 61.1087 +template<class C, class HashF>
 61.1088 +class HashsetCachedNodeEntry
 61.1089 +{
 61.1090 +public:
 61.1091 +    // Internal chaining for collisions.
 61.1092 +    intptr_t NextInChain;
 61.1093 +    size_t HashValue;
 61.1094 +    C     Value;
 61.1095 +
 61.1096 +    HashsetCachedNodeEntry()
 61.1097 +        : NextInChain(-2) { }
 61.1098 +    HashsetCachedNodeEntry(const HashsetCachedNodeEntry& e)
 61.1099 +        : NextInChain(e.NextInChain), HashValue(e.HashValue), Value(e.Value) { }
 61.1100 +    HashsetCachedNodeEntry(const C& key, intptr_t next)
 61.1101 +        : NextInChain(next), Value(key) { }
 61.1102 +    HashsetCachedNodeEntry(const typename C::NodeRef& keyRef, intptr_t next)
 61.1103 +        : NextInChain(next), Value(keyRef) { }
 61.1104 +
 61.1105 +    bool    IsEmpty() const            { return NextInChain == -2;  }
 61.1106 +    bool    IsEndOfChain() const       { return NextInChain == -1;  }
 61.1107 +    size_t  GetCachedHash(size_t maskValue) const  { OVR_UNUSED(maskValue); return HashValue; }
 61.1108 +    void    SetCachedHash(size_t hashValue)        { HashValue = hashValue; }
 61.1109 +
 61.1110 +    void    Clear()
 61.1111 +    {
 61.1112 +        Value.~C();
 61.1113 +        NextInChain = -2;
 61.1114 +    }
 61.1115 +    // Free is only used from dtor of hash; Clear is used during regular operations:
 61.1116 +    // assignment, hash reallocations, value reassignments, so on.
 61.1117 +    void    Free() { Clear(); }
 61.1118 +};
 61.1119 +
 61.1120 +
 61.1121 +//-----------------------------------------------------------------------------------
 61.1122 +template<class C, class U,
 61.1123 +         class HashF = FixedSizeHash<C>,
 61.1124 +         class Allocator = ContainerAllocator<C>,
 61.1125 +         class HashNode = OVR::HashNode<C,U,HashF>,
 61.1126 +         class Entry = HashsetCachedNodeEntry<HashNode, typename HashNode::NodeHashF>,
 61.1127 +         class Container =  HashSet<HashNode, typename HashNode::NodeHashF,
 61.1128 +             typename HashNode::NodeAltHashF, Allocator,
 61.1129 +             Entry> >
 61.1130 +class Hash
 61.1131 +{
 61.1132 +public:
 61.1133 +    OVR_MEMORY_REDEFINE_NEW(Hash)
 61.1134 +
 61.1135 +    // Types used for hash_set.
 61.1136 +    typedef U                                                           ValueType;
 61.1137 +    typedef Hash<C, U, HashF, Allocator, HashNode, Entry, Container>    SelfType;
 61.1138 +
 61.1139 +    // Actual hash table itself, implemented as hash_set.
 61.1140 +    Container   mHash;
 61.1141 +
 61.1142 +public:
 61.1143 +    Hash()     {  }
 61.1144 +    Hash(int sizeHint) : mHash(sizeHint)                        { }
 61.1145 +    Hash(const SelfType& src) : mHash(src.mHash)                { }
 61.1146 +    ~Hash()                                                     { }
 61.1147 +
 61.1148 +    void    operator = (const SelfType& src)    { mHash = src.mHash; }
 61.1149 +
 61.1150 +    // Remove all entries from the Hash table.
 61.1151 +    inline void    Clear() { mHash.Clear(); }
 61.1152 +    // Returns true if the Hash is empty.
 61.1153 +    inline bool    IsEmpty() const { return mHash.IsEmpty(); }
 61.1154 +
 61.1155 +    // Access (set).
 61.1156 +    inline void    Set(const C& key, const U& value)
 61.1157 +    {
 61.1158 +        typename HashNode::NodeRef e(key, value);
 61.1159 +        mHash.Set(e);
 61.1160 +    }
 61.1161 +    inline void    Add(const C& key, const U& value)
 61.1162 +    {
 61.1163 +        typename HashNode::NodeRef e(key, value);
 61.1164 +        mHash.Add(e);
 61.1165 +    }
 61.1166 +
 61.1167 +    // Removes an element by clearing its Entry.
 61.1168 +    inline void     Remove(const C& key)
 61.1169 +    {   
 61.1170 +        mHash.RemoveAlt(key);
 61.1171 +    }
 61.1172 +    template<class K>
 61.1173 +    inline void     RemoveAlt(const K& key)
 61.1174 +    {   
 61.1175 +        mHash.RemoveAlt(key);
 61.1176 +    }
 61.1177 +
 61.1178 +    // Retrieve the value under the given key.    
 61.1179 +    //  - If there's no value under the key, then return false and leave *pvalue alone.
 61.1180 +    //  - If there is a value, return true, and Set *Pvalue to the Entry's value.
 61.1181 +    //  - If value == NULL, return true or false according to the presence of the key.    
 61.1182 +    bool    Get(const C& key, U* pvalue) const   
 61.1183 +    {
 61.1184 +        const HashNode* p = mHash.GetAlt(key);
 61.1185 +        if (p)
 61.1186 +        {
 61.1187 +            if (pvalue)
 61.1188 +                *pvalue = p->Second;
 61.1189 +            return true;
 61.1190 +        }
 61.1191 +        return false;
 61.1192 +    }
 61.1193 +
 61.1194 +    template<class K>
 61.1195 +    bool    GetAlt(const K& key, U* pvalue) const   
 61.1196 +    {
 61.1197 +        const HashNode* p = mHash.GetAlt(key);
 61.1198 +        if (p)
 61.1199 +        {
 61.1200 +            if (pvalue)
 61.1201 +                *pvalue = p->Second;
 61.1202 +            return true;
 61.1203 +        }
 61.1204 +        return false;
 61.1205 +    }
 61.1206 +
 61.1207 +    // Retrieve the pointer to a value under the given key.    
 61.1208 +    //  - If there's no value under the key, then return NULL.    
 61.1209 +    //  - If there is a value, return the pointer.    
 61.1210 +    inline U*  Get(const C& key)
 61.1211 +    {
 61.1212 +        HashNode* p = mHash.GetAlt(key);
 61.1213 +        return p ? &p->Second : 0;
 61.1214 +    }
 61.1215 +    inline const U* Get(const C& key) const
 61.1216 +    {
 61.1217 +        const HashNode* p = mHash.GetAlt(key);
 61.1218 +        return p ? &p->Second : 0;
 61.1219 +    }
 61.1220 +
 61.1221 +    template<class K>
 61.1222 +    inline U*  GetAlt(const K& key)
 61.1223 +    {
 61.1224 +        HashNode* p = mHash.GetAlt(key);
 61.1225 +        return p ? &p->Second : 0;
 61.1226 +    }
 61.1227 +    template<class K>
 61.1228 +    inline const U* GetAlt(const K& key) const
 61.1229 +    {
 61.1230 +        const HashNode* p = mHash.GetAlt(key);
 61.1231 +        return p ? &p->Second : 0;
 61.1232 +    }
 61.1233 +
 61.1234 +    // Sizing methods - delegate to Hash.
 61.1235 +    inline size_t  GetSize() const              { return mHash.GetSize(); }    
 61.1236 +	inline int     GetSizeI() const             { return (int)GetSize(); }
 61.1237 +	inline void    Resize(size_t n)              { mHash.Resize(n); }
 61.1238 +    inline void    SetCapacity(size_t newSize)   { mHash.SetCapacity(newSize); }
 61.1239 +
 61.1240 +    // Iterator API, like STL.
 61.1241 +    typedef typename Container::ConstIterator   ConstIterator;
 61.1242 +    typedef typename Container::Iterator        Iterator;
 61.1243 +
 61.1244 +    inline Iterator        Begin()              { return mHash.Begin(); }
 61.1245 +    inline Iterator        End()                { return mHash.End(); }
 61.1246 +    inline ConstIterator   Begin() const        { return mHash.Begin(); }
 61.1247 +    inline ConstIterator   End() const          { return mHash.End();   }
 61.1248 +
 61.1249 +    Iterator        Find(const C& key)          { return mHash.FindAlt(key);  }
 61.1250 +    ConstIterator   Find(const C& key) const    { return mHash.FindAlt(key);  }
 61.1251 +
 61.1252 +    template<class K>
 61.1253 +    Iterator        FindAlt(const K& key)       { return mHash.FindAlt(key);  }
 61.1254 +    template<class K>
 61.1255 +    ConstIterator   FindAlt(const K& key) const { return mHash.FindAlt(key);  }
 61.1256 +};
 61.1257 +
 61.1258 +
 61.1259 +
 61.1260 +// Hash with uncached hash code; declared for convenience.
 61.1261 +template<class C, class U, class HashF = FixedSizeHash<C>, class Allocator = ContainerAllocator<C> >
 61.1262 +class HashUncached
 61.1263 +    : public Hash<C, U, HashF, Allocator, HashNode<C,U,HashF>,
 61.1264 +                   HashsetNodeEntry<HashNode<C,U,HashF>, typename HashNode<C,U,HashF>::NodeHashF> >
 61.1265 +{
 61.1266 +public:
 61.1267 +    typedef HashUncached<C, U, HashF, Allocator>                SelfType;
 61.1268 +    typedef Hash<C, U, HashF, Allocator, HashNode<C,U,HashF>,
 61.1269 +                 HashsetNodeEntry<HashNode<C,U,HashF>,
 61.1270 +                 typename HashNode<C,U,HashF>::NodeHashF> >     BaseType;
 61.1271 +
 61.1272 +    // Delegated constructors.
 61.1273 +    HashUncached()                                        { }
 61.1274 +    HashUncached(int sizeHint) : BaseType(sizeHint)       { }
 61.1275 +    HashUncached(const SelfType& src) : BaseType(src)     { }
 61.1276 +    ~HashUncached()                                       { }
 61.1277 +    void operator = (const SelfType& src)                 { BaseType::operator = (src); }
 61.1278 +};
 61.1279 +
 61.1280 +
 61.1281 +
 61.1282 +// And identity hash in which keys serve as hash value. Can be uncached,
 61.1283 +// since hash computation is assumed cheap.
 61.1284 +template<class C, class U, class Allocator = ContainerAllocator<C>, class HashF = IdentityHash<C> >
 61.1285 +class HashIdentity
 61.1286 +    : public HashUncached<C, U, HashF, Allocator>
 61.1287 +{
 61.1288 +public:
 61.1289 +    typedef HashIdentity<C, U, Allocator, HashF> SelfType;
 61.1290 +    typedef HashUncached<C, U, HashF, Allocator> BaseType;
 61.1291 +
 61.1292 +    // Delegated constructors.
 61.1293 +    HashIdentity()                                        { }
 61.1294 +    HashIdentity(int sizeHint) : BaseType(sizeHint)       { }
 61.1295 +    HashIdentity(const SelfType& src) : BaseType(src)     { }
 61.1296 +    ~HashIdentity()                                       { }
 61.1297 +    void operator = (const SelfType& src)                 { BaseType::operator = (src); }
 61.1298 +};
 61.1299 +
 61.1300 +
 61.1301 +} // OVR
 61.1302 +
 61.1303 +
 61.1304 +#ifdef OVR_DEFINE_NEW
 61.1305 +#define new OVR_DEFINE_NEW
 61.1306 +#endif
 61.1307 +
 61.1308 +#endif
    62.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    62.2 +++ b/LibOVR/Src/Kernel/OVR_KeyCodes.h	Wed Jan 14 06:51:16 2015 +0200
    62.3 @@ -0,0 +1,251 @@
    62.4 +/************************************************************************************
    62.5 +
    62.6 +PublicHeader:   OVR_Kernel.h
    62.7 +Filename    :   OVR_KeyCodes.h
    62.8 +Content     :   Common keyboard constants
    62.9 +Created     :   September 19, 2012
   62.10 +
   62.11 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   62.12 +
   62.13 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
   62.14 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
   62.15 +which is provided at the time of installation or download, or which 
   62.16 +otherwise accompanies this software in either electronic or hard copy form.
   62.17 +
   62.18 +You may obtain a copy of the License at
   62.19 +
   62.20 +http://www.oculusvr.com/licenses/LICENSE-3.2 
   62.21 +
   62.22 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
   62.23 +distributed under the License is distributed on an "AS IS" BASIS,
   62.24 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   62.25 +See the License for the specific language governing permissions and
   62.26 +limitations under the License.
   62.27 +
   62.28 +************************************************************************************/
   62.29 +
   62.30 +#ifndef OVR_KeyCodes_h
   62.31 +#define OVR_KeyCodes_h
   62.32 +
   62.33 +namespace OVR {
   62.34 +
   62.35 +//-----------------------------------------------------------------------------------
   62.36 +// ***** KeyCode
   62.37 +
   62.38 +// KeyCode enumeration defines platform-independent keyboard key constants.
   62.39 +// Note that Key_A through Key_Z are mapped to capital ascii constants.
   62.40 +
   62.41 +enum KeyCode
   62.42 +{
   62.43 +    // Key_None indicates that no key was specified.
   62.44 +    Key_None            = 0, 
   62.45 +
   62.46 +    // A through Z and numbers 0 through 9.
   62.47 +    Key_A               = 65,
   62.48 +    Key_B,
   62.49 +    Key_C,
   62.50 +    Key_D,
   62.51 +    Key_E,
   62.52 +    Key_F,
   62.53 +    Key_G,
   62.54 +    Key_H,
   62.55 +    Key_I,
   62.56 +    Key_J,
   62.57 +    Key_K,
   62.58 +    Key_L,
   62.59 +    Key_M,
   62.60 +    Key_N,
   62.61 +    Key_O,
   62.62 +    Key_P,
   62.63 +    Key_Q,
   62.64 +    Key_R,
   62.65 +    Key_S,
   62.66 +    Key_T,
   62.67 +    Key_U,
   62.68 +    Key_V,
   62.69 +    Key_W,
   62.70 +    Key_X,
   62.71 +    Key_Y,
   62.72 +    Key_Z,
   62.73 +    Key_Num0            = 48,
   62.74 +    Key_Num1,
   62.75 +    Key_Num2,
   62.76 +    Key_Num3,
   62.77 +    Key_Num4,
   62.78 +    Key_Num5,
   62.79 +    Key_Num6,
   62.80 +    Key_Num7,
   62.81 +    Key_Num8,
   62.82 +    Key_Num9,
   62.83 +
   62.84 +    // Numeric keypad.
   62.85 +    Key_KP_0            = 0xa0,
   62.86 +    Key_KP_1,
   62.87 +    Key_KP_2,
   62.88 +    Key_KP_3,
   62.89 +    Key_KP_4,
   62.90 +    Key_KP_5,
   62.91 +    Key_KP_6,
   62.92 +    Key_KP_7,
   62.93 +    Key_KP_8,
   62.94 +    Key_KP_9,
   62.95 +    Key_KP_Multiply,
   62.96 +    Key_KP_Add,
   62.97 +    Key_KP_Enter,
   62.98 +    Key_KP_Subtract,
   62.99 +    Key_KP_Decimal,
  62.100 +    Key_KP_Divide,
  62.101 +    
  62.102 +    // Function keys.
  62.103 +    Key_F1              = 0xb0,
  62.104 +    Key_F2,
  62.105 +    Key_F3,
  62.106 +    Key_F4,
  62.107 +    Key_F5,
  62.108 +    Key_F6,
  62.109 +    Key_F7,
  62.110 +    Key_F8,
  62.111 +    Key_F9,
  62.112 +    Key_F10,
  62.113 +    Key_F11,
  62.114 +    Key_F12,
  62.115 +    Key_F13,
  62.116 +    Key_F14,
  62.117 +    Key_F15,
  62.118 +    
  62.119 +    // Other keys.
  62.120 +    Key_Backspace       = 8,
  62.121 +    Key_Tab,
  62.122 +    Key_Clear           = 12,
  62.123 +    Key_Return,
  62.124 +    Key_Shift           = 16,
  62.125 +    Key_Control,
  62.126 +    Key_Alt,
  62.127 +    Key_Pause,
  62.128 +    Key_CapsLock        = 20, // Toggle
  62.129 +    Key_Escape          = 27,
  62.130 +    Key_Space           = 32,
  62.131 +    Key_Quote           = 39,
  62.132 +    Key_PageUp          = 0xc0,
  62.133 +    Key_PageDown,
  62.134 +    Key_End,
  62.135 +    Key_Home,
  62.136 +    Key_Left,
  62.137 +    Key_Up,
  62.138 +    Key_Right,
  62.139 +    Key_Down,
  62.140 +    Key_Insert,
  62.141 +    Key_Delete,
  62.142 +    Key_Help,
  62.143 +    
  62.144 +    Key_Comma           = 44,
  62.145 +    Key_Minus,
  62.146 +    Key_Slash           = 47,
  62.147 +    Key_Period,
  62.148 +    Key_NumLock         = 144, // Toggle
  62.149 +    Key_ScrollLock      = 145, // Toggle
  62.150 +    
  62.151 +    Key_Semicolon       = 59,
  62.152 +    Key_Equal           = 61,
  62.153 +    Key_Backtick        = 96,   // ` and tilda~ when shifted (US keyboard)
  62.154 +    Key_BracketLeft     = 91,
  62.155 +    Key_Backslash,
  62.156 +    Key_BracketRight,
  62.157 +
  62.158 +    Key_OEM_AX          = 0xE1,  //  'AX' key on Japanese AX keyboard
  62.159 +    Key_OEM_102         = 0xE2,  //  "<>" or "\|" on RT 102-key keyboard.
  62.160 +    Key_ICO_HELP        = 0xE3,  //  Help key on ICO
  62.161 +    Key_ICO_00          = 0xE4,  //  00 key on ICO
  62.162 +
  62.163 +    Key_Meta,
  62.164 +
  62.165 +    // Total number of keys.
  62.166 +    Key_CodeCount
  62.167 +};
  62.168 +
  62.169 +
  62.170 +//-----------------------------------------------------------------------------------
  62.171 +
  62.172 +class KeyModifiers 
  62.173 +{
  62.174 +public:
  62.175 +    enum
  62.176 +    {
  62.177 +        Key_ShiftPressed    = 0x01,
  62.178 +        Key_CtrlPressed     = 0x02,
  62.179 +        Key_AltPressed      = 0x04,
  62.180 +        Key_MetaPressed     = 0x08,
  62.181 +        Key_CapsToggled     = 0x10,
  62.182 +        Key_NumToggled      = 0x20,
  62.183 +        Key_ScrollToggled   = 0x40,
  62.184 +
  62.185 +        Initialized_Bit     = 0x80,
  62.186 +        Initialized_Mask    = 0xFF
  62.187 +    };
  62.188 +    unsigned char States;
  62.189 +
  62.190 +    KeyModifiers() : States(0) { }
  62.191 +        KeyModifiers(unsigned char st) : States((unsigned char)(st | Initialized_Bit)) { }
  62.192 +
  62.193 +    void Reset() { States = 0; }
  62.194 +
  62.195 +    bool IsShiftPressed() const { return (States & Key_ShiftPressed) != 0; }
  62.196 +    bool IsCtrlPressed() const  { return (States & Key_CtrlPressed) != 0; }
  62.197 +    bool IsAltPressed() const   { return (States & Key_AltPressed) != 0; }
  62.198 +    bool IsMetaPressed() const  { return (States & Key_MetaPressed) != 0; }
  62.199 +    bool IsCapsToggled() const  { return (States & Key_CapsToggled) != 0; }
  62.200 +    bool IsNumToggled() const   { return (States & Key_NumToggled) != 0; }
  62.201 +    bool IsScrollToggled() const{ return (States & Key_ScrollToggled) != 0; }
  62.202 +
  62.203 +    void SetShiftPressed(bool v = true)  { (v) ? States |= Key_ShiftPressed : States &= ~Key_ShiftPressed; }
  62.204 +    void SetCtrlPressed(bool v = true)   { (v) ? States |= Key_CtrlPressed  : States &= ~Key_CtrlPressed; }
  62.205 +    void SetAltPressed(bool v = true)    { (v) ? States |= Key_AltPressed   : States &= ~Key_AltPressed; }
  62.206 +    void SetMetaPressed(bool v = true)   { (v) ? States |= Key_MetaPressed  : States &= ~Key_MetaPressed; }
  62.207 +    void SetCapsToggled(bool v = true)   { (v) ? States |= Key_CapsToggled  : States &= ~Key_CapsToggled; }
  62.208 +    void SetNumToggled(bool v = true)    { (v) ? States |= Key_NumToggled   : States &= ~Key_NumToggled; }
  62.209 +    void SetScrollToggled(bool v = true) { (v) ? States |= Key_ScrollToggled: States &= ~Key_ScrollToggled; }
  62.210 +
  62.211 +    bool IsInitialized() const { return (States & Initialized_Mask) != 0; }
  62.212 +};
  62.213 +
  62.214 +
  62.215 +//-----------------------------------------------------------------------------------
  62.216 +
  62.217 +/*
  62.218 +enum PadKeyCode
  62.219 +{
  62.220 +    Pad_None, // Indicates absence of key code.
  62.221 +    Pad_Back,
  62.222 +    Pad_Start,
  62.223 +    Pad_A,
  62.224 +    Pad_B,
  62.225 +    Pad_X,
  62.226 +    Pad_Y,
  62.227 +    Pad_R1,  // RightShoulder;
  62.228 +    Pad_L1,  // LeftShoulder;
  62.229 +    Pad_R2,  // RightTrigger;
  62.230 +    Pad_L2,  // LeftTrigger;
  62.231 +    Pad_Up,
  62.232 +    Pad_Down,
  62.233 +    Pad_Right,
  62.234 +    Pad_Left,
  62.235 +    Pad_Plus,
  62.236 +    Pad_Minus,
  62.237 +    Pad_1,
  62.238 +    Pad_2,
  62.239 +    Pad_H,
  62.240 +    Pad_C,
  62.241 +    Pad_Z,
  62.242 +    Pad_O,
  62.243 +    Pad_T,
  62.244 +    Pad_S,
  62.245 +    Pad_Select,
  62.246 +    Pad_Home,
  62.247 +    Pad_RT,  // RightThumb;
  62.248 +    Pad_LT   // LeftThumb;
  62.249 +};
  62.250 +*/
  62.251 +
  62.252 +} // OVR
  62.253 +
  62.254 +#endif
    63.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    63.2 +++ b/LibOVR/Src/Kernel/OVR_List.h	Wed Jan 14 06:51:16 2015 +0200
    63.3 @@ -0,0 +1,342 @@
    63.4 +/************************************************************************************
    63.5 +
    63.6 +PublicHeader:   OVR
    63.7 +Filename    :   OVR_List.h
    63.8 +Content     :   Template implementation for doubly-connected linked List
    63.9 +Created     :   September 19, 2012
   63.10 +Notes       : 
   63.11 +
   63.12 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   63.13 +
   63.14 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
   63.15 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
   63.16 +which is provided at the time of installation or download, or which 
   63.17 +otherwise accompanies this software in either electronic or hard copy form.
   63.18 +
   63.19 +You may obtain a copy of the License at
   63.20 +
   63.21 +http://www.oculusvr.com/licenses/LICENSE-3.2 
   63.22 +
   63.23 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
   63.24 +distributed under the License is distributed on an "AS IS" BASIS,
   63.25 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   63.26 +See the License for the specific language governing permissions and
   63.27 +limitations under the License.
   63.28 +
   63.29 +************************************************************************************/
   63.30 +
   63.31 +#ifndef OVR_List_h
   63.32 +#define OVR_List_h
   63.33 +
   63.34 +#include "OVR_Types.h"
   63.35 +
   63.36 +namespace OVR {
   63.37 +
   63.38 +//-----------------------------------------------------------------------------------
   63.39 +// ***** ListNode
   63.40 +//
   63.41 +// Base class for the elements of the intrusive linked list.
   63.42 +// To store elements in the List do:
   63.43 +//
   63.44 +// struct MyData : ListNode<MyData>
   63.45 +// {
   63.46 +//     . . .
   63.47 +// };
   63.48 +
   63.49 +template<class T>
   63.50 +struct ListNode
   63.51 +{
   63.52 +    union {
   63.53 +        T*    pPrev;
   63.54 +        void* pVoidPrev;
   63.55 +    };
   63.56 +    union {
   63.57 +        T*    pNext;
   63.58 +        void* pVoidNext;
   63.59 +    };
   63.60 +
   63.61 +    ListNode()
   63.62 +    {
   63.63 +        pPrev = NULL;
   63.64 +        pNext = NULL;
   63.65 +    }
   63.66 +
   63.67 +    void    RemoveNode()
   63.68 +    {
   63.69 +        pPrev->pNext = pNext;
   63.70 +        pNext->pPrev = pPrev;
   63.71 +    }
   63.72 +
   63.73 +    // Removes us from the list and inserts pnew there instead.
   63.74 +    void    ReplaceNodeWith(T* pnew)
   63.75 +    {
   63.76 +        pPrev->pNext = pnew;
   63.77 +        pNext->pPrev = pnew;
   63.78 +        pnew->pPrev = pPrev;
   63.79 +        pnew->pNext = pNext;
   63.80 +    }
   63.81 +       
   63.82 +    // Inserts the argument linked list node after us in the list.
   63.83 +    void    InsertNodeAfter(T* p)
   63.84 +    {
   63.85 +        p->pPrev          = pNext->pPrev; // this
   63.86 +        p->pNext          = pNext;
   63.87 +        pNext->pPrev      = p;
   63.88 +        pNext             = p;
   63.89 +    }
   63.90 +    // Inserts the argument linked list node before us in the list.
   63.91 +    void    InsertNodeBefore(T* p)
   63.92 +    {
   63.93 +        p->pNext          = pNext->pPrev; // this
   63.94 +        p->pPrev          = pPrev;
   63.95 +        pPrev->pNext      = p;
   63.96 +        pPrev             = p;
   63.97 +    }
   63.98 +
   63.99 +    void    Alloc_MoveTo(ListNode<T>* pdest)
  63.100 +    {
  63.101 +        pdest->pNext = pNext;
  63.102 +        pdest->pPrev = pPrev;
  63.103 +        pPrev->pNext = (T*)pdest;
  63.104 +        pNext->pPrev = (T*)pdest;
  63.105 +    }
  63.106 +};
  63.107 +
  63.108 +
  63.109 +//------------------------------------------------------------------------
  63.110 +// ***** List
  63.111 +//
  63.112 +// Doubly linked intrusive list. 
  63.113 +// The data type must be derived from ListNode.
  63.114 +// 
  63.115 +// Adding:   PushFront(), PushBack().
  63.116 +// Removing: Remove() - the element must be in the list!
  63.117 +// Moving:   BringToFront(), SendToBack() - the element must be in the list!
  63.118 +//
  63.119 +// Iterating:
  63.120 +//    MyData* data = MyList.GetFirst();
  63.121 +//    while (!MyList.IsNull(data))
  63.122 +//    {
  63.123 +//        . . .
  63.124 +//        data = MyList.GetNext(data);
  63.125 +//    }
  63.126 +//
  63.127 +// Removing:
  63.128 +//    MyData* data = MyList.GetFirst();
  63.129 +//    while (!MyList.IsNull(data))
  63.130 +//    {
  63.131 +//        MyData* next = MyList.GetNext(data);
  63.132 +//        if (ToBeRemoved(data))
  63.133 +//             MyList.Remove(data);
  63.134 +//        data = next;
  63.135 +//    }
  63.136 +//
  63.137 +
  63.138 +// List<> represents a doubly-linked list of T, where each T must derive
  63.139 +// from ListNode<B>. B specifies the base class that was directly
  63.140 +// derived from ListNode, and is only necessary if there is an intermediate
  63.141 +// inheritance chain.
  63.142 +
  63.143 +template<class T, class B = T> class List
  63.144 +{
  63.145 +public:
  63.146 +    typedef T ValueType;
  63.147 +
  63.148 +    List()
  63.149 +    {
  63.150 +        Root.pNext = Root.pPrev = (ValueType*)&Root;
  63.151 +    }
  63.152 +
  63.153 +    void Clear()
  63.154 +    {
  63.155 +        Root.pNext = Root.pPrev = (ValueType*)&Root;
  63.156 +    }
  63.157 +
  63.158 +    const ValueType* GetFirst() const { return (const ValueType*)Root.pNext; }
  63.159 +    const ValueType* GetLast () const { return (const ValueType*)Root.pPrev; }
  63.160 +          ValueType* GetFirst()       { return (ValueType*)Root.pNext; }
  63.161 +          ValueType* GetLast ()       { return (ValueType*)Root.pPrev; }
  63.162 +
  63.163 +    // Determine if list is empty (i.e.) points to itself.
  63.164 +    // Go through void* access to avoid issues with strict-aliasing optimizing out the
  63.165 +    // access after RemoveNode(), etc.
  63.166 +    bool IsEmpty()                   const { return Root.pVoidNext == (const T*)(const B*)&Root; }
  63.167 +    bool IsFirst(const ValueType* p) const { return p == Root.pNext; }
  63.168 +    bool IsLast (const ValueType* p) const { return p == Root.pPrev; }
  63.169 +    bool IsNull (const ValueType* p) const { return p == (const T*)(const B*)&Root; }
  63.170 +
  63.171 +    inline static const ValueType* GetPrev(const ValueType* p) { return (const ValueType*)p->pPrev; }
  63.172 +    inline static const ValueType* GetNext(const ValueType* p) { return (const ValueType*)p->pNext; }
  63.173 +    inline static       ValueType* GetPrev(      ValueType* p) { return (ValueType*)p->pPrev; }
  63.174 +    inline static       ValueType* GetNext(      ValueType* p) { return (ValueType*)p->pNext; }
  63.175 +
  63.176 +    void PushFront(ValueType* p)
  63.177 +    {
  63.178 +        p->pNext          =  Root.pNext;
  63.179 +        p->pPrev          = (ValueType*)&Root;
  63.180 +        Root.pNext->pPrev =  p;
  63.181 +        Root.pNext        =  p;
  63.182 +    }
  63.183 +
  63.184 +    void PushBack(ValueType* p)
  63.185 +    {
  63.186 +        p->pPrev          =  Root.pPrev;
  63.187 +        p->pNext          = (ValueType*)&Root;
  63.188 +        Root.pPrev->pNext =  p;
  63.189 +        Root.pPrev        =  p;
  63.190 +    }
  63.191 +
  63.192 +    static void Remove(ValueType* p)
  63.193 +    {
  63.194 +        p->pPrev->pNext = p->pNext;
  63.195 +        p->pNext->pPrev = p->pPrev;
  63.196 +    }
  63.197 +
  63.198 +    void BringToFront(ValueType* p)
  63.199 +    {
  63.200 +        Remove(p);
  63.201 +        PushFront(p);
  63.202 +    }
  63.203 +
  63.204 +    void SendToBack(ValueType* p)
  63.205 +    {
  63.206 +        Remove(p);
  63.207 +        PushBack(p);
  63.208 +    }
  63.209 +
  63.210 +    // Appends the contents of the argument list to the front of this list;
  63.211 +    // items are removed from the argument list.
  63.212 +    void PushListToFront(List<T>& src)
  63.213 +    {
  63.214 +        if (!src.IsEmpty())
  63.215 +        {
  63.216 +            ValueType* pfirst = src.GetFirst();
  63.217 +            ValueType* plast  = src.GetLast();
  63.218 +            src.Clear();
  63.219 +            plast->pNext   = Root.pNext;
  63.220 +            pfirst->pPrev  = (ValueType*)&Root;
  63.221 +            Root.pNext->pPrev = plast;
  63.222 +            Root.pNext        = pfirst;
  63.223 +        }
  63.224 +    }
  63.225 +
  63.226 +    void PushListToBack(List<T>& src)
  63.227 +    {
  63.228 +        if (!src.IsEmpty())
  63.229 +        {
  63.230 +            ValueType* pfirst = src.GetFirst();
  63.231 +            ValueType* plast  = src.GetLast();
  63.232 +            src.Clear();
  63.233 +            plast->pNext   = (ValueType*)&Root;
  63.234 +            pfirst->pPrev  = Root.pPrev;
  63.235 +            Root.pPrev->pNext = pfirst;
  63.236 +            Root.pPrev        = plast;
  63.237 +        }
  63.238 +    }
  63.239 +
  63.240 +    // Removes all source list items after (and including) the 'pfirst' node from the 
  63.241 +    // source list and adds them to out list.
  63.242 +    void    PushFollowingListItemsToFront(List<T>& src, ValueType *pfirst)
  63.243 +    {
  63.244 +        if (pfirst != &src.Root)
  63.245 +        {
  63.246 +            ValueType *plast = src.Root.pPrev;
  63.247 +
  63.248 +            // Remove list remainder from source.
  63.249 +            pfirst->pPrev->pNext = (ValueType*)&src.Root;
  63.250 +            src.Root.pPrev      = pfirst->pPrev;
  63.251 +            // Add the rest of the items to list.
  63.252 +            plast->pNext      = Root.pNext;
  63.253 +            pfirst->pPrev     = (ValueType*)&Root;
  63.254 +            Root.pNext->pPrev = plast;
  63.255 +            Root.pNext        = pfirst;
  63.256 +        }
  63.257 +    }
  63.258 +
  63.259 +    // Removes all source list items up to but NOT including the 'pend' node from the 
  63.260 +    // source list and adds them to out list.
  63.261 +    void    PushPrecedingListItemsToFront(List<T>& src, ValueType *ptail)
  63.262 +    {
  63.263 +        if (src.GetFirst() != ptail)
  63.264 +        {
  63.265 +            ValueType *pfirst = src.Root.pNext;
  63.266 +            ValueType *plast  = ptail->pPrev;
  63.267 +
  63.268 +            // Remove list remainder from source.
  63.269 +            ptail->pPrev      = (ValueType*)&src.Root;
  63.270 +            src.Root.pNext    = ptail;            
  63.271 +
  63.272 +            // Add the rest of the items to list.
  63.273 +            plast->pNext      = Root.pNext;
  63.274 +            pfirst->pPrev     = (ValueType*)&Root;
  63.275 +            Root.pNext->pPrev = plast;
  63.276 +            Root.pNext        = pfirst;
  63.277 +        }
  63.278 +    }
  63.279 +
  63.280 +
  63.281 +    // Removes a range of source list items starting at 'pfirst' and up to, but not including 'pend',
  63.282 +    // and adds them to out list. Note that source items MUST already be in the list.
  63.283 +    void    PushListItemsToFront(ValueType *pfirst, ValueType *pend)
  63.284 +    {
  63.285 +        if (pfirst != pend)
  63.286 +        {
  63.287 +            ValueType *plast = pend->pPrev;
  63.288 +
  63.289 +            // Remove list remainder from source.
  63.290 +            pfirst->pPrev->pNext = pend;
  63.291 +            pend->pPrev          = pfirst->pPrev;
  63.292 +            // Add the rest of the items to list.
  63.293 +            plast->pNext      = Root.pNext;
  63.294 +            pfirst->pPrev     = (ValueType*)&Root;
  63.295 +            Root.pNext->pPrev = plast;
  63.296 +            Root.pNext        = pfirst;
  63.297 +        }
  63.298 +    }
  63.299 +
  63.300 +
  63.301 +    void    Alloc_MoveTo(List<T>* pdest)
  63.302 +    {
  63.303 +        if (IsEmpty())
  63.304 +            pdest->Clear();
  63.305 +        else
  63.306 +        {
  63.307 +            pdest->Root.pNext = Root.pNext;
  63.308 +            pdest->Root.pPrev = Root.pPrev;
  63.309 +
  63.310 +            Root.pNext->pPrev = (ValueType*)&pdest->Root;
  63.311 +            Root.pPrev->pNext = (ValueType*)&pdest->Root;
  63.312 +        }        
  63.313 +    }
  63.314 +
  63.315 +
  63.316 +private:
  63.317 +    // Copying is prohibited
  63.318 +    List(const List<T>&);
  63.319 +    const List<T>& operator = (const List<T>&);
  63.320 +
  63.321 +    ListNode<B> Root;
  63.322 +};
  63.323 +
  63.324 +
  63.325 +//------------------------------------------------------------------------
  63.326 +// ***** FreeListElements
  63.327 +//
  63.328 +// Remove all elements in the list and free them in the allocator
  63.329 +
  63.330 +template<class List, class Allocator>
  63.331 +void FreeListElements(List& list, Allocator& allocator)
  63.332 +{
  63.333 +    typename List::ValueType* self = list.GetFirst();
  63.334 +    while(!list.IsNull(self))
  63.335 +    {
  63.336 +        typename List::ValueType* next = list.GetNext(self);
  63.337 +        allocator.Free(self);
  63.338 +        self = next;
  63.339 +    }
  63.340 +    list.Clear();
  63.341 +}
  63.342 +
  63.343 +} // OVR
  63.344 +
  63.345 +#endif
    64.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    64.2 +++ b/LibOVR/Src/Kernel/OVR_Lockless.cpp	Wed Jan 14 06:51:16 2015 +0200
    64.3 @@ -0,0 +1,225 @@
    64.4 +/************************************************************************************
    64.5 +
    64.6 +Filename    :   OVR_Lockless.cpp
    64.7 +Content     :   Test logic for lock-less classes
    64.8 +Created     :   December 27, 2013
    64.9 +Authors     :   Michael Antonov
   64.10 +
   64.11 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   64.12 +
   64.13 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
   64.14 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
   64.15 +which is provided at the time of installation or download, or which 
   64.16 +otherwise accompanies this software in either electronic or hard copy form.
   64.17 +
   64.18 +You may obtain a copy of the License at
   64.19 +
   64.20 +http://www.oculusvr.com/licenses/LICENSE-3.2 
   64.21 +
   64.22 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
   64.23 +distributed under the License is distributed on an "AS IS" BASIS,
   64.24 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   64.25 +See the License for the specific language governing permissions and
   64.26 +limitations under the License.
   64.27 +
   64.28 +*************************************************************************************/
   64.29 +
   64.30 +#include "OVR_Lockless.h"
   64.31 +
   64.32 +#ifdef OVR_LOCKLESS_TEST
   64.33 +
   64.34 +#include "OVR_Threads.h"
   64.35 +#include "OVR_Timer.h"
   64.36 +#include "OVR_Log.h"
   64.37 +
   64.38 +namespace OVR { namespace LocklessTest {
   64.39 +
   64.40 +
   64.41 +const int TestIterations = 10000000;
   64.42 +
   64.43 +// Use volatile dummies to force compiler to do spinning.
   64.44 +volatile int Dummy1;
   64.45 +int          Unused1[32];
   64.46 +volatile int Dummy2;
   64.47 +int          Unused2[32];
   64.48 +volatile int Dummy3;
   64.49 +int          Unused3[32];
   64.50 +
   64.51 +
   64.52 +// Data block out of 20 consecutive integers, should be internally consistent.
   64.53 +struct TestData
   64.54 +{
   64.55 +    enum { ItemCount = 20 };
   64.56 +
   64.57 +    int Data[ItemCount];
   64.58 +
   64.59 +
   64.60 +    void Set(int val)
   64.61 +    {
   64.62 +        for (int i=0; i<ItemCount; i++)
   64.63 +        {
   64.64 +            Data[i] = val*100 + i;
   64.65 +        }
   64.66 +    }
   64.67 +
   64.68 +    int ReadAndCheckConsistency(int prevValue) const
   64.69 +    {
   64.70 +        int val = Data[0];
   64.71 +
   64.72 +        for (int i=1; i<ItemCount; i++)
   64.73 +        {
   64.74 +            
   64.75 +            if (Data[i] != (val + i))
   64.76 +            {
   64.77 +                // Only complain once per same-value entry
   64.78 +                if (prevValue != val / 100) 
   64.79 +                {
   64.80 +                    LogText("LocklessTest Fail - corruption at %d inside block %d\n",
   64.81 +                            i, val/100);
   64.82 +                    // OVR_ASSERT(Data[i] == val + i);
   64.83 +                }
   64.84 +                break;
   64.85 +            }
   64.86 +        }
   64.87 +
   64.88 +        return val / 100;
   64.89 +    }
   64.90 +};
   64.91 +
   64.92 +
   64.93 +
   64.94 +volatile bool              FirstItemWritten = false;
   64.95 +LocklessUpdater<TestData, TestData>  TestDataUpdater;
   64.96 +
   64.97 +// Use this lock to verify that testing algorithm is otherwise correct...
   64.98 +Lock                       TestLock;   
   64.99 +
  64.100 +
  64.101 +//-------------------------------------------------------------------------------------
  64.102 +
  64.103 +// Consumer thread reads values from TestDataUpdater and
  64.104 +// ensures that each one is internally consistent.
  64.105 +
  64.106 +class Consumer : public Thread
  64.107 +{
  64.108 +    virtual int Run()
  64.109 +    {
  64.110 +        LogText("LocklessTest::Consumer::Run started.\n");
  64.111 +        
  64.112 +        while (!FirstItemWritten)
  64.113 +        {
  64.114 +            // spin until producer wrote first value...
  64.115 +        }
  64.116 +
  64.117 +        TestData d;
  64.118 +        int      oldValue = 0;
  64.119 +        int      newValue;
  64.120 +
  64.121 +        do 
  64.122 +        {
  64.123 +            {
  64.124 +                //Lock::Locker scope(&TestLock);
  64.125 +                d = TestDataUpdater.GetState();
  64.126 +            }
  64.127 +            
  64.128 +            newValue = d.ReadAndCheckConsistency(oldValue);
  64.129 +            
  64.130 +            // Values should increase or stay the same!
  64.131 +            if (newValue < oldValue)
  64.132 +            {
  64.133 +                LogText("LocklessTest Fail - %d after %d;  delta = %d\n",
  64.134 +                        newValue, oldValue, newValue - oldValue);
  64.135 +         //       OVR_ASSERT(0);
  64.136 +            }
  64.137 +            
  64.138 +
  64.139 +            if (oldValue != newValue)
  64.140 +            {
  64.141 +                oldValue = newValue;
  64.142 +
  64.143 +                if (oldValue % (TestIterations/30) == 0)
  64.144 +                {
  64.145 +                    LogText("LocklessTest::Consumer - %5.2f%% done\n",
  64.146 +                            100.0f * (float)oldValue/(float)TestIterations);
  64.147 +                }
  64.148 +            }            
  64.149 +
  64.150 +            // Spin a while
  64.151 +            for (int j = 0; j< 300; j++)
  64.152 +            {
  64.153 +                Dummy3 = j;
  64.154 +            }
  64.155 +
  64.156 +
  64.157 +        } while (oldValue < (TestIterations * 99 / 100));
  64.158 +
  64.159 +        LogText("LocklessTest::Consumer::Run exiting.\n");
  64.160 +        return 0;
  64.161 +    }
  64.162 +
  64.163 +};
  64.164 +
  64.165 +
  64.166 +//-------------------------------------------------------------------------------------
  64.167 +
  64.168 +class Producer : public Thread
  64.169 +{
  64.170 +
  64.171 +    virtual int Run()
  64.172 +    {
  64.173 +        LogText("LocklessTest::Producer::Run started.\n");        
  64.174 +
  64.175 +        for (int testVal = 0; testVal < TestIterations; testVal++)
  64.176 +        {
  64.177 +            TestData d;
  64.178 +            d.Set(testVal);
  64.179 +
  64.180 +            {
  64.181 +                //Lock::Locker scope(&TestLock);
  64.182 +                TestDataUpdater.SetState(d);
  64.183 +            }
  64.184 +
  64.185 +            FirstItemWritten = true;
  64.186 +
  64.187 +            // Spin a bit
  64.188 +            for(int j = 0; j < 1000; j++)
  64.189 +            {
  64.190 +                Dummy2 = j;
  64.191 +            }
  64.192 +
  64.193 +            if (testVal % (TestIterations/30) == 0)
  64.194 +            {
  64.195 +                LogText("LocklessTest::Producer - %5.2f%% done\n",
  64.196 +                        100.0f * (float)testVal/(float)TestIterations);
  64.197 +            }
  64.198 +        }
  64.199 +
  64.200 +        LogText("LocklessTest::Producer::Run exiting.\n");
  64.201 +        return 0;
  64.202 +    }
  64.203 +};
  64.204 +
  64.205 +
  64.206 +} // namespace LocklessTest
  64.207 +
  64.208 +
  64.209 +
  64.210 +void StartLocklessTest()
  64.211 +{
  64.212 +    // These threads will release themselves once done
  64.213 +    Ptr<LocklessTest::Producer> producerThread = *new LocklessTest::Producer;
  64.214 +    Ptr<LocklessTest::Consumer> consumerThread = *new LocklessTest::Consumer;
  64.215 +
  64.216 +    producerThread->Start();
  64.217 +    consumerThread->Start();
  64.218 +
  64.219 +    while (!producerThread->IsFinished() && consumerThread->IsFinished())
  64.220 +    {
  64.221 +        Thread::MSleep(500);
  64.222 +    }
  64.223 +}
  64.224 +
  64.225 +
  64.226 +} // namespace OVR
  64.227 +
  64.228 +#endif // OVR_LOCKLESS_TEST
    65.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    65.2 +++ b/LibOVR/Src/Kernel/OVR_Lockless.h	Wed Jan 14 06:51:16 2015 +0200
    65.3 @@ -0,0 +1,117 @@
    65.4 +/************************************************************************************
    65.5 +
    65.6 +PublicHeader:   OVR_Kernel.h
    65.7 +Filename    :   OVR_Lockless.h
    65.8 +Content     :   Lock-less classes for producer/consumer communication
    65.9 +Created     :   November 9, 2013
   65.10 +Authors     :   John Carmack
   65.11 +
   65.12 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   65.13 +
   65.14 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
   65.15 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
   65.16 +which is provided at the time of installation or download, or which 
   65.17 +otherwise accompanies this software in either electronic or hard copy form.
   65.18 +
   65.19 +You may obtain a copy of the License at
   65.20 +
   65.21 +http://www.oculusvr.com/licenses/LICENSE-3.2 
   65.22 +
   65.23 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
   65.24 +distributed under the License is distributed on an "AS IS" BASIS,
   65.25 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   65.26 +See the License for the specific language governing permissions and
   65.27 +limitations under the License.
   65.28 +
   65.29 +*************************************************************************************/
   65.30 +
   65.31 +#ifndef OVR_Lockless_h
   65.32 +#define OVR_Lockless_h
   65.33 +
   65.34 +#include "OVR_Atomic.h"
   65.35 +
   65.36 +// Define this to compile-in Lockless test logic
   65.37 +//#define OVR_LOCKLESS_TEST
   65.38 +
   65.39 +namespace OVR {
   65.40 +
   65.41 +
   65.42 +// ***** LocklessUpdater
   65.43 +
   65.44 +// For single producer cases where you only care about the most recent update, not
   65.45 +// necessarily getting every one that happens (vsync timing, SensorFusion updates).
   65.46 +//
   65.47 +// This is multiple consumer safe, but is currently only used with a single consumer.
   65.48 +//
   65.49 +// The SlotType can be the same as T, but should probably be a larger fixed size.
   65.50 +// This allows for forward compatibility when the updater is shared between processes.
   65.51 +
   65.52 +// FIXME: ExchangeAdd_Sync() should be replaced with a portable read-only primitive,
   65.53 +// so that the lockless pose state can be read-only on remote processes and to reduce
   65.54 +// false sharing between processes and improve performance.
   65.55 +
   65.56 +template<class T, class SlotType>
   65.57 +class LocklessUpdater
   65.58 +{
   65.59 +public:
   65.60 +	LocklessUpdater() : UpdateBegin( 0 ), UpdateEnd( 0 )
   65.61 +    {
   65.62 +        OVR_COMPILER_ASSERT(sizeof(T) <= sizeof(SlotType));
   65.63 +    }
   65.64 +
   65.65 +	T GetState() const
   65.66 +	{
   65.67 +		// Copy the state out, then retry with the alternate slot
   65.68 +		// if we determine that our copy may have been partially
   65.69 +		// stepped on by a new update.
   65.70 +		T	state;
   65.71 +		int	begin, end, final;
   65.72 +
   65.73 +		for(;;)
   65.74 +		{
   65.75 +			// We are adding 0, only using these as atomic memory barriers, so it
   65.76 +			// is ok to cast off the const, allowing GetState() to remain const.
   65.77 +            end   = UpdateEnd.Load_Acquire();
   65.78 +            state = Slots[ end & 1 ];
   65.79 +            begin = UpdateBegin.Load_Acquire();
   65.80 +			if ( begin == end ) {
   65.81 +				break;
   65.82 +			}
   65.83 +
   65.84 +			// The producer is potentially blocked while only having partially
   65.85 +			// written the update, so copy out the other slot.
   65.86 +            state = Slots[ (begin & 1) ^ 1 ];
   65.87 +            final = UpdateBegin.Load_Acquire();
   65.88 +			if ( final == begin ) {
   65.89 +				break;
   65.90 +			}
   65.91 +
   65.92 +			// The producer completed the last update and started a new one before
   65.93 +			// we got it copied out, so try fetching the current buffer again.
   65.94 +		}
   65.95 +		return state;
   65.96 +	}
   65.97 +
   65.98 +	void	SetState( const T& state )
   65.99 +	{
  65.100 +        const int slot = UpdateBegin.ExchangeAdd_Sync(1) & 1;
  65.101 +        // Write to (slot ^ 1) because ExchangeAdd returns 'previous' value before add.
  65.102 +        Slots[slot ^ 1] = state;
  65.103 +        UpdateEnd.ExchangeAdd_Sync(1);
  65.104 +	}
  65.105 +
  65.106 +    AtomicInt<int> UpdateBegin;
  65.107 +    AtomicInt<int> UpdateEnd;
  65.108 +    SlotType       Slots[2];
  65.109 +};
  65.110 +
  65.111 +
  65.112 +#ifdef OVR_LOCKLESS_TEST
  65.113 +void StartLocklessTest();
  65.114 +#endif
  65.115 +
  65.116 +
  65.117 +} // namespace OVR
  65.118 +
  65.119 +#endif // OVR_Lockless_h
  65.120 +
    66.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    66.2 +++ b/LibOVR/Src/Kernel/OVR_Log.cpp	Wed Jan 14 06:51:16 2015 +0200
    66.3 @@ -0,0 +1,432 @@
    66.4 +/************************************************************************************
    66.5 +
    66.6 +Filename    :   OVR_Log.cpp
    66.7 +Content     :   Logging support
    66.8 +Created     :   September 19, 2012
    66.9 +Notes       : 
   66.10 +
   66.11 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   66.12 +
   66.13 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
   66.14 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
   66.15 +which is provided at the time of installation or download, or which 
   66.16 +otherwise accompanies this software in either electronic or hard copy form.
   66.17 +
   66.18 +You may obtain a copy of the License at
   66.19 +
   66.20 +http://www.oculusvr.com/licenses/LICENSE-3.2 
   66.21 +
   66.22 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
   66.23 +distributed under the License is distributed on an "AS IS" BASIS,
   66.24 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   66.25 +See the License for the specific language governing permissions and
   66.26 +limitations under the License.
   66.27 +
   66.28 +************************************************************************************/
   66.29 +
   66.30 +#include "OVR_Log.h"
   66.31 +#include "OVR_Std.h"
   66.32 +#include <stdarg.h>
   66.33 +#include <stdio.h>
   66.34 +#include <time.h>
   66.35 +#include "../Kernel/OVR_System.h"
   66.36 +#include "../Kernel/OVR_DebugHelp.h"
   66.37 +#include "../Util/Util_SystemGUI.h"
   66.38 +
   66.39 +#if defined(OVR_OS_MS) && !defined(OVR_OS_MS_MOBILE)
   66.40 +#define WIN32_LEAN_AND_MEAN
   66.41 +#include <windows.h>
   66.42 +#elif defined(OVR_OS_ANDROID)
   66.43 +#include <android/log.h>
   66.44 +#elif defined(OVR_OS_LINUX) || defined(OVR_OS_MAC) || defined(OVR_OS_UNIX)
   66.45 +#include <syslog.h>
   66.46 +#endif
   66.47 +
   66.48 +
   66.49 +class LogSubject : public OVR::SystemSingletonBase<LogSubject>
   66.50 +{
   66.51 +    static bool isShuttingDown;
   66.52 +
   66.53 +public:
   66.54 +
   66.55 +    LogSubject(){
   66.56 +        isShuttingDown = false;
   66.57 +        // Must be at end of function
   66.58 +        PushDestroyCallbacks();
   66.59 +    }
   66.60 +    
   66.61 +    virtual ~LogSubject(){} // Required because we use delete this below.
   66.62 +    
   66.63 +    virtual void OnThreadDestroy()
   66.64 +    {
   66.65 +        isShuttingDown = true;
   66.66 +    }
   66.67 +
   66.68 +    virtual void OnSystemDestroy()
   66.69 +    {
   66.70 +        delete this;
   66.71 +    }
   66.72 +
   66.73 +    static bool IsValid() {
   66.74 +        return isShuttingDown == false;
   66.75 +    }
   66.76 +
   66.77 +    OVR::Lock logSubjectLock;
   66.78 +    OVR::ObserverScope<OVR::Log::LogHandler> logSubject;
   66.79 +};
   66.80 +
   66.81 +bool LogSubject::isShuttingDown;
   66.82 +
   66.83 +OVR_DEFINE_SINGLETON(LogSubject);
   66.84 +
   66.85 +namespace OVR {
   66.86 +
   66.87 +    // Global Log pointer.
   66.88 +    Log* volatile OVR_GlobalLog = 0;
   66.89 +
   66.90 +//-----------------------------------------------------------------------------------
   66.91 +// ***** Log Implementation
   66.92 +
   66.93 +Log::Log(unsigned logMask) :
   66.94 +    LoggingMask(logMask)
   66.95 +{
   66.96 +#ifdef OVR_OS_WIN32
   66.97 +    hEventSource = RegisterEventSourceA(NULL, "OculusVR");
   66.98 +    OVR_ASSERT(hEventSource != NULL);
   66.99 +#endif
  66.100 +}
  66.101 +
  66.102 +Log::~Log()
  66.103 +{
  66.104 +#ifdef OVR_OS_WIN32
  66.105 +    if (hEventSource)
  66.106 +    {
  66.107 +        DeregisterEventSource(hEventSource);
  66.108 +    }
  66.109 +#endif
  66.110 +
  66.111 +    // Clear out global log
  66.112 +    if (this == OVR_GlobalLog)
  66.113 +    {
  66.114 +        // TBD: perhaps we should ASSERT if this happens before system shutdown?
  66.115 +        OVR_GlobalLog = 0;
  66.116 +    }
  66.117 +}
  66.118 +void Log::AddLogObserver(ObserverScope<LogHandler> *logObserver)
  66.119 +{
  66.120 +    if (OVR::System::IsInitialized() && LogSubject::GetInstance()->IsValid())
  66.121 +    {
  66.122 +        Lock::Locker locker(&LogSubject::GetInstance()->logSubjectLock);
  66.123 +        logObserver->GetPtr()->Observe(LogSubject::GetInstance()->logSubject);
  66.124 +    }
  66.125 +}
  66.126 +void Log::LogMessageVargInt(LogMessageType messageType, const char* fmt, va_list argList)
  66.127 +{
  66.128 +    if (OVR::System::IsInitialized() && LogSubject::GetInstance()->IsValid())
  66.129 +    {
  66.130 +        // Invoke subject
  66.131 +        char  buffer[MaxLogBufferMessageSize];
  66.132 +        char* pBuffer = buffer;
  66.133 +        char* pAllocated = NULL;
  66.134 +
  66.135 +        #if !defined(OVR_CC_MSVC) // Non-Microsoft compilers require you to save a copy of the va_list.
  66.136 +            va_list argListSaved;
  66.137 +            va_copy(argListSaved, argList);
  66.138 +        #endif
  66.139 +
  66.140 +        int result = FormatLog(pBuffer, MaxLogBufferMessageSize, Log_Text, fmt, argList);
  66.141 +
  66.142 +        if(result >= MaxLogBufferMessageSize) // If there was insufficient capacity...
  66.143 +        {
  66.144 +            pAllocated = (char*)OVR_ALLOC(result + 1); // We assume C++ exceptions are disabled. FormatLog will handle the case that pAllocated is NULL.
  66.145 +            pBuffer = pAllocated;
  66.146 +
  66.147 +            #if !defined(OVR_CC_MSVC)
  66.148 +                va_end(argList); // The caller owns argList and will call va_end on it.
  66.149 +                va_copy(argList, argListSaved);
  66.150 +            #endif
  66.151 +
  66.152 +            FormatLog(pBuffer, (size_t)result + 1, Log_Text, fmt, argList);
  66.153 +        }
  66.154 +
  66.155 +        Lock::Locker locker(&LogSubject::GetInstance()->logSubjectLock);
  66.156 +        LogSubject::GetInstance()->logSubject.GetPtr()->Call(pBuffer, messageType);
  66.157 +
  66.158 +        delete[] pAllocated;
  66.159 +    }
  66.160 +}
  66.161 +
  66.162 +void Log::LogMessageVarg(LogMessageType messageType, const char* fmt, va_list argList)
  66.163 +{
  66.164 +    if ((messageType & LoggingMask) == 0)
  66.165 +        return;
  66.166 +#ifndef OVR_BUILD_DEBUG
  66.167 +    if (IsDebugMessage(messageType))
  66.168 +        return;
  66.169 +#endif
  66.170 +
  66.171 +    char  buffer[MaxLogBufferMessageSize];
  66.172 +    char* pBuffer = buffer;
  66.173 +    char* pAllocated = NULL;
  66.174 +
  66.175 +    #if !defined(OVR_CC_MSVC) // Non-Microsoft compilers require you to save a copy of the va_list.
  66.176 +        va_list argListSaved;
  66.177 +        va_copy(argListSaved, argList);
  66.178 +    #endif
  66.179 +
  66.180 +    int result = FormatLog(pBuffer, MaxLogBufferMessageSize, messageType, fmt, argList);
  66.181 +
  66.182 +    if(result >= MaxLogBufferMessageSize) // If there was insufficient capacity...
  66.183 +    {
  66.184 +        pAllocated = (char*)OVR_ALLOC(result + 1); // We assume C++ exceptions are disabled. FormatLog will handle the case that pAllocated is NULL.
  66.185 +        pBuffer = pAllocated;
  66.186 +
  66.187 +        #if !defined(OVR_CC_MSVC)
  66.188 +            va_end(argList); // The caller owns argList and will call va_end on it.
  66.189 +            va_copy(argList, argListSaved);
  66.190 +        #endif
  66.191 +
  66.192 +        FormatLog(pBuffer, (size_t)result + 1, messageType, fmt, argList);
  66.193 +    }
  66.194 +
  66.195 +    DefaultLogOutput(pBuffer, messageType, result);
  66.196 +    delete[] pAllocated;
  66.197 +}
  66.198 +
  66.199 +void OVR::Log::LogMessage(LogMessageType messageType, const char* pfmt, ...)
  66.200 +{
  66.201 +    va_list argList;
  66.202 +    va_start(argList, pfmt);
  66.203 +    LogMessageVarg(messageType, pfmt, argList);
  66.204 +    va_end(argList);
  66.205 +}
  66.206 +
  66.207 +
  66.208 +// Return behavior is the same as ISO C vsnprintf: returns the required strlen of buffer (which will 
  66.209 +// be >= bufferSize if bufferSize is insufficient) or returns a negative value because the input was bad.
  66.210 +int Log::FormatLog(char* buffer, size_t bufferSize, LogMessageType messageType,
  66.211 +                    const char* fmt, va_list argList)
  66.212 +{
  66.213 +    OVR_ASSERT(buffer && (bufferSize >= 10)); // Need to be able to at least print "Assert: \n" to it.
  66.214 +    if(!buffer || (bufferSize < 10))
  66.215 +        return -1;
  66.216 +
  66.217 +    int addNewline = 1;
  66.218 +    int prefixLength = 0;
  66.219 +
  66.220 +    switch(messageType)
  66.221 +    {
  66.222 +    case Log_Error:      OVR_strcpy(buffer, bufferSize, "Error: ");  prefixLength = 7; break;
  66.223 +    case Log_Debug:      OVR_strcpy(buffer, bufferSize, "Debug: ");  prefixLength = 7; break;
  66.224 +    case Log_Assert:     OVR_strcpy(buffer, bufferSize, "Assert: "); prefixLength = 8; break;
  66.225 +    case Log_Text:       buffer[0] = 0; addNewline = 0; break;
  66.226 +    case Log_DebugText:  buffer[0] = 0; addNewline = 0; break;
  66.227 +    default:             buffer[0] = 0; addNewline = 0; break;
  66.228 +    }
  66.229 +
  66.230 +    char*  buffer2       = buffer + prefixLength;
  66.231 +    size_t size2         = bufferSize - (size_t)prefixLength;
  66.232 +    int    messageLength = OVR_vsnprintf(buffer2, size2, fmt, argList);
  66.233 +
  66.234 +    if (addNewline)
  66.235 +    {
  66.236 +        if (messageLength < 0) // If there was a format error... 
  66.237 +        {
  66.238 +            // To consider: append <format error> to the buffer here.
  66.239 +            buffer2[0] = '\n'; // We are guaranteed to have capacity for this.
  66.240 +            buffer2[1] = '\0';
  66.241 +        }
  66.242 +        else
  66.243 +        {
  66.244 +            // If the printed string used all of the capacity or required more than the capacity,
  66.245 +            // Chop the output by one character so we can append the \n safely.
  66.246 +            int messageEnd = (messageLength >= (int)(size2 - 1)) ? (int)(size2 - 2) : messageLength;
  66.247 +            buffer2[messageEnd + 0] = '\n';
  66.248 +            buffer2[messageEnd + 1] = '\0';
  66.249 +        }
  66.250 +    }
  66.251 +
  66.252 +    if (messageLength >= 0) // If the format was OK...
  66.253 +        return prefixLength + messageLength + addNewline; // Return the required strlen of buffer.
  66.254 +
  66.255 +    return messageLength; // Else we cannot know what the required strlen is and return the error to the caller.
  66.256 +}
  66.257 +
  66.258 +void Log::DefaultLogOutput(const char* formattedText, LogMessageType messageType, int bufferSize)
  66.259 +{
  66.260 +    bool debug = IsDebugMessage(messageType);
  66.261 +    OVR_UNUSED(bufferSize);
  66.262 +
  66.263 +#if defined(OVR_OS_WIN32)
  66.264 +    // Under Win32, output regular messages to console if it exists; debug window otherwise.
  66.265 +    static DWORD dummyMode;
  66.266 +    static bool  hasConsole = (GetStdHandle(STD_OUTPUT_HANDLE) != INVALID_HANDLE_VALUE) &&
  66.267 +                              (GetConsoleMode(GetStdHandle(STD_OUTPUT_HANDLE), &dummyMode));
  66.268 +
  66.269 +    if (!hasConsole || debug)
  66.270 +    {
  66.271 +        ::OutputDebugStringA(formattedText);
  66.272 +    }
  66.273 +
  66.274 +    fputs(formattedText, stdout);
  66.275 +
  66.276 +#elif defined(OVR_OS_MS) // Any other Microsoft OSs
  66.277 +
  66.278 +    ::OutputDebugStringA(formattedText);
  66.279 +
  66.280 +#elif defined(OVR_OS_ANDROID)
  66.281 +    // To do: use bufferSize to deal with the case that Android has a limited output length.
  66.282 +    __android_log_write(ANDROID_LOG_INFO, "OVR", formattedText);
  66.283 +
  66.284 +#else
  66.285 +    fputs(formattedText, stdout);
  66.286 +
  66.287 +#endif
  66.288 +
  66.289 +    if (messageType == Log_Error)
  66.290 +    {
  66.291 +#if defined(OVR_OS_WIN32)
  66.292 +        if (!ReportEventA(hEventSource, EVENTLOG_ERROR_TYPE, 0, 0, NULL, 1, 0, &formattedText, NULL))
  66.293 +        {
  66.294 +            OVR_ASSERT(false);
  66.295 +        }
  66.296 +#elif defined(OVR_OS_MS) // Any other Microsoft OSs
  66.297 +        // TBD
  66.298 +#elif defined(OVR_OS_ANDROID)
  66.299 +        // TBD
  66.300 +#elif defined(OVR_OS_MAC) || defined(OVR_OS_LINUX)
  66.301 +        syslog(LOG_ERR, "%s", formattedText);
  66.302 +#else
  66.303 +        // TBD
  66.304 +#endif
  66.305 +    }
  66.306 +
  66.307 +    // Just in case.
  66.308 +    OVR_UNUSED2(formattedText, debug);
  66.309 +}
  66.310 +
  66.311 +
  66.312 +//static
  66.313 +void Log::SetGlobalLog(Log *log)
  66.314 +{
  66.315 +    OVR_GlobalLog = log;
  66.316 +}
  66.317 +//static
  66.318 +Log* Log::GetGlobalLog()
  66.319 +{
  66.320 +// No global log by default?
  66.321 +//    if (!OVR_GlobalLog)
  66.322 +//        OVR_GlobalLog = GetDefaultLog();
  66.323 +    return OVR_GlobalLog;
  66.324 +}
  66.325 +
  66.326 +//static
  66.327 +Log* Log::GetDefaultLog()
  66.328 +{
  66.329 +    // Create default log pointer statically so that it can be used
  66.330 +    // even during startup.
  66.331 +    static Log defaultLog;
  66.332 +    return &defaultLog;
  66.333 +}
  66.334 +
  66.335 +
  66.336 +//-----------------------------------------------------------------------------------
  66.337 +// ***** Global Logging functions
  66.338 +
  66.339 +#if !defined(OVR_CC_MSVC)
  66.340 +// The reason for va_copy is because you can't use va_start twice on Linux
  66.341 +#define OVR_LOG_FUNCTION_IMPL(Name)  \
  66.342 +    void Log##Name(const char* fmt, ...) \
  66.343 +    {                                                                    \
  66.344 +        if (OVR_GlobalLog)                                               \
  66.345 +        {                                                                \
  66.346 +            va_list argList1;                                             \
  66.347 +            va_start(argList1, fmt);                                     \
  66.348 +            va_list argList2;                                             \
  66.349 +            va_copy(argList2, argList1);                                 \
  66.350 +            OVR_GlobalLog->LogMessageVargInt(Log_##Name, fmt, argList2); \
  66.351 +            va_end(argList2);                                             \
  66.352 +            OVR_GlobalLog->LogMessageVarg(Log_##Name, fmt, argList1);    \
  66.353 +            va_end(argList1);                                            \
  66.354 +        }                                                                \
  66.355 +    }
  66.356 +#else
  66.357 +#define OVR_LOG_FUNCTION_IMPL(Name)  \
  66.358 +    void Log##Name(const char* fmt, ...) \
  66.359 +    {                                                                    \
  66.360 +        if (OVR_GlobalLog)                                               \
  66.361 +        {                                                                \
  66.362 +            va_list argList1;                                             \
  66.363 +            va_start(argList1, fmt);                                     \
  66.364 +            OVR_GlobalLog->LogMessageVargInt(Log_##Name, fmt, argList1); \
  66.365 +            OVR_GlobalLog->LogMessageVarg(Log_##Name, fmt, argList1);    \
  66.366 +            va_end(argList1);                                            \
  66.367 +        }                                                                \
  66.368 +    }
  66.369 +#endif // #if !defined(OVR_OS_WIN32)
  66.370 +
  66.371 +OVR_LOG_FUNCTION_IMPL(Text)
  66.372 +OVR_LOG_FUNCTION_IMPL(Error)
  66.373 +
  66.374 +#ifdef OVR_BUILD_DEBUG
  66.375 +OVR_LOG_FUNCTION_IMPL(DebugText)
  66.376 +OVR_LOG_FUNCTION_IMPL(Debug)
  66.377 +OVR_LOG_FUNCTION_IMPL(Assert)
  66.378 +#endif
  66.379 +
  66.380 +
  66.381 +
  66.382 +// Assertion handler support
  66.383 +// To consider: Move this to an OVR_Types.cpp or OVR_Assert.cpp source file.
  66.384 +
  66.385 +static OVRAssertionHandler sOVRAssertionHandler = OVR::DefaultAssertionHandler;
  66.386 +static intptr_t sOVRAssertionHandlerUserParameter = 0;
  66.387 +
  66.388 +OVRAssertionHandler GetAssertionHandler(intptr_t* userParameter)
  66.389 +{
  66.390 +    if(userParameter)
  66.391 +        *userParameter = sOVRAssertionHandlerUserParameter;
  66.392 +    return sOVRAssertionHandler;
  66.393 +}
  66.394 +
  66.395 +void SetAssertionHandler(OVRAssertionHandler assertionHandler, intptr_t userParameter)
  66.396 +{
  66.397 +    sOVRAssertionHandler = assertionHandler;
  66.398 +    sOVRAssertionHandlerUserParameter = userParameter;
  66.399 +}
  66.400 +
  66.401 +intptr_t DefaultAssertionHandler(intptr_t /*userParameter*/, const char* title, const char* message)
  66.402 +{
  66.403 +    if(OVRIsDebuggerPresent())
  66.404 +    {
  66.405 +        OVR_DEBUG_BREAK;
  66.406 +    }
  66.407 +    else
  66.408 +    {
  66.409 +        #if defined(OVR_BUILD_DEBUG)
  66.410 +            // Print a stack trace of all threads.
  66.411 +            OVR::String s;
  66.412 +            OVR::String threadListOutput;
  66.413 +            static OVR::SymbolLookup symbolLookup;
  66.414 +
  66.415 +            s = "Failure: "; 
  66.416 +            s += message;
  66.417 +
  66.418 +            if(symbolLookup.Initialize() && symbolLookup.ReportThreadCallstack(threadListOutput, 4)) // This '4' is there to skip our internal handling and retrieve starting at the assertion location (our caller) only.
  66.419 +            {
  66.420 +                s += "\r\n\r\n";
  66.421 +                s += threadListOutput;
  66.422 +            }
  66.423 +
  66.424 +            OVR::Util::DisplayMessageBox(title, s.ToCStr());
  66.425 +        #else
  66.426 +            OVR::Util::DisplayMessageBox(title, message);
  66.427 +        #endif
  66.428 +    }
  66.429 +    
  66.430 +    return 0;
  66.431 +}
  66.432 +
  66.433 +
  66.434 +
  66.435 +} // OVR
    67.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    67.2 +++ b/LibOVR/Src/Kernel/OVR_Log.h	Wed Jan 14 06:51:16 2015 +0200
    67.3 @@ -0,0 +1,227 @@
    67.4 +/************************************************************************************
    67.5 +
    67.6 +PublicHeader:   OVR
    67.7 +Filename    :   OVR_Log.h
    67.8 +Content     :   Logging support
    67.9 +Created     :   September 19, 2012
   67.10 +Notes       : 
   67.11 +
   67.12 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   67.13 +
   67.14 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
   67.15 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
   67.16 +which is provided at the time of installation or download, or which 
   67.17 +otherwise accompanies this software in either electronic or hard copy form.
   67.18 +
   67.19 +You may obtain a copy of the License at
   67.20 +
   67.21 +http://www.oculusvr.com/licenses/LICENSE-3.2 
   67.22 +
   67.23 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
   67.24 +distributed under the License is distributed on an "AS IS" BASIS,
   67.25 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   67.26 +See the License for the specific language governing permissions and
   67.27 +limitations under the License.
   67.28 +
   67.29 +************************************************************************************/
   67.30 +
   67.31 +#ifndef OVR_Log_h
   67.32 +#define OVR_Log_h
   67.33 +
   67.34 +#include "OVR_Types.h"
   67.35 +#include "../Kernel/OVR_Delegates.h"
   67.36 +#include "../Kernel//OVR_Observer.h"
   67.37 +#include <stdarg.h>
   67.38 +
   67.39 +namespace OVR {
   67.40 +
   67.41 +//-----------------------------------------------------------------------------------
   67.42 +// ***** Logging Constants
   67.43 +
   67.44 +// LogMaskConstants defined bit mask constants that describe what log messages
   67.45 +// should be displayed.
   67.46 +enum LogMaskConstants
   67.47 +{
   67.48 +    LogMask_Regular = 0x100,
   67.49 +    LogMask_Debug   = 0x200,
   67.50 +    LogMask_None    = 0,
   67.51 +    LogMask_All     = LogMask_Regular|LogMask_Debug
   67.52 +};
   67.53 +
   67.54 +
   67.55 +// LogMessageType describes the type of the log message, controls when it is
   67.56 +// displayed and what prefix/suffix is given to it. Messages are subdivided into
   67.57 +// regular and debug logging types. Debug logging is only generated in debug builds.
   67.58 +//
   67.59 +// Log_Text         - General output text displayed without prefix or new-line.
   67.60 +//                    Used in OVR libraries for general log flow messages
   67.61 +//                    such as "Device Initialized".
   67.62 +//
   67.63 +// Log_Error        - Error message output with "Error: %s\n", intended for
   67.64 +//                    application/sample-level use only, in cases where an expected
   67.65 +//                    operation failed. OVR libraries should not use this internally,
   67.66 +//                    reporting status codes instead.
   67.67 +//
   67.68 +// Log_DebugText    - Message without prefix or new lines; output in Debug build only.
   67.69 +//
   67.70 +// Log_Debug        - Debug-build only message, formatted with "Debug: %s\n".
   67.71 +//                    Intended to comment on incorrect API usage that doesn't lead
   67.72 +//                    to crashes but can be avoided with proper use.
   67.73 +//                    There is no Debug Error on purpose, since real errors should
   67.74 +//                    be handled by API user.
   67.75 +//
   67.76 +// Log_Assert      -  Debug-build only message, formatted with "Assert: %s\n".
   67.77 +//                    Intended for severe unrecoverable conditions in library
   67.78 +//                    source code. Generated though OVR_ASSERT_MSG(c, "Text").
   67.79 +
   67.80 +enum LogMessageType
   67.81 +{    
   67.82 +    // General Logging
   67.83 +    Log_Text        = LogMask_Regular | 0,    
   67.84 +    Log_Error       = LogMask_Regular | 1, // "Error: %s\n".
   67.85 +    
   67.86 +    // Debug-only messages (not generated in release build)
   67.87 +    Log_DebugText   = LogMask_Debug | 0,
   67.88 +    Log_Debug       = LogMask_Debug | 1,   // "Debug: %s\n".
   67.89 +    Log_Assert      = LogMask_Debug | 2,   // "Assert: %s\n".
   67.90 +};
   67.91 +
   67.92 +
   67.93 +// LOG_VAARG_ATTRIBUTE macro, enforces printf-style fromatting for message types
   67.94 +#ifdef __GNUC__
   67.95 +#  define OVR_LOG_VAARG_ATTRIBUTE(a,b) __attribute__((format (printf, a, b)))
   67.96 +#else
   67.97 +#  define OVR_LOG_VAARG_ATTRIBUTE(a,b)
   67.98 +#endif
   67.99 +
  67.100 +//-----------------------------------------------------------------------------------
  67.101 +// ***** Log
  67.102 +
  67.103 +// Log defines a base class interface that can be implemented to catch both
  67.104 +// debug and runtime messages.
  67.105 +// Debug logging can be overridden by calling Log::SetGlobalLog.
  67.106 +
  67.107 +class Log
  67.108 +{
  67.109 +	friend class System;
  67.110 +
  67.111 +#ifdef OVR_OS_WIN32
  67.112 +    void* hEventSource;
  67.113 +#endif
  67.114 +
  67.115 +public: 
  67.116 +    Log(unsigned logMask = LogMask_Debug);
  67.117 +    virtual ~Log();
  67.118 +
  67.119 +	typedef Delegate2<void, const char*, LogMessageType> LogHandler;
  67.120 +
  67.121 +    // The following is deprecated, as there is no longer a max log buffer message size.
  67.122 +    enum { MaxLogBufferMessageSize = 4096 };
  67.123 +
  67.124 +    unsigned        GetLoggingMask() const            { return LoggingMask; }
  67.125 +    void            SetLoggingMask(unsigned logMask)  { LoggingMask = logMask; }
  67.126 +
  67.127 +	// Internal
  67.128 +	// Invokes observers, then calls LogMessageVarg()
  67.129 +	static void    LogMessageVargInt(LogMessageType messageType, const char* fmt, va_list argList);
  67.130 +
  67.131 +    // This virtual function receives all the messages,
  67.132 +    // developers should override this function in order to do custom logging
  67.133 +    virtual void    LogMessageVarg(LogMessageType messageType, const char* fmt, va_list argList);
  67.134 +
  67.135 +	static void		AddLogObserver(ObserverScope<LogHandler> *logObserver);
  67.136 +
  67.137 +    // Call the logging function with specific message type, with no type filtering.
  67.138 +    void            LogMessage(LogMessageType messageType,
  67.139 +                               const char* fmt, ...) OVR_LOG_VAARG_ATTRIBUTE(3,4);
  67.140 +
  67.141 +
  67.142 +    // Helper used by LogMessageVarg to format the log message, writing the resulting
  67.143 +    // string into buffer. It formats text based on fmt and appends prefix/new line
  67.144 +    // based on LogMessageType. Return behavior is the same as ISO C vsnprintf: returns the 
  67.145 +    // required strlen of buffer (which will be >= bufferSize if bufferSize is insufficient)
  67.146 +    // or returns a negative value because the input was bad.
  67.147 +    static int     FormatLog(char* buffer, size_t bufferSize, LogMessageType messageType,
  67.148 +                              const char* fmt, va_list argList);
  67.149 +
  67.150 +    // Default log output implementation used by by LogMessageVarg.
  67.151 +    // Debug flag may be used to re-direct output on some platforms, but doesn't
  67.152 +    // necessarily disable it in release builds; that is the job of the called.    
  67.153 +    void            DefaultLogOutput(const char* textBuffer, LogMessageType messageType, int bufferSize = -1);
  67.154 +
  67.155 +    // Determines if the specified message type is for debugging only.
  67.156 +    static bool     IsDebugMessage(LogMessageType messageType)
  67.157 +    {
  67.158 +        return (messageType & LogMask_Debug) != 0;
  67.159 +    }
  67.160 +
  67.161 +    // *** Global APIs
  67.162 +
  67.163 +    // Global Log registration APIs.
  67.164 +    //  - Global log is used for OVR_DEBUG messages. Set global log to null (0)
  67.165 +    //    to disable all logging.
  67.166 +    static void     SetGlobalLog(Log *log);
  67.167 +    static Log*     GetGlobalLog();
  67.168 +
  67.169 +    // Returns default log singleton instance.
  67.170 +    static Log*     GetDefaultLog();
  67.171 +
  67.172 +    // Applies logMask to the default log and returns a pointer to it.
  67.173 +    // By default, only Debug logging is enabled, so to avoid SDK generating console
  67.174 +    // messages in user app (those are always disabled in release build,
  67.175 +    // even if the flag is set). This function is useful in System constructor.
  67.176 +    static Log*     ConfigureDefaultLog(unsigned logMask = LogMask_Debug)
  67.177 +    {
  67.178 +        Log* log = GetDefaultLog();
  67.179 +        log->SetLoggingMask(logMask);
  67.180 +        return log;
  67.181 +    }
  67.182 +
  67.183 +private:
  67.184 +    // Logging mask described by LogMaskConstants.
  67.185 +    unsigned    LoggingMask;
  67.186 +};
  67.187 +
  67.188 +
  67.189 +//-----------------------------------------------------------------------------------
  67.190 +// ***** Global Logging Functions and Debug Macros
  67.191 +
  67.192 +// These functions will output text to global log with semantics described by
  67.193 +// their LogMessageType.
  67.194 +void LogText(const char* fmt, ...) OVR_LOG_VAARG_ATTRIBUTE(1,2);
  67.195 +void LogError(const char* fmt, ...) OVR_LOG_VAARG_ATTRIBUTE(1,2);
  67.196 +
  67.197 +#ifdef OVR_BUILD_DEBUG
  67.198 +
  67.199 +    // Debug build only logging.
  67.200 +    void LogDebugText(const char* fmt, ...) OVR_LOG_VAARG_ATTRIBUTE(1,2);
  67.201 +    void LogDebug(const char* fmt, ...) OVR_LOG_VAARG_ATTRIBUTE(1,2);
  67.202 +    void LogAssert(const char* fmt, ...) OVR_LOG_VAARG_ATTRIBUTE(1,2);
  67.203 +
  67.204 +    // Macro to do debug logging, printf-style.
  67.205 +    // An extra set of set of parenthesis must be used around arguments,
  67.206 +    // as in: OVR_DEBUG_LOG(("Value %d", 2)).
  67.207 +    #define OVR_DEBUG_LOG(args)       do { OVR::LogDebug args; } while(0)
  67.208 +    #define OVR_DEBUG_LOG_TEXT(args)  do { OVR::LogDebugText args; } while(0)
  67.209 +
  67.210 +	// Conditional logging. It logs when the condition 'c' is true.
  67.211 +	#define OVR_DEBUG_LOG_COND(c, args)			do { if ((c)) { OVR::LogDebug args; } } while(0)
  67.212 +	#define OVR_DEBUG_LOG_TEXT_COND(c, args)	do { if ((c)) { OVR::LogDebugText args; } } while(0)
  67.213 +
  67.214 +	// Conditional logging & asserting. It asserts/logs when the condition 'c' is NOT true.
  67.215 +    #define OVR_ASSERT_LOG(c, args)	  do { if (!(c)) { OVR::LogAssert args; OVR_DEBUG_BREAK; } } while(0)
  67.216 +
  67.217 +#else
  67.218 +
  67.219 +    // If not in debug build, macros do nothing.
  67.220 +    #define OVR_DEBUG_LOG(args)				((void)0)
  67.221 +    #define OVR_DEBUG_LOG_TEXT(args)		((void)0)
  67.222 +	#define OVR_DEBUG_LOG_COND(c, args)		((void)0)
  67.223 +	#define OVR_DEBUG_LOG_TEXT_COND(args)	((void)0)
  67.224 +    #define OVR_ASSERT_LOG(c, args)			((void)0)
  67.225 +
  67.226 +#endif
  67.227 +
  67.228 +} // OVR 
  67.229 +
  67.230 +#endif
    68.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    68.2 +++ b/LibOVR/Src/Kernel/OVR_Math.cpp	Wed Jan 14 06:51:16 2015 +0200
    68.3 @@ -0,0 +1,58 @@
    68.4 +/************************************************************************************
    68.5 +
    68.6 +Filename    :   OVR_Math.h
    68.7 +Content     :   Implementation of 3D primitives such as vectors, matrices.
    68.8 +Created     :   September 4, 2012
    68.9 +Authors     :   Andrew Reisse, Michael Antonov, Anna Yershova
   68.10 +
   68.11 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   68.12 +
   68.13 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
   68.14 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
   68.15 +which is provided at the time of installation or download, or which 
   68.16 +otherwise accompanies this software in either electronic or hard copy form.
   68.17 +
   68.18 +You may obtain a copy of the License at
   68.19 +
   68.20 +http://www.oculusvr.com/licenses/LICENSE-3.2 
   68.21 +
   68.22 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
   68.23 +distributed under the License is distributed on an "AS IS" BASIS,
   68.24 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   68.25 +See the License for the specific language governing permissions and
   68.26 +limitations under the License.
   68.27 +
   68.28 +*************************************************************************************/
   68.29 +
   68.30 +#include "OVR_Math.h"
   68.31 +#include "OVR_Log.h"
   68.32 +
   68.33 +#include <float.h>
   68.34 +
   68.35 +
   68.36 +namespace OVR {
   68.37 +
   68.38 +
   68.39 +//-------------------------------------------------------------------------------------
   68.40 +// ***** Constants
   68.41 +
   68.42 +template<>
   68.43 +const Vector3<float> Vector3<float>::ZERO = Vector3<float>();
   68.44 +
   68.45 +template<>
   68.46 +const Vector3<double> Vector3<double>::ZERO = Vector3<double>();
   68.47 +
   68.48 +template<>
   68.49 +const Matrix4<float> Matrix4<float>::IdentityValue = Matrix4<float>(1.0f, 0.0f, 0.0f, 0.0f, 
   68.50 +                                                                    0.0f, 1.0f, 0.0f, 0.0f, 
   68.51 +                                                                    0.0f, 0.0f, 1.0f, 0.0f,
   68.52 +                                                                    0.0f, 0.0f, 0.0f, 1.0f);
   68.53 +
   68.54 +template<>
   68.55 +const Matrix4<double> Matrix4<double>::IdentityValue = Matrix4<double>(1.0, 0.0, 0.0, 0.0, 
   68.56 +                                                                       0.0, 1.0, 0.0, 0.0, 
   68.57 +                                                                       0.0, 0.0, 1.0, 0.0,
   68.58 +                                                                       0.0, 0.0, 0.0, 1.0);
   68.59 +
   68.60 +
   68.61 +} // Namespace OVR
    69.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    69.2 +++ b/LibOVR/Src/Kernel/OVR_Math.h	Wed Jan 14 06:51:16 2015 +0200
    69.3 @@ -0,0 +1,2791 @@
    69.4 +/************************************************************************************
    69.5 +
    69.6 +PublicHeader:   OVR_Kernel.h
    69.7 +Filename    :   OVR_Math.h
    69.8 +Content     :   Implementation of 3D primitives such as vectors, matrices.
    69.9 +Created     :   September 4, 2012
   69.10 +Authors     :   Andrew Reisse, Michael Antonov, Steve LaValle, 
   69.11 +				Anna Yershova, Max Katsev, Dov Katz
   69.12 +
   69.13 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   69.14 +
   69.15 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
   69.16 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
   69.17 +which is provided at the time of installation or download, or which 
   69.18 +otherwise accompanies this software in either electronic or hard copy form.
   69.19 +
   69.20 +You may obtain a copy of the License at
   69.21 +
   69.22 +http://www.oculusvr.com/licenses/LICENSE-3.2 
   69.23 +
   69.24 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
   69.25 +distributed under the License is distributed on an "AS IS" BASIS,
   69.26 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   69.27 +See the License for the specific language governing permissions and
   69.28 +limitations under the License.
   69.29 +
   69.30 +*************************************************************************************/
   69.31 +
   69.32 +#ifndef OVR_Math_h
   69.33 +#define OVR_Math_h
   69.34 +
   69.35 +#include <assert.h>
   69.36 +#include <stdlib.h>
   69.37 +#include <math.h>
   69.38 +
   69.39 +#include "OVR_Types.h"
   69.40 +#include "OVR_RefCount.h"
   69.41 +#include "OVR_Std.h"
   69.42 +#include "OVR_Alg.h"
   69.43 +
   69.44 +
   69.45 +namespace OVR {
   69.46 +
   69.47 +//-------------------------------------------------------------------------------------
   69.48 +// ***** Constants for 3D world/axis definitions.
   69.49 +
   69.50 +// Definitions of axes for coordinate and rotation conversions.
   69.51 +enum Axis
   69.52 +{
   69.53 +    Axis_X = 0, Axis_Y = 1, Axis_Z = 2
   69.54 +};
   69.55 +
   69.56 +// RotateDirection describes the rotation direction around an axis, interpreted as follows:
   69.57 +//  CW  - Clockwise while looking "down" from positive axis towards the origin.
   69.58 +//  CCW - Counter-clockwise while looking from the positive axis towards the origin,
   69.59 +//        which is in the negative axis direction.
   69.60 +//  CCW is the default for the RHS coordinate system. Oculus standard RHS coordinate
   69.61 +//  system defines Y up, X right, and Z back (pointing out from the screen). In this
   69.62 +//  system Rotate_CCW around Z will specifies counter-clockwise rotation in XY plane.
   69.63 +enum RotateDirection
   69.64 +{
   69.65 +    Rotate_CCW = 1,
   69.66 +    Rotate_CW  = -1 
   69.67 +};
   69.68 +
   69.69 +// Constants for right handed and left handed coordinate systems
   69.70 +enum HandedSystem
   69.71 +{
   69.72 +    Handed_R = 1, Handed_L = -1
   69.73 +};
   69.74 +
   69.75 +// AxisDirection describes which way the coordinate axis points. Used by WorldAxes.
   69.76 +enum AxisDirection
   69.77 +{
   69.78 +    Axis_Up    =  2,
   69.79 +    Axis_Down  = -2,
   69.80 +    Axis_Right =  1,
   69.81 +    Axis_Left  = -1,
   69.82 +    Axis_In    =  3,
   69.83 +    Axis_Out   = -3
   69.84 +};
   69.85 +
   69.86 +struct WorldAxes
   69.87 +{
   69.88 +    AxisDirection XAxis, YAxis, ZAxis;
   69.89 +
   69.90 +    WorldAxes(AxisDirection x, AxisDirection y, AxisDirection z)
   69.91 +        : XAxis(x), YAxis(y), ZAxis(z) 
   69.92 +    { OVR_ASSERT(abs(x) != abs(y) && abs(y) != abs(z) && abs(z) != abs(x));}
   69.93 +};
   69.94 +
   69.95 +} // namespace OVR
   69.96 +
   69.97 +
   69.98 +//------------------------------------------------------------------------------------//
   69.99 +// ***** C Compatibility Types
  69.100 +
  69.101 +// These declarations are used to support conversion between C types used in
  69.102 +// LibOVR C interfaces and their C++ versions. As an example, they allow passing
  69.103 +// Vector3f into a function that expects ovrVector3f.
  69.104 +
  69.105 +typedef struct ovrQuatf_ ovrQuatf;
  69.106 +typedef struct ovrQuatd_ ovrQuatd;
  69.107 +typedef struct ovrSizei_ ovrSizei;
  69.108 +typedef struct ovrSizef_ ovrSizef;
  69.109 +typedef struct ovrRecti_ ovrRecti;
  69.110 +typedef struct ovrVector2i_ ovrVector2i;
  69.111 +typedef struct ovrVector2f_ ovrVector2f;
  69.112 +typedef struct ovrVector3f_ ovrVector3f;
  69.113 +typedef struct ovrVector3d_ ovrVector3d;
  69.114 +typedef struct ovrMatrix3d_ ovrMatrix3d;
  69.115 +typedef struct ovrMatrix4f_ ovrMatrix4f;
  69.116 +typedef struct ovrPosef_ ovrPosef;
  69.117 +typedef struct ovrPosed_ ovrPosed;
  69.118 +typedef struct ovrPoseStatef_ ovrPoseStatef;
  69.119 +typedef struct ovrPoseStated_ ovrPoseStated;
  69.120 +
  69.121 +namespace OVR {
  69.122 +
  69.123 +// Forward-declare our templates.
  69.124 +template<class T> class Quat;
  69.125 +template<class T> class Size;
  69.126 +template<class T> class Rect;
  69.127 +template<class T> class Vector2;
  69.128 +template<class T> class Vector3;
  69.129 +template<class T> class Matrix3;
  69.130 +template<class T> class Matrix4;
  69.131 +template<class T> class Pose;
  69.132 +template<class T> class PoseState;
  69.133 +
  69.134 +// CompatibleTypes::Type is used to lookup a compatible C-version of a C++ class.
  69.135 +template<class C>
  69.136 +struct CompatibleTypes
  69.137 +{    
  69.138 +    // Declaration here seems necessary for MSVC; specializations are
  69.139 +    // used instead.
  69.140 +    typedef struct {} Type;
  69.141 +};
  69.142 +
  69.143 +// Specializations providing CompatibleTypes::Type value.
  69.144 +template<> struct CompatibleTypes<Quat<float> >     { typedef ovrQuatf Type; };
  69.145 +template<> struct CompatibleTypes<Quat<double> >    { typedef ovrQuatd Type; };
  69.146 +template<> struct CompatibleTypes<Matrix3<double> > { typedef ovrMatrix3d Type; };
  69.147 +template<> struct CompatibleTypes<Matrix4<float> >  { typedef ovrMatrix4f Type; };
  69.148 +template<> struct CompatibleTypes<Size<int> >       { typedef ovrSizei Type; };
  69.149 +template<> struct CompatibleTypes<Size<float> >     { typedef ovrSizef Type; };
  69.150 +template<> struct CompatibleTypes<Rect<int> >       { typedef ovrRecti Type; };
  69.151 +template<> struct CompatibleTypes<Vector2<int> >    { typedef ovrVector2i Type; };
  69.152 +template<> struct CompatibleTypes<Vector2<float> >  { typedef ovrVector2f Type; };
  69.153 +template<> struct CompatibleTypes<Vector3<float> >  { typedef ovrVector3f Type; };
  69.154 +template<> struct CompatibleTypes<Vector3<double> > { typedef ovrVector3d Type; };
  69.155 +
  69.156 +template<> struct CompatibleTypes<Pose<float> > { typedef ovrPosef Type; };
  69.157 +template<> struct CompatibleTypes<Pose<double> > { typedef ovrPosed Type; };
  69.158 +
  69.159 +//------------------------------------------------------------------------------------//
  69.160 +// ***** Math
  69.161 +//
  69.162 +// Math class contains constants and functions. This class is a template specialized
  69.163 +// per type, with Math<float> and Math<double> being distinct.
  69.164 +template<class Type>
  69.165 +class Math
  69.166 +{  
  69.167 +public:
  69.168 +    // By default, support explicit conversion to float. This allows Vector2<int> to
  69.169 +    // compile, for example.
  69.170 +    typedef float OtherFloatType;
  69.171 +};
  69.172 +
  69.173 +
  69.174 +#define MATH_FLOAT_PI                (3.1415926f)
  69.175 +#define MATH_FLOAT_TWOPI             (2.0f *MATH_FLOAT_PI)
  69.176 +#define MATH_FLOAT_PIOVER2           (0.5f *MATH_FLOAT_PI)
  69.177 +#define MATH_FLOAT_PIOVER4           (0.25f*MATH_FLOAT_PI)
  69.178 +#define MATH_FLOAT_E                 (2.7182818f)
  69.179 +#define MATH_FLOAT_MAXVALUE			 (FLT_MAX) 
  69.180 +#define MATH_FLOAT MINPOSITIVEVALUE  (FLT_MIN)  
  69.181 +#define MATH_FLOAT_RADTODEGREEFACTOR (360.0f / MATH_FLOAT_TWOPI)
  69.182 +#define MATH_FLOAT_DEGREETORADFACTOR (MATH_FLOAT_TWOPI / 360.0f)
  69.183 +#define MATH_FLOAT_TOLERANCE		 (0.00001f)
  69.184 +#define MATH_FLOAT_SINGULARITYRADIUS (0.0000001f) // Use for Gimbal lock numerical problems
  69.185 +
  69.186 +#define MATH_DOUBLE_PI                (3.14159265358979)
  69.187 +#define MATH_DOUBLE_TWOPI             (2.0f *MATH_DOUBLE_PI)
  69.188 +#define MATH_DOUBLE_PIOVER2           (0.5f *MATH_DOUBLE_PI)
  69.189 +#define MATH_DOUBLE_PIOVER4           (0.25f*MATH_DOUBLE_PI)
  69.190 +#define MATH_DOUBLE_E                 (2.71828182845905)
  69.191 +#define MATH_DOUBLE_MAXVALUE		  (DBL_MAX)
  69.192 +#define MATH_DOUBLE MINPOSITIVEVALUE  (DBL_MIN)
  69.193 +#define MATH_DOUBLE_RADTODEGREEFACTOR (360.0f / MATH_DOUBLE_TWOPI)
  69.194 +#define MATH_DOUBLE_DEGREETORADFACTOR (MATH_DOUBLE_TWOPI / 360.0f)
  69.195 +#define MATH_DOUBLE_TOLERANCE		  (0.00001)
  69.196 +#define MATH_DOUBLE_SINGULARITYRADIUS (0.000000000001) // Use for Gimbal lock numerical problems
  69.197 +
  69.198 +
  69.199 +
  69.200 +
  69.201 +// Single-precision Math constants class.
  69.202 +template<>
  69.203 +class Math<float>
  69.204 +{
  69.205 +public:
  69.206 +     typedef double OtherFloatType;
  69.207 +};
  69.208 +
  69.209 +// Double-precision Math constants class.
  69.210 +template<>
  69.211 +class Math<double>
  69.212 +{
  69.213 +public:
  69.214 +    typedef float OtherFloatType;
  69.215 +};
  69.216 +
  69.217 +
  69.218 +typedef Math<float>  Mathf;
  69.219 +typedef Math<double> Mathd;
  69.220 +
  69.221 +// Conversion functions between degrees and radians
  69.222 +template<class T>
  69.223 +T RadToDegree(T rads) { return rads * ((T)MATH_DOUBLE_RADTODEGREEFACTOR); }
  69.224 +template<class T>
  69.225 +T DegreeToRad(T rads) { return rads * ((T)MATH_DOUBLE_DEGREETORADFACTOR); }
  69.226 +
  69.227 +// Numerically stable acos function
  69.228 +template<class T>
  69.229 +T Acos(T val) { 
  69.230 +		if (val > T(1))				return T(0);
  69.231 +		else if (val < T(-1))		return ((T)MATH_DOUBLE_PI);
  69.232 +		else						return acos(val); 
  69.233 +};
  69.234 +
  69.235 +// Numerically stable asin function
  69.236 +template<class T>
  69.237 +T Asin(T val) { 
  69.238 +	if (val > T(1))				return ((T)MATH_DOUBLE_PIOVER2);
  69.239 +	else if (val < T(-1))		return ((T)MATH_DOUBLE_PIOVER2) * T(3);
  69.240 +	else						return asin(val); 
  69.241 +};
  69.242 +
  69.243 +#ifdef OVR_CC_MSVC
  69.244 +inline int isnan(double x) { return _isnan(x); };
  69.245 +#endif
  69.246 +
  69.247 +template<class T>
  69.248 +class Quat;
  69.249 +
  69.250 +
  69.251 +//-------------------------------------------------------------------------------------
  69.252 +// ***** Vector2<>
  69.253 +
  69.254 +// Vector2f (Vector2d) represents a 2-dimensional vector or point in space,
  69.255 +// consisting of coordinates x and y
  69.256 +
  69.257 +template<class T>
  69.258 +class Vector2
  69.259 +{
  69.260 +public:
  69.261 +    T x, y;
  69.262 +
  69.263 +    Vector2() : x(0), y(0) { }
  69.264 +    Vector2(T x_, T y_) : x(x_), y(y_) { }
  69.265 +    explicit Vector2(T s) : x(s), y(s) { }
  69.266 +    explicit Vector2(const Vector2<typename Math<T>::OtherFloatType> &src)
  69.267 +        : x((T)src.x), y((T)src.y) { }
  69.268 +
  69.269 +
  69.270 +    // C-interop support.
  69.271 +    typedef  typename CompatibleTypes<Vector2<T> >::Type CompatibleType;
  69.272 +
  69.273 +    Vector2(const CompatibleType& s) : x(s.x), y(s.y) {  }
  69.274 +
  69.275 +    operator const CompatibleType& () const
  69.276 +    {
  69.277 +        static_assert(sizeof(Vector2<T>) == sizeof(CompatibleType), "sizeof(Vector2<T>) failure");
  69.278 +        return reinterpret_cast<const CompatibleType&>(*this);
  69.279 +    }
  69.280 +
  69.281 +        
  69.282 +    bool     operator== (const Vector2& b) const  { return x == b.x && y == b.y; }
  69.283 +    bool     operator!= (const Vector2& b) const  { return x != b.x || y != b.y; }
  69.284 +             
  69.285 +    Vector2  operator+  (const Vector2& b) const  { return Vector2(x + b.x, y + b.y); }
  69.286 +    Vector2& operator+= (const Vector2& b)        { x += b.x; y += b.y; return *this; }
  69.287 +    Vector2  operator-  (const Vector2& b) const  { return Vector2(x - b.x, y - b.y); }
  69.288 +    Vector2& operator-= (const Vector2& b)        { x -= b.x; y -= b.y; return *this; }
  69.289 +    Vector2  operator- () const                   { return Vector2(-x, -y); }
  69.290 +
  69.291 +    // Scalar multiplication/division scales vector.
  69.292 +    Vector2  operator*  (T s) const               { return Vector2(x*s, y*s); }
  69.293 +    Vector2& operator*= (T s)                     { x *= s; y *= s; return *this; }
  69.294 +
  69.295 +    Vector2  operator/  (T s) const               { T rcp = T(1)/s;
  69.296 +                                                    return Vector2(x*rcp, y*rcp); }
  69.297 +    Vector2& operator/= (T s)                     { T rcp = T(1)/s;
  69.298 +                                                    x *= rcp; y *= rcp;
  69.299 +                                                    return *this; }
  69.300 +
  69.301 +    static Vector2  Min(const Vector2& a, const Vector2& b) { return Vector2((a.x < b.x) ? a.x : b.x,
  69.302 +                                                                             (a.y < b.y) ? a.y : b.y); }
  69.303 +    static Vector2  Max(const Vector2& a, const Vector2& b) { return Vector2((a.x > b.x) ? a.x : b.x,
  69.304 +                                                                             (a.y > b.y) ? a.y : b.y); }
  69.305 +
  69.306 +    // Compare two vectors for equality with tolerance. Returns true if vectors match withing tolerance.
  69.307 +    bool	Compare(const Vector2&b, T tolerance = ((T)MATH_DOUBLE_TOLERANCE))  
  69.308 +    {
  69.309 +        return (fabs(b.x-x) < tolerance) && (fabs(b.y-y) < tolerance);
  69.310 +    }
  69.311 +    
  69.312 +	// Access element by index
  69.313 +	T& operator[] (int idx)
  69.314 +	{
  69.315 +		OVR_ASSERT(0 <= idx && idx < 2);
  69.316 +		return *(&x + idx);
  69.317 +	}
  69.318 +	const T& operator[] (int idx) const
  69.319 +	{
  69.320 +		OVR_ASSERT(0 <= idx && idx < 2);
  69.321 +		return *(&x + idx);
  69.322 +	}
  69.323 +
  69.324 +    // Entry-wise product of two vectors
  69.325 +    Vector2	EntrywiseMultiply(const Vector2& b) const	{ return Vector2(x * b.x, y * b.y);}
  69.326 +
  69.327 +
  69.328 +    // Multiply and divide operators do entry-wise math. Used Dot() for dot product.
  69.329 +    Vector2  operator*  (const Vector2& b) const        { return Vector2(x * b.x,  y * b.y); }
  69.330 +    Vector2  operator/  (const Vector2& b) const        { return Vector2(x / b.x,  y / b.y); }
  69.331 +
  69.332 +	// Dot product
  69.333 +    // Used to calculate angle q between two vectors among other things,
  69.334 +    // as (A dot B) = |a||b|cos(q).
  69.335 +    T		Dot(const Vector2& b) const                 { return x*b.x + y*b.y; }
  69.336 +
  69.337 +    // Returns the angle from this vector to b, in radians.
  69.338 +    T       Angle(const Vector2& b) const        
  69.339 +	{ 
  69.340 +		T div = LengthSq()*b.LengthSq();
  69.341 +		OVR_ASSERT(div != T(0));
  69.342 +		T result = Acos((this->Dot(b))/sqrt(div));
  69.343 +		return result;
  69.344 +	}
  69.345 +
  69.346 +    // Return Length of the vector squared.
  69.347 +    T       LengthSq() const                     { return (x * x + y * y); }
  69.348 +
  69.349 +    // Return vector length.
  69.350 +    T       Length() const                       { return sqrt(LengthSq()); }
  69.351 +
  69.352 +    // Returns squared distance between two points represented by vectors.
  69.353 +    T       DistanceSq(const Vector2& b) const   { return (*this - b).LengthSq(); }
  69.354 +
  69.355 +	// Returns distance between two points represented by vectors.
  69.356 +    T       Distance(const Vector2& b) const     { return (*this - b).Length(); }
  69.357 +
  69.358 +	// Determine if this a unit vector.
  69.359 +    bool    IsNormalized() const                 { return fabs(LengthSq() - T(1)) < ((T)MATH_DOUBLE_TOLERANCE); }
  69.360 +
  69.361 +    // Normalize, convention vector length to 1.    
  69.362 +    void    Normalize()                          
  69.363 +	{
  69.364 +		T l = Length();
  69.365 +		OVR_ASSERT(l != T(0));
  69.366 +		*this /= l; 
  69.367 +	}
  69.368 +    // Returns normalized (unit) version of the vector without modifying itself.
  69.369 +    Vector2 Normalized() const                   
  69.370 +	{ 
  69.371 +		T l = Length();
  69.372 +		OVR_ASSERT(l != T(0));
  69.373 +		return *this / l; 
  69.374 +	}
  69.375 +
  69.376 +    // Linearly interpolates from this vector to another.
  69.377 +    // Factor should be between 0.0 and 1.0, with 0 giving full value to this.
  69.378 +    Vector2 Lerp(const Vector2& b, T f) const    { return *this*(T(1) - f) + b*f; }
  69.379 +
  69.380 +    // Projects this vector onto the argument; in other words,
  69.381 +    // A.Project(B) returns projection of vector A onto B.
  69.382 +    Vector2 ProjectTo(const Vector2& b) const    
  69.383 +	{ 
  69.384 +		T l2 = b.LengthSq();
  69.385 +		OVR_ASSERT(l2 != T(0));
  69.386 +		return b * ( Dot(b) / l2 ); 
  69.387 +	}
  69.388 +};
  69.389 +
  69.390 +
  69.391 +typedef Vector2<float>  Vector2f;
  69.392 +typedef Vector2<double> Vector2d;
  69.393 +typedef Vector2<int>    Vector2i;
  69.394 +
  69.395 +typedef Vector2<float>  Point2f;
  69.396 +typedef Vector2<double> Point2d;
  69.397 +typedef Vector2<int>    Point2i;
  69.398 +
  69.399 +//-------------------------------------------------------------------------------------
  69.400 +// ***** Vector3<> - 3D vector of {x, y, z}
  69.401 +
  69.402 +//
  69.403 +// Vector3f (Vector3d) represents a 3-dimensional vector or point in space,
  69.404 +// consisting of coordinates x, y and z.
  69.405 +
  69.406 +template<class T>
  69.407 +class Vector3
  69.408 +{
  69.409 +public:
  69.410 +    T x, y, z;
  69.411 +
  69.412 +    // FIXME: default initialization of a vector class can be very expensive in a full-blown
  69.413 +    // application.  A few hundred thousand vector constructions is not unlikely and can add
  69.414 +    // up to milliseconds of time on processors like the PS3 PPU.
  69.415 +    Vector3() : x(0), y(0), z(0) { }
  69.416 +    Vector3(T x_, T y_, T z_ = 0) : x(x_), y(y_), z(z_) { }
  69.417 +    explicit Vector3(T s) : x(s), y(s), z(s) { }
  69.418 +    explicit Vector3(const Vector3<typename Math<T>::OtherFloatType> &src)
  69.419 +        : x((T)src.x), y((T)src.y), z((T)src.z) { }
  69.420 +
  69.421 +    static const Vector3 ZERO;
  69.422 +
  69.423 +    // C-interop support.
  69.424 +    typedef  typename CompatibleTypes<Vector3<T> >::Type CompatibleType;
  69.425 +
  69.426 +    Vector3(const CompatibleType& s) : x(s.x), y(s.y), z(s.z) {  }
  69.427 +
  69.428 +    operator const CompatibleType& () const
  69.429 +    {
  69.430 +        static_assert(sizeof(Vector3<T>) == sizeof(CompatibleType), "sizeof(Vector3<T>) failure");
  69.431 +        return reinterpret_cast<const CompatibleType&>(*this);
  69.432 +    }
  69.433 +
  69.434 +    bool     operator== (const Vector3& b) const  { return x == b.x && y == b.y && z == b.z; }
  69.435 +    bool     operator!= (const Vector3& b) const  { return x != b.x || y != b.y || z != b.z; }
  69.436 +             
  69.437 +    Vector3  operator+  (const Vector3& b) const  { return Vector3(x + b.x, y + b.y, z + b.z); }
  69.438 +    Vector3& operator+= (const Vector3& b)        { x += b.x; y += b.y; z += b.z; return *this; }
  69.439 +    Vector3  operator-  (const Vector3& b) const  { return Vector3(x - b.x, y - b.y, z - b.z); }
  69.440 +    Vector3& operator-= (const Vector3& b)        { x -= b.x; y -= b.y; z -= b.z; return *this; }
  69.441 +    Vector3  operator- () const                   { return Vector3(-x, -y, -z); }
  69.442 +
  69.443 +    // Scalar multiplication/division scales vector.
  69.444 +    Vector3  operator*  (T s) const               { return Vector3(x*s, y*s, z*s); }
  69.445 +    Vector3& operator*= (T s)                     { x *= s; y *= s; z *= s; return *this; }
  69.446 +
  69.447 +    Vector3  operator/  (T s) const               { T rcp = T(1)/s;
  69.448 +                                                    return Vector3(x*rcp, y*rcp, z*rcp); }
  69.449 +    Vector3& operator/= (T s)                     { T rcp = T(1)/s;
  69.450 +                                                    x *= rcp; y *= rcp; z *= rcp;
  69.451 +                                                    return *this; }
  69.452 +
  69.453 +    static Vector3  Min(const Vector3& a, const Vector3& b)
  69.454 +    {
  69.455 +        return Vector3((a.x < b.x) ? a.x : b.x,
  69.456 +                       (a.y < b.y) ? a.y : b.y,
  69.457 +                       (a.z < b.z) ? a.z : b.z);
  69.458 +    }
  69.459 +    static Vector3  Max(const Vector3& a, const Vector3& b)
  69.460 +    { 
  69.461 +        return Vector3((a.x > b.x) ? a.x : b.x,
  69.462 +                       (a.y > b.y) ? a.y : b.y,
  69.463 +                       (a.z > b.z) ? a.z : b.z);
  69.464 +    }        
  69.465 +
  69.466 +    // Compare two vectors for equality with tolerance. Returns true if vectors match withing tolerance.
  69.467 +    bool      Compare(const Vector3&b, T tolerance = ((T)MATH_DOUBLE_TOLERANCE)) 
  69.468 +    {
  69.469 +        return (fabs(b.x-x) < tolerance) && 
  69.470 +			   (fabs(b.y-y) < tolerance) && 
  69.471 +			   (fabs(b.z-z) < tolerance);
  69.472 +    }
  69.473 +    
  69.474 +    T& operator[] (int idx)
  69.475 +    {
  69.476 +        OVR_ASSERT(0 <= idx && idx < 3);
  69.477 +        return *(&x + idx);
  69.478 +    }
  69.479 +
  69.480 +    const T& operator[] (int idx) const
  69.481 +    {
  69.482 +        OVR_ASSERT(0 <= idx && idx < 3);
  69.483 +        return *(&x + idx);
  69.484 +    }
  69.485 +
  69.486 +    // Entrywise product of two vectors
  69.487 +    Vector3	EntrywiseMultiply(const Vector3& b) const	{ return Vector3(x * b.x, 
  69.488 +																		 y * b.y, 
  69.489 +																		 z * b.z);}
  69.490 +
  69.491 +    // Multiply and divide operators do entry-wise math
  69.492 +    Vector3  operator*  (const Vector3& b) const        { return Vector3(x * b.x, 
  69.493 +																		 y * b.y, 
  69.494 +																		 z * b.z); }
  69.495 +
  69.496 +    Vector3  operator/  (const Vector3& b) const        { return Vector3(x / b.x, 
  69.497 +																		 y / b.y, 
  69.498 +																		 z / b.z); }
  69.499 +
  69.500 +
  69.501 +	// Dot product
  69.502 +    // Used to calculate angle q between two vectors among other things,
  69.503 +    // as (A dot B) = |a||b|cos(q).
  69.504 +     T      Dot(const Vector3& b) const          { return x*b.x + y*b.y + z*b.z; }
  69.505 +
  69.506 +    // Compute cross product, which generates a normal vector.
  69.507 +    // Direction vector can be determined by right-hand rule: Pointing index finder in
  69.508 +    // direction a and middle finger in direction b, thumb will point in a.Cross(b).
  69.509 +    Vector3 Cross(const Vector3& b) const        { return Vector3(y*b.z - z*b.y,
  69.510 +                                                                  z*b.x - x*b.z,
  69.511 +                                                                  x*b.y - y*b.x); }
  69.512 +
  69.513 +    // Returns the angle from this vector to b, in radians.
  69.514 +    T       Angle(const Vector3& b) const 
  69.515 +	{
  69.516 +		T div = LengthSq()*b.LengthSq();
  69.517 +		OVR_ASSERT(div != T(0));
  69.518 +		T result = Acos((this->Dot(b))/sqrt(div));
  69.519 +		return result;
  69.520 +	}
  69.521 +
  69.522 +    // Return Length of the vector squared.
  69.523 +    T       LengthSq() const                     { return (x * x + y * y + z * z); }
  69.524 +
  69.525 +    // Return vector length.
  69.526 +    T       Length() const                       { return sqrt(LengthSq()); }
  69.527 +
  69.528 +    // Returns squared distance between two points represented by vectors.
  69.529 +    T       DistanceSq(Vector3 const& b) const         { return (*this - b).LengthSq(); }
  69.530 +
  69.531 +    // Returns distance between two points represented by vectors.
  69.532 +    T       Distance(Vector3 const& b) const     { return (*this - b).Length(); }
  69.533 +    
  69.534 +    // Determine if this a unit vector.
  69.535 +    bool    IsNormalized() const                 { return fabs(LengthSq() - T(1)) < ((T)MATH_DOUBLE_TOLERANCE); }
  69.536 +
  69.537 +    // Normalize, convention vector length to 1.    
  69.538 +    void    Normalize()                          
  69.539 +	{
  69.540 +		T l = Length();
  69.541 +		OVR_ASSERT(l != T(0));
  69.542 +		*this /= l; 
  69.543 +	}
  69.544 +
  69.545 +    // Returns normalized (unit) version of the vector without modifying itself.
  69.546 +    Vector3 Normalized() const                   
  69.547 +	{ 
  69.548 +		T l = Length();
  69.549 +		OVR_ASSERT(l != T(0));
  69.550 +		return *this / l; 
  69.551 +	}
  69.552 +
  69.553 +    // Linearly interpolates from this vector to another.
  69.554 +    // Factor should be between 0.0 and 1.0, with 0 giving full value to this.
  69.555 +    Vector3 Lerp(const Vector3& b, T f) const    { return *this*(T(1) - f) + b*f; }
  69.556 +
  69.557 +    // Projects this vector onto the argument; in other words,
  69.558 +    // A.Project(B) returns projection of vector A onto B.
  69.559 +    Vector3 ProjectTo(const Vector3& b) const    
  69.560 +	{ 
  69.561 +		T l2 = b.LengthSq();
  69.562 +		OVR_ASSERT(l2 != T(0));
  69.563 +		return b * ( Dot(b) / l2 ); 
  69.564 +	}
  69.565 +
  69.566 +    // Projects this vector onto a plane defined by a normal vector
  69.567 +    Vector3 ProjectToPlane(const Vector3& normal) const { return *this - this->ProjectTo(normal); }
  69.568 +};
  69.569 +
  69.570 +typedef Vector3<float>  Vector3f;
  69.571 +typedef Vector3<double> Vector3d;
  69.572 +typedef Vector3<int32_t>  Vector3i;
  69.573 +    
  69.574 +static_assert((sizeof(Vector3f) == 3*sizeof(float)), "sizeof(Vector3f) failure");
  69.575 +static_assert((sizeof(Vector3d) == 3*sizeof(double)), "sizeof(Vector3d) failure");
  69.576 +static_assert((sizeof(Vector3i) == 3*sizeof(int32_t)), "sizeof(Vector3i) failure");
  69.577 +
  69.578 +typedef Vector3<float>   Point3f;
  69.579 +typedef Vector3<double>  Point3d;
  69.580 +typedef Vector3<int32_t>  Point3i;
  69.581 +
  69.582 +
  69.583 +//-------------------------------------------------------------------------------------
  69.584 +// ***** Vector4<> - 4D vector of {x, y, z, w}
  69.585 +
  69.586 +//
  69.587 +// Vector4f (Vector4d) represents a 3-dimensional vector or point in space,
  69.588 +// consisting of coordinates x, y, z and w.
  69.589 +
  69.590 +template<class T>
  69.591 +class Vector4
  69.592 +{
  69.593 +public:
  69.594 +    T x, y, z, w;
  69.595 +
  69.596 +	// FIXME: default initialization of a vector class can be very expensive in a full-blown
  69.597 +	// application.  A few hundred thousand vector constructions is not unlikely and can add
  69.598 +	// up to milliseconds of time on processors like the PS3 PPU.
  69.599 +    Vector4() : x(0), y(0), z(0), w(0) { }
  69.600 +    Vector4(T x_, T y_, T z_, T w_) : x(x_), y(y_), z(z_), w(w_) { }
  69.601 +    explicit Vector4(T s) : x(s), y(s), z(s), w(s) { }
  69.602 +	explicit Vector4(const Vector3<T>& v, const float w_=1) : x(v.x), y(v.y), z(v.z), w(w_) { }
  69.603 +    explicit Vector4(const Vector4<typename Math<T>::OtherFloatType> &src)
  69.604 +        : x((T)src.x), y((T)src.y), z((T)src.z), w((T)src.w) { }
  69.605 +
  69.606 +    static const Vector4 ZERO;
  69.607 +
  69.608 +    // C-interop support.
  69.609 +    typedef  typename CompatibleTypes< Vector4<T> >::Type CompatibleType;
  69.610 +
  69.611 +    Vector4(const CompatibleType& s) : x(s.x), y(s.y), z(s.z), w(s.w) {  }
  69.612 +
  69.613 +    operator const CompatibleType& () const
  69.614 +    {
  69.615 +        static_assert(sizeof(Vector4<T>) == sizeof(CompatibleType), "sizeof(Vector4<T>) failure");
  69.616 +        return reinterpret_cast<const CompatibleType&>(*this);
  69.617 +    }
  69.618 +
  69.619 +	Vector4& operator= (const Vector3<T>& other)  { x=other.x; y=other.y; z=other.z; w=1; return *this; }
  69.620 +    bool     operator== (const Vector4& b) const  { return x == b.x && y == b.y && z == b.z && w == b.w; }
  69.621 +    bool     operator!= (const Vector4& b) const  { return x != b.x || y != b.y || z != b.z || w != b.w; }
  69.622 +             
  69.623 +    Vector4  operator+  (const Vector4& b) const  { return Vector4(x + b.x, y + b.y, z + b.z, w + b.w); }
  69.624 +    Vector4& operator+= (const Vector4& b)        { x += b.x; y += b.y; z += b.z; w += b.w; return *this; }
  69.625 +    Vector4  operator-  (const Vector4& b) const  { return Vector4(x - b.x, y - b.y, z - b.z, w - b.w); }
  69.626 +    Vector4& operator-= (const Vector4& b)        { x -= b.x; y -= b.y; z -= b.z; w -= b.w; return *this; }
  69.627 +    Vector4  operator- () const                   { return Vector4(-x, -y, -z, -w); }
  69.628 +
  69.629 +    // Scalar multiplication/division scales vector.
  69.630 +    Vector4  operator*  (T s) const               { return Vector4(x*s, y*s, z*s, w*s); }
  69.631 +    Vector4& operator*= (T s)                     { x *= s; y *= s; z *= s; w *= s;return *this; }
  69.632 +
  69.633 +    Vector4  operator/  (T s) const               { T rcp = T(1)/s;
  69.634 +                                                    return Vector4(x*rcp, y*rcp, z*rcp, w*rcp); }
  69.635 +    Vector4& operator/= (T s)                     { T rcp = T(1)/s;
  69.636 +                                                    x *= rcp; y *= rcp; z *= rcp; w *= rcp;
  69.637 +                                                    return *this; }
  69.638 +
  69.639 +    static Vector4  Min(const Vector4& a, const Vector4& b)
  69.640 +    {
  69.641 +        return Vector4((a.x < b.x) ? a.x : b.x,
  69.642 +                       (a.y < b.y) ? a.y : b.y,
  69.643 +                       (a.z < b.z) ? a.z : b.z,
  69.644 +					   (a.w < b.w) ? a.w : b.w);
  69.645 +    }
  69.646 +    static Vector4  Max(const Vector4& a, const Vector4& b)
  69.647 +    { 
  69.648 +        return Vector4((a.x > b.x) ? a.x : b.x,
  69.649 +                       (a.y > b.y) ? a.y : b.y,
  69.650 +                       (a.z > b.z) ? a.z : b.z,
  69.651 +					   (a.w > b.w) ? a.w : b.w);
  69.652 +    }        
  69.653 +
  69.654 +    // Compare two vectors for equality with tolerance. Returns true if vectors match withing tolerance.
  69.655 +    bool      Compare(const Vector4&b, T tolerance = ((T)MATH_DOUBLE_TOLERANCE))
  69.656 +    {
  69.657 +        return (fabs(b.x-x) < tolerance) && 
  69.658 +			   (fabs(b.y-y) < tolerance) && 
  69.659 +			   (fabs(b.z-z) < tolerance) &&
  69.660 +			   (fabs(b.w-w) < tolerance);
  69.661 +    }
  69.662 +    
  69.663 +    T& operator[] (int idx)
  69.664 +    {
  69.665 +        OVR_ASSERT(0 <= idx && idx < 4);
  69.666 +        return *(&x + idx);
  69.667 +    }
  69.668 +
  69.669 +    const T& operator[] (int idx) const
  69.670 +    {
  69.671 +        OVR_ASSERT(0 <= idx && idx < 4);
  69.672 +        return *(&x + idx);
  69.673 +    }
  69.674 +
  69.675 +    // Entry wise product of two vectors
  69.676 +    Vector4	EntrywiseMultiply(const Vector4& b) const	{ return Vector4(x * b.x, 
  69.677 +																		 y * b.y, 
  69.678 +																		 z * b.z);}
  69.679 +
  69.680 +    // Multiply and divide operators do entry-wise math
  69.681 +    Vector4  operator*  (const Vector4& b) const        { return Vector4(x * b.x, 
  69.682 +																		 y * b.y, 
  69.683 +																		 z * b.z,
  69.684 +																		 w * b.w); }
  69.685 +
  69.686 +    Vector4  operator/  (const Vector4& b) const        { return Vector4(x / b.x, 
  69.687 +																		 y / b.y, 
  69.688 +																		 z / b.z,
  69.689 +																		 w / b.w); }
  69.690 +
  69.691 +
  69.692 +	// Dot product
  69.693 +    T       Dot(const Vector4& b) const          { return x*b.x + y*b.y + z*b.z + w*b.w; }
  69.694 +
  69.695 +    // Return Length of the vector squared.
  69.696 +    T       LengthSq() const                     { return (x * x + y * y + z * z + w * w); }
  69.697 +
  69.698 +    // Return vector length.
  69.699 +    T       Length() const                       { return sqrt(LengthSq()); }
  69.700 +    
  69.701 +    // Determine if this a unit vector.
  69.702 +    bool    IsNormalized() const                 { return fabs(LengthSq() - T(1)) < Math<T>::Tolerance; }
  69.703 +
  69.704 +    // Normalize, convention vector length to 1.    
  69.705 +    void    Normalize()                          
  69.706 +	{
  69.707 +		T l = Length();
  69.708 +		OVR_ASSERT(l != T(0));
  69.709 +		*this /= l; 
  69.710 +	}
  69.711 +
  69.712 +    // Returns normalized (unit) version of the vector without modifying itself.
  69.713 +    Vector4 Normalized() const                   
  69.714 +	{ 
  69.715 +		T l = Length();
  69.716 +		OVR_ASSERT(l != T(0));
  69.717 +		return *this / l; 
  69.718 +	}
  69.719 +};
  69.720 +
  69.721 +typedef Vector4<float>  Vector4f;
  69.722 +typedef Vector4<double> Vector4d;
  69.723 +typedef Vector4<int>    Vector4i;
  69.724 +
  69.725 +
  69.726 +//-------------------------------------------------------------------------------------
  69.727 +// ***** Bounds3
  69.728 +
  69.729 +// Bounds class used to describe a 3D axis aligned bounding box.
  69.730 +
  69.731 +template<class T>
  69.732 +class Bounds3
  69.733 +{
  69.734 +public:
  69.735 +	Vector3<T>	b[2];
  69.736 +
  69.737 +	Bounds3()
  69.738 +	{
  69.739 +	}
  69.740 +
  69.741 +	Bounds3( const Vector3<T> & mins, const Vector3<T> & maxs )
  69.742 +{
  69.743 +		b[0] = mins;
  69.744 +		b[1] = maxs;
  69.745 +	}
  69.746 +
  69.747 +	void Clear()
  69.748 +	{
  69.749 +		b[0].x = b[0].y = b[0].z = Math<T>::MaxValue;
  69.750 +		b[1].x = b[1].y = b[1].z = -Math<T>::MaxValue;
  69.751 +	}
  69.752 +
  69.753 +	void AddPoint( const Vector3<T> & v )
  69.754 +	{
  69.755 +		b[0].x = Alg::Min( b[0].x, v.x );
  69.756 +		b[0].y = Alg::Min( b[0].y, v.y );
  69.757 +		b[0].z = Alg::Min( b[0].z, v.z );
  69.758 +		b[1].x = Alg::Max( b[1].x, v.x );
  69.759 +		b[1].y = Alg::Max( b[1].y, v.y );
  69.760 +		b[1].z = Alg::Max( b[1].z, v.z );
  69.761 +	}
  69.762 +
  69.763 +	const Vector3<T> & GetMins() const { return b[0]; }
  69.764 +	const Vector3<T> & GetMaxs() const { return b[1]; }
  69.765 +
  69.766 +	Vector3<T> & GetMins() { return b[0]; }
  69.767 +	Vector3<T> & GetMaxs() { return b[1]; }
  69.768 +};
  69.769 +
  69.770 +typedef Bounds3<float>	Bounds3f;
  69.771 +typedef Bounds3<double>	Bounds3d;
  69.772 +
  69.773 +
  69.774 +//-------------------------------------------------------------------------------------
  69.775 +// ***** Size
  69.776 +
  69.777 +// Size class represents 2D size with Width, Height components.
  69.778 +// Used to describe distentions of render targets, etc.
  69.779 +
  69.780 +template<class T>
  69.781 +class Size
  69.782 +{
  69.783 +public:
  69.784 +    T   w, h;
  69.785 +
  69.786 +    Size()              : w(0), h(0)   { }
  69.787 +    Size(T w_, T h_)    : w(w_), h(h_) { }
  69.788 +    explicit Size(T s)  : w(s), h(s)   { }
  69.789 +    explicit Size(const Size<typename Math<T>::OtherFloatType> &src)
  69.790 +        : w((T)src.w), h((T)src.h) { }
  69.791 +
  69.792 +    // C-interop support.
  69.793 +    typedef  typename CompatibleTypes<Size<T> >::Type CompatibleType;
  69.794 +
  69.795 +    Size(const CompatibleType& s) : w(s.w), h(s.h) {  }
  69.796 +
  69.797 +    operator const CompatibleType& () const
  69.798 +    {
  69.799 +        static_assert(sizeof(Size<T>) == sizeof(CompatibleType), "sizeof(Size<T>) failure");
  69.800 +        return reinterpret_cast<const CompatibleType&>(*this);
  69.801 +    }
  69.802 +
  69.803 +    bool     operator== (const Size& b) const  { return w == b.w && h == b.h; }
  69.804 +    bool     operator!= (const Size& b) const  { return w != b.w || h != b.h; }
  69.805 +             
  69.806 +    Size  operator+  (const Size& b) const  { return Size(w + b.w, h + b.h); }
  69.807 +    Size& operator+= (const Size& b)        { w += b.w; h += b.h; return *this; }
  69.808 +    Size  operator-  (const Size& b) const  { return Size(w - b.w, h - b.h); }
  69.809 +    Size& operator-= (const Size& b)        { w -= b.w; h -= b.h; return *this; }
  69.810 +    Size  operator- () const                { return Size(-w, -h); }
  69.811 +    Size  operator*  (const Size& b) const  { return Size(w * b.w, h * b.h); }
  69.812 +    Size& operator*= (const Size& b)        { w *= b.w; h *= b.h; return *this; }
  69.813 +    Size  operator/  (const Size& b) const  { return Size(w / b.w, h / b.h); }
  69.814 +    Size& operator/= (const Size& b)        { w /= b.w; h /= b.h; return *this; }
  69.815 +
  69.816 +    // Scalar multiplication/division scales both components.
  69.817 +    Size  operator*  (T s) const            { return Size(w*s, h*s); }
  69.818 +    Size& operator*= (T s)                  { w *= s; h *= s; return *this; }    
  69.819 +    Size  operator/  (T s) const            { return Size(w/s, h/s); }
  69.820 +    Size& operator/= (T s)                  { w /= s; h /= s; return *this; }
  69.821 +
  69.822 +    static Size Min(const Size& a, const Size& b)  { return Size((a.w  < b.w)  ? a.w  : b.w,
  69.823 +                                                                 (a.h < b.h) ? a.h : b.h); }
  69.824 +    static Size Max(const Size& a, const Size& b)  { return Size((a.w  > b.w)  ? a.w  : b.w,
  69.825 +                                                                 (a.h > b.h) ? a.h : b.h); }
  69.826 +    
  69.827 +    T       Area() const                    { return w * h; }
  69.828 +
  69.829 +    inline  Vector2<T> ToVector() const     { return Vector2<T>(w, h); }
  69.830 +};
  69.831 +
  69.832 +
  69.833 +typedef Size<int>       Sizei;
  69.834 +typedef Size<unsigned>  Sizeu;
  69.835 +typedef Size<float>     Sizef;
  69.836 +typedef Size<double>    Sized;
  69.837 +
  69.838 +
  69.839 +
  69.840 +//-----------------------------------------------------------------------------------
  69.841 +// ***** Rect
  69.842 +
  69.843 +// Rect describes a rectangular area for rendering, that includes position and size.
  69.844 +template<class T>
  69.845 +class Rect
  69.846 +{
  69.847 +public:
  69.848 +    T x, y;
  69.849 +    T w, h;
  69.850 +
  69.851 +    Rect() { }
  69.852 +    Rect(T x1, T y1, T w1, T h1)                   : x(x1), y(y1), w(w1), h(h1) { }    
  69.853 +    Rect(const Vector2<T>& pos, const Size<T>& sz) : x(pos.x), y(pos.y), w(sz.w), h(sz.h) { }
  69.854 +    Rect(const Size<T>& sz)                        : x(0), y(0), w(sz.w), h(sz.h) { }
  69.855 +    
  69.856 +    // C-interop support.
  69.857 +    typedef  typename CompatibleTypes<Rect<T> >::Type CompatibleType;
  69.858 +
  69.859 +    Rect(const CompatibleType& s) : x(s.Pos.x), y(s.Pos.y), w(s.Size.w), h(s.Size.h) {  }
  69.860 +
  69.861 +    operator const CompatibleType& () const
  69.862 +    {
  69.863 +        static_assert(sizeof(Rect<T>) == sizeof(CompatibleType), "sizeof(Rect<T>) failure");
  69.864 +        return reinterpret_cast<const CompatibleType&>(*this);
  69.865 +    }
  69.866 +
  69.867 +    Vector2<T> GetPos() const                { return Vector2<T>(x, y); }
  69.868 +    Size<T>    GetSize() const               { return Size<T>(w, h); }
  69.869 +    void       SetPos(const Vector2<T>& pos) { x = pos.x; y = pos.y; }
  69.870 +    void       SetSize(const Size<T>& sz)    { w = sz.w; h = sz.h; }
  69.871 +
  69.872 +    bool operator == (const Rect& vp) const
  69.873 +    { return (x == vp.x) && (y == vp.y) && (w == vp.w) && (h == vp.h); }
  69.874 +    bool operator != (const Rect& vp) const
  69.875 +    { return !operator == (vp); }
  69.876 +};
  69.877 +
  69.878 +typedef Rect<int> Recti;
  69.879 +
  69.880 +
  69.881 +//-------------------------------------------------------------------------------------//
  69.882 +// ***** Quat
  69.883 +//
  69.884 +// Quatf represents a quaternion class used for rotations.
  69.885 +// 
  69.886 +// Quaternion multiplications are done in right-to-left order, to match the
  69.887 +// behavior of matrices.
  69.888 +
  69.889 +
  69.890 +template<class T>
  69.891 +class Quat
  69.892 +{
  69.893 +public:
  69.894 +    // w + Xi + Yj + Zk
  69.895 +    T x, y, z, w;    
  69.896 +
  69.897 +    Quat() : x(0), y(0), z(0), w(1) { }
  69.898 +    Quat(T x_, T y_, T z_, T w_) : x(x_), y(y_), z(z_), w(w_) { }
  69.899 +    explicit Quat(const Quat<typename Math<T>::OtherFloatType> &src)
  69.900 +        : x((T)src.x), y((T)src.y), z((T)src.z), w((T)src.w) { }
  69.901 +
  69.902 +    typedef  typename CompatibleTypes<Quat<T> >::Type CompatibleType;
  69.903 +
  69.904 +    // C-interop support.
  69.905 +    Quat(const CompatibleType& s) : x(s.x), y(s.y), z(s.z), w(s.w) { }
  69.906 +
  69.907 +    operator CompatibleType () const
  69.908 +    {
  69.909 +        CompatibleType result;
  69.910 +        result.x = x;
  69.911 +        result.y = y;
  69.912 +        result.z = z;
  69.913 +        result.w = w;
  69.914 +        return result;
  69.915 +    }
  69.916 +
  69.917 +    // Constructs quaternion for rotation around the axis by an angle.
  69.918 +    Quat(const Vector3<T>& axis, T angle)
  69.919 +    {
  69.920 +        // Make sure we don't divide by zero. 
  69.921 +        if (axis.LengthSq() == 0)
  69.922 +        {
  69.923 +            // Assert if the axis is zero, but the angle isn't
  69.924 +            OVR_ASSERT(angle == 0);
  69.925 +            x = 0; y = 0; z = 0; w = 1;
  69.926 +            return;
  69.927 +        }
  69.928 +
  69.929 +		Vector3<T> unitAxis = axis.Normalized();
  69.930 +		T          sinHalfAngle = sin(angle * T(0.5));
  69.931 +
  69.932 +		w = cos(angle * T(0.5));
  69.933 +		x = unitAxis.x * sinHalfAngle;
  69.934 +		y = unitAxis.y * sinHalfAngle;
  69.935 +		z = unitAxis.z * sinHalfAngle;
  69.936 +    }
  69.937 +
  69.938 +    // Constructs quaternion for rotation around one of the coordinate axis by an angle.
  69.939 +    Quat(Axis A, T angle, RotateDirection d = Rotate_CCW, HandedSystem s = Handed_R)
  69.940 +    {
  69.941 +        T sinHalfAngle = s * d *sin(angle * T(0.5));
  69.942 +        T v[3];
  69.943 +        v[0] = v[1] = v[2] = T(0);
  69.944 +        v[A] = sinHalfAngle;
  69.945 +
  69.946 +        w = cos(angle * T(0.5));
  69.947 +        x = v[0];
  69.948 +        y = v[1];
  69.949 +        z = v[2];
  69.950 +    }
  69.951 +
  69.952 +    // Compute axis and angle from quaternion
  69.953 +    void GetAxisAngle(Vector3<T>* axis, T* angle) const
  69.954 +    {
  69.955 +		if ( x*x + y*y + z*z > ((T)MATH_DOUBLE_TOLERANCE) * ((T)MATH_DOUBLE_TOLERANCE) ) {
  69.956 +			*axis  = Vector3<T>(x, y, z).Normalized();
  69.957 +			*angle = 2 * Acos(w);
  69.958 +			if (*angle > ((T)MATH_DOUBLE_PI)) // Reduce the magnitude of the angle, if necessary
  69.959 +			{
  69.960 +				*angle = ((T)MATH_DOUBLE_TWOPI) - *angle;
  69.961 +				*axis = *axis * (-1);
  69.962 +			}
  69.963 +		}
  69.964 +		else 
  69.965 +		{
  69.966 +			*axis = Vector3<T>(1, 0, 0);
  69.967 +			*angle= 0;
  69.968 +		}
  69.969 +    }
  69.970 +
  69.971 +    // Constructs the quaternion from a rotation matrix
  69.972 +    explicit Quat(const Matrix4<T>& m)
  69.973 +    {
  69.974 +        T trace = m.M[0][0] + m.M[1][1] + m.M[2][2];
  69.975 +
  69.976 +        // In almost all cases, the first part is executed.
  69.977 +        // However, if the trace is not positive, the other
  69.978 +        // cases arise.
  69.979 +        if (trace > T(0)) 
  69.980 +        {
  69.981 +            T s = sqrt(trace + T(1)) * T(2); // s=4*qw
  69.982 +            w = T(0.25) * s;
  69.983 +            x = (m.M[2][1] - m.M[1][2]) / s;
  69.984 +            y = (m.M[0][2] - m.M[2][0]) / s;
  69.985 +            z = (m.M[1][0] - m.M[0][1]) / s; 
  69.986 +        } 
  69.987 +        else if ((m.M[0][0] > m.M[1][1])&&(m.M[0][0] > m.M[2][2])) 
  69.988 +        {
  69.989 +            T s = sqrt(T(1) + m.M[0][0] - m.M[1][1] - m.M[2][2]) * T(2);
  69.990 +            w = (m.M[2][1] - m.M[1][2]) / s;
  69.991 +            x = T(0.25) * s;
  69.992 +            y = (m.M[0][1] + m.M[1][0]) / s;
  69.993 +            z = (m.M[2][0] + m.M[0][2]) / s;
  69.994 +        } 
  69.995 +        else if (m.M[1][1] > m.M[2][2]) 
  69.996 +        {
  69.997 +            T s = sqrt(T(1) + m.M[1][1] - m.M[0][0] - m.M[2][2]) * T(2); // S=4*qy
  69.998 +            w = (m.M[0][2] - m.M[2][0]) / s;
  69.999 +            x = (m.M[0][1] + m.M[1][0]) / s;
 69.1000 +            y = T(0.25) * s;
 69.1001 +            z = (m.M[1][2] + m.M[2][1]) / s;
 69.1002 +        } 
 69.1003 +        else 
 69.1004 +        {
 69.1005 +            T s = sqrt(T(1) + m.M[2][2] - m.M[0][0] - m.M[1][1]) * T(2); // S=4*qz
 69.1006 +            w = (m.M[1][0] - m.M[0][1]) / s;
 69.1007 +            x = (m.M[0][2] + m.M[2][0]) / s;
 69.1008 +            y = (m.M[1][2] + m.M[2][1]) / s;
 69.1009 +            z = T(0.25) * s;
 69.1010 +        }
 69.1011 +    }
 69.1012 +
 69.1013 +	// Constructs the quaternion from a rotation matrix
 69.1014 +	explicit Quat(const Matrix3<T>& m)
 69.1015 +	{
 69.1016 +		T trace = m.M[0][0] + m.M[1][1] + m.M[2][2];
 69.1017 +
 69.1018 +		// In almost all cases, the first part is executed.
 69.1019 +		// However, if the trace is not positive, the other
 69.1020 +		// cases arise.
 69.1021 +		if (trace > T(0)) 
 69.1022 +		{
 69.1023 +			T s = sqrt(trace + T(1)) * T(2); // s=4*qw
 69.1024 +			w = T(0.25) * s;
 69.1025 +			x = (m.M[2][1] - m.M[1][2]) / s;
 69.1026 +			y = (m.M[0][2] - m.M[2][0]) / s;
 69.1027 +			z = (m.M[1][0] - m.M[0][1]) / s; 
 69.1028 +		} 
 69.1029 +		else if ((m.M[0][0] > m.M[1][1])&&(m.M[0][0] > m.M[2][2])) 
 69.1030 +		{
 69.1031 +			T s = sqrt(T(1) + m.M[0][0] - m.M[1][1] - m.M[2][2]) * T(2);
 69.1032 +			w = (m.M[2][1] - m.M[1][2]) / s;
 69.1033 +			x = T(0.25) * s;
 69.1034 +			y = (m.M[0][1] + m.M[1][0]) / s;
 69.1035 +			z = (m.M[2][0] + m.M[0][2]) / s;
 69.1036 +		} 
 69.1037 +		else if (m.M[1][1] > m.M[2][2]) 
 69.1038 +		{
 69.1039 +			T s = sqrt(T(1) + m.M[1][1] - m.M[0][0] - m.M[2][2]) * T(2); // S=4*qy
 69.1040 +			w = (m.M[0][2] - m.M[2][0]) / s;
 69.1041 +			x = (m.M[0][1] + m.M[1][0]) / s;
 69.1042 +			y = T(0.25) * s;
 69.1043 +			z = (m.M[1][2] + m.M[2][1]) / s;
 69.1044 +		} 
 69.1045 +		else 
 69.1046 +		{
 69.1047 +			T s = sqrt(T(1) + m.M[2][2] - m.M[0][0] - m.M[1][1]) * T(2); // S=4*qz
 69.1048 +			w = (m.M[1][0] - m.M[0][1]) / s;
 69.1049 +			x = (m.M[0][2] + m.M[2][0]) / s;
 69.1050 +			y = (m.M[1][2] + m.M[2][1]) / s;
 69.1051 +			z = T(0.25) * s;
 69.1052 +		}
 69.1053 +	}
 69.1054 +
 69.1055 +    bool operator== (const Quat& b) const   { return x == b.x && y == b.y && z == b.z && w == b.w; }
 69.1056 +    bool operator!= (const Quat& b) const   { return x != b.x || y != b.y || z != b.z || w != b.w; }
 69.1057 +
 69.1058 +    Quat  operator+  (const Quat& b) const  { return Quat(x + b.x, y + b.y, z + b.z, w + b.w); }
 69.1059 +    Quat& operator+= (const Quat& b)        { w += b.w; x += b.x; y += b.y; z += b.z; return *this; }
 69.1060 +    Quat  operator-  (const Quat& b) const  { return Quat(x - b.x, y - b.y, z - b.z, w - b.w); }
 69.1061 +    Quat& operator-= (const Quat& b)        { w -= b.w; x -= b.x; y -= b.y; z -= b.z; return *this; }
 69.1062 +
 69.1063 +    Quat  operator*  (T s) const            { return Quat(x * s, y * s, z * s, w * s); }
 69.1064 +    Quat& operator*= (T s)                  { w *= s; x *= s; y *= s; z *= s; return *this; }
 69.1065 +    Quat  operator/  (T s) const            { T rcp = T(1)/s; return Quat(x * rcp, y * rcp, z * rcp, w *rcp); }
 69.1066 +    Quat& operator/= (T s)                  { T rcp = T(1)/s; w *= rcp; x *= rcp; y *= rcp; z *= rcp; return *this; }
 69.1067 +
 69.1068 +
 69.1069 +    // Get Imaginary part vector
 69.1070 +    Vector3<T> Imag() const                 { return Vector3<T>(x,y,z); }
 69.1071 +
 69.1072 +    // Get quaternion length.
 69.1073 +    T       Length() const                  { return sqrt(LengthSq()); }
 69.1074 +
 69.1075 +    // Get quaternion length squared.
 69.1076 +    T       LengthSq() const                { return (x * x + y * y + z * z + w * w); }
 69.1077 +
 69.1078 +    // Simple Euclidean distance in R^4 (not SLERP distance, but at least respects Haar measure)
 69.1079 +    T       Distance(const Quat& q) const	
 69.1080 +	{ 
 69.1081 +        T d1 = (*this - q).Length();
 69.1082 +        T d2 = (*this + q).Length(); // Antipodal point check
 69.1083 +        return (d1 < d2) ? d1 : d2;
 69.1084 +	}
 69.1085 +
 69.1086 +    T       DistanceSq(const Quat& q) const
 69.1087 +    {
 69.1088 +        T d1 = (*this - q).LengthSq();
 69.1089 +        T d2 = (*this + q).LengthSq(); // Antipodal point check
 69.1090 +        return (d1 < d2) ? d1 : d2;
 69.1091 +    }
 69.1092 +
 69.1093 +    T       Dot(const Quat& q) const
 69.1094 +    {
 69.1095 +        return x * q.x + y * q.y + z * q.z + w * q.w;
 69.1096 +    }
 69.1097 +
 69.1098 +	// Angle between two quaternions in radians
 69.1099 +    T       Angle(const Quat& q) const
 69.1100 +	{
 69.1101 +		return 2 * Acos(Alg::Abs(Dot(q)));
 69.1102 +	}
 69.1103 +
 69.1104 +    // Normalize
 69.1105 +    bool    IsNormalized() const            { return fabs(LengthSq() - T(1)) < ((T)MATH_DOUBLE_TOLERANCE); }
 69.1106 +
 69.1107 +    void    Normalize()                     
 69.1108 +	{
 69.1109 + 		T l = Length();
 69.1110 +		OVR_ASSERT(l != T(0));
 69.1111 +		*this /= l; 
 69.1112 +	}
 69.1113 +
 69.1114 +	Quat    Normalized() const              
 69.1115 +	{ 
 69.1116 +		T l = Length();
 69.1117 +		OVR_ASSERT(l != T(0));
 69.1118 +		return *this / l; 
 69.1119 +	}
 69.1120 +
 69.1121 +    // Returns conjugate of the quaternion. Produces inverse rotation if quaternion is normalized.
 69.1122 +    Quat    Conj() const                    { return Quat(-x, -y, -z, w); }
 69.1123 +
 69.1124 +    // Quaternion multiplication. Combines quaternion rotations, performing the one on the 
 69.1125 +    // right hand side first.
 69.1126 +    Quat  operator* (const Quat& b) const   { return Quat(w * b.x + x * b.w + y * b.z - z * b.y,
 69.1127 +                                                          w * b.y - x * b.z + y * b.w + z * b.x,
 69.1128 +                                                          w * b.z + x * b.y - y * b.x + z * b.w,
 69.1129 +                                                          w * b.w - x * b.x - y * b.y - z * b.z); }
 69.1130 +
 69.1131 +    // 
 69.1132 +    // this^p normalized; same as rotating by this p times.
 69.1133 +    Quat PowNormalized(T p) const
 69.1134 +    {
 69.1135 +        Vector3<T> v;
 69.1136 +        T          a;
 69.1137 +        GetAxisAngle(&v, &a);
 69.1138 +        return Quat(v, a * p);
 69.1139 +    }
 69.1140 +
 69.1141 +    // Normalized linear interpolation of quaternions
 69.1142 +    Quat Nlerp(const Quat& other, T a)
 69.1143 +    {
 69.1144 +        T sign = (Dot(other) >= 0) ? 1 : -1;
 69.1145 +        return (*this * sign * a + other * (1-a)).Normalized();
 69.1146 +    }
 69.1147 +    
 69.1148 +    // Rotate transforms vector in a manner that matches Matrix rotations (counter-clockwise,
 69.1149 +    // assuming negative direction of the axis). Standard formula: q(t) * V * q(t)^-1. 
 69.1150 +    Vector3<T> Rotate(const Vector3<T>& v) const
 69.1151 +    {
 69.1152 +        return ((*this * Quat<T>(v.x, v.y, v.z, T(0))) * Inverted()).Imag();
 69.1153 +    }
 69.1154 +    
 69.1155 +    // Inversed quaternion rotates in the opposite direction.
 69.1156 +    Quat        Inverted() const
 69.1157 +    {
 69.1158 +        return Quat(-x, -y, -z, w);
 69.1159 +    }
 69.1160 +
 69.1161 +    // Sets this quaternion to the one rotates in the opposite direction.
 69.1162 +    void        Invert()
 69.1163 +    {
 69.1164 +        *this = Quat(-x, -y, -z, w);
 69.1165 +    }
 69.1166 +    
 69.1167 +    // GetEulerAngles extracts Euler angles from the quaternion, in the specified order of
 69.1168 +    // axis rotations and the specified coordinate system. Right-handed coordinate system
 69.1169 +    // is the default, with CCW rotations while looking in the negative axis direction.
 69.1170 +    // Here a,b,c, are the Yaw/Pitch/Roll angles to be returned.
 69.1171 +    // rotation a around axis A1
 69.1172 +    // is followed by rotation b around axis A2
 69.1173 +    // is followed by rotation c around axis A3
 69.1174 +    // rotations are CCW or CW (D) in LH or RH coordinate system (S)
 69.1175 +	template <Axis A1, Axis A2, Axis A3, RotateDirection D, HandedSystem S>
 69.1176 +    void GetEulerAngles(T *a, T *b, T *c) const 
 69.1177 +    {
 69.1178 +        static_assert((A1 != A2) && (A2 != A3) && (A1 != A3), "(A1 != A2) && (A2 != A3) && (A1 != A3)");
 69.1179 +
 69.1180 +        T Q[3] = { x, y, z };  //Quaternion components x,y,z
 69.1181 +
 69.1182 +        T ww  = w*w;
 69.1183 +        T Q11 = Q[A1]*Q[A1];
 69.1184 +        T Q22 = Q[A2]*Q[A2];
 69.1185 +        T Q33 = Q[A3]*Q[A3];
 69.1186 +
 69.1187 +        T psign = T(-1);
 69.1188 +        // Determine whether even permutation
 69.1189 +        if (((A1 + 1) % 3 == A2) && ((A2 + 1) % 3 == A3))
 69.1190 +            psign = T(1);
 69.1191 +        
 69.1192 +        T s2 = psign * T(2) * (psign*w*Q[A2] + Q[A1]*Q[A3]);
 69.1193 +
 69.1194 +        if (s2 < T(-1) + ((T)MATH_DOUBLE_SINGULARITYRADIUS))
 69.1195 +        { // South pole singularity
 69.1196 +            *a = T(0);
 69.1197 +            *b = -S*D*((T)MATH_DOUBLE_PIOVER2);
 69.1198 +            *c = S*D*atan2(T(2)*(psign*Q[A1]*Q[A2] + w*Q[A3]),
 69.1199 +		                   ww + Q22 - Q11 - Q33 );
 69.1200 +        }
 69.1201 +        else if (s2 > T(1) - ((T)MATH_DOUBLE_SINGULARITYRADIUS))
 69.1202 +        {  // North pole singularity
 69.1203 +            *a = T(0);
 69.1204 +            *b = S*D*((T)MATH_DOUBLE_PIOVER2);
 69.1205 +            *c = S*D*atan2(T(2)*(psign*Q[A1]*Q[A2] + w*Q[A3]),
 69.1206 +		                   ww + Q22 - Q11 - Q33);
 69.1207 +        }
 69.1208 +        else
 69.1209 +        {
 69.1210 +            *a = -S*D*atan2(T(-2)*(w*Q[A1] - psign*Q[A2]*Q[A3]),
 69.1211 +		                    ww + Q33 - Q11 - Q22);
 69.1212 +            *b = S*D*asin(s2);
 69.1213 +            *c = S*D*atan2(T(2)*(w*Q[A3] - psign*Q[A1]*Q[A2]),
 69.1214 +		                   ww + Q11 - Q22 - Q33);
 69.1215 +        }      
 69.1216 +        return;
 69.1217 +    }
 69.1218 +
 69.1219 +    template <Axis A1, Axis A2, Axis A3, RotateDirection D>
 69.1220 +    void GetEulerAngles(T *a, T *b, T *c) const
 69.1221 +    { GetEulerAngles<A1, A2, A3, D, Handed_R>(a, b, c); }
 69.1222 +
 69.1223 +    template <Axis A1, Axis A2, Axis A3>
 69.1224 +    void GetEulerAngles(T *a, T *b, T *c) const
 69.1225 +    { GetEulerAngles<A1, A2, A3, Rotate_CCW, Handed_R>(a, b, c); }
 69.1226 +
 69.1227 +    // GetEulerAnglesABA extracts Euler angles from the quaternion, in the specified order of
 69.1228 +    // axis rotations and the specified coordinate system. Right-handed coordinate system
 69.1229 +    // is the default, with CCW rotations while looking in the negative axis direction.
 69.1230 +    // Here a,b,c, are the Yaw/Pitch/Roll angles to be returned.
 69.1231 +    // rotation a around axis A1
 69.1232 +    // is followed by rotation b around axis A2
 69.1233 +    // is followed by rotation c around axis A1
 69.1234 +    // Rotations are CCW or CW (D) in LH or RH coordinate system (S)
 69.1235 +    template <Axis A1, Axis A2, RotateDirection D, HandedSystem S>
 69.1236 +    void GetEulerAnglesABA(T *a, T *b, T *c) const
 69.1237 +    {
 69.1238 +        static_assert(A1 != A2, "A1 != A2");
 69.1239 +
 69.1240 +        T Q[3] = {x, y, z}; // Quaternion components
 69.1241 +
 69.1242 +        // Determine the missing axis that was not supplied
 69.1243 +        int m = 3 - A1 - A2;
 69.1244 +
 69.1245 +        T ww = w*w;
 69.1246 +        T Q11 = Q[A1]*Q[A1];
 69.1247 +        T Q22 = Q[A2]*Q[A2];
 69.1248 +        T Qmm = Q[m]*Q[m];
 69.1249 +
 69.1250 +        T psign = T(-1);
 69.1251 +        if ((A1 + 1) % 3 == A2) // Determine whether even permutation
 69.1252 +        {
 69.1253 +            psign = T(1);
 69.1254 +        }
 69.1255 +
 69.1256 +        T c2 = ww + Q11 - Q22 - Qmm;
 69.1257 +        if (c2 < T(-1) + Math<T>::SingularityRadius)
 69.1258 +        { // South pole singularity
 69.1259 +            *a = T(0);
 69.1260 +            *b = S*D*((T)MATH_DOUBLE_PI);
 69.1261 +            *c = S*D*atan2( T(2)*(w*Q[A1] - psign*Q[A2]*Q[m]),
 69.1262 +		                    ww + Q22 - Q11 - Qmm);
 69.1263 +        }
 69.1264 +        else if (c2 > T(1) - Math<T>::SingularityRadius)
 69.1265 +        {  // North pole singularity
 69.1266 +            *a = T(0);
 69.1267 +            *b = T(0);
 69.1268 +            *c = S*D*atan2( T(2)*(w*Q[A1] - psign*Q[A2]*Q[m]),
 69.1269 +		                   ww + Q22 - Q11 - Qmm);
 69.1270 +        }
 69.1271 +        else
 69.1272 +        {
 69.1273 +            *a = S*D*atan2( psign*w*Q[m] + Q[A1]*Q[A2],
 69.1274 +		                   w*Q[A2] -psign*Q[A1]*Q[m]);
 69.1275 +            *b = S*D*acos(c2);
 69.1276 +            *c = S*D*atan2( -psign*w*Q[m] + Q[A1]*Q[A2],
 69.1277 +		                   w*Q[A2] + psign*Q[A1]*Q[m]);
 69.1278 +        }
 69.1279 +        return;
 69.1280 +    }
 69.1281 +};
 69.1282 +
 69.1283 +typedef Quat<float>  Quatf;
 69.1284 +typedef Quat<double> Quatd;
 69.1285 +
 69.1286 +static_assert((sizeof(Quatf) == 4*sizeof(float)), "sizeof(Quatf) failure");
 69.1287 +static_assert((sizeof(Quatd) == 4*sizeof(double)), "sizeof(Quatd) failure");
 69.1288 +
 69.1289 +//-------------------------------------------------------------------------------------
 69.1290 +// ***** Pose
 69.1291 +
 69.1292 +// Position and orientation combined.
 69.1293 +
 69.1294 +template<class T>
 69.1295 +class Pose
 69.1296 +{
 69.1297 +public:
 69.1298 +    typedef typename CompatibleTypes<Pose<T> >::Type CompatibleType;
 69.1299 +
 69.1300 +    Pose() { }
 69.1301 +    Pose(const Quat<T>& orientation, const Vector3<T>& pos)
 69.1302 +        : Rotation(orientation), Translation(pos) {  }
 69.1303 +    Pose(const Pose& s)
 69.1304 +        : Rotation(s.Rotation), Translation(s.Translation) {  }
 69.1305 +    Pose(const CompatibleType& s)
 69.1306 +        : Rotation(s.Orientation), Translation(s.Position) {  }
 69.1307 +    explicit Pose(const Pose<typename Math<T>::OtherFloatType> &s)
 69.1308 +        : Rotation(s.Rotation), Translation(s.Translation) {  }
 69.1309 +
 69.1310 +    operator typename CompatibleTypes<Pose<T> >::Type () const
 69.1311 +    {
 69.1312 +        typename CompatibleTypes<Pose<T> >::Type result;
 69.1313 +        result.Orientation = Rotation;
 69.1314 +        result.Position = Translation;
 69.1315 +        return result;
 69.1316 +    }
 69.1317 +
 69.1318 +    Quat<T>    Rotation;
 69.1319 +    Vector3<T> Translation;
 69.1320 +    
 69.1321 +    static_assert((sizeof(T) == sizeof(double) || sizeof(T) == sizeof(float)), "(sizeof(T) == sizeof(double) || sizeof(T) == sizeof(float))");
 69.1322 +
 69.1323 +    void ToArray(T* arr) const
 69.1324 +    {
 69.1325 +        T temp[7] =  { Rotation.x, Rotation.y, Rotation.z, Rotation.w, Translation.x, Translation.y, Translation.z };
 69.1326 +        for (int i = 0; i < 7; i++) arr[i] = temp[i];
 69.1327 +    }
 69.1328 +
 69.1329 +    static Pose<T> FromArray(const T* v)
 69.1330 +    {
 69.1331 +        Quat<T> rotation(v[0], v[1], v[2], v[3]);
 69.1332 +        Vector3<T> translation(v[4], v[5], v[6]);
 69.1333 +        return Pose<T>(rotation, translation);
 69.1334 +    }
 69.1335 +
 69.1336 +    Vector3<T> Rotate(const Vector3<T>& v) const
 69.1337 +    {
 69.1338 +        return Rotation.Rotate(v);
 69.1339 +    }
 69.1340 +
 69.1341 +    Vector3<T> Translate(const Vector3<T>& v) const
 69.1342 +    {
 69.1343 +        return v + Translation;
 69.1344 +    }
 69.1345 +
 69.1346 +    Vector3<T> Apply(const Vector3<T>& v) const
 69.1347 +    {
 69.1348 +        return Translate(Rotate(v));
 69.1349 +    }
 69.1350 +
 69.1351 +    Pose operator*(const Pose& other) const   
 69.1352 +    {
 69.1353 +        return Pose(Rotation * other.Rotation, Apply(other.Translation));
 69.1354 +    }
 69.1355 +
 69.1356 +    Pose Inverted() const   
 69.1357 +    {
 69.1358 +        Quat<T> inv = Rotation.Inverted();
 69.1359 +        return Pose(inv, inv.Rotate(-Translation));
 69.1360 +    }
 69.1361 +};
 69.1362 +
 69.1363 +typedef Pose<float>  Posef;
 69.1364 +typedef Pose<double> Posed;
 69.1365 +
 69.1366 +static_assert((sizeof(Posed) == sizeof(Quatd) + sizeof(Vector3d)), "sizeof(Posed) failure");
 69.1367 +static_assert((sizeof(Posef) == sizeof(Quatf) + sizeof(Vector3f)), "sizeof(Posef) failure");
 69.1368 +    
 69.1369 +
 69.1370 +//-------------------------------------------------------------------------------------
 69.1371 +// ***** Matrix4
 69.1372 +//
 69.1373 +// Matrix4 is a 4x4 matrix used for 3d transformations and projections.
 69.1374 +// Translation stored in the last column.
 69.1375 +// The matrix is stored in row-major order in memory, meaning that values
 69.1376 +// of the first row are stored before the next one.
 69.1377 +//
 69.1378 +// The arrangement of the matrix is chosen to be in Right-Handed 
 69.1379 +// coordinate system and counterclockwise rotations when looking down
 69.1380 +// the axis
 69.1381 +//
 69.1382 +// Transformation Order:
 69.1383 +//   - Transformations are applied from right to left, so the expression
 69.1384 +//     M1 * M2 * M3 * V means that the vector V is transformed by M3 first,
 69.1385 +//     followed by M2 and M1. 
 69.1386 +//
 69.1387 +// Coordinate system: Right Handed
 69.1388 +//
 69.1389 +// Rotations: Counterclockwise when looking down the axis. All angles are in radians.
 69.1390 +//    
 69.1391 +//  | sx   01   02   tx |    // First column  (sx, 10, 20): Axis X basis vector.
 69.1392 +//  | 10   sy   12   ty |    // Second column (01, sy, 21): Axis Y basis vector.
 69.1393 +//  | 20   21   sz   tz |    // Third columnt (02, 12, sz): Axis Z basis vector.
 69.1394 +//  | 30   31   32   33 |
 69.1395 +//
 69.1396 +//  The basis vectors are first three columns.
 69.1397 +
 69.1398 +template<class T>
 69.1399 +class Matrix4
 69.1400 +{
 69.1401 +    static const Matrix4 IdentityValue;
 69.1402 +
 69.1403 +public:
 69.1404 +    T M[4][4];    
 69.1405 +
 69.1406 +    enum NoInitType { NoInit };
 69.1407 +
 69.1408 +    // Construct with no memory initialization.
 69.1409 +    Matrix4(NoInitType) { }
 69.1410 +
 69.1411 +    // By default, we construct identity matrix.
 69.1412 +    Matrix4()
 69.1413 +    {
 69.1414 +        SetIdentity();        
 69.1415 +    }
 69.1416 +
 69.1417 +    Matrix4(T m11, T m12, T m13, T m14,
 69.1418 +            T m21, T m22, T m23, T m24,
 69.1419 +            T m31, T m32, T m33, T m34,
 69.1420 +            T m41, T m42, T m43, T m44)
 69.1421 +    {
 69.1422 +        M[0][0] = m11; M[0][1] = m12; M[0][2] = m13; M[0][3] = m14;
 69.1423 +        M[1][0] = m21; M[1][1] = m22; M[1][2] = m23; M[1][3] = m24;
 69.1424 +        M[2][0] = m31; M[2][1] = m32; M[2][2] = m33; M[2][3] = m34;
 69.1425 +        M[3][0] = m41; M[3][1] = m42; M[3][2] = m43; M[3][3] = m44;
 69.1426 +    }
 69.1427 +
 69.1428 +    Matrix4(T m11, T m12, T m13,
 69.1429 +            T m21, T m22, T m23,
 69.1430 +            T m31, T m32, T m33)
 69.1431 +    {
 69.1432 +        M[0][0] = m11; M[0][1] = m12; M[0][2] = m13; M[0][3] = 0;
 69.1433 +        M[1][0] = m21; M[1][1] = m22; M[1][2] = m23; M[1][3] = 0;
 69.1434 +        M[2][0] = m31; M[2][1] = m32; M[2][2] = m33; M[2][3] = 0;
 69.1435 +        M[3][0] = 0;   M[3][1] = 0;   M[3][2] = 0;   M[3][3] = 1;
 69.1436 +    }
 69.1437 +
 69.1438 +    explicit Matrix4(const Quat<T>& q)
 69.1439 +    {
 69.1440 +        T ww = q.w*q.w;
 69.1441 +        T xx = q.x*q.x;
 69.1442 +        T yy = q.y*q.y;
 69.1443 +        T zz = q.z*q.z;
 69.1444 +
 69.1445 +        M[0][0] = ww + xx - yy - zz;       M[0][1] = 2 * (q.x*q.y - q.w*q.z); M[0][2] = 2 * (q.x*q.z + q.w*q.y); M[0][3] = 0;
 69.1446 +        M[1][0] = 2 * (q.x*q.y + q.w*q.z); M[1][1] = ww - xx + yy - zz;       M[1][2] = 2 * (q.y*q.z - q.w*q.x); M[1][3] = 0;
 69.1447 +        M[2][0] = 2 * (q.x*q.z - q.w*q.y); M[2][1] = 2 * (q.y*q.z + q.w*q.x); M[2][2] = ww - xx - yy + zz;       M[2][3] = 0;
 69.1448 +        M[3][0] = 0;                       M[3][1] = 0;                       M[3][2] = 0;                       M[3][3] = 1;
 69.1449 +    }
 69.1450 +
 69.1451 +    explicit Matrix4(const Pose<T>& p)
 69.1452 +    {
 69.1453 +        Matrix4 result(p.Rotation);
 69.1454 +        result.SetTranslation(p.Translation);
 69.1455 +        *this = result;
 69.1456 +    }
 69.1457 +
 69.1458 +    // C-interop support
 69.1459 +    explicit Matrix4(const Matrix4<typename Math<T>::OtherFloatType> &src)
 69.1460 +    {
 69.1461 +        for (int i = 0; i < 4; i++)
 69.1462 +            for (int j = 0; j < 4; j++)
 69.1463 +                M[i][j] = (T)src.M[i][j];
 69.1464 +    }
 69.1465 +
 69.1466 +    // C-interop support.
 69.1467 +    Matrix4(const typename CompatibleTypes<Matrix4<T> >::Type& s) 
 69.1468 +    {
 69.1469 +        static_assert(sizeof(s) == sizeof(Matrix4), "sizeof(s) == sizeof(Matrix4)");
 69.1470 +        memcpy(M, s.M, sizeof(M));
 69.1471 +    }
 69.1472 +
 69.1473 +    operator typename CompatibleTypes<Matrix4<T> >::Type () const
 69.1474 +    {
 69.1475 +        typename CompatibleTypes<Matrix4<T> >::Type result;
 69.1476 +        static_assert(sizeof(result) == sizeof(Matrix4), "sizeof(result) == sizeof(Matrix4)");
 69.1477 +        memcpy(result.M, M, sizeof(M));
 69.1478 +        return result;
 69.1479 +    }
 69.1480 +
 69.1481 +    void ToString(char* dest, size_t destsize) const
 69.1482 +    {
 69.1483 +        size_t pos = 0;
 69.1484 +        for (int r=0; r<4; r++)
 69.1485 +            for (int c=0; c<4; c++)
 69.1486 +                pos += OVR_sprintf(dest+pos, destsize-pos, "%g ", M[r][c]);
 69.1487 +    }
 69.1488 +
 69.1489 +    static Matrix4 FromString(const char* src)
 69.1490 +    {
 69.1491 +        Matrix4 result;
 69.1492 +		if (src)
 69.1493 +		{
 69.1494 +        for (int r=0; r<4; r++)
 69.1495 +			{
 69.1496 +            for (int c=0; c<4; c++)
 69.1497 +            {
 69.1498 +                result.M[r][c] = (T)atof(src);
 69.1499 +                while (src && *src != ' ')
 69.1500 +					{
 69.1501 +                    src++;
 69.1502 +					}
 69.1503 +                while (src && *src == ' ')
 69.1504 +					{
 69.1505 +                    src++;
 69.1506 +            }
 69.1507 +				}
 69.1508 +			}
 69.1509 +		}
 69.1510 +        return result;
 69.1511 +    }
 69.1512 +
 69.1513 +    static const Matrix4& Identity()  { return IdentityValue; }
 69.1514 +
 69.1515 +    void SetIdentity()
 69.1516 +    {
 69.1517 +        M[0][0] = M[1][1] = M[2][2] = M[3][3] = 1;
 69.1518 +        M[0][1] = M[1][0] = M[2][3] = M[3][1] = 0;
 69.1519 +        M[0][2] = M[1][2] = M[2][0] = M[3][2] = 0;
 69.1520 +        M[0][3] = M[1][3] = M[2][1] = M[3][0] = 0;
 69.1521 +    }
 69.1522 +
 69.1523 +	void SetXBasis(const Vector3f & v)
 69.1524 +	{
 69.1525 +		M[0][0] = v.x;
 69.1526 +		M[1][0] = v.y;
 69.1527 +		M[2][0] = v.z;
 69.1528 +	}
 69.1529 +	Vector3f GetXBasis() const
 69.1530 +	{
 69.1531 +		return Vector3f(M[0][0], M[1][0], M[2][0]);
 69.1532 +	}
 69.1533 +
 69.1534 +	void SetYBasis(const Vector3f & v)
 69.1535 +	{
 69.1536 +		M[0][1] = v.x;
 69.1537 +		M[1][1] = v.y;
 69.1538 +		M[2][1] = v.z;
 69.1539 +	}
 69.1540 +	Vector3f GetYBasis() const
 69.1541 +	{
 69.1542 +		return Vector3f(M[0][1], M[1][1], M[2][1]);
 69.1543 +	}
 69.1544 +
 69.1545 +	void SetZBasis(const Vector3f & v)
 69.1546 +	{
 69.1547 +		M[0][2] = v.x;
 69.1548 +		M[1][2] = v.y;
 69.1549 +		M[2][2] = v.z;
 69.1550 +	}
 69.1551 +	Vector3f GetZBasis() const
 69.1552 +	{
 69.1553 +		return Vector3f(M[0][2], M[1][2], M[2][2]);
 69.1554 +	}
 69.1555 +
 69.1556 +	bool operator== (const Matrix4& b) const
 69.1557 +	{
 69.1558 +		bool isEqual = true;
 69.1559 +        for (int i = 0; i < 4; i++)
 69.1560 +            for (int j = 0; j < 4; j++)
 69.1561 +                isEqual &= (M[i][j] == b.M[i][j]);
 69.1562 +
 69.1563 +		return isEqual;
 69.1564 +	}
 69.1565 +
 69.1566 +    Matrix4 operator+ (const Matrix4& b) const
 69.1567 +    {
 69.1568 +        Matrix4 result(*this);
 69.1569 +        result += b;
 69.1570 +        return result;
 69.1571 +    }
 69.1572 +
 69.1573 +    Matrix4& operator+= (const Matrix4& b)
 69.1574 +    {
 69.1575 +        for (int i = 0; i < 4; i++)
 69.1576 +            for (int j = 0; j < 4; j++)
 69.1577 +                M[i][j] += b.M[i][j];
 69.1578 +        return *this;
 69.1579 +    }
 69.1580 +
 69.1581 +    Matrix4 operator- (const Matrix4& b) const
 69.1582 +    {
 69.1583 +        Matrix4 result(*this);
 69.1584 +        result -= b;
 69.1585 +        return result;
 69.1586 +    }
 69.1587 +
 69.1588 +    Matrix4& operator-= (const Matrix4& b)
 69.1589 +    {
 69.1590 +        for (int i = 0; i < 4; i++)
 69.1591 +            for (int j = 0; j < 4; j++)
 69.1592 +                M[i][j] -= b.M[i][j];
 69.1593 +        return *this;
 69.1594 +    }
 69.1595 +
 69.1596 +    // Multiplies two matrices into destination with minimum copying.
 69.1597 +    static Matrix4& Multiply(Matrix4* d, const Matrix4& a, const Matrix4& b)
 69.1598 +    {
 69.1599 +        OVR_ASSERT((d != &a) && (d != &b));
 69.1600 +        int i = 0;
 69.1601 +        do {
 69.1602 +            d->M[i][0] = a.M[i][0] * b.M[0][0] + a.M[i][1] * b.M[1][0] + a.M[i][2] * b.M[2][0] + a.M[i][3] * b.M[3][0];
 69.1603 +            d->M[i][1] = a.M[i][0] * b.M[0][1] + a.M[i][1] * b.M[1][1] + a.M[i][2] * b.M[2][1] + a.M[i][3] * b.M[3][1];
 69.1604 +            d->M[i][2] = a.M[i][0] * b.M[0][2] + a.M[i][1] * b.M[1][2] + a.M[i][2] * b.M[2][2] + a.M[i][3] * b.M[3][2];
 69.1605 +            d->M[i][3] = a.M[i][0] * b.M[0][3] + a.M[i][1] * b.M[1][3] + a.M[i][2] * b.M[2][3] + a.M[i][3] * b.M[3][3];
 69.1606 +        } while((++i) < 4);
 69.1607 +
 69.1608 +        return *d;
 69.1609 +    }
 69.1610 +
 69.1611 +    Matrix4 operator* (const Matrix4& b) const
 69.1612 +    {
 69.1613 +        Matrix4 result(Matrix4::NoInit);
 69.1614 +        Multiply(&result, *this, b);
 69.1615 +        return result;
 69.1616 +    }
 69.1617 +
 69.1618 +    Matrix4& operator*= (const Matrix4& b)
 69.1619 +    {
 69.1620 +        return Multiply(this, Matrix4(*this), b);
 69.1621 +    }
 69.1622 +
 69.1623 +    Matrix4 operator* (T s) const
 69.1624 +    {
 69.1625 +        Matrix4 result(*this);
 69.1626 +        result *= s;
 69.1627 +        return result;
 69.1628 +    }
 69.1629 +
 69.1630 +    Matrix4& operator*= (T s)
 69.1631 +    {
 69.1632 +        for (int i = 0; i < 4; i++)
 69.1633 +            for (int j = 0; j < 4; j++)
 69.1634 +                M[i][j] *= s;
 69.1635 +        return *this;
 69.1636 +    }
 69.1637 +
 69.1638 +
 69.1639 +    Matrix4 operator/ (T s) const
 69.1640 +    {
 69.1641 +        Matrix4 result(*this);
 69.1642 +        result /= s;
 69.1643 +        return result;
 69.1644 +    }
 69.1645 +
 69.1646 +    Matrix4& operator/= (T s)
 69.1647 +    {
 69.1648 +        for (int i = 0; i < 4; i++)
 69.1649 +            for (int j = 0; j < 4; j++)
 69.1650 +                M[i][j] /= s;
 69.1651 +        return *this;
 69.1652 +    }
 69.1653 +
 69.1654 +    Vector3<T> Transform(const Vector3<T>& v) const
 69.1655 +    {
 69.1656 +		const T rcpW = 1.0f / (M[3][0] * v.x + M[3][1] * v.y + M[3][2] * v.z + M[3][3]);
 69.1657 +		return Vector3<T>((M[0][0] * v.x + M[0][1] * v.y + M[0][2] * v.z + M[0][3]) * rcpW,
 69.1658 +						  (M[1][0] * v.x + M[1][1] * v.y + M[1][2] * v.z + M[1][3]) * rcpW,
 69.1659 +						  (M[2][0] * v.x + M[2][1] * v.y + M[2][2] * v.z + M[2][3]) * rcpW);
 69.1660 +	}
 69.1661 +
 69.1662 +	Vector4<T> Transform(const Vector4<T>& v) const
 69.1663 +	{
 69.1664 +		return Vector4<T>(M[0][0] * v.x + M[0][1] * v.y + M[0][2] * v.z + M[0][3] * v.w,
 69.1665 +						  M[1][0] * v.x + M[1][1] * v.y + M[1][2] * v.z + M[1][3] * v.w,
 69.1666 +						  M[2][0] * v.x + M[2][1] * v.y + M[2][2] * v.z + M[2][3] * v.w,
 69.1667 +						  M[3][0] * v.x + M[3][1] * v.y + M[3][2] * v.z + M[3][3] * v.w);
 69.1668 +    }
 69.1669 +
 69.1670 +    Matrix4 Transposed() const
 69.1671 +    {
 69.1672 +        return Matrix4(M[0][0], M[1][0], M[2][0], M[3][0],
 69.1673 +                        M[0][1], M[1][1], M[2][1], M[3][1],
 69.1674 +                        M[0][2], M[1][2], M[2][2], M[3][2],
 69.1675 +                        M[0][3], M[1][3], M[2][3], M[3][3]);
 69.1676 +    }
 69.1677 +
 69.1678 +    void     Transpose()
 69.1679 +    {
 69.1680 +        *this = Transposed();
 69.1681 +    }
 69.1682 +
 69.1683 +
 69.1684 +    T SubDet (const size_t* rows, const size_t* cols) const
 69.1685 +    {
 69.1686 +        return M[rows[0]][cols[0]] * (M[rows[1]][cols[1]] * M[rows[2]][cols[2]] - M[rows[1]][cols[2]] * M[rows[2]][cols[1]])
 69.1687 +             - M[rows[0]][cols[1]] * (M[rows[1]][cols[0]] * M[rows[2]][cols[2]] - M[rows[1]][cols[2]] * M[rows[2]][cols[0]])
 69.1688 +             + M[rows[0]][cols[2]] * (M[rows[1]][cols[0]] * M[rows[2]][cols[1]] - M[rows[1]][cols[1]] * M[rows[2]][cols[0]]);
 69.1689 +    }
 69.1690 +
 69.1691 +    T Cofactor(size_t I, size_t J) const
 69.1692 +    {
 69.1693 +        const size_t indices[4][3] = {{1,2,3},{0,2,3},{0,1,3},{0,1,2}};
 69.1694 +        return ((I+J)&1) ? -SubDet(indices[I],indices[J]) : SubDet(indices[I],indices[J]);
 69.1695 +    }
 69.1696 +
 69.1697 +    T    Determinant() const
 69.1698 +    {
 69.1699 +        return M[0][0] * Cofactor(0,0) + M[0][1] * Cofactor(0,1) + M[0][2] * Cofactor(0,2) + M[0][3] * Cofactor(0,3);
 69.1700 +    }
 69.1701 +
 69.1702 +    Matrix4 Adjugated() const
 69.1703 +    {
 69.1704 +        return Matrix4(Cofactor(0,0), Cofactor(1,0), Cofactor(2,0), Cofactor(3,0), 
 69.1705 +                        Cofactor(0,1), Cofactor(1,1), Cofactor(2,1), Cofactor(3,1), 
 69.1706 +                        Cofactor(0,2), Cofactor(1,2), Cofactor(2,2), Cofactor(3,2),
 69.1707 +                        Cofactor(0,3), Cofactor(1,3), Cofactor(2,3), Cofactor(3,3));
 69.1708 +    }
 69.1709 +
 69.1710 +    Matrix4 Inverted() const
 69.1711 +    {
 69.1712 +        T det = Determinant();
 69.1713 +        assert(det != 0);
 69.1714 +        return Adjugated() * (1.0f/det);
 69.1715 +    }
 69.1716 +
 69.1717 +    void Invert()
 69.1718 +    {
 69.1719 +        *this = Inverted();
 69.1720 +    }
 69.1721 +
 69.1722 +	// This is more efficient than general inverse, but ONLY works
 69.1723 +	// correctly if it is a homogeneous transform matrix (rot + trans)
 69.1724 +	Matrix4 InvertedHomogeneousTransform() const
 69.1725 +	{
 69.1726 +		// Make the inverse rotation matrix
 69.1727 +		Matrix4 rinv = this->Transposed();
 69.1728 +		rinv.M[3][0] = rinv.M[3][1] = rinv.M[3][2] = 0.0f;
 69.1729 +		// Make the inverse translation matrix
 69.1730 +		Vector3<T> tvinv(-M[0][3],-M[1][3],-M[2][3]);
 69.1731 +		Matrix4 tinv = Matrix4::Translation(tvinv);
 69.1732 +		return rinv * tinv;  // "untranslate", then "unrotate"
 69.1733 +	}
 69.1734 +
 69.1735 +	// This is more efficient than general inverse, but ONLY works
 69.1736 +	// correctly if it is a homogeneous transform matrix (rot + trans)
 69.1737 +	void InvertHomogeneousTransform()
 69.1738 +	{
 69.1739 +        *this = InvertedHomogeneousTransform();
 69.1740 +	}
 69.1741 +
 69.1742 +	// Matrix to Euler Angles conversion
 69.1743 +    // a,b,c, are the YawPitchRoll angles to be returned
 69.1744 +    // rotation a around axis A1
 69.1745 +    // is followed by rotation b around axis A2
 69.1746 +    // is followed by rotation c around axis A3
 69.1747 +    // rotations are CCW or CW (D) in LH or RH coordinate system (S)
 69.1748 +    template <Axis A1, Axis A2, Axis A3, RotateDirection D, HandedSystem S>
 69.1749 +    void ToEulerAngles(T *a, T *b, T *c) const
 69.1750 +    {
 69.1751 +        static_assert((A1 != A2) && (A2 != A3) && (A1 != A3), "(A1 != A2) && (A2 != A3) && (A1 != A3)");
 69.1752 +
 69.1753 +        T psign = -1;
 69.1754 +        if (((A1 + 1) % 3 == A2) && ((A2 + 1) % 3 == A3)) // Determine whether even permutation
 69.1755 +        psign = 1;
 69.1756 +        
 69.1757 +        T pm = psign*M[A1][A3];
 69.1758 +        if (pm < -1.0f + Math<T>::SingularityRadius)
 69.1759 +        { // South pole singularity
 69.1760 +            *a = 0;
 69.1761 +            *b = -S*D*((T)MATH_DOUBLE_PIOVER2);
 69.1762 +            *c = S*D*atan2( psign*M[A2][A1], M[A2][A2] );
 69.1763 +        }
 69.1764 +        else if (pm > 1.0f - Math<T>::SingularityRadius)
 69.1765 +        { // North pole singularity
 69.1766 +            *a = 0;
 69.1767 +            *b = S*D*((T)MATH_DOUBLE_PIOVER2);
 69.1768 +            *c = S*D*atan2( psign*M[A2][A1], M[A2][A2] );
 69.1769 +        }
 69.1770 +        else
 69.1771 +        { // Normal case (nonsingular)
 69.1772 +            *a = S*D*atan2( -psign*M[A2][A3], M[A3][A3] );
 69.1773 +            *b = S*D*asin(pm);
 69.1774 +            *c = S*D*atan2( -psign*M[A1][A2], M[A1][A1] );
 69.1775 +        }
 69.1776 +
 69.1777 +        return;
 69.1778 +    }
 69.1779 +
 69.1780 +	// Matrix to Euler Angles conversion
 69.1781 +    // a,b,c, are the YawPitchRoll angles to be returned
 69.1782 +    // rotation a around axis A1
 69.1783 +    // is followed by rotation b around axis A2
 69.1784 +    // is followed by rotation c around axis A1
 69.1785 +    // rotations are CCW or CW (D) in LH or RH coordinate system (S)
 69.1786 +    template <Axis A1, Axis A2, RotateDirection D, HandedSystem S>
 69.1787 +    void ToEulerAnglesABA(T *a, T *b, T *c) const
 69.1788 +    {        
 69.1789 +         static_assert(A1 != A2, "A1 != A2");
 69.1790 +  
 69.1791 +        // Determine the axis that was not supplied
 69.1792 +        int m = 3 - A1 - A2;
 69.1793 +
 69.1794 +        T psign = -1;
 69.1795 +        if ((A1 + 1) % 3 == A2) // Determine whether even permutation
 69.1796 +            psign = 1.0f;
 69.1797 +
 69.1798 +        T c2 = M[A1][A1];
 69.1799 +        if (c2 < -1 + Math<T>::SingularityRadius)
 69.1800 +        { // South pole singularity
 69.1801 +            *a = 0;
 69.1802 +            *b = S*D*((T)MATH_DOUBLE_PI);
 69.1803 +            *c = S*D*atan2( -psign*M[A2][m],M[A2][A2]);
 69.1804 +        }
 69.1805 +        else if (c2 > 1.0f - Math<T>::SingularityRadius)
 69.1806 +        { // North pole singularity
 69.1807 +            *a = 0;
 69.1808 +            *b = 0;
 69.1809 +            *c = S*D*atan2( -psign*M[A2][m],M[A2][A2]);
 69.1810 +        }
 69.1811 +        else
 69.1812 +        { // Normal case (nonsingular)
 69.1813 +            *a = S*D*atan2( M[A2][A1],-psign*M[m][A1]);
 69.1814 +            *b = S*D*acos(c2);
 69.1815 +            *c = S*D*atan2( M[A1][A2],psign*M[A1][m]);
 69.1816 +        }
 69.1817 +        return;
 69.1818 +    }
 69.1819 +  
 69.1820 +    // Creates a matrix that converts the vertices from one coordinate system
 69.1821 +    // to another.
 69.1822 +    static Matrix4 AxisConversion(const WorldAxes& to, const WorldAxes& from)
 69.1823 +    {        
 69.1824 +        // Holds axis values from the 'to' structure
 69.1825 +        int toArray[3] = { to.XAxis, to.YAxis, to.ZAxis };
 69.1826 +
 69.1827 +        // The inverse of the toArray
 69.1828 +        int inv[4]; 
 69.1829 +        inv[0] = inv[abs(to.XAxis)] = 0;
 69.1830 +        inv[abs(to.YAxis)] = 1;
 69.1831 +        inv[abs(to.ZAxis)] = 2;
 69.1832 +
 69.1833 +        Matrix4 m(0,  0,  0, 
 69.1834 +                  0,  0,  0,
 69.1835 +                  0,  0,  0);
 69.1836 +
 69.1837 +        // Only three values in the matrix need to be changed to 1 or -1.
 69.1838 +        m.M[inv[abs(from.XAxis)]][0] = T(from.XAxis/toArray[inv[abs(from.XAxis)]]);
 69.1839 +        m.M[inv[abs(from.YAxis)]][1] = T(from.YAxis/toArray[inv[abs(from.YAxis)]]);
 69.1840 +        m.M[inv[abs(from.ZAxis)]][2] = T(from.ZAxis/toArray[inv[abs(from.ZAxis)]]);
 69.1841 +        return m;
 69.1842 +    } 
 69.1843 +
 69.1844 +
 69.1845 +	// Creates a matrix for translation by vector
 69.1846 +    static Matrix4 Translation(const Vector3<T>& v)
 69.1847 +    {
 69.1848 +        Matrix4 t;
 69.1849 +        t.M[0][3] = v.x;
 69.1850 +        t.M[1][3] = v.y;
 69.1851 +        t.M[2][3] = v.z;
 69.1852 +        return t;
 69.1853 +    }
 69.1854 +
 69.1855 +	// Creates a matrix for translation by vector
 69.1856 +    static Matrix4 Translation(T x, T y, T z = 0.0f)
 69.1857 +    {
 69.1858 +        Matrix4 t;
 69.1859 +        t.M[0][3] = x;
 69.1860 +        t.M[1][3] = y;
 69.1861 +        t.M[2][3] = z;
 69.1862 +        return t;
 69.1863 +    }
 69.1864 +
 69.1865 +	// Sets the translation part
 69.1866 +    void SetTranslation(const Vector3<T>& v)
 69.1867 +    {
 69.1868 +        M[0][3] = v.x;
 69.1869 +        M[1][3] = v.y;
 69.1870 +        M[2][3] = v.z;
 69.1871 +    }
 69.1872 +
 69.1873 +    Vector3<T> GetTranslation() const
 69.1874 +    {
 69.1875 +        return Vector3<T>( M[0][3], M[1][3], M[2][3] );
 69.1876 +    }
 69.1877 +
 69.1878 +	// Creates a matrix for scaling by vector
 69.1879 +    static Matrix4 Scaling(const Vector3<T>& v)
 69.1880 +    {
 69.1881 +        Matrix4 t;
 69.1882 +        t.M[0][0] = v.x;
 69.1883 +        t.M[1][1] = v.y;
 69.1884 +        t.M[2][2] = v.z;
 69.1885 +        return t;
 69.1886 +    }
 69.1887 +
 69.1888 +	// Creates a matrix for scaling by vector
 69.1889 +    static Matrix4 Scaling(T x, T y, T z)
 69.1890 +    {
 69.1891 +        Matrix4 t;
 69.1892 +        t.M[0][0] = x;
 69.1893 +        t.M[1][1] = y;
 69.1894 +        t.M[2][2] = z;
 69.1895 +        return t;
 69.1896 +    }
 69.1897 +
 69.1898 +	// Creates a matrix for scaling by constant
 69.1899 +    static Matrix4 Scaling(T s)
 69.1900 +    {
 69.1901 +        Matrix4 t;
 69.1902 +        t.M[0][0] = s;
 69.1903 +        t.M[1][1] = s;
 69.1904 +        t.M[2][2] = s;
 69.1905 +        return t;
 69.1906 +    }
 69.1907 +
 69.1908 +    // Simple L1 distance in R^12
 69.1909 +	T Distance(const Matrix4& m2) const           
 69.1910 +	{ 
 69.1911 +		T d = fabs(M[0][0] - m2.M[0][0]) + fabs(M[0][1] - m2.M[0][1]);
 69.1912 +		d += fabs(M[0][2] - m2.M[0][2]) + fabs(M[0][3] - m2.M[0][3]);
 69.1913 +		d += fabs(M[1][0] - m2.M[1][0]) + fabs(M[1][1] - m2.M[1][1]);
 69.1914 +		d += fabs(M[1][2] - m2.M[1][2]) + fabs(M[1][3] - m2.M[1][3]);
 69.1915 +		d += fabs(M[2][0] - m2.M[2][0]) + fabs(M[2][1] - m2.M[2][1]);
 69.1916 +		d += fabs(M[2][2] - m2.M[2][2]) + fabs(M[2][3] - m2.M[2][3]);
 69.1917 +		d += fabs(M[3][0] - m2.M[3][0]) + fabs(M[3][1] - m2.M[3][1]);
 69.1918 +		d += fabs(M[3][2] - m2.M[3][2]) + fabs(M[3][3] - m2.M[3][3]);
 69.1919 +		return d; 
 69.1920 +	}
 69.1921 +
 69.1922 +    // Creates a rotation matrix rotating around the X axis by 'angle' radians.
 69.1923 +    // Just for quick testing.  Not for final API.  Need to remove case.
 69.1924 +    static Matrix4 RotationAxis(Axis A, T angle, RotateDirection d, HandedSystem s)
 69.1925 +    {
 69.1926 +        T sina = s * d *sin(angle);
 69.1927 +        T cosa = cos(angle);
 69.1928 +        
 69.1929 +        switch(A)
 69.1930 +        {
 69.1931 +        case Axis_X:
 69.1932 +            return Matrix4(1,  0,     0, 
 69.1933 +                           0,  cosa,  -sina,
 69.1934 +                           0,  sina,  cosa);
 69.1935 +        case Axis_Y:
 69.1936 +            return Matrix4(cosa,  0,   sina, 
 69.1937 +                           0,     1,   0,
 69.1938 +                           -sina, 0,   cosa);
 69.1939 +        case Axis_Z:
 69.1940 +            return Matrix4(cosa,  -sina,  0, 
 69.1941 +                           sina,  cosa,   0,
 69.1942 +                           0,     0,      1);
 69.1943 +        }
 69.1944 +    }
 69.1945 +
 69.1946 +
 69.1947 +    // Creates a rotation matrix rotating around the X axis by 'angle' radians.
 69.1948 +    // Rotation direction is depends on the coordinate system:
 69.1949 +    // RHS (Oculus default): Positive angle values rotate Counter-clockwise (CCW),
 69.1950 +    //                        while looking in the negative axis direction. This is the
 69.1951 +    //                        same as looking down from positive axis values towards origin.
 69.1952 +    // LHS: Positive angle values rotate clock-wise (CW), while looking in the
 69.1953 +    //       negative axis direction.
 69.1954 +    static Matrix4 RotationX(T angle)
 69.1955 +    {
 69.1956 +        T sina = sin(angle);
 69.1957 +        T cosa = cos(angle);
 69.1958 +        return Matrix4(1,  0,     0, 
 69.1959 +                       0,  cosa,  -sina,
 69.1960 +                       0,  sina,  cosa);
 69.1961 +    }
 69.1962 +
 69.1963 +    // Creates a rotation matrix rotating around the Y axis by 'angle' radians.
 69.1964 +    // Rotation direction is depends on the coordinate system:
 69.1965 +    //  RHS (Oculus default): Positive angle values rotate Counter-clockwise (CCW),
 69.1966 +    //                        while looking in the negative axis direction. This is the
 69.1967 +    //                        same as looking down from positive axis values towards origin.
 69.1968 +    //  LHS: Positive angle values rotate clock-wise (CW), while looking in the
 69.1969 +    //       negative axis direction.
 69.1970 +    static Matrix4 RotationY(T angle)
 69.1971 +    {
 69.1972 +        T sina = sin(angle);
 69.1973 +        T cosa = cos(angle);
 69.1974 +        return Matrix4(cosa,  0,   sina, 
 69.1975 +                       0,     1,   0,
 69.1976 +                       -sina, 0,   cosa);
 69.1977 +    }
 69.1978 +
 69.1979 +    // Creates a rotation matrix rotating around the Z axis by 'angle' radians.
 69.1980 +    // Rotation direction is depends on the coordinate system:
 69.1981 +    //  RHS (Oculus default): Positive angle values rotate Counter-clockwise (CCW),
 69.1982 +    //                        while looking in the negative axis direction. This is the
 69.1983 +    //                        same as looking down from positive axis values towards origin.
 69.1984 +    //  LHS: Positive angle values rotate clock-wise (CW), while looking in the
 69.1985 +    //       negative axis direction.
 69.1986 +    static Matrix4 RotationZ(T angle)
 69.1987 +    {
 69.1988 +        T sina = sin(angle);
 69.1989 +        T cosa = cos(angle);
 69.1990 +        return Matrix4(cosa,  -sina,  0, 
 69.1991 +                       sina,  cosa,   0,
 69.1992 +                       0,     0,      1);
 69.1993 +    }
 69.1994 +
 69.1995 +    // LookAtRH creates a View transformation matrix for right-handed coordinate system.
 69.1996 +    // The resulting matrix points camera from 'eye' towards 'at' direction, with 'up'
 69.1997 +    // specifying the up vector. The resulting matrix should be used with PerspectiveRH
 69.1998 +    // projection.
 69.1999 +    static Matrix4 LookAtRH(const Vector3<T>& eye, const Vector3<T>& at, const Vector3<T>& up)
 69.2000 +    {
 69.2001 +        Vector3<T> z = (eye - at).Normalized();  // Forward
 69.2002 +        Vector3<T> x = up.Cross(z).Normalized(); // Right
 69.2003 +        Vector3<T> y = z.Cross(x);
 69.2004 +
 69.2005 +        Matrix4 m(x.x,  x.y,  x.z,  -(x.Dot(eye)),
 69.2006 +                  y.x,  y.y,  y.z,  -(y.Dot(eye)),
 69.2007 +                  z.x,  z.y,  z.z,  -(z.Dot(eye)),
 69.2008 +                  0,    0,    0,    1 );
 69.2009 +        return m;
 69.2010 +    }
 69.2011 +    
 69.2012 +    // LookAtLH creates a View transformation matrix for left-handed coordinate system.
 69.2013 +    // The resulting matrix points camera from 'eye' towards 'at' direction, with 'up'
 69.2014 +    // specifying the up vector. 
 69.2015 +    static Matrix4 LookAtLH(const Vector3<T>& eye, const Vector3<T>& at, const Vector3<T>& up)
 69.2016 +    {
 69.2017 +        Vector3<T> z = (at - eye).Normalized();  // Forward
 69.2018 +        Vector3<T> x = up.Cross(z).Normalized(); // Right
 69.2019 +        Vector3<T> y = z.Cross(x);
 69.2020 +
 69.2021 +        Matrix4 m(x.x,  x.y,  x.z,  -(x.Dot(eye)),
 69.2022 +                  y.x,  y.y,  y.z,  -(y.Dot(eye)),
 69.2023 +                  z.x,  z.y,  z.z,  -(z.Dot(eye)),
 69.2024 +                  0,    0,    0,    1 ); 
 69.2025 +        return m;
 69.2026 +    }
 69.2027 +    
 69.2028 +    // PerspectiveRH creates a right-handed perspective projection matrix that can be
 69.2029 +    // used with the Oculus sample renderer. 
 69.2030 +    //  yfov   - Specifies vertical field of view in radians.
 69.2031 +    //  aspect - Screen aspect ration, which is usually width/height for square pixels.
 69.2032 +    //           Note that xfov = yfov * aspect.
 69.2033 +    //  znear  - Absolute value of near Z clipping clipping range.
 69.2034 +    //  zfar   - Absolute value of far  Z clipping clipping range (larger then near).
 69.2035 +    // Even though RHS usually looks in the direction of negative Z, positive values
 69.2036 +    // are expected for znear and zfar.
 69.2037 +    static Matrix4 PerspectiveRH(T yfov, T aspect, T znear, T zfar)
 69.2038 +    {
 69.2039 +        Matrix4 m;
 69.2040 +        T tanHalfFov = tan(yfov * 0.5f);
 69.2041 +
 69.2042 +        m.M[0][0] = 1. / (aspect * tanHalfFov);
 69.2043 +        m.M[1][1] = 1. / tanHalfFov;
 69.2044 +        m.M[2][2] = zfar / (znear - zfar);
 69.2045 +        m.M[3][2] = -1.;
 69.2046 +        m.M[2][3] = (zfar * znear) / (znear - zfar);
 69.2047 +        m.M[3][3] = 0.;
 69.2048 +
 69.2049 +        // Note: Post-projection matrix result assumes Left-Handed coordinate system,
 69.2050 +        //       with Y up, X right and Z forward. This supports positive z-buffer values.
 69.2051 +		// This is the case even for RHS coordinate input.
 69.2052 +        return m;
 69.2053 +    }
 69.2054 +    
 69.2055 +    // PerspectiveLH creates a left-handed perspective projection matrix that can be
 69.2056 +    // used with the Oculus sample renderer. 
 69.2057 +    //  yfov   - Specifies vertical field of view in radians.
 69.2058 +    //  aspect - Screen aspect ration, which is usually width/height for square pixels.
 69.2059 +    //           Note that xfov = yfov * aspect.
 69.2060 +    //  znear  - Absolute value of near Z clipping clipping range.
 69.2061 +    //  zfar   - Absolute value of far  Z clipping clipping range (larger then near).
 69.2062 +    static Matrix4 PerspectiveLH(T yfov, T aspect, T znear, T zfar)
 69.2063 +    {
 69.2064 +        Matrix4 m;
 69.2065 +        T tanHalfFov = tan(yfov * 0.5f);
 69.2066 +
 69.2067 +        m.M[0][0] = 1. / (aspect * tanHalfFov);
 69.2068 +        m.M[1][1] = 1. / tanHalfFov;
 69.2069 +        //m.M[2][2] = zfar / (znear - zfar);
 69.2070 +         m.M[2][2] = zfar / (zfar - znear);
 69.2071 +        m.M[3][2] = -1.;
 69.2072 +        m.M[2][3] = (zfar * znear) / (znear - zfar);
 69.2073 +        m.M[3][3] = 0.;
 69.2074 +
 69.2075 +        // Note: Post-projection matrix result assumes Left-Handed coordinate system,    
 69.2076 +        //       with Y up, X right and Z forward. This supports positive z-buffer values.
 69.2077 +        // This is the case even for RHS coordinate input. 
 69.2078 +        return m;
 69.2079 +    }
 69.2080 +
 69.2081 +    static Matrix4 Ortho2D(T w, T h)
 69.2082 +    {
 69.2083 +        Matrix4 m;
 69.2084 +        m.M[0][0] = 2.0/w;
 69.2085 +        m.M[1][1] = -2.0/h;
 69.2086 +        m.M[0][3] = -1.0;
 69.2087 +        m.M[1][3] = 1.0;
 69.2088 +        m.M[2][2] = 0;
 69.2089 +        return m;
 69.2090 +    }
 69.2091 +};
 69.2092 +
 69.2093 +typedef Matrix4<float>  Matrix4f;
 69.2094 +typedef Matrix4<double> Matrix4d;
 69.2095 +
 69.2096 +//-------------------------------------------------------------------------------------
 69.2097 +// ***** Matrix3
 69.2098 +//
 69.2099 +// Matrix3 is a 3x3 matrix used for representing a rotation matrix.
 69.2100 +// The matrix is stored in row-major order in memory, meaning that values
 69.2101 +// of the first row are stored before the next one.
 69.2102 +//
 69.2103 +// The arrangement of the matrix is chosen to be in Right-Handed 
 69.2104 +// coordinate system and counterclockwise rotations when looking down
 69.2105 +// the axis
 69.2106 +//
 69.2107 +// Transformation Order:
 69.2108 +//   - Transformations are applied from right to left, so the expression
 69.2109 +//     M1 * M2 * M3 * V means that the vector V is transformed by M3 first,
 69.2110 +//     followed by M2 and M1. 
 69.2111 +//
 69.2112 +// Coordinate system: Right Handed
 69.2113 +//
 69.2114 +// Rotations: Counterclockwise when looking down the axis. All angles are in radians.
 69.2115 +
 69.2116 +template<typename T>
 69.2117 +class SymMat3;
 69.2118 +
 69.2119 +template<class T>
 69.2120 +class Matrix3
 69.2121 +{
 69.2122 +	static const Matrix3 IdentityValue;
 69.2123 +
 69.2124 +public:
 69.2125 +	T M[3][3];    
 69.2126 +
 69.2127 +	enum NoInitType { NoInit };
 69.2128 +
 69.2129 +	// Construct with no memory initialization.
 69.2130 +	Matrix3(NoInitType) { }
 69.2131 +
 69.2132 +	// By default, we construct identity matrix.
 69.2133 +	Matrix3()
 69.2134 +	{
 69.2135 +		SetIdentity();        
 69.2136 +	}
 69.2137 +
 69.2138 +	Matrix3(T m11, T m12, T m13,
 69.2139 +			T m21, T m22, T m23,
 69.2140 +			T m31, T m32, T m33)
 69.2141 +	{
 69.2142 +		M[0][0] = m11; M[0][1] = m12; M[0][2] = m13;
 69.2143 +		M[1][0] = m21; M[1][1] = m22; M[1][2] = m23;
 69.2144 +		M[2][0] = m31; M[2][1] = m32; M[2][2] = m33;
 69.2145 +	}
 69.2146 +	
 69.2147 +	/*
 69.2148 +	explicit Matrix3(const Quat<T>& q)
 69.2149 +	{
 69.2150 +		T ww = q.w*q.w;
 69.2151 +		T xx = q.x*q.x;
 69.2152 +		T yy = q.y*q.y;
 69.2153 +		T zz = q.z*q.z;
 69.2154 +
 69.2155 +		M[0][0] = ww + xx - yy - zz;       M[0][1] = 2 * (q.x*q.y - q.w*q.z); M[0][2] = 2 * (q.x*q.z + q.w*q.y);
 69.2156 +		M[1][0] = 2 * (q.x*q.y + q.w*q.z); M[1][1] = ww - xx + yy - zz;       M[1][2] = 2 * (q.y*q.z - q.w*q.x);
 69.2157 +		M[2][0] = 2 * (q.x*q.z - q.w*q.y); M[2][1] = 2 * (q.y*q.z + q.w*q.x); M[2][2] = ww - xx - yy + zz;      
 69.2158 +	}
 69.2159 +	*/
 69.2160 +	
 69.2161 +	explicit Matrix3(const Quat<T>& q)
 69.2162 +	{
 69.2163 +		const T tx  = q.x+q.x,  ty  = q.y+q.y,  tz  = q.z+q.z;
 69.2164 +		const T twx = q.w*tx,   twy = q.w*ty,   twz = q.w*tz;
 69.2165 +		const T txx = q.x*tx,   txy = q.x*ty,   txz = q.x*tz;
 69.2166 +		const T tyy = q.y*ty,   tyz = q.y*tz,   tzz = q.z*tz;
 69.2167 +		M[0][0] = T(1) - (tyy + tzz);	M[0][1] = txy - twz;			M[0][2] = txz + twy;
 69.2168 +		M[1][0] = txy + twz;			M[1][1] = T(1) - (txx + tzz);	M[1][2] = tyz - twx;
 69.2169 +		M[2][0] = txz - twy;			M[2][1] = tyz + twx;			M[2][2] = T(1) - (txx + tyy);
 69.2170 +	}
 69.2171 +	
 69.2172 +	inline explicit Matrix3(T s)
 69.2173 +    {
 69.2174 +        M[0][0] = M[1][1] = M[2][2] = s;
 69.2175 +        M[0][1] = M[0][2] = M[1][0] = M[1][2] = M[2][0] = M[2][1] = 0;
 69.2176 +    }
 69.2177 +
 69.2178 +	explicit Matrix3(const Pose<T>& p)
 69.2179 +	{
 69.2180 +		Matrix3 result(p.Rotation);
 69.2181 +		result.SetTranslation(p.Translation);
 69.2182 +		*this = result;
 69.2183 +	}
 69.2184 +
 69.2185 +	// C-interop support
 69.2186 +	explicit Matrix3(const Matrix4<typename Math<T>::OtherFloatType> &src)
 69.2187 +	{
 69.2188 +		for (int i = 0; i < 3; i++)
 69.2189 +			for (int j = 0; j < 3; j++)
 69.2190 +				M[i][j] = (T)src.M[i][j];
 69.2191 +	}
 69.2192 +
 69.2193 +	// C-interop support.
 69.2194 +	Matrix3(const typename CompatibleTypes<Matrix3<T> >::Type& s) 
 69.2195 +	{
 69.2196 +		static_assert(sizeof(s) == sizeof(Matrix3), "sizeof(s) == sizeof(Matrix3)");
 69.2197 +		memcpy(M, s.M, sizeof(M));
 69.2198 +	}
 69.2199 +
 69.2200 +	operator const typename CompatibleTypes<Matrix3<T> >::Type () const
 69.2201 +	{
 69.2202 +		typename CompatibleTypes<Matrix3<T> >::Type result;
 69.2203 +		static_assert(sizeof(result) == sizeof(Matrix3), "sizeof(result) == sizeof(Matrix3)");
 69.2204 +		memcpy(result.M, M, sizeof(M));
 69.2205 +		return result;
 69.2206 +	}
 69.2207 +
 69.2208 +	void ToString(char* dest, size_t destsize) const
 69.2209 +	{
 69.2210 +		size_t pos = 0;
 69.2211 +		for (int r=0; r<3; r++)
 69.2212 +			for (int c=0; c<3; c++)
 69.2213 +				pos += OVR_sprintf(dest+pos, destsize-pos, "%g ", M[r][c]);
 69.2214 +	}
 69.2215 +
 69.2216 +	static Matrix3 FromString(const char* src)
 69.2217 +	{
 69.2218 +		Matrix3 result;
 69.2219 +		for (int r=0; r<3; r++)
 69.2220 +			for (int c=0; c<3; c++)
 69.2221 +			{
 69.2222 +				result.M[r][c] = (T)atof(src);
 69.2223 +				while (src && *src != ' ')
 69.2224 +					src++;
 69.2225 +				while (src && *src == ' ')
 69.2226 +					src++;
 69.2227 +			}
 69.2228 +			return result;
 69.2229 +	}
 69.2230 +
 69.2231 +	static const Matrix3& Identity()  { return IdentityValue; }
 69.2232 +
 69.2233 +	void SetIdentity()
 69.2234 +	{
 69.2235 +		M[0][0] = M[1][1] = M[2][2] = 1;
 69.2236 +		M[0][1] = M[1][0] = M[2][0] = 0;
 69.2237 +		M[0][2] = M[1][2] = M[2][1] = 0;
 69.2238 +	}
 69.2239 +
 69.2240 +	bool operator== (const Matrix3& b) const
 69.2241 +	{
 69.2242 +		bool isEqual = true;
 69.2243 +		for (int i = 0; i < 3; i++)
 69.2244 +			for (int j = 0; j < 3; j++)
 69.2245 +				isEqual &= (M[i][j] == b.M[i][j]);
 69.2246 +
 69.2247 +		return isEqual;
 69.2248 +	}
 69.2249 +
 69.2250 +	Matrix3 operator+ (const Matrix3& b) const
 69.2251 +	{
 69.2252 +        Matrix4<T> result(*this);
 69.2253 +		result += b;
 69.2254 +		return result;
 69.2255 +	}
 69.2256 +
 69.2257 +	Matrix3& operator+= (const Matrix3& b)
 69.2258 +	{
 69.2259 +		for (int i = 0; i < 3; i++)
 69.2260 +			for (int j = 0; j < 3; j++)
 69.2261 +				M[i][j] += b.M[i][j];
 69.2262 +		return *this;
 69.2263 +	}
 69.2264 +
 69.2265 +	void operator= (const Matrix3& b)
 69.2266 +	{
 69.2267 +		for (int i = 0; i < 3; i++)
 69.2268 +			for (int j = 0; j < 3; j++)
 69.2269 +				M[i][j] = b.M[i][j];
 69.2270 +		return;
 69.2271 +	}
 69.2272 +
 69.2273 +	void operator= (const SymMat3<T>& b)
 69.2274 +	{
 69.2275 +		for (int i = 0; i < 3; i++)
 69.2276 +			for (int j = 0; j < 3; j++)
 69.2277 +				M[i][j] = 0;
 69.2278 +
 69.2279 +		M[0][0] = b.v[0];
 69.2280 +		M[0][1] = b.v[1];
 69.2281 +		M[0][2] = b.v[2];
 69.2282 +		M[1][1] = b.v[3];
 69.2283 +		M[1][2] = b.v[4];
 69.2284 +		M[2][2] = b.v[5];
 69.2285 +
 69.2286 +		return;
 69.2287 +	}
 69.2288 +
 69.2289 +	Matrix3 operator- (const Matrix3& b) const
 69.2290 +	{
 69.2291 +		Matrix3 result(*this);
 69.2292 +		result -= b;
 69.2293 +		return result;
 69.2294 +	}
 69.2295 +
 69.2296 +	Matrix3& operator-= (const Matrix3& b)
 69.2297 +	{
 69.2298 +		for (int i = 0; i < 3; i++)
 69.2299 +			for (int j = 0; j < 3; j++)
 69.2300 +				M[i][j] -= b.M[i][j];
 69.2301 +		return *this;
 69.2302 +	}
 69.2303 +
 69.2304 +	// Multiplies two matrices into destination with minimum copying.
 69.2305 +	static Matrix3& Multiply(Matrix3* d, const Matrix3& a, const Matrix3& b)
 69.2306 +	{
 69.2307 +		OVR_ASSERT((d != &a) && (d != &b));
 69.2308 +		int i = 0;
 69.2309 +		do {
 69.2310 +			d->M[i][0] = a.M[i][0] * b.M[0][0] + a.M[i][1] * b.M[1][0] + a.M[i][2] * b.M[2][0];
 69.2311 +			d->M[i][1] = a.M[i][0] * b.M[0][1] + a.M[i][1] * b.M[1][1] + a.M[i][2] * b.M[2][1];
 69.2312 +			d->M[i][2] = a.M[i][0] * b.M[0][2] + a.M[i][1] * b.M[1][2] + a.M[i][2] * b.M[2][2];
 69.2313 +		} while((++i) < 3);
 69.2314 +
 69.2315 +		return *d;
 69.2316 +	}
 69.2317 +
 69.2318 +	Matrix3 operator* (const Matrix3& b) const
 69.2319 +	{
 69.2320 +		Matrix3 result(Matrix3::NoInit);
 69.2321 +		Multiply(&result, *this, b);
 69.2322 +		return result;
 69.2323 +	}
 69.2324 +
 69.2325 +	Matrix3& operator*= (const Matrix3& b)
 69.2326 +	{
 69.2327 +		return Multiply(this, Matrix3(*this), b);
 69.2328 +	}
 69.2329 +
 69.2330 +	Matrix3 operator* (T s) const
 69.2331 +	{
 69.2332 +		Matrix3 result(*this);
 69.2333 +		result *= s;
 69.2334 +		return result;
 69.2335 +	}
 69.2336 +
 69.2337 +	Matrix3& operator*= (T s)
 69.2338 +	{
 69.2339 +		for (int i = 0; i < 3; i++)
 69.2340 +			for (int j = 0; j < 3; j++)
 69.2341 +				M[i][j] *= s;
 69.2342 +		return *this;
 69.2343 +	}
 69.2344 +
 69.2345 +	Vector3<T> operator* (const Vector3<T> &b) const
 69.2346 +	{
 69.2347 +		Vector3<T> result;
 69.2348 +		result.x = M[0][0]*b.x + M[0][1]*b.y + M[0][2]*b.z;
 69.2349 +		result.y = M[1][0]*b.x + M[1][1]*b.y + M[1][2]*b.z;
 69.2350 +		result.z = M[2][0]*b.x + M[2][1]*b.y + M[2][2]*b.z;
 69.2351 +
 69.2352 +		return result;
 69.2353 +	}
 69.2354 +
 69.2355 +	Matrix3 operator/ (T s) const
 69.2356 +	{
 69.2357 +		Matrix3 result(*this);
 69.2358 +		result /= s;
 69.2359 +		return result;
 69.2360 +	}
 69.2361 +
 69.2362 +	Matrix3& operator/= (T s)
 69.2363 +	{
 69.2364 +		for (int i = 0; i < 3; i++)
 69.2365 +			for (int j = 0; j < 3; j++)
 69.2366 +				M[i][j] /= s;
 69.2367 +		return *this;
 69.2368 +	}
 69.2369 +
 69.2370 +	Vector2<T> Transform(const Vector2<T>& v) const
 69.2371 +	{
 69.2372 +		const float rcpZ = 1.0f / (M[2][0] * v.x + M[2][1] * v.y + M[2][2]);
 69.2373 +		return Vector2<T>((M[0][0] * v.x + M[0][1] * v.y + M[0][2]) * rcpZ,
 69.2374 +						  (M[1][0] * v.x + M[1][1] * v.y + M[1][2]) * rcpZ);
 69.2375 +	}
 69.2376 +
 69.2377 +	Vector3<T> Transform(const Vector3<T>& v) const
 69.2378 +	{
 69.2379 +		return Vector3<T>(M[0][0] * v.x + M[0][1] * v.y + M[0][2] * v.z,
 69.2380 +						  M[1][0] * v.x + M[1][1] * v.y + M[1][2] * v.z,
 69.2381 +						  M[2][0] * v.x + M[2][1] * v.y + M[2][2] * v.z);
 69.2382 +	}
 69.2383 +
 69.2384 +	Matrix3 Transposed() const
 69.2385 +	{
 69.2386 +		return Matrix3(M[0][0], M[1][0], M[2][0],
 69.2387 +					   M[0][1], M[1][1], M[2][1],
 69.2388 +					   M[0][2], M[1][2], M[2][2]);
 69.2389 +	}
 69.2390 +
 69.2391 +	void     Transpose()
 69.2392 +	{
 69.2393 +		*this = Transposed();
 69.2394 +	}
 69.2395 +
 69.2396 +
 69.2397 +	T SubDet (const size_t* rows, const size_t* cols) const
 69.2398 +	{
 69.2399 +		return M[rows[0]][cols[0]] * (M[rows[1]][cols[1]] * M[rows[2]][cols[2]] - M[rows[1]][cols[2]] * M[rows[2]][cols[1]])
 69.2400 +			 - M[rows[0]][cols[1]] * (M[rows[1]][cols[0]] * M[rows[2]][cols[2]] - M[rows[1]][cols[2]] * M[rows[2]][cols[0]])
 69.2401 +			 + M[rows[0]][cols[2]] * (M[rows[1]][cols[0]] * M[rows[2]][cols[1]] - M[rows[1]][cols[1]] * M[rows[2]][cols[0]]);
 69.2402 +	}
 69.2403 +
 69.2404 +	// M += a*b.t()
 69.2405 +	inline void Rank1Add(const Vector3<T> &a, const Vector3<T> &b)
 69.2406 +	{
 69.2407 +		M[0][0] += a.x*b.x;		M[0][1] += a.x*b.y;		M[0][2] += a.x*b.z;
 69.2408 +		M[1][0] += a.y*b.x;		M[1][1] += a.y*b.y;		M[1][2] += a.y*b.z;
 69.2409 +		M[2][0] += a.z*b.x;		M[2][1] += a.z*b.y;		M[2][2] += a.z*b.z;
 69.2410 +	}
 69.2411 +
 69.2412 +	// M -= a*b.t()
 69.2413 +	inline void Rank1Sub(const Vector3<T> &a, const Vector3<T> &b)
 69.2414 +	{
 69.2415 +		M[0][0] -= a.x*b.x;		M[0][1] -= a.x*b.y;		M[0][2] -= a.x*b.z;
 69.2416 +		M[1][0] -= a.y*b.x;		M[1][1] -= a.y*b.y;		M[1][2] -= a.y*b.z;
 69.2417 +		M[2][0] -= a.z*b.x;		M[2][1] -= a.z*b.y;		M[2][2] -= a.z*b.z;
 69.2418 +	}
 69.2419 +
 69.2420 +	inline Vector3<T> Col(int c) const
 69.2421 +	{
 69.2422 +		return Vector3<T>(M[0][c], M[1][c], M[2][c]);
 69.2423 +	}
 69.2424 +
 69.2425 +	inline Vector3<T> Row(int r) const
 69.2426 +	{
 69.2427 +        return Vector3<T>(M[r][0], M[r][1], M[r][2]);
 69.2428 +	}
 69.2429 +
 69.2430 +	inline T Determinant() const
 69.2431 +	{
 69.2432 +		const Matrix3<T>& m = *this;
 69.2433 +		T d; 
 69.2434 +
 69.2435 +		d  = m.M[0][0] * (m.M[1][1]*m.M[2][2] - m.M[1][2] * m.M[2][1]);
 69.2436 +		d -= m.M[0][1] * (m.M[1][0]*m.M[2][2] - m.M[1][2] * m.M[2][0]);
 69.2437 +		d += m.M[0][2] * (m.M[1][0]*m.M[2][1] - m.M[1][1] * m.M[2][0]);
 69.2438 +
 69.2439 +		return d;
 69.2440 +	}
 69.2441 +	
 69.2442 +	inline Matrix3<T> Inverse() const
 69.2443 +    {
 69.2444 +        Matrix3<T> a;
 69.2445 +        const  Matrix3<T>& m = *this;
 69.2446 +        T d = Determinant();
 69.2447 +
 69.2448 +        assert(d != 0);
 69.2449 +        T s = T(1)/d;
 69.2450 +
 69.2451 +        a.M[0][0] = s * (m.M[1][1] * m.M[2][2] - m.M[1][2] * m.M[2][1]);   
 69.2452 +        a.M[1][0] = s * (m.M[1][2] * m.M[2][0] - m.M[1][0] * m.M[2][2]);   
 69.2453 +        a.M[2][0] = s * (m.M[1][0] * m.M[2][1] - m.M[1][1] * m.M[2][0]);   
 69.2454 +
 69.2455 +		a.M[0][1] = s * (m.M[0][2] * m.M[2][1] - m.M[0][1] * m.M[2][2]);   
 69.2456 +		a.M[1][1] = s * (m.M[0][0] * m.M[2][2] - m.M[0][2] * m.M[2][0]);   
 69.2457 +		a.M[2][1] = s * (m.M[0][1] * m.M[2][0] - m.M[0][0] * m.M[2][1]);   
 69.2458 +        
 69.2459 +		a.M[0][2] = s * (m.M[0][1] * m.M[1][2] - m.M[0][2] * m.M[1][1]);   
 69.2460 +		a.M[1][2] = s * (m.M[0][2] * m.M[1][0] - m.M[0][0] * m.M[1][2]);   
 69.2461 +		a.M[2][2] = s * (m.M[0][0] * m.M[1][1] - m.M[0][1] * m.M[1][0]);   
 69.2462 +        
 69.2463 +        return a;
 69.2464 +    }
 69.2465 +	
 69.2466 +};
 69.2467 +
 69.2468 +typedef Matrix3<float>  Matrix3f;
 69.2469 +typedef Matrix3<double> Matrix3d;
 69.2470 +
 69.2471 +//-------------------------------------------------------------------------------------
 69.2472 +
 69.2473 +template<typename T>
 69.2474 +class SymMat3
 69.2475 +{
 69.2476 +private:
 69.2477 +	typedef SymMat3<T> this_type;
 69.2478 +
 69.2479 +public:
 69.2480 +	typedef T Value_t;
 69.2481 +	// Upper symmetric
 69.2482 +	T v[6]; // _00 _01 _02 _11 _12 _22
 69.2483 +
 69.2484 +	inline SymMat3() {}
 69.2485 +
 69.2486 +	inline explicit SymMat3(T s)
 69.2487 +	{
 69.2488 +		v[0] = v[3] = v[5] = s;
 69.2489 +		v[1] = v[2] = v[4] = 0;
 69.2490 +	}
 69.2491 +
 69.2492 +	inline explicit SymMat3(T a00, T a01, T a02, T a11, T a12, T a22)
 69.2493 +	{
 69.2494 +		v[0] = a00; v[1] = a01; v[2] = a02;
 69.2495 +		v[3] = a11; v[4] = a12;
 69.2496 +		v[5] = a22;
 69.2497 +	}
 69.2498 +
 69.2499 +	static inline int Index(unsigned int i, unsigned int j)
 69.2500 +	{
 69.2501 +		return (i <= j) ? (3*i - i*(i+1)/2 + j) : (3*j - j*(j+1)/2 + i);
 69.2502 +	}
 69.2503 +
 69.2504 +	inline T operator()(int i, int j) const { return v[Index(i,j)]; }
 69.2505 +	
 69.2506 +	inline T &operator()(int i, int j) { return v[Index(i,j)]; }
 69.2507 +
 69.2508 +	template<typename U>
 69.2509 +	inline SymMat3<U> CastTo() const
 69.2510 +	{
 69.2511 +		return SymMat3<U>(static_cast<U>(v[0]), static_cast<U>(v[1]), static_cast<U>(v[2]),
 69.2512 +						  static_cast<U>(v[3]), static_cast<U>(v[4]), static_cast<U>(v[5]));
 69.2513 +	}
 69.2514 +
 69.2515 +	inline this_type& operator+=(const this_type& b)
 69.2516 +	{
 69.2517 +		v[0]+=b.v[0];
 69.2518 +		v[1]+=b.v[1];
 69.2519 +		v[2]+=b.v[2];
 69.2520 +		v[3]+=b.v[3];
 69.2521 +		v[4]+=b.v[4];
 69.2522 +		v[5]+=b.v[5];
 69.2523 +		return *this;
 69.2524 +	}
 69.2525 +
 69.2526 +	inline this_type& operator-=(const this_type& b)
 69.2527 +	{
 69.2528 +		v[0]-=b.v[0];
 69.2529 +		v[1]-=b.v[1];
 69.2530 +		v[2]-=b.v[2];
 69.2531 +		v[3]-=b.v[3];
 69.2532 +		v[4]-=b.v[4];
 69.2533 +		v[5]-=b.v[5];
 69.2534 +
 69.2535 +		return *this;
 69.2536 +	}
 69.2537 +
 69.2538 +	inline this_type& operator*=(T s)
 69.2539 +	{
 69.2540 +		v[0]*=s;
 69.2541 +		v[1]*=s;
 69.2542 +		v[2]*=s;
 69.2543 +		v[3]*=s;
 69.2544 +		v[4]*=s;
 69.2545 +		v[5]*=s;
 69.2546 +
 69.2547 +		return *this;
 69.2548 +	}
 69.2549 +		
 69.2550 +	inline SymMat3 operator*(T s) const
 69.2551 +	{
 69.2552 +		SymMat3 d;
 69.2553 +		d.v[0] = v[0]*s; 
 69.2554 +		d.v[1] = v[1]*s; 
 69.2555 +		d.v[2] = v[2]*s; 
 69.2556 +		d.v[3] = v[3]*s; 
 69.2557 +		d.v[4] = v[4]*s; 
 69.2558 +		d.v[5] = v[5]*s; 
 69.2559 +						
 69.2560 +		return d;
 69.2561 +	}
 69.2562 +
 69.2563 +	// Multiplies two matrices into destination with minimum copying.
 69.2564 +	static SymMat3& Multiply(SymMat3* d, const SymMat3& a, const SymMat3& b)
 69.2565 +	{		
 69.2566 +		// _00 _01 _02 _11 _12 _22
 69.2567 +
 69.2568 +		d->v[0] = a.v[0] * b.v[0];
 69.2569 +		d->v[1] = a.v[0] * b.v[1] + a.v[1] * b.v[3];
 69.2570 +		d->v[2] = a.v[0] * b.v[2] + a.v[1] * b.v[4];
 69.2571 +					
 69.2572 +		d->v[3] = a.v[3] * b.v[3];
 69.2573 +		d->v[4] = a.v[3] * b.v[4] + a.v[4] * b.v[5];
 69.2574 +				
 69.2575 +		d->v[5] = a.v[5] * b.v[5];
 69.2576 +	
 69.2577 +		return *d;
 69.2578 +	}
 69.2579 +	
 69.2580 +	inline T Determinant() const
 69.2581 +	{
 69.2582 +		const this_type& m = *this;
 69.2583 +		T d; 
 69.2584 +
 69.2585 +		d  = m(0,0) * (m(1,1)*m(2,2) - m(1,2) * m(2,1));
 69.2586 +		d -= m(0,1) * (m(1,0)*m(2,2) - m(1,2) * m(2,0));
 69.2587 +		d += m(0,2) * (m(1,0)*m(2,1) - m(1,1) * m(2,0));
 69.2588 +
 69.2589 +		return d;
 69.2590 +	}
 69.2591 +
 69.2592 +	inline this_type Inverse() const
 69.2593 +	{
 69.2594 +		this_type a;
 69.2595 +		const this_type& m = *this;
 69.2596 +		T d = Determinant();
 69.2597 +
 69.2598 +		assert(d != 0);
 69.2599 +		T s = T(1)/d;
 69.2600 +
 69.2601 +		a(0,0) = s * (m(1,1) * m(2,2) - m(1,2) * m(2,1));   
 69.2602 +
 69.2603 +		a(0,1) = s * (m(0,2) * m(2,1) - m(0,1) * m(2,2));   
 69.2604 +		a(1,1) = s * (m(0,0) * m(2,2) - m(0,2) * m(2,0));   
 69.2605 +
 69.2606 +		a(0,2) = s * (m(0,1) * m(1,2) - m(0,2) * m(1,1));   
 69.2607 +		a(1,2) = s * (m(0,2) * m(1,0) - m(0,0) * m(1,2));   
 69.2608 +		a(2,2) = s * (m(0,0) * m(1,1) - m(0,1) * m(1,0));   
 69.2609 +
 69.2610 +		return a;
 69.2611 +	}
 69.2612 +
 69.2613 +	inline T Trace() const { return v[0] + v[3] + v[5]; }
 69.2614 +
 69.2615 +	// M = a*a.t()
 69.2616 +	inline void Rank1(const Vector3<T> &a)
 69.2617 +	{
 69.2618 +		v[0] = a.x*a.x; v[1] = a.x*a.y; v[2] = a.x*a.z;
 69.2619 +		v[3] = a.y*a.y; v[4] = a.y*a.z;
 69.2620 +		v[5] = a.z*a.z;
 69.2621 +	}
 69.2622 +
 69.2623 +	// M += a*a.t()
 69.2624 +	inline void Rank1Add(const Vector3<T> &a)
 69.2625 +	{
 69.2626 +		v[0] += a.x*a.x; v[1] += a.x*a.y; v[2] += a.x*a.z;
 69.2627 +		v[3] += a.y*a.y; v[4] += a.y*a.z;
 69.2628 +		v[5] += a.z*a.z;
 69.2629 +	}
 69.2630 +
 69.2631 +	// M -= a*a.t()
 69.2632 +	inline void Rank1Sub(const Vector3<T> &a)
 69.2633 +	{
 69.2634 +		v[0] -= a.x*a.x; v[1] -= a.x*a.y; v[2] -= a.x*a.z;
 69.2635 +		v[3] -= a.y*a.y; v[4] -= a.y*a.z;
 69.2636 +		v[5] -= a.z*a.z;
 69.2637 +	}
 69.2638 +};
 69.2639 +
 69.2640 +typedef SymMat3<float>  SymMat3f;
 69.2641 +typedef SymMat3<double> SymMat3d;
 69.2642 +
 69.2643 +template<typename T>
 69.2644 +inline Matrix3<T> operator*(const SymMat3<T>& a, const SymMat3<T>& b)
 69.2645 +{
 69.2646 +	#define AJB_ARBC(r,c) (a(r,0)*b(0,c)+a(r,1)*b(1,c)+a(r,2)*b(2,c))
 69.2647 +    return Matrix3<T>(
 69.2648 +		AJB_ARBC(0,0), AJB_ARBC(0,1), AJB_ARBC(0,2),
 69.2649 +		AJB_ARBC(1,0), AJB_ARBC(1,1), AJB_ARBC(1,2),
 69.2650 +		AJB_ARBC(2,0), AJB_ARBC(2,1), AJB_ARBC(2,2));
 69.2651 +	#undef AJB_ARBC
 69.2652 +}
 69.2653 +
 69.2654 +template<typename T>
 69.2655 +inline Matrix3<T> operator*(const Matrix3<T>& a, const SymMat3<T>& b)
 69.2656 +{
 69.2657 +	#define AJB_ARBC(r,c) (a(r,0)*b(0,c)+a(r,1)*b(1,c)+a(r,2)*b(2,c))
 69.2658 +	return Matrix3<T>(
 69.2659 +		AJB_ARBC(0,0), AJB_ARBC(0,1), AJB_ARBC(0,2),
 69.2660 +		AJB_ARBC(1,0), AJB_ARBC(1,1), AJB_ARBC(1,2),
 69.2661 +		AJB_ARBC(2,0), AJB_ARBC(2,1), AJB_ARBC(2,2));
 69.2662 +	#undef AJB_ARBC
 69.2663 +}
 69.2664 +
 69.2665 +//-------------------------------------------------------------------------------------
 69.2666 +// ***** Angle
 69.2667 +
 69.2668 +// Cleanly representing the algebra of 2D rotations.
 69.2669 +// The operations maintain the angle between -Pi and Pi, the same range as atan2.
 69.2670 +
 69.2671 +template<class T>
 69.2672 +class Angle
 69.2673 +{
 69.2674 +public:
 69.2675 +	enum AngularUnits
 69.2676 +	{
 69.2677 +		Radians = 0,
 69.2678 +		Degrees = 1
 69.2679 +	};
 69.2680 +
 69.2681 +    Angle() : a(0) {}
 69.2682 +    
 69.2683 +	// Fix the range to be between -Pi and Pi
 69.2684 +	Angle(T a_, AngularUnits u = Radians) : a((u == Radians) ? a_ : a_*((T)MATH_DOUBLE_DEGREETORADFACTOR)) { FixRange(); }
 69.2685 +
 69.2686 +	T    Get(AngularUnits u = Radians) const       { return (u == Radians) ? a : a*((T)MATH_DOUBLE_RADTODEGREEFACTOR); }
 69.2687 +	void Set(const T& x, AngularUnits u = Radians) { a = (u == Radians) ? x : x*((T)MATH_DOUBLE_DEGREETORADFACTOR); FixRange(); }
 69.2688 +	int Sign() const                               { if (a == 0) return 0; else return (a > 0) ? 1 : -1; }
 69.2689 +	T   Abs() const                                { return (a > 0) ? a : -a; }
 69.2690 +
 69.2691 +    bool operator== (const Angle& b) const    { return a == b.a; }
 69.2692 +    bool operator!= (const Angle& b) const    { return a != b.a; }
 69.2693 +//	bool operator<  (const Angle& b) const    { return a < a.b; } 
 69.2694 +//	bool operator>  (const Angle& b) const    { return a > a.b; } 
 69.2695 +//	bool operator<= (const Angle& b) const    { return a <= a.b; } 
 69.2696 +//	bool operator>= (const Angle& b) const    { return a >= a.b; } 
 69.2697 +//	bool operator= (const T& x)               { a = x; FixRange(); }
 69.2698 +
 69.2699 +	// These operations assume a is already between -Pi and Pi.
 69.2700 +	Angle& operator+= (const Angle& b)        { a = a + b.a; FastFixRange(); return *this; }
 69.2701 +	Angle& operator+= (const T& x)            { a = a + x; FixRange(); return *this; }
 69.2702 +    Angle  operator+  (const Angle& b) const  { Angle res = *this; res += b; return res; }
 69.2703 +	Angle  operator+  (const T& x) const      { Angle res = *this; res += x; return res; }
 69.2704 +	Angle& operator-= (const Angle& b)        { a = a - b.a; FastFixRange(); return *this; }
 69.2705 +	Angle& operator-= (const T& x)            { a = a - x; FixRange(); return *this; }
 69.2706 +	Angle  operator-  (const Angle& b) const  { Angle res = *this; res -= b; return res; }
 69.2707 +	Angle  operator-  (const T& x) const      { Angle res = *this; res -= x; return res; }
 69.2708 +	
 69.2709 +	T   Distance(const Angle& b)              { T c = fabs(a - b.a); return (c <= ((T)MATH_DOUBLE_PI)) ? c : ((T)MATH_DOUBLE_TWOPI) - c; }
 69.2710 +
 69.2711 +private:
 69.2712 +
 69.2713 +	// The stored angle, which should be maintained between -Pi and Pi
 69.2714 +	T a;
 69.2715 +
 69.2716 +	// Fixes the angle range to [-Pi,Pi], but assumes no more than 2Pi away on either side 
 69.2717 +	inline void FastFixRange()
 69.2718 +	{
 69.2719 +		if (a < -((T)MATH_DOUBLE_PI))
 69.2720 +			a += ((T)MATH_DOUBLE_TWOPI);
 69.2721 +		else if (a > ((T)MATH_DOUBLE_PI))
 69.2722 +			a -= ((T)MATH_DOUBLE_TWOPI);
 69.2723 +	}
 69.2724 +
 69.2725 +	// Fixes the angle range to [-Pi,Pi] for any given range, but slower then the fast method
 69.2726 +	inline void FixRange()
 69.2727 +	{
 69.2728 +        // do nothing if the value is already in the correct range, since fmod call is expensive
 69.2729 +        if (a >= -((T)MATH_DOUBLE_PI) && a <= ((T)MATH_DOUBLE_PI))
 69.2730 +            return;
 69.2731 +		a = fmod(a,((T)MATH_DOUBLE_TWOPI));
 69.2732 +		if (a < -((T)MATH_DOUBLE_PI))
 69.2733 +			a += ((T)MATH_DOUBLE_TWOPI);
 69.2734 +		else if (a > ((T)MATH_DOUBLE_PI))
 69.2735 +			a -= ((T)MATH_DOUBLE_TWOPI);
 69.2736 +	}
 69.2737 +};
 69.2738 +
 69.2739 +
 69.2740 +typedef Angle<float>  Anglef;
 69.2741 +typedef Angle<double> Angled;
 69.2742 +
 69.2743 +
 69.2744 +//-------------------------------------------------------------------------------------
 69.2745 +// ***** Plane
 69.2746 +
 69.2747 +// Consists of a normal vector and distance from the origin where the plane is located.
 69.2748 +
 69.2749 +template<class T>
 69.2750 +class Plane
 69.2751 +{
 69.2752 +public:
 69.2753 +    Vector3<T> N;
 69.2754 +    T          D;
 69.2755 +
 69.2756 +    Plane() : D(0) {}
 69.2757 +
 69.2758 +    // Normals must already be normalized
 69.2759 +    Plane(const Vector3<T>& n, T d) : N(n), D(d) {}
 69.2760 +    Plane(T x, T y, T z, T d) : N(x,y,z), D(d) {}
 69.2761 +
 69.2762 +    // construct from a point on the plane and the normal
 69.2763 +    Plane(const Vector3<T>& p, const Vector3<T>& n) : N(n), D(-(p * n)) {}
 69.2764 +
 69.2765 +    // Find the point to plane distance. The sign indicates what side of the plane the point is on (0 = point on plane).
 69.2766 +    T TestSide(const Vector3<T>& p) const
 69.2767 +    {
 69.2768 +        return (N.Dot(p)) + D;
 69.2769 +    }
 69.2770 +
 69.2771 +    Plane<T> Flipped() const
 69.2772 +    {
 69.2773 +        return Plane(-N, -D);
 69.2774 +    }
 69.2775 +
 69.2776 +    void Flip()
 69.2777 +    {
 69.2778 +        N = -N;
 69.2779 +        D = -D;
 69.2780 +    }
 69.2781 +
 69.2782 +	bool operator==(const Plane<T>& rhs) const
 69.2783 +	{
 69.2784 +		return (this->D == rhs.D && this->N == rhs.N);
 69.2785 +	}
 69.2786 +};
 69.2787 +
 69.2788 +typedef Plane<float> Planef;
 69.2789 +typedef Plane<double> Planed;
 69.2790 +
 69.2791 +
 69.2792 +} // Namespace OVR
 69.2793 +
 69.2794 +#endif
    70.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    70.2 +++ b/LibOVR/Src/Kernel/OVR_Nullptr.h	Wed Jan 14 06:51:16 2015 +0200
    70.3 @@ -0,0 +1,150 @@
    70.4 +/************************************************************************************
    70.5 +
    70.6 +PublicHeader:   OVR_Kernel.h
    70.7 +Filename    :   OVR_Nullptr.h
    70.8 +Content     :   Implements C++11 nullptr for the case that the compiler doesn't.
    70.9 +Created     :   June 19, 2014
   70.10 +Notes       : 
   70.11 +
   70.12 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   70.13 +
   70.14 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
   70.15 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
   70.16 +which is provided at the time of installation or download, or which 
   70.17 +otherwise accompanies this software in either electronic or hard copy form.
   70.18 +
   70.19 +You may obtain a copy of the License at
   70.20 +
   70.21 +http://www.oculusvr.com/licenses/LICENSE-3.2 
   70.22 +
   70.23 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
   70.24 +distributed under the License is distributed on an "AS IS" BASIS,
   70.25 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   70.26 +See the License for the specific language governing permissions and
   70.27 +limitations under the License.
   70.28 +
   70.29 +************************************************************************************/
   70.30 +
   70.31 +#ifndef OVR_Nullptr_h
   70.32 +#define OVR_Nullptr_h
   70.33 +
   70.34 +#pragma once
   70.35 +
   70.36 +#include "OVR_Types.h"
   70.37 +
   70.38 +
   70.39 +//-----------------------------------------------------------------------------------
   70.40 +// ***** OVR_HAVE_std_nullptr_t
   70.41 +//
   70.42 +// Identifies if <cstddef.h> includes std::nullptr_t. 
   70.43 +//
   70.44 +#if !defined(OVR_HAVE_std_nullptr_t) && defined(OVR_CPP11_ENABLED)
   70.45 +    #if defined(OVR_STDLIB_LIBCPP)
   70.46 +        #define OVR_HAVE_std_nullptr_t 1
   70.47 +    #elif defined(OVR_STDLIB_LIBSTDCPP)
   70.48 +        #if (__GLIBCXX__ >= 20110325) && (__GLIBCXX__ != 20110428) && (__GLIBCXX__ != 20120702)
   70.49 +            #define OVR_HAVE_std_nullptr_t 1
   70.50 +        #endif
   70.51 +    #elif defined(_MSC_VER) && (_MSC_VER >= 1600) // VS2010+
   70.52 +        #define OVR_HAVE_std_nullptr_t 1
   70.53 +    #elif defined(__clang__)
   70.54 +        #define OVR_HAVE_std_nullptr_t 1
   70.55 +    #elif defined(OVR_CPP_GNUC) && (OVR_CC_VERSION >= 406) // GCC 4.6+
   70.56 +        #define OVR_HAVE_std_nullptr_t 1
   70.57 +    #endif
   70.58 +#endif
   70.59 +
   70.60 +
   70.61 +//-----------------------------------------------------------------------------------
   70.62 +// ***** nullptr / std::nullptr_t
   70.63 +//
   70.64 +// Declares and defines nullptr and related types.
   70.65 +//
   70.66 +#if defined(OVR_CPP_NO_NULLPTR)
   70.67 +    namespace std
   70.68 +    {
   70.69 +        class nullptr_t
   70.70 +        {
   70.71 +        public:
   70.72 +            template <typename T>
   70.73 +            operator T*() const
   70.74 +                { return 0; }
   70.75 +         
   70.76 +            template <typename C, typename T>
   70.77 +            operator T C::*() const
   70.78 +                { return 0; }
   70.79 +
   70.80 +            #if OVR_CPP_NO_EXPLICIT_CONVERSION_OPERATORS
   70.81 +                typedef void* (nullptr_t::*bool_)() const;  // 4.12,p1. We can't portably use operator bool(){ return false; } because bool 
   70.82 +                operator bool_() const                      // is convertable to int which breaks other required functionality.
   70.83 +                    { return false; }
   70.84 +            #else
   70.85 +                operator bool() const
   70.86 +                    { return false; }
   70.87 +            #endif
   70.88 +
   70.89 +        private:
   70.90 +            void operator&() const; // 5.2.10,p9
   70.91 +        };
   70.92 +
   70.93 +        inline nullptr_t nullptr_get()
   70.94 +        {
   70.95 +            nullptr_t n = { };
   70.96 +            return n;
   70.97 +        }
   70.98 +
   70.99 +        #if !defined(nullptr)
  70.100 +            #define nullptr nullptr_get()
  70.101 +        #endif
  70.102 +
  70.103 +    } // namespace std
  70.104 +
  70.105 +
  70.106 +    // 5.9,p2 p4
  70.107 +    // 13.6, p13
  70.108 +    template <typename T>
  70.109 +    inline bool operator==(T* pT, const std::nullptr_t)
  70.110 +        { return pT == 0; }
  70.111 +
  70.112 +    template <typename T>
  70.113 +    inline bool operator==(const std::nullptr_t, T* pT)
  70.114 +        { return pT == 0; }
  70.115 +
  70.116 +    template <typename T, typename U>
  70.117 +    inline bool operator==(const std::nullptr_t, T U::* pU)
  70.118 +        { return pU == 0; }
  70.119 +
  70.120 +    template <typename T, typename U>
  70.121 +    inline bool operator==(T U::* pTU, const std::nullptr_t)
  70.122 +        { return pTU == 0; }
  70.123 +
  70.124 +    inline bool operator==(const std::nullptr_t, const std::nullptr_t)
  70.125 +        { return true; }
  70.126 +
  70.127 +    inline bool operator!=(const std::nullptr_t, const std::nullptr_t)
  70.128 +        { return false; }
  70.129 +
  70.130 +    inline bool operator<(const std::nullptr_t, const std::nullptr_t)
  70.131 +        { return false; }
  70.132 +
  70.133 +    inline bool operator<=(const std::nullptr_t, const std::nullptr_t)
  70.134 +        { return true; }
  70.135 +
  70.136 +    inline bool operator>(const std::nullptr_t, const std::nullptr_t)
  70.137 +        { return false; }
  70.138 +
  70.139 +    inline bool operator>=(const std::nullptr_t, const std::nullptr_t)
  70.140 +        { return true; }
  70.141 +
  70.142 +    using std::nullptr_t;
  70.143 +    using std::nullptr_get;
  70.144 +
  70.145 +// Some compilers natively support C++11 nullptr but the standard library being used 
  70.146 +// doesn't declare std::nullptr_t, in which case we provide one ourselves.
  70.147 +#elif !defined(OVR_HAVE_std_nullptr_t) && !defined(OVR_CPP_NO_DECLTYPE)
  70.148 +    namespace std { typedef decltype(nullptr) nullptr_t; }
  70.149 +#endif
  70.150 +
  70.151 +
  70.152 +#endif
  70.153 +
    71.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    71.2 +++ b/LibOVR/Src/Kernel/OVR_Observer.h	Wed Jan 14 06:51:16 2015 +0200
    71.3 @@ -0,0 +1,457 @@
    71.4 +/************************************************************************************
    71.5 +
    71.6 +PublicHeader:   Kernel
    71.7 +Filename    :   OVR_Observer.h
    71.8 +Content     :   Observer pattern
    71.9 +Created     :   June 20, 2014
   71.10 +Author      :   Chris Taylor
   71.11 +
   71.12 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   71.13 +
   71.14 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
   71.15 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
   71.16 +which is provided at the time of installation or download, or which 
   71.17 +otherwise accompanies this software in either electronic or hard copy form.
   71.18 +
   71.19 +You may obtain a copy of the License at
   71.20 +
   71.21 +http://www.oculusvr.com/licenses/LICENSE-3.2 
   71.22 +
   71.23 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
   71.24 +distributed under the License is distributed on an "AS IS" BASIS,
   71.25 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   71.26 +See the License for the specific language governing permissions and
   71.27 +limitations under the License.
   71.28 +
   71.29 +************************************************************************************/
   71.30 +
   71.31 +#ifndef OVR_Observer_h
   71.32 +#define OVR_Observer_h
   71.33 +
   71.34 +#include "OVR_Types.h"
   71.35 +#include "OVR_Atomic.h"
   71.36 +#include "OVR_RefCount.h"
   71.37 +#include "OVR_Delegates.h"
   71.38 +#include "OVR_Array.h"
   71.39 +#include "OVR_String.h"
   71.40 +#include "OVR_Hash.h"
   71.41 +
   71.42 +namespace OVR {
   71.43 +
   71.44 +template<class DelegateT> class Observer;
   71.45 +template<class DelegateT> class ObserverScope;
   71.46 +template<class DelegateT> class ObserverHash;
   71.47 +
   71.48 +
   71.49 +//-----------------------------------------------------------------------------
   71.50 +// Observer pattern
   71.51 +
   71.52 +// An Observer will observe a Subject.  The Subject can emit callbacks that get
   71.53 +// serviced by the Observers.
   71.54 +
   71.55 +// The trickiest part of this is the shutdown code.
   71.56 +// To simplify shutdown, the Observer is a reference-counted object divorced
   71.57 +// from the handler that is called.  To avoid misuse, the ObserverScope object
   71.58 +// is provided to ensure that the Shutdown() method is called when it goes out
   71.59 +// of scope.
   71.60 +
   71.61 +// The Observer<> class doubles as the subject class.
   71.62 +// To avoid misuse, assertions are added if a subject tries to observe, or if
   71.63 +// an observer tries to be watched.
   71.64 +
   71.65 +/*
   71.66 +    Usage example:
   71.67 +
   71.68 +    Say we want to invoke a handler with the signature:
   71.69 +
   71.70 +        void MyHandler(int i, bool b);
   71.71 +
   71.72 +    The corresponding delegate type is:
   71.73 +
   71.74 +        typedef Delegate2<void, int, bool> Handler;
   71.75 +
   71.76 +    Note: The return value will be ignored for the Observer pattern.
   71.77 +
   71.78 +    For this example there are two classes, one that emits events and another
   71.79 +    that listens for events:
   71.80 +*/
   71.81 +
   71.82 +/*
   71.83 +    Event emitter example:
   71.84 +
   71.85 +    class MyEmitter
   71.86 +    {
   71.87 +        ObserverScope<Handler> TheSubject;
   71.88 +
   71.89 +    public:
   71.90 +        void ClearAllListeners()
   71.91 +        {
   71.92 +            TheSubject.ReleaseAll();
   71.93 +        }
   71.94 +
   71.95 +        void CallListeners(int x, bool y)
   71.96 +        {
   71.97 +            TheSubject->Call(x, y);
   71.98 +        }
   71.99 +
  71.100 +        Observer<Handler>* GetSubject()
  71.101 +        {
  71.102 +            return TheSubject;
  71.103 +        }
  71.104 +    };
  71.105 +*/
  71.106 +
  71.107 +/*
  71.108 +    Event listener example:
  71.109 +
  71.110 +    class MyListener
  71.111 +    {
  71.112 +        ObserverScope<Handler> TheObserver;
  71.113 +
  71.114 +        void OnEvent(int x, bool y)
  71.115 +        {
  71.116 +            // Handle event here
  71.117 +        }
  71.118 +
  71.119 +    public:
  71.120 +        MyListener()
  71.121 +        {
  71.122 +            TheObserver.SetHandler(
  71.123 +                Handler::FromMember<MyListener, &MyListener::OnEvent>(this)
  71.124 +                );
  71.125 +        }
  71.126 +
  71.127 +        void ClearListener()
  71.128 +        {
  71.129 +            TheObserver.ReleaseAll();
  71.130 +        }
  71.131 +
  71.132 +        void ListenTo(Observer<Handler>* emitter)
  71.133 +        {
  71.134 +            TheObserver->Observe(emitter);
  71.135 +        }
  71.136 +    };
  71.137 +*/
  71.138 +
  71.139 +/*
  71.140 +    Usage example:
  71.141 +
  71.142 +    MyListener listener;
  71.143 +    MyEmitter emitter;
  71.144 +
  71.145 +    // To listen to an emitter,
  71.146 +    listener.ListenTo(emitter.GetSubject());
  71.147 +
  71.148 +    // To call the listeners,
  71.149 +    emitter.CallListeners(22, true);
  71.150 +*/
  71.151 +
  71.152 +template<class DelegateT>
  71.153 +class Observer : public RefCountBase< Observer<DelegateT> >
  71.154 +{
  71.155 +	friend class ObserverScope<DelegateT>;
  71.156 +	friend class ObserverHash<DelegateT>;
  71.157 +
  71.158 +public:
  71.159 +    typedef Observer<DelegateT> ThisType;
  71.160 +    typedef DelegateT Handler;
  71.161 +
  71.162 +protected:
  71.163 +	bool                     IsShutdown; // Flag to indicate that the object went out of scope
  71.164 +	mutable Lock             TheLock;    // Lock to synchronize calls and shutdown
  71.165 +	Array< Ptr< ThisType > > References; // List of observed or observing objects
  71.166 +	Handler                  TheHandler; // Observer-only: Handler for callbacks
  71.167 +
  71.168 +	Observer() :
  71.169 +		IsShutdown(false)
  71.170 +	{
  71.171 +		TheHandler.Invalidate();
  71.172 +	}
  71.173 +	Observer(Handler handler) :
  71.174 +		IsShutdown(false),
  71.175 +		TheHandler(handler)
  71.176 +	{
  71.177 +	}
  71.178 +	~Observer()
  71.179 +	{
  71.180 +		OVR_ASSERT(References.GetSizeI() == 0);
  71.181 +	}
  71.182 +
  71.183 +public:
  71.184 +	void SetHandler(Handler handler)
  71.185 +	{
  71.186 +		OVR_ASSERT(References.GetSizeI() == 0);
  71.187 +		TheHandler = handler;
  71.188 +	}
  71.189 +
  71.190 +	// Release references and prevent further actions
  71.191 +	void Shutdown()
  71.192 +	{
  71.193 +		Lock::Locker locker(&TheLock);
  71.194 +		IsShutdown = true;
  71.195 +		References.ClearAndRelease();
  71.196 +	}
  71.197 +
  71.198 +	// Get count of references held
  71.199 +	int GetSizeI() const
  71.200 +	{
  71.201 +		Lock::Locker locker(&TheLock);
  71.202 +		return References.GetSizeI();
  71.203 +	}
  71.204 +
  71.205 +	// Observe a subject
  71.206 +	bool Observe(ThisType *subject)
  71.207 +	{
  71.208 +		OVR_ASSERT(TheHandler.IsValid());
  71.209 +
  71.210 +		if (!subject)
  71.211 +		{
  71.212 +			return false;
  71.213 +		}
  71.214 +
  71.215 +		Lock::Locker locker(&TheLock);
  71.216 +
  71.217 +		if (IsShutdown)
  71.218 +		{
  71.219 +			return false;
  71.220 +		}
  71.221 +
  71.222 +		if (!subject->SubjectAddObserver(this))
  71.223 +		{
  71.224 +			return false;
  71.225 +		}
  71.226 +
  71.227 +		References.PushBack(subject);
  71.228 +		return true;
  71.229 +	}
  71.230 +
  71.231 +protected:
  71.232 +	// Subject function: AddObserver()
  71.233 +	// Returns true if the observer was added
  71.234 +	bool SubjectAddObserver(ThisType* observer)
  71.235 +	{
  71.236 +		OVR_ASSERT(!TheHandler.IsValid());
  71.237 +
  71.238 +		if (!observer)
  71.239 +		{
  71.240 +			return true;
  71.241 +		}
  71.242 +
  71.243 +		Lock::Locker locker(&TheLock);
  71.244 +
  71.245 +		if (IsShutdown)
  71.246 +		{
  71.247 +			return false;
  71.248 +		}
  71.249 +
  71.250 +		const int count = References.GetSizeI();
  71.251 +		for (int i = 0; i < count; ++i)
  71.252 +		{
  71.253 +			if (References[i] == observer)
  71.254 +			{
  71.255 +				// Already watched
  71.256 +				return true;
  71.257 +			}
  71.258 +		}
  71.259 +
  71.260 +		References.PushBack(observer);
  71.261 +
  71.262 +		return true;
  71.263 +	}
  71.264 +
  71.265 +public:
  71.266 +    // Subject function: Call()
  71.267 +#define OVR_OBSERVER_CALL_BODY(params) \
  71.268 +    bool callSuccess = false; \
  71.269 +	Lock::Locker locker(&TheLock); \
  71.270 +	int count = References.GetSizeI(); \
  71.271 +	for (int i = 0; i < count; ++i) \
  71.272 +	{ \
  71.273 +		if (!References[i]->IsShutdown) \
  71.274 +		{ \
  71.275 +			OVR_ASSERT(References[i]->TheHandler.IsValid()); \
  71.276 +			References[i]->TheHandler params; \
  71.277 +            callSuccess = true; \
  71.278 +		} \
  71.279 +		if (References[i]->IsShutdown) \
  71.280 +		{ \
  71.281 +			References.RemoveAt(i); \
  71.282 +			--i; --count; \
  71.283 +		} \
  71.284 +	} \
  71.285 +    return callSuccess;
  71.286 +
  71.287 +	// Call: Various parameter counts
  71.288 +    // Returns true if a call was made
  71.289 +	bool Call()
  71.290 +	{
  71.291 +		OVR_OBSERVER_CALL_BODY(())
  71.292 +	}
  71.293 +	template<class Param1>
  71.294 +    bool Call(Param1& p1)
  71.295 +	{
  71.296 +		OVR_OBSERVER_CALL_BODY((p1))
  71.297 +	}
  71.298 +	template<class Param1>
  71.299 +    bool Call(Param1* p1)
  71.300 +	{
  71.301 +		OVR_OBSERVER_CALL_BODY((p1))
  71.302 +	}
  71.303 +	template<class Param1, class Param2>
  71.304 +    bool Call(Param1& p1, Param2& p2)
  71.305 +	{
  71.306 +		OVR_OBSERVER_CALL_BODY((p1, p2))
  71.307 +	}
  71.308 +	template<class Param1, class Param2>
  71.309 +    bool Call(Param1* p1, Param2* p2)
  71.310 +	{
  71.311 +		OVR_OBSERVER_CALL_BODY((p1, p2))
  71.312 +	}
  71.313 +	template<class Param1, class Param2, class Param3>
  71.314 +    bool Call(Param1& p1, Param2& p2, Param3& p3)
  71.315 +	{
  71.316 +		OVR_OBSERVER_CALL_BODY((p1, p2, p3))
  71.317 +	}
  71.318 +	template<class Param1, class Param2, class Param3>
  71.319 +    bool Call(Param1* p1, Param2* p2, Param3* p3)
  71.320 +	{
  71.321 +		OVR_OBSERVER_CALL_BODY((p1, p2, p3))
  71.322 +	}
  71.323 +
  71.324 +#undef OVR_OBSERVER_CALL_BODY
  71.325 +};
  71.326 +
  71.327 +
  71.328 +//-----------------------------------------------------------------------------
  71.329 +// ObserverScope
  71.330 +
  71.331 +// Scoped shutdown of the Observer object
  71.332 +template<class DelegateT>
  71.333 +class ObserverScope : public NewOverrideBase
  71.334 +{
  71.335 +	Ptr< Observer<DelegateT> > TheObserver;
  71.336 +	DelegateT TheHandler;
  71.337 +
  71.338 +	void Shutdown()
  71.339 +	{
  71.340 +		if (TheObserver)
  71.341 +		{
  71.342 +			TheObserver->Shutdown();
  71.343 +			TheObserver.Clear();
  71.344 +		}
  71.345 +	}
  71.346 +
  71.347 +public:
  71.348 +	ObserverScope()
  71.349 +	{
  71.350 +		TheObserver = *new Observer<DelegateT>;
  71.351 +	}
  71.352 +	~ObserverScope()
  71.353 +	{
  71.354 +		Shutdown();
  71.355 +	}
  71.356 +
  71.357 +	// Release all references and recreate it
  71.358 +	void ReleaseAll()
  71.359 +	{
  71.360 +		Shutdown();
  71.361 +		TheObserver = *new Observer<DelegateT>;
  71.362 +		if (TheHandler.IsValid())
  71.363 +		{
  71.364 +			TheObserver->SetHandler(TheHandler);
  71.365 +		}
  71.366 +	}
  71.367 +
  71.368 +	void SetHandler(DelegateT handler)
  71.369 +	{
  71.370 +		TheHandler = handler;
  71.371 +		TheObserver->SetHandler(handler);
  71.372 +	}
  71.373 +
  71.374 +	Observer<DelegateT>* GetPtr()
  71.375 +	{
  71.376 +		return TheObserver.GetPtr();
  71.377 +	}
  71.378 +	Observer<DelegateT>* operator->()
  71.379 +	{
  71.380 +		return TheObserver.GetPtr();
  71.381 +	}
  71.382 +	const Observer<DelegateT>* operator->() const
  71.383 +	{
  71.384 +		return TheObserver.GetPtr();
  71.385 +	}
  71.386 +	operator Observer<DelegateT>*()
  71.387 +	{
  71.388 +		return TheObserver.GetPtr();
  71.389 +	}
  71.390 +};
  71.391 +
  71.392 +
  71.393 +//-----------------------------------------------------------------------------
  71.394 +// ObserverHash
  71.395 +
  71.396 +// A hash containing Observers
  71.397 +template<class DelegateT>
  71.398 +class ObserverHash : public NewOverrideBase
  71.399 +{
  71.400 +public:
  71.401 +	ObserverHash() {}
  71.402 +	~ObserverHash() {Clear();}
  71.403 +	void Clear()
  71.404 +	{
  71.405 +		Lock::Locker locker(&TheLock);
  71.406 +		typename OVR::Hash< String, Ptr<Observer<DelegateT> >, OVR::String::HashFunctor >::Iterator it = _Hash.Begin();
  71.407 +		for( it = _Hash.Begin(); it != _Hash.End(); ++it )
  71.408 +		{
  71.409 +			Ptr<Observer<DelegateT> > o = it->Second;
  71.410 +			o->Shutdown();
  71.411 +		}
  71.412 +	}
  71.413 +
  71.414 +	Ptr<Observer<DelegateT> > GetSubject(OVR::String key)
  71.415 +	{
  71.416 +		Lock::Locker locker(&TheLock);
  71.417 +		Ptr<Observer<DelegateT> > *o = _Hash.Get(key);
  71.418 +		if (o)
  71.419 +			return (*o);
  71.420 +		return NULL;
  71.421 +	}
  71.422 +
  71.423 +	// Add handler to new observer with implicit creation of subject.
  71.424 +	void AddObserverToSubject(OVR::String key, Observer<DelegateT> *observer)
  71.425 +	{
  71.426 +		Lock::Locker locker(&TheLock);
  71.427 +		Ptr<Observer<DelegateT> > *subjectPtr = _Hash.Get(key);
  71.428 +
  71.429 +		if (subjectPtr==NULL)
  71.430 +		{
  71.431 +			Ptr<Observer<DelegateT> > subject = *new Observer<DelegateT>();
  71.432 +			_Hash.Add(key, subject);
  71.433 +			observer->Observe(subject);
  71.434 +		}
  71.435 +		else
  71.436 +		{
  71.437 +			observer->Observe(*subjectPtr);
  71.438 +		}
  71.439 +	}
  71.440 +
  71.441 +	void RemoveSubject(OVR::String key)
  71.442 +	{
  71.443 +		Lock::Locker locker(&TheLock);
  71.444 +		Ptr<Observer<DelegateT> > *subjectPtr = _Hash.Get(key);
  71.445 +		if (subjectPtr!=NULL)
  71.446 +		{
  71.447 +			(*subjectPtr)->Shutdown();
  71.448 +			_Hash.Remove(key);
  71.449 +		}
  71.450 +	}
  71.451 +
  71.452 +protected:
  71.453 +	OVR::Hash< OVR::String, Ptr<Observer<DelegateT> >, OVR::String::HashFunctor > _Hash;
  71.454 +	Lock                     TheLock;      // Lock to synchronize calls and shutdown
  71.455 +};
  71.456 +
  71.457 +
  71.458 +} // namespace OVR
  71.459 +
  71.460 +#endif // OVR_Observer_h
    72.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    72.2 +++ b/LibOVR/Src/Kernel/OVR_RefCount.cpp	Wed Jan 14 06:51:16 2015 +0200
    72.3 @@ -0,0 +1,111 @@
    72.4 +/************************************************************************************
    72.5 +
    72.6 +Filename    :   OVR_RefCount.cpp
    72.7 +Content     :   Reference counting implementation
    72.8 +Created     :   September 19, 2012
    72.9 +Notes       : 
   72.10 +
   72.11 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   72.12 +
   72.13 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
   72.14 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
   72.15 +which is provided at the time of installation or download, or which 
   72.16 +otherwise accompanies this software in either electronic or hard copy form.
   72.17 +
   72.18 +You may obtain a copy of the License at
   72.19 +
   72.20 +http://www.oculusvr.com/licenses/LICENSE-3.2 
   72.21 +
   72.22 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
   72.23 +distributed under the License is distributed on an "AS IS" BASIS,
   72.24 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   72.25 +See the License for the specific language governing permissions and
   72.26 +limitations under the License.
   72.27 +
   72.28 +************************************************************************************/
   72.29 +
   72.30 +#include "OVR_RefCount.h"
   72.31 +#include "OVR_Atomic.h"
   72.32 +#include "OVR_Log.h"
   72.33 +
   72.34 +namespace OVR {
   72.35 +
   72.36 +#ifdef OVR_CC_ARM
   72.37 +void* ReturnArg0(void* p)
   72.38 +{
   72.39 +    return p;
   72.40 +}
   72.41 +#endif
   72.42 +
   72.43 +// ***** Reference Count Base implementation
   72.44 +
   72.45 +RefCountImplCore::~RefCountImplCore()
   72.46 +{
   72.47 +    // RefCount can be either 1 or 0 here.
   72.48 +    //  0 if Release() was properly called.
   72.49 +    //  1 if the object was declared on stack or as an aggregate.
   72.50 +    OVR_ASSERT(RefCount <= 1);
   72.51 +}
   72.52 +
   72.53 +#ifdef OVR_BUILD_DEBUG
   72.54 +void RefCountImplCore::reportInvalidDelete(void *pmem)
   72.55 +{
   72.56 +    OVR_DEBUG_LOG(
   72.57 +        ("Invalid delete call on ref-counted object at %p. Please use Release()", pmem));
   72.58 +    OVR_ASSERT(0);
   72.59 +}
   72.60 +#endif
   72.61 +
   72.62 +RefCountNTSImplCore::~RefCountNTSImplCore()
   72.63 +{
   72.64 +    // RefCount can be either 1 or 0 here.
   72.65 +    //  0 if Release() was properly called.
   72.66 +    //  1 if the object was declared on stack or as an aggregate.
   72.67 +    OVR_ASSERT(RefCount <= 1);
   72.68 +}
   72.69 +
   72.70 +#ifdef OVR_BUILD_DEBUG
   72.71 +void RefCountNTSImplCore::reportInvalidDelete(void *pmem)
   72.72 +{
   72.73 +    OVR_DEBUG_LOG(
   72.74 +        ("Invalid delete call on ref-counted object at %p. Please use Release()", pmem));
   72.75 +    OVR_ASSERT(0);
   72.76 +}
   72.77 +#endif
   72.78 +
   72.79 +
   72.80 +// *** Thread-Safe RefCountImpl
   72.81 +
   72.82 +void    RefCountImpl::AddRef()
   72.83 +{
   72.84 +    AtomicOps<int>::ExchangeAdd_NoSync(&RefCount, 1);
   72.85 +}
   72.86 +void    RefCountImpl::Release()
   72.87 +{
   72.88 +    if ((AtomicOps<int>::ExchangeAdd_NoSync(&RefCount, -1) - 1) == 0)
   72.89 +        delete this;
   72.90 +}
   72.91 +
   72.92 +// *** Thread-Safe RefCountVImpl w/virtual AddRef/Release
   72.93 +
   72.94 +void    RefCountVImpl::AddRef()
   72.95 +{
   72.96 +    AtomicOps<int>::ExchangeAdd_NoSync(&RefCount, 1);
   72.97 +}
   72.98 +void    RefCountVImpl::Release()
   72.99 +{
  72.100 +    if ((AtomicOps<int>::ExchangeAdd_NoSync(&RefCount, -1) - 1) == 0)
  72.101 +        delete this;
  72.102 +}
  72.103 +
  72.104 +// *** NON-Thread-Safe RefCountImpl
  72.105 +
  72.106 +void    RefCountNTSImpl::Release() const
  72.107 +{
  72.108 +    RefCount--;
  72.109 +    if (RefCount == 0)
  72.110 +        delete this;
  72.111 +}
  72.112 +
  72.113 +
  72.114 +} // OVR
    73.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    73.2 +++ b/LibOVR/Src/Kernel/OVR_RefCount.h	Wed Jan 14 06:51:16 2015 +0200
    73.3 @@ -0,0 +1,565 @@
    73.4 +/************************************************************************************
    73.5 +
    73.6 +PublicHeader:   Kernel
    73.7 +Filename    :   OVR_RefCount.h
    73.8 +Content     :   Reference counting implementation headers
    73.9 +Created     :   September 19, 2012
   73.10 +Notes       : 
   73.11 +
   73.12 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   73.13 +
   73.14 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
   73.15 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
   73.16 +which is provided at the time of installation or download, or which 
   73.17 +otherwise accompanies this software in either electronic or hard copy form.
   73.18 +
   73.19 +You may obtain a copy of the License at
   73.20 +
   73.21 +http://www.oculusvr.com/licenses/LICENSE-3.2 
   73.22 +
   73.23 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
   73.24 +distributed under the License is distributed on an "AS IS" BASIS,
   73.25 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   73.26 +See the License for the specific language governing permissions and
   73.27 +limitations under the License.
   73.28 +
   73.29 +************************************************************************************/
   73.30 +
   73.31 +#ifndef OVR_RefCount_h
   73.32 +#define OVR_RefCount_h
   73.33 +
   73.34 +#include "OVR_Types.h"
   73.35 +#include "OVR_Allocator.h"
   73.36 +
   73.37 +namespace OVR {
   73.38 +
   73.39 +//-----------------------------------------------------------------------------------
   73.40 +// ***** Reference Counting
   73.41 +
   73.42 +// There are three types of reference counting base classes:
   73.43 +//
   73.44 +//  RefCountBase     - Provides thread-safe reference counting (Default).
   73.45 +//  RefCountBaseNTS  - Non Thread Safe version of reference counting.
   73.46 +
   73.47 +
   73.48 +// ***** Declared classes
   73.49 +
   73.50 +template<class C>
   73.51 +class   RefCountBase;
   73.52 +template<class C>
   73.53 +class   RefCountBaseNTS;
   73.54 +
   73.55 +class   RefCountImpl;
   73.56 +class   RefCountNTSImpl;
   73.57 +
   73.58 +
   73.59 +//-----------------------------------------------------------------------------------
   73.60 +// ***** Implementation For Reference Counting
   73.61 +
   73.62 +// RefCountImplCore holds RefCount value and defines a few utility
   73.63 +// functions shared by all implementations.
   73.64 +
   73.65 +class RefCountImplCore
   73.66 +{
   73.67 +protected:
   73.68 +   volatile int RefCount;
   73.69 +
   73.70 +public:
   73.71 +    // RefCountImpl constructor always initializes RefCount to 1 by default.
   73.72 +    OVR_FORCE_INLINE RefCountImplCore() : RefCount(1) { }
   73.73 +
   73.74 +    // Need virtual destructor
   73.75 +    // This:    1. Makes sure the right destructor's called.
   73.76 +    //          2. Makes us have VTable, necessary if we are going to have format needed by InitNewMem()
   73.77 +    virtual ~RefCountImplCore();
   73.78 +
   73.79 +    // Debug method only.
   73.80 +    int GetRefCount() const { return RefCount;  }
   73.81 +
   73.82 +    // This logic is used to detect invalid 'delete' calls of reference counted
   73.83 +    // objects. Direct delete calls are not allowed on them unless they come in
   73.84 +    // internally from Release.
   73.85 +#ifdef OVR_BUILD_DEBUG    
   73.86 +    static void   OVR_CDECL  reportInvalidDelete(void *pmem);
   73.87 +    inline static void checkInvalidDelete(RefCountImplCore *pmem)
   73.88 +    {
   73.89 +        if (pmem->RefCount != 0)
   73.90 +            reportInvalidDelete(pmem);
   73.91 +    }
   73.92 +#else
   73.93 +    inline static void checkInvalidDelete(RefCountImplCore *) { }
   73.94 +#endif
   73.95 +
   73.96 +    // Base class ref-count content should not be copied.
   73.97 +    void operator = (const RefCountImplCore &) { }  
   73.98 +};
   73.99 +
  73.100 +class RefCountNTSImplCore
  73.101 +{
  73.102 +protected:
  73.103 +    mutable int RefCount;
  73.104 +
  73.105 +public:
  73.106 +    // RefCountImpl constructor always initializes RefCount to 1 by default.
  73.107 +    OVR_FORCE_INLINE RefCountNTSImplCore() : RefCount(1) { }
  73.108 +
  73.109 +    // Need virtual destructor
  73.110 +    // This:    1. Makes sure the right destructor's called.
  73.111 +    //          2. Makes us have VTable, necessary if we are going to have format needed by InitNewMem()
  73.112 +    virtual ~RefCountNTSImplCore();
  73.113 +
  73.114 +    // Debug method only.
  73.115 +    int             GetRefCount() const { return RefCount;  }
  73.116 +
  73.117 +    // This logic is used to detect invalid 'delete' calls of reference counted
  73.118 +    // objects. Direct delete calls are not allowed on them unless they come in
  73.119 +    // internally from Release.
  73.120 +#ifdef OVR_BUILD_DEBUG    
  73.121 +    static void   OVR_CDECL  reportInvalidDelete(void *pmem);
  73.122 +    OVR_FORCE_INLINE static void checkInvalidDelete(RefCountNTSImplCore *pmem)
  73.123 +    {
  73.124 +        if (pmem->RefCount != 0)
  73.125 +            reportInvalidDelete(pmem);
  73.126 +    }
  73.127 +#else
  73.128 +    OVR_FORCE_INLINE static void checkInvalidDelete(RefCountNTSImplCore *) { }
  73.129 +#endif
  73.130 +
  73.131 +    // Base class ref-count content should not be copied.
  73.132 +    void operator = (const RefCountNTSImplCore &) { }  
  73.133 +};
  73.134 +
  73.135 +
  73.136 +
  73.137 +// RefCountImpl provides Thread-Safe implementation of reference counting, so
  73.138 +// it should be used by default in most places.
  73.139 +
  73.140 +class RefCountImpl : public RefCountImplCore
  73.141 +{
  73.142 +public:
  73.143 +    // Thread-Safe Ref-Count Implementation.
  73.144 +    void    AddRef();
  73.145 +    void    Release();   
  73.146 +};
  73.147 +
  73.148 +// RefCountVImpl provides Thread-Safe implementation of reference counting, plus,
  73.149 +// virtual AddRef and Release.
  73.150 +
  73.151 +class RefCountVImpl : virtual public RefCountImplCore
  73.152 +{
  73.153 +public:
  73.154 +    // Thread-Safe Ref-Count Implementation.
  73.155 +    virtual void      AddRef();
  73.156 +    virtual void      Release();   
  73.157 +};
  73.158 +
  73.159 +
  73.160 +// RefCountImplNTS provides Non-Thread-Safe implementation of reference counting,
  73.161 +// which is slightly more efficient since it doesn't use atomics.
  73.162 +
  73.163 +class RefCountNTSImpl : public RefCountNTSImplCore
  73.164 +{
  73.165 +public:
  73.166 +    OVR_FORCE_INLINE void    AddRef() const { RefCount++; }
  73.167 +    void    Release() const;   
  73.168 +};
  73.169 +
  73.170 +
  73.171 +
  73.172 +// RefCountBaseStatImpl<> is a common class that adds new/delete override with Stat tracking
  73.173 +// to the reference counting implementation. Base must be one of the RefCountImpl classes.
  73.174 +
  73.175 +template<class Base>
  73.176 +class RefCountBaseStatImpl : public Base
  73.177 +{
  73.178 +public:
  73.179 +    RefCountBaseStatImpl() { }
  73.180 +     
  73.181 +    // *** Override New and Delete
  73.182 +
  73.183 +    // DOM-IGNORE-BEGIN
  73.184 +    // Undef new temporarily if it is being redefined
  73.185 +#ifdef OVR_DEFINE_NEW
  73.186 +#undef new
  73.187 +#endif
  73.188 +
  73.189 +#ifdef OVR_BUILD_DEBUG
  73.190 +    // Custom check used to detect incorrect calls of 'delete' on ref-counted objects.
  73.191 +    #define OVR_REFCOUNTALLOC_CHECK_DELETE(class_name, p)   \
  73.192 +        do {if (p) Base::checkInvalidDelete((class_name*)p); } while(0)
  73.193 +#else
  73.194 +    #define OVR_REFCOUNTALLOC_CHECK_DELETE(class_name, p)
  73.195 +#endif
  73.196 +
  73.197 +    // Redefine all new & delete operators.
  73.198 +    OVR_MEMORY_REDEFINE_NEW_IMPL(Base, OVR_REFCOUNTALLOC_CHECK_DELETE)
  73.199 +
  73.200 +#undef OVR_REFCOUNTALLOC_CHECK_DELETE
  73.201 +
  73.202 +#ifdef OVR_DEFINE_NEW
  73.203 +#define new OVR_DEFINE_NEW
  73.204 +#endif
  73.205 +        // OVR_BUILD_DEFINE_NEW
  73.206 +        // DOM-IGNORE-END
  73.207 +};
  73.208 +
  73.209 +
  73.210 +template<class Base>
  73.211 +class RefCountBaseStatVImpl : virtual public Base
  73.212 +{
  73.213 +public:
  73.214 +	RefCountBaseStatVImpl() { }
  73.215 +
  73.216 +	// *** Override New and Delete
  73.217 +
  73.218 +	// DOM-IGNORE-BEGIN
  73.219 +	// Undef new temporarily if it is being redefined
  73.220 +#ifdef OVR_DEFINE_NEW
  73.221 +#undef new
  73.222 +#endif
  73.223 +
  73.224 +#define OVR_REFCOUNTALLOC_CHECK_DELETE(class_name, p)
  73.225 +
  73.226 +	// Redefine all new & delete operators.
  73.227 +	OVR_MEMORY_REDEFINE_NEW_IMPL(Base, OVR_REFCOUNTALLOC_CHECK_DELETE)
  73.228 +
  73.229 +#undef OVR_REFCOUNTALLOC_CHECK_DELETE
  73.230 +
  73.231 +#ifdef OVR_DEFINE_NEW
  73.232 +#define new OVR_DEFINE_NEW
  73.233 +#endif
  73.234 +		// OVR_BUILD_DEFINE_NEW
  73.235 +		// DOM-IGNORE-END
  73.236 +};
  73.237 +
  73.238 +
  73.239 +
  73.240 +//-----------------------------------------------------------------------------------
  73.241 +// *** End user RefCountBase<> classes
  73.242 +
  73.243 +
  73.244 +// RefCountBase is a base class for classes that require thread-safe reference
  73.245 +// counting; it also overrides the new and delete operators to use MemoryHeap.
  73.246 +//
  73.247 +// Reference counted objects start out with RefCount value of 1. Further lifetime
  73.248 +// management is done through the AddRef() and Release() methods, typically
  73.249 +// hidden by Ptr<>.
  73.250 +
  73.251 +template<class C>
  73.252 +class RefCountBase : public RefCountBaseStatImpl<RefCountImpl>
  73.253 +{
  73.254 +public:    
  73.255 +    // Constructor.
  73.256 +    OVR_FORCE_INLINE RefCountBase() : RefCountBaseStatImpl<RefCountImpl>() { }    
  73.257 +};
  73.258 +
  73.259 +// RefCountBaseV is the same as RefCountBase but with virtual AddRef/Release
  73.260 +
  73.261 +template<class C>
  73.262 +class RefCountBaseV : virtual public RefCountBaseStatVImpl<RefCountVImpl>
  73.263 +{
  73.264 +public:    
  73.265 +    // Constructor.
  73.266 +    OVR_FORCE_INLINE RefCountBaseV() : RefCountBaseStatVImpl<RefCountVImpl>() { }    
  73.267 +};
  73.268 +
  73.269 +
  73.270 +// RefCountBaseNTS is a base class for classes that require Non-Thread-Safe reference
  73.271 +// counting; it also overrides the new and delete operators to use MemoryHeap.
  73.272 +// This class should only be used if all pointers to it are known to be assigned,
  73.273 +// destroyed and manipulated within one thread.
  73.274 +//
  73.275 +// Reference counted objects start out with RefCount value of 1. Further lifetime
  73.276 +// management is done through the AddRef() and Release() methods, typically
  73.277 +// hidden by Ptr<>.
  73.278 +
  73.279 +template<class C>
  73.280 +class RefCountBaseNTS : public RefCountBaseStatImpl<RefCountNTSImpl>
  73.281 +{
  73.282 +public:    
  73.283 +    // Constructor.
  73.284 +    OVR_FORCE_INLINE RefCountBaseNTS() : RefCountBaseStatImpl<RefCountNTSImpl>() { }    
  73.285 +};
  73.286 +
  73.287 +//-----------------------------------------------------------------------------------
  73.288 +// ***** Pickable template pointer
  73.289 +enum PickType { PickValue };
  73.290 +
  73.291 +template <typename T>
  73.292 +class Pickable
  73.293 +{
  73.294 +public:
  73.295 +    Pickable() : pV(NULL) {}
  73.296 +    explicit Pickable(T* p) : pV(p) {}
  73.297 +    Pickable(T* p, PickType) : pV(p) 
  73.298 +    {
  73.299 +        OVR_ASSERT(pV);
  73.300 +        if (pV)
  73.301 +            pV->AddRef();
  73.302 +    }
  73.303 +    template <typename OT>
  73.304 +    Pickable(const Pickable<OT>& other) : pV(other.GetPtr()) {}
  73.305 +
  73.306 +public:
  73.307 +    Pickable& operator =(const Pickable& other)
  73.308 +    {
  73.309 +        OVR_ASSERT(pV == NULL);
  73.310 +        pV = other.pV;
  73.311 +        // Extra check.
  73.312 +        //other.pV = NULL;
  73.313 +        return *this;
  73.314 +    }
  73.315 +
  73.316 +public:
  73.317 +    T* GetPtr() const { return pV; }
  73.318 +    T* operator->() const
  73.319 +    {
  73.320 +        return pV;
  73.321 +    }
  73.322 +    T& operator*() const
  73.323 +    {
  73.324 +        OVR_ASSERT(pV);
  73.325 +        return *pV;
  73.326 +    }
  73.327 +
  73.328 +private:
  73.329 +    T* pV;
  73.330 +};
  73.331 +
  73.332 +template <typename T>
  73.333 +OVR_FORCE_INLINE
  73.334 +Pickable<T> MakePickable(T* p)
  73.335 +{
  73.336 +    return Pickable<T>(p);
  73.337 +}
  73.338 +
  73.339 +//-----------------------------------------------------------------------------------
  73.340 +// ***** Ref-Counted template pointer
  73.341 +
  73.342 +// Automatically AddRefs and Releases interfaces
  73.343 +
  73.344 +void* ReturnArg0(void* p);
  73.345 +
  73.346 +template<class C>
  73.347 +class Ptr
  73.348 +{
  73.349 +#ifdef OVR_CC_ARM
  73.350 +    static C* ReturnArg(void* p) { return (C*)ReturnArg0(p); }
  73.351 +#endif
  73.352 +
  73.353 +protected:
  73.354 +    C   *pObject;
  73.355 +
  73.356 +public:
  73.357 +
  73.358 +    // Constructors
  73.359 +    OVR_FORCE_INLINE Ptr() : pObject(0)
  73.360 +    { }
  73.361 +#ifdef OVR_CC_ARM
  73.362 +    OVR_FORCE_INLINE Ptr(C &robj) : pObject(ReturnArg(&robj))
  73.363 +#else
  73.364 +    OVR_FORCE_INLINE Ptr(C &robj) : pObject(&robj)
  73.365 +#endif
  73.366 +    { }
  73.367 +    OVR_FORCE_INLINE Ptr(Pickable<C> v) : pObject(v.GetPtr())
  73.368 +    {
  73.369 +        // No AddRef() on purpose.
  73.370 +    }
  73.371 +    OVR_FORCE_INLINE Ptr(Ptr<C>& other, PickType) : pObject(other.pObject)
  73.372 +    {
  73.373 +        other.pObject = NULL;
  73.374 +        // No AddRef() on purpose.
  73.375 +    }
  73.376 +    OVR_FORCE_INLINE Ptr(C *pobj)
  73.377 +    {
  73.378 +        if (pobj) pobj->AddRef();   
  73.379 +        pObject = pobj;
  73.380 +    }
  73.381 +    OVR_FORCE_INLINE Ptr(const Ptr<C> &src)
  73.382 +    {
  73.383 +        if (src.pObject) src.pObject->AddRef();     
  73.384 +        pObject = src.pObject;
  73.385 +    }
  73.386 +
  73.387 +    template<class R>
  73.388 +    OVR_FORCE_INLINE Ptr(Ptr<R> &src)
  73.389 +    {
  73.390 +        if (src) src->AddRef();
  73.391 +        pObject = src;
  73.392 +    }
  73.393 +    template<class R>
  73.394 +    OVR_FORCE_INLINE Ptr(Pickable<R> v) : pObject(v.GetPtr())
  73.395 +    {
  73.396 +        // No AddRef() on purpose.
  73.397 +    }
  73.398 +
  73.399 +    // Destructor
  73.400 +    OVR_FORCE_INLINE ~Ptr()
  73.401 +    {
  73.402 +        if (pObject) pObject->Release();        
  73.403 +    }
  73.404 +
  73.405 +    // Compares
  73.406 +    OVR_FORCE_INLINE bool operator == (const Ptr &other) const       { return pObject == other.pObject; }
  73.407 +    OVR_FORCE_INLINE bool operator != (const Ptr &other) const       { return pObject != other.pObject; }
  73.408 +
  73.409 +    OVR_FORCE_INLINE bool operator == (C *pother) const              { return pObject == pother; }
  73.410 +    OVR_FORCE_INLINE bool operator != (C *pother) const              { return pObject != pother; }
  73.411 +
  73.412 +
  73.413 +    OVR_FORCE_INLINE bool operator < (const Ptr &other) const       { return pObject < other.pObject; }
  73.414 +
  73.415 +    // Assignment
  73.416 +    template<class R>
  73.417 +    OVR_FORCE_INLINE const Ptr<C>& operator = (const Ptr<R> &src)
  73.418 +    {
  73.419 +        // By design we don't check for src == pObject, as we don't expect that to be the case the large majority of the time.
  73.420 +        if (src) src->AddRef();
  73.421 +        if (pObject) pObject->Release();        
  73.422 +        pObject = src;
  73.423 +        return *this;
  73.424 +    }   
  73.425 +    // Specialization
  73.426 +    OVR_FORCE_INLINE const Ptr<C>& operator = (const Ptr<C> &src)
  73.427 +    {
  73.428 +        if (src) src->AddRef();
  73.429 +        if (pObject) pObject->Release();        
  73.430 +        pObject = src;
  73.431 +        return *this;
  73.432 +    }   
  73.433 +    
  73.434 +    OVR_FORCE_INLINE const Ptr<C>& operator = (C *psrc)
  73.435 +    {
  73.436 +        if (psrc) psrc->AddRef();
  73.437 +        if (pObject) pObject->Release();        
  73.438 +        pObject = psrc;
  73.439 +        return *this;
  73.440 +    }   
  73.441 +    OVR_FORCE_INLINE const Ptr<C>& operator = (C &src)
  73.442 +    {       
  73.443 +        if (pObject) pObject->Release();        
  73.444 +        pObject = &src;
  73.445 +        return *this;
  73.446 +    }
  73.447 +    OVR_FORCE_INLINE Ptr<C>& operator = (Pickable<C> src)
  73.448 +    {
  73.449 +        return Pick(src);
  73.450 +    }
  73.451 +    template<class R>
  73.452 +    OVR_FORCE_INLINE Ptr<C>& operator = (Pickable<R> src)
  73.453 +    {
  73.454 +        return Pick(src);
  73.455 +    }
  73.456 +    
  73.457 +    // Set Assignment
  73.458 +    template<class R>
  73.459 +    OVR_FORCE_INLINE Ptr<C>& SetPtr(const Ptr<R> &src)
  73.460 +    {
  73.461 +        if (src) src->AddRef();
  73.462 +        if (pObject) pObject->Release();
  73.463 +        pObject = src;
  73.464 +        return *this;
  73.465 +    }
  73.466 +    // Specialization
  73.467 +    OVR_FORCE_INLINE Ptr<C>& SetPtr(const Ptr<C> &src)
  73.468 +    {
  73.469 +        if (src) src->AddRef();
  73.470 +        if (pObject) pObject->Release();
  73.471 +        pObject = src;
  73.472 +        return *this;
  73.473 +    }   
  73.474 +    
  73.475 +    OVR_FORCE_INLINE Ptr<C>& SetPtr(C *psrc)
  73.476 +    {
  73.477 +        if (psrc) psrc->AddRef();
  73.478 +        if (pObject) pObject->Release();
  73.479 +        pObject = psrc;
  73.480 +        return *this;
  73.481 +    }   
  73.482 +    OVR_FORCE_INLINE Ptr<C>& SetPtr(C &src)
  73.483 +    {       
  73.484 +        if (pObject) pObject->Release();
  73.485 +        pObject = &src;
  73.486 +        return *this;
  73.487 +    }
  73.488 +    OVR_FORCE_INLINE Ptr<C>& SetPtr(Pickable<C> src)
  73.489 +    {       
  73.490 +        return Pick(src);
  73.491 +    }
  73.492 +
  73.493 +    // Nulls ref-counted pointer without decrement
  73.494 +    OVR_FORCE_INLINE void    NullWithoutRelease()    
  73.495 +    { 
  73.496 +        pObject = 0;    
  73.497 +    }
  73.498 +
  73.499 +    // Clears the pointer to the object
  73.500 +    OVR_FORCE_INLINE void    Clear()
  73.501 +    {
  73.502 +        if (pObject) pObject->Release();
  73.503 +        pObject = 0;
  73.504 +    }
  73.505 +
  73.506 +    // Obtain pointer reference directly, for D3D interfaces
  73.507 +    OVR_FORCE_INLINE C*& GetRawRef()                 { return pObject; }
  73.508 +
  73.509 +    // Access Operators
  73.510 +    OVR_FORCE_INLINE C* GetPtr() const               { return pObject; }
  73.511 +    OVR_FORCE_INLINE C& operator * () const          { return *pObject; }
  73.512 +    OVR_FORCE_INLINE C* operator -> ()  const        { return pObject; }
  73.513 +    // Conversion                   
  73.514 +    OVR_FORCE_INLINE operator C* () const            { return pObject; }
  73.515 +
  73.516 +    // Pickers.
  73.517 +
  73.518 +    // Pick a value.
  73.519 +    OVR_FORCE_INLINE Ptr<C>& Pick(Ptr<C>& other)
  73.520 +    {
  73.521 +        if (&other != this)
  73.522 +        {
  73.523 +            if (pObject) pObject->Release();
  73.524 +            pObject = other.pObject;
  73.525 +            other.pObject = 0;
  73.526 +        }
  73.527 +
  73.528 +        return *this;
  73.529 +    }
  73.530 +
  73.531 +    OVR_FORCE_INLINE Ptr<C>& Pick(Pickable<C> v)
  73.532 +    {
  73.533 +        if (v.GetPtr() != pObject)
  73.534 +        {
  73.535 +            if (pObject) pObject->Release();
  73.536 +            pObject = v.GetPtr();
  73.537 +        }
  73.538 +
  73.539 +        return *this;
  73.540 +    }
  73.541 +
  73.542 +    template<class R>
  73.543 +    OVR_FORCE_INLINE Ptr<C>& Pick(Pickable<R> v)
  73.544 +    {
  73.545 +        if (v.GetPtr() != pObject)
  73.546 +        {
  73.547 +            if (pObject) pObject->Release();
  73.548 +            pObject = v.GetPtr();
  73.549 +        }
  73.550 +
  73.551 +        return *this;
  73.552 +    }
  73.553 +
  73.554 +    OVR_FORCE_INLINE Ptr<C>& Pick(C* p)
  73.555 +    {
  73.556 +        if (p != pObject)
  73.557 +        {
  73.558 +            if (pObject) pObject->Release();
  73.559 +            pObject = p;
  73.560 +        }
  73.561 +
  73.562 +        return *this;
  73.563 +    }
  73.564 +};
  73.565 +
  73.566 +} // OVR
  73.567 +
  73.568 +#endif
    74.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    74.2 +++ b/LibOVR/Src/Kernel/OVR_SharedMemory.cpp	Wed Jan 14 06:51:16 2015 +0200
    74.3 @@ -0,0 +1,691 @@
    74.4 +/************************************************************************************
    74.5 +
    74.6 +Filename    :   OVR_SharedMemory.cpp
    74.7 +Content     :   Inter-process shared memory subsystem
    74.8 +Created     :   June 1, 2014
    74.9 +Notes       : 
   74.10 +
   74.11 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   74.12 +
   74.13 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
   74.14 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
   74.15 +which is provided at the time of installation or download, or which 
   74.16 +otherwise accompanies this software in either electronic or hard copy form.
   74.17 +
   74.18 +You may obtain a copy of the License at
   74.19 +
   74.20 +http://www.oculusvr.com/licenses/LICENSE-3.2 
   74.21 +
   74.22 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
   74.23 +distributed under the License is distributed on an "AS IS" BASIS,
   74.24 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   74.25 +See the License for the specific language governing permissions and
   74.26 +limitations under the License.
   74.27 +
   74.28 +************************************************************************************/
   74.29 +
   74.30 +#include "OVR_SharedMemory.h"
   74.31 +#include "OVR_Atomic.h"
   74.32 +#include "OVR_Log.h"
   74.33 +#include "OVR_String.h"
   74.34 +#include "OVR_Array.h"
   74.35 +
   74.36 +#if defined(OVR_OS_WIN32) && !defined(OVR_FAKE_SHAREDMEMORY)
   74.37 +#include <Sddl.h> // ConvertStringSecurityDescriptorToSecurityDescriptor
   74.38 +#endif // OVR_OS_WIN32
   74.39 +
   74.40 +#if (defined(OVR_OS_LINUX) || defined(OVR_OS_MAC)) && !defined(OVR_FAKE_SHAREDMEMORY)
   74.41 +#include <sys/mman.h> // shm_open(), mmap()
   74.42 +#include <errno.h> // error results for mmap
   74.43 +#include <sys/stat.h> // mode constants
   74.44 +#include <fcntl.h> // O_ constants
   74.45 +#include <unistd.h> // close()
   74.46 +#endif // OVR_OS_LINUX
   74.47 +
   74.48 +OVR_DEFINE_SINGLETON(OVR::SharedMemoryFactory);
   74.49 +
   74.50 +namespace OVR {
   74.51 +
   74.52 +
   74.53 +    //// Fake version
   74.54 +
   74.55 +#if defined(OVR_FAKE_SHAREDMEMORY)
   74.56 +
   74.57 +    class FakeMemoryBlock : public RefCountBase<FakeMemoryBlock>
   74.58 +    {
   74.59 +        String Name;
   74.60 +        char*  Data;
   74.61 +        int    SizeBytes;
   74.62 +        int    References;
   74.63 +
   74.64 +    public:
   74.65 +        FakeMemoryBlock(const String& name, int size) :
   74.66 +            Name(name),
   74.67 +            Data(NULL),
   74.68 +            SizeBytes(size),
   74.69 +            References(1)
   74.70 +        {
   74.71 +            Data = new char[SizeBytes];
   74.72 +        }
   74.73 +        ~FakeMemoryBlock()
   74.74 +        {
   74.75 +            delete[] Data;
   74.76 +        }
   74.77 +
   74.78 +        bool IsNamed(const String& name)
   74.79 +        {
   74.80 +            return Name.CompareNoCase(name) == 0;
   74.81 +        }
   74.82 +        void* GetData()
   74.83 +        {
   74.84 +            return Data;
   74.85 +        }
   74.86 +        int GetSizeI()
   74.87 +        {
   74.88 +            return SizeBytes;
   74.89 +        }
   74.90 +        void IncrementReferences()
   74.91 +        {
   74.92 +            ++References;
   74.93 +        }
   74.94 +        bool DecrementReferences()
   74.95 +        {
   74.96 +            return --References <= 0;
   74.97 +        }
   74.98 +    };
   74.99 +
  74.100 +    class SharedMemoryInternal : public NewOverrideBase
  74.101 +    {
  74.102 +    public:
  74.103 +        void* FileView;
  74.104 +        Ptr<FakeMemoryBlock> Block;
  74.105 +
  74.106 +        void Close();
  74.107 +
  74.108 +        SharedMemoryInternal(FakeMemoryBlock* block) :
  74.109 +            Block(block)
  74.110 +        {
  74.111 +            FileView = Block->GetData();
  74.112 +        }
  74.113 +        ~SharedMemoryInternal()
  74.114 +        {
  74.115 +            Close();
  74.116 +        }
  74.117 +
  74.118 +        static SharedMemoryInternal* CreateSharedMemory(const SharedMemory::OpenParameters& params);
  74.119 +    };
  74.120 +
  74.121 +
  74.122 +    //// FakeMemoryManager
  74.123 +
  74.124 +    class FakeMemoryManager : public NewOverrideBase, public SystemSingletonBase<FakeMemoryManager>
  74.125 +    {
  74.126 +        OVR_DECLARE_SINGLETON(FakeMemoryManager);
  74.127 +
  74.128 +        Lock FakeLock;
  74.129 +        Array< Ptr<FakeMemoryBlock> > FakeArray;
  74.130 +
  74.131 +    public:
  74.132 +        SharedMemoryInternal* Open(const char *name, int bytes, bool openOnly)
  74.133 +        {
  74.134 +            Lock::Locker locker(&FakeLock);
  74.135 +
  74.136 +            const int count = FakeArray.GetSizeI();
  74.137 +            for (int ii = 0; ii < count; ++ii)
  74.138 +            {
  74.139 +                if (FakeArray[ii]->IsNamed(name))
  74.140 +                {
  74.141 +                    FakeArray[ii]->IncrementReferences();
  74.142 +                    return new SharedMemoryInternal(FakeArray[ii]);
  74.143 +                }
  74.144 +            }
  74.145 +
  74.146 +            if (openOnly)
  74.147 +            {
  74.148 +                return NULL;
  74.149 +            }
  74.150 +
  74.151 +            Ptr<FakeMemoryBlock> data = *new FakeMemoryBlock(name, bytes);
  74.152 +            FakeArray.PushBack(data);
  74.153 +            return new SharedMemoryInternal(data);
  74.154 +        }
  74.155 +
  74.156 +        void Free(FakeMemoryBlock* block)
  74.157 +        {
  74.158 +            Lock::Locker locker(&FakeLock);
  74.159 +
  74.160 +            const int count = FakeArray.GetSizeI();
  74.161 +            for (int ii = 0; ii < count; ++ii)
  74.162 +            {
  74.163 +                if (FakeArray[ii].GetPtr() == block)
  74.164 +                {
  74.165 +                    // If the reference count hit zero,
  74.166 +                    if (FakeArray[ii]->DecrementReferences())
  74.167 +                    {
  74.168 +                        // Toast
  74.169 +                        FakeArray.RemoveAtUnordered(ii);
  74.170 +                    }
  74.171 +                    break;
  74.172 +                }
  74.173 +            }
  74.174 +        }
  74.175 +    };
  74.176 +
  74.177 +    FakeMemoryManager::FakeMemoryManager()
  74.178 +    {
  74.179 +        PushDestroyCallbacks();
  74.180 +    }
  74.181 +
  74.182 +    FakeMemoryManager::~FakeMemoryManager()
  74.183 +    {
  74.184 +        OVR_ASSERT(FakeArray.GetSizeI() == 0);
  74.185 +    }
  74.186 +
  74.187 +    void FakeMemoryManager::OnSystemDestroy()
  74.188 +    {
  74.189 +        delete this;
  74.190 +    }
  74.191 +
  74.192 +
  74.193 +} // namespace OVR
  74.194 +
  74.195 +OVR_DEFINE_SINGLETON(FakeMemoryManager);
  74.196 +
  74.197 +namespace OVR {
  74.198 +
  74.199 +
  74.200 +void SharedMemoryInternal::Close()
  74.201 +{
  74.202 +	FakeMemoryManager::GetInstance()->Free(Block);
  74.203 +	Block.Clear();
  74.204 +}
  74.205 +
  74.206 +SharedMemoryInternal* SharedMemoryInternal::CreateSharedMemory(const SharedMemory::OpenParameters& params)
  74.207 +{
  74.208 +	return FakeMemoryManager::GetInstance()->Open(params.globalName, params.minSizeBytes, params.openMode == SharedMemory::OpenMode_OpenOnly);
  74.209 +}
  74.210 +
  74.211 +#endif
  74.212 +
  74.213 +
  74.214 +//// Windows version
  74.215 +
  74.216 +#if defined(OVR_OS_WIN32) && !defined(OVR_FAKE_SHAREDMEMORY)
  74.217 +
  74.218 +#pragma comment(lib, "advapi32.lib")
  74.219 +
  74.220 +// Hidden implementation class for OS-specific behavior
  74.221 +class SharedMemoryInternal : public NewOverrideBase
  74.222 +{
  74.223 +public:
  74.224 +	HANDLE FileMapping;
  74.225 +	void* FileView;
  74.226 +
  74.227 +	SharedMemoryInternal(HANDLE fileMapping, void* fileView) :
  74.228 +		FileMapping(fileMapping),
  74.229 +		FileView(fileView)
  74.230 +	{
  74.231 +	}
  74.232 +
  74.233 +	~SharedMemoryInternal()
  74.234 +	{
  74.235 +		// If file view is set,
  74.236 +		if (FileView)
  74.237 +		{
  74.238 +			UnmapViewOfFile(FileView);
  74.239 +			FileView = NULL;
  74.240 +		}
  74.241 +
  74.242 +		// If file mapping is set,
  74.243 +		if (FileMapping != NULL)
  74.244 +		{
  74.245 +			CloseHandle(FileMapping);
  74.246 +			FileMapping = NULL;
  74.247 +		}
  74.248 +	}
  74.249 +
  74.250 +	static SharedMemoryInternal* DoFileMap(HANDLE hFileMapping, const char* fileName, bool openReadOnly, int minSize);
  74.251 +	static SharedMemoryInternal* AttemptOpenSharedMemory(const char* fileName, int minSize, bool openReadOnly);
  74.252 +	static SharedMemoryInternal* AttemptCreateSharedMemory(const char* fileName, int minSize, bool openReadOnly, bool allowRemoteWrite);
  74.253 +	static SharedMemoryInternal* CreateSharedMemory(const SharedMemory::OpenParameters& params);
  74.254 +};
  74.255 +
  74.256 +SharedMemoryInternal* SharedMemoryInternal::DoFileMap(HANDLE hFileMapping, const char* fileName, bool openReadOnly, int minSize)
  74.257 +{
  74.258 +	// Interpret the access mode as a map desired access code
  74.259 +	DWORD mapDesiredAccess = openReadOnly ? FILE_MAP_READ : FILE_MAP_WRITE;
  74.260 +
  74.261 +	// Map view of the file to this process
  74.262 +	void* pFileView = MapViewOfFile(hFileMapping, mapDesiredAccess, 0, 0, minSize);
  74.263 +
  74.264 +	// If mapping could not be created,
  74.265 +	if (!pFileView)
  74.266 +	{
  74.267 +		CloseHandle(hFileMapping);
  74.268 +
  74.269 +		OVR_DEBUG_LOG(("[SharedMemory] FAILURE: Unable to map view of file for %s error code = %d", fileName, GetLastError()));
  74.270 +        OVR_UNUSED(fileName);
  74.271 +		return NULL;
  74.272 +	}
  74.273 +
  74.274 +	// Create internal representation
  74.275 +	SharedMemoryInternal* pimple = new SharedMemoryInternal(hFileMapping, pFileView);
  74.276 +
  74.277 +	// If memory allocation fails,
  74.278 +	if (!pimple)
  74.279 +	{
  74.280 +		UnmapViewOfFile(pFileView);
  74.281 +		CloseHandle(hFileMapping);
  74.282 +
  74.283 +		OVR_DEBUG_LOG(("[SharedMemory] FAILURE: Out of memory"));
  74.284 +		return NULL;
  74.285 +	}
  74.286 +
  74.287 +	return pimple;
  74.288 +}
  74.289 +
  74.290 +SharedMemoryInternal* SharedMemoryInternal::AttemptOpenSharedMemory(const char* fileName, int minSize, bool openReadOnly)
  74.291 +{
  74.292 +	// Interpret the access mode as a map desired access code
  74.293 +	DWORD mapDesiredAccess = openReadOnly ? FILE_MAP_READ : FILE_MAP_WRITE;
  74.294 +
  74.295 +	// Open file mapping
  74.296 +	HANDLE hFileMapping = OpenFileMappingA(mapDesiredAccess, TRUE, fileName);
  74.297 +
  74.298 +	// If file was mapped unsuccessfully,
  74.299 +	if (NULL == hFileMapping)
  74.300 +	{
  74.301 +		OVR_DEBUG_LOG(("[SharedMemory] WARNING: Unable to open file mapping for %s error code = %d (not necessarily bad)", fileName, GetLastError()));
  74.302 +		return NULL;
  74.303 +	}
  74.304 +
  74.305 +	// Map the file
  74.306 +	return DoFileMap(hFileMapping, fileName, openReadOnly, minSize);
  74.307 +}
  74.308 +
  74.309 +SharedMemoryInternal* SharedMemoryInternal::AttemptCreateSharedMemory(const char* fileName, int minSize, bool openReadOnly, bool allowRemoteWrite)
  74.310 +{
  74.311 +	// Prepare a SECURITY_ATTRIBUTES object
  74.312 +	SECURITY_ATTRIBUTES security;
  74.313 +	ZeroMemory(&security, sizeof(security));
  74.314 +	security.nLength = sizeof(security);
  74.315 +
  74.316 +	// Security descriptor by DACL strings:
  74.317 +	// ACE strings grant Allow(A), Object/Contains Inheritance (OICI) of:
  74.318 +	// + Grant All (GA) to System (SY)
  74.319 +	// + Grant All (GA) to Built-in Administrators (BA)
  74.320 +	// + Grant Read-Only (GR) or Read-Write (GWGR) to Interactive Users (IU) - ie. games
  74.321 +	static const char* DACLString_ReadOnly = "D:P(A;OICI;GA;;;SY)(A;OICI;GA;;;BA)(A;OICI;GR;;;IU)";
  74.322 +	static const char* DACLString_ReadWrite = "D:P(A;OICI;GA;;;SY)(A;OICI;GA;;;BA)(A;OICI;GWGR;;;IU)";
  74.323 +
  74.324 +	// Select the remote process access mode
  74.325 +	const char* remoteAccessString =
  74.326 +		allowRemoteWrite ? DACLString_ReadWrite : DACLString_ReadOnly;
  74.327 +
  74.328 +	// Attempt to convert access string to security attributes
  74.329 +	// Note: This will allocate the security descriptor with LocalAlloc() and must be freed later
  74.330 +	BOOL bConvertOkay = ConvertStringSecurityDescriptorToSecurityDescriptorA(
  74.331 +		remoteAccessString, SDDL_REVISION_1, &security.lpSecurityDescriptor, NULL);
  74.332 +
  74.333 +	// If conversion fails,
  74.334 +	if (!bConvertOkay)
  74.335 +	{
  74.336 +		OVR_DEBUG_LOG(("[SharedMemory] FAILURE: Unable to convert access string, error code = %d", GetLastError()));
  74.337 +		return NULL;
  74.338 +	}
  74.339 +
  74.340 +	// Interpret the access mode as a page protection code
  74.341 +	int pageProtectCode = openReadOnly ? PAGE_READONLY : PAGE_READWRITE;
  74.342 +
  74.343 +	// Attempt to create a file mapping
  74.344 +	HANDLE hFileMapping = CreateFileMappingA(INVALID_HANDLE_VALUE,	// From page file
  74.345 +											 &security,				// Security attributes
  74.346 +											 pageProtectCode,		// Read-only?
  74.347 +											 0,						// High word for size = 0
  74.348 +											 minSize,				// Low word for size
  74.349 +											 fileName);				// Name of global shared memory file
  74.350 +
  74.351 +	// Free the security descriptor buffer
  74.352 +	LocalFree(security.lpSecurityDescriptor);
  74.353 +
  74.354 +	// If mapping could not be created,
  74.355 +	if (NULL == hFileMapping)
  74.356 +	{
  74.357 +		OVR_DEBUG_LOG(("[SharedMemory] FAILURE: Unable to create file mapping for %s error code = %d", fileName, GetLastError()));
  74.358 +		return NULL;
  74.359 +	}
  74.360 +
  74.361 +#ifndef OVR_ALLOW_CREATE_FILE_MAPPING_IF_EXISTS
  74.362 +	// If the file mapping already exists,
  74.363 +	if (GetLastError() == ERROR_ALREADY_EXISTS)
  74.364 +	{
  74.365 +		CloseHandle(hFileMapping);
  74.366 +
  74.367 +		OVR_DEBUG_LOG(("[SharedMemory] FAILURE: File mapping at %s already exists", fileName));
  74.368 +		return NULL;
  74.369 +	}
  74.370 +#endif
  74.371 +
  74.372 +	// Map the file
  74.373 +	return DoFileMap(hFileMapping, fileName, openReadOnly, minSize);
  74.374 +}
  74.375 +
  74.376 +SharedMemoryInternal* SharedMemoryInternal::CreateSharedMemory(const SharedMemory::OpenParameters& params)
  74.377 +{
  74.378 +	SharedMemoryInternal* retval = NULL;
  74.379 +
  74.380 +	// Construct the file mapping name in a Windows-specific way
  74.381 +	OVR::String fileMappingName = params.globalName;
  74.382 +	const char *fileName = fileMappingName.ToCStr();
  74.383 +
  74.384 +	// Is being opened read-only?
  74.385 +	const bool openReadOnly = (params.accessMode == SharedMemory::AccessMode_ReadOnly);
  74.386 +
  74.387 +	// Try up to 3 times to reduce low-probability failures:
  74.388 +	static const int ATTEMPTS_MAX = 3;
  74.389 +	for (int attempts = 0; attempts < ATTEMPTS_MAX; ++attempts)
  74.390 +	{
  74.391 +		// If opening should be attempted first,
  74.392 +		if (params.openMode != SharedMemory::OpenMode_CreateOnly)
  74.393 +		{
  74.394 +			// Attempt to open a shared memory map
  74.395 +			retval = AttemptOpenSharedMemory(fileName, params.minSizeBytes, openReadOnly);
  74.396 +
  74.397 +			// If successful,
  74.398 +			if (retval)
  74.399 +			{
  74.400 +				// Done!
  74.401 +				break;
  74.402 +			}
  74.403 +		}
  74.404 +
  74.405 +		// If creating the shared memory is also acceptable,
  74.406 +		if (params.openMode != SharedMemory::OpenMode_OpenOnly)
  74.407 +		{
  74.408 +			// Interpret create mode
  74.409 +			const bool allowRemoteWrite = (params.remoteMode == SharedMemory::RemoteMode_ReadWrite);
  74.410 +
  74.411 +			// Attempt to create a shared memory map
  74.412 +			retval = AttemptCreateSharedMemory(fileName, params.minSizeBytes, openReadOnly, allowRemoteWrite);
  74.413 +
  74.414 +			// If successful,
  74.415 +			if (retval)
  74.416 +			{
  74.417 +				// Done!
  74.418 +				break;
  74.419 +			}
  74.420 +		}
  74.421 +	} // Re-attempt create/open
  74.422 +
  74.423 +	// Note: On Windows the initial contents of the region are guaranteed to be zero.
  74.424 +	return retval;
  74.425 +}
  74.426 +
  74.427 +#endif // OVR_OS_WIN32
  74.428 +
  74.429 +
  74.430 +#if (defined(OVR_OS_LINUX) || defined(OVR_OS_MAC)) && !defined(OVR_FAKE_SHAREDMEMORY)
  74.431 +
  74.432 +// Hidden implementation class for OS-specific behavior
  74.433 +class SharedMemoryInternal
  74.434 +{
  74.435 +public:
  74.436 +	int   FileMapping;
  74.437 +	void* FileView;
  74.438 +    int   FileSize;
  74.439 +
  74.440 +	SharedMemoryInternal(int fileMapping, void* fileView, int fileSize) :
  74.441 +		FileMapping(fileMapping),
  74.442 +		FileView(fileView),
  74.443 +        FileSize(fileSize)
  74.444 +	{
  74.445 +	}
  74.446 +
  74.447 +	~SharedMemoryInternal()
  74.448 +	{
  74.449 +		// If file view is set,
  74.450 +		if (FileView)
  74.451 +		{
  74.452 +            munmap(FileView, FileSize);
  74.453 +			FileView = MAP_FAILED;
  74.454 +		}
  74.455 +
  74.456 +		// If file mapping is set,
  74.457 +		if (FileMapping >= 0)
  74.458 +		{
  74.459 +            close(FileMapping);
  74.460 +			FileMapping = -1;
  74.461 +		}
  74.462 +	}
  74.463 +
  74.464 +	static SharedMemoryInternal* DoFileMap(int hFileMapping, const char* fileName, bool openReadOnly, int minSize);
  74.465 +	static SharedMemoryInternal* AttemptOpenSharedMemory(const char* fileName, int minSize, bool openReadOnly);
  74.466 +	static SharedMemoryInternal* AttemptCreateSharedMemory(const char* fileName, int minSize, bool openReadOnly, bool allowRemoteWrite);
  74.467 +	static SharedMemoryInternal* CreateSharedMemory(const SharedMemory::OpenParameters& params);
  74.468 +};
  74.469 +
  74.470 +SharedMemoryInternal* SharedMemoryInternal::DoFileMap(int hFileMapping, const char* fileName, bool openReadOnly, int minSize)
  74.471 +{
  74.472 +    // Calculate the required flags based on read/write mode
  74.473 +    int prot = openReadOnly ? PROT_READ : (PROT_READ|PROT_WRITE);
  74.474 +
  74.475 +    // Map the file view
  74.476 +    void* pFileView = mmap(NULL, minSize, prot, MAP_SHARED, hFileMapping, 0);
  74.477 +
  74.478 +    if (pFileView == MAP_FAILED)
  74.479 +    {
  74.480 +        close(hFileMapping);
  74.481 +
  74.482 +		OVR_DEBUG_LOG(("[SharedMemory] FAILURE: Unable to map view of file for %s error code = %d", fileName, errno));
  74.483 +        OVR_UNUSED(fileName);
  74.484 +		return NULL;
  74.485 +    }
  74.486 +
  74.487 +	// Create internal representation
  74.488 +	SharedMemoryInternal* pimple = new SharedMemoryInternal(hFileMapping, pFileView, minSize);
  74.489 +
  74.490 +	// If memory allocation fails,
  74.491 +	if (!pimple)
  74.492 +	{
  74.493 +        munmap(pFileView, minSize);
  74.494 +        close(hFileMapping);
  74.495 +
  74.496 +		OVR_DEBUG_LOG(("[SharedMemory] FAILURE: Out of memory"));
  74.497 +		return NULL;
  74.498 +	}
  74.499 +
  74.500 +	return pimple;
  74.501 +}
  74.502 +
  74.503 +SharedMemoryInternal* SharedMemoryInternal::AttemptOpenSharedMemory(const char* fileName, int minSize, bool openReadOnly)
  74.504 +{
  74.505 +    // Calculate permissions and flags based on read/write mode
  74.506 +    int flags = openReadOnly ? O_RDONLY : O_RDWR;
  74.507 +    int perms = openReadOnly ? S_IRUSR : (S_IRUSR | S_IWUSR);
  74.508 +
  74.509 +    // Attempt to open the shared memory file
  74.510 +    int hFileMapping = shm_open(fileName, flags, perms);
  74.511 +
  74.512 +    // If file was not opened successfully,
  74.513 +    if (hFileMapping < 0)
  74.514 +    {
  74.515 +		OVR_DEBUG_LOG(("[SharedMemory] WARNING: Unable to open file mapping for %s error code = %d (not necessarily bad)", fileName, errno));
  74.516 +		return NULL;
  74.517 +    }
  74.518 +
  74.519 +	// Map the file
  74.520 +	return DoFileMap(hFileMapping, fileName, openReadOnly, minSize);
  74.521 +}
  74.522 +
  74.523 +SharedMemoryInternal* SharedMemoryInternal::AttemptCreateSharedMemory(const char* fileName, int minSize, bool openReadOnly, bool allowRemoteWrite)
  74.524 +{
  74.525 +    // Create mode
  74.526 +    // Note: Cannot create the shared memory file read-only because then ftruncate() will fail.
  74.527 +    int flags = O_CREAT | O_RDWR;
  74.528 +
  74.529 +#ifndef OVR_ALLOW_CREATE_FILE_MAPPING_IF_EXISTS
  74.530 +    // Require exclusive access when creating (seems like a good idea without trying it yet..)
  74.531 +    if (shm_unlink(fileName) < 0)
  74.532 +    {
  74.533 +		OVR_DEBUG_LOG(("[SharedMemory] WARNING: Unable to unlink shared memory file %s error code = %d", fileName, errno));
  74.534 +    }
  74.535 +    flags |= O_EXCL;
  74.536 +#endif
  74.537 +
  74.538 +    // Set own read/write permissions
  74.539 +    int perms = openReadOnly ? S_IRUSR : (S_IRUSR|S_IWUSR);
  74.540 +
  74.541 +    // Allow other users to read/write the shared memory file
  74.542 +    perms |= allowRemoteWrite ? (S_IWGRP|S_IWOTH|S_IRGRP|S_IROTH) : (S_IRGRP|S_IROTH);
  74.543 +
  74.544 +    // Attempt to open the shared memory file
  74.545 +    int hFileMapping = shm_open(fileName, flags, perms);
  74.546 +
  74.547 +    // If file was not opened successfully,
  74.548 +    if (hFileMapping < 0)
  74.549 +    {
  74.550 +		OVR_DEBUG_LOG(("[SharedMemory] FAILURE: Unable to create file mapping for %s error code = %d", fileName, errno));
  74.551 +		return NULL;
  74.552 +    }
  74.553 +
  74.554 +    int truncRes = ftruncate(hFileMapping, minSize);
  74.555 +
  74.556 +    // If file was not opened successfully,
  74.557 +    if (truncRes < 0)
  74.558 +    {
  74.559 +        close(hFileMapping);
  74.560 +		OVR_DEBUG_LOG(("[SharedMemory] FAILURE: Unable to truncate file for %s to %d error code = %d", fileName, minSize, errno));
  74.561 +		return NULL;
  74.562 +    }
  74.563 +
  74.564 +	// Map the file
  74.565 +	return DoFileMap(hFileMapping, fileName, openReadOnly, minSize);
  74.566 +}
  74.567 +
  74.568 +SharedMemoryInternal* SharedMemoryInternal::CreateSharedMemory(const SharedMemory::OpenParameters& params)
  74.569 +{
  74.570 +	SharedMemoryInternal* retval = NULL;
  74.571 +
  74.572 +	// Construct the file mapping name in a Linux-specific way
  74.573 +	OVR::String fileMappingName = "/";
  74.574 +	fileMappingName += params.globalName;
  74.575 +	const char *fileName = fileMappingName.ToCStr();
  74.576 +
  74.577 +	// Is being opened read-only?
  74.578 +	const bool openReadOnly = (params.accessMode == SharedMemory::AccessMode_ReadOnly);
  74.579 +
  74.580 +	// Try up to 3 times to reduce low-probability failures:
  74.581 +	static const int ATTEMPTS_MAX = 3;
  74.582 +	for (int attempts = 0; attempts < ATTEMPTS_MAX; ++attempts)
  74.583 +	{
  74.584 +		// If opening should be attempted first,
  74.585 +		if (params.openMode != SharedMemory::OpenMode_CreateOnly)
  74.586 +		{
  74.587 +			// Attempt to open a shared memory map
  74.588 +			retval = AttemptOpenSharedMemory(fileName, params.minSizeBytes, openReadOnly);
  74.589 +
  74.590 +			// If successful,
  74.591 +			if (retval)
  74.592 +			{
  74.593 +				// Done!
  74.594 +				break;
  74.595 +			}
  74.596 +		}
  74.597 +
  74.598 +		// If creating the shared memory is also acceptable,
  74.599 +		if (params.openMode != SharedMemory::OpenMode_OpenOnly)
  74.600 +		{
  74.601 +            // Interpret create mode
  74.602 +            const bool allowRemoteWrite = (params.remoteMode == SharedMemory::RemoteMode_ReadWrite);
  74.603 +
  74.604 +            // Attempt to create a shared memory map
  74.605 +            retval = AttemptCreateSharedMemory(fileName, params.minSizeBytes, openReadOnly, allowRemoteWrite);
  74.606 +
  74.607 +            // If successful,
  74.608 +            if (retval)
  74.609 +            {
  74.610 +                // Done!
  74.611 +                break;
  74.612 +            }
  74.613 +		}
  74.614 +	} // Re-attempt create/open
  74.615 +
  74.616 +	// Note: On Windows the initial contents of the region are guaranteed to be zero.
  74.617 +	return retval;
  74.618 +}
  74.619 +
  74.620 +#endif // OVR_OS_LINUX
  74.621 +
  74.622 +
  74.623 +//// SharedMemory
  74.624 +
  74.625 +SharedMemory::SharedMemory(int size, void* data, SharedMemoryInternal* pInternal) :
  74.626 +	Size(size),
  74.627 +	Data(data),
  74.628 +	Internal(pInternal)
  74.629 +{
  74.630 +}
  74.631 +// Call close when it goes out of scope
  74.632 +SharedMemory::~SharedMemory()
  74.633 +{
  74.634 +	Close();
  74.635 +    delete Internal;
  74.636 +}
  74.637 +
  74.638 +void SharedMemory::Close()
  74.639 +{
  74.640 +	if (Internal)
  74.641 +	{
  74.642 +		delete Internal;
  74.643 +		Internal = NULL;
  74.644 +	}
  74.645 +}
  74.646 +
  74.647 +
  74.648 +//// SharedMemoryFactory
  74.649 +
  74.650 +Ptr<SharedMemory> SharedMemoryFactory::Open(const SharedMemory::OpenParameters& params)
  74.651 +{
  74.652 +	Ptr<SharedMemory> retval;
  74.653 +
  74.654 +	// If no name specified or no size requested,
  74.655 +	if (!params.globalName || (params.minSizeBytes <= 0))
  74.656 +	{
  74.657 +		OVR_DEBUG_LOG(("[SharedMemory] FAILURE: Invalid parameters to Create()"));
  74.658 +		return NULL;
  74.659 +	}
  74.660 +
  74.661 +	OVR_DEBUG_LOG(("[SharedMemory] Creating shared memory region: %s > %d bytes",
  74.662 +		params.globalName, params.minSizeBytes));
  74.663 +
  74.664 +	// Attempt to create a shared memory region from the parameters
  74.665 +	SharedMemoryInternal* pInternal = SharedMemoryInternal::CreateSharedMemory(params);
  74.666 +
  74.667 +	if (pInternal)
  74.668 +	{
  74.669 +		// Create the wrapper object
  74.670 +		retval = *new SharedMemory(params.minSizeBytes, pInternal->FileView, pInternal);
  74.671 +	}
  74.672 +
  74.673 +	return retval;
  74.674 +}
  74.675 +
  74.676 +SharedMemoryFactory::SharedMemoryFactory()
  74.677 +{
  74.678 +	OVR_DEBUG_LOG(("[SharedMemory] Creating factory"));
  74.679 +
  74.680 +    PushDestroyCallbacks();
  74.681 +}
  74.682 +
  74.683 +SharedMemoryFactory::~SharedMemoryFactory()
  74.684 +{
  74.685 +	OVR_DEBUG_LOG(("[SharedMemory] Destroying factory"));
  74.686 +}
  74.687 +
  74.688 +void SharedMemoryFactory::OnSystemDestroy()
  74.689 +{
  74.690 +    delete this;
  74.691 +}
  74.692 +
  74.693 +
  74.694 +} // namespace OVR
    75.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    75.2 +++ b/LibOVR/Src/Kernel/OVR_SharedMemory.h	Wed Jan 14 06:51:16 2015 +0200
    75.3 @@ -0,0 +1,240 @@
    75.4 +/************************************************************************************
    75.5 +
    75.6 +PublicHeader:   OVR
    75.7 +Filename    :   OVR_SharedMemory.h
    75.8 +Content     :   Inter-process shared memory subsystem
    75.9 +Created     :   June 1, 2014
   75.10 +Notes       : 
   75.11 +
   75.12 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   75.13 +
   75.14 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
   75.15 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
   75.16 +which is provided at the time of installation or download, or which 
   75.17 +otherwise accompanies this software in either electronic or hard copy form.
   75.18 +
   75.19 +You may obtain a copy of the License at
   75.20 +
   75.21 +http://www.oculusvr.com/licenses/LICENSE-3.2 
   75.22 +
   75.23 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
   75.24 +distributed under the License is distributed on an "AS IS" BASIS,
   75.25 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   75.26 +See the License for the specific language governing permissions and
   75.27 +limitations under the License.
   75.28 +
   75.29 +************************************************************************************/
   75.30 +
   75.31 +#ifndef OVR_SharedMemory_h
   75.32 +#define OVR_SharedMemory_h
   75.33 +
   75.34 +#include "OVR_Types.h"
   75.35 +#include "OVR_RefCount.h"
   75.36 +#include "OVR_Allocator.h"
   75.37 +#include "OVR_System.h"
   75.38 +
   75.39 +#ifdef OVR_SINGLE_PROCESS /* Everything running in one process usually for debugging */
   75.40 +#define OVR_FAKE_SHAREDMEMORY /* Single-process version to avoid admin privs */
   75.41 +#endif
   75.42 +
   75.43 +namespace OVR {
   75.44 +
   75.45 +class SharedMemoryInternal; // Opaque
   75.46 +
   75.47 +
   75.48 +// SharedMemory
   75.49 +// Note: Safe when used between 32-bit and 64-bit processes
   75.50 +class SharedMemory : public RefCountBase<SharedMemory>
   75.51 +{
   75.52 +	friend class SharedMemoryFactory;
   75.53 +
   75.54 +	OVR_NON_COPYABLE(SharedMemory);
   75.55 +
   75.56 +public:
   75.57 +	// Only constructed by the SharedMemory Factory
   75.58 +    SharedMemory(int size, void* data, SharedMemoryInternal* pInternal);
   75.59 +	// Call close when it goes out of scope
   75.60 +    ~SharedMemory();
   75.61 +
   75.62 +	// Modes for opening a new shared memory region
   75.63 +	enum OpenMode
   75.64 +	{
   75.65 +		// Note: On Windows, Create* requires Administrator priviledges or running as a Service.
   75.66 +		OpenMode_CreateOnly,		// Must not already exist
   75.67 +		OpenMode_OpenOnly,			// Must already exist
   75.68 +		OpenMode_CreateOrOpen		// May exist or not
   75.69 +	};
   75.70 +
   75.71 +	// Local access restrictions
   75.72 +	enum AccessMode
   75.73 +	{
   75.74 +		AccessMode_ReadOnly,		// Acquire read-only access
   75.75 +		AccessMode_ReadWrite,		// Acquire read or write access
   75.76 +	};
   75.77 +
   75.78 +	// Remote access restrictions
   75.79 +	enum RemoteMode
   75.80 +	{
   75.81 +		RemoteMode_ReadOnly,		// Other processes will need to open in read-only mode
   75.82 +		RemoteMode_ReadWrite		// Other processes can open in read-write mode
   75.83 +	};
   75.84 +
   75.85 +	// Modes for opening a new shared memory region
   75.86 +	struct OpenParameters
   75.87 +	{
   75.88 +		OpenParameters() :
   75.89 +			globalName(NULL),
   75.90 +			minSizeBytes(0),
   75.91 +			openMode(SharedMemory::OpenMode_CreateOrOpen),
   75.92 +			remoteMode(SharedMemory::RemoteMode_ReadWrite),
   75.93 +			accessMode(SharedMemory::AccessMode_ReadWrite)
   75.94 +		{
   75.95 +		}
   75.96 +
   75.97 +		// Creation parameters
   75.98 +		const char*					globalName;		// Name of the shared memory region
   75.99 +		int							minSizeBytes;	// Minimum number of bytes to request
  75.100 +		SharedMemory::OpenMode		openMode;		// Creating the file or opening the file?
  75.101 +		SharedMemory::RemoteMode	remoteMode;		// When creating, what access should other processes get?
  75.102 +		SharedMemory::AccessMode	accessMode;		// When opening/creating, what access should this process get?
  75.103 +	};
  75.104 +
  75.105 +public:
  75.106 +	// Returns the size of the shared memory region
  75.107 +	int GetSizeI() const
  75.108 +	{
  75.109 +		return Size;
  75.110 +	}
  75.111 +
  75.112 +	// Returns the process-local pointer to the shared memory region
  75.113 +	// Note: This may be different on different processes
  75.114 +	void* GetData() const
  75.115 +	{
  75.116 +		return Data;
  75.117 +	}
  75.118 +
  75.119 +protected:
  75.120 +	int Size;		// How many shared bytes are shared at the pointer address?
  75.121 +	void* Data;		// Pointer to the shared memory region.
  75.122 +
  75.123 +	// Hidden implementation class for OS-specific behavior
  75.124 +	SharedMemoryInternal* Internal;
  75.125 +
  75.126 +	// Close and cleanup the shared memory region
  75.127 +	// Note: This is called on destruction
  75.128 +	void Close();
  75.129 +};
  75.130 +
  75.131 +
  75.132 +// SharedMemoryFactory
  75.133 +class SharedMemoryFactory : public NewOverrideBase, public SystemSingletonBase<SharedMemoryFactory>
  75.134 +{
  75.135 +    OVR_DECLARE_SINGLETON(SharedMemoryFactory);
  75.136 +
  75.137 +public:
  75.138 +    // Construct a SharedMemory object.
  75.139 +	// Note: The new object is reference-counted so it should be stored with Ptr<>.  Initial reference count is 1.
  75.140 +	Ptr<SharedMemory> Open(const SharedMemory::OpenParameters&);
  75.141 +};
  75.142 +
  75.143 +
  75.144 +// A shared object
  75.145 +// Its constructor will be called when creating a writer
  75.146 +// Its destructor will not be called
  75.147 +template<class SharedType>
  75.148 +class ISharedObject : public NewOverrideBase
  75.149 +{
  75.150 +public:
  75.151 +	static const int RegionSize = (int)sizeof(SharedType);
  75.152 +
  75.153 +protected:
  75.154 +	Ptr<SharedMemory> pSharedMemory;
  75.155 +
  75.156 +	bool Open(const char* name, bool readOnly)
  75.157 +	{
  75.158 +		// Configure open parameters based on read-only mode
  75.159 +		SharedMemory::OpenParameters params;
  75.160 +
  75.161 +        // FIXME: This is a hack.  We currently need to allow clients to open this for read-write even
  75.162 +        // though they only need read-only access.  This is because in the first 0.4 release the
  75.163 +        // LocklessUpdater class technically writes to it (increments by 0) to read from the space.
  75.164 +        // This was quickly corrected in 0.4.1 and we are waiting for the right time to disallow write
  75.165 +        // access when everyone upgrades to 0.4.1+.
  75.166 +        //params.remoteMode = SharedMemory::RemoteMode_ReadOnly;
  75.167 +        params.remoteMode = SharedMemory::RemoteMode_ReadWrite;
  75.168 +
  75.169 +        params.globalName = name;
  75.170 +        params.accessMode = readOnly ? SharedMemory::AccessMode_ReadOnly : SharedMemory::AccessMode_ReadWrite;
  75.171 +        params.minSizeBytes = RegionSize;
  75.172 +		params.openMode = readOnly ? SharedMemory::OpenMode_OpenOnly : SharedMemory::OpenMode_CreateOrOpen;
  75.173 +
  75.174 +		// Attempt to open the shared memory file
  75.175 +		pSharedMemory = SharedMemoryFactory::GetInstance()->Open(params);
  75.176 +
  75.177 +		// If it was not able to be opened,
  75.178 +		if (pSharedMemory && pSharedMemory->GetSizeI() >= RegionSize && pSharedMemory->GetData())
  75.179 +		{
  75.180 +			// If writing,
  75.181 +			if (!readOnly)
  75.182 +			{
  75.183 +				// Construct the object also
  75.184 +				Construct<SharedType>(pSharedMemory->GetData());
  75.185 +			}
  75.186 +
  75.187 +			return true;
  75.188 +		}
  75.189 +
  75.190 +		return false;
  75.191 +	}
  75.192 +
  75.193 +	SharedType* Get() const
  75.194 +	{
  75.195 +		if (!pSharedMemory)
  75.196 +		{
  75.197 +			return NULL;
  75.198 +		}
  75.199 +
  75.200 +		void* data = pSharedMemory->GetData();
  75.201 +		if (!data)
  75.202 +		{
  75.203 +			return NULL;
  75.204 +		}
  75.205 +
  75.206 +		return reinterpret_cast<SharedType*>(data);
  75.207 +	}
  75.208 +};
  75.209 +
  75.210 +// Writer specialized shared object: Ctor will be called on Open()
  75.211 +template<class SharedType>
  75.212 +class SharedObjectWriter : public ISharedObject<SharedType>
  75.213 +{
  75.214 +public:
  75.215 +	OVR_FORCE_INLINE bool Open(const char* name)
  75.216 +	{
  75.217 +		return ISharedObject<SharedType>::Open(name, false);
  75.218 +	}
  75.219 +	OVR_FORCE_INLINE SharedType* Get()
  75.220 +	{
  75.221 +		return ISharedObject<SharedType>::Get();
  75.222 +	}
  75.223 +};
  75.224 +
  75.225 +// Reader specialized shared object: Ctor will not be called
  75.226 +template<class SharedType>
  75.227 +class SharedObjectReader : public ISharedObject<SharedType>
  75.228 +{
  75.229 +public:
  75.230 +	OVR_FORCE_INLINE bool Open(const char* name)
  75.231 +	{
  75.232 +		return ISharedObject<SharedType>::Open(name, true);
  75.233 +	}
  75.234 +	OVR_FORCE_INLINE const SharedType* Get() const
  75.235 +	{
  75.236 +		return ISharedObject<SharedType>::Get();
  75.237 +	}
  75.238 +};
  75.239 +
  75.240 +
  75.241 +} // namespace OVR
  75.242 +
  75.243 +#endif // OVR_SharedMemory_h
    76.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    76.2 +++ b/LibOVR/Src/Kernel/OVR_Std.cpp	Wed Jan 14 06:51:16 2015 +0200
    76.3 @@ -0,0 +1,1097 @@
    76.4 +/************************************************************************************
    76.5 +
    76.6 +Filename    :   OVR_Std.cpp
    76.7 +Content     :   Standard C function implementation
    76.8 +Created     :   September 19, 2012
    76.9 +Notes       : 
   76.10 +
   76.11 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   76.12 +
   76.13 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
   76.14 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
   76.15 +which is provided at the time of installation or download, or which 
   76.16 +otherwise accompanies this software in either electronic or hard copy form.
   76.17 +
   76.18 +You may obtain a copy of the License at
   76.19 +
   76.20 +http://www.oculusvr.com/licenses/LICENSE-3.2 
   76.21 +
   76.22 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
   76.23 +distributed under the License is distributed on an "AS IS" BASIS,
   76.24 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   76.25 +See the License for the specific language governing permissions and
   76.26 +limitations under the License.
   76.27 +
   76.28 +************************************************************************************/
   76.29 +
   76.30 +#include "OVR_Std.h"
   76.31 +#include "OVR_Alg.h"
   76.32 +
   76.33 +// localeconv() call in OVR_strtod()
   76.34 +#include <locale.h>
   76.35 +
   76.36 +namespace OVR {
   76.37 +
   76.38 +// Source for functions not available on all platforms is included here.
   76.39 +
   76.40 +size_t OVR_CDECL OVR_strlcpy(char* dest, const char* src, size_t destsize)
   76.41 +{
   76.42 +    const char* s = src;
   76.43 +    size_t      n = destsize;
   76.44 +
   76.45 +    if(n && --n)
   76.46 +    {
   76.47 +        do{
   76.48 +            if((*dest++ = *s++) == 0)
   76.49 +                break;
   76.50 +        } while(--n);
   76.51 +    }
   76.52 +
   76.53 +    if(!n)
   76.54 +    {
   76.55 +        if(destsize)
   76.56 +            *dest = 0;
   76.57 +        while(*s++)
   76.58 +            { }
   76.59 +    }
   76.60 +
   76.61 +    return (size_t)((s - src) - 1);
   76.62 +}
   76.63 +
   76.64 +
   76.65 +size_t OVR_CDECL OVR_strlcat(char* dest, const char* src, size_t destsize)
   76.66 +{
   76.67 +    const size_t d = destsize ? OVR_strlen(dest) : 0;
   76.68 +    const size_t s = OVR_strlen(src);
   76.69 +    const size_t t = s + d;
   76.70 +
   76.71 +    OVR_ASSERT((destsize == 0) || (d < destsize));
   76.72 +
   76.73 +    if(t < destsize)
   76.74 +        memcpy(dest + d, src, (s + 1) * sizeof(*src));
   76.75 +    else
   76.76 +    {
   76.77 +        if(destsize)
   76.78 +        {
   76.79 +            memcpy(dest + d, src, ((destsize - d) - 1) * sizeof(*src));
   76.80 +            dest[destsize - 1] = 0;
   76.81 +        }
   76.82 +    }
   76.83 +
   76.84 +    return t;
   76.85 +}
   76.86 +
   76.87 +
   76.88 +// Case insensitive compare implemented in platform-specific way.
   76.89 +int OVR_CDECL OVR_stricmp(const char* a, const char* b)
   76.90 +{
   76.91 +#if defined(OVR_OS_MS)
   76.92 +    #if defined(OVR_CC_MSVC) && (OVR_CC_MSVC >= 1400)
   76.93 +        return ::_stricmp(a, b);
   76.94 +    #else
   76.95 +        return ::stricmp(a, b);
   76.96 +    #endif
   76.97 +
   76.98 +#else
   76.99 +    return strcasecmp(a, b);
  76.100 +#endif
  76.101 +}
  76.102 +
  76.103 +int OVR_CDECL OVR_strnicmp(const char* a, const char* b, size_t count)
  76.104 +{
  76.105 +#if defined(OVR_OS_MS)
  76.106 +    #if defined(OVR_CC_MSVC) && (OVR_CC_MSVC >= 1400)
  76.107 +        return ::_strnicmp(a, b, count);
  76.108 +    #else
  76.109 +        return ::strnicmp(a, b, count);
  76.110 +    #endif
  76.111 +
  76.112 +#else
  76.113 +    return strncasecmp(a, b, count);
  76.114 +#endif
  76.115 +}
  76.116 +
  76.117 +wchar_t* OVR_CDECL OVR_wcscpy(wchar_t* dest, size_t destsize, const wchar_t* src)
  76.118 +{
  76.119 +#if defined(OVR_MSVC_SAFESTRING)
  76.120 +    wcscpy_s(dest, destsize, src);
  76.121 +    return dest;
  76.122 +#elif defined(OVR_OS_MS)
  76.123 +    OVR_UNUSED(destsize);
  76.124 +    wcscpy(dest, src);
  76.125 +    return dest;
  76.126 +#else
  76.127 +    size_t l = OVR_wcslen(src) + 1; // incl term null
  76.128 +    l = (l < destsize) ? l : destsize;
  76.129 +    memcpy(dest, src, l * sizeof(wchar_t));
  76.130 +    return dest;
  76.131 +#endif
  76.132 +}
  76.133 +
  76.134 +wchar_t* OVR_CDECL OVR_wcsncpy(wchar_t* dest, size_t destsize, const wchar_t* src, size_t count)
  76.135 +{
  76.136 +#if defined(OVR_MSVC_SAFESTRING)
  76.137 +    wcsncpy_s(dest, destsize, src, count);
  76.138 +    return dest;
  76.139 +#else
  76.140 +    size_t srclen = OVR_wcslen(src);
  76.141 +    size_t l = Alg::Min(srclen, count);
  76.142 +    l = (l < destsize) ? l : destsize;
  76.143 +    memcpy(dest, src, l * sizeof(wchar_t));
  76.144 +    if (count > srclen)
  76.145 +    {
  76.146 +        size_t remLen = Alg::Min(destsize - l, (count - srclen));
  76.147 +        memset(&dest[l], 0, sizeof(wchar_t)*remLen);
  76.148 +    }
  76.149 +    else if (l < destsize)
  76.150 +        dest[l] = 0;
  76.151 +    return dest;
  76.152 +#endif
  76.153 +}
  76.154 +
  76.155 +
  76.156 +wchar_t* OVR_CDECL OVR_wcscat(wchar_t* dest, size_t destsize, const wchar_t* src)
  76.157 +{
  76.158 +#if defined(OVR_MSVC_SAFESTRING)
  76.159 +    wcscat_s(dest, destsize, src);
  76.160 +    return dest;
  76.161 +#elif defined(OVR_OS_MS)
  76.162 +    OVR_UNUSED(destsize);
  76.163 +    wcscat(dest, src);
  76.164 +    return dest;
  76.165 +#else
  76.166 +    size_t dstlen = OVR_wcslen(dest); // do not incl term null
  76.167 +    size_t srclen = OVR_wcslen(src) + 1; // incl term null
  76.168 +    size_t copylen = (dstlen + srclen < destsize) ? srclen : destsize - dstlen;
  76.169 +    memcpy(dest + dstlen, src, copylen * sizeof(wchar_t));
  76.170 +    return dest;
  76.171 +#endif
  76.172 +}
  76.173 +
  76.174 +size_t  OVR_CDECL OVR_wcslen(const wchar_t* str)
  76.175 +{
  76.176 +#if defined(OVR_OS_MS)
  76.177 +    return wcslen(str);
  76.178 +#else
  76.179 +    size_t i = 0;
  76.180 +    while(str[i] != '\0')
  76.181 +        ++i;
  76.182 +    return i;
  76.183 +#endif
  76.184 +}
  76.185 +
  76.186 +int OVR_CDECL OVR_wcscmp(const wchar_t* a, const wchar_t* b)
  76.187 +{
  76.188 +#if defined(OVR_OS_MS) || defined(OVR_OS_LINUX)
  76.189 +    return wcscmp(a, b);
  76.190 +#else
  76.191 +    // not supported, use custom implementation
  76.192 +    const wchar_t *pa = a, *pb = b;
  76.193 +    while (*pa && *pb)
  76.194 +    {
  76.195 +        wchar_t ca = *pa;
  76.196 +        wchar_t cb = *pb;
  76.197 +        if (ca < cb)
  76.198 +            return -1;
  76.199 +        else if (ca > cb)
  76.200 +            return 1;
  76.201 +        pa++;
  76.202 +        pb++;
  76.203 +    }
  76.204 +    if (*pa)
  76.205 +        return 1;
  76.206 +    else if (*pb)
  76.207 +        return -1;
  76.208 +    else
  76.209 +        return 0;
  76.210 +#endif
  76.211 +}
  76.212 +
  76.213 +int OVR_CDECL OVR_wcsicmp(const wchar_t* a, const wchar_t* b)
  76.214 +{
  76.215 +#if defined(OVR_OS_MS)
  76.216 +    #if defined(OVR_CC_MSVC) && (OVR_CC_MSVC >= 1400)
  76.217 +        return ::_wcsicmp(a, b);
  76.218 +    #else
  76.219 +        return ::wcsicmp(a, b);
  76.220 +    #endif
  76.221 +#elif defined(OVR_OS_MAC) || defined(__CYGWIN__) || defined(OVR_OS_ANDROID) || defined(OVR_OS_IPHONE)
  76.222 +    // not supported, use custom implementation
  76.223 +    const wchar_t *pa = a, *pb = b;
  76.224 +    while (*pa && *pb)
  76.225 +    {
  76.226 +        wchar_t ca = OVR_towlower(*pa);
  76.227 +        wchar_t cb = OVR_towlower(*pb);
  76.228 +        if (ca < cb)
  76.229 +            return -1;
  76.230 +        else if (ca > cb)
  76.231 +            return 1;
  76.232 +        pa++;
  76.233 +        pb++;
  76.234 +    }
  76.235 +    if (*pa)
  76.236 +        return 1;
  76.237 +    else if (*pb)
  76.238 +        return -1;
  76.239 +    else
  76.240 +        return 0;
  76.241 +#else
  76.242 +    return wcscasecmp(a, b);
  76.243 +#endif
  76.244 +}
  76.245 +
  76.246 +// This function is not inline because of dependency on <locale.h>
  76.247 +double OVR_CDECL OVR_strtod(const char* str, char** tailptr)
  76.248 +{
  76.249 +#if !defined(OVR_OS_ANDROID) // The Android C library doesn't have localeconv.
  76.250 +    const char s = *localeconv()->decimal_point;
  76.251 +
  76.252 +    if (s != '.') // If the C library is using a locale that is not using '.' as a decimal point, we convert the input str's '.' chars to the char that the C library expects (e.g. ',' or ' ').
  76.253 +    {
  76.254 +        char buffer[347 + 1];
  76.255 +
  76.256 +        OVR_strcpy(buffer, sizeof(buffer), str);
  76.257 +
  76.258 +        // Ensure null-termination of string
  76.259 +        buffer[sizeof(buffer)-1] = '\0';
  76.260 +
  76.261 +        for (char* c = buffer; *c != '\0'; ++c)
  76.262 +        {
  76.263 +            if (*c == '.')
  76.264 +            {
  76.265 +                *c = s;
  76.266 +                break;
  76.267 +            }
  76.268 +        }
  76.269 +
  76.270 +        char *nextPtr = NULL;
  76.271 +        double retval = strtod(buffer, &nextPtr);
  76.272 +
  76.273 +        // If a tail pointer is requested,
  76.274 +        if (tailptr)
  76.275 +        {
  76.276 +            // Return a tail pointer that points to the same offset as nextPtr, in the orig string
  76.277 +            *tailptr = !nextPtr ? NULL : (char*)str + (int)(nextPtr - buffer);
  76.278 +        }
  76.279 +
  76.280 +        return retval;
  76.281 +    }
  76.282 +#endif
  76.283 +
  76.284 +    return strtod(str, tailptr);
  76.285 +}
  76.286 +
  76.287 +
  76.288 +#ifndef OVR_NO_WCTYPE
  76.289 +
  76.290 +//// Use this class to generate Unicode bitsets. For example:
  76.291 +////
  76.292 +//// UnicodeBitSet bitSet;
  76.293 +//// for(unsigned i = 0; i < 65536; ++i)
  76.294 +//// {
  76.295 +////     if (iswalpha(i))
  76.296 +////         bitSet.Set(i);
  76.297 +//// }
  76.298 +//// bitSet.Dump();
  76.299 +////
  76.300 +////---------------------------------------------------------------
  76.301 +//class UnicodeBitSet
  76.302 +//{
  76.303 +//public:
  76.304 +//    UnicodeBitSet()
  76.305 +//    {
  76.306 +//        memset(Offsets, 0, sizeof(Offsets));
  76.307 +//        memset(Bits,    0, sizeof(Bits));
  76.308 +//    }
  76.309 +//
  76.310 +//    void Set(unsigned bit) { Bits[bit >> 8][(bit >> 4) & 15] |= 1 << (bit & 15); }
  76.311 +//
  76.312 +//    void Dump()
  76.313 +//    {
  76.314 +//        unsigned i, j;
  76.315 +//        unsigned offsetCount = 0;
  76.316 +//        for(i = 0; i < 256; ++i)
  76.317 +//        {
  76.318 +//            if (isNull(i)) Offsets[i] = 0;
  76.319 +//            else
  76.320 +//            if (isFull(i)) Offsets[i] = 1;
  76.321 +//            else           Offsets[i] = uint16_t(offsetCount++ * 16 + 256);
  76.322 +//        }
  76.323 +//        for(i = 0; i < 16; ++i)
  76.324 +//        {
  76.325 +//            for(j = 0; j < 16; ++j)
  76.326 +//            {
  76.327 +//                printf("%5u,", Offsets[i*16+j]);
  76.328 +//            }
  76.329 +//            printf("\n");
  76.330 +//        }
  76.331 +//        for(i = 0; i < 256; ++i)
  76.332 +//        {
  76.333 +//            if (Offsets[i] > 255)
  76.334 +//            {
  76.335 +//                for(j = 0; j < 16; j++)
  76.336 +//                {
  76.337 +//                    printf("%5u,", Bits[i][j]);
  76.338 +//                }
  76.339 +//                printf("\n");
  76.340 +//            }
  76.341 +//        }
  76.342 +//    }
  76.343 +//
  76.344 +//private:
  76.345 +//    bool isNull(unsigned n) const
  76.346 +//    {
  76.347 +//        const uint16_t* p = Bits[n];
  76.348 +//        for(unsigned i = 0; i < 16; ++i)
  76.349 +//            if (p[i] != 0) return false;
  76.350 +//        return true;
  76.351 +//    }
  76.352 +//
  76.353 +//    bool isFull(unsigned n) const
  76.354 +//    {
  76.355 +//        const uint16_t* p = Bits[n];
  76.356 +//        for(unsigned i = 0; i < 16; ++i)
  76.357 +//            if (p[i] != 0xFFFF) return false;
  76.358 +//        return true;
  76.359 +//    }
  76.360 +//
  76.361 +//    uint16_t Offsets[256];
  76.362 +//    uint16_t Bits[256][16];
  76.363 +//};
  76.364 +
  76.365 +
  76.366 +const uint16_t UnicodeAlnumBits[] = {
  76.367 +  256,    1,  272,  288,  304,  320,  336,  352,    0,  368,  384,  400,  416,  432,  448,  464,
  76.368 +  480,  496,  512,  528,  544,    1,  560,  576,  592,    0,    0,    0,    0,    0,  608,  624,
  76.369 +  640,  656,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.370 +  672,  688,    0,    0,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
  76.371 +    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,  704,    1,    1,
  76.372 +    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
  76.373 +    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
  76.374 +    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
  76.375 +    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
  76.376 +    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,  720,
  76.377 +    1,    1,    1,    1,  736,    0,    0,    0,    0,    0,    0,    0,    1,    1,    1,    1,
  76.378 +    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
  76.379 +    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
  76.380 +    1,    1,    1,    1,    1,    1,    1,  752,    0,    0,    0,    0,    0,    0,    0,    0,
  76.381 +    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.382 +    0,    0,    0,    0,    0,    0,    0,    0,    0,    1,  768,  784,    1,  800,  816,  832,
  76.383 +    0,    0,    0, 1023,65534, 2047,65534, 2047,    0,    0,    0,  524,65535,65407,65535,65407,
  76.384 +65535,65535,65532,   15,    0,65535,65535,65535,65535,65535,16383,63999,    3,    0,16415,    0,
  76.385 +    0,    0,    0,    0,   32,    0,    0, 1024,55104,65535,65531,65535,32767,64767,65535,   15,
  76.386 +65535,65535,65535,65535,65535,65535,65535,65535,61443,65535,65535,65535, 6559,65535,65535,  831,
  76.387 +    0,    0,    0,65534,65535,  639,65534,65535,  255,    0,    0,    0,    0,65535, 2047,    7,
  76.388 +    0,    0,65534, 2047,65534,   63, 1023,65535,65535,65535,65535,65535,65535, 8175, 8702, 8191,
  76.389 +    0,65535, 8191,65535,    0,    0,    0,    0,65535,65535,65535,    1,    0,    0,    0,    0,
  76.390 +65518,65535,65535,58367, 8191,65281,65487,    0,40942,65529,65023,50117, 6559,45184,65487,    3,
  76.391 +34788,65529,65023,50029, 6535,24064,65472,   31,45038,65531,65023,58349, 7103,    1,65473,    0,
  76.392 +40942,65529,65023,58317, 6543,45248,65475,    0,51180,54845,50968,50111, 7623,  128,65408,    0,
  76.393 +57326,65533,65023,50159, 7647,   96,65475,    0,57324,65533,65023,50159, 7647,16480,65475,    0,
  76.394 +57324,65533,65023,50175, 7631,  128,65475,    0,65516,64639,65535,12283,32895,65375,    0,   12,
  76.395 +65534,65535,65535, 2047,32767, 1023,    0,    0, 9622,65264,60590,15359, 8223,13311,    0,    0,
  76.396 +    1,    0, 1023,    0,65279,65535, 2047,65534, 3843,65279,65535, 8191,    0,    0,    0,    0,
  76.397 +65535,65535,63227,  327, 1023, 1023,    0,    0,    0,    0,65535,65535,   63,65535,65535,  127,
  76.398 +65535,65535,65535,65535,65535,33791,65535,65535,65535,65535,65287,65535,65535,65535,65535, 1023,
  76.399 +65407,65535,65535,65535,15743,15743,65535,65535,15743,65535,32767,32573,32573,65407,32767,65535,
  76.400 +32767,32573,65535,65535,65407, 2047,65024,    3,    0,    0,65535,65535,65535,65535,65535,   31,
  76.401 +65534,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,
  76.402 +65535,65535,65535,65535,65535,65535,40959,  127,65534, 2047,65535,65535,65535,65535, 2047,    0,
  76.403 +    0,    0,    0,    0,    0,    0,    0,    0,65535,65535,65535,65535,  511,    0, 1023,    0,
  76.404 +    0, 1023,65535,65535,65527,65535,65535,  255,65535,65535, 1023,    0,    0,    0,    0,    0,
  76.405 +65535,65535,65535,65535,65535,65535,65535,65535,65535, 4095,65535,65535,65535,65535,65535, 1023,
  76.406 +65535,16191,65535,65535,16191,43775,65535,16383,65535,65535,65535,24543, 8156, 4047, 8191, 8156,
  76.407 +    0,    0,    0,    0,    0,    0,    0,32768,    0,    0,    0,    0,    0,    0,    0,    0,
  76.408 +64644,15919,48464, 1019,    0,    0,65535,65535,   15,    0,    0,    0,    0,    0,    0,    0,
  76.409 +  192,    0, 1022, 1792,65534,65535,65535,65535,65535,   31,65534,65535,65535,65535,65535, 2047,
  76.410 +65504,65535, 8191,65534,65535,65535,65535,65535,32767,    0,65535,  255,    0,    0,    0,    0,
  76.411 +65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,   63,    0,    0,    0,    0,
  76.412 +65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,   63,    0,    0,    0,    0,    0,
  76.413 +65535,65535,65535,65535,65535,65535,65535,65535, 8191,    0,    0,    0,    0,    0,    0,    0,
  76.414 +65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,   15,    0,    0,    0,    0,    0,
  76.415 +65535,65535,16383,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.416 +  127,41208,65023,24447,65499,65535,65535,65535,65535,65535,65535,    3,    0,65528,65535,65535,
  76.417 +65535,65535,65535,16383,    0,65535,65535,65535,65535,65532,65535,65535,  255,    0,    0, 4095,
  76.418 +    0,    0,    0,    0,    0,    0,    0,65495,65535,65535,65535,65535,65535,65535,65535, 8191,
  76.419 +    0, 1023,65534, 2047,65534, 2047,65472,65534,65535,16383,65535,32767,64764, 7420,    0,    0};
  76.420 +
  76.421 +const uint16_t UnicodeAlphaBits[] = {
  76.422 +  256,    1,  272,  288,  304,  320,  336,  352,    0,  368,  384,  400,  416,  432,  448,  464,
  76.423 +  480,  496,  512,  528,  544,    1,  560,  576,  592,    0,    0,    0,    0,    0,  608,  624,
  76.424 +  640,  656,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.425 +  672,  688,    0,    0,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
  76.426 +    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,  704,    1,    1,
  76.427 +    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
  76.428 +    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
  76.429 +    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
  76.430 +    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
  76.431 +    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,  720,
  76.432 +    1,    1,    1,    1,  736,    0,    0,    0,    0,    0,    0,    0,    1,    1,    1,    1,
  76.433 +    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
  76.434 +    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
  76.435 +    1,    1,    1,    1,    1,    1,    1,  752,    0,    0,    0,    0,    0,    0,    0,    0,
  76.436 +    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.437 +    0,    0,    0,    0,    0,    0,    0,    0,    0,    1,  768,  784,    1,  800,  816,  832,
  76.438 +    0,    0,    0,    0,65534, 2047,65534, 2047,    0,    0,    0,    0,65535,65407,65535,65407,
  76.439 +65535,65535,65532,   15,    0,65535,65535,65535,65535,65535,16383,63999,    3,    0,16415,    0,
  76.440 +    0,    0,    0,    0,   32,    0,    0, 1024,55104,65535,65531,65535,32767,64767,65535,   15,
  76.441 +65535,65535,65535,65535,65535,65535,65535,65535,61443,65535,65535,65535, 6559,65535,65535,  831,
  76.442 +    0,    0,    0,65534,65535,  639,65534,65535,  255,    0,    0,    0,    0,65535, 2047,    7,
  76.443 +    0,    0,65534, 2047,65534,   63,    0,65535,65535,65535,65535,65535,65535, 8175, 8702, 7168,
  76.444 +    0,65535, 8191,65535,    0,    0,    0,    0,65535,65535,65535,    1,    0,    0,    0,    0,
  76.445 +65518,65535,65535,58367, 8191,65281,   15,    0,40942,65529,65023,50117, 6559,45184,   15,    3,
  76.446 +34788,65529,65023,50029, 6535,24064,    0,   31,45038,65531,65023,58349, 7103,    1,    1,    0,
  76.447 +40942,65529,65023,58317, 6543,45248,    3,    0,51180,54845,50968,50111, 7623,  128,    0,    0,
  76.448 +57326,65533,65023,50159, 7647,   96,    3,    0,57324,65533,65023,50159, 7647,16480,    3,    0,
  76.449 +57324,65533,65023,50175, 7631,  128,    3,    0,65516,64639,65535,12283,32895,65375,    0,   12,
  76.450 +65534,65535,65535, 2047,32767,    0,    0,    0, 9622,65264,60590,15359, 8223,12288,    0,    0,
  76.451 +    1,    0,    0,    0,65279,65535, 2047,65534, 3843,65279,65535, 8191,    0,    0,    0,    0,
  76.452 +65535,65535,63227,  327,    0, 1023,    0,    0,    0,    0,65535,65535,   63,65535,65535,  127,
  76.453 +65535,65535,65535,65535,65535,33791,65535,65535,65535,65535,65287,65535,65535,65535,65535, 1023,
  76.454 +65407,65535,65535,65535,15743,15743,65535,65535,15743,65535,32767,32573,32573,65407,32767,65535,
  76.455 +32767,32573,65535,65535,65407, 2047,    0,    0,    0,    0,65535,65535,65535,65535,65535,   31,
  76.456 +65534,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,
  76.457 +65535,65535,65535,65535,65535,65535,40959,  127,65534, 2047,65535,65535,65535,65535, 2047,    0,
  76.458 +    0,    0,    0,    0,    0,    0,    0,    0,65535,65535,65535,65535,  511,    0,    0,    0,
  76.459 +    0,    0,65535,65535,65527,65535,65535,  255,65535,65535, 1023,    0,    0,    0,    0,    0,
  76.460 +65535,65535,65535,65535,65535,65535,65535,65535,65535, 4095,65535,65535,65535,65535,65535, 1023,
  76.461 +65535,16191,65535,65535,16191,43775,65535,16383,65535,65535,65535,24543, 8156, 4047, 8191, 8156,
  76.462 +    0,    0,    0,    0,    0,    0,    0,32768,    0,    0,    0,    0,    0,    0,    0,    0,
  76.463 +64644,15919,48464, 1019,    0,    0,65535,65535,   15,    0,    0,    0,    0,    0,    0,    0,
  76.464 +  192,    0, 1022, 1792,65534,65535,65535,65535,65535,   31,65534,65535,65535,65535,65535, 2047,
  76.465 +65504,65535, 8191,65534,65535,65535,65535,65535,32767,    0,65535,  255,    0,    0,    0,    0,
  76.466 +65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,   63,    0,    0,    0,    0,
  76.467 +65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,   63,    0,    0,    0,    0,    0,
  76.468 +65535,65535,65535,65535,65535,65535,65535,65535, 8191,    0,    0,    0,    0,    0,    0,    0,
  76.469 +65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,   15,    0,    0,    0,    0,    0,
  76.470 +65535,65535,16383,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.471 +  127,41208,65023,24447,65499,65535,65535,65535,65535,65535,65535,    3,    0,65528,65535,65535,
  76.472 +65535,65535,65535,16383,    0,65535,65535,65535,65535,65532,65535,65535,  255,    0,    0, 4095,
  76.473 +    0,    0,    0,    0,    0,    0,    0,65495,65535,65535,65535,65535,65535,65535,65535, 8191,
  76.474 +    0,    0,65534, 2047,65534, 2047,65472,65534,65535,16383,65535,32767,64764, 7420,    0,    0};
  76.475 +
  76.476 +const uint16_t UnicodeDigitBits[] = {
  76.477 +  256,    0,    0,    0,    0,    0,  272,    0,    0,  288,  304,  320,  336,  352,  368,  384,
  76.478 +  400,    0,    0,  416,    0,    0,    0,  432,  448,    0,    0,    0,    0,    0,    0,    0,
  76.479 +    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.480 +    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.481 +    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.482 +    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.483 +    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.484 +    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.485 +    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.486 +    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.487 +    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.488 +    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.489 +    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.490 +    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.491 +    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.492 +    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,  464,
  76.493 +    0,    0,    0, 1023,    0,    0,    0,    0,    0,    0,    0,  524,    0,    0,    0,    0,
  76.494 +    0,    0,    0,    0,    0,    0, 1023,    0,    0,    0,    0,    0,    0,    0,    0, 1023,
  76.495 +    0,    0,    0,    0,    0,    0,65472,    0,    0,    0,    0,    0,    0,    0,65472,    0,
  76.496 +    0,    0,    0,    0,    0,    0,65472,    0,    0,    0,    0,    0,    0,    0,65472,    0,
  76.497 +    0,    0,    0,    0,    0,    0,65472,    0,    0,    0,    0,    0,    0,    0,65408,    0,
  76.498 +    0,    0,    0,    0,    0,    0,65472,    0,    0,    0,    0,    0,    0,    0,65472,    0,
  76.499 +    0,    0,    0,    0,    0,    0,65472,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.500 +    0,    0,    0,    0,    0, 1023,    0,    0,    0,    0,    0,    0,    0, 1023,    0,    0,
  76.501 +    0,    0, 1023,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.502 +    0,    0,    0,    0, 1023,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.503 +    0,    0,    0,    0,    0,    0,65024,    3,    0,    0,    0,    0,    0,    0,    0,    0,
  76.504 +    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0, 1023,    0,
  76.505 +    0, 1023,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.506 +    0, 1023,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0};
  76.507 +
  76.508 +const uint16_t UnicodeSpaceBits[] = {
  76.509 +  256,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.510 +    0,    0,    0,    0,    0,    0,  272,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.511 +  288,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.512 +  304,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.513 +    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.514 +    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.515 +    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.516 +    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.517 +    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.518 +    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.519 +    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.520 +    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.521 +    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.522 +    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.523 +    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.524 +    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.525 +15872,    0,    1,    0,    0,    0,    0,    0,    0,    0,    1,    0,    0,    0,    0,    0,
  76.526 +    0,    0,    0,    0,    0,    0,    0,    0,    1,    0,    0,    0,    0,    0,    0,    0,
  76.527 + 4095,    0,33536,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.528 +    1,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0};
  76.529 +
  76.530 +const uint16_t UnicodeXDigitBits[] = {
  76.531 +  256,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.532 +    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.533 +    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.534 +    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.535 +    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.536 +    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.537 +    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.538 +    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.539 +    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.540 +    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.541 +    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.542 +    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.543 +    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.544 +    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.545 +    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.546 +    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,  272,
  76.547 +    0,    0,    0, 1023,  126,    0,  126,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.548 +    0, 1023,  126,    0,  126,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0};
  76.549 +
  76.550 +// Uncomment if necessary
  76.551 +//const uint16_t UnicodeCntrlBits[] = {
  76.552 +//  256,    0,    0,    0,    0,    0,    0,  272,    0,    0,    0,    0,    0,    0,    0,    0,
  76.553 +//    0,    0,    0,    0,    0,    0,    0,    0,  288,    0,    0,    0,    0,    0,    0,    0,
  76.554 +//  304,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.555 +//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.556 +//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.557 +//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.558 +//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.559 +//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.560 +//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.561 +//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.562 +//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.563 +//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.564 +//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.565 +//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.566 +//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.567 +//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,  320,  336,
  76.568 +//65535,65535,    0,    0,    0,    0,    0,32768,65535,65535,    0,    0,    0,    0,    0,    0,
  76.569 +//32768,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.570 +//30720,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.571 +//61440,    0,31744,    0,    0,    0,64512,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.572 +//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,32768,
  76.573 +//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0, 3584};
  76.574 +//
  76.575 +//const uint16_t UnicodeGraphBits[] = {
  76.576 +//  256,    1,  272,  288,  304,  320,  336,  352,    0,  368,  384,  400,  416,  432,  448,  464,
  76.577 +//  480,  496,  512,  528,  544,    1,  560,  576,  592,    0,    0,    0,    0,    0,  608,  624,
  76.578 +//  640,  656,    0,  672,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.579 +//  688,  704,    0,    0,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
  76.580 +//    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,  720,    1,    1,
  76.581 +//    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
  76.582 +//    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
  76.583 +//    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
  76.584 +//    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
  76.585 +//    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,  736,
  76.586 +//    1,    1,    1,    1,  752,    0,    0,    0,    0,    0,    0,    0,    1,    1,    1,    1,
  76.587 +//    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
  76.588 +//    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
  76.589 +//    1,    1,    1,    1,    1,    1,    1,  768,    0,    0,    0,    0,    0,    0,    0,    0,
  76.590 +//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.591 +//    0,    0,    0,    0,    0,    0,    0,    0,    0,    1,  784,  800,    1,  816,  832,  848,
  76.592 +//    0,    0,65534,65535,65535,65535,65535,32767,    0,    0,65534,65535,65535,65535,65535,65535,
  76.593 +//65535,65535,65532,   15,    0,65535,65535,65535,65535,65535,16383,63999,    3,    0,16415,    0,
  76.594 +//    0,    0,    0,    0,   32,    0,    0,17408,55232,65535,65531,65535,32767,64767,65535,   15,
  76.595 +//65535,65535,65535,65535,65535,65535,65535,65535,61443,65535,65535,65535, 6559,65535,65535,  831,
  76.596 +//    0,    0,    0,65534,65535,65151,65534,65535, 1791,    0,    0,16384,    9,65535, 2047,   31,
  76.597 +// 4096,34816,65534, 2047,65534,   63,16383,65535,65535,65535,65535,65535,65535, 8191, 8702, 8191,
  76.598 +//16383,65535, 8191,65535,    0,    0,    0,    0,65535,65535,65535,    1,    0,    0,    0,    0,
  76.599 +//65518,65535,65535,58367, 8191,65281,65535,    1,40942,65529,65023,50117, 6559,45184,65487,    3,
  76.600 +//34788,65529,65023,50029, 6535,24064,65472,   31,45038,65531,65023,58349, 7103,    1,65473,    0,
  76.601 +//40942,65529,65023,58317, 6543,45248,65475,    0,51180,54845,50968,50111, 7623,  128,65408,    0,
  76.602 +//57326,65533,65023,50159, 7647,   96,65475,    0,57324,65533,65023,50159, 7647,16480,65475,    0,
  76.603 +//57324,65533,65023,50175, 7631,  128,65475,    0,65516,64639,65535,12283,32895,65375,    0,   28,
  76.604 +//65534,65535,65535, 2047,65535, 4095,    0,    0, 9622,65264,60590,15359, 8223,13311,    0,    0,
  76.605 +//65521,    7, 1023,15360,65279,65535, 2047,65534, 3875,65279,65535, 8191,    0,    0,    0,    0,
  76.606 +//65535,65535,63227,  327,65535, 1023,    0,    0,    0,    0,65535,65535,   63,65535,65535, 2175,
  76.607 +//65535,65535,65535,65535,65535,33791,65535,65535,65535,65535,65287,65535,65535,65535,65535, 1023,
  76.608 +//65407,65535,65535,65535,15743,15743,65535,65535,15743,65535,32767,32573,32573,65407,32767,65535,
  76.609 +//32767,32573,65535,65535,65407, 2047,65534,    3,    0,    0,65535,65535,65535,65535,65535,   31,
  76.610 +//65534,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,
  76.611 +//65535,65535,65535,65535,65535,65535,65535,  127,65534, 8191,65535,65535,65535,65535,16383,    0,
  76.612 +//    0,    0,    0,    0,    0,    0,    0,    0,65535,65535,65535,65535,  511, 6128, 1023,    0,
  76.613 +// 2047, 1023,65535,65535,65527,65535,65535,  255,65535,65535, 1023,    0,    0,    0,    0,    0,
  76.614 +//65535,65535,65535,65535,65535,65535,65535,65535,65535, 4095,65535,65535,65535,65535,65535, 1023,
  76.615 +//65535,16191,65535,65535,16191,43775,65535,16383,65535,65535,65535,24543, 8156, 4047, 8191, 8156,
  76.616 +//    0,65535,  255,65535,16239,    0,    0,57344,24576,    0,    0,    0,    0,    0,    0,    0,
  76.617 +//64644,15919,48464, 1019,    0,    0,65535,65535,   15,    0,    0,    0,    0,    0,    0,    0,
  76.618 +//    0,    0, 1536,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.619 +//65486,65523, 1022, 1793,65534,65535,65535,65535,65535,   31,65534,65535,65535,65535,65535, 4095,
  76.620 +//65504,65535, 8191,65534,65535,65535,65535,65535,32767,    0,65535,  255,    0,    0,    0,    0,
  76.621 +//65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,   63,    0,    0,    0,    0,
  76.622 +//65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,   63,    0,    0,    0,    0,    0,
  76.623 +//65535,65535,65535,65535,65535,65535,65535,65535, 8191,    0,    0,    0,    0,    0,    0,    0,
  76.624 +//65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,   15,    0,    0,    0,    0,    0,
  76.625 +//65535,65535,16383,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.626 +//  127,41208,65023,24447,65499,65535,65535,65535,65535,65535,65535,    3,    0,65528,65535,65535,
  76.627 +//65535,65535,65535,65535,    0,65535,65535,65535,65535,65532,65535,65535,  255,    0,    0, 4095,
  76.628 +//    0,    0,    0,65535,65055,65527, 3339,65495,65535,65535,65535,65535,65535,65535,65535, 8191,
  76.629 +//63470,36863,65535,49151,65534,12287,65534,65534,65535,16383,65535,32767,64764, 7420,    0,    0};
  76.630 +//
  76.631 +//const uint16_t UnicodePrintBits[] = {
  76.632 +//  256,    1,  272,  288,  304,  320,  336,  352,    0,  368,  384,  400,  416,  432,  448,  464,
  76.633 +//  480,  496,  512,  528,  544,    1,  560,  576,  592,    0,    0,    0,    0,    0,  608,  624,
  76.634 +//  640,  656,    0,  672,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.635 +//  688,  704,    0,    0,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
  76.636 +//    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,  720,    1,    1,
  76.637 +//    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
  76.638 +//    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
  76.639 +//    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
  76.640 +//    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
  76.641 +//    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,  736,
  76.642 +//    1,    1,    1,    1,  752,    0,    0,    0,    0,    0,    0,    0,    1,    1,    1,    1,
  76.643 +//    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
  76.644 +//    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
  76.645 +//    1,    1,    1,    1,    1,    1,    1,  768,    0,    0,    0,    0,    0,    0,    0,    0,
  76.646 +//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.647 +//    0,    0,    0,    0,    0,    0,    0,    0,    0,    1,  784,  800,    1,  816,  832,  848,
  76.648 +//  512,    0,65535,65535,65535,65535,65535,32767,    0,    0,65535,65535,65535,65535,65535,65535,
  76.649 +//65535,65535,65532,   15,    0,65535,65535,65535,65535,65535,16383,63999,    3,    0,16415,    0,
  76.650 +//    0,    0,    0,    0,   32,    0,    0,17408,55232,65535,65531,65535,32767,64767,65535,   15,
  76.651 +//65535,65535,65535,65535,65535,65535,65535,65535,61443,65535,65535,65535, 6559,65535,65535,  831,
  76.652 +//    0,    0,    0,65534,65535,65151,65534,65535, 1791,    0,    0,16384,    9,65535, 2047,   31,
  76.653 +// 4096,34816,65534, 2047,65534,   63,16383,65535,65535,65535,65535,65535,65535, 8191, 8702, 8191,
  76.654 +//16383,65535, 8191,65535,    0,    0,    0,    0,65535,65535,65535,    1,    0,    0,    0,    0,
  76.655 +//65518,65535,65535,58367, 8191,65281,65535,    1,40942,65529,65023,50117, 6559,45184,65487,    3,
  76.656 +//34788,65529,65023,50029, 6535,24064,65472,   31,45038,65531,65023,58349, 7103,    1,65473,    0,
  76.657 +//40942,65529,65023,58317, 6543,45248,65475,    0,51180,54845,50968,50111, 7623,  128,65408,    0,
  76.658 +//57326,65533,65023,50159, 7647,   96,65475,    0,57324,65533,65023,50159, 7647,16480,65475,    0,
  76.659 +//57324,65533,65023,50175, 7631,  128,65475,    0,65516,64639,65535,12283,32895,65375,    0,   28,
  76.660 +//65534,65535,65535, 2047,65535, 4095,    0,    0, 9622,65264,60590,15359, 8223,13311,    0,    0,
  76.661 +//65521,    7, 1023,15360,65279,65535, 2047,65534, 3875,65279,65535, 8191,    0,    0,    0,    0,
  76.662 +//65535,65535,63227,  327,65535, 1023,    0,    0,    0,    0,65535,65535,   63,65535,65535, 2175,
  76.663 +//65535,65535,65535,65535,65535,33791,65535,65535,65535,65535,65287,65535,65535,65535,65535, 1023,
  76.664 +//65407,65535,65535,65535,15743,15743,65535,65535,15743,65535,32767,32573,32573,65407,32767,65535,
  76.665 +//32767,32573,65535,65535,65407, 2047,65534,    3,    0,    0,65535,65535,65535,65535,65535,   31,
  76.666 +//65534,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,
  76.667 +//65535,65535,65535,65535,65535,65535,65535,  127,65534, 8191,65535,65535,65535,65535,16383,    0,
  76.668 +//    0,    0,    0,    0,    0,    0,    0,    0,65535,65535,65535,65535,  511, 6128, 1023,    0,
  76.669 +// 2047, 1023,65535,65535,65527,65535,65535,  255,65535,65535, 1023,    0,    0,    0,    0,    0,
  76.670 +//65535,65535,65535,65535,65535,65535,65535,65535,65535, 4095,65535,65535,65535,65535,65535, 1023,
  76.671 +//65535,16191,65535,65535,16191,43775,65535,16383,65535,65535,65535,24543, 8156, 4047, 8191, 8156,
  76.672 +//    0,65535,  255,65535,16239,    0,    0,57344,24576,    0,    0,    0,    0,    0,    0,    0,
  76.673 +//64644,15919,48464, 1019,    0,    0,65535,65535,   15,    0,    0,    0,    0,    0,    0,    0,
  76.674 +//    0,    0, 1536,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.675 +//65487,65523, 1022, 1793,65534,65535,65535,65535,65535,   31,65534,65535,65535,65535,65535, 4095,
  76.676 +//65504,65535, 8191,65534,65535,65535,65535,65535,32767,    0,65535,  255,    0,    0,    0,    0,
  76.677 +//65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,   63,    0,    0,    0,    0,
  76.678 +//65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,   63,    0,    0,    0,    0,    0,
  76.679 +//65535,65535,65535,65535,65535,65535,65535,65535, 8191,    0,    0,    0,    0,    0,    0,    0,
  76.680 +//65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,   15,    0,    0,    0,    0,    0,
  76.681 +//65535,65535,16383,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.682 +//  127,41208,65023,24447,65499,65535,65535,65535,65535,65535,65535,    3,    0,65528,65535,65535,
  76.683 +//65535,65535,65535,65535,    0,65535,65535,65535,65535,65532,65535,65535,  255,    0,    0, 4095,
  76.684 +//    0,    0,    0,65535,65055,65527, 3339,65495,65535,65535,65535,65535,65535,65535,65535,40959,
  76.685 +//63470,36863,65535,49151,65534,12287,65534,65534,65535,16383,65535,32767,64764, 7420,    0,    0};
  76.686 +//
  76.687 +//const uint16_t UnicodePunctBits[] = {
  76.688 +//  256,    0,    0,  272,    0,  288,  304,  320,    0,  336,    0,    0,    0,  352,  368,  384,
  76.689 +//  400,    0,    0,  416,    0,    0,  432,  448,  464,    0,    0,    0,    0,    0,    0,    0,
  76.690 +//  480,    0,    0,  496,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.691 +//  512,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.692 +//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.693 +//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.694 +//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.695 +//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.696 +//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.697 +//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.698 +//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.699 +//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.700 +//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.701 +//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.702 +//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.703 +//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,  528,  544,  560,
  76.704 +//    0,    0,65534,64512,    1,63488,    1,30720,    0,    0,65534,65535,    0,  128,    0,  128,
  76.705 +//    0,    0,    0,    0,    0,    0,    0,16384,  128,    0,    0,    0,    0,    0,    0,    0,
  76.706 +//    0,    0,    0,    0,    0,64512,    0,    0, 1536,    0,    0,16384,    9,    0,    0,   24,
  76.707 +// 4096,34816,    0,    0,    0,    0,15360,    0,    0,    0,    0,    0,    0,   16,    0,    0,
  76.708 +//16383,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.709 +//    0,    0,    0,    0,    0,    0,   48,    1,    0,    0,    0,    0,    0,    0,    0,    0,
  76.710 +//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,   16,
  76.711 +//    0,    0,    0,    0,32768, 3072,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.712 +//65520,    7,    0,15360,    0,    0,    0,    0,   32,    0,    0,    0,    0,    0,    0,    0,
  76.713 +//    0,    0,    0,    0,64512,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0, 2048,
  76.714 +//    0,    0,    0,    0,    0,    0,  510,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.715 +//    0,    0,    0,    0,    0,    0,24576,    0,    0, 6144,    0,    0,    0,    0,14336,    0,
  76.716 +//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0, 6128,    0,    0,
  76.717 +// 2047,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.718 +//    0,65535,  255,65535,16239,    0,    0,24576,24576,    0,    0,    0,    0,    0,    0,    0,
  76.719 +//    0,    0, 1536,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.720 +//65294,65523,    0,    1,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0, 2048,
  76.721 +//    0,    0,    0,49152,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.722 +//    0,    0,    0,65535,65055,65527, 3339,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.723 +//63470,35840,    1,47104,    0,10240,   62,    0,    0,    0,    0,    0,    0,    0,    0,    0};
  76.724 +//
  76.725 +//const uint16_t UnicodeLowerBits[] = {
  76.726 +//  256,  272,  288,  304,  320,  336,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.727 +//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,  352,  368,
  76.728 +//  384,  400,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.729 +//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.730 +//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.731 +//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.732 +//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.733 +//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.734 +//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.735 +//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.736 +//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.737 +//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.738 +//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.739 +//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.740 +//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.741 +//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,  416,    0,    0,    0,  432,
  76.742 +//    0,    0,    0,    0,    0,    0,65534, 2047,    0,    0,    0,    0,    0,32768,65535,65407,
  76.743 +//43690,43690,43690,21930,43861,43690,43690,54442,12585,20004,11562,58961,23392,46421,43690,43565,
  76.744 +//43690,43690,43688,   10,    0,65535,65535,65535,65535,65535,16383,    0,    0,    0,    0,    0,
  76.745 +//    0,    0,    0,    0,    0,    0,    0,    0,    0,    1,61440,65535,32767,43235,43690,   15,
  76.746 +//    0,    0,    0,65535,65535,65535,43690,43690,40962,43690,43690,43690, 4372,43690,43690,  554,
  76.747 +//    0,    0,    0,    0,    0,    0,65534,65535,  255,    0,    0,    0,    0,    0,    0,    0,
  76.748 +//43690,43690,43690,43690,43690,43690,43690,43690,43690, 4074,43690,43690,43690,43690,43690,  682,
  76.749 +//  255,   63,  255,  255,   63,  255,  255,16383,65535,65535,65535,20703, 4316,  207,  255, 4316,
  76.750 +//    0,    0,    0,    0,    0,    0,    0,32768,    0,    0,    0,    0,    0,    0,    0,    0,
  76.751 +//50176,    8,32768,  528,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.752 +//  127,  248,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.753 +//    0,    0,    0,    0,65534, 2047,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0};
  76.754 +//
  76.755 +//const uint16_t UnicodeUpperBits[] = {
  76.756 +//  256,  272,  288,  304,  320,  336,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.757 +//  352,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,  368,  384,
  76.758 +//    0,  400,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.759 +//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.760 +//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.761 +//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.762 +//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.763 +//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.764 +//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.765 +//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.766 +//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.767 +//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.768 +//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.769 +//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.770 +//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.771 +//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,  416,
  76.772 +//    0,    0,    0,    0,65534, 2047,    0,    0,    0,    0,    0,    0,65535,32639,    0,    0,
  76.773 +//21845,21845,21845,43605,21674,21845,21845,11093,52950,45531,53973, 4526,44464,19114,21845,21974,
  76.774 +//21845,21845,21844,    5,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.775 +//    0,    0,    0,    0,    0,    0,    0,    0,55104,65534, 4091,    0,    0,21532,21845,    0,
  76.776 +//65535,65535,65535,    0,    0,    0,21845,21845,20481,21845,21845,21845, 2187,21845,21845,  277,
  76.777 +//    0,    0,    0,65534,65535,  127,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.778 +//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,65535,65535,   63,    0,    0,    0,
  76.779 +//21845,21845,21845,21845,21845,21845,21845,21845,21845,   21,21845,21845,21845,21845,21845,  341,
  76.780 +//65280,16128,65280,65280,16128,43520,65280,    0,65280,65280,65280, 7936, 7936, 3840, 7936, 7936,
  76.781 +//14468,15911,15696,   11,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.782 +//    0,    0,65534, 2047,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0};
  76.783 +
  76.784 +
  76.785 +// MA: March 19, 2010
  76.786 +// Modified ToUpper and ToLower tables to match values expected by AS3 tests.
  76.787 +// ToLower modifications:
  76.788 +//    304 ->  105
  76.789 +//   1024 -> 1104 *
  76.790 +//   1037 -> 1117 * 
  76.791 +// UoUpper modifications:
  76.792 +//    255 ->  376
  76.793 +//    305 ->   73
  76.794 +//    383 ->   83
  76.795 +//   1104 -> 1024 *
  76.796 +//   1117 -> 1037 *
  76.797 +// Entries marked with a '*' don't make complete sense based on Unicode manual, although
  76.798 +// they match AS3.
  76.799 +
  76.800 +
  76.801 +static const uint16_t UnicodeToUpperBits[] = {
  76.802 +  256,  272,  288,  304,  320,  336,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.803 +    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,  352,  368,
  76.804 +    0,  384,    0,    0,  400,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.805 +    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.806 +    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.807 +    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.808 +    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.809 +    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.810 +    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.811 +    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.812 +    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.813 +    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.814 +    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.815 +    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.816 +    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.817 +    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,  416,
  76.818 +    0,    0,    0,    0,    0,    0,65534, 2047,    0,    0,    0,    0,    0,    0,65535,65407,
  76.819 +43690,43690,43690,21674,43349,43690,43690,54442, 4392,  516, 8490, 8785,21056,46421,43690,43048, // MA: Modified for AS3.
  76.820 +43690,  170,    0,    0,    0, 2776,33545,   36, 3336,    4,    0,    0,    0,    0,    0,    0,
  76.821 +    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,61440,65534,32767,    0,43688,    0,
  76.822 +    0,    0,    0,65535,65535,65535,43690,43690,    2,43690,43690,43690, 4372,43690,35498,  554, // MA: Modified for AS3.
  76.823 +    0,    0,    0,    0,    0,    0,65534,65535,  127,    0,    0,    0,    0,    0,    0,    0,
  76.824 +43690,43690,43690,43690,43690,43690,43690,43690,43690,   42,43690,43690,43690,43690,43690,  682,
  76.825 +  255,   63,  255,  255,   63,  170,  255,16383,    0,    0,    0,    3,    0,    3,   35,    0,
  76.826 +    0,    0,    0,    0,    0,    0,    0,65535,    0,    0,    0,    0,    0,    0,    0,    0,
  76.827 +    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,65535, 1023,    0,
  76.828 +    0,    0,    0,    0,65534, 2047,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0};
  76.829 +
  76.830 +static const uint16_t UnicodeToLowerBits[] = {
  76.831 +  256,  272,  288,  304,  320,  336,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.832 +  352,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,  368,  384,
  76.833 +    0,  400,    0,    0,  416,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.834 +    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.835 +    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.836 +    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.837 +    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.838 +    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.839 +    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.840 +    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.841 +    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.842 +    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.843 +    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.844 +    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.845 +    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.846 +    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,  432,
  76.847 +    0,    0,    0,    0,65534, 2047,    0,    0,    0,    0,    0,    0,65535,32639,    0,    0,
  76.848 +21845,21845,21845,43605,21674,21845,21845,11093,52950,45531,53909, 4526,42128,19114,21845,21522,// MA: Modidied for AS3.
  76.849 +21845,   85,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.850 +    0,    0,    0,    0,    0,    0,    0,    0,55104,65534, 4091,    0,    0,    0,21844,    0,
  76.851 +65535,65535,65535,    0,    0,    0,21845,21845,    1,21845,21845,21845, 2186,21845,17749,  277,
  76.852 +    0,    0,    0,65534,65535,  127,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.853 +    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,65535,65535,   63,    0,    0,    0,
  76.854 +21845,21845,21845,21845,21845,21845,21845,21845,21845,   21,21845,21845,21845,21845,21845,  341,
  76.855 +65280,16128,65280,65280,16128,43520,65280,    0,    0,    0,    0, 3840, 3840, 3840, 7936, 3840,
  76.856 +    0,    0,    0,    0,    0,    0,65535,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  76.857 +    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,65472,65535,    0,    0,    0,
  76.858 +    0,    0,65534, 2047,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0};
  76.859 +
  76.860 +struct GUnicodePairType
  76.861 +{
  76.862 +    uint16_t Key, Value;
  76.863 +};
  76.864 +
  76.865 +static inline bool CmpUnicodeKey(const GUnicodePairType& a, uint16_t key)
  76.866 +{
  76.867 +    return a.Key < key;
  76.868 +}
  76.869 +
  76.870 +static const GUnicodePairType UnicodeToUpperTable[] = {
  76.871 +{   97,   65}, {   98,   66}, {   99,   67}, {  100,   68}, {  101,   69}, {  102,   70}, {  103,   71},
  76.872 +{  104,   72}, {  105,   73}, {  106,   74}, {  107,   75}, {  108,   76}, {  109,   77}, {  110,   78},
  76.873 +{  111,   79}, {  112,   80}, {  113,   81}, {  114,   82}, {  115,   83}, {  116,   84}, {  117,   85},
  76.874 +{  118,   86}, {  119,   87}, {  120,   88}, {  121,   89}, {  122,   90}, {  224,  192}, {  225,  193},
  76.875 +{  226,  194}, {  227,  195}, {  228,  196}, {  229,  197}, {  230,  198}, {  231,  199}, {  232,  200},
  76.876 +{  233,  201}, {  234,  202}, {  235,  203}, {  236,  204}, {  237,  205}, {  238,  206}, {  239,  207},
  76.877 +{  240,  208}, {  241,  209}, {  242,  210}, {  243,  211}, {  244,  212}, {  245,  213}, {  246,  214},
  76.878 +{  248,  216}, {  249,  217}, {  250,  218}, {  251,  219}, {  252,  220}, {  253,  221}, {  254,  222},
  76.879 +{  255,  376}, {  257,  256}, {  259,  258}, {  261,  260}, {  263,  262}, {  265,  264}, {  267,  266},
  76.880 +{  269,  268}, {  271,  270}, {  273,  272}, {  275,  274}, {  277,  276}, {  279,  278}, {  281,  280},
  76.881 +{  283,  282}, {  285,  284}, {  287,  286}, {  289,  288}, {  291,  290}, {  293,  292}, {  295,  294},
  76.882 +{  297,  296}, {  299,  298}, {  301,  300}, {  303,  302}, {  305,   73}, {  307,  306}, {  309,  308}, {  311,  310},
  76.883 +{  314,  313}, {  316,  315}, {  318,  317}, {  320,  319}, {  322,  321}, {  324,  323}, {  326,  325},
  76.884 +{  328,  327}, {  331,  330}, {  333,  332}, {  335,  334}, {  337,  336}, {  339,  338}, {  341,  340},
  76.885 +{  343,  342}, {  345,  344}, {  347,  346}, {  349,  348}, {  351,  350}, {  353,  352}, {  355,  354},
  76.886 +{  357,  356}, {  359,  358}, {  361,  360}, {  363,  362}, {  365,  364}, {  367,  366}, {  369,  368},
  76.887 +{  371,  370}, {  373,  372}, {  375,  374}, {  378,  377}, {  380,  379}, {  382,  381}, {  383,   83}, {  387,  386},
  76.888 +{  389,  388}, {  392,  391}, {  396,  395}, {  402,  401}, {  409,  408}, {  417,  416}, {  419,  418},
  76.889 +{  421,  420}, {  424,  423}, {  429,  428}, {  432,  431}, {  436,  435}, {  438,  437}, {  441,  440},
  76.890 +{  445,  444}, {  454,  452}, {  457,  455}, {  460,  458}, {  462,  461}, {  464,  463}, {  466,  465},
  76.891 +{  468,  467}, {  470,  469}, {  472,  471}, {  474,  473}, {  476,  475}, {  477,  398}, {  479,  478},
  76.892 +{  481,  480}, {  483,  482}, {  485,  484}, {  487,  486}, {  489,  488}, {  491,  490}, {  493,  492},
  76.893 +{  495,  494}, {  499,  497}, {  501,  500}, {  507,  506}, {  509,  508}, {  511,  510}, {  513,  512},
  76.894 +{  515,  514}, {  517,  516}, {  519,  518}, {  521,  520}, {  523,  522}, {  525,  524}, {  527,  526},
  76.895 +{  529,  528}, {  531,  530}, {  533,  532}, {  535,  534}, {  595,  385}, {  596,  390}, {  598,  393},
  76.896 +{  599,  394}, {  601,  399}, {  603,  400}, {  608,  403}, {  611,  404}, {  616,  407}, {  617,  406},
  76.897 +{  623,  412}, {  626,  413}, {  629,  415}, {  643,  425}, {  648,  430}, {  650,  433}, {  651,  434},
  76.898 +{  658,  439}, {  940,  902}, {  941,  904}, {  942,  905}, {  943,  906}, {  945,  913}, {  946,  914},
  76.899 +{  947,  915}, {  948,  916}, {  949,  917}, {  950,  918}, {  951,  919}, {  952,  920}, {  953,  921},
  76.900 +{  954,  922}, {  955,  923}, {  956,  924}, {  957,  925}, {  958,  926}, {  959,  927}, {  960,  928},
  76.901 +{  961,  929}, {  962,  931}, {  963,  931}, {  964,  932}, {  965,  933}, {  966,  934}, {  967,  935},
  76.902 +{  968,  936}, {  969,  937}, {  970,  938}, {  971,  939}, {  972,  908}, {  973,  910}, {  974,  911},
  76.903 +{  995,  994}, {  997,  996}, {  999,  998}, { 1001, 1000}, { 1003, 1002}, { 1005, 1004}, { 1007, 1006},
  76.904 +{ 1072, 1040}, { 1073, 1041}, { 1074, 1042}, { 1075, 1043}, { 1076, 1044}, { 1077, 1045}, { 1078, 1046},
  76.905 +{ 1079, 1047}, { 1080, 1048}, { 1081, 1049}, { 1082, 1050}, { 1083, 1051}, { 1084, 1052}, { 1085, 1053},
  76.906 +{ 1086, 1054}, { 1087, 1055}, { 1088, 1056}, { 1089, 1057}, { 1090, 1058}, { 1091, 1059}, { 1092, 1060},
  76.907 +{ 1093, 1061}, { 1094, 1062}, { 1095, 1063}, { 1096, 1064}, { 1097, 1065}, { 1098, 1066}, { 1099, 1067},
  76.908 +{ 1100, 1068}, { 1101, 1069}, { 1102, 1070}, { 1103, 1071}, { 1104, 1024}, { 1105, 1025}, { 1106, 1026}, { 1107, 1027},
  76.909 +{ 1108, 1028}, { 1109, 1029}, { 1110, 1030}, { 1111, 1031}, { 1112, 1032}, { 1113, 1033}, { 1114, 1034},
  76.910 +{ 1115, 1035}, { 1116, 1036}, { 1117, 1037}, { 1118, 1038}, { 1119, 1039}, { 1121, 1120}, { 1123, 1122}, { 1125, 1124},
  76.911 +{ 1127, 1126}, { 1129, 1128}, { 1131, 1130}, { 1133, 1132}, { 1135, 1134}, { 1137, 1136}, { 1139, 1138},
  76.912 +{ 1141, 1140}, { 1143, 1142}, { 1145, 1144}, { 1147, 1146}, { 1149, 1148}, { 1151, 1150}, { 1153, 1152},
  76.913 +{ 1169, 1168}, { 1171, 1170}, { 1173, 1172}, { 1175, 1174}, { 1177, 1176}, { 1179, 1178}, { 1181, 1180},
  76.914 +{ 1183, 1182}, { 1185, 1184}, { 1187, 1186}, { 1189, 1188}, { 1191, 1190}, { 1193, 1192}, { 1195, 1194},
  76.915 +{ 1197, 1196}, { 1199, 1198}, { 1201, 1200}, { 1203, 1202}, { 1205, 1204}, { 1207, 1206}, { 1209, 1208},
  76.916 +{ 1211, 1210}, { 1213, 1212}, { 1215, 1214}, { 1218, 1217}, { 1220, 1219}, { 1224, 1223}, { 1228, 1227},
  76.917 +{ 1233, 1232}, { 1235, 1234}, { 1237, 1236}, { 1239, 1238}, { 1241, 1240}, { 1243, 1242}, { 1245, 1244},
  76.918 +{ 1247, 1246}, { 1249, 1248}, { 1251, 1250}, { 1253, 1252}, { 1255, 1254}, { 1257, 1256}, { 1259, 1258},
  76.919 +{ 1263, 1262}, { 1265, 1264}, { 1267, 1266}, { 1269, 1268}, { 1273, 1272}, { 1377, 1329}, { 1378, 1330},
  76.920 +{ 1379, 1331}, { 1380, 1332}, { 1381, 1333}, { 1382, 1334}, { 1383, 1335}, { 1384, 1336}, { 1385, 1337},
  76.921 +{ 1386, 1338}, { 1387, 1339}, { 1388, 1340}, { 1389, 1341}, { 1390, 1342}, { 1391, 1343}, { 1392, 1344},
  76.922 +{ 1393, 1345}, { 1394, 1346}, { 1395, 1347}, { 1396, 1348}, { 1397, 1349}, { 1398, 1350}, { 1399, 1351},
  76.923 +{ 1400, 1352}, { 1401, 1353}, { 1402, 1354}, { 1403, 1355}, { 1404, 1356}, { 1405, 1357}, { 1406, 1358},
  76.924 +{ 1407, 1359}, { 1408, 1360}, { 1409, 1361}, { 1410, 1362}, { 1411, 1363}, { 1412, 1364}, { 1413, 1365},
  76.925 +{ 1414, 1366}, { 7681, 7680}, { 7683, 7682}, { 7685, 7684}, { 7687, 7686}, { 7689, 7688}, { 7691, 7690},
  76.926 +{ 7693, 7692}, { 7695, 7694}, { 7697, 7696}, { 7699, 7698}, { 7701, 7700}, { 7703, 7702}, { 7705, 7704},
  76.927 +{ 7707, 7706}, { 7709, 7708}, { 7711, 7710}, { 7713, 7712}, { 7715, 7714}, { 7717, 7716}, { 7719, 7718},
  76.928 +{ 7721, 7720}, { 7723, 7722}, { 7725, 7724}, { 7727, 7726}, { 7729, 7728}, { 7731, 7730}, { 7733, 7732},
  76.929 +{ 7735, 7734}, { 7737, 7736}, { 7739, 7738}, { 7741, 7740}, { 7743, 7742}, { 7745, 7744}, { 7747, 7746},
  76.930 +{ 7749, 7748}, { 7751, 7750}, { 7753, 7752}, { 7755, 7754}, { 7757, 7756}, { 7759, 7758}, { 7761, 7760},
  76.931 +{ 7763, 7762}, { 7765, 7764}, { 7767, 7766}, { 7769, 7768}, { 7771, 7770}, { 7773, 7772}, { 7775, 7774},
  76.932 +{ 7777, 7776}, { 7779, 7778}, { 7781, 7780}, { 7783, 7782}, { 7785, 7784}, { 7787, 7786}, { 7789, 7788},
  76.933 +{ 7791, 7790}, { 7793, 7792}, { 7795, 7794}, { 7797, 7796}, { 7799, 7798}, { 7801, 7800}, { 7803, 7802},
  76.934 +{ 7805, 7804}, { 7807, 7806}, { 7809, 7808}, { 7811, 7810}, { 7813, 7812}, { 7815, 7814}, { 7817, 7816},
  76.935 +{ 7819, 7818}, { 7821, 7820}, { 7823, 7822}, { 7825, 7824}, { 7827, 7826}, { 7829, 7828}, { 7841, 7840},
  76.936 +{ 7843, 7842}, { 7845, 7844}, { 7847, 7846}, { 7849, 7848}, { 7851, 7850}, { 7853, 7852}, { 7855, 7854},
  76.937 +{ 7857, 7856}, { 7859, 7858}, { 7861, 7860}, { 7863, 7862}, { 7865, 7864}, { 7867, 7866}, { 7869, 7868},
  76.938 +{ 7871, 7870}, { 7873, 7872}, { 7875, 7874}, { 7877, 7876}, { 7879, 7878}, { 7881, 7880}, { 7883, 7882},
  76.939 +{ 7885, 7884}, { 7887, 7886}, { 7889, 7888}, { 7891, 7890}, { 7893, 7892}, { 7895, 7894}, { 7897, 7896},
  76.940 +{ 7899, 7898}, { 7901, 7900}, { 7903, 7902}, { 7905, 7904}, { 7907, 7906}, { 7909, 7908}, { 7911, 7910},
  76.941 +{ 7913, 7912}, { 7915, 7914}, { 7917, 7916}, { 7919, 7918}, { 7921, 7920}, { 7923, 7922}, { 7925, 7924},
  76.942 +{ 7927, 7926}, { 7929, 7928}, { 7936, 7944}, { 7937, 7945}, { 7938, 7946}, { 7939, 7947}, { 7940, 7948},
  76.943 +{ 7941, 7949}, { 7942, 7950}, { 7943, 7951}, { 7952, 7960}, { 7953, 7961}, { 7954, 7962}, { 7955, 7963},
  76.944 +{ 7956, 7964}, { 7957, 7965}, { 7968, 7976}, { 7969, 7977}, { 7970, 7978}, { 7971, 7979}, { 7972, 7980},
  76.945 +{ 7973, 7981}, { 7974, 7982}, { 7975, 7983}, { 7984, 7992}, { 7985, 7993}, { 7986, 7994}, { 7987, 7995},
  76.946 +{ 7988, 7996}, { 7989, 7997}, { 7990, 7998}, { 7991, 7999}, { 8000, 8008}, { 8001, 8009}, { 8002, 8010},
  76.947 +{ 8003, 8011}, { 8004, 8012}, { 8005, 8013}, { 8017, 8025}, { 8019, 8027}, { 8021, 8029}, { 8023, 8031},
  76.948 +{ 8032, 8040}, { 8033, 8041}, { 8034, 8042}, { 8035, 8043}, { 8036, 8044}, { 8037, 8045}, { 8038, 8046},
  76.949 +{ 8039, 8047}, { 8048, 8122}, { 8049, 8123}, { 8050, 8136}, { 8051, 8137}, { 8052, 8138}, { 8053, 8139},
  76.950 +{ 8054, 8154}, { 8055, 8155}, { 8056, 8184}, { 8057, 8185}, { 8058, 8170}, { 8059, 8171}, { 8060, 8186},
  76.951 +{ 8061, 8187}, { 8112, 8120}, { 8113, 8121}, { 8144, 8152}, { 8145, 8153}, { 8160, 8168}, { 8161, 8169},
  76.952 +{ 8165, 8172}, { 8560, 8544}, { 8561, 8545}, { 8562, 8546}, { 8563, 8547}, { 8564, 8548}, { 8565, 8549},
  76.953 +{ 8566, 8550}, { 8567, 8551}, { 8568, 8552}, { 8569, 8553}, { 8570, 8554}, { 8571, 8555}, { 8572, 8556},
  76.954 +{ 8573, 8557}, { 8574, 8558}, { 8575, 8559}, { 9424, 9398}, { 9425, 9399}, { 9426, 9400}, { 9427, 9401},
  76.955 +{ 9428, 9402}, { 9429, 9403}, { 9430, 9404}, { 9431, 9405}, { 9432, 9406}, { 9433, 9407}, { 9434, 9408},
  76.956 +{ 9435, 9409}, { 9436, 9410}, { 9437, 9411}, { 9438, 9412}, { 9439, 9413}, { 9440, 9414}, { 9441, 9415},
  76.957 +{ 9442, 9416}, { 9443, 9417}, { 9444, 9418}, { 9445, 9419}, { 9446, 9420}, { 9447, 9421}, { 9448, 9422},
  76.958 +{ 9449, 9423}, {65345,65313}, {65346,65314}, {65347,65315}, {65348,65316}, {65349,65317}, {65350,65318},
  76.959 +{65351,65319}, {65352,65320}, {65353,65321}, {65354,65322}, {65355,65323}, {65356,65324}, {65357,65325},
  76.960 +{65358,65326}, {65359,65327}, {65360,65328}, {65361,65329}, {65362,65330}, {65363,65331}, {65364,65332},
  76.961 +{65365,65333}, {65366,65334}, {65367,65335}, {65368,65336}, {65369,65337}, {65370,65338}, {65535,    0}};
  76.962 +
  76.963 +static const GUnicodePairType UnicodeToLowerTable[] = {
  76.964 +{   65,   97}, {   66,   98}, {   67,   99}, {   68,  100}, {   69,  101}, {   70,  102}, {   71,  103},
  76.965 +{   72,  104}, {   73,  105}, {   74,  106}, {   75,  107}, {   76,  108}, {   77,  109}, {   78,  110},
  76.966 +{   79,  111}, {   80,  112}, {   81,  113}, {   82,  114}, {   83,  115}, {   84,  116}, {   85,  117},
  76.967 +{   86,  118}, {   87,  119}, {   88,  120}, {   89,  121}, {   90,  122}, {  192,  224}, {  193,  225},
  76.968 +{  194,  226}, {  195,  227}, {  196,  228}, {  197,  229}, {  198,  230}, {  199,  231}, {  200,  232},
  76.969 +{  201,  233}, {  202,  234}, {  203,  235}, {  204,  236}, {  205,  237}, {  206,  238}, {  207,  239},
  76.970 +{  208,  240}, {  209,  241}, {  210,  242}, {  211,  243}, {  212,  244}, {  213,  245}, {  214,  246},
  76.971 +{  216,  248}, {  217,  249}, {  218,  250}, {  219,  251}, {  220,  252}, {  221,  253}, {  222,  254},
  76.972 +{  256,  257}, {  258,  259}, {  260,  261}, {  262,  263}, {  264,  265}, {  266,  267}, {  268,  269},
  76.973 +{  270,  271}, {  272,  273}, {  274,  275}, {  276,  277}, {  278,  279}, {  280,  281}, {  282,  283},
  76.974 +{  284,  285}, {  286,  287}, {  288,  289}, {  290,  291}, {  292,  293}, {  294,  295}, {  296,  297},
  76.975 +{  298,  299}, {  300,  301}, {  302,  303}, {  304,  105}, {  306,  307}, {  308,  309}, {  310,  311}, {  313,  314},
  76.976 +{  315,  316}, {  317,  318}, {  319,  320}, {  321,  322}, {  323,  324}, {  325,  326}, {  327,  328},
  76.977 +{  330,  331}, {  332,  333}, {  334,  335}, {  336,  337}, {  338,  339}, {  340,  341}, {  342,  343},
  76.978 +{  344,  345}, {  346,  347}, {  348,  349}, {  350,  351}, {  352,  353}, {  354,  355}, {  356,  357},
  76.979 +{  358,  359}, {  360,  361}, {  362,  363}, {  364,  365}, {  366,  367}, {  368,  369}, {  370,  371},
  76.980 +{  372,  373}, {  374,  375}, {  376,  255}, {  377,  378}, {  379,  380}, {  381,  382}, {  385,  595},
  76.981 +{  386,  387}, {  388,  389}, {  390,  596}, {  391,  392}, {  393,  598}, {  394,  599}, {  395,  396},
  76.982 +{  398,  477}, {  399,  601}, {  400,  603}, {  401,  402}, {  403,  608}, {  404,  611}, {  406,  617},
  76.983 +{  407,  616}, {  408,  409}, {  412,  623}, {  413,  626}, {  415,  629}, {  416,  417}, {  418,  419},
  76.984 +{  420,  421}, {  423,  424}, {  425,  643}, {  428,  429}, {  430,  648}, {  431,  432}, {  433,  650},
  76.985 +{  434,  651}, {  435,  436}, {  437,  438}, {  439,  658}, {  440,  441}, {  444,  445}, {  452,  454},
  76.986 +{  455,  457}, {  458,  460}, {  461,  462}, {  463,  464}, {  465,  466}, {  467,  468}, {  469,  470},
  76.987 +{  471,  472}, {  473,  474}, {  475,  476}, {  478,  479}, {  480,  481}, {  482,  483}, {  484,  485},
  76.988 +{  486,  487}, {  488,  489}, {  490,  491}, {  492,  493}, {  494,  495}, {  497,  499}, {  500,  501},
  76.989 +{  506,  507}, {  508,  509}, {  510,  511}, {  512,  513}, {  514,  515}, {  516,  517}, {  518,  519},
  76.990 +{  520,  521}, {  522,  523}, {  524,  525}, {  526,  527}, {  528,  529}, {  530,  531}, {  532,  533},
  76.991 +{  534,  535}, {  902,  940}, {  904,  941}, {  905,  942}, {  906,  943}, {  908,  972}, {  910,  973},
  76.992 +{  911,  974}, {  913,  945}, {  914,  946}, {  915,  947}, {  916,  948}, {  917,  949}, {  918,  950},
  76.993 +{  919,  951}, {  920,  952}, {  921,  953}, {  922,  954}, {  923,  955}, {  924,  956}, {  925,  957},
  76.994 +{  926,  958}, {  927,  959}, {  928,  960}, {  929,  961}, {  931,  963}, {  932,  964}, {  933,  965},
  76.995 +{  934,  966}, {  935,  967}, {  936,  968}, {  937,  969}, {  938,  970}, {  939,  971}, {  994,  995},
  76.996 +{  996,  997}, {  998,  999}, { 1000, 1001}, { 1002, 1003}, { 1004, 1005}, { 1006, 1007}, { 1024, 1104}, { 1025, 1105},
  76.997 +{ 1026, 1106}, { 1027, 1107}, { 1028, 1108}, { 1029, 1109}, { 1030, 1110}, { 1031, 1111}, { 1032, 1112},
  76.998 +{ 1033, 1113}, { 1034, 1114}, { 1035, 1115}, { 1036, 1116}, { 1037, 1117}, { 1038, 1118}, { 1039, 1119}, { 1040, 1072},
  76.999 +{ 1041, 1073}, { 1042, 1074}, { 1043, 1075}, { 1044, 1076}, { 1045, 1077}, { 1046, 1078}, { 1047, 1079},
 76.1000 +{ 1048, 1080}, { 1049, 1081}, { 1050, 1082}, { 1051, 1083}, { 1052, 1084}, { 1053, 1085}, { 1054, 1086},
 76.1001 +{ 1055, 1087}, { 1056, 1088}, { 1057, 1089}, { 1058, 1090}, { 1059, 1091}, { 1060, 1092}, { 1061, 1093},
 76.1002 +{ 1062, 1094}, { 1063, 1095}, { 1064, 1096}, { 1065, 1097}, { 1066, 1098}, { 1067, 1099}, { 1068, 1100},
 76.1003 +{ 1069, 1101}, { 1070, 1102}, { 1071, 1103}, { 1120, 1121}, { 1122, 1123}, { 1124, 1125}, { 1126, 1127},
 76.1004 +{ 1128, 1129}, { 1130, 1131}, { 1132, 1133}, { 1134, 1135}, { 1136, 1137}, { 1138, 1139}, { 1140, 1141},
 76.1005 +{ 1142, 1143}, { 1144, 1145}, { 1146, 1147}, { 1148, 1149}, { 1150, 1151}, { 1152, 1153}, { 1168, 1169},
 76.1006 +{ 1170, 1171}, { 1172, 1173}, { 1174, 1175}, { 1176, 1177}, { 1178, 1179}, { 1180, 1181}, { 1182, 1183},
 76.1007 +{ 1184, 1185}, { 1186, 1187}, { 1188, 1189}, { 1190, 1191}, { 1192, 1193}, { 1194, 1195}, { 1196, 1197},
 76.1008 +{ 1198, 1199}, { 1200, 1201}, { 1202, 1203}, { 1204, 1205}, { 1206, 1207}, { 1208, 1209}, { 1210, 1211},
 76.1009 +{ 1212, 1213}, { 1214, 1215}, { 1217, 1218}, { 1219, 1220}, { 1223, 1224}, { 1227, 1228}, { 1232, 1233},
 76.1010 +{ 1234, 1235}, { 1236, 1237}, { 1238, 1239}, { 1240, 1241}, { 1242, 1243}, { 1244, 1245}, { 1246, 1247},
 76.1011 +{ 1248, 1249}, { 1250, 1251}, { 1252, 1253}, { 1254, 1255}, { 1256, 1257}, { 1258, 1259}, { 1262, 1263},
 76.1012 +{ 1264, 1265}, { 1266, 1267}, { 1268, 1269}, { 1272, 1273}, { 1329, 1377}, { 1330, 1378}, { 1331, 1379},
 76.1013 +{ 1332, 1380}, { 1333, 1381}, { 1334, 1382}, { 1335, 1383}, { 1336, 1384}, { 1337, 1385}, { 1338, 1386},
 76.1014 +{ 1339, 1387}, { 1340, 1388}, { 1341, 1389}, { 1342, 1390}, { 1343, 1391}, { 1344, 1392}, { 1345, 1393},
 76.1015 +{ 1346, 1394}, { 1347, 1395}, { 1348, 1396}, { 1349, 1397}, { 1350, 1398}, { 1351, 1399}, { 1352, 1400},
 76.1016 +{ 1353, 1401}, { 1354, 1402}, { 1355, 1403}, { 1356, 1404}, { 1357, 1405}, { 1358, 1406}, { 1359, 1407},
 76.1017 +{ 1360, 1408}, { 1361, 1409}, { 1362, 1410}, { 1363, 1411}, { 1364, 1412}, { 1365, 1413}, { 1366, 1414},
 76.1018 +{ 4256, 4304}, { 4257, 4305}, { 4258, 4306}, { 4259, 4307}, { 4260, 4308}, { 4261, 4309}, { 4262, 4310},
 76.1019 +{ 4263, 4311}, { 4264, 4312}, { 4265, 4313}, { 4266, 4314}, { 4267, 4315}, { 4268, 4316}, { 4269, 4317},
 76.1020 +{ 4270, 4318}, { 4271, 4319}, { 4272, 4320}, { 4273, 4321}, { 4274, 4322}, { 4275, 4323}, { 4276, 4324},
 76.1021 +{ 4277, 4325}, { 4278, 4326}, { 4279, 4327}, { 4280, 4328}, { 4281, 4329}, { 4282, 4330}, { 4283, 4331},
 76.1022 +{ 4284, 4332}, { 4285, 4333}, { 4286, 4334}, { 4287, 4335}, { 4288, 4336}, { 4289, 4337}, { 4290, 4338},
 76.1023 +{ 4291, 4339}, { 4292, 4340}, { 4293, 4341}, { 7680, 7681}, { 7682, 7683}, { 7684, 7685}, { 7686, 7687},
 76.1024 +{ 7688, 7689}, { 7690, 7691}, { 7692, 7693}, { 7694, 7695}, { 7696, 7697}, { 7698, 7699}, { 7700, 7701},
 76.1025 +{ 7702, 7703}, { 7704, 7705}, { 7706, 7707}, { 7708, 7709}, { 7710, 7711}, { 7712, 7713}, { 7714, 7715},
 76.1026 +{ 7716, 7717}, { 7718, 7719}, { 7720, 7721}, { 7722, 7723}, { 7724, 7725}, { 7726, 7727}, { 7728, 7729},
 76.1027 +{ 7730, 7731}, { 7732, 7733}, { 7734, 7735}, { 7736, 7737}, { 7738, 7739}, { 7740, 7741}, { 7742, 7743},
 76.1028 +{ 7744, 7745}, { 7746, 7747}, { 7748, 7749}, { 7750, 7751}, { 7752, 7753}, { 7754, 7755}, { 7756, 7757},
 76.1029 +{ 7758, 7759}, { 7760, 7761}, { 7762, 7763}, { 7764, 7765}, { 7766, 7767}, { 7768, 7769}, { 7770, 7771},
 76.1030 +{ 7772, 7773}, { 7774, 7775}, { 7776, 7777}, { 7778, 7779}, { 7780, 7781}, { 7782, 7783}, { 7784, 7785},
 76.1031 +{ 7786, 7787}, { 7788, 7789}, { 7790, 7791}, { 7792, 7793}, { 7794, 7795}, { 7796, 7797}, { 7798, 7799},
 76.1032 +{ 7800, 7801}, { 7802, 7803}, { 7804, 7805}, { 7806, 7807}, { 7808, 7809}, { 7810, 7811}, { 7812, 7813},
 76.1033 +{ 7814, 7815}, { 7816, 7817}, { 7818, 7819}, { 7820, 7821}, { 7822, 7823}, { 7824, 7825}, { 7826, 7827},
 76.1034 +{ 7828, 7829}, { 7840, 7841}, { 7842, 7843}, { 7844, 7845}, { 7846, 7847}, { 7848, 7849}, { 7850, 7851},
 76.1035 +{ 7852, 7853}, { 7854, 7855}, { 7856, 7857}, { 7858, 7859}, { 7860, 7861}, { 7862, 7863}, { 7864, 7865},
 76.1036 +{ 7866, 7867}, { 7868, 7869}, { 7870, 7871}, { 7872, 7873}, { 7874, 7875}, { 7876, 7877}, { 7878, 7879},
 76.1037 +{ 7880, 7881}, { 7882, 7883}, { 7884, 7885}, { 7886, 7887}, { 7888, 7889}, { 7890, 7891}, { 7892, 7893},
 76.1038 +{ 7894, 7895}, { 7896, 7897}, { 7898, 7899}, { 7900, 7901}, { 7902, 7903}, { 7904, 7905}, { 7906, 7907},
 76.1039 +{ 7908, 7909}, { 7910, 7911}, { 7912, 7913}, { 7914, 7915}, { 7916, 7917}, { 7918, 7919}, { 7920, 7921},
 76.1040 +{ 7922, 7923}, { 7924, 7925}, { 7926, 7927}, { 7928, 7929}, { 7944, 7936}, { 7945, 7937}, { 7946, 7938},
 76.1041 +{ 7947, 7939}, { 7948, 7940}, { 7949, 7941}, { 7950, 7942}, { 7951, 7943}, { 7960, 7952}, { 7961, 7953},
 76.1042 +{ 7962, 7954}, { 7963, 7955}, { 7964, 7956}, { 7965, 7957}, { 7976, 7968}, { 7977, 7969}, { 7978, 7970},
 76.1043 +{ 7979, 7971}, { 7980, 7972}, { 7981, 7973}, { 7982, 7974}, { 7983, 7975}, { 7992, 7984}, { 7993, 7985},
 76.1044 +{ 7994, 7986}, { 7995, 7987}, { 7996, 7988}, { 7997, 7989}, { 7998, 7990}, { 7999, 7991}, { 8008, 8000},
 76.1045 +{ 8009, 8001}, { 8010, 8002}, { 8011, 8003}, { 8012, 8004}, { 8013, 8005}, { 8025, 8017}, { 8027, 8019},
 76.1046 +{ 8029, 8021}, { 8031, 8023}, { 8040, 8032}, { 8041, 8033}, { 8042, 8034}, { 8043, 8035}, { 8044, 8036},
 76.1047 +{ 8045, 8037}, { 8046, 8038}, { 8047, 8039}, { 8120, 8112}, { 8121, 8113}, { 8122, 8048}, { 8123, 8049},
 76.1048 +{ 8136, 8050}, { 8137, 8051}, { 8138, 8052}, { 8139, 8053}, { 8152, 8144}, { 8153, 8145}, { 8154, 8054},
 76.1049 +{ 8155, 8055}, { 8168, 8160}, { 8169, 8161}, { 8170, 8058}, { 8171, 8059}, { 8172, 8165}, { 8184, 8056},
 76.1050 +{ 8185, 8057}, { 8186, 8060}, { 8187, 8061}, { 8544, 8560}, { 8545, 8561}, { 8546, 8562}, { 8547, 8563},
 76.1051 +{ 8548, 8564}, { 8549, 8565}, { 8550, 8566}, { 8551, 8567}, { 8552, 8568}, { 8553, 8569}, { 8554, 8570},
 76.1052 +{ 8555, 8571}, { 8556, 8572}, { 8557, 8573}, { 8558, 8574}, { 8559, 8575}, { 9398, 9424}, { 9399, 9425},
 76.1053 +{ 9400, 9426}, { 9401, 9427}, { 9402, 9428}, { 9403, 9429}, { 9404, 9430}, { 9405, 9431}, { 9406, 9432},
 76.1054 +{ 9407, 9433}, { 9408, 9434}, { 9409, 9435}, { 9410, 9436}, { 9411, 9437}, { 9412, 9438}, { 9413, 9439},
 76.1055 +{ 9414, 9440}, { 9415, 9441}, { 9416, 9442}, { 9417, 9443}, { 9418, 9444}, { 9419, 9445}, { 9420, 9446},
 76.1056 +{ 9421, 9447}, { 9422, 9448}, { 9423, 9449}, {65313,65345}, {65314,65346}, {65315,65347}, {65316,65348},
 76.1057 +{65317,65349}, {65318,65350}, {65319,65351}, {65320,65352}, {65321,65353}, {65322,65354}, {65323,65355},
 76.1058 +{65324,65356}, {65325,65357}, {65326,65358}, {65327,65359}, {65328,65360}, {65329,65361}, {65330,65362},
 76.1059 +{65331,65363}, {65332,65364}, {65333,65365}, {65334,65366}, {65335,65367}, {65336,65368}, {65337,65369},
 76.1060 +{65338,65370}, {65535,    0}};
 76.1061 +
 76.1062 +int OVR_CDECL OVR_towupper(wchar_t charCode)
 76.1063 +{
 76.1064 +    // Don't use UnicodeUpperBits! It differs from UnicodeToUpperBits.
 76.1065 +    if (UnicodeCharIs(UnicodeToUpperBits, charCode))
 76.1066 +    {
 76.1067 +        // To protect from memory overrun in case the character is not found
 76.1068 +        // we use one extra fake element in the table {65536, 0}.
 76.1069 +        size_t idx = Alg::LowerBoundSliced(
 76.1070 +            UnicodeToUpperTable,
 76.1071 +            0,
 76.1072 +            sizeof(UnicodeToUpperTable) / sizeof(UnicodeToUpperTable[0]) - 1,
 76.1073 +            (uint16_t)charCode,
 76.1074 +            CmpUnicodeKey);
 76.1075 +        return UnicodeToUpperTable[idx].Value;
 76.1076 +    }
 76.1077 +    return charCode;
 76.1078 +}
 76.1079 +
 76.1080 +int OVR_CDECL OVR_towlower(wchar_t charCode)
 76.1081 +{
 76.1082 +    // Don't use UnicodeLowerBits! It differs from UnicodeToLowerBits.
 76.1083 +    if (UnicodeCharIs(UnicodeToLowerBits, charCode))
 76.1084 +    {
 76.1085 +        // To protect from memory overrun in case the character is not found
 76.1086 +        // we use one extra fake element in the table {65536, 0}.
 76.1087 +        size_t idx = Alg::LowerBoundSliced(
 76.1088 +            UnicodeToLowerTable,
 76.1089 +            0,
 76.1090 +            sizeof(UnicodeToLowerTable) / sizeof(UnicodeToLowerTable[0]) - 1,
 76.1091 +            (uint16_t)charCode,
 76.1092 +            CmpUnicodeKey);
 76.1093 +        return UnicodeToLowerTable[idx].Value;
 76.1094 +    }
 76.1095 +    return charCode;
 76.1096 +}
 76.1097 +
 76.1098 +#endif //OVR_NO_WCTYPE
 76.1099 +
 76.1100 +} // OVR
    77.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    77.2 +++ b/LibOVR/Src/Kernel/OVR_Std.h	Wed Jan 14 06:51:16 2015 +0200
    77.3 @@ -0,0 +1,638 @@
    77.4 +/************************************************************************************
    77.5 +
    77.6 +PublicHeader:   OVR_Kernel.h
    77.7 +Filename    :   OVR_Std.h
    77.8 +Content     :   Standard C function interface
    77.9 +Created     :   September 19, 2012
   77.10 +Notes       : 
   77.11 +
   77.12 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   77.13 +
   77.14 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
   77.15 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
   77.16 +which is provided at the time of installation or download, or which 
   77.17 +otherwise accompanies this software in either electronic or hard copy form.
   77.18 +
   77.19 +You may obtain a copy of the License at
   77.20 +
   77.21 +http://www.oculusvr.com/licenses/LICENSE-3.2 
   77.22 +
   77.23 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
   77.24 +distributed under the License is distributed on an "AS IS" BASIS,
   77.25 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   77.26 +See the License for the specific language governing permissions and
   77.27 +limitations under the License.
   77.28 +
   77.29 +************************************************************************************/
   77.30 +
   77.31 +#ifndef OVR_Std_h
   77.32 +#define OVR_Std_h
   77.33 +
   77.34 +#include "OVR_Types.h"
   77.35 +#include <stdarg.h> // for va_list args
   77.36 +#include <string.h>
   77.37 +#include <stdio.h>
   77.38 +#include <stdlib.h>
   77.39 +#include <ctype.h>
   77.40 +
   77.41 +#if defined(OVR_CC_MSVC) && (OVR_CC_MSVC >= 1400)
   77.42 +#define OVR_MSVC_SAFESTRING
   77.43 +#include <errno.h>
   77.44 +#endif
   77.45 +
   77.46 +// Wide-char funcs
   77.47 +#include <wchar.h>
   77.48 +#include <wctype.h>
   77.49 +
   77.50 +namespace OVR {
   77.51 +
   77.52 +// Has the same behavior as itoa aside from also having a dest size argument.
   77.53 +// Return value: Pointer to the resulting null-terminated string, same as parameter str.
   77.54 +#if defined(OVR_OS_MS)
   77.55 +inline char* OVR_CDECL OVR_itoa(int val, char *dest, size_t destsize, int radix)
   77.56 +{
   77.57 +#if defined(OVR_MSVC_SAFESTRING)
   77.58 +    _itoa_s(val, dest, destsize, radix);
   77.59 +    return dest;
   77.60 +#else
   77.61 +    OVR_UNUSED(destsize);
   77.62 +    return itoa(val, dest, radix);
   77.63 +#endif
   77.64 +}
   77.65 +#else // OVR_OS_MS
   77.66 +inline char* OVR_itoa(int val, char* dest, size_t len, int radix)
   77.67 +{
   77.68 +    if (val == 0)
   77.69 +    {
   77.70 +        if (len > 1)
   77.71 +        {
   77.72 +            dest[0] = '0';
   77.73 +            dest[1] = '\0';  
   77.74 +        }
   77.75 +        else if(len > 0)
   77.76 +            dest[0] = '\0';  
   77.77 +        return dest;
   77.78 +    }
   77.79 +
   77.80 +    // FIXME: Fix the following code to avoid memory write overruns when len is in sufficient.
   77.81 +    int cur = val;
   77.82 +    size_t i    = 0; 
   77.83 +    size_t sign = 0;
   77.84 +
   77.85 +    if (val < 0)
   77.86 +    {
   77.87 +        val = -val;
   77.88 +        sign = 1;
   77.89 +    }
   77.90 +
   77.91 +    while ((val != 0) && (i < (len - 1 - sign)))        
   77.92 +    {
   77.93 +        cur    = val % radix;
   77.94 +        val   /= radix;
   77.95 +
   77.96 +        if (radix == 16)
   77.97 +        {
   77.98 +            switch(cur)
   77.99 +            {
  77.100 +            case 10:
  77.101 +                dest[i] = 'a';
  77.102 +                break;
  77.103 +            case 11:
  77.104 +                dest[i] = 'b';
  77.105 +                break;
  77.106 +            case 12:
  77.107 +                dest[i] = 'c';
  77.108 +                break;
  77.109 +            case 13:
  77.110 +                dest[i] = 'd';
  77.111 +                break;
  77.112 +            case 14:
  77.113 +                dest[i] = 'e';
  77.114 +                break;
  77.115 +            case 15:
  77.116 +                dest[i] = 'f';
  77.117 +                break;
  77.118 +            default:
  77.119 +                dest[i] = (char)('0' + cur);
  77.120 +                break;
  77.121 +            }
  77.122 +        } 
  77.123 +        else
  77.124 +        {
  77.125 +            dest[i] = (char)('0' + cur);
  77.126 +        }
  77.127 +        ++i;
  77.128 +    }
  77.129 +
  77.130 +    if (sign)
  77.131 +    {
  77.132 +        dest[i++] = '-';
  77.133 +    }
  77.134 +
  77.135 +    for (size_t j = 0; j < i / 2; ++j)
  77.136 +    {
  77.137 +        char tmp        = dest[j];
  77.138 +        dest[j]         = dest[i - 1 - j];
  77.139 +        dest[i - 1 - j] = tmp;
  77.140 +    }
  77.141 +    dest[i] = '\0';
  77.142 +
  77.143 +    return dest;
  77.144 +}
  77.145 +
  77.146 +#endif
  77.147 +
  77.148 +
  77.149 +// String functions
  77.150 +
  77.151 +inline size_t OVR_CDECL OVR_strlen(const char* str)
  77.152 +{
  77.153 +    return strlen(str);
  77.154 +}
  77.155 +
  77.156 +inline char* OVR_CDECL OVR_strcpy(char* dest, size_t destsize, const char* src)
  77.157 +{
  77.158 +#if defined(OVR_MSVC_SAFESTRING)
  77.159 +    strcpy_s(dest, destsize, src);
  77.160 +    return dest;
  77.161 +#else
  77.162 +    // FIXME: This should be a safer implementation
  77.163 +    OVR_UNUSED(destsize);
  77.164 +    return strcpy(dest, src);
  77.165 +#endif
  77.166 +}
  77.167 +
  77.168 +
  77.169 +// Acts the same as the strlcpy function. 
  77.170 +// Copies src to dest, 0-terminating even if it involves truncating the write.
  77.171 +// Returns the required strlen of dest (which is one less than the required size of dest).
  77.172 +// strlcpy is a safer alternative to strcpy and strncpy and provides size information.
  77.173 +// However, it still may result in an incomplete copy. 
  77.174 +//
  77.175 +// Example usage:
  77.176 +//     char buffer[256];
  77.177 +//     if(OVR_strlcpy(buffer, "hello world", sizeof(buffer)) < sizeof(buffer))
  77.178 +//         { there was enough space }
  77.179 +//     else
  77.180 +//         { need a larger buffer }
  77.181 +//
  77.182 +size_t OVR_CDECL OVR_strlcpy(char* dest, const char* src, size_t destsize);
  77.183 +
  77.184 +// Acts the same as the strlcat function.
  77.185 +// Appends src to dest, 0-terminating even if it involves an incomplete write.
  77.186 +// Doesn't 0-terminate in the case that destsize is 0.
  77.187 +// Returns the required strlen of dest (which is one less than the required size of dest).
  77.188 +// The terminating 0 char of dest is overwritten by the first 
  77.189 +// character of src, and a new 0 char is appended to dest. The required capacity 
  77.190 +// of the destination is (strlen(src) + strlen(dest) + 1).
  77.191 +// strlcat is a safer alternative to strcat and provides size information.
  77.192 +// However, it still may result in an incomplete copy. 
  77.193 +//
  77.194 +// Example usage:
  77.195 +//     char buffer[256] = "hello ";
  77.196 +//     if(OVR_strlcat(buffer, "world", sizeof(buffer)) < sizeof(buffer))
  77.197 +//         { there was enough space }
  77.198 +//     else
  77.199 +//         { need a larger buffer }
  77.200 +//
  77.201 +size_t OVR_CDECL OVR_strlcat(char* dest, const char* src, size_t destsize);
  77.202 +
  77.203 +
  77.204 +inline char* OVR_CDECL OVR_strncpy(char* dest, size_t destsize, const char* src, size_t count)
  77.205 +{
  77.206 +#if defined(OVR_MSVC_SAFESTRING)
  77.207 +    strncpy_s(dest, destsize, src, count);
  77.208 +    return dest;
  77.209 +#else
  77.210 +    // FIXME: This should be a safer implementation
  77.211 +    OVR_UNUSED(destsize);
  77.212 +    return strncpy(dest, src, count);
  77.213 +#endif
  77.214 +}
  77.215 +
  77.216 +inline char * OVR_CDECL OVR_strcat(char* dest, size_t destsize, const char* src)
  77.217 +{
  77.218 +#if defined(OVR_MSVC_SAFESTRING)
  77.219 +    strcat_s(dest, destsize, src);
  77.220 +    return dest;
  77.221 +#else
  77.222 +    // FIXME: This should be a safer implementation
  77.223 +    OVR_UNUSED(destsize);
  77.224 +    return strcat(dest, src);
  77.225 +#endif
  77.226 +}
  77.227 +
  77.228 +inline int OVR_CDECL OVR_strcmp(const char* dest, const char* src)
  77.229 +{
  77.230 +    return strcmp(dest, src);
  77.231 +}
  77.232 +
  77.233 +inline const char* OVR_CDECL OVR_strchr(const char* str, char c)
  77.234 +{
  77.235 +    return strchr(str, c);
  77.236 +}
  77.237 +
  77.238 +inline char* OVR_CDECL OVR_strchr(char* str, char c)
  77.239 +{
  77.240 +    return strchr(str, c);
  77.241 +}
  77.242 +
  77.243 +inline const char* OVR_strrchr(const char* str, char c)
  77.244 +{
  77.245 +    size_t len = OVR_strlen(str);
  77.246 +    for (size_t i=len; i>0; i--)     
  77.247 +        if (str[i]==c) 
  77.248 +            return str+i;
  77.249 +    return 0;
  77.250 +}
  77.251 +
  77.252 +inline const uint8_t* OVR_CDECL OVR_memrchr(const uint8_t* str, size_t size, uint8_t c)
  77.253 +{
  77.254 +    for (intptr_t i = (intptr_t)size - 1; i >= 0; i--)     
  77.255 +    {
  77.256 +        if (str[i] == c) 
  77.257 +            return str + i;
  77.258 +    }
  77.259 +    return 0;
  77.260 +}
  77.261 +
  77.262 +inline char* OVR_CDECL OVR_strrchr(char* str, char c)
  77.263 +{
  77.264 +    size_t len = OVR_strlen(str);
  77.265 +    for (size_t i=len; i>0; i--)     
  77.266 +        if (str[i]==c) 
  77.267 +            return str+i;
  77.268 +    return 0;
  77.269 +}
  77.270 +
  77.271 +
  77.272 +double OVR_CDECL OVR_strtod(const char* string, char** tailptr);
  77.273 +
  77.274 +inline long OVR_CDECL OVR_strtol(const char* string, char** tailptr, int radix)
  77.275 +{
  77.276 +    return strtol(string, tailptr, radix);
  77.277 +}
  77.278 +
  77.279 +inline long OVR_CDECL OVR_strtoul(const char* string, char** tailptr, int radix)
  77.280 +{
  77.281 +    return strtoul(string, tailptr, radix);
  77.282 +}
  77.283 +
  77.284 +inline int OVR_CDECL OVR_strncmp(const char* ws1, const char* ws2, size_t size)
  77.285 +{
  77.286 +    return strncmp(ws1, ws2, size);
  77.287 +}
  77.288 +
  77.289 +inline uint64_t OVR_CDECL OVR_strtouq(const char *nptr, char **endptr, int base)
  77.290 +{
  77.291 +#if defined(OVR_CC_MSVC)
  77.292 +    return _strtoui64(nptr, endptr, base);
  77.293 +#else
  77.294 +    return strtoull(nptr, endptr, base);
  77.295 +#endif
  77.296 +}
  77.297 +
  77.298 +inline int64_t OVR_CDECL OVR_strtoq(const char *nptr, char **endptr, int base)
  77.299 +{
  77.300 +#if defined(OVR_CC_MSVC)
  77.301 +    return _strtoi64(nptr, endptr, base);
  77.302 +#else
  77.303 +    return strtoll(nptr, endptr, base);
  77.304 +#endif
  77.305 +}
  77.306 +
  77.307 +
  77.308 +inline int64_t OVR_CDECL OVR_atoq(const char* string)
  77.309 +{
  77.310 +#if defined(OVR_CC_MSVC)
  77.311 +    return _atoi64(string);
  77.312 +#else
  77.313 +    return atoll(string);
  77.314 +#endif
  77.315 +}
  77.316 +
  77.317 +inline uint64_t OVR_CDECL OVR_atouq(const char* string)
  77.318 +{
  77.319 +  return OVR_strtouq(string, NULL, 10);
  77.320 +}
  77.321 +
  77.322 +
  77.323 +// Implemented in OVR_Std.cpp in platform-specific manner.
  77.324 +int OVR_CDECL OVR_stricmp(const char* dest, const char* src);
  77.325 +int OVR_CDECL OVR_strnicmp(const char* dest, const char* src, size_t count);
  77.326 +
  77.327 +
  77.328 +// This is like sprintf but with a destination buffer size argument. However, the behavior is different
  77.329 +// from vsnprintf in that the return value semantics are like sprintf (which returns -1 on capacity overflow) and 
  77.330 +// not like snprintf (which returns intended strlen on capacity overflow).
  77.331 +inline size_t OVR_CDECL OVR_sprintf(char *dest, size_t destsize, const char* format, ...)
  77.332 +{
  77.333 +    va_list argList;
  77.334 +    va_start(argList,format);
  77.335 +    size_t ret;
  77.336 +#if defined(OVR_CC_MSVC)
  77.337 +    #if defined(OVR_MSVC_SAFESTRING)
  77.338 +        ret = _vsnprintf_s(dest, destsize, _TRUNCATE, format, argList);
  77.339 +        OVR_ASSERT(ret != -1);
  77.340 +    #else
  77.341 +        OVR_UNUSED(destsize);
  77.342 +        ret = _vsnprintf(dest, destsize - 1, format, argList); // -1 for space for the null character
  77.343 +        OVR_ASSERT(ret != -1);
  77.344 +        dest[destsize-1] = 0;
  77.345 +    #endif
  77.346 +#else
  77.347 +    OVR_UNUSED(destsize);
  77.348 +    ret = vsprintf(dest, format, argList);
  77.349 +    OVR_ASSERT(ret < destsize);
  77.350 +#endif
  77.351 +    va_end(argList);
  77.352 +    return ret;
  77.353 +}
  77.354 +
  77.355 +
  77.356 +// This is like vsprintf but with a destination buffer size argument. However, the behavior is different
  77.357 +// from vsnprintf in that the return value semantics are like vsprintf (which returns -1 on capacity overflow) and 
  77.358 +// not like vsnprintf (which returns intended strlen on capacity overflow).
  77.359 +// Return value:
  77.360 +//    On success, the total number of characters written is returned.
  77.361 +//    On failure, a negative number is returned.
  77.362 +inline size_t OVR_CDECL OVR_vsprintf(char *dest, size_t destsize, const char * format, va_list argList)
  77.363 +{
  77.364 +    size_t ret;
  77.365 +#if defined(OVR_CC_MSVC)
  77.366 +    #if defined(OVR_MSVC_SAFESTRING)
  77.367 +        dest[0] = '\0';
  77.368 +        int rv = vsnprintf_s(dest, destsize, _TRUNCATE, format, argList);
  77.369 +        if (rv == -1)
  77.370 +        {
  77.371 +            dest[destsize - 1] = '\0';
  77.372 +            ret = destsize - 1;
  77.373 +        }
  77.374 +        else
  77.375 +            ret = (size_t)rv;
  77.376 +    #else
  77.377 +        OVR_UNUSED(destsize);
  77.378 +        int rv = _vsnprintf(dest, destsize - 1, format, argList);
  77.379 +        OVR_ASSERT(rv != -1);
  77.380 +        ret = (size_t)rv;
  77.381 +        dest[destsize-1] = 0;
  77.382 +    #endif
  77.383 +#else
  77.384 +    // FIXME: This should be a safer implementation
  77.385 +    OVR_UNUSED(destsize);
  77.386 +    ret = (size_t)vsprintf(dest, format, argList);
  77.387 +    OVR_ASSERT(ret < destsize);
  77.388 +#endif
  77.389 +    return ret;
  77.390 +}
  77.391 +
  77.392 +// Same behavior as ISO C99 vsnprintf.
  77.393 +// Returns the strlen of the resulting formatted string, or a negative value if the format is invalid.
  77.394 +// destsize specifies the capacity of the input buffer.
  77.395 +//
  77.396 +// Example usage:
  77.397 +//     void Log(char *dest, size_t destsize, const char * format, ...)
  77.398 +//     {
  77.399 +//         char buffer[1024];
  77.400 +//         va_list argList;
  77.401 +//         va_start(argList,format);
  77.402 +//         int result = OVR_vsnprintf(dest, destsize, format, argList);
  77.403 +//         assert(result < destsize); // Else we'd have to retry with a dynamically allocated buffer (of size=result+1) and new argList copy.
  77.404 +//         va_end(argList);
  77.405 +//     }
  77.406 +
  77.407 +inline int OVR_CDECL OVR_vsnprintf(char *dest, size_t destsize, const char * format, va_list argList)
  77.408 +{
  77.409 +    int ret;
  77.410 +#if defined(OVR_CC_MSVC)
  77.411 +    OVR_DISABLE_MSVC_WARNING(4996) // 'vsnprintf': This function or variable may be unsafe.
  77.412 +    ret = vsnprintf(dest, destsize, format, argList); // Microsoft vsnprintf is non-conforming; it returns -1 if destsize is insufficient.
  77.413 +    if (ret < 0) // If there was a format error or if destsize was insufficient...
  77.414 +    {
  77.415 +        ret = _vscprintf(format, argList); // Get the expected dest strlen. If the return value is still -1 then there was a format error.
  77.416 +
  77.417 +        if (destsize) // If we can 0-terminate the output...
  77.418 +        {
  77.419 +            if (ret < 0)
  77.420 +                dest[0] = 0;
  77.421 +            else
  77.422 +                dest[destsize-1] = 0;
  77.423 +        }
  77.424 +    }
  77.425 +    // Else the string was written OK and ret is its strlen.
  77.426 +    OVR_RESTORE_MSVC_WARNING()
  77.427 +#else
  77.428 +    ret = vsnprintf(dest, destsize, format, argList);
  77.429 +#endif
  77.430 +    return ret;
  77.431 +}
  77.432 +
  77.433 +
  77.434 +// Same behavior as ISO C99 snprintf.
  77.435 +// Returns the strlen of the resulting formatted string, or a negative value if the format is invalid.
  77.436 +// destsize specifies the capacity of the input buffer.
  77.437 +//
  77.438 +// Example usage:
  77.439 +//     char buffer[16];
  77.440 +//     int result = OVR_snprintf(buffer, sizeof(buffer), "%d", 37);
  77.441 +//     if (result >= sizeof(buffer)) // If there was insufficient capacity...
  77.442 +//     {
  77.443 +//         char* p = new char[result + 1]; // Or char* p = (char*)OVR_ALLOC(result + 1);
  77.444 +//         OVR_snprintf(p, (size_t)result, "%d", 37);
  77.445 +//         delete[] p;
  77.446 +//     }
  77.447 +//
  77.448 +inline int OVR_CDECL OVR_snprintf(char *dest, size_t destsize, const char * format, ...)
  77.449 +{
  77.450 +    va_list argList;
  77.451 +    va_start(argList,format);
  77.452 +    int ret = OVR_vsnprintf(dest, destsize, format, argList);
  77.453 +    va_end(argList);
  77.454 +    return ret;
  77.455 +}
  77.456 +
  77.457 +
  77.458 +// Returns the strlen of the resulting formatted string, or a negative value if the format is invalid.
  77.459 +// Note: If you are planning on printing a string then it's more efficient to just use OVR_vsnprintf and 
  77.460 +// look at the return value and handle the uncommon case that there wasn't enough space.
  77.461 +inline int OVR_CDECL OVR_vscprintf(const char * format, va_list argList)
  77.462 +{
  77.463 +    int ret;
  77.464 +#if defined(OVR_CC_MSVC)
  77.465 +    ret = _vscprintf(format, argList);
  77.466 +#else    
  77.467 +    ret = vsnprintf(NULL, 0, format, argList);
  77.468 +#endif
  77.469 +    return ret;       
  77.470 +}
  77.471 +
  77.472 +
  77.473 +wchar_t* OVR_CDECL OVR_wcscpy(wchar_t* dest, size_t destsize, const wchar_t* src);
  77.474 +wchar_t* OVR_CDECL OVR_wcsncpy(wchar_t* dest, size_t destsize, const wchar_t* src, size_t count);
  77.475 +wchar_t* OVR_CDECL OVR_wcscat(wchar_t* dest, size_t destsize, const wchar_t* src);
  77.476 +size_t   OVR_CDECL OVR_wcslen(const wchar_t* str);
  77.477 +int      OVR_CDECL OVR_wcscmp(const wchar_t* a, const wchar_t* b);
  77.478 +int      OVR_CDECL OVR_wcsicmp(const wchar_t* a, const wchar_t* b);
  77.479 +
  77.480 +inline int OVR_CDECL OVR_wcsicoll(const wchar_t* a, const wchar_t* b)
  77.481 +{
  77.482 +#if defined(OVR_OS_MS)
  77.483 +    #if defined(OVR_CC_MSVC) && (OVR_CC_MSVC >= 1400)
  77.484 +        return ::_wcsicoll(a, b);
  77.485 +    #else
  77.486 +        return ::wcsicoll(a, b);
  77.487 +    #endif
  77.488 +#else
  77.489 +    // not supported, use regular wcsicmp
  77.490 +    return OVR_wcsicmp(a, b);
  77.491 +#endif
  77.492 +}
  77.493 +
  77.494 +inline int OVR_CDECL OVR_wcscoll(const wchar_t* a, const wchar_t* b)
  77.495 +{
  77.496 +#if defined(OVR_OS_MS) || defined(OVR_OS_LINUX)
  77.497 +    return wcscoll(a, b);
  77.498 +#else
  77.499 +    // not supported, use regular wcscmp
  77.500 +    return OVR_wcscmp(a, b);
  77.501 +#endif
  77.502 +}
  77.503 +
  77.504 +#ifndef OVR_NO_WCTYPE
  77.505 +
  77.506 +inline int OVR_CDECL UnicodeCharIs(const uint16_t* table, wchar_t charCode)
  77.507 +{
  77.508 +    unsigned offset = table[charCode >> 8];
  77.509 +    if (offset == 0) return 0;
  77.510 +    if (offset == 1) return 1;
  77.511 +    return (table[offset + ((charCode >> 4) & 15)] & (1 << (charCode & 15))) != 0;
  77.512 +}
  77.513 +
  77.514 +extern const uint16_t UnicodeAlnumBits[];
  77.515 +extern const uint16_t UnicodeAlphaBits[];
  77.516 +extern const uint16_t UnicodeDigitBits[];
  77.517 +extern const uint16_t UnicodeSpaceBits[];
  77.518 +extern const uint16_t UnicodeXDigitBits[];
  77.519 +
  77.520 +// Uncomment if necessary
  77.521 +//extern const uint16_t UnicodeCntrlBits[];
  77.522 +//extern const uint16_t UnicodeGraphBits[];
  77.523 +//extern const uint16_t UnicodeLowerBits[];
  77.524 +//extern const uint16_t UnicodePrintBits[];
  77.525 +//extern const uint16_t UnicodePunctBits[];
  77.526 +//extern const uint16_t UnicodeUpperBits[];
  77.527 +
  77.528 +inline int OVR_CDECL OVR_iswalnum (wchar_t charCode) { return UnicodeCharIs(UnicodeAlnumBits,  charCode); }
  77.529 +inline int OVR_CDECL OVR_iswalpha (wchar_t charCode) { return UnicodeCharIs(UnicodeAlphaBits,  charCode); }
  77.530 +inline int OVR_CDECL OVR_iswdigit (wchar_t charCode) { return UnicodeCharIs(UnicodeDigitBits,  charCode); }
  77.531 +inline int OVR_CDECL OVR_iswspace (wchar_t charCode) { return UnicodeCharIs(UnicodeSpaceBits,  charCode); }
  77.532 +inline int OVR_CDECL OVR_iswxdigit(wchar_t charCode) { return UnicodeCharIs(UnicodeXDigitBits, charCode); }
  77.533 +
  77.534 +// Uncomment if necessary
  77.535 +//inline int OVR_CDECL OVR_iswcntrl (wchar_t charCode) { return UnicodeCharIs(UnicodeCntrlBits,  charCode); }
  77.536 +//inline int OVR_CDECL OVR_iswgraph (wchar_t charCode) { return UnicodeCharIs(UnicodeGraphBits,  charCode); }
  77.537 +//inline int OVR_CDECL OVR_iswlower (wchar_t charCode) { return UnicodeCharIs(UnicodeLowerBits,  charCode); }
  77.538 +//inline int OVR_CDECL OVR_iswprint (wchar_t charCode) { return UnicodeCharIs(UnicodePrintBits,  charCode); }
  77.539 +//inline int OVR_CDECL OVR_iswpunct (wchar_t charCode) { return UnicodeCharIs(UnicodePunctBits,  charCode); }
  77.540 +//inline int OVR_CDECL OVR_iswupper (wchar_t charCode) { return UnicodeCharIs(UnicodeUpperBits,  charCode); }
  77.541 +
  77.542 +int OVR_CDECL OVR_towupper(wchar_t charCode);
  77.543 +int OVR_CDECL OVR_towlower(wchar_t charCode);
  77.544 +
  77.545 +#else // OVR_NO_WCTYPE
  77.546 +
  77.547 +inline int OVR_CDECL OVR_iswspace(wchar_t c)
  77.548 +{
  77.549 +    return iswspace(c);
  77.550 +}
  77.551 +
  77.552 +inline int OVR_CDECL OVR_iswdigit(wchar_t c)
  77.553 +{
  77.554 +    return iswdigit(c);
  77.555 +}
  77.556 +
  77.557 +inline int OVR_CDECL OVR_iswxdigit(wchar_t c)
  77.558 +{
  77.559 +    return iswxdigit(c);
  77.560 +}
  77.561 +
  77.562 +inline int OVR_CDECL OVR_iswalpha(wchar_t c)
  77.563 +{
  77.564 +    return iswalpha(c);
  77.565 +}
  77.566 +
  77.567 +inline int OVR_CDECL OVR_iswalnum(wchar_t c)
  77.568 +{
  77.569 +    return iswalnum(c);
  77.570 +}
  77.571 +
  77.572 +inline wchar_t OVR_CDECL OVR_towlower(wchar_t c)
  77.573 +{
  77.574 +    return (wchar_t)towlower(c);
  77.575 +}
  77.576 +
  77.577 +inline wchar_t OVR_towupper(wchar_t c)
  77.578 +{
  77.579 +    return (wchar_t)towupper(c);
  77.580 +}
  77.581 +
  77.582 +#endif // OVR_NO_WCTYPE
  77.583 +
  77.584 +// ASCII versions of tolower and toupper. Don't use "char"
  77.585 +inline int OVR_CDECL OVR_tolower(int c)
  77.586 +{
  77.587 +    return (c >= 'A' && c <= 'Z') ? c - 'A' + 'a' : c;
  77.588 +}
  77.589 +
  77.590 +inline int OVR_CDECL OVR_toupper(int c)
  77.591 +{
  77.592 +    return (c >= 'a' && c <= 'z') ? c - 'a' + 'A' : c;
  77.593 +}
  77.594 +
  77.595 +
  77.596 +
  77.597 +inline double OVR_CDECL OVR_wcstod(const wchar_t* string, wchar_t** tailptr)
  77.598 +{
  77.599 +#if defined(OVR_OS_OTHER)
  77.600 +    OVR_UNUSED(tailptr);
  77.601 +    char buffer[64];
  77.602 +    char* tp = NULL;
  77.603 +    size_t max = OVR_wcslen(string);
  77.604 +    if (max > 63) max = 63;
  77.605 +    unsigned char c = 0;
  77.606 +    for (size_t i=0; i < max; i++)
  77.607 +    {
  77.608 +        c = (unsigned char)string[i];
  77.609 +        buffer[i] = ((c) < 128 ? (char)c : '!');
  77.610 +    }
  77.611 +    buffer[max] = 0;
  77.612 +    return OVR_strtod(buffer, &tp);
  77.613 +#else
  77.614 +    return wcstod(string, tailptr);
  77.615 +#endif
  77.616 +}
  77.617 +
  77.618 +inline long OVR_CDECL OVR_wcstol(const wchar_t* string, wchar_t** tailptr, int radix)
  77.619 +{
  77.620 +#if defined(OVR_OS_OTHER)
  77.621 +    OVR_UNUSED(tailptr);
  77.622 +    char buffer[64];
  77.623 +    char* tp = NULL;
  77.624 +    size_t max = OVR_wcslen(string);
  77.625 +    if (max > 63) max = 63;
  77.626 +    unsigned char c = 0;
  77.627 +    for (size_t i=0; i < max; i++)
  77.628 +    {
  77.629 +        c = (unsigned char)string[i];
  77.630 +        buffer[i] = ((c) < 128 ? (char)c : '!');
  77.631 +    }
  77.632 +    buffer[max] = 0;
  77.633 +    return strtol(buffer, &tp, radix);
  77.634 +#else
  77.635 +    return wcstol(string, tailptr, radix);
  77.636 +#endif
  77.637 +}
  77.638 +
  77.639 +} // OVR
  77.640 +
  77.641 +#endif // OVR_Std_h
    78.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    78.2 +++ b/LibOVR/Src/Kernel/OVR_String.cpp	Wed Jan 14 06:51:16 2015 +0200
    78.3 @@ -0,0 +1,779 @@
    78.4 +/************************************************************************************
    78.5 +
    78.6 +Filename    :   OVR_String.cpp
    78.7 +Content     :   String UTF8 string implementation with copy-on-write semantics
    78.8 +                (thread-safe for assignment but not modification).
    78.9 +Created     :   September 19, 2012
   78.10 +Notes       : 
   78.11 +
   78.12 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   78.13 +
   78.14 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
   78.15 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
   78.16 +which is provided at the time of installation or download, or which 
   78.17 +otherwise accompanies this software in either electronic or hard copy form.
   78.18 +
   78.19 +You may obtain a copy of the License at
   78.20 +
   78.21 +http://www.oculusvr.com/licenses/LICENSE-3.2 
   78.22 +
   78.23 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
   78.24 +distributed under the License is distributed on an "AS IS" BASIS,
   78.25 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   78.26 +See the License for the specific language governing permissions and
   78.27 +limitations under the License.
   78.28 +
   78.29 +************************************************************************************/
   78.30 +
   78.31 +#include "OVR_String.h"
   78.32 +
   78.33 +#include <stdlib.h>
   78.34 +#include <ctype.h>
   78.35 +
   78.36 +#ifdef OVR_OS_QNX
   78.37 +# include <strings.h>
   78.38 +#endif
   78.39 +
   78.40 +namespace OVR {
   78.41 +
   78.42 +#define String_LengthIsSize (size_t(1) << String::Flag_LengthIsSizeShift)
   78.43 +
   78.44 +String::DataDesc String::NullData = {String_LengthIsSize, 1, {0} };
   78.45 +
   78.46 +
   78.47 +String::String()
   78.48 +{
   78.49 +    pData = &NullData;
   78.50 +    pData->AddRef();
   78.51 +};
   78.52 +
   78.53 +String::String(const char* pdata)
   78.54 +{
   78.55 +    // Obtain length in bytes; it doesn't matter if _data is UTF8.
   78.56 +    size_t size = pdata ? OVR_strlen(pdata) : 0; 
   78.57 +    pData = AllocDataCopy1(size, 0, pdata, size);
   78.58 +};
   78.59 +
   78.60 +String::String(const char* pdata1, const char* pdata2, const char* pdata3)
   78.61 +{
   78.62 +    // Obtain length in bytes; it doesn't matter if _data is UTF8.
   78.63 +    size_t size1 = pdata1 ? OVR_strlen(pdata1) : 0; 
   78.64 +    size_t size2 = pdata2 ? OVR_strlen(pdata2) : 0; 
   78.65 +    size_t size3 = pdata3 ? OVR_strlen(pdata3) : 0; 
   78.66 +
   78.67 +    DataDesc *pdataDesc = AllocDataCopy2(size1 + size2 + size3, 0,
   78.68 +                                         pdata1, size1, pdata2, size2);
   78.69 +    memcpy(pdataDesc->Data + size1 + size2, pdata3, size3);   
   78.70 +    pData = pdataDesc;    
   78.71 +}
   78.72 +
   78.73 +String::String(const char* pdata, size_t size)
   78.74 +{
   78.75 +    OVR_ASSERT((size == 0) || (pdata != 0));
   78.76 +    pData = AllocDataCopy1(size, 0, pdata, size);
   78.77 +};
   78.78 +
   78.79 +
   78.80 +String::String(const InitStruct& src, size_t size)
   78.81 +{
   78.82 +    pData = AllocData(size, 0);
   78.83 +    src.InitString(GetData()->Data, size);
   78.84 +}
   78.85 +
   78.86 +String::String(const String& src)
   78.87 +{    
   78.88 +    pData = src.GetData();
   78.89 +    pData->AddRef();
   78.90 +}
   78.91 +
   78.92 +String::String(const StringBuffer& src)
   78.93 +{
   78.94 +    pData = AllocDataCopy1(src.GetSize(), 0, src.ToCStr(), src.GetSize());
   78.95 +}
   78.96 +
   78.97 +String::String(const wchar_t* data)
   78.98 +{
   78.99 +    pData = &NullData;
  78.100 +    pData->AddRef();
  78.101 +    // Simplified logic for wchar_t constructor.
  78.102 +    if (data)    
  78.103 +        *this = data;    
  78.104 +}
  78.105 +
  78.106 +
  78.107 +String::DataDesc* String::AllocData(size_t size, size_t lengthIsSize)
  78.108 +{
  78.109 +    String::DataDesc* pdesc;
  78.110 +
  78.111 +    if (size == 0)
  78.112 +    {
  78.113 +        pdesc = &NullData;
  78.114 +        pdesc->AddRef();
  78.115 +        return pdesc;
  78.116 +    }
  78.117 +
  78.118 +    pdesc = (DataDesc*)OVR_ALLOC(sizeof(DataDesc)+ size);
  78.119 +    pdesc->Data[size] = 0;
  78.120 +    pdesc->RefCount = 1;
  78.121 +    pdesc->Size     = size | lengthIsSize;  
  78.122 +    return pdesc;
  78.123 +}
  78.124 +
  78.125 +
  78.126 +String::DataDesc* String::AllocDataCopy1(size_t size, size_t lengthIsSize,
  78.127 +                                         const char* pdata, size_t copySize)
  78.128 +{
  78.129 +    String::DataDesc* pdesc = AllocData(size, lengthIsSize);
  78.130 +    memcpy(pdesc->Data, pdata, copySize);
  78.131 +    return pdesc;
  78.132 +}
  78.133 +
  78.134 +String::DataDesc* String::AllocDataCopy2(size_t size, size_t lengthIsSize,
  78.135 +                                         const char* pdata1, size_t copySize1,
  78.136 +                                         const char* pdata2, size_t copySize2)
  78.137 +{
  78.138 +    String::DataDesc* pdesc = AllocData(size, lengthIsSize);
  78.139 +    memcpy(pdesc->Data, pdata1, copySize1);
  78.140 +    memcpy(pdesc->Data + copySize1, pdata2, copySize2);
  78.141 +    return pdesc;
  78.142 +}
  78.143 +
  78.144 +
  78.145 +size_t String::GetLength() const 
  78.146 +{
  78.147 +    // Optimize length accesses for non-UTF8 character strings. 
  78.148 +    DataDesc* pdata = GetData();
  78.149 +    size_t    length, size = pdata->GetSize();
  78.150 +    
  78.151 +    if (pdata->LengthIsSize())
  78.152 +        return size;    
  78.153 +    
  78.154 +    length = (size_t)UTF8Util::GetLength(pdata->Data, (size_t)size);
  78.155 +    
  78.156 +    if (length == size)
  78.157 +        pdata->Size |= String_LengthIsSize;
  78.158 +    
  78.159 +    return length;
  78.160 +}
  78.161 +
  78.162 +
  78.163 +//static uint32_t String_CharSearch(const char* buf, )
  78.164 +
  78.165 +
  78.166 +uint32_t String::GetCharAt(size_t index) const 
  78.167 +{  
  78.168 +    intptr_t    i = (intptr_t) index;
  78.169 +    DataDesc*   pdata = GetData();
  78.170 +    const char* buf = pdata->Data;
  78.171 +    uint32_t    c;
  78.172 +    
  78.173 +    if (pdata->LengthIsSize())
  78.174 +    {
  78.175 +        OVR_ASSERT(index < pdata->GetSize());
  78.176 +        buf += i;
  78.177 +        return UTF8Util::DecodeNextChar_Advance0(&buf);
  78.178 +    }
  78.179 +
  78.180 +    c = UTF8Util::GetCharAt(index, buf, pdata->GetSize());
  78.181 +    return c;
  78.182 +}
  78.183 +
  78.184 +uint32_t String::GetFirstCharAt(size_t index, const char** offset) const
  78.185 +{
  78.186 +    DataDesc*   pdata = GetData();
  78.187 +    intptr_t    i = (intptr_t) index;
  78.188 +    const char* buf = pdata->Data;
  78.189 +    const char* end = buf + pdata->GetSize();
  78.190 +    uint32_t    c;
  78.191 +
  78.192 +    do 
  78.193 +    {
  78.194 +        c = UTF8Util::DecodeNextChar_Advance0(&buf);
  78.195 +        i--;
  78.196 +
  78.197 +        if (buf >= end)
  78.198 +        {
  78.199 +            // We've hit the end of the string; don't go further.
  78.200 +            OVR_ASSERT(i == 0);
  78.201 +            return c;
  78.202 +        }
  78.203 +    } while (i >= 0);
  78.204 +
  78.205 +    *offset = buf;
  78.206 +
  78.207 +    return c;
  78.208 +}
  78.209 +
  78.210 +uint32_t String::GetNextChar(const char** offset) const
  78.211 +{
  78.212 +    return UTF8Util::DecodeNextChar(offset);
  78.213 +}
  78.214 +
  78.215 +
  78.216 +
  78.217 +void String::AppendChar(uint32_t ch)
  78.218 +{
  78.219 +    DataDesc*   pdata = GetData();
  78.220 +    size_t      size = pdata->GetSize();
  78.221 +    char        buff[8];
  78.222 +    intptr_t    encodeSize = 0;
  78.223 +
  78.224 +    // Converts ch into UTF8 string and fills it into buff.   
  78.225 +    UTF8Util::EncodeChar(buff, &encodeSize, ch);
  78.226 +    OVR_ASSERT(encodeSize >= 0);
  78.227 +
  78.228 +    SetData(AllocDataCopy2(size + (size_t)encodeSize, 0,
  78.229 +                           pdata->Data, size, buff, (size_t)encodeSize));
  78.230 +    pdata->Release();
  78.231 +}
  78.232 +
  78.233 +
  78.234 +void String::AppendString(const wchar_t* pstr, intptr_t len)
  78.235 +{
  78.236 +    if (!pstr)
  78.237 +        return;
  78.238 +
  78.239 +    DataDesc*   pdata = GetData();
  78.240 +    size_t      oldSize = pdata->GetSize();    
  78.241 +    size_t      encodeSize = (size_t)UTF8Util::GetEncodeStringSize(pstr, len);
  78.242 +
  78.243 +    DataDesc*   pnewData = AllocDataCopy1(oldSize + (size_t)encodeSize, 0,
  78.244 +                                          pdata->Data, oldSize);
  78.245 +    UTF8Util::EncodeString(pnewData->Data + oldSize,  pstr, len);
  78.246 +
  78.247 +    SetData(pnewData);
  78.248 +    pdata->Release();
  78.249 +}
  78.250 +
  78.251 +
  78.252 +void String::AppendString(const char* putf8str, intptr_t utf8StrSz)
  78.253 +{
  78.254 +    if (!putf8str || !utf8StrSz)
  78.255 +        return;
  78.256 +    if (utf8StrSz == -1)
  78.257 +        utf8StrSz = (intptr_t)OVR_strlen(putf8str);
  78.258 +
  78.259 +    DataDesc*   pdata = GetData();
  78.260 +    size_t      oldSize = pdata->GetSize();
  78.261 +
  78.262 +    SetData(AllocDataCopy2(oldSize + (size_t)utf8StrSz, 0,
  78.263 +                           pdata->Data, oldSize, putf8str, (size_t)utf8StrSz));
  78.264 +    pdata->Release();
  78.265 +}
  78.266 +
  78.267 +void    String::AssignString(const InitStruct& src, size_t size)
  78.268 +{
  78.269 +    DataDesc*   poldData = GetData();
  78.270 +    DataDesc*   pnewData = AllocData(size, 0);
  78.271 +    src.InitString(pnewData->Data, size);
  78.272 +    SetData(pnewData);
  78.273 +    poldData->Release();
  78.274 +}
  78.275 +
  78.276 +void    String::AssignString(const char* putf8str, size_t size)
  78.277 +{
  78.278 +    DataDesc* poldData = GetData();
  78.279 +    SetData(AllocDataCopy1(size, 0, putf8str, size));
  78.280 +    poldData->Release();
  78.281 +}
  78.282 +
  78.283 +void    String::operator = (const char* pstr)
  78.284 +{
  78.285 +    AssignString(pstr, pstr ? OVR_strlen(pstr) : 0);
  78.286 +}
  78.287 +
  78.288 +void    String::operator = (const wchar_t* pwstr)
  78.289 +{
  78.290 +    pwstr = pwstr ? pwstr : L"";
  78.291 +
  78.292 +    DataDesc*   poldData = GetData();
  78.293 +    size_t      size = (size_t)UTF8Util::GetEncodeStringSize(pwstr);
  78.294 +
  78.295 +    DataDesc*   pnewData = AllocData(size, 0);
  78.296 +    UTF8Util::EncodeString(pnewData->Data, pwstr);
  78.297 +    SetData(pnewData);
  78.298 +    poldData->Release();
  78.299 +}
  78.300 +
  78.301 +
  78.302 +void    String::operator = (const String& src)
  78.303 +{     
  78.304 +    DataDesc*    psdata = src.GetData();
  78.305 +    DataDesc*    pdata = GetData();    
  78.306 +
  78.307 +    SetData(psdata);
  78.308 +    psdata->AddRef();
  78.309 +    pdata->Release();
  78.310 +}
  78.311 +
  78.312 +
  78.313 +void    String::operator = (const StringBuffer& src)
  78.314 +{ 
  78.315 +    DataDesc* polddata = GetData();    
  78.316 +    SetData(AllocDataCopy1(src.GetSize(), 0, src.ToCStr(), src.GetSize()));
  78.317 +    polddata->Release();
  78.318 +}
  78.319 +
  78.320 +void    String::operator += (const String& src)
  78.321 +{
  78.322 +    DataDesc   *pourData = GetData(),
  78.323 +               *psrcData = src.GetData();
  78.324 +    size_t      ourSize  = pourData->GetSize(),
  78.325 +                srcSize  = psrcData->GetSize();
  78.326 +    size_t      lflag    = pourData->GetLengthFlag() & psrcData->GetLengthFlag();
  78.327 +
  78.328 +    SetData(AllocDataCopy2(ourSize + srcSize, lflag,
  78.329 +                           pourData->Data, ourSize, psrcData->Data, srcSize));
  78.330 +    pourData->Release();
  78.331 +}
  78.332 +
  78.333 +
  78.334 +String   String::operator + (const char* str) const
  78.335 +{   
  78.336 +    String tmp1(*this);
  78.337 +    tmp1 += (str ? str : "");
  78.338 +    return tmp1;
  78.339 +}
  78.340 +
  78.341 +String   String::operator + (const String& src) const
  78.342 +{ 
  78.343 +    String tmp1(*this);
  78.344 +    tmp1 += src;
  78.345 +    return tmp1;
  78.346 +}
  78.347 +
  78.348 +void    String::Remove(size_t posAt, intptr_t removeLength)
  78.349 +{
  78.350 +    DataDesc*   pdata = GetData();
  78.351 +    size_t      oldSize = pdata->GetSize();    
  78.352 +    // Length indicates the number of characters to remove. 
  78.353 +    size_t      length = GetLength();
  78.354 +
  78.355 +    // If index is past the string, nothing to remove.
  78.356 +    if (posAt >= length)
  78.357 +        return;
  78.358 +    // Otherwise, cap removeLength to the length of the string.
  78.359 +    if ((posAt + removeLength) > length)
  78.360 +        removeLength = length - posAt;
  78.361 +
  78.362 +    // Get the byte position of the UTF8 char at position posAt.
  78.363 +    intptr_t bytePos    = UTF8Util::GetByteIndex(posAt, pdata->Data, oldSize);
  78.364 +    intptr_t removeSize = UTF8Util::GetByteIndex(removeLength, pdata->Data + bytePos, oldSize-bytePos);
  78.365 +
  78.366 +    SetData(AllocDataCopy2(oldSize - removeSize, pdata->GetLengthFlag(),
  78.367 +                           pdata->Data, bytePos,
  78.368 +                           pData->Data + bytePos + removeSize, (oldSize - bytePos - removeSize)));
  78.369 +    pdata->Release();
  78.370 +}
  78.371 +
  78.372 +
  78.373 +String   String::Substring(size_t start, size_t end) const
  78.374 +{
  78.375 +    size_t length = GetLength();
  78.376 +    if ((start >= length) || (start >= end))
  78.377 +        return String();   
  78.378 +
  78.379 +    DataDesc* pdata = GetData();
  78.380 +    
  78.381 +    // If size matches, we know the exact index range.
  78.382 +    if (pdata->LengthIsSize())
  78.383 +        return String(pdata->Data + start, end - start);
  78.384 +    
  78.385 +    // Get position of starting character.
  78.386 +    intptr_t byteStart = UTF8Util::GetByteIndex(start, pdata->Data, pdata->GetSize());
  78.387 +    intptr_t byteSize  = UTF8Util::GetByteIndex(end - start, pdata->Data + byteStart, pdata->GetSize()-byteStart);
  78.388 +    return String(pdata->Data + byteStart, (size_t)byteSize);
  78.389 +}
  78.390 +
  78.391 +void String::Clear()
  78.392 +{   
  78.393 +    NullData.AddRef();
  78.394 +    GetData()->Release();
  78.395 +    SetData(&NullData);
  78.396 +}
  78.397 +
  78.398 +
  78.399 +String   String::ToUpper() const 
  78.400 +{       
  78.401 +    uint32_t    c;
  78.402 +    const char* psource = GetData()->Data;
  78.403 +    const char* pend = psource + GetData()->GetSize();
  78.404 +    String      str;
  78.405 +    intptr_t    bufferOffset = 0;
  78.406 +    char        buffer[512];
  78.407 +    
  78.408 +    while(psource < pend)
  78.409 +    {
  78.410 +        do {            
  78.411 +            c = UTF8Util::DecodeNextChar_Advance0(&psource);
  78.412 +            UTF8Util::EncodeChar(buffer, &bufferOffset, OVR_towupper(wchar_t(c)));
  78.413 +        } while ((psource < pend) && (bufferOffset < intptr_t(sizeof(buffer)-8)));
  78.414 +
  78.415 +        // Append string a piece at a time.
  78.416 +        str.AppendString(buffer, bufferOffset);
  78.417 +        bufferOffset = 0;
  78.418 +    }
  78.419 +
  78.420 +    return str;
  78.421 +}
  78.422 +
  78.423 +String   String::ToLower() const 
  78.424 +{
  78.425 +    uint32_t    c;
  78.426 +    const char* psource = GetData()->Data;
  78.427 +    const char* pend = psource + GetData()->GetSize();
  78.428 +    String      str;
  78.429 +    intptr_t    bufferOffset = 0;
  78.430 +    char        buffer[512];
  78.431 +
  78.432 +    while(psource < pend)
  78.433 +    {
  78.434 +        do {
  78.435 +            c = UTF8Util::DecodeNextChar_Advance0(&psource);
  78.436 +            UTF8Util::EncodeChar(buffer, &bufferOffset, OVR_towlower(wchar_t(c)));
  78.437 +        } while ((psource < pend) && (bufferOffset < intptr_t(sizeof(buffer)-8)));
  78.438 +
  78.439 +        // Append string a piece at a time.
  78.440 +        str.AppendString(buffer, bufferOffset);
  78.441 +        bufferOffset = 0;
  78.442 +    }
  78.443 +
  78.444 +    return str;
  78.445 +}
  78.446 +
  78.447 +
  78.448 +
  78.449 +String& String::Insert(const char* substr, size_t posAt, intptr_t strSize)
  78.450 +{
  78.451 +    DataDesc* poldData   = GetData();
  78.452 +    size_t    oldSize    = poldData->GetSize();
  78.453 +    size_t    insertSize = (strSize < 0) ? OVR_strlen(substr) : (size_t)strSize;    
  78.454 +    size_t    byteIndex  =  (poldData->LengthIsSize()) ?
  78.455 +                            posAt : (size_t)UTF8Util::GetByteIndex(posAt, poldData->Data, oldSize);
  78.456 +
  78.457 +    OVR_ASSERT(byteIndex <= oldSize);
  78.458 +    
  78.459 +    DataDesc* pnewData = AllocDataCopy2(oldSize + insertSize, 0,
  78.460 +                                        poldData->Data, byteIndex, substr, insertSize);
  78.461 +    memcpy(pnewData->Data + byteIndex + insertSize,
  78.462 +           poldData->Data + byteIndex, oldSize - byteIndex);
  78.463 +    SetData(pnewData);
  78.464 +    poldData->Release();
  78.465 +    return *this;
  78.466 +}
  78.467 +
  78.468 +/*
  78.469 +String& String::Insert(const uint32_t* substr, size_t posAt, intptr_t len)
  78.470 +{
  78.471 +    for (intptr_t i = 0; i < len; ++i)
  78.472 +    {
  78.473 +        size_t charw = InsertCharAt(substr[i], posAt);
  78.474 +        posAt += charw;
  78.475 +    }
  78.476 +    return *this;
  78.477 +}
  78.478 +*/
  78.479 +
  78.480 +size_t String::InsertCharAt(uint32_t c, size_t posAt)
  78.481 +{
  78.482 +    char      buf[8];
  78.483 +    intptr_t  index = 0;
  78.484 +    UTF8Util::EncodeChar(buf, &index, c);
  78.485 +    OVR_ASSERT(index >= 0);
  78.486 +    buf[(size_t)index] = 0;
  78.487 +
  78.488 +    Insert(buf, posAt, index);
  78.489 +    return (size_t)index;
  78.490 +}
  78.491 +
  78.492 +
  78.493 +int String::CompareNoCase(const char* a, const char* b)
  78.494 +{
  78.495 +    return OVR_stricmp(a, b);
  78.496 +}
  78.497 +
  78.498 +int String::CompareNoCase(const char* a, const char* b, intptr_t len)
  78.499 +{
  78.500 +    if (len)
  78.501 +    {
  78.502 +        intptr_t f,l;
  78.503 +        intptr_t slen = len;
  78.504 +        const char *s = b;
  78.505 +        do {
  78.506 +            f = (intptr_t)OVR_tolower((int)(*(a++)));
  78.507 +            l = (intptr_t)OVR_tolower((int)(*(b++)));
  78.508 +        } while (--len && f && (f == l) && *b != 0);
  78.509 +
  78.510 +        if (f == l && (len != 0 || *b != 0))
  78.511 +        {
  78.512 +            f = (intptr_t)slen;
  78.513 +            l = (intptr_t)OVR_strlen(s);
  78.514 +            return int(f - l);
  78.515 +        }
  78.516 +
  78.517 +        return int(f - l);
  78.518 +    }
  78.519 +    else
  78.520 +        return (0-(int)OVR_strlen(b));
  78.521 +}
  78.522 +
  78.523 +// ***** Implement hash static functions
  78.524 +
  78.525 +// Hash function
  78.526 +size_t String::BernsteinHashFunction(const void* pdataIn, size_t size, size_t seed)
  78.527 +{
  78.528 +    const uint8_t*    pdata   = (const uint8_t*) pdataIn;
  78.529 +    size_t          h       = seed;
  78.530 +    while (size > 0)
  78.531 +    {
  78.532 +        size--;
  78.533 +        h = ((h << 5) + h) ^ (unsigned) pdata[size];
  78.534 +    }
  78.535 +
  78.536 +    return h;
  78.537 +}
  78.538 +
  78.539 +// Hash function, case-insensitive
  78.540 +size_t String::BernsteinHashFunctionCIS(const void* pdataIn, size_t size, size_t seed)
  78.541 +{
  78.542 +    const uint8_t*    pdata = (const uint8_t*) pdataIn;
  78.543 +    size_t          h = seed;
  78.544 +    while (size > 0)
  78.545 +    {
  78.546 +        size--;
  78.547 +        h = ((h << 5) + h) ^ OVR_tolower(pdata[size]);
  78.548 +    }
  78.549 +
  78.550 +    // Alternative: "sdbm" hash function, suggested at same web page above.
  78.551 +    // h = 0;
  78.552 +    // for bytes { h = (h << 16) + (h << 6) - hash + *p; }
  78.553 +    return h;
  78.554 +}
  78.555 +
  78.556 +
  78.557 +
  78.558 +// ***** String Buffer used for Building Strings
  78.559 +
  78.560 +
  78.561 +#define OVR_SBUFF_DEFAULT_GROW_SIZE 512
  78.562 +// Constructors / Destructor.
  78.563 +StringBuffer::StringBuffer()
  78.564 +    : pData(NULL), Size(0), BufferSize(0), GrowSize(OVR_SBUFF_DEFAULT_GROW_SIZE), LengthIsSize(false)
  78.565 +{
  78.566 +}
  78.567 +
  78.568 +StringBuffer::StringBuffer(size_t growSize)
  78.569 +    : pData(NULL), Size(0), BufferSize(0), GrowSize(OVR_SBUFF_DEFAULT_GROW_SIZE), LengthIsSize(false)
  78.570 +{
  78.571 +    SetGrowSize(growSize);
  78.572 +}
  78.573 +
  78.574 +StringBuffer::StringBuffer(const char* data)
  78.575 +    : pData(NULL), Size(0), BufferSize(0), GrowSize(OVR_SBUFF_DEFAULT_GROW_SIZE), LengthIsSize(false)
  78.576 +{
  78.577 +    AppendString(data);
  78.578 +}
  78.579 +
  78.580 +StringBuffer::StringBuffer(const char* data, size_t dataSize)
  78.581 +    : pData(NULL), Size(0), BufferSize(0), GrowSize(OVR_SBUFF_DEFAULT_GROW_SIZE), LengthIsSize(false)
  78.582 +{
  78.583 +    AppendString(data, dataSize);
  78.584 +}
  78.585 +
  78.586 +StringBuffer::StringBuffer(const String& src)
  78.587 +    : pData(NULL), Size(0), BufferSize(0), GrowSize(OVR_SBUFF_DEFAULT_GROW_SIZE), LengthIsSize(false)
  78.588 +{
  78.589 +    AppendString(src.ToCStr(), src.GetSize());
  78.590 +}
  78.591 +
  78.592 +StringBuffer::StringBuffer(const StringBuffer& src)
  78.593 +    : pData(NULL), Size(0), BufferSize(0), GrowSize(OVR_SBUFF_DEFAULT_GROW_SIZE), LengthIsSize(false)
  78.594 +{
  78.595 +    AppendString(src.ToCStr(), src.GetSize());
  78.596 +}
  78.597 +
  78.598 +StringBuffer::StringBuffer(const wchar_t* data)
  78.599 +    : pData(NULL), Size(0), BufferSize(0), GrowSize(OVR_SBUFF_DEFAULT_GROW_SIZE), LengthIsSize(false)
  78.600 +{
  78.601 +    *this = data;
  78.602 +}
  78.603 +
  78.604 +StringBuffer::~StringBuffer()
  78.605 +{
  78.606 +    if (pData)
  78.607 +        OVR_FREE(pData);
  78.608 +}
  78.609 +void StringBuffer::SetGrowSize(size_t growSize) 
  78.610 +{ 
  78.611 +    if (growSize <= 16)
  78.612 +        GrowSize = 16;
  78.613 +    else
  78.614 +    {
  78.615 +        uint8_t bits = Alg::UpperBit(uint32_t(growSize-1));
  78.616 +		size_t size = (size_t)1 << bits;
  78.617 +        GrowSize = size == growSize ? growSize : size;
  78.618 +    }
  78.619 +}
  78.620 +
  78.621 +size_t StringBuffer::GetLength() const
  78.622 +{
  78.623 +    size_t length, size = GetSize();
  78.624 +    if (LengthIsSize)
  78.625 +        return size;
  78.626 +
  78.627 +    length = (size_t)UTF8Util::GetLength(pData, (size_t)GetSize());
  78.628 +
  78.629 +    if (length == GetSize())
  78.630 +        LengthIsSize = true;
  78.631 +    return length;
  78.632 +}
  78.633 +
  78.634 +void    StringBuffer::Reserve(size_t _size)
  78.635 +{
  78.636 +    if (_size >= BufferSize) // >= because of trailing zero! (!AB)
  78.637 +    {
  78.638 +        BufferSize = (_size + 1 + GrowSize - 1)& ~(GrowSize-1);
  78.639 +        if (!pData)
  78.640 +            pData = (char*)OVR_ALLOC(BufferSize);
  78.641 +        else 
  78.642 +            pData = (char*)OVR_REALLOC(pData, BufferSize);
  78.643 +    }
  78.644 +}
  78.645 +void    StringBuffer::Resize(size_t _size)
  78.646 +{
  78.647 +    Reserve(_size);
  78.648 +    LengthIsSize = false;
  78.649 +    Size = _size;
  78.650 +    if (pData)
  78.651 +        pData[Size] = 0;
  78.652 +}
  78.653 +
  78.654 +void StringBuffer::Clear()
  78.655 +{
  78.656 +    Resize(0);
  78.657 +    /*
  78.658 +    if (pData != pEmptyNullData)
  78.659 +    {
  78.660 +        OVR_FREE(pHeap, pData);
  78.661 +        pData = pEmptyNullData;
  78.662 +        Size = BufferSize = 0;
  78.663 +        LengthIsSize = false;
  78.664 +    }
  78.665 +    */
  78.666 +}
  78.667 +// Appends a character
  78.668 +void     StringBuffer::AppendChar(uint32_t ch)
  78.669 +{
  78.670 +    char    buff[8];
  78.671 +    size_t  origSize = GetSize();
  78.672 +
  78.673 +    // Converts ch into UTF8 string and fills it into buff. Also increments index according to the number of bytes
  78.674 +    // in the UTF8 string.
  78.675 +    intptr_t   srcSize = 0;
  78.676 +    UTF8Util::EncodeChar(buff, &srcSize, ch);
  78.677 +    OVR_ASSERT(srcSize >= 0);
  78.678 +    
  78.679 +    size_t size = origSize + srcSize;
  78.680 +    Resize(size);
  78.681 +    OVR_ASSERT(pData != NULL);
  78.682 +    memcpy(pData + origSize, buff, srcSize);
  78.683 +}
  78.684 +
  78.685 +// Append a string
  78.686 +void     StringBuffer::AppendString(const wchar_t* pstr, intptr_t len)
  78.687 +{
  78.688 +    if (!pstr || !len)
  78.689 +        return;
  78.690 +
  78.691 +    intptr_t srcSize  = UTF8Util::GetEncodeStringSize(pstr, len);
  78.692 +    size_t   origSize = GetSize();
  78.693 +    size_t   size     = srcSize + origSize;
  78.694 +
  78.695 +    Resize(size);
  78.696 +    OVR_ASSERT(pData != NULL);
  78.697 +    UTF8Util::EncodeString(pData + origSize,  pstr, len);
  78.698 +}
  78.699 +
  78.700 +void      StringBuffer::AppendString(const char* putf8str, intptr_t utf8StrSz)
  78.701 +{
  78.702 +    if (!putf8str || !utf8StrSz)
  78.703 +        return;
  78.704 +    if (utf8StrSz == -1)
  78.705 +        utf8StrSz = (intptr_t)OVR_strlen(putf8str);
  78.706 +
  78.707 +    size_t  origSize = GetSize();
  78.708 +    size_t  size     = utf8StrSz + origSize;
  78.709 +
  78.710 +    Resize(size);
  78.711 +    OVR_ASSERT(pData != NULL);
  78.712 +    memcpy(pData + origSize, putf8str, utf8StrSz);
  78.713 +}
  78.714 +
  78.715 +// If pstr is NULL then the StringBuffer is cleared.
  78.716 +void      StringBuffer::operator = (const char* pstr)
  78.717 +{
  78.718 +    pstr = pstr ? pstr : "";
  78.719 +    size_t size = OVR_strlen(pstr);
  78.720 +    Resize(size);
  78.721 +    OVR_ASSERT((pData != NULL) || (size == 0));
  78.722 +    memcpy(pData, pstr, size);
  78.723 +}
  78.724 +
  78.725 +// If pstr is NULL then the StringBuffer is cleared.
  78.726 +void      StringBuffer::operator = (const wchar_t* pstr)
  78.727 +{
  78.728 +    pstr = pstr ? pstr : L"";
  78.729 +    size_t size = (size_t)UTF8Util::GetEncodeStringSize(pstr);
  78.730 +    Resize(size);
  78.731 +    OVR_ASSERT((pData != NULL) || (size == 0));
  78.732 +    UTF8Util::EncodeString(pData, pstr);
  78.733 +}
  78.734 +
  78.735 +void      StringBuffer::operator = (const String& src)
  78.736 +{
  78.737 +    const size_t size = src.GetSize();
  78.738 +    Resize(size);
  78.739 +    OVR_ASSERT((pData != NULL) || (size == 0));
  78.740 +    memcpy(pData, src.ToCStr(), size);
  78.741 +}
  78.742 +
  78.743 +void      StringBuffer::operator = (const StringBuffer& src)
  78.744 +{
  78.745 +	Clear();
  78.746 +	AppendString(src.ToCStr(), src.GetSize());
  78.747 +}
  78.748 +
  78.749 +
  78.750 +// Inserts substr at posAt
  78.751 +void      StringBuffer::Insert(const char* substr, size_t posAt, intptr_t len)
  78.752 +{
  78.753 +    size_t    oldSize    = Size;
  78.754 +    size_t    insertSize = (len < 0) ? OVR_strlen(substr) : (size_t)len;    
  78.755 +    size_t    byteIndex  = LengthIsSize ? posAt : 
  78.756 +                           (size_t)UTF8Util::GetByteIndex(posAt, pData, (intptr_t)Size);
  78.757 +
  78.758 +    OVR_ASSERT(byteIndex <= oldSize);
  78.759 +    Reserve(oldSize + insertSize);
  78.760 +
  78.761 +    OVR_ASSERT(pData != NULL); // pData is unilaterally written to below.
  78.762 +    memmove(pData + byteIndex + insertSize, pData + byteIndex, oldSize - byteIndex + 1);
  78.763 +    memcpy (pData + byteIndex, substr, insertSize);
  78.764 +    LengthIsSize = false;
  78.765 +    Size = oldSize + insertSize;
  78.766 +    pData[Size] = 0;
  78.767 +}
  78.768 +
  78.769 +// Inserts character at posAt
  78.770 +size_t    StringBuffer::InsertCharAt(uint32_t c, size_t posAt)
  78.771 +{
  78.772 +    char    buf[8];
  78.773 +    intptr_t   len = 0;
  78.774 +    UTF8Util::EncodeChar(buf, &len, c);
  78.775 +    OVR_ASSERT(len >= 0);
  78.776 +    buf[(size_t)len] = 0;
  78.777 +
  78.778 +    Insert(buf, posAt, len);
  78.779 +    return (size_t)len;
  78.780 +}
  78.781 +
  78.782 +} // OVR
    79.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    79.2 +++ b/LibOVR/Src/Kernel/OVR_String.h	Wed Jan 14 06:51:16 2015 +0200
    79.3 @@ -0,0 +1,658 @@
    79.4 +/************************************************************************************
    79.5 +
    79.6 +PublicHeader:   OVR_Kernel.h
    79.7 +Filename    :   OVR_String.h
    79.8 +Content     :   String UTF8 string implementation with copy-on-write semantics
    79.9 +                (thread-safe for assignment but not modification).
   79.10 +Created     :   September 19, 2012
   79.11 +Notes       : 
   79.12 +
   79.13 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   79.14 +
   79.15 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
   79.16 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
   79.17 +which is provided at the time of installation or download, or which 
   79.18 +otherwise accompanies this software in either electronic or hard copy form.
   79.19 +
   79.20 +You may obtain a copy of the License at
   79.21 +
   79.22 +http://www.oculusvr.com/licenses/LICENSE-3.2 
   79.23 +
   79.24 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
   79.25 +distributed under the License is distributed on an "AS IS" BASIS,
   79.26 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   79.27 +See the License for the specific language governing permissions and
   79.28 +limitations under the License.
   79.29 +
   79.30 +************************************************************************************/
   79.31 +
   79.32 +#ifndef OVR_String_h
   79.33 +#define OVR_String_h
   79.34 +
   79.35 +#include "OVR_Types.h"
   79.36 +#include "OVR_Allocator.h"
   79.37 +#include "OVR_UTF8Util.h"
   79.38 +#include "OVR_Atomic.h"
   79.39 +#include "OVR_Std.h"
   79.40 +#include "OVR_Alg.h"
   79.41 +
   79.42 +namespace OVR {
   79.43 +
   79.44 +// ***** Classes
   79.45 +
   79.46 +class String;
   79.47 +class StringBuffer;
   79.48 +
   79.49 +
   79.50 +//-----------------------------------------------------------------------------------
   79.51 +// ***** String Class 
   79.52 +
   79.53 +// String is UTF8 based string class with copy-on-write implementation
   79.54 +// for assignment.
   79.55 +
   79.56 +class String
   79.57 +{
   79.58 +protected:
   79.59 +
   79.60 +    enum FlagConstants
   79.61 +    {
   79.62 +        //Flag_GetLength      = 0x7FFFFFFF,
   79.63 +        // This flag is set if GetLength() == GetSize() for a string.
   79.64 +        // Avoid extra scanning is Substring and indexing logic.
   79.65 +        Flag_LengthIsSizeShift   = (sizeof(size_t)*8 - 1)
   79.66 +    };
   79.67 +
   79.68 +
   79.69 +    // Internal structure to hold string data
   79.70 +    struct DataDesc
   79.71 +    {
   79.72 +        // Number of bytes. Will be the same as the number of chars if the characters
   79.73 +        // are ascii, may not be equal to number of chars in case string data is UTF8.
   79.74 +        size_t  Size;       
   79.75 +        volatile int32_t RefCount;
   79.76 +        char    Data[1];
   79.77 +
   79.78 +        void    AddRef()
   79.79 +        {
   79.80 +            AtomicOps<int32_t>::ExchangeAdd_NoSync(&RefCount, 1);
   79.81 +        }
   79.82 +        // Decrement ref count. This needs to be thread-safe, since
   79.83 +        // a different thread could have also decremented the ref count.
   79.84 +        // For example, if u start off with a ref count = 2. Now if u
   79.85 +        // decrement the ref count and check against 0 in different
   79.86 +        // statements, a different thread can also decrement the ref count
   79.87 +        // in between our decrement and checking against 0 and will find
   79.88 +        // the ref count = 0 and delete the object. This will lead to a crash
   79.89 +        // when context switches to our thread and we'll be trying to delete
   79.90 +        // an already deleted object. Hence decrementing the ref count and
   79.91 +        // checking against 0 needs to made an atomic operation.
   79.92 +        void    Release()
   79.93 +        {
   79.94 +            if ((AtomicOps<int32_t>::ExchangeAdd_NoSync(&RefCount, -1) - 1) == 0)
   79.95 +                OVR_FREE(this);
   79.96 +        }
   79.97 +
   79.98 +        static size_t GetLengthFlagBit()     { return size_t(1) << Flag_LengthIsSizeShift; }
   79.99 +        size_t      GetSize() const         { return Size & ~GetLengthFlagBit() ; }
  79.100 +        size_t      GetLengthFlag()  const  { return Size & GetLengthFlagBit(); }
  79.101 +        bool        LengthIsSize() const    { return GetLengthFlag() != 0; }
  79.102 +    };
  79.103 +
  79.104 +    // Heap type of the string is encoded in the lower bits.
  79.105 +    enum HeapType
  79.106 +    {
  79.107 +        HT_Global   = 0,    // Heap is global.
  79.108 +        HT_Local    = 1,    // SF::String_loc: Heap is determined based on string's address.
  79.109 +        HT_Dynamic  = 2,    // SF::String_temp: Heap is stored as a part of the class.
  79.110 +        HT_Mask     = 3
  79.111 +    };
  79.112 +
  79.113 +    union {
  79.114 +        DataDesc* pData;
  79.115 +        size_t    HeapTypeBits;
  79.116 +    };
  79.117 +    typedef union {
  79.118 +        DataDesc* pData;
  79.119 +        size_t    HeapTypeBits;
  79.120 +    } DataDescUnion;
  79.121 +
  79.122 +    inline HeapType    GetHeapType() const { return (HeapType) (HeapTypeBits & HT_Mask); }
  79.123 +
  79.124 +    inline DataDesc*   GetData() const
  79.125 +    {
  79.126 +        DataDescUnion u;
  79.127 +        u.pData    = pData;
  79.128 +        u.HeapTypeBits = (u.HeapTypeBits & ~(size_t)HT_Mask);
  79.129 +        return u.pData;
  79.130 +    }
  79.131 +    
  79.132 +    inline void        SetData(DataDesc* pdesc)
  79.133 +    {
  79.134 +        HeapType ht = GetHeapType();
  79.135 +        pData = pdesc;
  79.136 +        OVR_ASSERT((HeapTypeBits & HT_Mask) == 0);
  79.137 +        HeapTypeBits |= ht;        
  79.138 +    }
  79.139 +
  79.140 +    
  79.141 +    DataDesc*   AllocData(size_t size, size_t lengthIsSize);
  79.142 +    DataDesc*   AllocDataCopy1(size_t size, size_t lengthIsSize,
  79.143 +                               const char* pdata, size_t copySize);
  79.144 +    DataDesc*   AllocDataCopy2(size_t size, size_t lengthIsSize,
  79.145 +                               const char* pdata1, size_t copySize1,
  79.146 +                               const char* pdata2, size_t copySize2);
  79.147 +
  79.148 +    // Special constructor to avoid data initalization when used in derived class.
  79.149 +    struct NoConstructor { };
  79.150 +    String(const NoConstructor&) { }
  79.151 +
  79.152 +public:
  79.153 +
  79.154 +    // For initializing string with dynamic buffer
  79.155 +    struct InitStruct
  79.156 +    {
  79.157 +        virtual ~InitStruct() { }
  79.158 +        virtual void InitString(char* pbuffer, size_t size) const = 0;
  79.159 +    };
  79.160 +
  79.161 +
  79.162 +    // Constructors / Destructors.
  79.163 +    String();
  79.164 +    String(const char* data);
  79.165 +    String(const char* data1, const char* pdata2, const char* pdata3 = 0);
  79.166 +    String(const char* data, size_t buflen);
  79.167 +    String(const String& src);
  79.168 +    String(const StringBuffer& src);
  79.169 +    String(const InitStruct& src, size_t size);
  79.170 +    explicit String(const wchar_t* data);      
  79.171 +
  79.172 +    // Destructor (Captain Obvious guarantees!)
  79.173 +    ~String()
  79.174 +    {
  79.175 +        GetData()->Release();
  79.176 +    }
  79.177 +
  79.178 +    // Declaration of NullString
  79.179 +    static DataDesc NullData;
  79.180 +
  79.181 +
  79.182 +    // *** General Functions
  79.183 +
  79.184 +    void        Clear();
  79.185 +
  79.186 +    // For casting to a pointer to char.
  79.187 +    operator const char*() const        { return GetData()->Data; }
  79.188 +    // Pointer to raw buffer.
  79.189 +    const char* ToCStr() const          { return GetData()->Data; }
  79.190 +
  79.191 +    // Returns number of bytes
  79.192 +    size_t      GetSize() const         { return GetData()->GetSize() ; }
  79.193 +    // Tells whether or not the string is empty
  79.194 +    bool        IsEmpty() const         { return GetSize() == 0; }
  79.195 +
  79.196 +    // Returns  number of characters
  79.197 +    size_t      GetLength() const;
  79.198 +    int         GetLengthI() const      { return (int)GetLength(); }
  79.199 +
  79.200 +    // Returns  character at the specified index
  79.201 +    uint32_t    GetCharAt(size_t index) const;
  79.202 +    uint32_t    GetFirstCharAt(size_t index, const char** offset) const;
  79.203 +    uint32_t    GetNextChar(const char** offset) const;
  79.204 +
  79.205 +    // Appends a character
  79.206 +    void        AppendChar(uint32_t ch);
  79.207 +
  79.208 +    // Append a string
  79.209 +    void        AppendString(const wchar_t* pstr, intptr_t len = -1);
  79.210 +    void        AppendString(const char* putf8str, intptr_t utf8StrSz = -1);
  79.211 +
  79.212 +    // Assigned a string with dynamic data (copied through initializer).
  79.213 +    void        AssignString(const InitStruct& src, size_t size);
  79.214 +    // Assigns string with known size.
  79.215 +    void        AssignString(const char* putf8str, size_t size);
  79.216 +
  79.217 +    //  Resize the string to the new size
  79.218 +//  void        Resize(size_t _size);
  79.219 +
  79.220 +    // Removes the character at posAt
  79.221 +    void        Remove(size_t posAt, intptr_t len = 1);
  79.222 +
  79.223 +    // Returns a String that's a substring of this.
  79.224 +    //  -start is the index of the first UTF8 character you want to include.
  79.225 +    //  -end is the index one past the last UTF8 character you want to include.
  79.226 +    String   Substring(size_t start, size_t end) const;
  79.227 +
  79.228 +    // Case-conversion
  79.229 +    String   ToUpper() const;
  79.230 +    String   ToLower() const;
  79.231 +
  79.232 +    // Inserts substr at posAt
  79.233 +    String&    Insert (const char* substr, size_t posAt, intptr_t len = -1);
  79.234 +
  79.235 +    // Inserts character at posAt
  79.236 +    size_t      InsertCharAt(uint32_t c, size_t posAt);
  79.237 +
  79.238 +    // Inserts substr at posAt, which is an index of a character (not byte).
  79.239 +    // Of size is specified, it is in bytes.
  79.240 +//  String&    Insert(const uint32_t* substr, size_t posAt, intptr_t size = -1);
  79.241 +
  79.242 +    // Get Byte index of the character at position = index
  79.243 +    size_t      GetByteIndex(size_t index) const { return (size_t)UTF8Util::GetByteIndex(index, GetData()->Data); }
  79.244 +
  79.245 +    // Utility: case-insensitive string compare.  stricmp() & strnicmp() are not
  79.246 +    // ANSI or POSIX, do not seem to appear in Linux.
  79.247 +    static int OVR_STDCALL   CompareNoCase(const char* a, const char* b);
  79.248 +    static int OVR_STDCALL   CompareNoCase(const char* a, const char* b, intptr_t len);
  79.249 +
  79.250 +    // Hash function, case-insensitive
  79.251 +    static size_t OVR_STDCALL BernsteinHashFunctionCIS(const void* pdataIn, size_t size, size_t seed = 5381);
  79.252 +
  79.253 +    // Hash function, case-sensitive
  79.254 +    static size_t OVR_STDCALL BernsteinHashFunction(const void* pdataIn, size_t size, size_t seed = 5381);
  79.255 +
  79.256 +
  79.257 +    // ***** File path parsing helper functions.
  79.258 +    // Implemented in OVR_String_FilePath.cpp.
  79.259 +
  79.260 +    // Absolute paths can star with:
  79.261 +    //  - protocols:        'file://', 'http://'
  79.262 +    //  - windows drive:    'c:\'
  79.263 +    //  - UNC share name:   '\\share'
  79.264 +    //  - unix root         '/'
  79.265 +    static bool HasAbsolutePath(const char* path);
  79.266 +    static bool HasExtension(const char* path);
  79.267 +    static bool HasProtocol(const char* path);
  79.268 +
  79.269 +    bool    HasAbsolutePath() const { return HasAbsolutePath(ToCStr()); }
  79.270 +    bool    HasExtension() const    { return HasExtension(ToCStr()); }
  79.271 +    bool    HasProtocol() const     { return HasProtocol(ToCStr()); }
  79.272 +
  79.273 +    String  GetProtocol() const;    // Returns protocol, if any, with trailing '://'.
  79.274 +    String  GetPath() const;        // Returns path with trailing '/'.
  79.275 +    String  GetFilename() const;    // Returns filename, including extension.
  79.276 +    String  GetExtension() const;   // Returns extension with a dot.
  79.277 +
  79.278 +    void    StripProtocol();        // Strips front protocol, if any, from the string.
  79.279 +    void    StripExtension();       // Strips off trailing extension.
  79.280 +    
  79.281 +
  79.282 +    // Operators
  79.283 +    // Assignment
  79.284 +    void        operator =  (const char* str);
  79.285 +    void        operator =  (const wchar_t* str);
  79.286 +    void        operator =  (const String& src);
  79.287 +    void        operator =  (const StringBuffer& src);
  79.288 +
  79.289 +    // Addition
  79.290 +    void        operator += (const String& src);
  79.291 +    void        operator += (const char* psrc)       { AppendString(psrc); }
  79.292 +    void        operator += (const wchar_t* psrc)    { AppendString(psrc); }
  79.293 +    void        operator += (char  ch)               { AppendChar(ch); }
  79.294 +    String      operator +  (const char* str) const;
  79.295 +    String      operator +  (const String& src)  const;
  79.296 +
  79.297 +    // Comparison
  79.298 +    bool        operator == (const String& str) const
  79.299 +    {
  79.300 +        return (OVR_strcmp(GetData()->Data, str.GetData()->Data)== 0);
  79.301 +    }
  79.302 +
  79.303 +    bool        operator != (const String& str) const
  79.304 +    {
  79.305 +        return !operator == (str);
  79.306 +    }
  79.307 +
  79.308 +    bool        operator == (const char* str) const
  79.309 +    {
  79.310 +        return OVR_strcmp(GetData()->Data, str) == 0;
  79.311 +    }
  79.312 +
  79.313 +    bool        operator != (const char* str) const
  79.314 +    {
  79.315 +        return !operator == (str);
  79.316 +    }
  79.317 +
  79.318 +    bool        operator <  (const char* pstr) const
  79.319 +    {
  79.320 +        return OVR_strcmp(GetData()->Data, pstr) < 0;
  79.321 +    }
  79.322 +
  79.323 +    bool        operator <  (const String& str) const
  79.324 +    {
  79.325 +        return *this < str.GetData()->Data;
  79.326 +    }
  79.327 +
  79.328 +    bool        operator >  (const char* pstr) const
  79.329 +    {
  79.330 +        return OVR_strcmp(GetData()->Data, pstr) > 0;
  79.331 +    }
  79.332 +
  79.333 +    bool        operator >  (const String& str) const
  79.334 +    {
  79.335 +        return *this > str.GetData()->Data;
  79.336 +    }
  79.337 +
  79.338 +    int CompareNoCase(const char* pstr) const
  79.339 +    {
  79.340 +        return CompareNoCase(GetData()->Data, pstr);
  79.341 +    }
  79.342 +    int CompareNoCase(const String& str) const
  79.343 +    {
  79.344 +        return CompareNoCase(GetData()->Data, str.ToCStr());
  79.345 +    }
  79.346 +
  79.347 +    // Accesses raw bytes
  79.348 +    const char&     operator [] (int index) const
  79.349 +    {
  79.350 +        OVR_ASSERT(index >= 0 && (size_t)index < GetSize());
  79.351 +        return GetData()->Data[index];
  79.352 +    }
  79.353 +    const char&     operator [] (size_t index) const
  79.354 +    {
  79.355 +        OVR_ASSERT(index < GetSize());
  79.356 +        return GetData()->Data[index];
  79.357 +    }
  79.358 +
  79.359 +
  79.360 +    // Case insensitive keys are used to look up insensitive string in hash tables
  79.361 +    // for SWF files with version before SWF 7.
  79.362 +    struct NoCaseKey
  79.363 +    {   
  79.364 +        const String* pStr;
  79.365 +        NoCaseKey(const String &str) : pStr(&str){};
  79.366 +    };
  79.367 +
  79.368 +    bool    operator == (const NoCaseKey& strKey) const
  79.369 +    {
  79.370 +        return (CompareNoCase(ToCStr(), strKey.pStr->ToCStr()) == 0);
  79.371 +    }
  79.372 +    bool    operator != (const NoCaseKey& strKey) const
  79.373 +    {
  79.374 +        return !(CompareNoCase(ToCStr(), strKey.pStr->ToCStr()) == 0);
  79.375 +    }
  79.376 +
  79.377 +    // Hash functor used for strings.
  79.378 +    struct HashFunctor
  79.379 +    {    
  79.380 +        size_t operator()(const String& data) const
  79.381 +        {
  79.382 +            size_t size = data.GetSize();
  79.383 +            return String::BernsteinHashFunction((const char*)data, size);
  79.384 +        }        
  79.385 +    };
  79.386 +    // Case-insensitive hash functor used for strings. Supports additional
  79.387 +    // lookup based on NoCaseKey.
  79.388 +    struct NoCaseHashFunctor
  79.389 +    {    
  79.390 +        size_t operator()(const String& data) const
  79.391 +        {
  79.392 +            size_t size = data.GetSize();
  79.393 +            return String::BernsteinHashFunctionCIS((const char*)data, size);
  79.394 +        }
  79.395 +        size_t operator()(const NoCaseKey& data) const
  79.396 +        {       
  79.397 +            size_t size = data.pStr->GetSize();
  79.398 +            return String::BernsteinHashFunctionCIS((const char*)data.pStr->ToCStr(), size);
  79.399 +        }
  79.400 +    };
  79.401 +
  79.402 +};
  79.403 +
  79.404 +
  79.405 +//-----------------------------------------------------------------------------------
  79.406 +// ***** String Buffer used for Building Strings
  79.407 +
  79.408 +class StringBuffer
  79.409 +{
  79.410 +    char*           pData;
  79.411 +    size_t          Size;
  79.412 +    size_t          BufferSize;
  79.413 +    size_t          GrowSize;    
  79.414 +    mutable bool    LengthIsSize;    
  79.415 +
  79.416 +public:
  79.417 +
  79.418 +    // Constructors / Destructor.    
  79.419 +    StringBuffer();
  79.420 +    explicit StringBuffer(size_t growSize);
  79.421 +    StringBuffer(const char* data);
  79.422 +    StringBuffer(const char* data, size_t buflen);
  79.423 +    StringBuffer(const String& src);
  79.424 +    StringBuffer(const StringBuffer& src);
  79.425 +    explicit StringBuffer(const wchar_t* data);
  79.426 +    ~StringBuffer();
  79.427 +    
  79.428 +
  79.429 +    // Modify grow size used for growing/shrinking the buffer.
  79.430 +    size_t      GetGrowSize() const         { return GrowSize; }
  79.431 +    void        SetGrowSize(size_t growSize);
  79.432 +    
  79.433 +
  79.434 +    // *** General Functions
  79.435 +    // Does not release memory, just sets Size to 0
  79.436 +    void        Clear();
  79.437 +
  79.438 +    // For casting to a pointer to char.
  79.439 +    operator const char*() const        { return (pData) ? pData : ""; }
  79.440 +    // Pointer to raw buffer.
  79.441 +    const char* ToCStr() const          { return (pData) ? pData : ""; }
  79.442 +
  79.443 +    // Returns number of bytes.
  79.444 +    size_t      GetSize() const         { return Size ; }
  79.445 +    // Tells whether or not the string is empty.
  79.446 +    bool        IsEmpty() const         { return GetSize() == 0; }
  79.447 +
  79.448 +    // Returns  number of characters
  79.449 +    size_t      GetLength() const;
  79.450 +
  79.451 +    // Returns  character at the specified index
  79.452 +    uint32_t    GetCharAt(size_t index) const;
  79.453 +    uint32_t    GetFirstCharAt(size_t index, const char** offset) const;
  79.454 +    uint32_t    GetNextChar(const char** offset) const;
  79.455 +
  79.456 +
  79.457 +    //  Resize the string to the new size
  79.458 +    void        Resize(size_t _size);
  79.459 +    void        Reserve(size_t _size);
  79.460 +
  79.461 +    // Appends a character
  79.462 +    void        AppendChar(uint32_t ch);
  79.463 +
  79.464 +    // Append a string
  79.465 +    void        AppendString(const wchar_t* pstr, intptr_t len = -1);
  79.466 +    void        AppendString(const char* putf8str, intptr_t utf8StrSz = -1);
  79.467 +    void        AppendFormat(const char* format, ...);
  79.468 +
  79.469 +    // Assigned a string with dynamic data (copied through initializer).
  79.470 +    //void        AssignString(const InitStruct& src, size_t size);
  79.471 +
  79.472 +    // Inserts substr at posAt
  79.473 +    void        Insert (const char* substr, size_t posAt, intptr_t len = -1);
  79.474 +    // Inserts character at posAt
  79.475 +    size_t      InsertCharAt(uint32_t c, size_t posAt);
  79.476 +
  79.477 +    // Assignment
  79.478 +    void        operator =  (const char* str);
  79.479 +    void        operator =  (const wchar_t* str);
  79.480 +    void        operator =  (const String& src);
  79.481 +    void        operator =  (const StringBuffer& src);
  79.482 +
  79.483 +    // Addition
  79.484 +    void        operator += (const String& src)      { AppendString(src.ToCStr(),src.GetSize()); }
  79.485 +    void        operator += (const char* psrc)       { AppendString(psrc); }
  79.486 +    void        operator += (const wchar_t* psrc)    { AppendString(psrc); }
  79.487 +    void        operator += (char  ch)               { AppendChar(ch); }
  79.488 +    //String   operator +  (const char* str) const ;
  79.489 +    //String   operator +  (const String& src)  const ;
  79.490 +
  79.491 +    // Accesses raw bytes
  79.492 +    char&       operator [] (int index)
  79.493 +    {
  79.494 +        OVR_ASSERT(((size_t)index) < GetSize());
  79.495 +        return pData[index];
  79.496 +    }
  79.497 +    char&       operator [] (size_t index)
  79.498 +    {
  79.499 +        OVR_ASSERT(index < GetSize());
  79.500 +        return pData[index];
  79.501 +    }
  79.502 +
  79.503 +    const char&     operator [] (int index) const 
  79.504 +    {
  79.505 +        OVR_ASSERT(((size_t)index) < GetSize());
  79.506 +        return pData[index];
  79.507 +    }
  79.508 +    const char&     operator [] (size_t index) const
  79.509 +    {
  79.510 +        OVR_ASSERT(index < GetSize());
  79.511 +        return pData[index];
  79.512 +    }
  79.513 +};
  79.514 +
  79.515 +
  79.516 +//
  79.517 +// Wrapper for string data. The data must have a guaranteed 
  79.518 +// lifespan throughout the usage of the wrapper. Not intended for 
  79.519 +// cached usage. Not thread safe.
  79.520 +//
  79.521 +class StringDataPtr
  79.522 +{
  79.523 +public:
  79.524 +    StringDataPtr() : pStr(NULL), Size(0) {}
  79.525 +    StringDataPtr(const StringDataPtr& p)
  79.526 +        : pStr(p.pStr), Size(p.Size) {}
  79.527 +    StringDataPtr(const char* pstr, size_t sz)
  79.528 +        : pStr(pstr), Size(sz) {}
  79.529 +    StringDataPtr(const char* pstr)
  79.530 +        : pStr(pstr), Size((pstr != NULL) ? OVR_strlen(pstr) : 0) {}
  79.531 +    explicit StringDataPtr(const String& str)
  79.532 +        : pStr(str.ToCStr()), Size(str.GetSize()) {}
  79.533 +    template <typename T, int N> 
  79.534 +    StringDataPtr(const T (&v)[N])
  79.535 +        : pStr(v), Size(N) {}
  79.536 +
  79.537 +public:
  79.538 +    const char* ToCStr() const { return pStr; }
  79.539 +    size_t      GetSize() const { return Size; }
  79.540 +    bool        IsEmpty() const { return GetSize() == 0; }
  79.541 +
  79.542 +    // value is a prefix of this string
  79.543 +    // Character's values are not compared.
  79.544 +    bool        IsPrefix(const StringDataPtr& value) const
  79.545 +    {
  79.546 +        return ToCStr() == value.ToCStr() && GetSize() >= value.GetSize();
  79.547 +    }
  79.548 +    // value is a suffix of this string
  79.549 +    // Character's values are not compared.
  79.550 +    bool        IsSuffix(const StringDataPtr& value) const
  79.551 +    {
  79.552 +        return ToCStr() <= value.ToCStr() && (End()) == (value.End());
  79.553 +    }
  79.554 +
  79.555 +    // Find first character.
  79.556 +    // init_ind - initial index.
  79.557 +    intptr_t    FindChar(char c, size_t init_ind = 0) const 
  79.558 +    {
  79.559 +        for (size_t i = init_ind; i < GetSize(); ++i)
  79.560 +            if (pStr[i] == c)
  79.561 +                return static_cast<intptr_t>(i);
  79.562 +
  79.563 +        return -1; 
  79.564 +    }
  79.565 +
  79.566 +    // Find last character.
  79.567 +    // init_ind - initial index.
  79.568 +    intptr_t    FindLastChar(char c, size_t init_ind = ~0) const 
  79.569 +    {
  79.570 +        if (init_ind == (size_t)~0 || init_ind > GetSize())
  79.571 +            init_ind = GetSize();
  79.572 +        else
  79.573 +            ++init_ind;
  79.574 +
  79.575 +        for (size_t i = init_ind; i > 0; --i)
  79.576 +            if (pStr[i - 1] == c)
  79.577 +                return static_cast<intptr_t>(i - 1);
  79.578 +
  79.579 +        return -1; 
  79.580 +    }
  79.581 +
  79.582 +    // Create new object and trim size bytes from the left.
  79.583 +    StringDataPtr  GetTrimLeft(size_t size) const
  79.584 +    {
  79.585 +        // Limit trim size to the size of the string.
  79.586 +        size = Alg::PMin(GetSize(), size);
  79.587 +
  79.588 +        return StringDataPtr(ToCStr() + size, GetSize() - size);
  79.589 +    }
  79.590 +    // Create new object and trim size bytes from the right.
  79.591 +    StringDataPtr  GetTrimRight(size_t size) const
  79.592 +    {
  79.593 +        // Limit trim to the size of the string.
  79.594 +        size = Alg::PMin(GetSize(), size);
  79.595 +
  79.596 +        return StringDataPtr(ToCStr(), GetSize() - size);
  79.597 +    }
  79.598 +
  79.599 +    // Create new object, which contains next token.
  79.600 +    // Useful for parsing.
  79.601 +    StringDataPtr GetNextToken(char separator = ':') const
  79.602 +    {
  79.603 +        size_t cur_pos = 0;
  79.604 +        const char* cur_str = ToCStr();
  79.605 +
  79.606 +        for (; cur_pos < GetSize() && cur_str[cur_pos]; ++cur_pos)
  79.607 +        {
  79.608 +            if (cur_str[cur_pos] == separator)
  79.609 +            {
  79.610 +                break;
  79.611 +            }
  79.612 +        }
  79.613 +
  79.614 +        return StringDataPtr(ToCStr(), cur_pos);
  79.615 +    }
  79.616 +
  79.617 +    // Trim size bytes from the left.
  79.618 +    StringDataPtr& TrimLeft(size_t size)
  79.619 +    {
  79.620 +        // Limit trim size to the size of the string.
  79.621 +        size = Alg::PMin(GetSize(), size);
  79.622 +        pStr += size;
  79.623 +        Size -= size;
  79.624 +
  79.625 +        return *this;
  79.626 +    }
  79.627 +    // Trim size bytes from the right.
  79.628 +    StringDataPtr& TrimRight(size_t size)
  79.629 +    {
  79.630 +        // Limit trim to the size of the string.
  79.631 +        size = Alg::PMin(GetSize(), size);
  79.632 +        Size -= size;
  79.633 +
  79.634 +        return *this;
  79.635 +    }
  79.636 +
  79.637 +    const char* Begin() const { return ToCStr(); }
  79.638 +    const char* End() const { return ToCStr() + GetSize(); }
  79.639 +
  79.640 +    // Hash functor used string data pointers
  79.641 +    struct HashFunctor
  79.642 +    {    
  79.643 +        size_t operator()(const StringDataPtr& data) const
  79.644 +        {
  79.645 +            return String::BernsteinHashFunction(data.ToCStr(), data.GetSize());
  79.646 +        }        
  79.647 +    };
  79.648 +
  79.649 +    bool operator== (const StringDataPtr& data) const 
  79.650 +    {
  79.651 +        return (OVR_strncmp(pStr, data.pStr, data.Size) == 0);
  79.652 +    }
  79.653 +
  79.654 +protected:
  79.655 +    const char* pStr;
  79.656 +    size_t      Size;
  79.657 +};
  79.658 +
  79.659 +} // OVR
  79.660 +
  79.661 +#endif
    80.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    80.2 +++ b/LibOVR/Src/Kernel/OVR_StringHash.h	Wed Jan 14 06:51:16 2015 +0200
    80.3 @@ -0,0 +1,100 @@
    80.4 +/************************************************************************************
    80.5 +
    80.6 +PublicHeader:   None
    80.7 +Filename    :   OVR_StringHash.h
    80.8 +Content     :   String hash table used when optional case-insensitive
    80.9 +                lookup is required.
   80.10 +Created     :   September 19, 2012
   80.11 +Notes       : 
   80.12 +
   80.13 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   80.14 +
   80.15 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
   80.16 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
   80.17 +which is provided at the time of installation or download, or which 
   80.18 +otherwise accompanies this software in either electronic or hard copy form.
   80.19 +
   80.20 +You may obtain a copy of the License at
   80.21 +
   80.22 +http://www.oculusvr.com/licenses/LICENSE-3.2 
   80.23 +
   80.24 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
   80.25 +distributed under the License is distributed on an "AS IS" BASIS,
   80.26 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   80.27 +See the License for the specific language governing permissions and
   80.28 +limitations under the License.
   80.29 +
   80.30 +************************************************************************************/
   80.31 +
   80.32 +#ifndef OVR_StringHash_h
   80.33 +#define OVR_StringHash_h
   80.34 +
   80.35 +#include "OVR_String.h"
   80.36 +#include "OVR_Hash.h"
   80.37 +
   80.38 +namespace OVR {
   80.39 +
   80.40 +//-----------------------------------------------------------------------------------
   80.41 +// *** StringHash
   80.42 +
   80.43 +// This is a custom string hash table that supports case-insensitive
   80.44 +// searches through special functions such as GetCaseInsensitive, etc.
   80.45 +// This class is used for Flash labels, exports and other case-insensitive tables.
   80.46 +
   80.47 +template<class U, class Allocator = ContainerAllocator<U> >
   80.48 +class StringHash : public Hash<String, U, String::NoCaseHashFunctor, Allocator>
   80.49 +{
   80.50 +public:
   80.51 +    typedef U                                                        ValueType;
   80.52 +    typedef StringHash<U, Allocator>                                 SelfType;
   80.53 +    typedef Hash<String, U, String::NoCaseHashFunctor, Allocator>    BaseType;
   80.54 +
   80.55 +public:    
   80.56 +
   80.57 +    void    operator = (const SelfType& src) { BaseType::operator = (src); }
   80.58 +
   80.59 +    bool    GetCaseInsensitive(const String& key, U* pvalue) const
   80.60 +    {
   80.61 +        String::NoCaseKey ikey(key);
   80.62 +        return BaseType::GetAlt(ikey, pvalue);
   80.63 +    }
   80.64 +    // Pointer-returning get variety.
   80.65 +    const U* GetCaseInsensitive(const String& key) const   
   80.66 +    {
   80.67 +        String::NoCaseKey ikey(key);
   80.68 +        return BaseType::GetAlt(ikey);
   80.69 +    }
   80.70 +    U*  GetCaseInsensitive(const String& key)
   80.71 +    {
   80.72 +        String::NoCaseKey ikey(key);
   80.73 +        return BaseType::GetAlt(ikey);
   80.74 +    }
   80.75 +
   80.76 +    
   80.77 +    typedef typename BaseType::Iterator base_iterator;
   80.78 +
   80.79 +    base_iterator    FindCaseInsensitive(const String& key)
   80.80 +    {
   80.81 +        String::NoCaseKey ikey(key);
   80.82 +        return BaseType::FindAlt(ikey);
   80.83 +    }
   80.84 +
   80.85 +    // Set just uses a find and assigns value if found. The key is not modified;
   80.86 +    // this behavior is identical to Flash string variable assignment.    
   80.87 +    void    SetCaseInsensitive(const String& key, const U& value)
   80.88 +    {
   80.89 +        base_iterator it = FindCaseInsensitive(key);
   80.90 +        if (it != BaseType::End())
   80.91 +        {
   80.92 +            it->Second = value;
   80.93 +        }
   80.94 +        else
   80.95 +        {
   80.96 +            BaseType::Add(key, value);
   80.97 +        }
   80.98 +    } 
   80.99 +};
  80.100 +
  80.101 +} // OVR 
  80.102 +
  80.103 +#endif
    81.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    81.2 +++ b/LibOVR/Src/Kernel/OVR_String_FormatUtil.cpp	Wed Jan 14 06:51:16 2015 +0200
    81.3 @@ -0,0 +1,76 @@
    81.4 +/************************************************************************************
    81.5 +
    81.6 +Filename    :   OVR_String_FormatUtil.cpp
    81.7 +Content     :   String format functions.
    81.8 +Created     :   February 27, 2013
    81.9 +Notes       : 
   81.10 +
   81.11 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   81.12 +
   81.13 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
   81.14 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
   81.15 +which is provided at the time of installation or download, or which 
   81.16 +otherwise accompanies this software in either electronic or hard copy form.
   81.17 +
   81.18 +You may obtain a copy of the License at
   81.19 +
   81.20 +http://www.oculusvr.com/licenses/LICENSE-3.2 
   81.21 +
   81.22 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
   81.23 +distributed under the License is distributed on an "AS IS" BASIS,
   81.24 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   81.25 +See the License for the specific language governing permissions and
   81.26 +limitations under the License.
   81.27 +
   81.28 +************************************************************************************/
   81.29 +
   81.30 +#include "OVR_String.h"
   81.31 +#include "OVR_Log.h"
   81.32 +
   81.33 +namespace OVR {
   81.34 +
   81.35 +void StringBuffer::AppendFormat(const char* format, ...)
   81.36 +{       
   81.37 +    va_list argList;
   81.38 +    char    buffer[512];
   81.39 +    char*   bufferUsed = buffer;
   81.40 +    char*   bufferAllocated = NULL;
   81.41 +
   81.42 +    va_start(argList, format);
   81.43 +
   81.44 +    #if !defined(OVR_CC_MSVC) // Non-Microsoft compilers require you to save a copy of the va_list.
   81.45 +        va_list argListSaved;
   81.46 +        va_copy(argListSaved, argList);
   81.47 +    #endif
   81.48 +
   81.49 +    int requiredStrlen = OVR_vsnprintf(bufferUsed, OVR_ARRAY_COUNT(buffer), format, argList); // The large majority of the time this will succeed.
   81.50 +
   81.51 +    if(requiredStrlen >= (int)sizeof(buffer)) // If the initial capacity wasn't enough...
   81.52 +    {
   81.53 +        bufferAllocated = (char*)OVR_ALLOC(sizeof(char) * (requiredStrlen + 1));
   81.54 +        bufferUsed = bufferAllocated;
   81.55 +        if(bufferAllocated)
   81.56 +        {
   81.57 +            #if !defined(OVR_CC_MSVC)
   81.58 +                va_end(argList);
   81.59 +                va_copy(argList, argListSaved);
   81.60 +            #endif
   81.61 +            requiredStrlen = OVR_vsnprintf(bufferAllocated, (requiredStrlen + 1), format, argList);
   81.62 +        }
   81.63 +    }
   81.64 +
   81.65 +    if(requiredStrlen < 0) // If there was a printf format error...
   81.66 +    {
   81.67 +        bufferUsed = NULL;
   81.68 +    }
   81.69 +
   81.70 +    va_end(argList);
   81.71 +
   81.72 +    if(bufferUsed)
   81.73 +        AppendString(bufferUsed);
   81.74 +
   81.75 +    if(bufferAllocated)
   81.76 +        OVR_FREE(bufferAllocated);
   81.77 +}
   81.78 +
   81.79 +} // OVR
    82.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    82.2 +++ b/LibOVR/Src/Kernel/OVR_String_PathUtil.cpp	Wed Jan 14 06:51:16 2015 +0200
    82.3 @@ -0,0 +1,211 @@
    82.4 +/************************************************************************************
    82.5 +
    82.6 +Filename    :   OVR_String_PathUtil.cpp
    82.7 +Content     :   String filename/url helper function
    82.8 +Created     :   September 19, 2012
    82.9 +Notes       : 
   82.10 +
   82.11 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   82.12 +
   82.13 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
   82.14 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
   82.15 +which is provided at the time of installation or download, or which 
   82.16 +otherwise accompanies this software in either electronic or hard copy form.
   82.17 +
   82.18 +You may obtain a copy of the License at
   82.19 +
   82.20 +http://www.oculusvr.com/licenses/LICENSE-3.2 
   82.21 +
   82.22 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
   82.23 +distributed under the License is distributed on an "AS IS" BASIS,
   82.24 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   82.25 +See the License for the specific language governing permissions and
   82.26 +limitations under the License.
   82.27 +
   82.28 +************************************************************************************/
   82.29 +
   82.30 +#include "OVR_String.h"
   82.31 +#include "OVR_UTF8Util.h"
   82.32 +
   82.33 +namespace OVR {
   82.34 +
   82.35 +//--------------------------------------------------------------------
   82.36 +// ***** Path-Scanner helper function 
   82.37 +
   82.38 +// Scans file path finding filename start and extension start, fills in their addess.
   82.39 +void ScanFilePath(const char* url, const char** pfilename, const char** pext)
   82.40 +{ 
   82.41 +    const char* urlStart = url;
   82.42 +    const char *filename = 0;
   82.43 +    const char *lastDot = 0;
   82.44 +
   82.45 +    uint32_t charVal = UTF8Util::DecodeNextChar(&url);
   82.46 +
   82.47 +    while (charVal != 0)
   82.48 +    {
   82.49 +        if ((charVal == '/') || (charVal == '\\'))
   82.50 +        {
   82.51 +            filename = url;
   82.52 +            lastDot  = 0;
   82.53 +        }
   82.54 +        else if (charVal == '.')
   82.55 +        {
   82.56 +            lastDot = url - 1;
   82.57 +        }
   82.58 +        
   82.59 +        charVal = UTF8Util::DecodeNextChar(&url);
   82.60 +    }
   82.61 +
   82.62 +    if (pfilename)
   82.63 +    {
   82.64 +        // It was a naked filename
   82.65 +        if (urlStart && (*urlStart != '.') && *urlStart)
   82.66 +            *pfilename = urlStart;
   82.67 +        else
   82.68 +            *pfilename = filename;
   82.69 +    }
   82.70 +
   82.71 +    if (pext)
   82.72 +    {
   82.73 +        *pext = lastDot;
   82.74 +    }
   82.75 +}
   82.76 +
   82.77 +// Scans till the end of protocol. Returns first character past protocol,
   82.78 +// 0 if not found.
   82.79 +//  - protocol: 'file://', 'http://'
   82.80 +const char* ScanPathProtocol(const char* url)
   82.81 +{    
   82.82 +    uint32_t charVal = UTF8Util::DecodeNextChar(&url);
   82.83 +    uint32_t charVal2;
   82.84 +   
   82.85 +    while (charVal != 0)
   82.86 +    {
   82.87 +        // Treat a colon followed by a slash as absolute.
   82.88 +        if (charVal == ':')
   82.89 +        {
   82.90 +            charVal2 = UTF8Util::DecodeNextChar(&url);
   82.91 +            charVal  = UTF8Util::DecodeNextChar(&url);
   82.92 +            if ((charVal == '/') && (charVal2 == '\\'))
   82.93 +                return url;
   82.94 +        }
   82.95 +        charVal = UTF8Util::DecodeNextChar(&url);
   82.96 +    }
   82.97 +    return 0;
   82.98 +}
   82.99 +
  82.100 +
  82.101 +//--------------------------------------------------------------------
  82.102 +// ***** String Path API implementation
  82.103 +
  82.104 +bool String::HasAbsolutePath(const char* url)
  82.105 +{
  82.106 +    // Absolute paths can star with:
  82.107 +    //  - protocols:        'file://', 'http://'
  82.108 +    //  - windows drive:    'c:\'
  82.109 +    //  - UNC share name:   '\\share'
  82.110 +    //  - unix root         '/'
  82.111 +
  82.112 +    // On the other hand, relative paths are:
  82.113 +    //  - directory:        'directory/file'
  82.114 +    //  - this directory:   './file'
  82.115 +    //  - parent directory: '../file'
  82.116 +    // 
  82.117 +    // For now, we don't parse '.' or '..' out, but instead let it be concatenated
  82.118 +    // to string and let the OS figure it out. This, however, is not good for file
  82.119 +    // name matching in library/etc, so it should be improved.
  82.120 +
  82.121 +    if (!url || !*url)
  82.122 +        return true; // Treat empty strings as absolute.    
  82.123 +
  82.124 +    uint32_t charVal = UTF8Util::DecodeNextChar(&url);
  82.125 +
  82.126 +    // Fist character of '/' or '\\' means absolute url.
  82.127 +    if ((charVal == '/') || (charVal == '\\'))
  82.128 +        return true;
  82.129 +
  82.130 +    while (charVal != 0)
  82.131 +    {
  82.132 +        // Treat a colon followed by a slash as absolute.
  82.133 +        if (charVal == ':')
  82.134 +        {
  82.135 +            charVal = UTF8Util::DecodeNextChar(&url);
  82.136 +            // Protocol or windows drive. Absolute.
  82.137 +            if ((charVal == '/') || (charVal == '\\'))
  82.138 +                return true;
  82.139 +        }
  82.140 +        else if ((charVal == '/') || (charVal == '\\'))
  82.141 +        {
  82.142 +            // Not a first character (else 'if' above the loop would have caught it).
  82.143 +            // Must be a relative url.
  82.144 +            break;
  82.145 +        }
  82.146 +
  82.147 +        charVal = UTF8Util::DecodeNextChar(&url);
  82.148 +    }
  82.149 +
  82.150 +    // We get here for relative paths.
  82.151 +    return false;    
  82.152 +}
  82.153 +
  82.154 +
  82.155 +bool String::HasExtension(const char* path)
  82.156 +{
  82.157 +    const char* ext = 0;
  82.158 +    ScanFilePath(path, 0, &ext);
  82.159 +    return ext != 0;
  82.160 +}
  82.161 +bool String::HasProtocol(const char* path)
  82.162 +{
  82.163 +    return ScanPathProtocol(path) != 0;
  82.164 +}
  82.165 +
  82.166 +
  82.167 +String  String::GetPath() const
  82.168 +{
  82.169 +    const char* filename = 0;
  82.170 +    ScanFilePath(ToCStr(), &filename, 0);
  82.171 +
  82.172 +    // Technically we can have extra logic somewhere for paths,
  82.173 +    // such as enforcing protocol and '/' only based on flags,
  82.174 +    // but we keep it simple for now.
  82.175 +    return String(ToCStr(), filename ? (filename-ToCStr()) : GetSize());
  82.176 +}
  82.177 +
  82.178 +String  String::GetProtocol() const
  82.179 +{
  82.180 +    const char* protocolEnd = ScanPathProtocol(ToCStr());
  82.181 +    return String(ToCStr(), protocolEnd ? (protocolEnd-ToCStr()) : 0);
  82.182 +}
  82.183 +
  82.184 +String  String::GetFilename() const
  82.185 +{
  82.186 +    const char* filename = 0;
  82.187 +    ScanFilePath(ToCStr(), &filename, 0);
  82.188 +    return String(filename);
  82.189 +}
  82.190 +String  String::GetExtension() const
  82.191 +{
  82.192 +    const char* ext = 0;
  82.193 +    ScanFilePath(ToCStr(), 0, &ext);
  82.194 +    return String(ext);
  82.195 +}
  82.196 +
  82.197 +void    String::StripExtension()
  82.198 +{
  82.199 +    const char* ext = 0;
  82.200 +    ScanFilePath(ToCStr(), 0, &ext);    
  82.201 +    if (ext)
  82.202 +    {
  82.203 +        *this = String(ToCStr(), ext-ToCStr());
  82.204 +    }
  82.205 +}
  82.206 +
  82.207 +void    String::StripProtocol()
  82.208 +{
  82.209 +    const char* protocol = ScanPathProtocol(ToCStr());
  82.210 +    if (protocol)
  82.211 +        AssignString(protocol, OVR_strlen(protocol));
  82.212 +}
  82.213 +
  82.214 +} // OVR
    83.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    83.2 +++ b/LibOVR/Src/Kernel/OVR_SysFile.cpp	Wed Jan 14 06:51:16 2015 +0200
    83.3 @@ -0,0 +1,138 @@
    83.4 +/**************************************************************************
    83.5 +
    83.6 +Filename    :   OVR_SysFile.cpp
    83.7 +Content     :   File wrapper class implementation (Win32)
    83.8 +
    83.9 +Created     :   April 5, 1999
   83.10 +Authors     :   Michael Antonov
   83.11 +
   83.12 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   83.13 +
   83.14 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
   83.15 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
   83.16 +which is provided at the time of installation or download, or which 
   83.17 +otherwise accompanies this software in either electronic or hard copy form.
   83.18 +
   83.19 +You may obtain a copy of the License at
   83.20 +
   83.21 +http://www.oculusvr.com/licenses/LICENSE-3.2 
   83.22 +
   83.23 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
   83.24 +distributed under the License is distributed on an "AS IS" BASIS,
   83.25 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   83.26 +See the License for the specific language governing permissions and
   83.27 +limitations under the License.
   83.28 +
   83.29 +**************************************************************************/
   83.30 +
   83.31 +#define  GFILE_CXX
   83.32 +
   83.33 +// Standard C library (Captain Obvious guarantees!)
   83.34 +#include <stdio.h>
   83.35 +
   83.36 +#include "OVR_SysFile.h"
   83.37 +#include "OVR_Log.h"
   83.38 +
   83.39 +namespace OVR {
   83.40 +
   83.41 +// This is - a dummy file that fails on all calls.
   83.42 +
   83.43 +class UnopenedFile : public File
   83.44 +{
   83.45 +public:
   83.46 +    UnopenedFile()  { }
   83.47 +    ~UnopenedFile() { }
   83.48 +
   83.49 +    virtual const char* GetFilePath()               { return 0; }
   83.50 +
   83.51 +    // ** File Information
   83.52 +    virtual bool        IsValid()                   { return 0; }
   83.53 +    virtual bool        IsWritable()                { return 0; }
   83.54 +
   83.55 +    // Return position / file size
   83.56 +    virtual int         Tell()                      { return 0; }
   83.57 +    virtual int64_t     LTell()                     { return 0; }
   83.58 +    virtual int         GetLength()                 { return 0; }
   83.59 +    virtual int64_t     LGetLength()                { return 0; }
   83.60 +
   83.61 +//  virtual bool        Stat(FileStats *pfs)        { return 0; }
   83.62 +    virtual int         GetErrorCode()              { return Error_FileNotFound; }
   83.63 +
   83.64 +    // ** Stream implementation & I/O
   83.65 +    virtual int         Write(const uint8_t * /*pbuffer*/, int /*numBytes*/) { return -1; }
   83.66 +    virtual int         Read(uint8_t * /*pbuffer*/, int /*numBytes*/)         { return -1; }
   83.67 +    virtual int         SkipBytes(int /*numBytes*/)                          { return  0; }
   83.68 +    virtual int         BytesAvailable()                                     { return  0; }
   83.69 +    virtual bool        Flush()                                              { return  0; }
   83.70 +    virtual int         Seek(int /*offset*/, int /*origin*/)                 { return -1; }
   83.71 +    virtual int64_t     LSeek(int64_t /*offset*/, int /*origin*/)            { return -1; }
   83.72 +    
   83.73 +    virtual int         CopyFromStream(File * /*pstream*/, int /*byteSize*/)  { return -1; }
   83.74 +    virtual bool        Close()                                              { return  0; }
   83.75 +};
   83.76 +
   83.77 +
   83.78 +
   83.79 +// ***** System File
   83.80 +
   83.81 +// System file is created to access objects on file system directly
   83.82 +// This file can refer directly to path
   83.83 +
   83.84 +// ** Constructor
   83.85 +SysFile::SysFile() : DelegatedFile(0)
   83.86 +{
   83.87 +    pFile = *new UnopenedFile;
   83.88 +}
   83.89 +
   83.90 +Ptr<File> FileFILEOpen(const String& path, int flags, int mode);
   83.91 +
   83.92 +// Opens a file
   83.93 +SysFile::SysFile(const String& path, int flags, int mode) : DelegatedFile(0)
   83.94 +{
   83.95 +    Open(path, flags, mode);
   83.96 +}
   83.97 +
   83.98 +
   83.99 +// ** Open & management
  83.100 +// Will fail if file's already open
  83.101 +bool SysFile::Open(const String& path, int flags, int mode)
  83.102 +{
  83.103 +    pFile = FileFILEOpen(path, flags, mode);
  83.104 +    if ((!pFile) || (!pFile->IsValid()))
  83.105 +    {
  83.106 +        pFile = *new UnopenedFile;
  83.107 +        OVR_DEBUG_LOG(("Failed to open file: %s", path.ToCStr()));
  83.108 +        return 0;
  83.109 +    }
  83.110 +    //pFile = *OVR_NEW DelegatedFile(pFile); // MA Testing
  83.111 +    if (flags & Open_Buffered)
  83.112 +        pFile = *new BufferedFile(pFile);
  83.113 +    return 1;
  83.114 +}
  83.115 +
  83.116 +
  83.117 +// ** Overrides
  83.118 +
  83.119 +int SysFile::GetErrorCode()
  83.120 +{
  83.121 +    return pFile ? pFile->GetErrorCode() : Error_FileNotFound;
  83.122 +}
  83.123 +
  83.124 +
  83.125 +// Overrides to provide re-open support
  83.126 +bool SysFile::IsValid()
  83.127 +{
  83.128 +    return pFile && pFile->IsValid();
  83.129 +}
  83.130 +bool SysFile::Close()
  83.131 +{
  83.132 +    if (IsValid())
  83.133 +    {
  83.134 +        DelegatedFile::Close();
  83.135 +        pFile = *new UnopenedFile;
  83.136 +        return 1;
  83.137 +    }
  83.138 +    return 0;
  83.139 +}
  83.140 +
  83.141 +} // OVR
    84.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    84.2 +++ b/LibOVR/Src/Kernel/OVR_SysFile.h	Wed Jan 14 06:51:16 2015 +0200
    84.3 @@ -0,0 +1,104 @@
    84.4 +/************************************************************************************
    84.5 +
    84.6 +PublicHeader:   Kernel
    84.7 +Filename    :   OVR_SysFile.h
    84.8 +Content     :   Header for all internal file management - functions and structures
    84.9 +                to be inherited by OS specific subclasses.
   84.10 +Created     :   September 19, 2012
   84.11 +Notes       : 
   84.12 +
   84.13 +Notes       :   errno may not be preserved across use of GBaseFile member functions
   84.14 +            :   Directories cannot be deleted while files opened from them are in use
   84.15 +                (For the GetFullName function)
   84.16 +
   84.17 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   84.18 +
   84.19 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
   84.20 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
   84.21 +which is provided at the time of installation or download, or which 
   84.22 +otherwise accompanies this software in either electronic or hard copy form.
   84.23 +
   84.24 +You may obtain a copy of the License at
   84.25 +
   84.26 +http://www.oculusvr.com/licenses/LICENSE-3.2 
   84.27 +
   84.28 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
   84.29 +distributed under the License is distributed on an "AS IS" BASIS,
   84.30 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   84.31 +See the License for the specific language governing permissions and
   84.32 +limitations under the License.
   84.33 +
   84.34 +************************************************************************************/
   84.35 +
   84.36 +#ifndef OVR_SysFile_h
   84.37 +#define OVR_SysFile_h
   84.38 +
   84.39 +#include "OVR_File.h"
   84.40 +
   84.41 +namespace OVR {
   84.42 +
   84.43 +// ***** Declared classes
   84.44 +class   SysFile;
   84.45 +
   84.46 +//-----------------------------------------------------------------------------------
   84.47 +// *** File Statistics
   84.48 +
   84.49 +// This class contents are similar to _stat, providing
   84.50 +// creation, modify and other information about the file.
   84.51 +struct FileStat
   84.52 +{
   84.53 +    // No change or create time because they are not available on most systems
   84.54 +    int64_t ModifyTime;
   84.55 +    int64_t AccessTime;
   84.56 +    int64_t FileSize;
   84.57 +
   84.58 +    bool operator== (const FileStat& stat) const
   84.59 +    {
   84.60 +        return ( (ModifyTime == stat.ModifyTime) &&
   84.61 +                 (AccessTime == stat.AccessTime) &&
   84.62 +                 (FileSize == stat.FileSize) );
   84.63 +    }
   84.64 +};
   84.65 +
   84.66 +//-----------------------------------------------------------------------------------
   84.67 +// *** System File
   84.68 +
   84.69 +// System file is created to access objects on file system directly
   84.70 +// This file can refer directly to path.
   84.71 +// System file can be open & closed several times; however, such use is not recommended
   84.72 +// This class is realy a wrapper around an implementation of File interface for a 
   84.73 +// particular platform.
   84.74 +
   84.75 +class SysFile : public DelegatedFile
   84.76 +{
   84.77 +protected:
   84.78 +  SysFile(const SysFile &source) : DelegatedFile () { OVR_UNUSED(source); }
   84.79 +public:
   84.80 +
   84.81 +    // ** Constructor
   84.82 +    SysFile();
   84.83 +    // Opens a file
   84.84 +    SysFile(const String& path, int flags = Open_Read|Open_Buffered, int mode = Mode_ReadWrite); 
   84.85 +
   84.86 +    // ** Open & management 
   84.87 +    bool  Open(const String& path, int flags = Open_Read|Open_Buffered, int mode = Mode_ReadWrite);
   84.88 +        
   84.89 +    OVR_FORCE_INLINE bool  Create(const String& path, int mode = Mode_ReadWrite)
   84.90 +    { return Open(path, Open_ReadWrite|Open_Create, mode); }
   84.91 +
   84.92 +    // Helper function: obtain file statistics information. In OVR, this is used to detect file changes.
   84.93 +    // Return 0 if function failed, most likely because the file doesn't exist.
   84.94 +    static bool OVR_CDECL GetFileStat(FileStat* pfileStats, const String& path);
   84.95 +    
   84.96 +    // ** Overrides
   84.97 +    // Overridden to provide re-open support
   84.98 +    virtual int   GetErrorCode();
   84.99 +
  84.100 +    virtual bool  IsValid();
  84.101 +
  84.102 +    virtual bool  Close();    
  84.103 +};
  84.104 +
  84.105 +} // Namespace OVR
  84.106 +
  84.107 +#endif
    85.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    85.2 +++ b/LibOVR/Src/Kernel/OVR_System.cpp	Wed Jan 14 06:51:16 2015 +0200
    85.3 @@ -0,0 +1,149 @@
    85.4 +/************************************************************************************
    85.5 +
    85.6 +Filename    :   OVR_System.cpp
    85.7 +Content     :   General kernel initialization/cleanup, including that
    85.8 +                of the memory allocator.
    85.9 +Created     :   September 19, 2012
   85.10 +Notes       : 
   85.11 +
   85.12 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   85.13 +
   85.14 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
   85.15 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
   85.16 +which is provided at the time of installation or download, or which 
   85.17 +otherwise accompanies this software in either electronic or hard copy form.
   85.18 +
   85.19 +You may obtain a copy of the License at
   85.20 +
   85.21 +http://www.oculusvr.com/licenses/LICENSE-3.2 
   85.22 +
   85.23 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
   85.24 +distributed under the License is distributed on an "AS IS" BASIS,
   85.25 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   85.26 +See the License for the specific language governing permissions and
   85.27 +limitations under the License.
   85.28 +
   85.29 +************************************************************************************/
   85.30 +
   85.31 +#include "OVR_System.h"
   85.32 +#include "OVR_Threads.h"
   85.33 +#include "OVR_Timer.h"
   85.34 +#include "../Displays/OVR_Display.h"
   85.35 +#ifdef OVR_OS_WIN32
   85.36 +#include "../Displays/OVR_Win32_ShimFunctions.h"
   85.37 +#endif
   85.38 +
   85.39 +namespace OVR {
   85.40 +
   85.41 +#ifdef OVR_OS_WIN32
   85.42 +extern bool anyRiftsInExtendedMode();
   85.43 +#endif
   85.44 +
   85.45 +// Stack of destroy listeners (push/pop semantics)
   85.46 +static SystemSingletonInternal *SystemShutdownListenerStack = 0;
   85.47 +static Lock stackLock;
   85.48 +static bool DisplayShimInitialized = false;
   85.49 +
   85.50 +void SystemSingletonInternal::PushDestroyCallbacks()
   85.51 +{
   85.52 +    Lock::Locker locker(&stackLock);
   85.53 +
   85.54 +    // Push listener onto the stack
   85.55 +    NextSingleton = SystemShutdownListenerStack;
   85.56 +    SystemShutdownListenerStack = this;
   85.57 +}
   85.58 +
   85.59 +void System::DirectDisplayInitialize()
   85.60 +{
   85.61 +#ifdef OVR_OS_WIN32
   85.62 +	// Set up display code for Windows
   85.63 +	Win32::DisplayShim::GetInstance();
   85.64 +
   85.65 +	// This code will look for the first display. If it's a display
   85.66 +	// that's extending the destkop, the code will assume we're in
   85.67 +	// compatibility mode. Compatibility mode prevents shim loading
   85.68 +	// and renders only to extended Rifts.
   85.69 +	// If we find a display and it's application exclusive,
   85.70 +	// we load the shim so we can render to it.
   85.71 +	// If no display is available, we revert to whatever the
   85.72 +	// driver tells us we're in
   85.73 +
   85.74 +	bool anyExtendedRifts = anyRiftsInExtendedMode() || Display::InCompatibilityMode( false );
   85.75 +	
   85.76 +    DisplayShimInitialized = Win32::DisplayShim::GetInstance().Initialize(anyExtendedRifts);
   85.77 +#endif
   85.78 +}
   85.79 +
   85.80 +bool System::DirectDisplayEnabled()
   85.81 +{
   85.82 +    return DisplayShimInitialized;
   85.83 +}
   85.84 +
   85.85 +// Initializes System core, installing allocator.
   85.86 +void System::Init(Log* log, Allocator *palloc)
   85.87 +{    
   85.88 +    if (!Allocator::GetInstance())
   85.89 +    {
   85.90 +        Log::SetGlobalLog(log);
   85.91 +        Timer::initializeTimerSystem();
   85.92 +        Allocator::setInstance(palloc);
   85.93 +		Display::Initialize();
   85.94 +		DirectDisplayInitialize();
   85.95 +    }
   85.96 +    else
   85.97 +    {
   85.98 +        OVR_DEBUG_LOG(("System::Init failed - duplicate call."));
   85.99 +    }
  85.100 +}
  85.101 +
  85.102 +void System::Destroy()
  85.103 +{    
  85.104 +    if (Allocator::GetInstance())
  85.105 +    {
  85.106 +#ifdef OVR_OS_WIN32
  85.107 +		Win32::DisplayShim::GetInstance().Shutdown();
  85.108 +#endif
  85.109 +
  85.110 +		// Invoke all of the post-finish callbacks (normal case)
  85.111 +        for (SystemSingletonInternal *listener = SystemShutdownListenerStack; listener; listener = listener->NextSingleton)
  85.112 +		{
  85.113 +			listener->OnThreadDestroy();
  85.114 +		}
  85.115 +
  85.116 +#ifdef OVR_ENABLE_THREADS
  85.117 +		// Wait for all threads to finish; this must be done so that memory
  85.118 +		// allocator and all destructors finalize correctly.
  85.119 +		Thread::FinishAllThreads();
  85.120 +#endif
  85.121 +
  85.122 +		// Invoke all of the post-finish callbacks (normal case)
  85.123 +        for (SystemSingletonInternal *next, *listener = SystemShutdownListenerStack; listener; listener = next)
  85.124 +		{
  85.125 +            next = listener->NextSingleton;
  85.126 +
  85.127 +			listener->OnSystemDestroy();
  85.128 +		}
  85.129 +
  85.130 +        SystemShutdownListenerStack = 0;
  85.131 +
  85.132 +		// Shutdown heap and destroy SysAlloc singleton, if any.
  85.133 +        Allocator::GetInstance()->onSystemShutdown();
  85.134 +        Allocator::setInstance(0);
  85.135 +
  85.136 +        Timer::shutdownTimerSystem();
  85.137 +        Log::SetGlobalLog(Log::GetDefaultLog());
  85.138 +    }
  85.139 +    else
  85.140 +    {
  85.141 +        OVR_DEBUG_LOG(("System::Destroy failed - System not initialized."));
  85.142 +    }
  85.143 +}
  85.144 +
  85.145 +// Returns 'true' if system was properly initialized.
  85.146 +bool System::IsInitialized()
  85.147 +{
  85.148 +    return Allocator::GetInstance() != 0;
  85.149 +}
  85.150 +
  85.151 +
  85.152 +} // namespace OVR
    86.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    86.2 +++ b/LibOVR/Src/Kernel/OVR_System.h	Wed Jan 14 06:51:16 2015 +0200
    86.3 @@ -0,0 +1,174 @@
    86.4 +/************************************************************************************
    86.5 +
    86.6 +PublicHeader:   OVR
    86.7 +Filename    :   OVR_System.h
    86.8 +Content     :   General kernel initialization/cleanup, including that
    86.9 +                of the memory allocator.
   86.10 +Created     :   September 19, 2012
   86.11 +Notes       : 
   86.12 +
   86.13 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   86.14 +
   86.15 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
   86.16 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
   86.17 +which is provided at the time of installation or download, or which 
   86.18 +otherwise accompanies this software in either electronic or hard copy form.
   86.19 +
   86.20 +You may obtain a copy of the License at
   86.21 +
   86.22 +http://www.oculusvr.com/licenses/LICENSE-3.2 
   86.23 +
   86.24 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
   86.25 +distributed under the License is distributed on an "AS IS" BASIS,
   86.26 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   86.27 +See the License for the specific language governing permissions and
   86.28 +limitations under the License.
   86.29 +
   86.30 +************************************************************************************/
   86.31 +
   86.32 +#ifndef OVR_System_h
   86.33 +#define OVR_System_h
   86.34 +
   86.35 +#include "OVR_Allocator.h"
   86.36 +#include "OVR_Log.h"
   86.37 +#include "OVR_Atomic.h"
   86.38 +
   86.39 +namespace OVR {
   86.40 +
   86.41 +
   86.42 +//-----------------------------------------------------------------------------
   86.43 +// SystemSingleton
   86.44 +
   86.45 +// Subsystems are implemented using the Singleton pattern.
   86.46 +// To avoid code duplication in all the places where Singletons are defined,
   86.47 +// The pattern is defined once here and used everywhere.
   86.48 +
   86.49 +class SystemSingletonInternal
   86.50 +{
   86.51 +    friend class System;
   86.52 +
   86.53 +    SystemSingletonInternal* NextSingleton;
   86.54 +
   86.55 +    // No copying allowed
   86.56 +    OVR_NON_COPYABLE(SystemSingletonInternal);
   86.57 +
   86.58 +protected:
   86.59 +    SystemSingletonInternal() :
   86.60 +        NextSingleton(0)
   86.61 +    {
   86.62 +    }
   86.63 +
   86.64 +    virtual ~SystemSingletonInternal(){}
   86.65 +
   86.66 +    // Call this to register the destroy events
   86.67 +    // Destroy callbacks will be called in the reverse order they were registered
   86.68 +    // Note: As a rule of thumb, call this at the end of the singleton class constructor.
   86.69 +    void PushDestroyCallbacks();
   86.70 +
   86.71 +    // Required: Invoked when the System object is shutting down
   86.72 +    // Called after threads are stopped
   86.73 +    // Called before Log, Allocator, and Timer subsystems are stopped
   86.74 +    // Listeners are called in the opposite order they were registered
   86.75 +    virtual void OnSystemDestroy() = 0;
   86.76 +
   86.77 +    // Called just before waiting for threads to die
   86.78 +    // Listeners are called in the opposite order they were registered
   86.79 +    // Useful to start terminating threads at the right time
   86.80 +    // Note: The singleton must not delete itself here.
   86.81 +    virtual void OnThreadDestroy() {}
   86.82 +};
   86.83 +
   86.84 +// Singletons derive from this class
   86.85 +template<class T>
   86.86 +class SystemSingletonBase : public SystemSingletonInternal
   86.87 +{
   86.88 +    static AtomicPtr<T> SingletonInstance;
   86.89 +    static T* SlowGetInstance();
   86.90 +
   86.91 +protected:
   86.92 +    ~SystemSingletonBase()
   86.93 +    {
   86.94 +        // Make sure the instance gets set to zero on dtor
   86.95 +        if (SingletonInstance == this)
   86.96 +            SingletonInstance = 0;
   86.97 +    }
   86.98 +
   86.99 +public:
  86.100 +    static OVR_FORCE_INLINE T* GetInstance()
  86.101 +    {
  86.102 +        // Fast version
  86.103 +        // Note: The singleton instance is stored in an AtomicPtr<> to allow it to be accessed
  86.104 +        // atomically from multiple threads without locks.
  86.105 +        T* instance = SingletonInstance;
  86.106 +        return instance ? instance : SlowGetInstance();
  86.107 +    }
  86.108 +};
  86.109 +
  86.110 +// For reference, see N3337 14.5.1.3 (Static data members of class templates):
  86.111 +template<class T> OVR::AtomicPtr<T> OVR::SystemSingletonBase<T>::SingletonInstance;
  86.112 +
  86.113 +// Place this in the singleton class in the header file
  86.114 +#define OVR_DECLARE_SINGLETON(T) \
  86.115 +    friend class OVR::SystemSingletonBase<T>; \
  86.116 +private: \
  86.117 +    T(); \
  86.118 +    virtual ~T(); \
  86.119 +    virtual void OnSystemDestroy();
  86.120 +
  86.121 +// Place this in the singleton class source file
  86.122 +#define OVR_DEFINE_SINGLETON(T) \
  86.123 +    namespace OVR { \
  86.124 +    template<> T* SystemSingletonBase<T>::SlowGetInstance() \
  86.125 +    { \
  86.126 +        static OVR::Lock lock; \
  86.127 +        OVR::Lock::Locker locker(&lock); \
  86.128 +        if (!SingletonInstance) SingletonInstance = new T; \
  86.129 +        return SingletonInstance; \
  86.130 +    } \
  86.131 +    }
  86.132 +
  86.133 +
  86.134 +// ***** System Core Initialization class
  86.135 +
  86.136 +// System initialization must take place before any other OVR_Kernel objects are used;
  86.137 +// this is done my calling System::Init(). Among other things, this is necessary to
  86.138 +// initialize the memory allocator. Similarly, System::Destroy must be
  86.139 +// called before program exist for proper cleanup. Both of these tasks can be achieved by
  86.140 +// simply creating System object first, allowing its constructor/destructor do the work.
  86.141 +
  86.142 +// TBD: Require additional System class for Oculus Rift API?
  86.143 +
  86.144 +class System
  86.145 +{
  86.146 +public:
  86.147 +    // System constructor expects allocator to be specified, if it is being substituted.
  86.148 +    System(Log* log = Log::ConfigureDefaultLog(LogMask_Debug),
  86.149 +           Allocator* palloc = DefaultAllocator::InitSystemSingleton())
  86.150 +    {
  86.151 +        Init(log, palloc);
  86.152 +    }
  86.153 +    ~System()
  86.154 +    {
  86.155 +        Destroy();
  86.156 +    }
  86.157 +
  86.158 +	static void OVR_CDECL DirectDisplayInitialize();
  86.159 +    static bool OVR_CDECL DirectDisplayEnabled();
  86.160 +
  86.161 +    // Returns 'true' if system was properly initialized.
  86.162 +    static bool OVR_CDECL IsInitialized();
  86.163 +
  86.164 +    // Initializes System core.  Users can override memory implementation by passing
  86.165 +    // a different Allocator here.
  86.166 +    static void OVR_CDECL Init(Log* log = Log::ConfigureDefaultLog(LogMask_Debug),
  86.167 +                               Allocator *palloc = DefaultAllocator::InitSystemSingleton());
  86.168 +
  86.169 +	// De-initializes System more, finalizing the threading system and destroying
  86.170 +    // the global memory allocator.
  86.171 +    static void OVR_CDECL Destroy();
  86.172 +};
  86.173 +
  86.174 +
  86.175 +} // namespace OVR
  86.176 +
  86.177 +#endif
    87.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    87.2 +++ b/LibOVR/Src/Kernel/OVR_ThreadCommandQueue.cpp	Wed Jan 14 06:51:16 2015 +0200
    87.3 @@ -0,0 +1,401 @@
    87.4 +/************************************************************************************
    87.5 +
    87.6 +PublicHeader:   None
    87.7 +Filename    :   OVR_ThreadCommandQueue.cpp
    87.8 +Content     :   Command queue for operations executed on a thread
    87.9 +Created     :   October 29, 2012
   87.10 +
   87.11 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   87.12 +
   87.13 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
   87.14 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
   87.15 +which is provided at the time of installation or download, or which 
   87.16 +otherwise accompanies this software in either electronic or hard copy form.
   87.17 +
   87.18 +You may obtain a copy of the License at
   87.19 +
   87.20 +http://www.oculusvr.com/licenses/LICENSE-3.2 
   87.21 +
   87.22 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
   87.23 +distributed under the License is distributed on an "AS IS" BASIS,
   87.24 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   87.25 +See the License for the specific language governing permissions and
   87.26 +limitations under the License.
   87.27 +
   87.28 +************************************************************************************/
   87.29 +
   87.30 +#include "OVR_ThreadCommandQueue.h"
   87.31 +
   87.32 +namespace OVR {
   87.33 +
   87.34 +
   87.35 +//------------------------------------------------------------------------
   87.36 +// ***** CircularBuffer
   87.37 +
   87.38 +// CircularBuffer is a FIFO buffer implemented in a single block of memory,
   87.39 +// which allows writing and reading variable-size data chucks. Write fails
   87.40 +// if buffer is full.
   87.41 +
   87.42 +class CircularBuffer
   87.43 +{
   87.44 +    enum {
   87.45 +        AlignSize = 16,
   87.46 +        AlignMask = AlignSize - 1
   87.47 +    };
   87.48 +
   87.49 +    uint8_t*  pBuffer;
   87.50 +    size_t  Size;
   87.51 +    size_t  Tail;   // Byte offset of next item to be popped.
   87.52 +    size_t  Head;   // Byte offset of where next push will take place.
   87.53 +    size_t  End;    // When Head < Tail, this is used instead of Size.    
   87.54 +
   87.55 +    inline size_t roundUpSize(size_t size)
   87.56 +    { return (size + AlignMask) & ~(size_t)AlignMask; }
   87.57 +
   87.58 +public:
   87.59 +
   87.60 +    CircularBuffer(size_t size)
   87.61 +        : Size(size), Tail(0), Head(0), End(0)
   87.62 +    {
   87.63 +        pBuffer = (uint8_t*)OVR_ALLOC_ALIGNED(roundUpSize(size), AlignSize);
   87.64 +    }
   87.65 +    ~CircularBuffer()
   87.66 +    {
   87.67 +        // For ThreadCommands, we must consume everything before shutdown.
   87.68 +        OVR_ASSERT(IsEmpty());
   87.69 +        OVR_FREE_ALIGNED(pBuffer);
   87.70 +    }
   87.71 +
   87.72 +    bool    IsEmpty() const { return (Head == Tail); }
   87.73 +
   87.74 +    // Allocates a state block of specified size and advances pointers,
   87.75 +    // returning 0 if buffer is full.
   87.76 +    uint8_t*  Write(size_t size);
   87.77 +
   87.78 +    // Returns a pointer to next available data block; 0 if none available.
   87.79 +    uint8_t*  ReadBegin()
   87.80 +    { return (Head != Tail) ? (pBuffer + Tail) : 0; }
   87.81 +    // Consumes data of specified size; this must match size passed to Write.
   87.82 +    void    ReadEnd(size_t size);
   87.83 +};
   87.84 +
   87.85 +
   87.86 +// Allocates a state block of specified size and advances pointers,
   87.87 +// returning 0 if buffer is full.
   87.88 +uint8_t* CircularBuffer::Write(size_t size)
   87.89 +{
   87.90 +    uint8_t* p = 0;
   87.91 +
   87.92 +    size = roundUpSize(size);
   87.93 +    // Since this is circular buffer, always allow at least one item.
   87.94 +    OVR_ASSERT(size < Size/2);
   87.95 +
   87.96 +    if (Head >= Tail)
   87.97 +    {
   87.98 +        OVR_ASSERT(End == 0);
   87.99 +        
  87.100 +        if (size <= (Size - Head))
  87.101 +        {
  87.102 +            p    = pBuffer + Head;
  87.103 +            Head += size;
  87.104 +        }
  87.105 +        else if (size < Tail)
  87.106 +        {
  87.107 +            p    = pBuffer;
  87.108 +            End  = Head;
  87.109 +            Head = size;
  87.110 +            OVR_ASSERT(Head != Tail);
  87.111 +        }
  87.112 +    }
  87.113 +    else
  87.114 +    {
  87.115 +        OVR_ASSERT(End != 0);
  87.116 +
  87.117 +        if ((Tail - Head) > size)
  87.118 +        {
  87.119 +            p    = pBuffer + Head;
  87.120 +            Head += size;
  87.121 +            OVR_ASSERT(Head != Tail);
  87.122 +        }
  87.123 +    }
  87.124 +
  87.125 +    return p;
  87.126 +}
  87.127 +
  87.128 +void CircularBuffer::ReadEnd(size_t size)
  87.129 +{
  87.130 +    OVR_ASSERT(Head != Tail);
  87.131 +    size = roundUpSize(size);
  87.132 +    
  87.133 +    Tail += size;        
  87.134 +    if (Tail == End)
  87.135 +    {
  87.136 +        Tail = End = 0;
  87.137 +    }
  87.138 +    else if (Tail == Head)
  87.139 +    {        
  87.140 +        OVR_ASSERT(End == 0);
  87.141 +        Tail = Head = 0;
  87.142 +    }
  87.143 +}
  87.144 +
  87.145 +
  87.146 +//-------------------------------------------------------------------------------------
  87.147 +// ***** ThreadCommand
  87.148 +
  87.149 +ThreadCommand::PopBuffer::~PopBuffer()
  87.150 +{
  87.151 +	if (Size) {
  87.152 +		Destruct<ThreadCommand>(toCommand());
  87.153 +	}
  87.154 +}
  87.155 +
  87.156 +void ThreadCommand::PopBuffer::InitFromBuffer(void* data)
  87.157 +{
  87.158 +    ThreadCommand* cmd = (ThreadCommand*)data;
  87.159 +    OVR_ASSERT(cmd->Size <= MaxSize);
  87.160 +
  87.161 +	if (Size) {
  87.162 +		Destruct<ThreadCommand>(toCommand());
  87.163 +	}
  87.164 +    Size = cmd->Size;    
  87.165 +    memcpy(Buffer, (void*)cmd, Size);
  87.166 +}
  87.167 +
  87.168 +void ThreadCommand::PopBuffer::Execute()
  87.169 +{
  87.170 +    ThreadCommand* command = toCommand();
  87.171 +    OVR_ASSERT(command);
  87.172 +    command->Execute();
  87.173 +	if (NeedsWait()) {
  87.174 +		GetEvent()->PulseEvent();
  87.175 +	}
  87.176 +}
  87.177 +
  87.178 +//-------------------------------------------------------------------------------------
  87.179 +
  87.180 +class ThreadCommandQueueImpl : public NewOverrideBase
  87.181 +{
  87.182 +    typedef ThreadCommand::NotifyEvent NotifyEvent;
  87.183 +    friend class ThreadCommandQueue;
  87.184 +    
  87.185 +public:
  87.186 +
  87.187 +    ThreadCommandQueueImpl(ThreadCommandQueue* queue) :
  87.188 +		pQueue(queue),
  87.189 +		ExitEnqueued(false),
  87.190 +		ExitProcessed(false),
  87.191 +		CommandBuffer(2048),
  87.192 +		PullThreadId(0)
  87.193 +    {
  87.194 +    }
  87.195 +    ~ThreadCommandQueueImpl();
  87.196 +
  87.197 +
  87.198 +    bool PushCommand(const ThreadCommand& command);
  87.199 +    bool PopCommand(ThreadCommand::PopBuffer* popBuffer);
  87.200 +
  87.201 +
  87.202 +    // ExitCommand is used by notify us that Thread is shutting down.
  87.203 +    struct ExitCommand : public ThreadCommand
  87.204 +    {
  87.205 +        ThreadCommandQueueImpl* pImpl;
  87.206 +        
  87.207 +        ExitCommand(ThreadCommandQueueImpl* impl, bool wait)
  87.208 +            : ThreadCommand(sizeof(ExitCommand), wait, true), pImpl(impl) { }
  87.209 +
  87.210 +        virtual void Execute() const
  87.211 +        {
  87.212 +            Lock::Locker lock(&pImpl->QueueLock);
  87.213 +            pImpl->ExitProcessed = true;
  87.214 +        }
  87.215 +        virtual ThreadCommand* CopyConstruct(void* p) const 
  87.216 +        { return Construct<ExitCommand>(p, *this); }
  87.217 +    };
  87.218 +
  87.219 +
  87.220 +    NotifyEvent* AllocNotifyEvent_NTS()
  87.221 +    {
  87.222 +        NotifyEvent* p = AvailableEvents.GetFirst();
  87.223 +
  87.224 +        if (!AvailableEvents.IsNull(p))
  87.225 +            p->RemoveNode();        
  87.226 +        else
  87.227 +            p = new NotifyEvent;
  87.228 +        return p;
  87.229 +    }
  87.230 +
  87.231 +    void         FreeNotifyEvent_NTS(NotifyEvent* p)
  87.232 +    {
  87.233 +        AvailableEvents.PushBack(p);
  87.234 +    }
  87.235 +
  87.236 +    void        FreeNotifyEvents_NTS()
  87.237 +    {
  87.238 +        while(!AvailableEvents.IsEmpty())
  87.239 +        {
  87.240 +            NotifyEvent* p = AvailableEvents.GetFirst();
  87.241 +            p->RemoveNode();
  87.242 +            delete p;
  87.243 +        }
  87.244 +    }
  87.245 +
  87.246 +    ThreadCommandQueue* pQueue;
  87.247 +    Lock                QueueLock;
  87.248 +    volatile bool       ExitEnqueued;
  87.249 +    volatile bool       ExitProcessed;
  87.250 +    List<NotifyEvent>   AvailableEvents;
  87.251 +    List<NotifyEvent>   BlockedProducers;
  87.252 +    CircularBuffer      CommandBuffer;
  87.253 +
  87.254 +	// The pull thread id is set to the last thread that pulled commands.
  87.255 +	// Since this thread command queue is designed for a single thread,
  87.256 +	// reentrant behavior that would cause a dead-lock for messages that
  87.257 +	// wait for completion can be avoided by simply comparing the
  87.258 +	// thread id of the last pull.
  87.259 +	OVR::ThreadId		PullThreadId;
  87.260 +};
  87.261 +
  87.262 +ThreadCommandQueueImpl::~ThreadCommandQueueImpl()
  87.263 +{
  87.264 +    Lock::Locker lock(&QueueLock);
  87.265 +    OVR_ASSERT(BlockedProducers.IsEmpty());
  87.266 +    FreeNotifyEvents_NTS();
  87.267 +}
  87.268 +
  87.269 +bool ThreadCommandQueueImpl::PushCommand(const ThreadCommand& command)
  87.270 +{
  87.271 +	if (command.NeedsWait() && PullThreadId == OVR::GetCurrentThreadId())
  87.272 +	{
  87.273 +		command.Execute();
  87.274 +		return true;
  87.275 +	}
  87.276 +
  87.277 +    ThreadCommand::NotifyEvent* completeEvent = 0;
  87.278 +    ThreadCommand::NotifyEvent* queueAvailableEvent = 0;
  87.279 +
  87.280 +    // Repeat  writing command into buffer until it is available.    
  87.281 +	for (;;) {
  87.282 +        { // Lock Scope
  87.283 +            Lock::Locker lock(&QueueLock);
  87.284 +
  87.285 +            if (queueAvailableEvent) {
  87.286 +                FreeNotifyEvent_NTS(queueAvailableEvent);
  87.287 +                queueAvailableEvent = 0;
  87.288 +            }
  87.289 +
  87.290 +            // Don't allow any commands after PushExitCommand() is called.
  87.291 +			if (ExitEnqueued && !command.ExitFlag) {
  87.292 +				return false;
  87.293 +			}
  87.294 +
  87.295 +            bool bufferWasEmpty = CommandBuffer.IsEmpty();
  87.296 +            uint8_t* buffer = CommandBuffer.Write(command.GetSize());
  87.297 +
  87.298 +			if (buffer) {
  87.299 +                ThreadCommand* c = command.CopyConstruct(buffer);
  87.300 +
  87.301 +				if (c->NeedsWait()) {
  87.302 +					completeEvent = c->pEvent = AllocNotifyEvent_NTS();
  87.303 +				}
  87.304 +
  87.305 +				// Signal-waker consumer when we add data to buffer.
  87.306 +				if (bufferWasEmpty) {
  87.307 +					pQueue->OnPushNonEmpty_Locked();
  87.308 +				}
  87.309 +
  87.310 +				break;
  87.311 +            }
  87.312 +
  87.313 +            queueAvailableEvent = AllocNotifyEvent_NTS();
  87.314 +            BlockedProducers.PushBack(queueAvailableEvent);
  87.315 +        } // Lock Scope
  87.316 +
  87.317 +        queueAvailableEvent->Wait();
  87.318 +    } // Intentional infinite loop
  87.319 +
  87.320 +    // Command was enqueued, wait if necessary.
  87.321 +    if (completeEvent) {
  87.322 +        completeEvent->Wait();
  87.323 +        Lock::Locker lock(&QueueLock);
  87.324 +        FreeNotifyEvent_NTS(completeEvent);
  87.325 +    }
  87.326 +
  87.327 +    return true;
  87.328 +}
  87.329 +
  87.330 +
  87.331 +// Pops the next command from the thread queue, if any is available.
  87.332 +bool ThreadCommandQueueImpl::PopCommand(ThreadCommand::PopBuffer* popBuffer)
  87.333 +{    
  87.334 +	PullThreadId = OVR::GetCurrentThreadId();
  87.335 +
  87.336 +	Lock::Locker lock(&QueueLock);
  87.337 +
  87.338 +    uint8_t* buffer = CommandBuffer.ReadBegin();
  87.339 +    if (!buffer)
  87.340 +    {
  87.341 +        // Notify thread while in lock scope, enabling initialization of wait.
  87.342 +        pQueue->OnPopEmpty_Locked();
  87.343 +        return false;
  87.344 +    }
  87.345 +
  87.346 +    popBuffer->InitFromBuffer(buffer);
  87.347 +    CommandBuffer.ReadEnd(popBuffer->GetSize());
  87.348 +
  87.349 +    if (!BlockedProducers.IsEmpty())
  87.350 +    {
  87.351 +        ThreadCommand::NotifyEvent* queueAvailableEvent = BlockedProducers.GetFirst();
  87.352 +        queueAvailableEvent->RemoveNode();
  87.353 +        queueAvailableEvent->PulseEvent();
  87.354 +        // Event is freed later by waiter.
  87.355 +    }    
  87.356 +    return true;
  87.357 +}
  87.358 +
  87.359 +
  87.360 +//-------------------------------------------------------------------------------------
  87.361 +
  87.362 +ThreadCommandQueue::ThreadCommandQueue()
  87.363 +{
  87.364 +    pImpl = new ThreadCommandQueueImpl(this);
  87.365 +}
  87.366 +ThreadCommandQueue::~ThreadCommandQueue()
  87.367 +{
  87.368 +    delete pImpl;
  87.369 +}
  87.370 +
  87.371 +bool ThreadCommandQueue::PushCommand(const ThreadCommand& command)
  87.372 +{
  87.373 +    return pImpl->PushCommand(command);
  87.374 +}
  87.375 +
  87.376 +bool ThreadCommandQueue::PopCommand(ThreadCommand::PopBuffer* popBuffer)
  87.377 +{    
  87.378 +    return pImpl->PopCommand(popBuffer);
  87.379 +}
  87.380 +
  87.381 +void ThreadCommandQueue::PushExitCommand(bool wait)
  87.382 +{
  87.383 +    // Exit is processed in two stages:
  87.384 +    //  - First, ExitEnqueued flag is set to block further commands from queuing up.
  87.385 +    //  - Second, the actual exit call is processed on the consumer thread, flushing
  87.386 +    //    any prior commands.
  87.387 +    //    IsExiting() only returns true after exit has flushed.
  87.388 +    {
  87.389 +        Lock::Locker lock(&pImpl->QueueLock);
  87.390 +        if (pImpl->ExitEnqueued)
  87.391 +            return;
  87.392 +        pImpl->ExitEnqueued = true;
  87.393 +    }
  87.394 +
  87.395 +    PushCommand(ThreadCommandQueueImpl::ExitCommand(pImpl, wait));
  87.396 +}
  87.397 +
  87.398 +bool ThreadCommandQueue::IsExiting() const
  87.399 +{
  87.400 +    return pImpl->ExitProcessed;
  87.401 +}
  87.402 +
  87.403 +
  87.404 +} // namespace OVR
    88.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    88.2 +++ b/LibOVR/Src/Kernel/OVR_ThreadCommandQueue.h	Wed Jan 14 06:51:16 2015 +0200
    88.3 @@ -0,0 +1,318 @@
    88.4 +/************************************************************************************
    88.5 +
    88.6 +PublicHeader:   None
    88.7 +Filename    :   OVR_ThreadCommandQueue.h
    88.8 +Content     :   Command queue for operations executed on a thread
    88.9 +Created     :   October 29, 2012
   88.10 +Author      :   Michael Antonov
   88.11 +
   88.12 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   88.13 +
   88.14 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
   88.15 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
   88.16 +which is provided at the time of installation or download, or which 
   88.17 +otherwise accompanies this software in either electronic or hard copy form.
   88.18 +
   88.19 +You may obtain a copy of the License at
   88.20 +
   88.21 +http://www.oculusvr.com/licenses/LICENSE-3.2 
   88.22 +
   88.23 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
   88.24 +distributed under the License is distributed on an "AS IS" BASIS,
   88.25 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   88.26 +See the License for the specific language governing permissions and
   88.27 +limitations under the License.
   88.28 +
   88.29 +************************************************************************************/
   88.30 +
   88.31 +#ifndef OVR_ThreadCommandQueue_h
   88.32 +#define OVR_ThreadCommandQueue_h
   88.33 +
   88.34 +#include "../Kernel/OVR_Types.h"
   88.35 +#include "../Kernel/OVR_List.h"
   88.36 +#include "../Kernel/OVR_Atomic.h"
   88.37 +#include "../Kernel/OVR_Threads.h"
   88.38 +
   88.39 +namespace OVR {
   88.40 +
   88.41 +class ThreadCommand;
   88.42 +class ThreadCommandQueue;
   88.43 +
   88.44 +
   88.45 +//-------------------------------------------------------------------------------------
   88.46 +// ***** ThreadCommand
   88.47 +
   88.48 +// ThreadCommand is a base class implementation for commands stored in ThreadCommandQueue.
   88.49 +class ThreadCommand
   88.50 +{
   88.51 +public:    
   88.52 +    // NotifyEvent is used by ThreadCommandQueue::PushCallAndWait to notify the
   88.53 +    // calling (producer)  thread when command is completed or queue slot is available.
   88.54 +    class NotifyEvent : public ListNode<NotifyEvent>, public NewOverrideBase
   88.55 +    {
   88.56 +        Event E;
   88.57 +    public:   
   88.58 +        NotifyEvent() { }
   88.59 +
   88.60 +        void Wait()        { E.Wait(); }
   88.61 +        void PulseEvent()  { E.PulseEvent(); }
   88.62 +    };
   88.63 +
   88.64 +    // ThreadCommand::PopBuffer is temporary storage for a command popped off
   88.65 +    // by ThreadCommandQueue::PopCommand. 
   88.66 +    class PopBuffer
   88.67 +    {
   88.68 +        enum { MaxSize = 256 };
   88.69 +
   88.70 +        size_t Size;
   88.71 +        union {            
   88.72 +            uint8_t Buffer[MaxSize];
   88.73 +            size_t Align;
   88.74 +        };
   88.75 +
   88.76 +        ThreadCommand* toCommand() const { return (ThreadCommand*)Buffer; }
   88.77 +
   88.78 +    public:
   88.79 +        PopBuffer() : Size(0) { }
   88.80 +        ~PopBuffer();
   88.81 +
   88.82 +        void        InitFromBuffer(void* data);
   88.83 +
   88.84 +        bool        HasCommand() const  { return Size != 0; }
   88.85 +        size_t      GetSize() const     { return Size; }
   88.86 +        bool        NeedsWait() const   { return toCommand()->NeedsWait(); }
   88.87 +        NotifyEvent* GetEvent() const   { return toCommand()->pEvent; }
   88.88 +
   88.89 +        // Execute the command and also notifies caller to finish waiting,
   88.90 +        // if necessary.
   88.91 +        void        Execute();
   88.92 +    };
   88.93 +    
   88.94 +    uint16_t     Size;
   88.95 +    bool         WaitFlag; 
   88.96 +    bool         ExitFlag; // Marks the last exit command. 
   88.97 +    NotifyEvent* pEvent;
   88.98 +
   88.99 +    ThreadCommand(size_t size, bool waitFlag, bool exitFlag = false)
  88.100 +        : Size((uint16_t)size), WaitFlag(waitFlag), ExitFlag(exitFlag), pEvent(0) { }
  88.101 +    virtual ~ThreadCommand() { }
  88.102 +
  88.103 +    bool          NeedsWait() const { return WaitFlag; }
  88.104 +    size_t        GetSize() const   { return Size; }
  88.105 +
  88.106 +    virtual void            Execute() const = 0;
  88.107 +    // Copy constructor used for serializing this to memory buffer.
  88.108 +    virtual ThreadCommand*  CopyConstruct(void* p) const = 0;
  88.109 +};
  88.110 +
  88.111 +
  88.112 +//-------------------------------------------------------------------------------------
  88.113 +
  88.114 +// CleanType is a template that strips 'const' and '&' modifiers from the argument type;
  88.115 +// for example, typename CleanType<A&>::Type is equivalent to A.
  88.116 +template<class T> struct CleanType           { typedef T Type; };
  88.117 +template<class T> struct CleanType<T&>       { typedef T Type; };
  88.118 +template<class T> struct CleanType<const T>  { typedef T Type; };
  88.119 +template<class T> struct CleanType<const T&> { typedef T Type; };
  88.120 +
  88.121 +// SelfType is a template that yields the argument type. This helps avoid conflicts with
  88.122 +// automatic template argument deduction for function calls when identical argument
  88.123 +// is already defined.
  88.124 +template<class T> struct SelfType { typedef T Type; };
  88.125 +
  88.126 +
  88.127 +
  88.128 +//-------------------------------------------------------------------------------------
  88.129 +// ThreadCommand specializations for member functions with different number of
  88.130 +// arguments and argument types.
  88.131 +
  88.132 +// Used to return nothing from a ThreadCommand, to avoid problems with 'void'.
  88.133 +struct Void
  88.134 +{
  88.135 +    Void() {}
  88.136 +    Void(int) {}
  88.137 +};
  88.138 +
  88.139 +// ThreadCommand for member function with 0 arguments.
  88.140 +template<class C, class R>
  88.141 +class ThreadCommandMF0 : public ThreadCommand
  88.142 +{   
  88.143 +    typedef R (C::*FnPtr)();
  88.144 +    C*      pClass;
  88.145 +    FnPtr   pFn;
  88.146 +    R*      pRet;
  88.147 +
  88.148 +    void executeImpl() const
  88.149 +    {
  88.150 +        pRet ? (void)(*pRet = (pClass->*pFn)()) :
  88.151 +	           (void)(pClass->*pFn)();
  88.152 +    }
  88.153 +
  88.154 +public:    
  88.155 +    ThreadCommandMF0(C* pclass, FnPtr fn, R* ret, bool needsWait)
  88.156 +        : ThreadCommand(sizeof(ThreadCommandMF0), needsWait),
  88.157 +          pClass(pclass), pFn(fn), pRet(ret) { }
  88.158 +
  88.159 +    virtual void           Execute() const { executeImpl(); }
  88.160 +    virtual ThreadCommand* CopyConstruct(void* p) const
  88.161 +    { return Construct<ThreadCommandMF0>(p, *this); }
  88.162 +};
  88.163 +
  88.164 +
  88.165 +// ThreadCommand for member function with 1 argument.
  88.166 +template<class C, class R, class A0>
  88.167 +class ThreadCommandMF1 : public ThreadCommand
  88.168 +{   
  88.169 +    typedef R (C::*FnPtr)(A0);
  88.170 +    C*                           pClass;
  88.171 +    FnPtr                        pFn;
  88.172 +    R*                           pRet;
  88.173 +    typename CleanType<A0>::Type AVal0;
  88.174 +
  88.175 +    void executeImpl() const
  88.176 +    {
  88.177 +      pRet ? (void)(*pRet = (pClass->*pFn)(AVal0)) :
  88.178 +	         (void)(pClass->*pFn)(AVal0);
  88.179 +    }
  88.180 +
  88.181 +public:    
  88.182 +    ThreadCommandMF1(C* pclass, FnPtr fn, R* ret, A0 a0, bool needsWait)
  88.183 +        : ThreadCommand(sizeof(ThreadCommandMF1), needsWait),
  88.184 +          pClass(pclass), pFn(fn), pRet(ret), AVal0(a0) { }
  88.185 +
  88.186 +    virtual void           Execute() const { executeImpl(); }
  88.187 +    virtual ThreadCommand* CopyConstruct(void* p) const
  88.188 +    { return Construct<ThreadCommandMF1>(p, *this); }
  88.189 +};
  88.190 +
  88.191 +// ThreadCommand for member function with 2 arguments.
  88.192 +template<class C, class R, class A0, class A1>
  88.193 +class ThreadCommandMF2 : public ThreadCommand
  88.194 +{   
  88.195 +    typedef R (C::*FnPtr)(A0, A1);
  88.196 +    C*                            pClass;
  88.197 +    FnPtr                         pFn;
  88.198 +    R*                            pRet;
  88.199 +    typename CleanType<A0>::Type  AVal0;
  88.200 +    typename CleanType<A1>::Type  AVal1;
  88.201 +
  88.202 +    void executeImpl() const
  88.203 +    {
  88.204 +        pRet ? (void)(*pRet = (pClass->*pFn)(AVal0, AVal1)) :
  88.205 +	           (void)(pClass->*pFn)(AVal0, AVal1);
  88.206 +    }
  88.207 +
  88.208 +public:    
  88.209 +    ThreadCommandMF2(C* pclass, FnPtr fn, R* ret, A0 a0, A1 a1, bool needsWait)
  88.210 +        : ThreadCommand(sizeof(ThreadCommandMF2), needsWait),
  88.211 +          pClass(pclass), pFn(fn), pRet(ret), AVal0(a0), AVal1(a1) { }
  88.212 +    
  88.213 +    virtual void           Execute() const { executeImpl(); }
  88.214 +    virtual ThreadCommand* CopyConstruct(void* p) const 
  88.215 +    { return Construct<ThreadCommandMF2>(p, *this); }
  88.216 +};
  88.217 +
  88.218 +
  88.219 +//-------------------------------------------------------------------------------------
  88.220 +// ***** ThreadCommandQueue
  88.221 +
  88.222 +// ThreadCommandQueue is a queue of executable function-call commands intended to be
  88.223 +// serviced by a single consumer thread. Commands are added to the queue with PushCall
  88.224 +// and removed with PopCall; they are processed in FIFO order. Multiple producer threads
  88.225 +// are supported and will be blocked if internal data buffer is full.
  88.226 +
  88.227 +class ThreadCommandQueue
  88.228 +{
  88.229 +public:
  88.230 +
  88.231 +    ThreadCommandQueue();
  88.232 +    virtual ~ThreadCommandQueue();
  88.233 +
  88.234 +
  88.235 +    // Pops the next command from the thread queue, if any is available.
  88.236 +    // The command should be executed by calling popBuffer->Execute().
  88.237 +    // Returns 'false' if no command is available at the time of the call.
  88.238 +    bool PopCommand(ThreadCommand::PopBuffer* popBuffer);
  88.239 +
  88.240 +    // Generic implementaion of PushCommand; enqueues a command for execution.
  88.241 +    // Returns 'false' if push failed, usually indicating thread shutdown.
  88.242 +    bool PushCommand(const ThreadCommand& command);
  88.243 +
  88.244 +    // 
  88.245 +    void PushExitCommand(bool wait);
  88.246 +
  88.247 +    // Returns 'true' once ExitCommand has been processed, so the thread can shut down.
  88.248 +    bool IsExiting() const;
  88.249 +
  88.250 +
  88.251 +    // These two virtual functions serve as notifications for derived
  88.252 +    // thread waiting.    
  88.253 +    virtual void OnPushNonEmpty_Locked() { }
  88.254 +    virtual void OnPopEmpty_Locked()     { }
  88.255 +
  88.256 +
  88.257 +    // *** PushCall with no result
  88.258 +    
  88.259 +    // Enqueue a member function of 'this' class to be called on consumer thread.
  88.260 +    // By default the function returns immediately; set 'wait' argument to 'true' to
  88.261 +    // wait for completion.
  88.262 +    template<class C, class R>
  88.263 +    bool PushCall(R (C::*fn)(), bool wait = false)
  88.264 +    { return PushCommand(ThreadCommandMF0<C,R>(static_cast<C*>(this), fn, 0, wait)); }       
  88.265 +    template<class C, class R, class A0>
  88.266 +    bool PushCall(R (C::*fn)(A0), typename SelfType<A0>::Type a0, bool wait = false)
  88.267 +    { return PushCommand(ThreadCommandMF1<C,R,A0>(static_cast<C*>(this), fn, 0, a0, wait)); }
  88.268 +    template<class C, class R, class A0, class A1>
  88.269 +    bool PushCall(R (C::*fn)(A0, A1),
  88.270 +                  typename SelfType<A0>::Type a0, typename SelfType<A1>::Type a1, bool wait = false)
  88.271 +    { return PushCommand(ThreadCommandMF2<C,R,A0,A1>(static_cast<C*>(this), fn, 0, a0, a1, wait)); }
  88.272 +    // Enqueue a specified member function call of class C.
  88.273 +    // By default the function returns immediately; set 'wait' argument to 'true' to
  88.274 +    // wait for completion.
  88.275 +    template<class C, class R>
  88.276 +    bool PushCall(C* p, R (C::*fn)(), bool wait = false)
  88.277 +    { return PushCommand(ThreadCommandMF0<C,R>(p, fn, 0, wait)); }
  88.278 +    template<class C, class R, class A0>
  88.279 +    bool PushCall(C* p, R (C::*fn)(A0), typename SelfType<A0>::Type a0, bool wait = false)
  88.280 +    { return PushCommand(ThreadCommandMF1<C,R,A0>(p, fn, 0, a0, wait)); }
  88.281 +    template<class C, class R, class A0, class A1>
  88.282 +    bool PushCall(C* p, R (C::*fn)(A0, A1),
  88.283 +                  typename SelfType<A0>::Type a0, typename SelfType<A1>::Type a1, bool wait = false)
  88.284 +    { return PushCommand(ThreadCommandMF2<C,R,A0,A1>(p, fn, 0, a0, a1, wait)); }
  88.285 +    
  88.286 +    
  88.287 +    // *** PushCall with Result
  88.288 +
  88.289 +    // Enqueue a member function of 'this' class call and wait for call to complete
  88.290 +    // on consumer thread before returning.
  88.291 +    template<class C, class R>
  88.292 +    bool PushCallAndWaitResult(R (C::*fn)(), R* ret)
  88.293 +    { return PushCommand(ThreadCommandMF0<C,R>(static_cast<C*>(this), fn, ret, true)); }       
  88.294 +    template<class C, class R, class A0>
  88.295 +    bool PushCallAndWaitResult(R (C::*fn)(A0), R* ret, typename SelfType<A0>::Type a0)
  88.296 +    { return PushCommand(ThreadCommandMF1<C,R,A0>(static_cast<C*>(this), fn, ret, a0, true)); }
  88.297 +    template<class C, class R, class A0, class A1>
  88.298 +    bool PushCallAndWaitResult(R (C::*fn)(A0, A1), R* ret,
  88.299 +                               typename SelfType<A0>::Type a0, typename SelfType<A1>::Type a1)
  88.300 +    { return PushCommand(ThreadCommandMF2<C,R,A0,A1>(static_cast<C*>(this), fn, ret, a0, a1, true)); }
  88.301 +    // Enqueue a member function call for class C and wait for the call to complete
  88.302 +    // on consumer thread before returning.
  88.303 +    template<class C, class R>
  88.304 +    bool PushCallAndWaitResult(C* p, R (C::*fn)(), R* ret)
  88.305 +    { return PushCommand(ThreadCommandMF0<C,R>(p, fn, ret, true)); }
  88.306 +    template<class C, class R, class A0>
  88.307 +    bool PushCallAndWaitResult(C* p, R (C::*fn)(A0), R* ret, typename SelfType<A0>::Type a0)
  88.308 +    { return PushCommand(ThreadCommandMF1<C,R,A0>(p, fn, ret, a0, true)); }
  88.309 +    template<class C, class R, class A0, class A1>
  88.310 +    bool PushCallAndWaitResult(C* p, R (C::*fn)(A0, A1), R* ret,
  88.311 +                               typename SelfType<A0>::Type a0, typename SelfType<A1>::Type a1)
  88.312 +    { return PushCommand(ThreadCommandMF2<C,R,A0,A1>(p, fn, ret, a0, a1, true)); }
  88.313 +
  88.314 +private:
  88.315 +    class ThreadCommandQueueImpl* pImpl;
  88.316 +};
  88.317 +
  88.318 +
  88.319 +} // namespace OVR
  88.320 +
  88.321 +#endif // OVR_ThreadCommandQueue_h
    89.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    89.2 +++ b/LibOVR/Src/Kernel/OVR_Threads.h	Wed Jan 14 06:51:16 2015 +0200
    89.3 @@ -0,0 +1,434 @@
    89.4 +/************************************************************************************
    89.5 +
    89.6 +PublicHeader:   None
    89.7 +Filename    :   OVR_Threads.h
    89.8 +Content     :   Contains thread-related (safe) functionality
    89.9 +Created     :   September 19, 2012
   89.10 +Notes       : 
   89.11 +
   89.12 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   89.13 +
   89.14 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
   89.15 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
   89.16 +which is provided at the time of installation or download, or which 
   89.17 +otherwise accompanies this software in either electronic or hard copy form.
   89.18 +
   89.19 +You may obtain a copy of the License at
   89.20 +
   89.21 +http://www.oculusvr.com/licenses/LICENSE-3.2 
   89.22 +
   89.23 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
   89.24 +distributed under the License is distributed on an "AS IS" BASIS,
   89.25 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   89.26 +See the License for the specific language governing permissions and
   89.27 +limitations under the License.
   89.28 +
   89.29 +************************************************************************************/
   89.30 +#ifndef OVR_Threads_h
   89.31 +#define OVR_Threads_h
   89.32 +
   89.33 +#include "OVR_Types.h"
   89.34 +#include "OVR_Atomic.h"
   89.35 +#include "OVR_RefCount.h"
   89.36 +#include "OVR_Array.h"
   89.37 +
   89.38 +// Defines the infinite wait delay timeout
   89.39 +#define OVR_WAIT_INFINITE 0xFFFFFFFF
   89.40 +
   89.41 +// To be defined in the project configuration options
   89.42 +#ifdef OVR_ENABLE_THREADS
   89.43 +
   89.44 +
   89.45 +namespace OVR {
   89.46 +
   89.47 +//-----------------------------------------------------------------------------------
   89.48 +// ****** Declared classes
   89.49 +
   89.50 +// Declared with thread support only
   89.51 +class   Mutex;
   89.52 +class   WaitCondition;
   89.53 +class   Event;
   89.54 +// Implementation forward declarations
   89.55 +class MutexImpl;
   89.56 +class WaitConditionImpl;
   89.57 +
   89.58 +
   89.59 +
   89.60 +//-----------------------------------------------------------------------------------
   89.61 +// ***** Mutex
   89.62 +
   89.63 +// Mutex class represents a system Mutex synchronization object that provides access 
   89.64 +// serialization between different threads, allowing one thread mutually exclusive access 
   89.65 +// to a resource. Mutex is more heavy-weight then Lock, but supports WaitCondition.
   89.66 +
   89.67 +class Mutex
   89.68 +{
   89.69 +    friend class WaitConditionImpl;    
   89.70 +    friend class MutexImpl;
   89.71 +
   89.72 +    MutexImpl  *pImpl; 
   89.73 +
   89.74 +public:
   89.75 +    // Constructor/destructor
   89.76 +    Mutex(bool recursive = 1);
   89.77 +    ~Mutex();
   89.78 +
   89.79 +    // Locking functions
   89.80 +    void  DoLock();
   89.81 +    bool  TryLock();
   89.82 +    void  Unlock();
   89.83 +
   89.84 +    // Returns 1 if the mutes is currently locked by another thread
   89.85 +    // Returns 0 if the mutex is not locked by another thread, and can therefore be acquired. 
   89.86 +    bool  IsLockedByAnotherThread();
   89.87 +    
   89.88 +    // Locker class; Used for automatic locking of a mutex withing scope    
   89.89 +    class Locker
   89.90 +    {
   89.91 +    public:
   89.92 +        Mutex *pMutex;
   89.93 +        Locker(Mutex *pmutex)
   89.94 +            { pMutex = pmutex; pMutex->DoLock(); }
   89.95 +        ~Locker()
   89.96 +            { pMutex->Unlock(); }
   89.97 +    };
   89.98 +};
   89.99 +
  89.100 +
  89.101 +//-----------------------------------------------------------------------------------
  89.102 +// ***** WaitCondition
  89.103 +
  89.104 +/*
  89.105 +    WaitCondition is a synchronization primitive that can be used to implement what is known as a monitor.
  89.106 +    Dependent threads wait on a wait condition by calling Wait(), and get woken up by other threads that
  89.107 +    call Notify() or NotifyAll().
  89.108 +
  89.109 +    The unique feature of this class is that it provides an atomic way of first releasing a Mutex, and then 
  89.110 +    starting a wait on a wait condition. If both the mutex and the wait condition are associated with the same
  89.111 +    resource, this ensures that any condition checked for while the mutex was locked does not change before
  89.112 +    the wait on the condition is actually initiated.
  89.113 +*/
  89.114 +
  89.115 +class WaitCondition
  89.116 +{
  89.117 +    friend class WaitConditionImpl;
  89.118 +    // Internal implementation structure
  89.119 +    WaitConditionImpl *pImpl;
  89.120 +
  89.121 +public:
  89.122 +    // Constructor/destructor
  89.123 +    WaitCondition();
  89.124 +    ~WaitCondition();
  89.125 +
  89.126 +    // Release mutex and wait for condition. The mutex is re-aquired after the wait.
  89.127 +    // Delay is specified in milliseconds (1/1000 of a second).
  89.128 +    bool    Wait(Mutex *pmutex, unsigned delay = OVR_WAIT_INFINITE);
  89.129 +
  89.130 +    // Notify a condition, releasing at one object waiting
  89.131 +    void    Notify();
  89.132 +    // Notify a condition, releasing all objects waiting
  89.133 +    void    NotifyAll();
  89.134 +};
  89.135 +
  89.136 +
  89.137 +//-----------------------------------------------------------------------------------
  89.138 +// ***** Event
  89.139 +
  89.140 +// Event is a wait-able synchronization object similar to Windows event.
  89.141 +// Event can be waited on until it's signaled by another thread calling
  89.142 +// either SetEvent or PulseEvent.
  89.143 +
  89.144 +class Event
  89.145 +{
  89.146 +    // Event state, its mutex and the wait condition
  89.147 +    volatile bool   State;
  89.148 +    volatile bool   Temporary;  
  89.149 +    mutable Mutex   StateMutex;
  89.150 +    WaitCondition   StateWaitCondition;
  89.151 +
  89.152 +    void updateState(bool newState, bool newTemp, bool mustNotify);
  89.153 +
  89.154 +public:    
  89.155 +    Event(bool setInitially = 0) : State(setInitially), Temporary(false) { }
  89.156 +    ~Event() { }
  89.157 +
  89.158 +    // Wait on an event condition until it is set
  89.159 +    // Delay is specified in milliseconds (1/1000 of a second).
  89.160 +    bool  Wait(unsigned delay = OVR_WAIT_INFINITE);
  89.161 +    
  89.162 +    // Set an event, releasing objects waiting on it
  89.163 +    void  SetEvent()
  89.164 +    { updateState(true, false, true); }
  89.165 +
  89.166 +    // Reset an event, un-signaling it
  89.167 +    void  ResetEvent()
  89.168 +    { updateState(false, false, false); }
  89.169 +
  89.170 +    // Set and then reset an event once a waiter is released.
  89.171 +    // If threads are already waiting, they will be notified and released
  89.172 +    // If threads are not waiting, the event is set until the first thread comes in
  89.173 +    void  PulseEvent()
  89.174 +    { updateState(true, true, true); }
  89.175 +};
  89.176 +
  89.177 +
  89.178 +//-----------------------------------------------------------------------------------
  89.179 +// ***** Thread class
  89.180 +
  89.181 +// ThreadHandle is a handle to a thread, which on some platforms (e.g. Windows) is 
  89.182 +// different from ThreadId. On Unix platforms, a ThreadHandle is the same as a 
  89.183 +// ThreadId and is pthread_t.
  89.184 +typedef void* ThreadHandle;
  89.185 +
  89.186 +// ThreadId uniquely identifies a thread; returned by Windows GetCurrentThreadId(), 
  89.187 +// Unix pthread_self() and Thread::GetThreadId.
  89.188 +typedef void* ThreadId;
  89.189 +
  89.190 +
  89.191 +// *** Thread flags
  89.192 +
  89.193 +// Indicates that the thread is has been started, i.e. Start method has been called, and threads
  89.194 +// OnExit() method has not yet been called/returned.
  89.195 +#define OVR_THREAD_STARTED               0x01
  89.196 +// This flag is set once the thread has ran, and finished.
  89.197 +#define OVR_THREAD_FINISHED              0x02
  89.198 +// This flag is set temporarily if this thread was started suspended. It is used internally.
  89.199 +#define OVR_THREAD_START_SUSPENDED       0x08
  89.200 +// This flag is used to ask a thread to exit. Message driven threads will usually check this flag
  89.201 +// and finish once it is set.
  89.202 +#define OVR_THREAD_EXIT                  0x10
  89.203 +
  89.204 +
  89.205 +class Thread : public RefCountBase<Thread>
  89.206 +{ // NOTE: Waitable must be the first base since it implements RefCountImpl.    
  89.207 +public:
  89.208 +    // *** Callback functions, can be used instead of overriding Run
  89.209 +
  89.210 +    // Run function prototypes.    
  89.211 +    // Thread function and user handle passed to it, executed by the default
  89.212 +    // Thread::Run implementation if not null.
  89.213 +    typedef int (*ThreadFn)(Thread *pthread, void* h);
  89.214 +    
  89.215 +    // Thread ThreadFunction1 is executed if not 0, otherwise ThreadFunction2 is tried
  89.216 +    ThreadFn    ThreadFunction;    
  89.217 +    // User handle passes to a thread
  89.218 +    void*       UserHandle;
  89.219 +
  89.220 +    // Thread state to start a thread with
  89.221 +    enum ThreadState
  89.222 +    {
  89.223 +        NotRunning  = 0,
  89.224 +        Running     = 1,
  89.225 +        Suspended   = 2
  89.226 +    };
  89.227 +
  89.228 +    // Thread priority
  89.229 +    enum ThreadPriority
  89.230 +    {
  89.231 +        CriticalPriority,
  89.232 +        HighestPriority,
  89.233 +        AboveNormalPriority,
  89.234 +        NormalPriority,
  89.235 +        BelowNormalPriority,
  89.236 +        LowestPriority,
  89.237 +        IdlePriority,
  89.238 +    };
  89.239 +
  89.240 +    // Thread constructor parameters
  89.241 +    struct CreateParams
  89.242 +    {
  89.243 +        CreateParams(ThreadFn func = 0, void* hand = 0, size_t ssize = 128 * 1024, 
  89.244 +                     int proc = -1, ThreadState state = NotRunning, ThreadPriority prior = NormalPriority)
  89.245 +                     : threadFunction(func), userHandle(hand), stackSize(ssize), 
  89.246 +                       processor(proc), initialState(state), priority(prior) {}
  89.247 +        ThreadFn       threadFunction;   // Thread function
  89.248 +        void*          userHandle;       // User handle passes to a thread
  89.249 +        size_t         stackSize;        // Thread stack size
  89.250 +        int            processor;        // Thread hardware processor
  89.251 +        ThreadState    initialState;     // 
  89.252 +        ThreadPriority priority;         // Thread priority
  89.253 +    };
  89.254 +
  89.255 +
  89.256 +    // *** Constructors
  89.257 +
  89.258 +    // A default constructor always creates a thread in NotRunning state, because
  89.259 +    // the derived class has not yet been initialized. The derived class can call Start explicitly.
  89.260 +    // "processor" parameter specifies which hardware processor this thread will be run on. 
  89.261 +    // -1 means OS decides this. Implemented only on Win32
  89.262 +    Thread(size_t stackSize = 128 * 1024, int processor = -1);
  89.263 +    // Constructors that initialize the thread with a pointer to function.
  89.264 +    // An option to start a thread is available, but it should not be used if classes are derived from Thread.
  89.265 +    // "processor" parameter specifies which hardware processor this thread will be run on. 
  89.266 +    // -1 means OS decides this. Implemented only on Win32
  89.267 +    Thread(ThreadFn threadFunction, void*  userHandle = 0, size_t stackSize = 128 * 1024,
  89.268 +           int processor = -1, ThreadState initialState = NotRunning);
  89.269 +    // Constructors that initialize the thread with a create parameters structure.
  89.270 +    explicit Thread(const CreateParams& params);
  89.271 +
  89.272 +    // Destructor.
  89.273 +    virtual ~Thread();
  89.274 +
  89.275 +    // Waits for all Threads to finish; should be called only from the root
  89.276 +    // application thread. Once this function returns, we know that all other
  89.277 +    // thread's references to Thread object have been released.
  89.278 +    static  void OVR_CDECL FinishAllThreads();
  89.279 +
  89.280 +
  89.281 +    // *** Overridable Run function for thread processing
  89.282 +
  89.283 +    // - returning from this method will end the execution of the thread
  89.284 +    // - return value is usually 0 for success 
  89.285 +    virtual int   Run();
  89.286 +    // Called after return/exit function
  89.287 +    virtual void  OnExit();
  89.288 +
  89.289 +
  89.290 +    // *** Thread management
  89.291 +
  89.292 +    // Starts the thread if its not already running
  89.293 +    // - internally sets up the threading and calls Run()
  89.294 +    // - initial state can either be Running or Suspended, NotRunning will just fail and do nothing
  89.295 +    // - returns the exit code
  89.296 +    virtual bool  Start(ThreadState initialState = Running);
  89.297 +
  89.298 +    // Quits with an exit code
  89.299 +    virtual void  Exit(int exitCode=0);
  89.300 +
  89.301 +    // Suspend the thread until resumed
  89.302 +    // Returns 1 for success, 0 for failure.
  89.303 +    bool  Suspend();
  89.304 +    // Resumes currently suspended thread
  89.305 +    // Returns 1 for success, 0 for failure.
  89.306 +    bool  Resume();
  89.307 +
  89.308 +    // Static function to return a pointer to the current thread
  89.309 +    //static Thread* GetThread();
  89.310 +
  89.311 +
  89.312 +    // *** Thread status query functions
  89.313 +
  89.314 +    bool          GetExitFlag() const;
  89.315 +    void          SetExitFlag(bool exitFlag);
  89.316 +
  89.317 +    // Determines whether the thread was running and is now finished
  89.318 +    bool          IsFinished() const;
  89.319 +    // Determines if the thread is currently suspended
  89.320 +    bool          IsSuspended() const;
  89.321 +    // Returns current thread state
  89.322 +    ThreadState   GetThreadState() const;
  89.323 +
  89.324 +    // Wait for thread to finish for a maxmimum number of milliseconds
  89.325 +    // For maxWaitMs = 0 it simply polls and then returns if the thread is not finished
  89.326 +    // For maxWaitMs < 0 it will wait forever
  89.327 +    bool          Join(int maxWaitMs = -1) const;
  89.328 +
  89.329 +    // Returns the number of available CPUs on the system 
  89.330 +    static int    GetCPUCount();
  89.331 +
  89.332 +    // Returns the thread exit code. Exit code is initialized to 0,
  89.333 +    // and set to the return value if Run function after the thread is finished.
  89.334 +    inline int    GetExitCode() const { return ExitCode; }
  89.335 +    // Returns an OS handle 
  89.336 +#if defined(OVR_OS_MS)
  89.337 +    void*          GetOSHandle() const { return ThreadHandle; }
  89.338 +#else
  89.339 +    pthread_t      GetOSHandle() const { return ThreadHandle; }
  89.340 +#endif
  89.341 +
  89.342 +#if defined(OVR_OS_MS)
  89.343 +    ThreadId       GetThreadId() const { return IdValue; }
  89.344 +#else
  89.345 +    ThreadId       GetThreadId() const { return (ThreadId)GetOSHandle(); }
  89.346 +#endif
  89.347 +
  89.348 +    // Returns the platform-specific equivalent const that corresponds to the given ThreadPriority. 
  89.349 +    static int            GetOSPriority(ThreadPriority);
  89.350 +    static ThreadPriority GetOVRPriority(int osPriority); // May return a value outside the ThreadPriority enum range in unusual cases.
  89.351 +
  89.352 +    // Gets this instance's priority.
  89.353 +    ThreadPriority GetPriority();
  89.354 +
  89.355 +    // Gets the current thread's priority.
  89.356 +    static ThreadPriority GetCurrentPriority();
  89.357 +
  89.358 +    // Sets this instance's thread's priority.
  89.359 +    // Some platforms (e.g. Unix) don't let you set thread priorities unless you have root privileges/
  89.360 +    bool SetPriority(ThreadPriority);
  89.361 +
  89.362 +    // Sets the current thread's priority.
  89.363 +    static bool SetCurrentPriority(ThreadPriority);
  89.364 +
  89.365 +    // *** Sleep
  89.366 +
  89.367 +    // Sleep secs seconds
  89.368 +    static bool    Sleep(unsigned secs);
  89.369 +    // Sleep msecs milliseconds
  89.370 +    static bool    MSleep(unsigned msecs);
  89.371 +
  89.372 +
  89.373 +    // *** Debugging functionality
  89.374 +    virtual void    SetThreadName(const char* name);
  89.375 +    static void     SetThreadName(const char* name, ThreadId threadId);
  89.376 +    static void     SetCurrentThreadName(const char* name);
  89.377 +
  89.378 +    static void     GetThreadName(char* name, size_t nameCapacity, ThreadId threadId);
  89.379 +    static void     GetCurrentThreadName(char* name, size_t nameCapacity);
  89.380 +
  89.381 +private:
  89.382 +#if defined(OVR_OS_WIN32)
  89.383 +    friend unsigned WINAPI Thread_Win32StartFn(void *phandle);
  89.384 +#elif defined(OVR_OS_MS) // Any other Microsoft OS...
  89.385 +    friend DWORD WINAPI Thread_Win32StartFn(void *phandle);
  89.386 +#else
  89.387 +    friend void *Thread_PthreadStartFn(void * phandle);
  89.388 +
  89.389 +    static int            InitAttr;
  89.390 +    static pthread_attr_t Attr;
  89.391 +#endif
  89.392 +
  89.393 +protected:    
  89.394 +    // Thread state flags
  89.395 +    AtomicInt<uint32_t>   ThreadFlags;
  89.396 +    AtomicInt<int32_t>   SuspendCount;
  89.397 +    size_t              StackSize;
  89.398 +
  89.399 +    // Hardware processor which this thread is running on.
  89.400 +    int            Processor;
  89.401 +    ThreadPriority Priority;
  89.402 +
  89.403 +#if defined(OVR_OS_MS)
  89.404 +    void*               ThreadHandle;
  89.405 +    volatile ThreadId   IdValue;
  89.406 +
  89.407 +    // System-specific cleanup function called from destructor
  89.408 +    void                CleanupSystemThread();
  89.409 +
  89.410 +#else
  89.411 +    pthread_t           ThreadHandle;
  89.412 +#endif
  89.413 +
  89.414 +    // Exit code of the thread, as returned by Run.
  89.415 +    int                 ExitCode;
  89.416 +
  89.417 +    // Internal run function.
  89.418 +    int                 PRun();    
  89.419 +    // Finishes the thread and releases internal reference to it.
  89.420 +    void                FinishAndRelease();
  89.421 +
  89.422 +    void                Init(const CreateParams& params);
  89.423 +
  89.424 +    // Protected copy constructor
  89.425 +    Thread(const Thread &source) : RefCountBase<Thread>() { OVR_UNUSED(source); }
  89.426 +
  89.427 +};
  89.428 +
  89.429 +// Returns the unique Id of a thread it is called on, intended for
  89.430 +// comparison purposes.
  89.431 +ThreadId GetCurrentThreadId();
  89.432 +
  89.433 +
  89.434 +} // OVR
  89.435 +
  89.436 +#endif // OVR_ENABLE_THREADS
  89.437 +#endif // OVR_Threads_h
    90.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    90.2 +++ b/LibOVR/Src/Kernel/OVR_ThreadsPthread.cpp	Wed Jan 14 06:51:16 2015 +0200
    90.3 @@ -0,0 +1,984 @@
    90.4 +/************************************************************************************
    90.5 +
    90.6 +Filename    :   OVR_ThreadsPthread.cpp
    90.7 +Content     :   
    90.8 +Created     :   
    90.9 +Notes       : 
   90.10 +
   90.11 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   90.12 +
   90.13 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
   90.14 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
   90.15 +which is provided at the time of installation or download, or which 
   90.16 +otherwise accompanies this software in either electronic or hard copy form.
   90.17 +
   90.18 +You may obtain a copy of the License at
   90.19 +
   90.20 +http://www.oculusvr.com/licenses/LICENSE-3.2 
   90.21 +
   90.22 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
   90.23 +distributed under the License is distributed on an "AS IS" BASIS,
   90.24 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   90.25 +See the License for the specific language governing permissions and
   90.26 +limitations under the License.
   90.27 +
   90.28 +************************************************************************************/
   90.29 +
   90.30 +#include "OVR_Threads.h"
   90.31 +#include "OVR_Hash.h"
   90.32 +
   90.33 +#ifdef OVR_ENABLE_THREADS
   90.34 +
   90.35 +#include "OVR_Timer.h"
   90.36 +#include "OVR_Log.h"
   90.37 +
   90.38 +#include <pthread.h>
   90.39 +#include <sched.h>
   90.40 +#include <time.h>
   90.41 +#include <unistd.h>
   90.42 +#include <sys/time.h>
   90.43 +#include <errno.h>
   90.44 +
   90.45 +#if defined(OVR_OS_MAC) || defined(OVR_OS_BSD)
   90.46 +    #include <sys/sysctl.h>
   90.47 +    #include <sys/param.h>
   90.48 +    #if !defined(OVR_OS_MAC)
   90.49 +        #include <pthread_np.h>
   90.50 +    #endif
   90.51 +#endif
   90.52 +    
   90.53 +
   90.54 +
   90.55 +namespace OVR {
   90.56 +
   90.57 +// ***** Mutex implementation
   90.58 +
   90.59 +
   90.60 +// *** Internal Mutex implementation structure
   90.61 +
   90.62 +class MutexImpl : public NewOverrideBase
   90.63 +{
   90.64 +    // System mutex or semaphore
   90.65 +    pthread_mutex_t   SMutex;
   90.66 +    bool          Recursive;
   90.67 +    unsigned      LockCount;
   90.68 +    pthread_t     LockedBy;
   90.69 +
   90.70 +    friend class WaitConditionImpl;
   90.71 +
   90.72 +public:
   90.73 +    // Constructor/destructor
   90.74 +    MutexImpl(Mutex* pmutex, bool recursive = 1);
   90.75 +    ~MutexImpl();
   90.76 +
   90.77 +    // Locking functions
   90.78 +    void                DoLock();
   90.79 +    bool                TryLock();
   90.80 +    void                Unlock(Mutex* pmutex);
   90.81 +    // Returns 1 if the mutes is currently locked
   90.82 +    bool                IsLockedByAnotherThread(Mutex* pmutex);        
   90.83 +    bool                IsSignaled() const;
   90.84 +};
   90.85 +
   90.86 +pthread_mutexattr_t Lock::RecursiveAttr;
   90.87 +bool Lock::RecursiveAttrInit = 0;
   90.88 +
   90.89 +// *** Constructor/destructor
   90.90 +MutexImpl::MutexImpl(Mutex* pmutex, bool recursive)
   90.91 +{   
   90.92 +    OVR_UNUSED(pmutex);
   90.93 +    Recursive           = recursive;
   90.94 +    LockCount           = 0;
   90.95 +
   90.96 +    if (Recursive)
   90.97 +    {
   90.98 +        if (!Lock::RecursiveAttrInit)
   90.99 +        {
  90.100 +            pthread_mutexattr_init(&Lock::RecursiveAttr);
  90.101 +            pthread_mutexattr_settype(&Lock::RecursiveAttr, PTHREAD_MUTEX_RECURSIVE);
  90.102 +            Lock::RecursiveAttrInit = 1;
  90.103 +        }
  90.104 +
  90.105 +        pthread_mutex_init(&SMutex, &Lock::RecursiveAttr);
  90.106 +    }
  90.107 +    else
  90.108 +        pthread_mutex_init(&SMutex, 0);
  90.109 +}
  90.110 +
  90.111 +MutexImpl::~MutexImpl()
  90.112 +{
  90.113 +    pthread_mutex_destroy(&SMutex);
  90.114 +}
  90.115 +
  90.116 +
  90.117 +// Lock and try lock
  90.118 +void MutexImpl::DoLock()
  90.119 +{
  90.120 +    while (pthread_mutex_lock(&SMutex))
  90.121 +        ;
  90.122 +    LockCount++;
  90.123 +    LockedBy = pthread_self();
  90.124 +}
  90.125 +
  90.126 +bool MutexImpl::TryLock()
  90.127 +{
  90.128 +    if (!pthread_mutex_trylock(&SMutex))
  90.129 +    {
  90.130 +        LockCount++;
  90.131 +        LockedBy = pthread_self();
  90.132 +        return 1;
  90.133 +    }
  90.134 +    
  90.135 +    return 0;
  90.136 +}
  90.137 +
  90.138 +void MutexImpl::Unlock(Mutex* pmutex)
  90.139 +{
  90.140 +    OVR_UNUSED(pmutex);
  90.141 +    OVR_ASSERT(pthread_self() == LockedBy && LockCount > 0);
  90.142 +
  90.143 +    //unsigned lockCount;
  90.144 +    LockCount--;
  90.145 +    //lockCount = LockCount;
  90.146 +
  90.147 +    pthread_mutex_unlock(&SMutex);
  90.148 +}
  90.149 +
  90.150 +bool    MutexImpl::IsLockedByAnotherThread(Mutex* pmutex)
  90.151 +{
  90.152 +    OVR_UNUSED(pmutex);
  90.153 +    // There could be multiple interpretations of IsLocked with respect to current thread
  90.154 +    if (LockCount == 0)
  90.155 +        return 0;
  90.156 +    if (pthread_self() != LockedBy)
  90.157 +        return 1;
  90.158 +    return 0;
  90.159 +}
  90.160 +
  90.161 +bool    MutexImpl::IsSignaled() const
  90.162 +{
  90.163 +    // An mutex is signaled if it is not locked ANYWHERE
  90.164 +    // Note that this is different from IsLockedByAnotherThread function,
  90.165 +    // that takes current thread into account
  90.166 +    return LockCount == 0;
  90.167 +}
  90.168 +
  90.169 +
  90.170 +// *** Actual Mutex class implementation
  90.171 +
  90.172 +Mutex::Mutex(bool recursive)
  90.173 +{
  90.174 +    // NOTE: RefCount mode already thread-safe for all waitables.
  90.175 +    pImpl = new MutexImpl(this, recursive);
  90.176 +}
  90.177 +
  90.178 +Mutex::~Mutex()
  90.179 +{
  90.180 +    delete pImpl;
  90.181 +}
  90.182 +
  90.183 +// Lock and try lock
  90.184 +void Mutex::DoLock()
  90.185 +{
  90.186 +    pImpl->DoLock();
  90.187 +}
  90.188 +bool Mutex::TryLock()
  90.189 +{
  90.190 +    return pImpl->TryLock();
  90.191 +}
  90.192 +void Mutex::Unlock()
  90.193 +{
  90.194 +    pImpl->Unlock(this);
  90.195 +}
  90.196 +bool    Mutex::IsLockedByAnotherThread()
  90.197 +{
  90.198 +    return pImpl->IsLockedByAnotherThread(this);
  90.199 +}
  90.200 +
  90.201 +
  90.202 +
  90.203 +//-----------------------------------------------------------------------------------
  90.204 +// ***** Event
  90.205 +
  90.206 +bool Event::Wait(unsigned delay)
  90.207 +{
  90.208 +    Mutex::Locker lock(&StateMutex);
  90.209 +
  90.210 +    // Do the correct amount of waiting
  90.211 +    if (delay == OVR_WAIT_INFINITE)
  90.212 +    {
  90.213 +        while(!State)
  90.214 +            StateWaitCondition.Wait(&StateMutex);
  90.215 +    }
  90.216 +    else if (delay)
  90.217 +    {
  90.218 +        if (!State)
  90.219 +            StateWaitCondition.Wait(&StateMutex, delay);
  90.220 +    }
  90.221 +
  90.222 +    bool state = State;
  90.223 +    // Take care of temporary 'pulsing' of a state
  90.224 +    if (Temporary)
  90.225 +    {
  90.226 +        Temporary   = false;
  90.227 +        State       = false;
  90.228 +    }
  90.229 +    return state;
  90.230 +}
  90.231 +
  90.232 +void Event::updateState(bool newState, bool newTemp, bool mustNotify)
  90.233 +{
  90.234 +    Mutex::Locker lock(&StateMutex);
  90.235 +    State       = newState;
  90.236 +    Temporary   = newTemp;
  90.237 +    if (mustNotify)
  90.238 +        StateWaitCondition.NotifyAll();    
  90.239 +}
  90.240 +
  90.241 +
  90.242 +
  90.243 +// ***** Wait Condition Implementation
  90.244 +
  90.245 +// Internal implementation class
  90.246 +class WaitConditionImpl : public NewOverrideBase
  90.247 +{
  90.248 +    pthread_mutex_t     SMutex;
  90.249 +    pthread_cond_t      Condv;
  90.250 +
  90.251 +public:
  90.252 +
  90.253 +    // Constructor/destructor
  90.254 +    WaitConditionImpl();
  90.255 +    ~WaitConditionImpl();
  90.256 +
  90.257 +    // Release mutex and wait for condition. The mutex is re-aqured after the wait.
  90.258 +    bool    Wait(Mutex *pmutex, unsigned delay = OVR_WAIT_INFINITE);
  90.259 +
  90.260 +    // Notify a condition, releasing at one object waiting
  90.261 +    void    Notify();
  90.262 +    // Notify a condition, releasing all objects waiting
  90.263 +    void    NotifyAll();
  90.264 +};
  90.265 +
  90.266 +
  90.267 +WaitConditionImpl::WaitConditionImpl()
  90.268 +{
  90.269 +    pthread_mutex_init(&SMutex, 0);
  90.270 +    pthread_cond_init(&Condv, 0);
  90.271 +}
  90.272 +
  90.273 +WaitConditionImpl::~WaitConditionImpl()
  90.274 +{
  90.275 +    pthread_mutex_destroy(&SMutex);
  90.276 +    pthread_cond_destroy(&Condv);
  90.277 +}    
  90.278 +
  90.279 +bool    WaitConditionImpl::Wait(Mutex *pmutex, unsigned delay)
  90.280 +{
  90.281 +    bool            result = 1;
  90.282 +    unsigned            lockCount = pmutex->pImpl->LockCount;
  90.283 +
  90.284 +    // Mutex must have been locked
  90.285 +    if (lockCount == 0)
  90.286 +        return 0;
  90.287 +
  90.288 +    pthread_mutex_lock(&SMutex);
  90.289 +
  90.290 +    // Finally, release a mutex or semaphore
  90.291 +    if (pmutex->pImpl->Recursive)
  90.292 +    {
  90.293 +        // Release the recursive mutex N times
  90.294 +        pmutex->pImpl->LockCount = 0;
  90.295 +        for(unsigned i=0; i<lockCount; i++)
  90.296 +            pthread_mutex_unlock(&pmutex->pImpl->SMutex);
  90.297 +    }
  90.298 +    else
  90.299 +    {
  90.300 +        pmutex->pImpl->LockCount = 0;
  90.301 +        pthread_mutex_unlock(&pmutex->pImpl->SMutex);
  90.302 +    }
  90.303 +
  90.304 +    // Note that there is a gap here between mutex.Unlock() and Wait().
  90.305 +    // The other mutex protects this gap.
  90.306 +
  90.307 +    if (delay == OVR_WAIT_INFINITE)
  90.308 +        pthread_cond_wait(&Condv,&SMutex);
  90.309 +    else
  90.310 +    {
  90.311 +        timespec ts;
  90.312 +
  90.313 +        struct timeval tv;
  90.314 +        gettimeofday(&tv, 0);
  90.315 +
  90.316 +        ts.tv_sec = tv.tv_sec + (delay / 1000);
  90.317 +        ts.tv_nsec = (tv.tv_usec + (delay % 1000) * 1000) * 1000;
  90.318 +
  90.319 +        if (ts.tv_nsec > 999999999)
  90.320 +        {
  90.321 +            ts.tv_sec++;
  90.322 +            ts.tv_nsec -= 1000000000;
  90.323 +        }
  90.324 +        int r = pthread_cond_timedwait(&Condv,&SMutex, &ts);
  90.325 +        OVR_ASSERT(r == 0 || r == ETIMEDOUT);
  90.326 +        if (r)
  90.327 +            result = 0;
  90.328 +    }
  90.329 +
  90.330 +    pthread_mutex_unlock(&SMutex);
  90.331 +
  90.332 +    // Re-aquire the mutex
  90.333 +    for(unsigned i=0; i<lockCount; i++)
  90.334 +        pmutex->DoLock(); 
  90.335 +
  90.336 +    // Return the result
  90.337 +    return result;
  90.338 +}
  90.339 +
  90.340 +// Notify a condition, releasing the least object in a queue
  90.341 +void    WaitConditionImpl::Notify()
  90.342 +{
  90.343 +    pthread_mutex_lock(&SMutex);
  90.344 +    pthread_cond_signal(&Condv);
  90.345 +    pthread_mutex_unlock(&SMutex);
  90.346 +}
  90.347 +
  90.348 +// Notify a condition, releasing all objects waiting
  90.349 +void    WaitConditionImpl::NotifyAll()
  90.350 +{
  90.351 +    pthread_mutex_lock(&SMutex);
  90.352 +    pthread_cond_broadcast(&Condv);
  90.353 +    pthread_mutex_unlock(&SMutex);
  90.354 +}
  90.355 +
  90.356 +
  90.357 +
  90.358 +// *** Actual implementation of WaitCondition
  90.359 +
  90.360 +WaitCondition::WaitCondition()
  90.361 +{
  90.362 +    pImpl = new WaitConditionImpl;
  90.363 +}
  90.364 +WaitCondition::~WaitCondition()
  90.365 +{
  90.366 +    delete pImpl;
  90.367 +}
  90.368 +    
  90.369 +bool    WaitCondition::Wait(Mutex *pmutex, unsigned delay)
  90.370 +{
  90.371 +    return pImpl->Wait(pmutex, delay);
  90.372 +}
  90.373 +// Notification
  90.374 +void    WaitCondition::Notify()
  90.375 +{
  90.376 +    pImpl->Notify();
  90.377 +}
  90.378 +void    WaitCondition::NotifyAll()
  90.379 +{
  90.380 +    pImpl->NotifyAll();
  90.381 +}
  90.382 +
  90.383 +
  90.384 +// ***** Current thread
  90.385 +
  90.386 +// Per-thread variable
  90.387 +/*
  90.388 +static __thread Thread* pCurrentThread = 0;
  90.389 +
  90.390 +// Static function to return a pointer to the current thread
  90.391 +void    Thread::InitCurrentThread(Thread *pthread)
  90.392 +{
  90.393 +    pCurrentThread = pthread;
  90.394 +}
  90.395 +
  90.396 +// Static function to return a pointer to the current thread
  90.397 +Thread*    Thread::GetThread()
  90.398 +{
  90.399 +    return pCurrentThread;
  90.400 +}
  90.401 +*/
  90.402 +
  90.403 +
  90.404 +// *** Thread constructors.
  90.405 +
  90.406 +Thread::Thread(UPInt stackSize, int processor)
  90.407 +{
  90.408 +    // NOTE: RefCount mode already thread-safe for all Waitable objects.
  90.409 +    CreateParams params;
  90.410 +    params.stackSize = stackSize;
  90.411 +    params.processor = processor;
  90.412 +    Init(params);
  90.413 +}
  90.414 +
  90.415 +Thread::Thread(Thread::ThreadFn threadFunction, void*  userHandle, UPInt stackSize,
  90.416 +                 int processor, Thread::ThreadState initialState)
  90.417 +{
  90.418 +    CreateParams params(threadFunction, userHandle, stackSize, processor, initialState);
  90.419 +    Init(params);
  90.420 +}
  90.421 +
  90.422 +Thread::Thread(const CreateParams& params)
  90.423 +{
  90.424 +    Init(params);
  90.425 +}
  90.426 +
  90.427 +void Thread::Init(const CreateParams& params)
  90.428 +{
  90.429 +    // Clear the variables    
  90.430 +    ThreadFlags     = 0;
  90.431 +    ThreadHandle    = 0;
  90.432 +    ExitCode        = 0;
  90.433 +    SuspendCount    = 0;
  90.434 +    StackSize       = params.stackSize;
  90.435 +    Processor       = params.processor;
  90.436 +    Priority        = params.priority;
  90.437 +
  90.438 +    // Clear Function pointers
  90.439 +    ThreadFunction  = params.threadFunction;
  90.440 +    UserHandle      = params.userHandle;
  90.441 +    if (params.initialState != NotRunning)
  90.442 +        Start(params.initialState);
  90.443 +}
  90.444 +
  90.445 +Thread::~Thread()
  90.446 +{
  90.447 +    // Thread should not running while object is being destroyed,
  90.448 +    // this would indicate ref-counting issue.
  90.449 +    //OVR_ASSERT(IsRunning() == 0);
  90.450 +
  90.451 +    // Clean up thread.    
  90.452 +    ThreadHandle = 0;
  90.453 +}
  90.454 +
  90.455 +
  90.456 +
  90.457 +// *** Overridable User functions.
  90.458 +
  90.459 +// Default Run implementation
  90.460 +int    Thread::Run()
  90.461 +{
  90.462 +    // Call pointer to function, if available.    
  90.463 +    return (ThreadFunction) ? ThreadFunction(this, UserHandle) : 0;
  90.464 +}
  90.465 +void    Thread::OnExit()
  90.466 +{   
  90.467 +}
  90.468 +
  90.469 +
  90.470 +// Finishes the thread and releases internal reference to it.
  90.471 +void    Thread::FinishAndRelease()
  90.472 +{
  90.473 +    // Note: thread must be US.
  90.474 +    ThreadFlags &= (UInt32)~(OVR_THREAD_STARTED);
  90.475 +    ThreadFlags |= OVR_THREAD_FINISHED;
  90.476 +
  90.477 +    // Release our reference; this is equivalent to 'delete this'
  90.478 +    // from the point of view of our thread.
  90.479 +    Release();
  90.480 +}
  90.481 +
  90.482 +
  90.483 +
  90.484 +// *** ThreadList - used to track all created threads
  90.485 +
  90.486 +class ThreadList : public NewOverrideBase
  90.487 +{
  90.488 +    //------------------------------------------------------------------------
  90.489 +    struct ThreadHashOp
  90.490 +    {
  90.491 +        size_t operator()(const Thread* ptr)
  90.492 +        {
  90.493 +            return (((size_t)ptr) >> 6) ^ (size_t)ptr;
  90.494 +        }
  90.495 +    };
  90.496 +
  90.497 +    HashSet<Thread*, ThreadHashOp>        ThreadSet;
  90.498 +    Mutex                                 ThreadMutex;
  90.499 +    WaitCondition                         ThreadsEmpty;
  90.500 +    // Track the root thread that created us.
  90.501 +    pthread_t                             RootThreadId;
  90.502 +
  90.503 +    static ThreadList* volatile pRunningThreads;
  90.504 +
  90.505 +    void addThread(Thread *pthread)
  90.506 +    {
  90.507 +        Mutex::Locker lock(&ThreadMutex);
  90.508 +        ThreadSet.Add(pthread);
  90.509 +    }
  90.510 +
  90.511 +    void removeThread(Thread *pthread)
  90.512 +    {
  90.513 +        Mutex::Locker lock(&ThreadMutex);
  90.514 +        ThreadSet.Remove(pthread);
  90.515 +        if (ThreadSet.GetSize() == 0)
  90.516 +            ThreadsEmpty.Notify();
  90.517 +    }
  90.518 +
  90.519 +    void finishAllThreads()
  90.520 +    {
  90.521 +        // Only original root thread can call this.
  90.522 +        OVR_ASSERT(pthread_self() == RootThreadId);
  90.523 +
  90.524 +        Mutex::Locker lock(&ThreadMutex);
  90.525 +        while (ThreadSet.GetSize() != 0)
  90.526 +            ThreadsEmpty.Wait(&ThreadMutex);
  90.527 +    }
  90.528 +
  90.529 +public:
  90.530 +
  90.531 +    ThreadList()
  90.532 +    {
  90.533 +        RootThreadId = pthread_self();
  90.534 +    }
  90.535 +    ~ThreadList() { }
  90.536 +
  90.537 +
  90.538 +    static void AddRunningThread(Thread *pthread)
  90.539 +    {
  90.540 +        // Non-atomic creation ok since only the root thread
  90.541 +        if (!pRunningThreads)
  90.542 +        {
  90.543 +            pRunningThreads = new ThreadList;
  90.544 +            OVR_ASSERT(pRunningThreads);
  90.545 +        }
  90.546 +        pRunningThreads->addThread(pthread);
  90.547 +    }
  90.548 +
  90.549 +    // NOTE: 'pthread' might be a dead pointer when this is
  90.550 +    // called so it should not be accessed; it is only used
  90.551 +    // for removal.
  90.552 +    static void RemoveRunningThread(Thread *pthread)
  90.553 +    {
  90.554 +        OVR_ASSERT(pRunningThreads);        
  90.555 +        pRunningThreads->removeThread(pthread);
  90.556 +    }
  90.557 +
  90.558 +    static void FinishAllThreads()
  90.559 +    {
  90.560 +        // This is ok because only root thread can wait for other thread finish.
  90.561 +        if (pRunningThreads)
  90.562 +        {           
  90.563 +            pRunningThreads->finishAllThreads();
  90.564 +            delete pRunningThreads;
  90.565 +            pRunningThreads = 0;
  90.566 +        }        
  90.567 +    }
  90.568 +};
  90.569 +
  90.570 +// By default, we have no thread list.
  90.571 +ThreadList* volatile ThreadList::pRunningThreads = 0;
  90.572 +
  90.573 +
  90.574 +// FinishAllThreads - exposed publicly in Thread.
  90.575 +void Thread::FinishAllThreads()
  90.576 +{
  90.577 +    ThreadList::FinishAllThreads();
  90.578 +}
  90.579 +
  90.580 +// *** Run override
  90.581 +
  90.582 +int    Thread::PRun()
  90.583 +{
  90.584 +    // Suspend us on start, if requested
  90.585 +    if (ThreadFlags & OVR_THREAD_START_SUSPENDED)
  90.586 +    {
  90.587 +        Suspend();
  90.588 +        ThreadFlags &= (UInt32)~OVR_THREAD_START_SUSPENDED;
  90.589 +    }
  90.590 +
  90.591 +    // Call the virtual run function
  90.592 +    ExitCode = Run();    
  90.593 +    return ExitCode;
  90.594 +}
  90.595 +
  90.596 +
  90.597 +
  90.598 +
  90.599 +// *** User overridables
  90.600 +
  90.601 +bool    Thread::GetExitFlag() const
  90.602 +{
  90.603 +    return (ThreadFlags & OVR_THREAD_EXIT) != 0;
  90.604 +}       
  90.605 +
  90.606 +void    Thread::SetExitFlag(bool exitFlag)
  90.607 +{
  90.608 +    // The below is atomic since ThreadFlags is AtomicInt.
  90.609 +    if (exitFlag)
  90.610 +        ThreadFlags |= OVR_THREAD_EXIT;
  90.611 +    else
  90.612 +        ThreadFlags &= (UInt32) ~OVR_THREAD_EXIT;
  90.613 +}
  90.614 +
  90.615 +
  90.616 +// Determines whether the thread was running and is now finished
  90.617 +bool    Thread::IsFinished() const
  90.618 +{
  90.619 +    return (ThreadFlags & OVR_THREAD_FINISHED) != 0;
  90.620 +}
  90.621 +// Determines whether the thread is suspended
  90.622 +bool    Thread::IsSuspended() const
  90.623 +{   
  90.624 +    return SuspendCount > 0;
  90.625 +}
  90.626 +// Returns current thread state
  90.627 +Thread::ThreadState Thread::GetThreadState() const
  90.628 +{
  90.629 +    if (IsSuspended())
  90.630 +        return Suspended;    
  90.631 +    if (ThreadFlags & OVR_THREAD_STARTED)
  90.632 +        return Running;    
  90.633 +    return NotRunning;
  90.634 +}
  90.635 +
  90.636 +// Join thread
  90.637 +bool Thread::Join(int maxWaitMs) const
  90.638 +{
  90.639 +    // If polling,
  90.640 +    if (maxWaitMs == 0)
  90.641 +    {
  90.642 +        // Just return if finished
  90.643 +        return IsFinished();
  90.644 +    }
  90.645 +    // If waiting forever,
  90.646 +    else if (maxWaitMs > 0)
  90.647 +    {
  90.648 +        UInt32 t0 = Timer::GetTicksMs();
  90.649 +
  90.650 +        while (!IsFinished())
  90.651 +        {
  90.652 +            UInt32 t1 = Timer::GetTicksMs();
  90.653 +
  90.654 +            // If the wait has expired,
  90.655 +            int delta = (int)(t1 - t0);
  90.656 +            if (delta >= maxWaitMs)
  90.657 +            {
  90.658 +                return false;
  90.659 +            }
  90.660 +
  90.661 +            Thread::MSleep(10);
  90.662 +        }
  90.663 +
  90.664 +        return true;
  90.665 +    }
  90.666 +    else
  90.667 +    {
  90.668 +        while (!IsFinished())
  90.669 +        {
  90.670 +            pthread_join(ThreadHandle, NULL);
  90.671 +        }
  90.672 +    }
  90.673 +
  90.674 +    return true;
  90.675 +}
  90.676 +
  90.677 +/*
  90.678 +static const char* mapsched_policy(int policy)
  90.679 +{
  90.680 +    switch(policy)
  90.681 +    {
  90.682 +    case SCHED_OTHER:
  90.683 +        return "SCHED_OTHER";
  90.684 +    case SCHED_RR:
  90.685 +        return "SCHED_RR";
  90.686 +    case SCHED_FIFO:
  90.687 +        return "SCHED_FIFO";
  90.688 +
  90.689 +    }
  90.690 +    return "UNKNOWN";
  90.691 +}
  90.692 +    int policy;
  90.693 +    sched_param sparam;
  90.694 +    pthread_getschedparam(pthread_self(), &policy, &sparam);
  90.695 +    int max_prior = sched_get_priority_max(policy);
  90.696 +    int min_prior = sched_get_priority_min(policy);
  90.697 +    printf(" !!!! policy: %s, priority: %d, max priority: %d, min priority: %d\n", mapsched_policy(policy), sparam.sched_priority, max_prior, min_prior);
  90.698 +#include <stdio.h>
  90.699 +*/
  90.700 +// ***** Thread management
  90.701 +
  90.702 +// The actual first function called on thread start
  90.703 +void* Thread_PthreadStartFn(void* phandle)
  90.704 +{
  90.705 +    Thread* pthread = (Thread*)phandle;
  90.706 +    int     result = pthread->PRun();
  90.707 +    // Signal the thread as done and release it atomically.
  90.708 +    pthread->FinishAndRelease();
  90.709 +    // At this point Thread object might be dead; however we can still pass
  90.710 +    // it to RemoveRunningThread since it is only used as a key there.   
  90.711 +    ThreadList::RemoveRunningThread(pthread);
  90.712 +    return reinterpret_cast<void*>(result);
  90.713 +}
  90.714 +
  90.715 +int Thread::InitAttr = 0;
  90.716 +pthread_attr_t Thread::Attr; 
  90.717 +
  90.718 +/* static */
  90.719 +int Thread::GetOSPriority(ThreadPriority p)
  90.720 +{
  90.721 +    OVR_UNUSED(p);
  90.722 +    return -1;
  90.723 +}
  90.724 +
  90.725 +/* static */
  90.726 +Thread::ThreadPriority Thread::GetOVRPriority(int osPriority)
  90.727 +{
  90.728 +    #if defined(OVR_OS_LINUX)
  90.729 +        return (ThreadPriority)(Thread::NormalPriority - osPriority); // This works for both SCHED_OTHER, SCHED_RR, and SCHED_FIFO.
  90.730 +    #else
  90.731 +        // Apple priorities are such that the min is a value less than the max.
  90.732 +        static int minPriority = sched_get_priority_min(SCHED_FIFO); // We don't have a means to pass a policy type to this function.
  90.733 +        static int maxPriority = sched_get_priority_max(SCHED_FIFO);
  90.734 +
  90.735 +        return (ThreadPriority)(Thread::NormalPriority - (osPriority - ((minPriority + maxPriority) / 2)));
  90.736 +    #endif
  90.737 +}
  90.738 +
  90.739 +
  90.740 +Thread::ThreadPriority Thread::GetPriority()
  90.741 +{
  90.742 +    int         policy;
  90.743 +    sched_param param;
  90.744 +
  90.745 +    int result = pthread_getschedparam(ThreadHandle, &policy, &param);
  90.746 +
  90.747 +    if(result == 0)
  90.748 +    {
  90.749 +        #if !defined(OVR_OS_LINUX)
  90.750 +            if(policy == SCHED_OTHER)
  90.751 +            {
  90.752 +                return Thread::NormalPriority; //SCHED_OTHER allows only normal priority on BSD-style Unix and Mac OS X.
  90.753 +            }
  90.754 +        #endif
  90.755 +
  90.756 +        return GetOVRPriority(param.sched_priority);
  90.757 +    }
  90.758 +
  90.759 +    return Thread::NormalPriority;
  90.760 +}
  90.761 +
  90.762 +/* static */
  90.763 +Thread::ThreadPriority Thread::GetCurrentPriority()
  90.764 +{
  90.765 +    int         policy;
  90.766 +    sched_param param;
  90.767 +    pthread_t   currentThreadId = pthread_self();
  90.768 +
  90.769 +    int result = pthread_getschedparam(currentThreadId, &policy, &param);
  90.770 +
  90.771 +    if(result == 0)
  90.772 +    {
  90.773 +        #if !defined(OVR_OS_LINUX)
  90.774 +            if(policy == SCHED_OTHER)
  90.775 +            {
  90.776 +                return Thread::NormalPriority; //SCHED_OTHER allows only normal priority on BSD-style Unix and Mac OS X.
  90.777 +            }
  90.778 +        #endif
  90.779 +
  90.780 +        return GetOVRPriority(param.sched_priority);
  90.781 +    }
  90.782 +
  90.783 +    return Thread::NormalPriority;
  90.784 +}
  90.785 +
  90.786 +
  90.787 +bool Thread::SetPriority(ThreadPriority)
  90.788 +{
  90.789 +    // We currently fail. To do: add code to support this via pthread_getschedparam/pthread_attr_setschedparam
  90.790 +    // This won't work unless using SCHED_FIFO or SCHED_RR anyway, which require root privileges.
  90.791 +    return false;
  90.792 +}
  90.793 +
  90.794 +/* static */
  90.795 +bool Thread::SetCurrentPriority(ThreadPriority)
  90.796 +{
  90.797 +    // We currently fail. To do: add code to support this via pthread_getschedparam/pthread_attr_setschedparam
  90.798 +    // This won't work unless using SCHED_FIFO or SCHED_RR anyway, which require root privileges.
  90.799 +    return false;
  90.800 +}
  90.801 +
  90.802 +bool    Thread::Start(ThreadState initialState)
  90.803 +{
  90.804 +    if (initialState == NotRunning)
  90.805 +        return 0;
  90.806 +    if (GetThreadState() != NotRunning)
  90.807 +    {
  90.808 +        OVR_DEBUG_LOG(("Thread::Start failed - thread %p already running", this));
  90.809 +        return 0;
  90.810 +    }
  90.811 +
  90.812 +    if (!InitAttr)
  90.813 +    {
  90.814 +        pthread_attr_init(&Attr);
  90.815 +        pthread_attr_setdetachstate(&Attr, PTHREAD_CREATE_DETACHED);
  90.816 +        pthread_attr_setstacksize(&Attr, 128 * 1024);
  90.817 +        sched_param sparam;
  90.818 +        sparam.sched_priority = Thread::GetOSPriority(NormalPriority);
  90.819 +        pthread_attr_setschedparam(&Attr, &sparam);
  90.820 +        InitAttr = 1;
  90.821 +    }
  90.822 +
  90.823 +    ExitCode        = 0;
  90.824 +    SuspendCount    = 0;
  90.825 +    ThreadFlags     = (initialState == Running) ? 0 : OVR_THREAD_START_SUSPENDED;
  90.826 +
  90.827 +    // AddRef to us until the thread is finished
  90.828 +    AddRef();
  90.829 +    ThreadList::AddRunningThread(this);
  90.830 +
  90.831 +    int result;
  90.832 +    if (StackSize != 128 * 1024 || Priority != NormalPriority)
  90.833 +    {
  90.834 +        pthread_attr_t attr;
  90.835 +
  90.836 +        pthread_attr_init(&attr);
  90.837 +        pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
  90.838 +        pthread_attr_setstacksize(&attr, StackSize);
  90.839 +        sched_param sparam;
  90.840 +        sparam.sched_priority = Thread::GetOSPriority(Priority);
  90.841 +        pthread_attr_setschedparam(&attr, &sparam);
  90.842 +        result = pthread_create(&ThreadHandle, &attr, Thread_PthreadStartFn, this);
  90.843 +        pthread_attr_destroy(&attr);
  90.844 +    }
  90.845 +    else
  90.846 +        result = pthread_create(&ThreadHandle, &Attr, Thread_PthreadStartFn, this);
  90.847 +
  90.848 +    if (result)
  90.849 +    {
  90.850 +        ThreadFlags = 0;
  90.851 +        Release();
  90.852 +        ThreadList::RemoveRunningThread(this);
  90.853 +        return 0;
  90.854 +    }
  90.855 +    return 1;
  90.856 +}
  90.857 +
  90.858 +
  90.859 +// Suspend the thread until resumed
  90.860 +bool    Thread::Suspend()
  90.861 +{
  90.862 +    OVR_DEBUG_LOG(("Thread::Suspend - cannot suspend threads on this system"));
  90.863 +    return 0;
  90.864 +}
  90.865 +
  90.866 +// Resumes currently suspended thread
  90.867 +bool    Thread::Resume()
  90.868 +{
  90.869 +    return 0;
  90.870 +}
  90.871 +
  90.872 +
  90.873 +// Quits with an exit code  
  90.874 +void    Thread::Exit(int exitCode)
  90.875 +{
  90.876 +    // Can only exist the current thread
  90.877 +   // if (GetThread() != this)
  90.878 +   //     return;
  90.879 +
  90.880 +    // Call the virtual OnExit function
  90.881 +    OnExit();   
  90.882 +
  90.883 +    // Signal this thread object as done and release it's references.
  90.884 +    FinishAndRelease();
  90.885 +    ThreadList::RemoveRunningThread(this);
  90.886 +
  90.887 +    pthread_exit(reinterpret_cast<void*>(exitCode));
  90.888 +}
  90.889 +
  90.890 +ThreadId GetCurrentThreadId()
  90.891 +{
  90.892 +    return (void*)pthread_self();
  90.893 +}
  90.894 +
  90.895 +// *** Sleep functions
  90.896 +
  90.897 +/* static */
  90.898 +bool    Thread::Sleep(unsigned secs)
  90.899 +{
  90.900 +    sleep(secs);
  90.901 +    return 1;
  90.902 +}
  90.903 +/* static */
  90.904 +bool    Thread::MSleep(unsigned msecs)
  90.905 +{
  90.906 +    usleep(msecs*1000);
  90.907 +    return 1;
  90.908 +}
  90.909 +
  90.910 +/* static */
  90.911 +int     Thread::GetCPUCount()
  90.912 +{
  90.913 +    #if defined(OVR_OS_MAC) || defined(OVR_OS_BSD)
  90.914 +        // http://developer.apple.com/mac/library/documentation/Darwin/Reference/ManPages/man3/sysctlbyname.3.html
  90.915 +        int    cpuCount = 0;
  90.916 +        size_t len = sizeof(cpuCount);
  90.917 +
  90.918 +        if(sysctlbyname("hw.logicalcpu", &cpuCount, &len, NULL, 0) != 0) 
  90.919 +            cpuCount = 1;
  90.920 +
  90.921 +        return cpuCount;
  90.922 +
  90.923 +    #else // Linux, Android
  90.924 +
  90.925 +        // Alternative: read /proc/cpuinfo
  90.926 +        #ifdef _SC_NPROCESSORS_ONLN
  90.927 +            return (int)sysconf(_SC_NPROCESSORS_ONLN);
  90.928 +        #else
  90.929 +            return 1;
  90.930 +        #endif
  90.931 +    #endif
  90.932 +}
  90.933 +
  90.934 +
  90.935 +void Thread::SetThreadName( const char* name )
  90.936 +{
  90.937 +    #if defined (OVR_OS_APPLE)
  90.938 +        if(ThreadHandle == pthread_self())
  90.939 +            pthread_setname_np(name);
  90.940 +        // Else there's nothing we can do.
  90.941 +    #else
  90.942 +        if(ThreadHandle != 0)
  90.943 +            pthread_setname_np(ThreadHandle, name);
  90.944 +        // Else we can possibly save this name and set it later when the thread starts.
  90.945 +    #endif
  90.946 +}
  90.947 +
  90.948 +
  90.949 +void Thread::SetThreadName(const char* name, ThreadId threadId)
  90.950 +{
  90.951 +    #if defined (OVR_OS_APPLE)
  90.952 +        if(pthread_equal((pthread_t)threadId, pthread_self()))
  90.953 +            pthread_setname_np(name);
  90.954 +        // Else there's no way to set the name of another thread.
  90.955 +    #else
  90.956 +        pthread_setname_np((pthread_t)threadId, name);
  90.957 +    #endif
  90.958 +}
  90.959 +
  90.960 +
  90.961 +void Thread::SetCurrentThreadName(const char* name)
  90.962 +{
  90.963 +    #if defined (OVR_OS_APPLE)
  90.964 +        pthread_setname_np(name);
  90.965 +    #else
  90.966 +        pthread_setname_np(pthread_self(), name);
  90.967 +    #endif
  90.968 +}
  90.969 +
  90.970 +
  90.971 +void Thread::GetThreadName(char* name, size_t nameCapacity, ThreadId threadId)
  90.972 +{
  90.973 +    name[0] = 0;
  90.974 +    pthread_getname_np((pthread_t)threadId, name, nameCapacity);
  90.975 +}
  90.976 +
  90.977 +
  90.978 +void Thread::GetCurrentThreadName(char* name, size_t nameCapacity)
  90.979 +{
  90.980 +    name[0] = 0;
  90.981 +    pthread_getname_np(pthread_self(), name, nameCapacity);
  90.982 +}
  90.983 +
  90.984 +
  90.985 +} // namespace OVR
  90.986 +
  90.987 +#endif  // OVR_ENABLE_THREADS
    91.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    91.2 +++ b/LibOVR/Src/Kernel/OVR_Timer.cpp	Wed Jan 14 06:51:16 2015 +0200
    91.3 @@ -0,0 +1,551 @@
    91.4 +/************************************************************************************
    91.5 +
    91.6 +Filename    :   OVR_Timer.cpp
    91.7 +Content     :   Provides static functions for precise timing
    91.8 +Created     :   September 19, 2012
    91.9 +Notes       : 
   91.10 +
   91.11 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   91.12 +
   91.13 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
   91.14 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
   91.15 +which is provided at the time of installation or download, or which 
   91.16 +otherwise accompanies this software in either electronic or hard copy form.
   91.17 +
   91.18 +You may obtain a copy of the License at
   91.19 +
   91.20 +http://www.oculusvr.com/licenses/LICENSE-3.2 
   91.21 +
   91.22 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
   91.23 +distributed under the License is distributed on an "AS IS" BASIS,
   91.24 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   91.25 +See the License for the specific language governing permissions and
   91.26 +limitations under the License.
   91.27 +
   91.28 +************************************************************************************/
   91.29 +
   91.30 +#include "OVR_Timer.h"
   91.31 +#include "OVR_Log.h"
   91.32 +
   91.33 +#if defined(OVR_OS_MS) && !defined(OVR_OS_MS_MOBILE)
   91.34 +#define WIN32_LEAN_AND_MEAN
   91.35 +#include <windows.h>
   91.36 +#include <MMSystem.h>
   91.37 +#elif defined(OVR_OS_ANDROID)
   91.38 +#include <time.h>
   91.39 +#include <android/log.h>
   91.40 +#elif defined(OVR_OS_MAC)
   91.41 +#include <mach/mach_time.h>
   91.42 +#else
   91.43 +#include <time.h>
   91.44 +#include <sys/time.h>
   91.45 +#include <errno.h>
   91.46 +#endif
   91.47 +
   91.48 +
   91.49 +#if defined(OVR_BUILD_DEBUG) && defined(OVR_OS_WIN32)
   91.50 +    #ifndef NTSTATUS
   91.51 +        #define NTSTATUS DWORD
   91.52 +    #endif
   91.53 +
   91.54 +    typedef NTSTATUS (NTAPI* NtQueryTimerResolutionType)(PULONG MaximumTime, PULONG MinimumTime, PULONG CurrentTime);
   91.55 +    NtQueryTimerResolutionType pNtQueryTimerResolution;
   91.56 +#endif
   91.57 +
   91.58 +
   91.59 +
   91.60 +#if defined(OVR_OS_MS) && !defined(OVR_OS_WIN32) // Non-desktop Microsoft platforms...
   91.61 +
   91.62 +// Add this alias here because we're not going to include OVR_CAPI.cpp
   91.63 +extern "C" {
   91.64 +    double ovr_GetTimeInSeconds()
   91.65 +    {
   91.66 +        return Timer::GetSeconds();
   91.67 +    }
   91.68 +}
   91.69 +
   91.70 +#endif
   91.71 +
   91.72 +
   91.73 +
   91.74 +
   91.75 +namespace OVR {
   91.76 +
   91.77 +// For recorded data playback
   91.78 +bool   Timer::useFakeSeconds = false;
   91.79 +double Timer::FakeSeconds    = 0;
   91.80 +
   91.81 +
   91.82 +
   91.83 +
   91.84 +//------------------------------------------------------------------------
   91.85 +// *** Android Specific Timer
   91.86 +
   91.87 +#if defined(OVR_OS_ANDROID) // To consider: This implementation can also work on most Linux distributions
   91.88 +
   91.89 +//------------------------------------------------------------------------
   91.90 +// *** Timer - Platform Independent functions
   91.91 +
   91.92 +// Returns global high-resolution application timer in seconds.
   91.93 +double Timer::GetSeconds()
   91.94 +{
   91.95 +	if(useFakeSeconds)
   91.96 +		return FakeSeconds;
   91.97 +
   91.98 +    // Choreographer vsync timestamp is based on.
   91.99 +    struct timespec tp;
  91.100 +    const int       status = clock_gettime(CLOCK_MONOTONIC, &tp);
  91.101 +
  91.102 +#ifdef OVR_BUILD_DEBUG
  91.103 +    if (status != 0)
  91.104 +    {
  91.105 +        OVR_DEBUG_LOG(("clock_gettime status=%i", status ));
  91.106 +    }
  91.107 +#else
  91.108 +    OVR_UNUSED(status);
  91.109 +#endif
  91.110 +
  91.111 +    return (double)tp.tv_sec;
  91.112 +}
  91.113 +
  91.114 +
  91.115 +
  91.116 +uint64_t Timer::GetTicksNanos()
  91.117 +{
  91.118 +    if (useFakeSeconds)
  91.119 +        return (uint64_t) (FakeSeconds * NanosPerSecond);
  91.120 +
  91.121 +    // Choreographer vsync timestamp is based on.
  91.122 +    struct timespec tp;
  91.123 +    const int       status = clock_gettime(CLOCK_MONOTONIC, &tp);
  91.124 +
  91.125 +#ifdef OVR_BUILD_DEBUG
  91.126 +    if (status != 0)
  91.127 +    {
  91.128 +        OVR_DEBUG_LOG(("clock_gettime status=%i", status ));
  91.129 +    }
  91.130 +#else
  91.131 +    OVR_UNUSED(status);
  91.132 +#endif
  91.133 +
  91.134 +    const uint64_t result = (uint64_t)tp.tv_sec * (uint64_t)(1000 * 1000 * 1000) + uint64_t(tp.tv_nsec);
  91.135 +    return result;
  91.136 +}
  91.137 +
  91.138 +
  91.139 +void Timer::initializeTimerSystem()
  91.140 +{
  91.141 +    // Empty for this platform.
  91.142 +}
  91.143 +
  91.144 +void Timer::shutdownTimerSystem()
  91.145 +{
  91.146 +    // Empty for this platform.
  91.147 +}
  91.148 +
  91.149 +
  91.150 +
  91.151 +
  91.152 +
  91.153 +//------------------------------------------------------------------------
  91.154 +// *** Win32 Specific Timer
  91.155 +
  91.156 +#elif defined (OVR_OS_MS)
  91.157 +
  91.158 +
  91.159 +// This helper class implements high-resolution wrapper that combines timeGetTime() output
  91.160 +// with QueryPerformanceCounter.  timeGetTime() is lower precision but drives the high bits,
  91.161 +// as it's tied to the system clock.
  91.162 +struct PerformanceTimer
  91.163 +{
  91.164 +    PerformanceTimer()
  91.165 +        : UsingVistaOrLater(false),
  91.166 +          TimeCS(),
  91.167 +          OldMMTimeMs(0), 
  91.168 +          MMTimeWrapCounter(0), 
  91.169 +          PerfFrequency(0),
  91.170 +          PerfFrequencyInverse(0),
  91.171 +          PerfFrequencyInverseNanos(0),
  91.172 +          PerfMinusTicksDeltaNanos(0),
  91.173 +          LastResultNanos(0)
  91.174 +    { }
  91.175 +    
  91.176 +    enum {
  91.177 +        MMTimerResolutionNanos = 1000000
  91.178 +    };
  91.179 +   
  91.180 +    void    Initialize();
  91.181 +    void    Shutdown();
  91.182 +
  91.183 +    uint64_t  GetTimeSeconds();
  91.184 +    double    GetTimeSecondsDouble();
  91.185 +    uint64_t  GetTimeNanos();
  91.186 +
  91.187 +    UINT64 getFrequency()
  91.188 +    {
  91.189 +        if (PerfFrequency == 0)
  91.190 +        {
  91.191 +            LARGE_INTEGER freq;
  91.192 +            QueryPerformanceFrequency(&freq);
  91.193 +            PerfFrequency = freq.QuadPart;
  91.194 +            PerfFrequencyInverse = 1.0 / (double)PerfFrequency;
  91.195 +            PerfFrequencyInverseNanos = 1000000000.0 / (double)PerfFrequency;
  91.196 +        }        
  91.197 +        return PerfFrequency;
  91.198 +    }
  91.199 +    
  91.200 +    double GetFrequencyInverse()
  91.201 +    {
  91.202 +        OVR_ASSERT(PerfFrequencyInverse != 0.0); // Assert that the frequency has been initialized.
  91.203 +        return PerfFrequencyInverse;
  91.204 +    }
  91.205 +
  91.206 +	bool            UsingVistaOrLater;
  91.207 +
  91.208 +    CRITICAL_SECTION TimeCS;
  91.209 +    // timeGetTime() support with wrap.
  91.210 +    uint32_t        OldMMTimeMs;
  91.211 +    uint32_t        MMTimeWrapCounter;
  91.212 +    // Cached performance frequency result.
  91.213 +    uint64_t        PerfFrequency;              // cycles per second, typically a large value like 3000000, but usually not the same as the CPU clock rate.
  91.214 +    double          PerfFrequencyInverse;       // seconds per cycle (will be a small fractional value).
  91.215 +    double          PerfFrequencyInverseNanos;  // nanoseconds per cycle.
  91.216 +    
  91.217 +    // Computed as (perfCounterNanos - ticksCounterNanos) initially,
  91.218 +    // and used to adjust timing.
  91.219 +    uint64_t        PerfMinusTicksDeltaNanos;
  91.220 +    // Last returned value in nanoseconds, to ensure we don't back-step in time.
  91.221 +    uint64_t        LastResultNanos;
  91.222 +};
  91.223 +
  91.224 +static PerformanceTimer Win32_PerfTimer;
  91.225 +
  91.226 +
  91.227 +void PerformanceTimer::Initialize()
  91.228 +{
  91.229 +    #if defined(OVR_OS_WIN32) // Desktop Windows only
  91.230 +        // The following has the effect of setting the NT timer resolution (NtSetTimerResolution) to 1 millisecond.
  91.231 +        MMRESULT mmr = timeBeginPeriod(1);
  91.232 +        OVR_ASSERT(TIMERR_NOERROR == mmr);
  91.233 +        OVR_UNUSED(mmr);
  91.234 +    #endif
  91.235 +
  91.236 +    InitializeCriticalSection(&TimeCS);
  91.237 +    MMTimeWrapCounter = 0;
  91.238 +    getFrequency();
  91.239 +
  91.240 +    #if defined(OVR_OS_WIN32) // Desktop Windows only
  91.241 +	    // Set Vista flag.  On Vista, we can just use QPC() without all the extra work
  91.242 +        OSVERSIONINFOEX ver;
  91.243 +	    ZeroMemory(&ver, sizeof(OSVERSIONINFOEX));
  91.244 +	    ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
  91.245 +	    ver.dwMajorVersion = 6; // Vista+
  91.246 +
  91.247 +        DWORDLONG condMask = 0;
  91.248 +        VER_SET_CONDITION(condMask, VER_MAJORVERSION, VER_GREATER_EQUAL);
  91.249 +
  91.250 +	    // VerifyVersionInfo returns true if the OS meets the conditions set above
  91.251 +	    UsingVistaOrLater = VerifyVersionInfo(&ver, VER_MAJORVERSION, condMask) != 0;
  91.252 +    #else
  91.253 +        UsingVistaOrLater = true;
  91.254 +    #endif
  91.255 +
  91.256 +	OVR_DEBUG_LOG(("PerformanceTimer UsingVistaOrLater = %d", (int)UsingVistaOrLater));
  91.257 +
  91.258 +    #if defined(OVR_BUILD_DEBUG) && defined(OVR_OS_WIN32)
  91.259 +        HMODULE hNtDll = LoadLibrary(L"NtDll.dll");
  91.260 +        if (hNtDll)
  91.261 +        {
  91.262 +            pNtQueryTimerResolution = (NtQueryTimerResolutionType)GetProcAddress(hNtDll, "NtQueryTimerResolution");
  91.263 +          //pNtSetTimerResolution = (NtSetTimerResolutionType)GetProcAddress(hNtDll, "NtSetTimerResolution");
  91.264 +
  91.265 +            if(pNtQueryTimerResolution)
  91.266 +            {
  91.267 +                ULONG MinimumResolution; // in 100-ns units
  91.268 +                ULONG MaximumResolution;
  91.269 +                ULONG ActualResolution;
  91.270 +                pNtQueryTimerResolution(&MinimumResolution, &MaximumResolution, &ActualResolution);
  91.271 +	            OVR_DEBUG_LOG(("NtQueryTimerResolution = Min %ld us, Max %ld us, Current %ld us", MinimumResolution / 10, MaximumResolution / 10, ActualResolution / 10));
  91.272 +            }
  91.273 +
  91.274 +            FreeLibrary(hNtDll);
  91.275 +        }
  91.276 +    #endif
  91.277 +}
  91.278 +
  91.279 +void PerformanceTimer::Shutdown()
  91.280 +{
  91.281 +    DeleteCriticalSection(&TimeCS);
  91.282 +
  91.283 +    #if defined(OVR_OS_WIN32) // Desktop Windows only
  91.284 +        MMRESULT mmr = timeEndPeriod(1);
  91.285 +        OVR_ASSERT(TIMERR_NOERROR == mmr);
  91.286 +        OVR_UNUSED(mmr);
  91.287 +    #endif
  91.288 +}
  91.289 +
  91.290 +
  91.291 +uint64_t PerformanceTimer::GetTimeSeconds()
  91.292 +{
  91.293 +	if (UsingVistaOrLater)
  91.294 +	{
  91.295 +        LARGE_INTEGER li;
  91.296 +		QueryPerformanceCounter(&li);
  91.297 +        OVR_ASSERT(PerfFrequencyInverse != 0); // Initialize should have been called earlier.
  91.298 +        return (uint64_t)(li.QuadPart * PerfFrequencyInverse);
  91.299 +    }
  91.300 +
  91.301 +    return (uint64_t)(GetTimeNanos() * .0000000001);
  91.302 +}
  91.303 +
  91.304 +
  91.305 +double PerformanceTimer::GetTimeSecondsDouble()
  91.306 +{
  91.307 +	if (UsingVistaOrLater)
  91.308 +	{
  91.309 +        LARGE_INTEGER li;
  91.310 +		QueryPerformanceCounter(&li);
  91.311 +        OVR_ASSERT(PerfFrequencyInverse != 0);
  91.312 +        return (li.QuadPart * PerfFrequencyInverse);
  91.313 +    }
  91.314 +
  91.315 +    return (GetTimeNanos() * .0000000001);
  91.316 +}
  91.317 +
  91.318 +
  91.319 +uint64_t PerformanceTimer::GetTimeNanos()
  91.320 +{
  91.321 +    uint64_t      resultNanos;
  91.322 +    LARGE_INTEGER li;
  91.323 +
  91.324 +    OVR_ASSERT(PerfFrequencyInverseNanos != 0); // Initialize should have been called earlier.
  91.325 +
  91.326 +    if (UsingVistaOrLater) // Includes non-desktop platforms
  91.327 +	{
  91.328 +		// Then we can use QPC() directly without all that extra work
  91.329 +		QueryPerformanceCounter(&li);
  91.330 +        resultNanos = (uint64_t)(li.QuadPart * PerfFrequencyInverseNanos);
  91.331 +	}
  91.332 +	else
  91.333 +	{
  91.334 +        // On Win32 QueryPerformanceFrequency is unreliable due to SMP and
  91.335 +        // performance levels, so use this logic to detect wrapping and track
  91.336 +        // high bits.
  91.337 +        ::EnterCriticalSection(&TimeCS);
  91.338 +
  91.339 +        // Get raw value and perf counter "At the same time".
  91.340 +        QueryPerformanceCounter(&li);
  91.341 +
  91.342 +        DWORD mmTimeMs = timeGetTime();
  91.343 +        if (OldMMTimeMs > mmTimeMs)
  91.344 +            MMTimeWrapCounter++;
  91.345 +        OldMMTimeMs = mmTimeMs;
  91.346 +
  91.347 +        // Normalize to nanoseconds.
  91.348 +        uint64_t  perfCounterNanos   = (uint64_t)(li.QuadPart * PerfFrequencyInverseNanos);
  91.349 +        uint64_t  mmCounterNanos     = ((uint64_t(MMTimeWrapCounter) << 32) | mmTimeMs) * 1000000;
  91.350 +        if (PerfMinusTicksDeltaNanos == 0)
  91.351 +            PerfMinusTicksDeltaNanos = perfCounterNanos - mmCounterNanos;
  91.352 + 
  91.353 +        // Compute result before snapping. 
  91.354 +        //
  91.355 +        // On first call, this evaluates to:
  91.356 +        //          resultNanos = mmCounterNanos.    
  91.357 +        // Next call, assuming no wrap:
  91.358 +        //          resultNanos = prev_mmCounterNanos + (perfCounterNanos - prev_perfCounterNanos).        
  91.359 +        // After wrap, this would be:
  91.360 +        //          resultNanos = snapped(prev_mmCounterNanos +/- 1ms) + (perfCounterNanos - prev_perfCounterNanos).
  91.361 +        //
  91.362 +        resultNanos = perfCounterNanos - PerfMinusTicksDeltaNanos;    
  91.363 +
  91.364 +        // Snap the range so that resultNanos never moves further apart then its target resolution.
  91.365 +        // It's better to allow more slack on the high side as timeGetTime() may be updated at sporadically 
  91.366 +        // larger then 1 ms intervals even when 1 ms resolution is requested.
  91.367 +        if (resultNanos > (mmCounterNanos + MMTimerResolutionNanos*2))
  91.368 +        {
  91.369 +            resultNanos = mmCounterNanos + MMTimerResolutionNanos*2;
  91.370 +            if (resultNanos < LastResultNanos)
  91.371 +                resultNanos = LastResultNanos;
  91.372 +            PerfMinusTicksDeltaNanos = perfCounterNanos - resultNanos;
  91.373 +        }
  91.374 +        else if (resultNanos < (mmCounterNanos - MMTimerResolutionNanos))
  91.375 +        {
  91.376 +            resultNanos = mmCounterNanos - MMTimerResolutionNanos;
  91.377 +            if (resultNanos < LastResultNanos)
  91.378 +                resultNanos = LastResultNanos;
  91.379 +            PerfMinusTicksDeltaNanos = perfCounterNanos - resultNanos;
  91.380 +        }
  91.381 +
  91.382 +        LastResultNanos = resultNanos;
  91.383 +        ::LeaveCriticalSection(&TimeCS);
  91.384 +	}
  91.385 +
  91.386 +	//Tom's addition, to keep precision
  91.387 +	//static uint64_t    initial_time = 0;
  91.388 +	//if (!initial_time) initial_time = resultNanos;
  91.389 +	//resultNanos -= initial_time;
  91.390 +	// FIXME: This cannot be used for cross-process timestamps
  91.391 +
  91.392 +    return resultNanos;
  91.393 +}
  91.394 +
  91.395 +
  91.396 +//------------------------------------------------------------------------
  91.397 +// *** Timer - Platform Independent functions
  91.398 +
  91.399 +// Returns global high-resolution application timer in seconds.
  91.400 +double Timer::GetSeconds()
  91.401 +{
  91.402 +	if(useFakeSeconds)
  91.403 +		return FakeSeconds;
  91.404 +
  91.405 +    return Win32_PerfTimer.GetTimeSecondsDouble();
  91.406 +}
  91.407 +
  91.408 +
  91.409 +
  91.410 +// Delegate to PerformanceTimer.
  91.411 +uint64_t Timer::GetTicksNanos()
  91.412 +{
  91.413 +    if (useFakeSeconds)
  91.414 +        return (uint64_t) (FakeSeconds * NanosPerSecond);
  91.415 +
  91.416 +    return Win32_PerfTimer.GetTimeNanos();
  91.417 +}
  91.418 +void Timer::initializeTimerSystem()
  91.419 +{
  91.420 +    Win32_PerfTimer.Initialize();
  91.421 +}
  91.422 +void Timer::shutdownTimerSystem()
  91.423 +{
  91.424 +    Win32_PerfTimer.Shutdown();
  91.425 +}
  91.426 +
  91.427 +
  91.428 +
  91.429 +#elif defined(OVR_OS_MAC)
  91.430 +
  91.431 +
  91.432 +double Timer::TimeConvertFactorNanos   = 0.0;
  91.433 +double Timer::TimeConvertFactorSeconds = 0.0;
  91.434 +
  91.435 +
  91.436 +//------------------------------------------------------------------------
  91.437 +// *** Standard OS Timer     
  91.438 +
  91.439 +// Returns global high-resolution application timer in seconds.
  91.440 +double Timer::GetSeconds()
  91.441 +{
  91.442 +	if(useFakeSeconds)
  91.443 +		return FakeSeconds;
  91.444 +    
  91.445 +    OVR_ASSERT(TimeConvertFactorNanos != 0.0);
  91.446 +    return (double)mach_absolute_time() * TimeConvertFactorNanos;
  91.447 +}
  91.448 +
  91.449 +
  91.450 +uint64_t Timer::GetTicksNanos()
  91.451 +{
  91.452 +    if (useFakeSeconds)
  91.453 +        return (uint64_t) (FakeSeconds * NanosPerSecond);
  91.454 +    
  91.455 +    OVR_ASSERT(TimeConvertFactorSeconds != 0.0);
  91.456 +    return (uint64_t)(mach_absolute_time() * TimeConvertFactorSeconds);
  91.457 +}
  91.458 +
  91.459 +void Timer::initializeTimerSystem()
  91.460 +{
  91.461 +    mach_timebase_info_data_t timeBase;
  91.462 +    mach_timebase_info(&timeBase);
  91.463 +    TimeConvertFactorSeconds = ((double)timeBase.numer / (double)timeBase.denom);
  91.464 +    TimeConvertFactorNanos   = TimeConvertFactorSeconds / 1000000000.0;
  91.465 +}
  91.466 +
  91.467 +void Timer::shutdownTimerSystem()
  91.468 +{
  91.469 +    // Empty for this platform.
  91.470 +}
  91.471 +
  91.472 +
  91.473 +#else // Posix platforms (e.g. Linux, BSD Unix)
  91.474 +
  91.475 +
  91.476 +bool Timer::MonotonicClockAvailable = false;
  91.477 +
  91.478 +
  91.479 +// Returns global high-resolution application timer in seconds.
  91.480 +double Timer::GetSeconds()
  91.481 +{
  91.482 +	if(useFakeSeconds)
  91.483 +		return FakeSeconds;
  91.484 +
  91.485 +    // http://linux/die/netman3/clock_gettime
  91.486 +    #if defined(CLOCK_MONOTONIC) // If we can use clock_gettime, which has nanosecond precision...
  91.487 +        if(MonotonicClockAvailable)
  91.488 +        {
  91.489 +            timespec ts;
  91.490 +            clock_gettime(CLOCK_MONOTONIC, &ts); // Better to use CLOCK_MONOTONIC than CLOCK_REALTIME.
  91.491 +            return static_cast<double>(ts.tv_sec) + static_cast<double>(ts.tv_nsec) / 1E9;
  91.492 +        }
  91.493 +    #endif
  91.494 +
  91.495 +    // We cannot use rdtsc because its frequency changes at runtime.
  91.496 +    struct timeval tv;
  91.497 +    gettimeofday(&tv, 0);
  91.498 +
  91.499 +    return static_cast<double>(tv.tv_sec) + static_cast<double>(tv.tv_usec) / 1E6;
  91.500 +}
  91.501 +
  91.502 +
  91.503 +uint64_t Timer::GetTicksNanos()
  91.504 +{
  91.505 +    if (useFakeSeconds)
  91.506 +        return (uint64_t) (FakeSeconds * NanosPerSecond);
  91.507 +
  91.508 +    #if defined(CLOCK_MONOTONIC) // If we can use clock_gettime, which has nanosecond precision...
  91.509 +        if(MonotonicClockAvailable)
  91.510 +        {
  91.511 +            timespec ts;
  91.512 +            clock_gettime(CLOCK_MONOTONIC, &ts);
  91.513 +            return ((uint64_t)ts.tv_sec * 1000000000ULL) + (uint64_t)ts.tv_nsec;
  91.514 +        }
  91.515 +    #endif
  91.516 +
  91.517 +
  91.518 +    // We cannot use rdtsc because its frequency changes at runtime.
  91.519 +	uint64_t result;
  91.520 +
  91.521 +    // Return microseconds.
  91.522 +    struct timeval tv;
  91.523 +
  91.524 +    gettimeofday(&tv, 0);
  91.525 +
  91.526 +    result = (uint64_t)tv.tv_sec * 1000000;
  91.527 +    result += tv.tv_usec;
  91.528 +
  91.529 +    return result * 1000;
  91.530 +}
  91.531 +
  91.532 +
  91.533 +void Timer::initializeTimerSystem()
  91.534 +{
  91.535 +    #if defined(CLOCK_MONOTONIC)
  91.536 +        timespec ts; // We could also check for the availability of CLOCK_MONOTONIC with sysconf(_SC_MONOTONIC_CLOCK)
  91.537 +        int result = clock_gettime(CLOCK_MONOTONIC, &ts);
  91.538 +        MonotonicClockAvailable = (result == 0);
  91.539 +    #endif
  91.540 +}
  91.541 +
  91.542 +void Timer::shutdownTimerSystem()
  91.543 +{
  91.544 +    // Empty for this platform.
  91.545 +}
  91.546 +
  91.547 +
  91.548 +
  91.549 +#endif  // OS-specific
  91.550 +
  91.551 +
  91.552 +
  91.553 +} // OVR
  91.554 +
    92.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    92.2 +++ b/LibOVR/Src/Kernel/OVR_Timer.h	Wed Jan 14 06:51:16 2015 +0200
    92.3 @@ -0,0 +1,99 @@
    92.4 +/************************************************************************************
    92.5 +
    92.6 +PublicHeader:   OVR
    92.7 +Filename    :   OVR_Timer.h
    92.8 +Content     :   Provides static functions for precise timing
    92.9 +Created     :   September 19, 2012
   92.10 +Notes       : 
   92.11 +
   92.12 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   92.13 +
   92.14 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
   92.15 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
   92.16 +which is provided at the time of installation or download, or which 
   92.17 +otherwise accompanies this software in either electronic or hard copy form.
   92.18 +
   92.19 +You may obtain a copy of the License at
   92.20 +
   92.21 +http://www.oculusvr.com/licenses/LICENSE-3.2 
   92.22 +
   92.23 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
   92.24 +distributed under the License is distributed on an "AS IS" BASIS,
   92.25 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   92.26 +See the License for the specific language governing permissions and
   92.27 +limitations under the License.
   92.28 +
   92.29 +************************************************************************************/
   92.30 +
   92.31 +#ifndef OVR_Timer_h
   92.32 +#define OVR_Timer_h
   92.33 +
   92.34 +#include "OVR_Types.h"
   92.35 +
   92.36 +namespace OVR {
   92.37 +    
   92.38 +//-----------------------------------------------------------------------------------
   92.39 +// ***** Timer
   92.40 +
   92.41 +// Timer class defines a family of static functions used for application
   92.42 +// timing and profiling.
   92.43 +
   92.44 +class Timer
   92.45 +{
   92.46 +public:
   92.47 +    enum {
   92.48 +        MsPerSecond     = 1000,                  // Milliseconds in one second.
   92.49 +        MksPerSecond    = 1000 * 1000,           // Microseconds in one second.
   92.50 +        NanosPerSecond  = 1000 * 1000 * 1000,    // Nanoseconds in one second.
   92.51 +    };
   92.52 +
   92.53 +    // ***** Timing APIs for Application    
   92.54 +
   92.55 +    // These APIs should be used to guide animation and other program functions
   92.56 +    // that require precision.
   92.57 +
   92.58 +    // Returns global high-resolution application timer in seconds.
   92.59 +    static double  OVR_STDCALL GetSeconds();    
   92.60 +
   92.61 +    // Returns time in Nanoseconds, using highest possible system resolution.
   92.62 +    static uint64_t  OVR_STDCALL GetTicksNanos();
   92.63 +
   92.64 +    // Kept for compatibility.
   92.65 +    // Returns ticks in milliseconds, as a 32-bit number. May wrap around every 49.2 days.
   92.66 +    // Use either time difference of two values of GetTicks to avoid wrap-around.
   92.67 +    static uint32_t  OVR_STDCALL GetTicksMs()
   92.68 +    { return  uint32_t(GetTicksNanos() / 1000000); }
   92.69 +
   92.70 +    // for recorded data playback
   92.71 +    static void SetFakeSeconds(double fakeSeconds, bool enable = true) 
   92.72 +    { 
   92.73 +        FakeSeconds = fakeSeconds; 
   92.74 +        useFakeSeconds = enable; 
   92.75 +    }
   92.76 +
   92.77 +private:
   92.78 +    friend class System;
   92.79 +    // System called during program startup/shutdown.
   92.80 +    static void initializeTimerSystem();
   92.81 +    static void shutdownTimerSystem();
   92.82 +
   92.83 +    // for recorded data playback
   92.84 +    static double FakeSeconds;
   92.85 +    static bool   useFakeSeconds;
   92.86 +    
   92.87 +    #if defined(OVR_OS_ANDROID)
   92.88 +        // Android-specific data
   92.89 +    #elif defined (OVR_OS_MS)
   92.90 +        // Microsoft-specific data
   92.91 +    #elif defined(OVR_OS_MAC)
   92.92 +        static double TimeConvertFactorNanos;     // Conversion factor for GetTicksNanos
   92.93 +        static double TimeConvertFactorSeconds;   // Conversion factor for GetSeconds.
   92.94 +    #else
   92.95 +        static bool MonotonicClockAvailable;      // True if clock_gettime supports CLOCK_MONOTONIC
   92.96 +    #endif
   92.97 +};
   92.98 +
   92.99 +
  92.100 +} // OVR::Timer
  92.101 +
  92.102 +#endif
    93.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    93.2 +++ b/LibOVR/Src/Kernel/OVR_Types.h	Wed Jan 14 06:51:16 2015 +0200
    93.3 @@ -0,0 +1,909 @@
    93.4 +/************************************************************************************
    93.5 +
    93.6 +PublicHeader:   OVR_Kernel.h
    93.7 +Filename    :   OVR_Types.h
    93.8 +Content     :   Standard library defines and simple types
    93.9 +Created     :   September 19, 2012
   93.10 +Notes       : 
   93.11 +
   93.12 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   93.13 +
   93.14 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
   93.15 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
   93.16 +which is provided at the time of installation or download, or which 
   93.17 +otherwise accompanies this software in either electronic or hard copy form.
   93.18 +
   93.19 +You may obtain a copy of the License at
   93.20 +
   93.21 +http://www.oculusvr.com/licenses/LICENSE-3.2 
   93.22 +
   93.23 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
   93.24 +distributed under the License is distributed on an "AS IS" BASIS,
   93.25 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   93.26 +See the License for the specific language governing permissions and
   93.27 +limitations under the License.
   93.28 +
   93.29 +************************************************************************************/
   93.30 +
   93.31 +#ifndef OVR_Types_H
   93.32 +#define OVR_Types_H
   93.33 +
   93.34 +#include "OVR_Compiler.h"
   93.35 +
   93.36 +
   93.37 +// Unsupported compiler configurations
   93.38 +#if _MSC_VER == 0x1600
   93.39 +#  if _MSC_FULL_VER < 160040219
   93.40 +#     error "Oculus does not support VS2010 without SP1 installed: It will crash in Release mode"
   93.41 +#  endif
   93.42 +#endif
   93.43 +
   93.44 +
   93.45 +//-----------------------------------------------------------------------------------
   93.46 +// ****** Operating system identification
   93.47 +//
   93.48 +// Try to use the most generic version of these defines as possible in order to achieve
   93.49 +// the simplest portable code. For example, instead of using #if (defined(OVR_OS_IPHONE) || defined(OVR_OS_MAC)),
   93.50 +// consider using #if defined(OVR_OS_APPLE).
   93.51 +//
   93.52 +// Type definitions exist for the following operating systems: (OVR_OS_x)
   93.53 +//
   93.54 +//    WIN32      - Win32 and Win64 (Windows XP and later) Does not include Microsoft phone and console platforms, despite that Microsoft's _WIN32 may be defined by the compiler for them.
   93.55 +//    WIN64      - Win64 (Windows XP and later)
   93.56 +//    MAC        - Mac OS X (may be defined in addition to BSD)
   93.57 +//    LINUX      - Linux
   93.58 +//    BSD        - BSD Unix
   93.59 +//    ANDROID    - Android (may be defined in addition to LINUX)
   93.60 +//    IPHONE     - iPhone
   93.61 +//    MS_MOBILE  - Microsoft mobile OS.
   93.62 +//
   93.63 +//  Meta platforms
   93.64 +//    MS        - Any OS by Microsoft (e.g. Win32, Win64, phone, console)
   93.65 +//    APPLE     - Any OS by Apple (e.g. iOS, OS X)
   93.66 +//    UNIX      - Linux, BSD, Mac OS X.
   93.67 +//    MOBILE    - iOS, Android, Microsoft phone
   93.68 +//    CONSOLE   - Console platforms
   93.69 +//
   93.70 +
   93.71 +#if (defined(__APPLE__) && (defined(__GNUC__) ||\
   93.72 +     defined(__xlC__) || defined(__xlc__))) || defined(__MACOS__)
   93.73 +#  if (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) || defined(__IPHONE_OS_VERSION_MIN_REQUIRED))
   93.74 +#    define OVR_OS_IPHONE
   93.75 +#  else
   93.76 +#    define OVR_OS_DARWIN
   93.77 +#    define OVR_OS_MAC
   93.78 +#    define OVR_OS_BSD
   93.79 +#  endif
   93.80 +#elif (defined(WIN64) || defined(_WIN64) || defined(__WIN64__))
   93.81 +#  define OVR_OS_WIN64
   93.82 +#  define OVR_OS_WIN32   // Defined for compatibility and because the Win64 API supports the Win32 API.
   93.83 +#elif (defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__))
   93.84 +#  define OVR_OS_WIN32
   93.85 +#elif defined(ANDROID) || defined(__ANDROID__)
   93.86 +#  define OVR_OS_ANDROID
   93.87 +#  define OVR_OS_LINUX
   93.88 +#elif defined(__linux__) || defined(__linux)
   93.89 +#  define OVR_OS_LINUX
   93.90 +#elif defined(_BSD_) || defined(__FreeBSD__)
   93.91 +#  define OVR_OS_BSD
   93.92 +#else
   93.93 +#  define OVR_OS_OTHER
   93.94 +#endif
   93.95 +
   93.96 +#if !defined(OVR_OS_MS_MOBILE)
   93.97 +#   if (defined(_M_ARM) || defined(_M_IX86) || defined(_M_AMD64)) && !defined(OVR_OS_WIN32) && !defined(OVR_OS_CONSOLE)
   93.98 +#       define OVR_OS_MS_MOBILE
   93.99 +#   endif
  93.100 +#endif
  93.101 +
  93.102 +#if !defined(OVR_OS_MS)
  93.103 +#   if defined(OVR_OS_WIN32) || defined(OVR_OS_WIN64) || defined(OVR_OS_MS_MOBILE)
  93.104 +#       define OVR_OS_MS
  93.105 +#   endif
  93.106 +#endif
  93.107 +
  93.108 +#if !defined(OVR_OS_APPLE)
  93.109 +#   if defined(OVR_OS_MAC) || defined(OVR_OS_IPHONE)
  93.110 +#       define OVR_OS_APPLE
  93.111 +#   endif
  93.112 +#endif
  93.113 +
  93.114 +#if !defined(OVR_OS_UNIX)
  93.115 +#   if defined(OVR_OS_ANDROID) || defined(OVR_OS_BSD) || defined(OVR_OS_LINUX) || defined(OVR_OS_MAC)
  93.116 +#       define OVR_OS_UNIX
  93.117 +#   endif
  93.118 +#endif
  93.119 +
  93.120 +#if !defined(OVR_OS_MOBILE)
  93.121 +#   if defined(OVR_OS_ANDROID) || defined(OVR_OS_IPHONE) || defined(OVR_OS_MS_MOBILE)
  93.122 +#       define OVR_OS_MOBILE
  93.123 +#   endif
  93.124 +#endif
  93.125 +
  93.126 +
  93.127 +
  93.128 +
  93.129 +//-----------------------------------------------------------------------------------
  93.130 +// ***** CPU Architecture
  93.131 +//
  93.132 +// The following CPUs are defined: (OVR_CPU_x)
  93.133 +//
  93.134 +//    X86        - x86 (IA-32)
  93.135 +//    X86_64     - x86_64 (amd64)
  93.136 +//    PPC        - PowerPC
  93.137 +//    PPC64      - PowerPC64
  93.138 +//    MIPS       - MIPS
  93.139 +//    OTHER      - CPU for which no special support is present or needed
  93.140 +
  93.141 +
  93.142 +#if defined(__x86_64__) || defined(WIN64) || defined(_WIN64) || defined(__WIN64__) || defined(_M_AMD64)
  93.143 +#  define OVR_CPU_X86_64
  93.144 +#  define OVR_64BIT_POINTERS
  93.145 +#elif defined(__i386__) || defined(OVR_OS_WIN32)
  93.146 +#  define OVR_CPU_X86
  93.147 +#elif defined(__powerpc64__)
  93.148 +#  define OVR_CPU_PPC64
  93.149 +#elif defined(__ppc__)
  93.150 +#  define OVR_CPU_PPC
  93.151 +#elif defined(__mips__) || defined(__MIPSEL__)
  93.152 +#  define OVR_CPU_MIPS
  93.153 +#elif defined(__arm__)
  93.154 +#  define OVR_CPU_ARM
  93.155 +#else
  93.156 +#  define OVR_CPU_OTHER
  93.157 +#endif
  93.158 +
  93.159 +//-----------------------------------------------------------------------------------
  93.160 +// ***** Co-Processor Architecture
  93.161 +//
  93.162 +// The following co-processors are defined: (OVR_CPU_x)
  93.163 +//
  93.164 +//    SSE        - Available on all modern x86 processors.
  93.165 +//    Altivec    - Available on all modern ppc processors.
  93.166 +//    Neon       - Available on some armv7+ processors.
  93.167 +
  93.168 +#if defined(__SSE__) || defined(_M_IX86) || defined(_M_AMD64) // _M_IX86 and _M_AMD64 are Microsoft identifiers for Intel-based platforms.
  93.169 +#  define  OVR_CPU_SSE
  93.170 +#endif // __SSE__
  93.171 +
  93.172 +#if defined( __ALTIVEC__ )
  93.173 +#  define OVR_CPU_ALTIVEC
  93.174 +#endif // __ALTIVEC__
  93.175 +
  93.176 +#if defined(__ARM_NEON__)
  93.177 +#  define OVR_CPU_ARM_NEON
  93.178 +#endif // __ARM_NEON__
  93.179 +
  93.180 +
  93.181 +//-----------------------------------------------------------------------------------
  93.182 +// ***** Compiler Warnings
  93.183 +
  93.184 +// Disable MSVC warnings
  93.185 +#if defined(OVR_CC_MSVC)
  93.186 +#  pragma warning(disable : 4127)    // Inconsistent dll linkage
  93.187 +#  pragma warning(disable : 4530)    // Exception handling
  93.188 +#  if (OVR_CC_MSVC<1300)
  93.189 +#    pragma warning(disable : 4514)  // Unreferenced inline function has been removed
  93.190 +#    pragma warning(disable : 4710)  // Function not inlined
  93.191 +#    pragma warning(disable : 4714)  // _force_inline not inlined
  93.192 +#    pragma warning(disable : 4786)  // Debug variable name longer than 255 chars
  93.193 +#  endif // (OVR_CC_MSVC<1300)
  93.194 +#endif // (OVR_CC_MSVC)
  93.195 +
  93.196 +
  93.197 +
  93.198 +// *** Linux Unicode - must come before Standard Includes
  93.199 +
  93.200 +#ifdef OVR_OS_LINUX
  93.201 +// Use glibc unicode functions on linux.
  93.202 +#  ifndef  _GNU_SOURCE
  93.203 +#    define _GNU_SOURCE
  93.204 +#  endif
  93.205 +#endif
  93.206 +
  93.207 +//-----------------------------------------------------------------------------------
  93.208 +// ***** Standard Includes
  93.209 +//
  93.210 +#include    <stddef.h>
  93.211 +#include    <limits.h>
  93.212 +#include    <float.h>
  93.213 +
  93.214 +
  93.215 +// MSVC Based Memory Leak checking - for now
  93.216 +#if defined(OVR_CC_MSVC) && defined(OVR_BUILD_DEBUG)
  93.217 +#  define _CRTDBG_MAP_ALLOC
  93.218 +#  include <stdlib.h>
  93.219 +#  include <crtdbg.h>
  93.220 +#endif
  93.221 +
  93.222 +
  93.223 +//-----------------------------------------------------------------------------------
  93.224 +// ***** int8_t, int16_t, etc.
  93.225 +
  93.226 +#if defined(OVR_CC_MSVC) && (OVR_CC_VER <= 1500) // VS2008 and earlier
  93.227 +    typedef signed char        int8_t; 
  93.228 +    typedef unsigned char     uint8_t;
  93.229 +    typedef signed short      int16_t;
  93.230 +    typedef unsigned short   uint16_t;
  93.231 +    typedef signed int        int32_t;
  93.232 +    typedef unsigned int     uint32_t;
  93.233 +    typedef signed __int64    int64_t;
  93.234 +    typedef unsigned __int64 uint64_t;
  93.235 +#else
  93.236 +    #include <stdint.h>
  93.237 +#endif
  93.238 +
  93.239 +
  93.240 +//-----------------------------------------------------------------------------------
  93.241 +// ***** Type definitions for Common Systems
  93.242 +
  93.243 +namespace OVR {
  93.244 +
  93.245 +typedef char            Char;
  93.246 +
  93.247 +// Pointer-sized integer
  93.248 +typedef size_t          UPInt;
  93.249 +typedef ptrdiff_t       SPInt;
  93.250 +
  93.251 +
  93.252 +#if defined(OVR_OS_MS)
  93.253 +
  93.254 +typedef char            SByte;  // 8 bit Integer (Byte)
  93.255 +typedef unsigned char   UByte;
  93.256 +typedef short           SInt16; // 16 bit Integer (Word)
  93.257 +typedef unsigned short  UInt16;
  93.258 +typedef long            SInt32; // 32 bit Integer
  93.259 +typedef unsigned long   UInt32;
  93.260 +typedef __int64         SInt64; // 64 bit Integer (QWord)
  93.261 +typedef unsigned __int64 UInt64;
  93.262 +
  93.263 + 
  93.264 +#elif defined(OVR_OS_MAC) || defined(OVR_OS_IPHONE) || defined(OVR_CC_GNU)
  93.265 +
  93.266 +typedef int             SByte  __attribute__((__mode__ (__QI__)));
  93.267 +typedef unsigned int    UByte  __attribute__((__mode__ (__QI__)));
  93.268 +typedef int             SInt16 __attribute__((__mode__ (__HI__)));
  93.269 +typedef unsigned int    UInt16 __attribute__((__mode__ (__HI__)));
  93.270 +typedef int             SInt32 __attribute__((__mode__ (__SI__)));
  93.271 +typedef unsigned int    UInt32 __attribute__((__mode__ (__SI__)));
  93.272 +typedef int             SInt64 __attribute__((__mode__ (__DI__)));
  93.273 +typedef unsigned int    UInt64 __attribute__((__mode__ (__DI__)));
  93.274 +
  93.275 +#else
  93.276 +
  93.277 +#include <sys/types.h>
  93.278 +typedef int8_t          SByte;
  93.279 +typedef uint8_t         UByte;
  93.280 +typedef int16_t         SInt16;
  93.281 +typedef uint16_t        UInt16;
  93.282 +typedef int32_t         SInt32;
  93.283 +typedef uint32_t        UInt32;
  93.284 +typedef int64_t         SInt64;
  93.285 +typedef uint64_t        UInt64;
  93.286 +
  93.287 +#endif
  93.288 +    
  93.289 +    
  93.290 +//osx PID is a signed int32 (already defined to pid_t in OSX framework)
  93.291 +//linux PID is a signed int32 (already defined)
  93.292 +//win32 PID is an unsigned int64
  93.293 +#ifdef OVR_OS_WIN32
  93.294 +//process ID representation
  93.295 +typedef unsigned long pid_t;
  93.296 +#endif
  93.297 +
  93.298 +struct OVR_GUID
  93.299 +{
  93.300 +	uint32_t Data1;
  93.301 +	uint16_t Data2;
  93.302 +	uint16_t Data3;
  93.303 +	uint8_t  Data4[8];
  93.304 +};
  93.305 +
  93.306 +
  93.307 +
  93.308 +} // OVR
  93.309 +
  93.310 +
  93.311 +
  93.312 +//-----------------------------------------------------------------------------------
  93.313 +// ****** Standard C/C++ Library
  93.314 +//
  93.315 +// Identifies which standard library is currently being used. 
  93.316 +//
  93.317 +//    LIBSTDCPP   - GNU libstdc++, used by GCC.
  93.318 +//    LIBCPP      - LLVM libc++, typically used by clang and GCC.
  93.319 +//    DINKUMWARE  - Used by Microsoft and various non-Microsoft compilers (e.g. Sony clang).
  93.320 +
  93.321 +#if !defined(OVR_STDLIB_LIBSTDCPP)
  93.322 +    #if defined(__GLIBCXX__)
  93.323 +        #define OVR_STDLIB_LIBSTDCPP 1
  93.324 +    #endif
  93.325 +#endif
  93.326 +
  93.327 +#if !defined(OVR_STDLIB_LIBCPP)
  93.328 +    #if defined(__clang__)
  93.329 +        #if defined(__cplusplus) && __has_include(<__config>)
  93.330 +            #define OVR_STDLIB_LIBCPP 1
  93.331 +        #endif
  93.332 +    #endif 
  93.333 +#endif
  93.334 +
  93.335 +#if !defined(OVR_STDLIB_DINKUMWARE)
  93.336 +    #if defined(_YVALS) // Dinkumware globally #defines _YVALS from the #includes above.
  93.337 +        #define OVR_STDLIB_DINKUMWARE 1
  93.338 +    #endif
  93.339 +#endif
  93.340 +
  93.341 +
  93.342 +//-----------------------------------------------------------------------------------
  93.343 +// ***** Macro Definitions
  93.344 +//
  93.345 +// We define the following:
  93.346 +//
  93.347 +//  OVR_BYTE_ORDER      - Defined to either OVR_LITTLE_ENDIAN or OVR_BIG_ENDIAN
  93.348 +//  OVR_FORCE_INLINE    - Forces inline expansion of function
  93.349 +//  OVR_ASM             - Assembly language prefix
  93.350 +//  OVR_STR             - Prefixes string with L"" if building unicode
  93.351 +// 
  93.352 +//  OVR_STDCALL         - Use stdcall calling convention (Pascal arg order)
  93.353 +//  OVR_CDECL           - Use cdecl calling convention (C argument order)
  93.354 +//  OVR_FASTCALL        - Use fastcall calling convention (registers)
  93.355 +//
  93.356 +
  93.357 +// Byte order constants, OVR_BYTE_ORDER is defined to be one of these.
  93.358 +#define OVR_LITTLE_ENDIAN       1
  93.359 +#define OVR_BIG_ENDIAN          2
  93.360 +
  93.361 +
  93.362 +#if defined(OVR_OS_MS)
  93.363 +    
  93.364 +    // ***** Windows and non-desktop platforms
  93.365 +
  93.366 +    // Byte order
  93.367 +    #define OVR_BYTE_ORDER    OVR_LITTLE_ENDIAN
  93.368 +
  93.369 +    // Calling convention - goes after function return type but before function name
  93.370 +    #ifdef __cplusplus_cli
  93.371 +    #  define OVR_FASTCALL      __stdcall
  93.372 +    #else
  93.373 +    #  define OVR_FASTCALL      __fastcall
  93.374 +    #endif
  93.375 +
  93.376 +    #define OVR_STDCALL         __stdcall
  93.377 +    #define OVR_CDECL           __cdecl
  93.378 +
  93.379 +
  93.380 +    // Assembly macros
  93.381 +    #if defined(OVR_CC_MSVC)
  93.382 +    #  define OVR_ASM           _asm
  93.383 +    #else
  93.384 +    #  define OVR_ASM           asm
  93.385 +    #endif // (OVR_CC_MSVC)
  93.386 +
  93.387 +    #ifdef UNICODE
  93.388 +    #  define OVR_STR(str)      L##str
  93.389 +    #else
  93.390 +    #  define OVR_STR(str)      str
  93.391 +    #endif // UNICODE
  93.392 +
  93.393 +#else
  93.394 +
  93.395 +    // **** Standard systems
  93.396 +
  93.397 +    #if (defined(BYTE_ORDER) && (BYTE_ORDER == BIG_ENDIAN))|| \
  93.398 +        (defined(_BYTE_ORDER) && (_BYTE_ORDER == _BIG_ENDIAN))
  93.399 +    #  define OVR_BYTE_ORDER    OVR_BIG_ENDIAN
  93.400 +    #elif (defined(__ARMEB__) || defined(OVR_CPU_PPC) || defined(OVR_CPU_PPC64))
  93.401 +    #  define OVR_BYTE_ORDER    OVR_BIG_ENDIAN
  93.402 +    #else
  93.403 +    #  define OVR_BYTE_ORDER    OVR_LITTLE_ENDIAN
  93.404 +    #endif
  93.405 +    
  93.406 +    // Assembly macros
  93.407 +    #define OVR_ASM                  __asm__
  93.408 +    #define OVR_ASM_PROC(procname)   OVR_ASM
  93.409 +    #define OVR_ASM_END              OVR_ASM
  93.410 +    
  93.411 +    // Calling convention - goes after function return type but before function name
  93.412 +    #define OVR_FASTCALL
  93.413 +    #define OVR_STDCALL
  93.414 +    #define OVR_CDECL
  93.415 +
  93.416 +#endif // defined(OVR_OS_WIN32)
  93.417 +
  93.418 +
  93.419 +//-----------------------------------------------------------------------------------
  93.420 +// ***** OVR_PTR_SIZE
  93.421 +// 
  93.422 +// Specifies the byte size of pointers (same as sizeof void*).
  93.423 +
  93.424 +#if !defined(OVR_PTR_SIZE)
  93.425 +    #if defined(__WORDSIZE)
  93.426 +        #define OVR_PTR_SIZE ((__WORDSIZE) / 8)
  93.427 +    #elif defined(_WIN64) || defined(__LP64__) || defined(_LP64) || defined(_M_IA64) || defined(__ia64__) || defined(__arch64__) || defined(__64BIT__) || defined(__Ptr_Is_64)
  93.428 +        #define OVR_PTR_SIZE 8
  93.429 +    #elif defined(__CC_ARM) && (__sizeof_ptr == 8)
  93.430 +        #define OVR_PTR_SIZE 8
  93.431 +    #else
  93.432 +        #define OVR_PTR_SIZE 4
  93.433 +    #endif
  93.434 +#endif
  93.435 +
  93.436 +
  93.437 +//-----------------------------------------------------------------------------------
  93.438 +// ***** OVR_WORD_SIZE
  93.439 +// 
  93.440 +// Specifies the byte size of a machine word/register. Not necessarily the same as
  93.441 +// the size of pointers, but usually >= the size of pointers.
  93.442 +
  93.443 +#if !defined(OVR_WORD_SIZE)
  93.444 +   #define OVR_WORD_SIZE OVR_PTR_SIZE // For our currently supported platforms these are equal.
  93.445 +#endif
  93.446 +
  93.447 +
  93.448 +// ------------------------------------------------------------------------
  93.449 +// ***** OVR_FORCE_INLINE
  93.450 +//
  93.451 +// Force inline substitute - goes before function declaration
  93.452 +// Example usage:
  93.453 +//     OVR_FORCE_INLINE void Test();
  93.454 +
  93.455 +#if !defined(OVR_FORCE_INLINE)
  93.456 +    #if defined(OVR_CC_MSVC)
  93.457 +        #define OVR_FORCE_INLINE  __forceinline
  93.458 +    #elif defined(OVR_CC_GNU)
  93.459 +        #define OVR_FORCE_INLINE  __attribute__((always_inline)) inline
  93.460 +    #else
  93.461 +        #define OVR_FORCE_INLINE  inline
  93.462 +    #endif  // OVR_CC_MSVC
  93.463 +#endif
  93.464 +
  93.465 +
  93.466 +// ------------------------------------------------------------------------
  93.467 +// ***** OVR_NO_INLINE
  93.468 +//
  93.469 +// Cannot be used with inline or OVR_FORCE_INLINE.
  93.470 +// Example usage:
  93.471 +//     OVR_NO_INLINE void Test();
  93.472 +
  93.473 +#if !defined(OVR_NO_INLINE)
  93.474 +    #if defined(OVR_CC_MSVC) && (_MSC_VER >= 1500) // VS2008+
  93.475 +        #define OVR_NO_INLINE __declspec(noinline)
  93.476 +    #elif !defined(OVR_CC_MSVC)
  93.477 +        #define OVR_NO_INLINE __attribute__((noinline))
  93.478 +    #endif
  93.479 +#endif
  93.480 +
  93.481 +
  93.482 +// -----------------------------------------------------------------------------------
  93.483 +// ***** OVR_STRINGIZE
  93.484 +//
  93.485 +// Converts a preprocessor symbol to a string.
  93.486 +//
  93.487 +// Example usage:
  93.488 +//     printf("Line: %s", OVR_STRINGIZE(__LINE__));
  93.489 +//
  93.490 +#if !defined(OVR_STRINGIFY)
  93.491 +    #define OVR_STRINGIZEIMPL(x) #x
  93.492 +    #define OVR_STRINGIZE(x)     OVR_STRINGIZEIMPL(x)
  93.493 +#endif
  93.494 +
  93.495 +
  93.496 +// -----------------------------------------------------------------------------------
  93.497 +// ***** OVR_JOIN
  93.498 +//
  93.499 +// Joins two preprocessing symbols together. Supports the case when either or the
  93.500 +// the symbols are macros themselves.
  93.501 +//
  93.502 +// Example usage:
  93.503 +//    char OVR_JOIN(unique_, __LINE__);  // Results in (e.g.) char unique_123;
  93.504 +//
  93.505 +#if !defined(OVR_JOIN)
  93.506 +    #define OVR_JOIN(a, b)  OVR_JOIN1(a, b)
  93.507 +    #define OVR_JOIN1(a, b) OVR_JOIN2(a, b)
  93.508 +    #define OVR_JOIN2(a, b) a##b
  93.509 +#endif
  93.510 +
  93.511 +
  93.512 +//-----------------------------------------------------------------------------------
  93.513 +// ***** OVR_OFFSETOF
  93.514 +// 
  93.515 +// Portable implementation of offsetof for structs and classes. offsetof and GCC's 
  93.516 +// __builtin_offsetof work only with POD types (standard-layout types under C++11), 
  93.517 +// despite that it can safely work with a number of types that aren't POD. This 
  93.518 +// version works with more types without generating compiler warnings or errors.
  93.519 +// Returns the offset as a size_t, as per offsetof.
  93.520 +//
  93.521 +// Example usage:
  93.522 +//     struct Test{ int i; float f; };
  93.523 +//     size_t fPos = OVR_OFFSETOF(Test, f);
  93.524 +
  93.525 +#if defined(OVR_CC_GNU)
  93.526 +    #define OVR_OFFSETOF(class_, member_) ((size_t)(((uintptr_t)&reinterpret_cast<const volatile char&>((((class_*)65536)->member_))) - 65536))
  93.527 +#else
  93.528 +    #define OVR_OFFSETOF(class_, member_) offsetof(class_, member_)
  93.529 +#endif
  93.530 +
  93.531 +
  93.532 +//-----------------------------------------------------------------------------------
  93.533 +// ***** OVR_SIZEOF_MEMBER
  93.534 +//
  93.535 +// Implements a portable way to determine the size of struct or class data member. 
  93.536 +// C++11 allows this directly via sizeof (see OVR_CPP_NO_EXTENDED_SIZEOF), and this 
  93.537 +// macro exists to handle pre-C++11 compilers.
  93.538 +// Returns the offset as a size_t, as per sizeof.
  93.539 +//
  93.540 +// Example usage:
  93.541 +//     struct Test{ int i; float f; };
  93.542 +//     size_t fSize = OVR_SIZEOF_MEMBER(Test, f);
  93.543 +//
  93.544 +#if defined(OVR_CPP_NO_EXTENDED_SIZEOF)
  93.545 +    #define OVR_SIZEOF_MEMBER(class_, member_) (sizeof(((class_*)0)->member_))
  93.546 +#else
  93.547 +    #define OVR_SIZEOF_MEMBER(class_, member_) (sizeof(class_::member_))
  93.548 +#endif
  93.549 +
  93.550 +
  93.551 +//-----------------------------------------------------------------------------------
  93.552 +// ***** OVR_DEBUG_BREAK, OVR_DEBUG_CODE, 
  93.553 +//       OVR_ASSERT, OVR_ASSERT_M, OVR_ASSERT_AND_UNUSED
  93.554 +//
  93.555 +// Macros have effect only in debug builds.
  93.556 +//
  93.557 +// Example OVR_DEBUG_BREAK usage (note the lack of parentheses):
  93.558 +//     #define MY_ASSERT(expression) do { if (!(expression)) { OVR_DEBUG_BREAK; } } while(0)
  93.559 +//
  93.560 +// Example OVR_DEBUG_CODE usage:
  93.561 +//     OVR_DEBUG_CODE(printf("debug test\n");)
  93.562 +//       or
  93.563 +//     OVR_DEBUG_CODE(printf("debug test\n"));
  93.564 +//
  93.565 +// Example OVR_ASSERT usage:
  93.566 +//     OVR_ASSERT(count < 100);
  93.567 +//     OVR_ASSERT_M(count < 100, "count is too high");
  93.568 +//
  93.569 +#if defined(OVR_BUILD_DEBUG)
  93.570 +	// Causes a debugger breakpoint in debug builds. Has no effect in release builds.
  93.571 +	// Microsoft Win32 specific debugging support
  93.572 +	#if defined(OVR_CC_MSVC)
  93.573 +		#define OVR_DEBUG_BREAK __debugbreak()
  93.574 +	#elif defined(OVR_CC_GNU) || defined(OVR_CC_CLANG)
  93.575 +		#if defined(OVR_CPU_X86) || defined(OVR_CPU_X86_64)
  93.576 +			#define OVR_DEBUG_BREAK do { OVR_ASM("int $3\n\t"); } while(0)
  93.577 +		#else
  93.578 +			#define OVR_DEBUG_BREAK __builtin_trap()
  93.579 +		#endif
  93.580 +	#else
  93.581 +		#define OVR_DEBUG_BREAK do { *((int *) 0) = 1; } while(0)
  93.582 +	#endif
  93.583 +
  93.584 +	// The expresssion is defined only in debug builds. It is defined away in release builds.
  93.585 +	#define OVR_DEBUG_CODE(c) c
  93.586 +
  93.587 +	// In debug builds this tests the given expression; if false then executes OVR_DEBUG_BREAK,
  93.588 +	// if true then no action. Has no effect in release builds.
  93.589 +	#if defined(__clang_analyzer__) // During static analysis, make it so the analyzer thinks that failed asserts result in program exit. Reduced false positives.
  93.590 +		#include <stdlib.h>
  93.591 +		#define OVR_ASSERT_M(p, message) do { if (!(p))  { OVR_DEBUG_BREAK; exit(0); } } while(0)
  93.592 +		#define OVR_ASSERT(p)            do { if (!(p))  { OVR_DEBUG_BREAK; exit(0); } } while(0)
  93.593 +	#else
  93.594 +		// void OVR_ASSERT_M(bool expression, const char message);
  93.595 +		// Note: The expresion below is expanded into all usage of this assertion macro. 
  93.596 +		// We should try to minimize the size of the expanded code to the extent possible.
  93.597 +		#define OVR_ASSERT_M(p, message) do                                                               \
  93.598 +		{                                                                                                 \
  93.599 +			if (!(p))                                                                                     \
  93.600 +			{                                                                                             \
  93.601 +				intptr_t ovrAssertUserParam;                                                              \
  93.602 +				OVRAssertionHandler ovrAssertUserHandler = OVR::GetAssertionHandler(&ovrAssertUserParam); \
  93.603 +																							              \
  93.604 +				if(ovrAssertUserHandler && !OVRIsDebuggerPresent())                                       \
  93.605 +				{                                                                                         \
  93.606 +					ovrAssertUserHandler(ovrAssertUserParam, "Assertion failure", message);               \
  93.607 +				}                                                                                         \
  93.608 +				else                                                                                      \
  93.609 +				{                                                                                         \
  93.610 +					OVR_DEBUG_BREAK;                                                                      \
  93.611 +				}                                                                                         \
  93.612 +			}                                                                                             \
  93.613 +		} while(0)
  93.614 +
  93.615 +		// void OVR_ASSERT(bool expression);
  93.616 +		#define OVR_ASSERT(p) OVR_ASSERT_M((p), (#p))
  93.617 +	#endif
  93.618 +
  93.619 +	// Acts the same as OVR_ASSERT in debug builds. Acts the same as OVR_UNUSED in release builds.
  93.620 +	// Example usage: OVR_ASSERT_AND_UNUSED(x < 30, x);
  93.621 +	#define OVR_ASSERT_AND_UNUSED(expression, value) OVR_ASSERT(expression); OVR_UNUSED(value)
  93.622 +
  93.623 +#else 
  93.624 +
  93.625 +	// The expresssion is defined only in debug builds. It is defined away in release builds.
  93.626 +	#define OVR_DEBUG_CODE(c)
  93.627 +
  93.628 +	// Causes a debugger breakpoint in debug builds. Has no effect in release builds.
  93.629 +	#define OVR_DEBUG_BREAK  ((void)0)
  93.630 +
  93.631 +	// In debug builds this tests the given expression; if false then executes OVR_DEBUG_BREAK,
  93.632 +	// if true then no action. Has no effect in release builds.
  93.633 +	#define OVR_ASSERT(p)      ((void)0)
  93.634 +	#define OVR_ASSERT_M(p, m) ((void)0)
  93.635 +
  93.636 +	// Acts the same as OVR_ASSERT in debug builds. Acts the same as OVR_UNUSED in release builds.
  93.637 +	// Example usage: OVR_ASSERT_AND_UNUSED(x < 30, x);
  93.638 +	#define OVR_ASSERT_AND_UNUSED(expression, value) OVR_UNUSED(value)
  93.639 +
  93.640 +#endif // OVR_BUILD_DEBUG
  93.641 +
  93.642 +
  93.643 +
  93.644 +// Assert handler
  93.645 +// The user of this library can override the default assertion handler and provide their own.
  93.646 +namespace OVR
  93.647 +{
  93.648 +    // The return value meaning is reserved for future definition and currently has no effect.
  93.649 +    typedef intptr_t (*OVRAssertionHandler)(intptr_t userParameter, const char* title, const char* message);
  93.650 +
  93.651 +    // Returns the current assertion handler.
  93.652 +    OVRAssertionHandler GetAssertionHandler(intptr_t* userParameter = NULL);
  93.653 +
  93.654 +    // Sets the current assertion handler.
  93.655 +    // The default assertion handler if none is set simply issues a debug break.
  93.656 +    // Example usage:
  93.657 +    //     intptr_t CustomAssertionHandler(intptr_t /*userParameter*/, const char* title, const char* message)) { 
  93.658 +    //         MessageBox(title, message);
  93.659 +    //         OVR_DEBUG_BREAK;
  93.660 +    //     }
  93.661 +    void SetAssertionHandler(OVRAssertionHandler assertionHandler, intptr_t userParameter = 0);
  93.662 +
  93.663 +    // Implements the default assertion handler.
  93.664 +    intptr_t DefaultAssertionHandler(intptr_t userParameter, const char* title, const char* message);
  93.665 +
  93.666 +    // Currently defined in OVR_DebugHelp.cpp
  93.667 +    bool OVRIsDebuggerPresent();
  93.668 +}
  93.669 +
  93.670 +
  93.671 +// ------------------------------------------------------------------------
  93.672 +// ***** static_assert
  93.673 +//
  93.674 +// Portable support for C++11 static_assert.
  93.675 +// Acts as if the following were declared:
  93.676 +//     void static_assert(bool const_expression, const char* msg);
  93.677 +//
  93.678 +// Example usage:
  93.679 +//     static_assert(sizeof(int32_t) == 4, "int32_t expected to be 4 bytes.");
  93.680 +
  93.681 +#if defined(OVR_CPP_NO_STATIC_ASSERT) // If the compiler doesn't provide it intrinsically...
  93.682 +    #if !defined(OVR_SA_UNUSED)
  93.683 +        #if defined(OVR_CC_GNU) || defined(OVR_CC_CLANG)
  93.684 +            #define OVR_SA_UNUSED __attribute__((unused))
  93.685 +        #else
  93.686 +            #define OVR_SA_UNUSED
  93.687 +        #endif
  93.688 +        #define OVR_SA_PASTE(a,b) a##b
  93.689 +        #define OVR_SA_HELP(a,b)  OVR_SA_PASTE(a,b)
  93.690 +    #endif
  93.691 +
  93.692 +    #if defined(__COUNTER__)
  93.693 +        #define static_assert(expression, msg) typedef char OVR_SA_HELP(compileTimeAssert, __COUNTER__) [((expression) != 0) ? 1 : -1] OVR_SA_UNUSED
  93.694 +    #else
  93.695 +        #define static_assert(expression, msg) typedef char OVR_SA_HELP(compileTimeAssert, __LINE__) [((expression) != 0) ? 1 : -1] OVR_SA_UNUSED
  93.696 +    #endif
  93.697 +#endif
  93.698 +
  93.699 +
  93.700 +// ------------------------------------------------------------------------
  93.701 +// ***** OVR_COMPILER_ASSERT
  93.702 +//
  93.703 +// Compile-time assert; produces compiler error if condition is false.
  93.704 +// The expression must be a compile-time constant expression.
  93.705 +// This macro is deprecated in favor of static_assert, which provides better
  93.706 +// compiler output and works in a broader range of contexts.
  93.707 +// 
  93.708 +// Example usage:
  93.709 +//     OVR_COMPILER_ASSERT(sizeof(int32_t == 4));
  93.710 +
  93.711 +#if !defined(OVR_COMPILER_ASSERT)
  93.712 +    #define OVR_COMPILER_ASSERT(expression)        static_assert(expression, #expression)
  93.713 +    #define OVR_COMPILER_ASSERT_M(expression, msg) static_assert(expression, msg)
  93.714 +#endif
  93.715 +
  93.716 +
  93.717 +// ***** OVR_PROCESSOR_PAUSE
  93.718 +//
  93.719 +// Yields the processor for other hyperthreads, usually for the purpose of implementing spins and spin locks. 
  93.720 +//
  93.721 +// Example usage:
  93.722 +//     while(!finished())
  93.723 +//         OVR_PROCESSOR_PAUSE();
  93.724 +
  93.725 +#if defined(OVR_CPU_X86) || defined(OVR_CPU_X86_64)
  93.726 +    #if defined(OVR_CC_GNU) || defined(OVR_CC_CLANG)
  93.727 +        #define OVR_PROCESSOR_PAUSE() asm volatile("pause" ::: "memory") // Consumes 38-40 clocks on current Intel x86 and x64 hardware.
  93.728 +    #elif defined(OVR_CC_MSVC)
  93.729 +        #include <emmintrin.h>
  93.730 +        #pragma intrinsic(_mm_pause) // Maps to asm pause.
  93.731 +        #define OVR_PROCESSOR_PAUSE _mm_pause
  93.732 +    #else
  93.733 +        #define OVR_PROCESSOR_PAUSE()
  93.734 +    #endif
  93.735 +#else
  93.736 +    #define OVR_PROCESSOR_PAUSE()
  93.737 +#endif
  93.738 +
  93.739 +
  93.740 +// ------------------------------------------------------------------------
  93.741 +// ***** OVR_ARRAY_COUNT
  93.742 +//
  93.743 +// Returns the element count of a C array. 
  93.744 +//
  93.745 +// Example usage:
  93.746 +//     float itemArray[16];
  93.747 +//     for(size_t i = 0; i < OVR_ARRAY_COUNT(itemArray); i++) { ... }
  93.748 +
  93.749 +#if defined(OVR_CPP_NO_CONSTEXPR)
  93.750 +    #ifndef OVR_ARRAY_COUNT
  93.751 +        #define OVR_ARRAY_COUNT(x) (sizeof(x) / sizeof(x[0]))
  93.752 +    #endif
  93.753 +#else
  93.754 +    // Smarter C++11 version which knows the difference between arrays and pointers. 
  93.755 +    template <typename T, size_t N>
  93.756 +    char (&OVRArrayCountHelper(T (&x)[N]))[N];
  93.757 +    #define OVR_ARRAY_COUNT(x) (sizeof(OVRArrayCountHelper(x)))
  93.758 +#endif
  93.759 +
  93.760 +
  93.761 +// ------------------------------------------------------------------------
  93.762 +// ***** OVR_CURRENT_FUNCTION
  93.763 +//
  93.764 +// Portable wrapper for __PRETTY_FUNCTION__, C99 __func__, __FUNCTION__.
  93.765 +// This represents the most expressive version available.
  93.766 +// Acts as if the following were declared:
  93.767 +//     static const char OVR_CURRENT_FUNCTION[] = "function-name";
  93.768 +//
  93.769 +// Example usage:
  93.770 +//     void Test() { printf("%s", OVR_CURRENT_FUNCTION); }
  93.771 +
  93.772 +#if defined(OVR_CC_GNU) || defined(OVR_CC_CLANG) || (defined(__ICC) && (__ICC >= 600)) // GCC, clang, Intel
  93.773 +    #define OVR_CURRENT_FUNCTION __PRETTY_FUNCTION__
  93.774 +#elif defined(__FUNCSIG__) // VC++
  93.775 +    #define OVR_CURRENT_FUNCTION __FUNCSIG__
  93.776 +#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901) // C99 compilers
  93.777 +    #define OVR_CURRENT_FUNCTION __func__
  93.778 +#else
  93.779 +    #define OVR_CURRENT_FUNCTION __FUNCTION__
  93.780 +#endif
  93.781 +
  93.782 +
  93.783 +//-----------------------------------------------------------------------------------
  93.784 +// ***** OVR_DEPRECATED / OVR_DEPRECATED_MSG
  93.785 +// 
  93.786 +// Portably annotates a function or struct as deprecated.
  93.787 +// Note that clang supports __deprecated_enum_msg, which may be useful to support.
  93.788 +//
  93.789 +// Example usage:
  93.790 +//    OVR_DEPRECATED void Test();       // Use on the function declaration, as opposed to definition.
  93.791 +//
  93.792 +//    struct OVR_DEPRECATED Test{ ... };
  93.793 +//
  93.794 +//    OVR_DEPRECATED_MSG("Test is deprecated")
  93.795 +//    void Test();
  93.796 +
  93.797 +#if !defined(OVR_DEPRECATED)
  93.798 +    #if defined(OVR_CC_MSVC) && (OVR_CC_VERSION > 1400) // VS2005+
  93.799 +        #define OVR_DEPRECATED          __declspec(deprecated)
  93.800 +        #define OVR_DEPRECATED_MSG(msg) __declspec(deprecated(msg))
  93.801 +    #elif defined(OVR_CC_CLANG) && OVR_CC_HAS_FEATURE(attribute_deprecated_with_message)
  93.802 +        #define OVR_DEPRECATED          __declspec(deprecated)
  93.803 +        #define OVR_DEPRECATED_MSG(msg) __attribute__((deprecated(msg)))
  93.804 +    #elif defined(OVR_CC_GNU) && (OVR_CC_VERSION >= 405)
  93.805 +        #define OVR_DEPRECATED          __declspec(deprecated)
  93.806 +        #define OVR_DEPRECATED_MSG(msg) __attribute__((deprecated(msg)))
  93.807 +    #elif !defined(OVR_CC_MSVC)
  93.808 +        #define OVR_DEPRECATED          __attribute__((deprecated))
  93.809 +        #define OVR_DEPRECATED_MSG(msg) __attribute__((deprecated))
  93.810 +    #else
  93.811 +        #define OVR_DEPRECATED
  93.812 +        #define OVR_DEPRECATED_MSG(msg)
  93.813 +    #endif
  93.814 +#endif
  93.815 +
  93.816 +
  93.817 +//-----------------------------------------------------------------------------------
  93.818 +// ***** OVR_UNUSED - Unused Argument handling
  93.819 +// Macro to quiet compiler warnings about unused parameters/variables.
  93.820 +//
  93.821 +// Example usage:
  93.822 +//     void Test() {
  93.823 +//         int x = SomeFunction();
  93.824 +//         OVR_UNUSED(x);
  93.825 +//     }
  93.826 +//
  93.827 +
  93.828 +#if defined(OVR_CC_GNU)
  93.829 +#  define   OVR_UNUSED(a)   do {__typeof__ (&a) __attribute__ ((unused)) __tmp = &a; } while(0)
  93.830 +#else
  93.831 +#  define   OVR_UNUSED(a)   (a)
  93.832 +#endif
  93.833 +
  93.834 +#define     OVR_UNUSED1(a1) OVR_UNUSED(a1)
  93.835 +#define     OVR_UNUSED2(a1,a2) OVR_UNUSED(a1); OVR_UNUSED(a2)
  93.836 +#define     OVR_UNUSED3(a1,a2,a3) OVR_UNUSED2(a1,a2); OVR_UNUSED(a3)
  93.837 +#define     OVR_UNUSED4(a1,a2,a3,a4) OVR_UNUSED3(a1,a2,a3); OVR_UNUSED(a4)
  93.838 +#define     OVR_UNUSED5(a1,a2,a3,a4,a5) OVR_UNUSED4(a1,a2,a3,a4); OVR_UNUSED(a5)
  93.839 +#define     OVR_UNUSED6(a1,a2,a3,a4,a5,a6) OVR_UNUSED4(a1,a2,a3,a4); OVR_UNUSED2(a5,a6)
  93.840 +#define     OVR_UNUSED7(a1,a2,a3,a4,a5,a6,a7) OVR_UNUSED4(a1,a2,a3,a4); OVR_UNUSED3(a5,a6,a7)
  93.841 +#define     OVR_UNUSED8(a1,a2,a3,a4,a5,a6,a7,a8) OVR_UNUSED4(a1,a2,a3,a4); OVR_UNUSED4(a5,a6,a7,a8)
  93.842 +#define     OVR_UNUSED9(a1,a2,a3,a4,a5,a6,a7,a8,a9) OVR_UNUSED4(a1,a2,a3,a4); OVR_UNUSED5(a5,a6,a7,a8,a9)
  93.843 +
  93.844 +
  93.845 +//-----------------------------------------------------------------------------------
  93.846 +// ***** Configuration Macros
  93.847 +//
  93.848 +// Expands to the current build type as a const char string literal.
  93.849 +// Acts as the following declaration: const char OVR_BUILD_STRING[];
  93.850 +
  93.851 +#ifdef OVR_BUILD_DEBUG
  93.852 +#  define OVR_BUILD_STRING  "Debug"
  93.853 +#else
  93.854 +#  define OVR_BUILD_STRING  "Release"
  93.855 +#endif
  93.856 +
  93.857 +
  93.858 +//// Enables SF Debugging information
  93.859 +//# define OVR_BUILD_DEBUG
  93.860 +
  93.861 +// OVR_DEBUG_STATEMENT injects a statement only in debug builds.
  93.862 +// OVR_DEBUG_SELECT injects first argument in debug builds, second argument otherwise.
  93.863 +#ifdef OVR_BUILD_DEBUG
  93.864 +#define OVR_DEBUG_STATEMENT(s)   s
  93.865 +#define OVR_DEBUG_SELECT(d, nd)  d
  93.866 +#else
  93.867 +#define OVR_DEBUG_STATEMENT(s)
  93.868 +#define OVR_DEBUG_SELECT(d, nd)  nd
  93.869 +#endif
  93.870 +
  93.871 +
  93.872 +#define OVR_ENABLE_THREADS
  93.873 +//
  93.874 +// Prevents OVR from defining new within
  93.875 +// type macros, so developers can override
  93.876 +// new using the #define new new(...) trick
  93.877 +// - used with OVR_DEFINE_NEW macro
  93.878 +//# define OVR_BUILD_DEFINE_NEW
  93.879 +//
  93.880 +
  93.881 +
  93.882 +//-----------------------------------------------------------------------------------
  93.883 +// ***** Find normal allocations
  93.884 +//
  93.885 +// Our allocations are all supposed to go through the OVR System Allocator, so that
  93.886 +// they can be run through a game's own preferred allocator.  Occasionally we will
  93.887 +// accidentally introduce new code that doesn't adhere to this contract.  And it
  93.888 +// then becomes difficult to track down these normal allocations.  This piece of
  93.889 +// code makes it easy to check for normal allocations by asserting whenever they
  93.890 +// happen in our code.
  93.891 +
  93.892 +//#define OVR_FIND_NORMAL_ALLOCATIONS
  93.893 +#ifdef OVR_FIND_NORMAL_ALLOCATIONS
  93.894 +
  93.895 +inline void* operator new (size_t size, const char* filename, int line)
  93.896 +{
  93.897 +    void* ptr = new char[size];
  93.898 +    OVR_ASSERT(false);
  93.899 +    return ptr;
  93.900 +}
  93.901 +
  93.902 +#define new new(__FILE__, __LINE__)
  93.903 +
  93.904 +#endif // OVR_FIND_NORMAL_ALLOCATIONS
  93.905 +
  93.906 +
  93.907 +#include "OVR_Nullptr.h"
  93.908 +
  93.909 +
  93.910 +
  93.911 +
  93.912 +#endif  // OVR_Types_h
    94.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    94.2 +++ b/LibOVR/Src/Kernel/OVR_UTF8Util.cpp	Wed Jan 14 06:51:16 2015 +0200
    94.3 @@ -0,0 +1,556 @@
    94.4 +/**************************************************************************
    94.5 +
    94.6 +Filename    :   OVR_UTF8Util.cpp
    94.7 +Content     :   UTF8 Unicode character encoding/decoding support
    94.8 +Created     :   September 19, 2012
    94.9 +Notes       : 
   94.10 +Notes       :   Much useful info at "UTF-8 and Unicode FAQ"
   94.11 +                http://www.cl.cam.ac.uk/~mgk25/unicode.html
   94.12 +
   94.13 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   94.14 +
   94.15 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
   94.16 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
   94.17 +which is provided at the time of installation or download, or which 
   94.18 +otherwise accompanies this software in either electronic or hard copy form.
   94.19 +
   94.20 +You may obtain a copy of the License at
   94.21 +
   94.22 +http://www.oculusvr.com/licenses/LICENSE-3.2 
   94.23 +
   94.24 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
   94.25 +distributed under the License is distributed on an "AS IS" BASIS,
   94.26 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   94.27 +See the License for the specific language governing permissions and
   94.28 +limitations under the License.
   94.29 +
   94.30 +************************************************************************************/
   94.31 +
   94.32 +#include "OVR_UTF8Util.h"
   94.33 +
   94.34 +namespace OVR { namespace UTF8Util {
   94.35 +
   94.36 +intptr_t OVR_STDCALL GetLength(const char* buf, intptr_t buflen)
   94.37 +{
   94.38 +    const char* p = buf;
   94.39 +    intptr_t length = 0;
   94.40 +
   94.41 +    if (buflen != -1)
   94.42 +    {
   94.43 +        while (p - buf < buflen)
   94.44 +        {
   94.45 +            // We should be able to have ASStrings with 0 in the middle.
   94.46 +            UTF8Util::DecodeNextChar_Advance0(&p);
   94.47 +            length++;
   94.48 +        }
   94.49 +    }
   94.50 +    else
   94.51 +    {
   94.52 +        while (UTF8Util::DecodeNextChar_Advance0(&p))
   94.53 +            length++;
   94.54 +    }
   94.55 +    
   94.56 +    return length;
   94.57 +}
   94.58 +
   94.59 +uint32_t OVR_STDCALL GetCharAt(intptr_t index, const char* putf8str, intptr_t length)
   94.60 +{
   94.61 +    const char* buf = putf8str;
   94.62 +    uint32_t  c = 0;
   94.63 +
   94.64 +    if (length != -1)
   94.65 +    {
   94.66 +        while (buf - putf8str < length)
   94.67 +        {           
   94.68 +            c = UTF8Util::DecodeNextChar_Advance0(&buf);
   94.69 +            if (index == 0)
   94.70 +                return c;
   94.71 +            index--;
   94.72 +        }
   94.73 +
   94.74 +        return c;
   94.75 +    }
   94.76 +
   94.77 +    do 
   94.78 +    {
   94.79 +        c = UTF8Util::DecodeNextChar_Advance0(&buf);
   94.80 +        index--;
   94.81 +
   94.82 +        if (c == 0)
   94.83 +        {
   94.84 +            // We've hit the end of the string; don't go further.
   94.85 +            OVR_ASSERT(index == 0);
   94.86 +            return c;
   94.87 +        }
   94.88 +    } while (index >= 0);
   94.89 +
   94.90 +    return c;
   94.91 +}
   94.92 +
   94.93 +intptr_t OVR_STDCALL GetByteIndex(intptr_t index, const char *putf8str, intptr_t length)
   94.94 +{
   94.95 +    const char* buf = putf8str;
   94.96 +
   94.97 +    if (length != -1)
   94.98 +    {
   94.99 +        while ((buf - putf8str) < length && index > 0)
  94.100 +        {
  94.101 +            UTF8Util::DecodeNextChar_Advance0(&buf);
  94.102 +            index--;
  94.103 +        }
  94.104 +
  94.105 +        return buf-putf8str;
  94.106 +    }
  94.107 +
  94.108 +    while (index > 0) 
  94.109 +    {
  94.110 +        uint32_t c = UTF8Util::DecodeNextChar_Advance0(&buf);
  94.111 +        index--;
  94.112 +
  94.113 +        if (c == 0)
  94.114 +            return buf-putf8str;
  94.115 +    };
  94.116 +
  94.117 +    return buf-putf8str;
  94.118 +}
  94.119 +
  94.120 +int OVR_STDCALL GetEncodeCharSize(uint32_t ucs_character)
  94.121 +{
  94.122 +    if (ucs_character <= 0x7F)
  94.123 +        return 1;
  94.124 +    else if (ucs_character <= 0x7FF)
  94.125 +        return 2;
  94.126 +    else if (ucs_character <= 0xFFFF)
  94.127 +        return 3;
  94.128 +    else if (ucs_character <= 0x1FFFFF)
  94.129 +        return 4;
  94.130 +    else if (ucs_character <= 0x3FFFFFF)
  94.131 +        return 5;
  94.132 +    else if (ucs_character <= 0x7FFFFFFF)
  94.133 +        return 6;
  94.134 +    else
  94.135 +        return 0;
  94.136 +}
  94.137 +
  94.138 +uint32_t OVR_STDCALL DecodeNextChar_Advance0(const char** putf8Buffer)
  94.139 +{
  94.140 +    uint32_t  uc;
  94.141 +    char    c;
  94.142 +    
  94.143 +    // Security considerations:
  94.144 +    //
  94.145 +    // Changed, this is now only the case for DecodeNextChar:
  94.146 +    //  - If we hit a zero byte, we want to return 0 without stepping
  94.147 +    //    the buffer pointer past the 0. th
  94.148 +    //
  94.149 +    // If we hit an "overlong sequence"; i.e. a character encoded
  94.150 +    // in a longer multibyte string than is necessary, then we
  94.151 +    // need to discard the character.  This is so attackers can't
  94.152 +    // disguise dangerous characters or character sequences --
  94.153 +    // there is only one valid encoding for each character.
  94.154 +    //
  94.155 +    // If we decode characters { 0xD800 .. 0xDFFF } or { 0xFFFE,
  94.156 +    // 0xFFFF } then we ignore them; they are not valid in UTF-8.
  94.157 +    
  94.158 +    // This isn't actually an invalid character; it's a valid char that
  94.159 +    // looks like an inverted question mark.
  94.160 +#define INVALID_CHAR 0x0FFFD
  94.161 +    
  94.162 +#define FIRST_BYTE(mask, shift)     \
  94.163 +    uc = (c & (mask)) << (shift);
  94.164 +    
  94.165 +#define NEXT_BYTE(shift) \
  94.166 +    c = **putf8Buffer;   \
  94.167 +    if (c == 0) return 0; /* end of buffer, do not advance */   \
  94.168 +    if ((c & 0xC0) != 0x80) return INVALID_CHAR; /* standard check */  \
  94.169 +    (*putf8Buffer)++;    \
  94.170 +    uc |= (c & 0x3F) << shift;
  94.171 +    
  94.172 +    c = **putf8Buffer;
  94.173 +    (*putf8Buffer)++;
  94.174 +    if (c == 0)
  94.175 +        return 0;   // End of buffer.
  94.176 +    
  94.177 +    if ((c & 0x80) == 0) return (uint32_t) c; // Conventional 7-bit ASCII.
  94.178 +    
  94.179 +    // Multi-byte sequences.
  94.180 +    if ((c & 0xE0) == 0xC0)
  94.181 +    {
  94.182 +        // Two-byte sequence.
  94.183 +        FIRST_BYTE(0x1F, 6);
  94.184 +        NEXT_BYTE(0);
  94.185 +        if (uc < 0x80) return INVALID_CHAR;  // overlong
  94.186 +        return uc;
  94.187 +    }
  94.188 +    else if ((c & 0xF0) == 0xE0)
  94.189 +    {
  94.190 +        // Three-byte sequence.
  94.191 +        FIRST_BYTE(0x0F, 12);
  94.192 +        NEXT_BYTE(6);
  94.193 +        NEXT_BYTE(0);
  94.194 +        if (uc < 0x800) return INVALID_CHAR; // overlong
  94.195 +        // Not valid ISO 10646, but Flash requires these to work
  94.196 +        // see AS3 test e15_5_3_2_3 for String.fromCharCode().charCodeAt(0)
  94.197 +        // if (uc >= 0x0D800 && uc <= 0x0DFFF) return INVALID_CHAR;
  94.198 +        // if (uc == 0x0FFFE || uc == 0x0FFFF) return INVALID_CHAR; // not valid ISO 10646
  94.199 +        return uc;
  94.200 +    }
  94.201 +    else if ((c & 0xF8) == 0xF0)
  94.202 +    {
  94.203 +        // Four-byte sequence.
  94.204 +        FIRST_BYTE(0x07, 18);
  94.205 +        NEXT_BYTE(12);
  94.206 +        NEXT_BYTE(6);
  94.207 +        NEXT_BYTE(0);
  94.208 +        if (uc < 0x010000) return INVALID_CHAR;  // overlong
  94.209 +        return uc;
  94.210 +    }
  94.211 +    else if ((c & 0xFC) == 0xF8)
  94.212 +    {
  94.213 +        // Five-byte sequence.
  94.214 +        FIRST_BYTE(0x03, 24);
  94.215 +        NEXT_BYTE(18);
  94.216 +        NEXT_BYTE(12);
  94.217 +        NEXT_BYTE(6);
  94.218 +        NEXT_BYTE(0);
  94.219 +        if (uc < 0x0200000) return INVALID_CHAR; // overlong
  94.220 +        return uc;
  94.221 +    }
  94.222 +    else if ((c & 0xFE) == 0xFC)
  94.223 +    {
  94.224 +        // Six-byte sequence.
  94.225 +        FIRST_BYTE(0x01, 30);
  94.226 +        NEXT_BYTE(24);
  94.227 +        NEXT_BYTE(18);
  94.228 +        NEXT_BYTE(12);
  94.229 +        NEXT_BYTE(6);
  94.230 +        NEXT_BYTE(0);
  94.231 +        if (uc < 0x04000000) return INVALID_CHAR;    // overlong
  94.232 +        return uc;
  94.233 +    }
  94.234 +    else
  94.235 +    {
  94.236 +        // Invalid.
  94.237 +        return INVALID_CHAR;
  94.238 +    }
  94.239 +}
  94.240 +
  94.241 +
  94.242 +void OVR_STDCALL EncodeChar(char* pbuffer, intptr_t* pindex, uint32_t ucs_character)
  94.243 +{
  94.244 +    if (ucs_character <= 0x7F)
  94.245 +    {
  94.246 +        // Plain single-byte ASCII.
  94.247 +        pbuffer[(*pindex)++] = (char) ucs_character;
  94.248 +    }
  94.249 +    else if (ucs_character <= 0x7FF)
  94.250 +    {
  94.251 +        // Two bytes.
  94.252 +        pbuffer[(*pindex)++] = 0xC0 | (char)(ucs_character >> 6);
  94.253 +        pbuffer[(*pindex)++] = 0x80 | (char)((ucs_character >> 0) & 0x3F);
  94.254 +    }
  94.255 +    else if (ucs_character <= 0xFFFF)
  94.256 +    {
  94.257 +        // Three bytes.
  94.258 +        pbuffer[(*pindex)++] = 0xE0 | (char)(ucs_character >> 12);
  94.259 +        pbuffer[(*pindex)++] = 0x80 | (char)((ucs_character >> 6) & 0x3F);
  94.260 +        pbuffer[(*pindex)++] = 0x80 | (char)((ucs_character >> 0) & 0x3F);
  94.261 +    }
  94.262 +    else if (ucs_character <= 0x1FFFFF)
  94.263 +    {
  94.264 +        // Four bytes.
  94.265 +        pbuffer[(*pindex)++] = 0xF0 | (char)(ucs_character >> 18);
  94.266 +        pbuffer[(*pindex)++] = 0x80 | (char)((ucs_character >> 12) & 0x3F);
  94.267 +        pbuffer[(*pindex)++] = 0x80 | (char)((ucs_character >> 6) & 0x3F);
  94.268 +        pbuffer[(*pindex)++] = 0x80 | (char)((ucs_character >> 0) & 0x3F);
  94.269 +    }
  94.270 +    else if (ucs_character <= 0x3FFFFFF)
  94.271 +    {
  94.272 +        // Five bytes.
  94.273 +        pbuffer[(*pindex)++] = 0xF8 | (char)(ucs_character >> 24);
  94.274 +        pbuffer[(*pindex)++] = 0x80 | (char)((ucs_character >> 18) & 0x3F);
  94.275 +        pbuffer[(*pindex)++] = 0x80 | (char)((ucs_character >> 12) & 0x3F);
  94.276 +        pbuffer[(*pindex)++] = 0x80 | (char)((ucs_character >> 6) & 0x3F);
  94.277 +        pbuffer[(*pindex)++] = 0x80 | (char)((ucs_character >> 0) & 0x3F);
  94.278 +    }
  94.279 +    else if (ucs_character <= 0x7FFFFFFF)
  94.280 +    {
  94.281 +        // Six bytes.
  94.282 +        pbuffer[(*pindex)++] = 0xFC | (char)(ucs_character >> 30);
  94.283 +        pbuffer[(*pindex)++] = 0x80 | (char)((ucs_character >> 24) & 0x3F);
  94.284 +        pbuffer[(*pindex)++] = 0x80 | (char)((ucs_character >> 18) & 0x3F);
  94.285 +        pbuffer[(*pindex)++] = 0x80 | (char)((ucs_character >> 12) & 0x3F);
  94.286 +        pbuffer[(*pindex)++] = 0x80 | (char)((ucs_character >> 6) & 0x3F);
  94.287 +        pbuffer[(*pindex)++] = 0x80 | (char)((ucs_character >> 0) & 0x3F);
  94.288 +    }
  94.289 +    else
  94.290 +    {
  94.291 +        // Invalid char; don't encode anything.
  94.292 +    }
  94.293 +}
  94.294 +
  94.295 +intptr_t OVR_STDCALL GetEncodeStringSize(const wchar_t* pchar, intptr_t length)
  94.296 +{
  94.297 +    intptr_t len = 0;
  94.298 +    if (length != -1)
  94.299 +        for (int i = 0; i < length; i++)
  94.300 +        {
  94.301 +            len += GetEncodeCharSize(pchar[i]);
  94.302 +        }
  94.303 +    else
  94.304 +        for (int i = 0;; i++)
  94.305 +        {
  94.306 +            if (pchar[i] == 0)
  94.307 +                return len;
  94.308 +            len += GetEncodeCharSize(pchar[i]);
  94.309 +        }
  94.310 +    return len;
  94.311 +}
  94.312 +
  94.313 +void OVR_STDCALL EncodeString(char *pbuff, const wchar_t* pchar, intptr_t length)
  94.314 +{
  94.315 +    intptr_t ofs = 0;
  94.316 +    if (length != -1)
  94.317 +    {
  94.318 +        for (int i = 0; i < length; i++)
  94.319 +        {            
  94.320 +            EncodeChar(pbuff, &ofs, pchar[i]);
  94.321 +        }
  94.322 +    }
  94.323 +    else
  94.324 +    {
  94.325 +        for (int i = 0;; i++)
  94.326 +        {
  94.327 +            if (pchar[i] == 0)
  94.328 +                break;
  94.329 +            EncodeChar(pbuff, &ofs, pchar[i]);
  94.330 +        }
  94.331 +    }
  94.332 +    pbuff[ofs] = 0;
  94.333 +}
  94.334 +
  94.335 +size_t OVR_STDCALL DecodeString(wchar_t *pbuff, const char* putf8str, intptr_t bytesLen)
  94.336 +{
  94.337 +    wchar_t *pbegin = pbuff;
  94.338 +    if (bytesLen == -1)
  94.339 +    {
  94.340 +        while (1)
  94.341 +        {
  94.342 +            uint32_t ch = DecodeNextChar_Advance0(&putf8str);
  94.343 +            if (ch == 0)
  94.344 +                break;
  94.345 +            else if (ch >= 0xFFFF)
  94.346 +                ch = 0xFFFD;
  94.347 +            *pbuff++ = wchar_t(ch);
  94.348 +        }
  94.349 +    }
  94.350 +    else
  94.351 +    {
  94.352 +        const char* p = putf8str;
  94.353 +        while ((p - putf8str) < bytesLen)
  94.354 +        {
  94.355 +            uint32_t ch = DecodeNextChar_Advance0(&p);
  94.356 +            if (ch >= 0xFFFF)
  94.357 +                ch = 0xFFFD;
  94.358 +            *pbuff++ = wchar_t(ch);
  94.359 +        }
  94.360 +    }
  94.361 +
  94.362 +    *pbuff = 0;
  94.363 +    return pbuff - pbegin;
  94.364 +}
  94.365 +
  94.366 +
  94.367 +#ifdef UTF8_UNIT_TEST
  94.368 +
  94.369 +// Compile this test case with something like:
  94.370 +//
  94.371 +// gcc utf8.cpp -g -I.. -DUTF8_UNIT_TEST -lstdc++ -o utf8_test
  94.372 +//
  94.373 +//    or
  94.374 +//
  94.375 +// cl utf8.cpp -Zi -Od -DUTF8_UNIT_TEST -I..
  94.376 +//
  94.377 +// If possible, try running the test program with the first arg
  94.378 +// pointing at the file:
  94.379 +//
  94.380 +// http://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt
  94.381 +// 
  94.382 +// and examine the results by eye to make sure they are acceptable to
  94.383 +// you.
  94.384 +
  94.385 +
  94.386 +#include "base/utility.h"
  94.387 +#include <stdio.h>
  94.388 +
  94.389 +
  94.390 +bool    check_equal(const char* utf8_in, const uint32_t* ucs_in)
  94.391 +{
  94.392 +    for (;;)
  94.393 +    {
  94.394 +        uint32_t  next_ucs = *ucs_in++;
  94.395 +        uint32_t  next_ucs_from_utf8 = utf8::decode_next_unicode_character(&utf8_in);
  94.396 +        if (next_ucs != next_ucs_from_utf8)
  94.397 +        {
  94.398 +            return false;
  94.399 +        }
  94.400 +        if (next_ucs == 0)
  94.401 +        {
  94.402 +            OVR_ASSERT(next_ucs_from_utf8 == 0);
  94.403 +            break;
  94.404 +        }
  94.405 +    }
  94.406 +    
  94.407 +    return true;
  94.408 +}
  94.409 +
  94.410 +
  94.411 +void    log_ascii(const char* line)
  94.412 +{
  94.413 +    for (;;)
  94.414 +    {
  94.415 +        unsigned char   c = (unsigned char) *line++;
  94.416 +        if (c == 0)
  94.417 +        {
  94.418 +            // End of line.
  94.419 +            return;
  94.420 +        }
  94.421 +        else if (c != '\n'
  94.422 +            && (c < 32 || c > 127))
  94.423 +        {
  94.424 +            // Non-printable as plain ASCII.
  94.425 +            printf("<0x%02X>", (int) c);
  94.426 +        }
  94.427 +        else
  94.428 +        {
  94.429 +            printf("%c", c);
  94.430 +        }
  94.431 +    }
  94.432 +}
  94.433 +
  94.434 +
  94.435 +void    log_ucs(const uint32_t* line)
  94.436 +{
  94.437 +    for (;;)
  94.438 +    {
  94.439 +        uint32_t  uc = *line++;
  94.440 +        if (uc == 0)
  94.441 +        {
  94.442 +            // End of line.
  94.443 +            return;
  94.444 +        }
  94.445 +        else if (uc != '\n'
  94.446 +            && (uc < 32 || uc > 127))
  94.447 +        {
  94.448 +            // Non-printable as plain ASCII.
  94.449 +            printf("<U-%04X>", uc);
  94.450 +        }
  94.451 +        else
  94.452 +        {
  94.453 +            printf("%c", (char) uc);
  94.454 +        }
  94.455 +    }
  94.456 +}
  94.457 +
  94.458 +
  94.459 +// Simple canned test.
  94.460 +int main(int argc, const char* argv[])
  94.461 +{
  94.462 +    {
  94.463 +        const char* test8 = "Ignacio Castaño";
  94.464 +        const uint32_t  test32[] =
  94.465 +        {
  94.466 +            0x49, 0x67, 0x6E, 0x61, 0x63,
  94.467 +                0x69, 0x6F, 0x20, 0x43, 0x61,
  94.468 +                0x73, 0x74, 0x61, 0xF1, 0x6F,
  94.469 +                0x00
  94.470 +        };
  94.471 +        
  94.472 +        OVR_ASSERT(check_equal(test8, test32));
  94.473 +    }
  94.474 +        
  94.475 +        // If user passed an arg, try reading the file as UTF-8 encoded text.
  94.476 +        if (argc > 1)
  94.477 +        {
  94.478 +            const char* filename = argv[1];
  94.479 +            FILE*   fp = fopen(filename, "rb");
  94.480 +            if (fp == NULL)
  94.481 +            {
  94.482 +                printf("Can't open file '%s'\n", filename);
  94.483 +                return 1;
  94.484 +            }
  94.485 +            
  94.486 +            // Read lines from the file, encode/decode them, and highlight discrepancies.
  94.487 +            const int LINE_SIZE = 200;  // max line size
  94.488 +            char    line_buffer_utf8[LINE_SIZE];
  94.489 +            char    reencoded_utf8[6 * LINE_SIZE];
  94.490 +            uint32_t  line_buffer_ucs[LINE_SIZE];
  94.491 +            
  94.492 +            int byte_counter = 0;
  94.493 +            for (;;)
  94.494 +            {
  94.495 +                int c = fgetc(fp);
  94.496 +                if (c == EOF)
  94.497 +                {
  94.498 +                    // Done.
  94.499 +                    break;
  94.500 +                }
  94.501 +                line_buffer_utf8[byte_counter++] = c;
  94.502 +                if (c == '\n' || byte_counter >= LINE_SIZE - 2)
  94.503 +                {
  94.504 +                    // End of line.  Process the line.
  94.505 +                    line_buffer_utf8[byte_counter++] = 0;   // terminate.
  94.506 +                    
  94.507 +                    // Decode into UCS.
  94.508 +                    const char* p = line_buffer_utf8;
  94.509 +                    uint32_t* q = line_buffer_ucs;
  94.510 +                    for (;;)
  94.511 +                    {
  94.512 +                        uint32_t  uc = UTF8Util::DecodeNextChar(&p);
  94.513 +                        *q++ = uc;
  94.514 +                        
  94.515 +                        OVR_ASSERT(q < line_buffer_ucs + LINE_SIZE);
  94.516 +                        OVR_ASSERT(p < line_buffer_utf8 + LINE_SIZE);
  94.517 +                        
  94.518 +                        if (uc == 0) break;
  94.519 +                    }
  94.520 +                    
  94.521 +                    // Encode back into UTF-8.
  94.522 +                    q = line_buffer_ucs;
  94.523 +                    int index = 0;
  94.524 +                    for (;;)
  94.525 +                    {
  94.526 +                        uint32_t  uc = *q++;
  94.527 +                        OVR_ASSERT(index < LINE_SIZE * 6 - 6);
  94.528 +                        int last_index = index;
  94.529 +                        UTF8Util::EncodeChar(reencoded_utf8, &index, uc);
  94.530 +                        OVR_ASSERT(index <= last_index + 6);
  94.531 +                        if (uc == 0) break;
  94.532 +                    }
  94.533 +                    
  94.534 +                    // This can be useful for debugging.
  94.535 +#if 0
  94.536 +                    // Show the UCS and the re-encoded UTF-8.
  94.537 +                    log_ucs(line_buffer_ucs);
  94.538 +                    log_ascii(reencoded_utf8);
  94.539 +#endif // 0
  94.540 +                    
  94.541 +                    OVR_ASSERT(check_equal(line_buffer_utf8, line_buffer_ucs));
  94.542 +                    OVR_ASSERT(check_equal(reencoded_utf8, line_buffer_ucs));
  94.543 +                    
  94.544 +                    // Start next line.
  94.545 +                    byte_counter = 0;
  94.546 +                }
  94.547 +            }
  94.548 +            
  94.549 +            fclose(fp);
  94.550 +        }
  94.551 +        
  94.552 +        return 0;
  94.553 +}
  94.554 +
  94.555 +
  94.556 +#endif // UTF8_UNIT_TEST
  94.557 +
  94.558 +}} // namespace UTF8Util::OVR
  94.559 +
    95.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    95.2 +++ b/LibOVR/Src/Kernel/OVR_UTF8Util.h	Wed Jan 14 06:51:16 2015 +0200
    95.3 @@ -0,0 +1,99 @@
    95.4 +/************************************************************************************
    95.5 +
    95.6 +PublicHeader:   OVR_Kernel.h
    95.7 +Filename    :   OVR_UTF8Util.h
    95.8 +Content     :   UTF8 Unicode character encoding/decoding support
    95.9 +Created     :   September 19, 2012
   95.10 +Notes       : 
   95.11 +
   95.12 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   95.13 +
   95.14 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
   95.15 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
   95.16 +which is provided at the time of installation or download, or which 
   95.17 +otherwise accompanies this software in either electronic or hard copy form.
   95.18 +
   95.19 +You may obtain a copy of the License at
   95.20 +
   95.21 +http://www.oculusvr.com/licenses/LICENSE-3.2 
   95.22 +
   95.23 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
   95.24 +distributed under the License is distributed on an "AS IS" BASIS,
   95.25 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   95.26 +See the License for the specific language governing permissions and
   95.27 +limitations under the License.
   95.28 +
   95.29 +************************************************************************************/
   95.30 +
   95.31 +#ifndef OVR_UTF8Util_h
   95.32 +#define OVR_UTF8Util_h
   95.33 +
   95.34 +#include "OVR_Types.h"
   95.35 +
   95.36 +namespace OVR { namespace UTF8Util {
   95.37 +
   95.38 +//-----------------------------------------------------------------------------------
   95.39 +
   95.40 +// *** UTF8 string length and indexing.
   95.41 +
   95.42 +// Determines the length of UTF8 string in characters.
   95.43 +// If source length is specified (in bytes), null 0 character is counted properly.
   95.44 +intptr_t OVR_STDCALL GetLength(const char* putf8str, intptr_t length = -1);
   95.45 +
   95.46 +// Gets a decoded UTF8 character at index; you can access up to the index returned
   95.47 +// by GetLength. 0 will be returned for out of bounds access.
   95.48 +uint32_t OVR_STDCALL GetCharAt(intptr_t index, const char* putf8str, intptr_t length = -1);
   95.49 +
   95.50 +// Converts UTF8 character index into byte offset.
   95.51 +// -1 is returned if index was out of bounds.
   95.52 +intptr_t OVR_STDCALL GetByteIndex(intptr_t index, const char* putf8str, intptr_t length = -1);
   95.53 +
   95.54 +
   95.55 +// *** 16-bit Unicode string Encoding/Decoding routines.
   95.56 +
   95.57 +// Determines the number of bytes necessary to encode a string.
   95.58 +// Does not count the terminating 0 (null) character.
   95.59 +intptr_t OVR_STDCALL GetEncodeStringSize(const wchar_t* pchar, intptr_t length = -1);
   95.60 +
   95.61 +// Encodes a unicode (UCS-2 only) string into a buffer. The size of buffer must be at
   95.62 +// least GetEncodeStringSize() + 1.
   95.63 +void     OVR_STDCALL EncodeString(char *pbuff, const wchar_t* pchar, intptr_t length = -1);
   95.64 +
   95.65 +// Decode UTF8 into a wchar_t buffer. Must have GetLength()+1 characters available.
   95.66 +// Characters over 0xFFFF are replaced with 0xFFFD.
   95.67 +// Returns the length of resulting string (number of characters)
   95.68 +size_t   OVR_STDCALL DecodeString(wchar_t *pbuff, const char* putf8str, intptr_t bytesLen = -1);
   95.69 +
   95.70 +
   95.71 +// *** Individual character Encoding/Decoding.
   95.72 +
   95.73 +// Determined the number of bytes necessary to encode a UCS character.
   95.74 +int      OVR_STDCALL GetEncodeCharSize(uint32_t ucsCharacter);
   95.75 +
   95.76 +// Encodes the given UCS character into the given UTF-8 buffer.
   95.77 +// Writes the data starting at buffer[offset], and 
   95.78 +// increments offset by the number of bytes written.
   95.79 +// May write up to 6 bytes, so make sure there's room in the buffer
   95.80 +void     OVR_STDCALL EncodeChar(char* pbuffer, intptr_t* poffset, uint32_t ucsCharacter);
   95.81 +
   95.82 +// Return the next Unicode character in the UTF-8 encoded buffer.
   95.83 +// Invalid UTF-8 sequences produce a U+FFFD character as output.
   95.84 +// Advances *utf8_buffer past the character returned. Pointer advance
   95.85 +// occurs even if the terminating 0 character is hit, since that allows
   95.86 +// strings with middle '\0' characters to be supported.
   95.87 +uint32_t OVR_STDCALL DecodeNextChar_Advance0(const char** putf8Buffer);
   95.88 +
   95.89 +// Safer version of DecodeNextChar, which doesn't advance pointer if
   95.90 +// null character is hit.
   95.91 +inline uint32_t DecodeNextChar(const char** putf8Buffer)
   95.92 +{
   95.93 +    uint32_t ch = DecodeNextChar_Advance0(putf8Buffer);
   95.94 +    if (ch == 0)
   95.95 +        (*putf8Buffer)--;
   95.96 +    return ch;
   95.97 +}
   95.98 +
   95.99 +
  95.100 +}} // OVR::UTF8Util
  95.101 +
  95.102 +#endif
    96.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    96.2 +++ b/LibOVR/Src/Net/OVR_BitStream.cpp	Wed Jan 14 06:51:16 2015 +0200
    96.3 @@ -0,0 +1,1151 @@
    96.4 +/************************************************************************************
    96.5 +
    96.6 +Filename    :   OVR_BitStream.cpp
    96.7 +Content     :   A generic serialization toolkit for packing data to a binary stream.
    96.8 +Created     :   June 10, 2014
    96.9 +Authors     :   Kevin Jenkins
   96.10 +
   96.11 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   96.12 +
   96.13 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
   96.14 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
   96.15 +which is provided at the time of installation or download, or which 
   96.16 +otherwise accompanies this software in either electronic or hard copy form.
   96.17 +
   96.18 +You may obtain a copy of the License at
   96.19 +
   96.20 +http://www.oculusvr.com/licenses/LICENSE-3.2 
   96.21 +
   96.22 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
   96.23 +distributed under the License is distributed on an "AS IS" BASIS,
   96.24 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   96.25 +See the License for the specific language governing permissions and
   96.26 +limitations under the License.
   96.27 +
   96.28 +************************************************************************************/
   96.29 +
   96.30 +#include "OVR_BitStream.h"
   96.31 +
   96.32 +#ifdef OVR_OS_WIN32
   96.33 +#include <WinSock2.h>
   96.34 +#else
   96.35 +#include <arpa/inet.h>
   96.36 +#endif
   96.37 +
   96.38 +namespace OVR { namespace Net {
   96.39 +
   96.40 +
   96.41 +//-----------------------------------------------------------------------------
   96.42 +// BitStream
   96.43 +	
   96.44 +BitStream::BitStream()
   96.45 +{
   96.46 +	numberOfBitsUsed = 0;
   96.47 +	//numberOfBitsAllocated = 32 * 8;
   96.48 +	numberOfBitsAllocated = BITSTREAM_STACK_ALLOCATION_SIZE * 8;
   96.49 +	readOffset = 0;
   96.50 +	//data = ( unsigned char* ) OVR_ALLOC( 32);
   96.51 +	data = ( unsigned char* ) stackData;
   96.52 +
   96.53 +#ifdef _DEBUG	
   96.54 +	//	OVR_ASSERT( data );
   96.55 +#endif
   96.56 +	//memset(data, 0, 32);
   96.57 +	copyData = true;
   96.58 +}
   96.59 +
   96.60 +BitStream::BitStream( const unsigned int initialBytesToAllocate )
   96.61 +{
   96.62 +	numberOfBitsUsed = 0;
   96.63 +	readOffset = 0;
   96.64 +	if (initialBytesToAllocate <= BITSTREAM_STACK_ALLOCATION_SIZE)
   96.65 +	{
   96.66 +		data = ( unsigned char* ) stackData;
   96.67 +		numberOfBitsAllocated = BITSTREAM_STACK_ALLOCATION_SIZE * 8;
   96.68 +	}
   96.69 +	else
   96.70 +	{
   96.71 +		data = ( unsigned char* ) OVR_ALLOC( (size_t) initialBytesToAllocate);
   96.72 +		numberOfBitsAllocated = initialBytesToAllocate << 3;
   96.73 +	}
   96.74 +#ifdef _DEBUG
   96.75 +	OVR_ASSERT( data );
   96.76 +#endif
   96.77 +	// memset(data, 0, initialBytesToAllocate);
   96.78 +	copyData = true;
   96.79 +}
   96.80 +
   96.81 +BitStream::BitStream( char* _data, const unsigned int lengthInBytes, bool _copyData )
   96.82 +{
   96.83 +	numberOfBitsUsed = lengthInBytes << 3;
   96.84 +	readOffset = 0;
   96.85 +	copyData = _copyData;
   96.86 +	numberOfBitsAllocated = lengthInBytes << 3;
   96.87 +
   96.88 +	if ( copyData )
   96.89 +	{
   96.90 +		if ( lengthInBytes > 0 )
   96.91 +		{
   96.92 +			if (lengthInBytes < BITSTREAM_STACK_ALLOCATION_SIZE)
   96.93 +			{
   96.94 +				data = ( unsigned char* ) stackData;
   96.95 +				numberOfBitsAllocated = BITSTREAM_STACK_ALLOCATION_SIZE << 3;
   96.96 +			}
   96.97 +			else
   96.98 +			{
   96.99 +				data = ( unsigned char* ) OVR_ALLOC( (size_t) lengthInBytes);
  96.100 +			}
  96.101 +#ifdef _DEBUG
  96.102 +			OVR_ASSERT( data );
  96.103 +#endif
  96.104 +			memcpy( data, _data, (size_t) lengthInBytes );
  96.105 +		}
  96.106 +		else
  96.107 +			data = 0;
  96.108 +	}
  96.109 +	else
  96.110 +		data = ( unsigned char* ) _data;
  96.111 +}
  96.112 +
  96.113 +// Use this if you pass a pointer copy to the constructor (_copyData==false) and want to overallocate to prevent reallocation
  96.114 +void BitStream::SetNumberOfBitsAllocated( const BitSize_t lengthInBits )
  96.115 +{
  96.116 +#ifdef _DEBUG
  96.117 +	OVR_ASSERT( lengthInBits >= ( BitSize_t ) numberOfBitsAllocated );
  96.118 +#endif	
  96.119 +	numberOfBitsAllocated = lengthInBits;
  96.120 +}
  96.121 +
  96.122 +BitStream::~BitStream()
  96.123 +{
  96.124 +	if ( copyData && numberOfBitsAllocated > (BITSTREAM_STACK_ALLOCATION_SIZE << 3))
  96.125 +		OVR_FREE( data );  // Use realloc and free so we are more efficient than delete and new for resizing
  96.126 +}
  96.127 +
  96.128 +void BitStream::Reset( void )
  96.129 +{
  96.130 +	// Note:  Do NOT reallocate memory because BitStream is used
  96.131 +	// in places to serialize/deserialize a buffer. Reallocation
  96.132 +	// is a dangerous operation (may result in leaks).
  96.133 +
  96.134 +	if ( numberOfBitsUsed > 0 )
  96.135 +	{
  96.136 +		//  memset(data, 0, BITS_TO_BYTES(numberOfBitsUsed));
  96.137 +	}
  96.138 +
  96.139 +	// Don't free memory here for speed efficiency
  96.140 +	//free(data);  // Use realloc and free so we are more efficient than delete and new for resizing
  96.141 +	numberOfBitsUsed = 0;
  96.142 +
  96.143 +	//numberOfBitsAllocated=8;
  96.144 +	readOffset = 0;
  96.145 +
  96.146 +	//data=(unsigned char*)OVR_ALLOC(1, _FILE_AND_LINE_);
  96.147 +	// if (numberOfBitsAllocated>0)
  96.148 +	//  memset(data, 0, BITS_TO_BYTES(numberOfBitsAllocated));
  96.149 +}
  96.150 +
  96.151 +// Write an array or casted stream
  96.152 +void BitStream::Write( const char* inputByteArray, const unsigned int numberOfBytes )
  96.153 +{
  96.154 +	if (numberOfBytes==0)
  96.155 +		return;
  96.156 +
  96.157 +	// Optimization:
  96.158 +	if ((numberOfBitsUsed & 7) == 0)
  96.159 +	{
  96.160 +		AddBitsAndReallocate( BYTES_TO_BITS(numberOfBytes) );
  96.161 +		memcpy(data+BITS_TO_BYTES(numberOfBitsUsed), inputByteArray, (size_t) numberOfBytes);
  96.162 +		numberOfBitsUsed+=BYTES_TO_BITS(numberOfBytes);
  96.163 +	}
  96.164 +	else
  96.165 +	{
  96.166 +		WriteBits( ( unsigned char* ) inputByteArray, numberOfBytes * 8, true );
  96.167 +	}
  96.168 +
  96.169 +}
  96.170 +void BitStream::Write( BitStream *bitStream)
  96.171 +{
  96.172 +	Write(bitStream, bitStream->GetNumberOfBitsUsed()-bitStream->GetReadOffset());
  96.173 +}
  96.174 +void BitStream::Write( BitStream *bitStream, BitSize_t numberOfBits )
  96.175 +{
  96.176 +	AddBitsAndReallocate( numberOfBits );
  96.177 +	BitSize_t numberOfBitsMod8;
  96.178 +
  96.179 +	if ((bitStream->GetReadOffset()&7)==0 && (numberOfBitsUsed&7)==0)
  96.180 +	{
  96.181 +		int readOffsetBytes=bitStream->GetReadOffset()/8;
  96.182 +		int numBytes=numberOfBits/8;
  96.183 +		memcpy(data + (numberOfBitsUsed >> 3), bitStream->GetData()+readOffsetBytes, numBytes);
  96.184 +		numberOfBits-=BYTES_TO_BITS(numBytes);
  96.185 +		bitStream->SetReadOffset(BYTES_TO_BITS(numBytes+readOffsetBytes));
  96.186 +		numberOfBitsUsed+=BYTES_TO_BITS(numBytes);
  96.187 +	}
  96.188 +
  96.189 +	while (numberOfBits-->0 && bitStream->readOffset + 1 <= bitStream->numberOfBitsUsed)
  96.190 +	{
  96.191 +		numberOfBitsMod8 = numberOfBitsUsed & 7;
  96.192 +		if ( numberOfBitsMod8 == 0 )
  96.193 +		{
  96.194 +			// New byte
  96.195 +			if (bitStream->data[ bitStream->readOffset >> 3 ] & ( 0x80 >> ( bitStream->readOffset & 7 ) ) )
  96.196 +			{
  96.197 +				// Write 1
  96.198 +				data[ numberOfBitsUsed >> 3 ] = 0x80;
  96.199 +			}
  96.200 +			else
  96.201 +			{
  96.202 +				// Write 0
  96.203 +				data[ numberOfBitsUsed >> 3 ] = 0;
  96.204 +			}
  96.205 +
  96.206 +		}
  96.207 +		else
  96.208 +		{
  96.209 +			// Existing byte
  96.210 +			if (bitStream->data[ bitStream->readOffset >> 3 ] & ( 0x80 >> ( bitStream->readOffset & 7 ) ) )
  96.211 +				data[ numberOfBitsUsed >> 3 ] |= 0x80 >> ( numberOfBitsMod8 ); // Set the bit to 1
  96.212 +			// else 0, do nothing
  96.213 +		}
  96.214 +
  96.215 +		bitStream->readOffset++;
  96.216 +		numberOfBitsUsed++;
  96.217 +	}
  96.218 +}
  96.219 +void BitStream::Write( BitStream &bitStream, BitSize_t numberOfBits )
  96.220 +{
  96.221 +	Write(&bitStream, numberOfBits);
  96.222 +}
  96.223 +void BitStream::Write( BitStream &bitStream )
  96.224 +{
  96.225 +	Write(&bitStream);
  96.226 +}
  96.227 +bool BitStream::Read( BitStream *bitStream, BitSize_t numberOfBits )
  96.228 +{
  96.229 +	if (GetNumberOfUnreadBits() < numberOfBits)
  96.230 +		return false;
  96.231 +	bitStream->Write(this, numberOfBits);
  96.232 +	return true;
  96.233 +}
  96.234 +bool BitStream::Read( BitStream *bitStream )
  96.235 +{
  96.236 +	bitStream->Write(this);
  96.237 +	return true;
  96.238 +}
  96.239 +bool BitStream::Read( BitStream &bitStream, BitSize_t numberOfBits )
  96.240 +{
  96.241 +	if (GetNumberOfUnreadBits() < numberOfBits)
  96.242 +		return false;
  96.243 +	bitStream.Write(this, numberOfBits);
  96.244 +	return true;
  96.245 +}
  96.246 +bool BitStream::Read( BitStream &bitStream )
  96.247 +{
  96.248 +	bitStream.Write(this);
  96.249 +	return true;
  96.250 +}
  96.251 +
  96.252 +// Read an array or casted stream
  96.253 +bool BitStream::Read( char* outByteArray, const unsigned int numberOfBytes )
  96.254 +{
  96.255 +	// Optimization:
  96.256 +	if ((readOffset & 7) == 0)
  96.257 +	{
  96.258 +		if ( readOffset + ( numberOfBytes << 3 ) > numberOfBitsUsed )
  96.259 +			return false;
  96.260 +
  96.261 +		// Write the data
  96.262 +		memcpy( outByteArray, data + ( readOffset >> 3 ), (size_t) numberOfBytes );
  96.263 +
  96.264 +		readOffset += numberOfBytes << 3;
  96.265 +		return true;
  96.266 +	}
  96.267 +	else
  96.268 +	{
  96.269 +		return ReadBits( ( unsigned char* ) outByteArray, numberOfBytes * 8 );
  96.270 +	}
  96.271 +}
  96.272 +
  96.273 +// Sets the read pointer back to the beginning of your data.
  96.274 +void BitStream::ResetReadPointer( void )
  96.275 +{
  96.276 +	readOffset = 0;
  96.277 +}
  96.278 +
  96.279 +// Sets the write pointer back to the beginning of your data.
  96.280 +void BitStream::ResetWritePointer( void )
  96.281 +{
  96.282 +	numberOfBitsUsed = 0;
  96.283 +}
  96.284 +
  96.285 +// Write a 0
  96.286 +void BitStream::Write0( void )
  96.287 +{
  96.288 +	AddBitsAndReallocate( 1 );
  96.289 +
  96.290 +	// New bytes need to be zeroed
  96.291 +	if ( ( numberOfBitsUsed & 7 ) == 0 )
  96.292 +		data[ numberOfBitsUsed >> 3 ] = 0;
  96.293 +
  96.294 +	numberOfBitsUsed++;
  96.295 +}
  96.296 +
  96.297 +// Write a 1
  96.298 +void BitStream::Write1( void )
  96.299 +{
  96.300 +	AddBitsAndReallocate( 1 );
  96.301 +
  96.302 +	BitSize_t numberOfBitsMod8 = numberOfBitsUsed & 7;
  96.303 +
  96.304 +	if ( numberOfBitsMod8 == 0 )
  96.305 +		data[ numberOfBitsUsed >> 3 ] = 0x80;
  96.306 +	else
  96.307 +		data[ numberOfBitsUsed >> 3 ] |= 0x80 >> ( numberOfBitsMod8 ); // Set the bit to 1
  96.308 +
  96.309 +	numberOfBitsUsed++;
  96.310 +}
  96.311 +
  96.312 +// Returns true if the next data read is a 1, false if it is a 0
  96.313 +bool BitStream::ReadBit( void )
  96.314 +{
  96.315 +	bool result = ( data[ readOffset >> 3 ] & ( 0x80 >> ( readOffset & 7 ) ) ) !=0;
  96.316 +	readOffset++;
  96.317 +	return result;
  96.318 +}
  96.319 +
  96.320 +// Align the bitstream to the byte boundary and then write the specified number of bits.
  96.321 +// This is faster than WriteBits but wastes the bits to do the alignment and requires you to call
  96.322 +// SetReadToByteAlignment at the corresponding read position
  96.323 +void BitStream::WriteAlignedBytes( const unsigned char* inByteArray, const unsigned int numberOfBytesToWrite )
  96.324 +{
  96.325 +	AlignWriteToByteBoundary();
  96.326 +	Write((const char*) inByteArray, numberOfBytesToWrite);
  96.327 +}
  96.328 +void BitStream::EndianSwapBytes( int byteOffset, int length )
  96.329 +{
  96.330 +	if (DoEndianSwap())
  96.331 +	{
  96.332 +		ReverseBytesInPlace(data+byteOffset, length);
  96.333 +	}
  96.334 +}
  96.335 +/// Aligns the bitstream, writes inputLength, and writes input. Won't write beyond maxBytesToWrite
  96.336 +void BitStream::WriteAlignedBytesSafe( const char *inByteArray, const unsigned int inputLength, const unsigned int maxBytesToWrite )
  96.337 +{
  96.338 +	if (inByteArray==0 || inputLength==0)
  96.339 +	{
  96.340 +		WriteCompressed((unsigned int)0);
  96.341 +		return;
  96.342 +	}
  96.343 +	WriteCompressed(inputLength);
  96.344 +	WriteAlignedBytes((const unsigned char*) inByteArray, inputLength < maxBytesToWrite ? inputLength : maxBytesToWrite);
  96.345 +}
  96.346 +
  96.347 +// Read bits, starting at the next aligned bits. Note that the modulus 8 starting offset of the
  96.348 +// sequence must be the same as was used with WriteBits. This will be a problem with packet coalescence
  96.349 +// unless you byte align the coalesced packets.
  96.350 +bool BitStream::ReadAlignedBytes( unsigned char* inOutByteArray, const unsigned int numberOfBytesToRead )
  96.351 +{
  96.352 +#ifdef _DEBUG
  96.353 +	OVR_ASSERT( numberOfBytesToRead > 0 );
  96.354 +#endif
  96.355 +
  96.356 +	if ( numberOfBytesToRead <= 0 )
  96.357 +		return false;
  96.358 +
  96.359 +	// Byte align
  96.360 +	AlignReadToByteBoundary();
  96.361 +
  96.362 +	if ( readOffset + ( numberOfBytesToRead << 3 ) > numberOfBitsUsed )
  96.363 +		return false;
  96.364 +
  96.365 +	// Write the data
  96.366 +	memcpy( inOutByteArray, data + ( readOffset >> 3 ), (size_t) numberOfBytesToRead );
  96.367 +
  96.368 +	readOffset += numberOfBytesToRead << 3;
  96.369 +
  96.370 +	return true;
  96.371 +}
  96.372 +bool BitStream::ReadAlignedBytesSafe( char *inOutByteArray, int &inputLength, const int maxBytesToRead )
  96.373 +{
  96.374 +	return ReadAlignedBytesSafe(inOutByteArray,(unsigned int&) inputLength,(unsigned int)maxBytesToRead);
  96.375 +}
  96.376 +bool BitStream::ReadAlignedBytesSafe( char *inOutByteArray, unsigned int &inputLength, const unsigned int maxBytesToRead )
  96.377 +{
  96.378 +	if (ReadCompressed(inputLength)==false)
  96.379 +		return false;
  96.380 +	if (inputLength > maxBytesToRead)
  96.381 +		inputLength=maxBytesToRead;
  96.382 +	if (inputLength==0)
  96.383 +		return true;
  96.384 +	return ReadAlignedBytes((unsigned char*) inOutByteArray, inputLength);
  96.385 +}
  96.386 +bool BitStream::ReadAlignedBytesSafeAlloc( char **outByteArray, int &inputLength, const unsigned int maxBytesToRead )
  96.387 +{
  96.388 +	return ReadAlignedBytesSafeAlloc(outByteArray,(unsigned int&) inputLength, maxBytesToRead);
  96.389 +}
  96.390 +bool BitStream::ReadAlignedBytesSafeAlloc( char ** outByteArray, unsigned int &inputLength, const unsigned int maxBytesToRead )
  96.391 +{
  96.392 +	OVR_FREE(*outByteArray);
  96.393 +	*outByteArray=0;
  96.394 +	if (ReadCompressed(inputLength)==false)
  96.395 +		return false;
  96.396 +	if (inputLength > maxBytesToRead)
  96.397 +		inputLength=maxBytesToRead;
  96.398 +	if (inputLength==0)
  96.399 +		return true;
  96.400 +	*outByteArray = (char*) OVR_ALLOC( (size_t) inputLength);
  96.401 +	return ReadAlignedBytes((unsigned char*) *outByteArray, inputLength);
  96.402 +}
  96.403 +
  96.404 +// Write numberToWrite bits from the input source
  96.405 +void BitStream::WriteBits( const unsigned char* inByteArray, BitSize_t numberOfBitsToWrite, const bool rightAlignedBits )
  96.406 +{
  96.407 +//	if (numberOfBitsToWrite<=0)
  96.408 +//		return;
  96.409 +
  96.410 +	AddBitsAndReallocate( numberOfBitsToWrite );
  96.411 +
  96.412 +	const BitSize_t numberOfBitsUsedMod8 = numberOfBitsUsed & 7;
  96.413 +
  96.414 +	// If currently aligned and numberOfBits is a multiple of 8, just memcpy for speed
  96.415 +	if (numberOfBitsUsedMod8==0 && (numberOfBitsToWrite&7)==0)
  96.416 +	{
  96.417 +		memcpy( data + ( numberOfBitsUsed >> 3 ), inByteArray, numberOfBitsToWrite>>3);
  96.418 +		numberOfBitsUsed+=numberOfBitsToWrite;
  96.419 +		return;
  96.420 +	}
  96.421 +
  96.422 +	unsigned char dataByte;
  96.423 +	const unsigned char* inputPtr=inByteArray;
  96.424 +
  96.425 +	// Faster to put the while at the top surprisingly enough
  96.426 +	while ( numberOfBitsToWrite > 0 )
  96.427 +		//do
  96.428 +	{
  96.429 +		dataByte = *( inputPtr++ );
  96.430 +
  96.431 +		if ( numberOfBitsToWrite < 8 && rightAlignedBits )   // rightAlignedBits means in the case of a partial byte, the bits are aligned from the right (bit 0) rather than the left (as in the normal internal representation)
  96.432 +			dataByte <<= 8 - numberOfBitsToWrite;  // shift left to get the bits on the left, as in our internal representation
  96.433 +
  96.434 +		// Writing to a new byte each time
  96.435 +		if ( numberOfBitsUsedMod8 == 0 )
  96.436 +			* ( data + ( numberOfBitsUsed >> 3 ) ) = dataByte;
  96.437 +		else
  96.438 +		{
  96.439 +			// Copy over the new data.
  96.440 +			*( data + ( numberOfBitsUsed >> 3 ) ) |= dataByte >> ( numberOfBitsUsedMod8 ); // First half
  96.441 +
  96.442 +			if ( 8 - ( numberOfBitsUsedMod8 ) < 8 && 8 - ( numberOfBitsUsedMod8 ) < numberOfBitsToWrite )   // If we didn't write it all out in the first half (8 - (numberOfBitsUsed%8) is the number we wrote in the first half)
  96.443 +			{
  96.444 +				*( data + ( numberOfBitsUsed >> 3 ) + 1 ) = (unsigned char) ( dataByte << ( 8 - ( numberOfBitsUsedMod8 ) ) ); // Second half (overlaps byte boundary)
  96.445 +			}
  96.446 +		}
  96.447 +
  96.448 +		if ( numberOfBitsToWrite >= 8 )
  96.449 +		{
  96.450 +			numberOfBitsUsed += 8;
  96.451 +			numberOfBitsToWrite -= 8;
  96.452 +		}
  96.453 +		else
  96.454 +		{
  96.455 +			numberOfBitsUsed += numberOfBitsToWrite;
  96.456 +			numberOfBitsToWrite=0;
  96.457 +		}
  96.458 +	}
  96.459 +	// } while(numberOfBitsToWrite>0);
  96.460 +}
  96.461 +
  96.462 +// Set the stream to some initial data.  For internal use
  96.463 +void BitStream::SetData( unsigned char *inByteArray )
  96.464 +{
  96.465 +	data=inByteArray;
  96.466 +	copyData=false;
  96.467 +}
  96.468 +
  96.469 +// Assume the input source points to a native type, compress and write it
  96.470 +void BitStream::WriteCompressed( const unsigned char* inByteArray,
  96.471 +								const unsigned int size, const bool unsignedData )
  96.472 +{
  96.473 +	BitSize_t currentByte = ( size >> 3 ) - 1; // PCs
  96.474 +
  96.475 +	unsigned char byteMatch;
  96.476 +
  96.477 +	if ( unsignedData )
  96.478 +	{
  96.479 +		byteMatch = 0;
  96.480 +	}
  96.481 +
  96.482 +	else
  96.483 +	{
  96.484 +		byteMatch = 0xFF;
  96.485 +	}
  96.486 +
  96.487 +	// Write upper bytes with a single 1
  96.488 +	// From high byte to low byte, if high byte is a byteMatch then write a 1 bit. Otherwise write a 0 bit and then write the remaining bytes
  96.489 +	while ( currentByte > 0 )
  96.490 +	{
  96.491 +		if ( inByteArray[ currentByte ] == byteMatch )   // If high byte is byteMatch (0 of 0xff) then it would have the same value shifted
  96.492 +		{
  96.493 +			bool b = true;
  96.494 +			Write( b );
  96.495 +		}
  96.496 +		else
  96.497 +		{
  96.498 +			// Write the remainder of the data after writing 0
  96.499 +			bool b = false;
  96.500 +			Write( b );
  96.501 +
  96.502 +			WriteBits( inByteArray, ( currentByte + 1 ) << 3, true );
  96.503 +			//  currentByte--;
  96.504 +
  96.505 +
  96.506 +			return ;
  96.507 +		}
  96.508 +
  96.509 +		currentByte--;
  96.510 +	}
  96.511 +
  96.512 +	// If the upper half of the last byte is a 0 (positive) or 16 (negative) then write a 1 and the remaining 4 bits.  Otherwise write a 0 and the 8 bites.
  96.513 +	if ( ( unsignedData && ( ( *( inByteArray + currentByte ) ) & 0xF0 ) == 0x00 ) ||
  96.514 +		( unsignedData == false && ( ( *( inByteArray + currentByte ) ) & 0xF0 ) == 0xF0 ) )
  96.515 +	{
  96.516 +		bool b = true;
  96.517 +		Write( b );
  96.518 +		WriteBits( inByteArray + currentByte, 4, true );
  96.519 +	}
  96.520 +
  96.521 +	else
  96.522 +	{
  96.523 +		bool b = false;
  96.524 +		Write( b );
  96.525 +		WriteBits( inByteArray + currentByte, 8, true );
  96.526 +	}
  96.527 +}
  96.528 +
  96.529 +// Read numberOfBitsToRead bits to the output source
  96.530 +// alignBitsToRight should be set to true to convert internal bitstream data to userdata
  96.531 +// It should be false if you used WriteBits with rightAlignedBits false
  96.532 +bool BitStream::ReadBits( unsigned char *inOutByteArray, BitSize_t numberOfBitsToRead, const bool alignBitsToRight )
  96.533 +{
  96.534 +#ifdef _DEBUG
  96.535 +	//	OVR_ASSERT( numberOfBitsToRead > 0 );
  96.536 +#endif
  96.537 +	if (numberOfBitsToRead<=0)
  96.538 +		return false;
  96.539 +
  96.540 +	if ( readOffset + numberOfBitsToRead > numberOfBitsUsed )
  96.541 +		return false;
  96.542 +
  96.543 +
  96.544 +	const BitSize_t readOffsetMod8 = readOffset & 7;
  96.545 +
  96.546 +	// If currently aligned and numberOfBits is a multiple of 8, just memcpy for speed
  96.547 +	if (readOffsetMod8==0 && (numberOfBitsToRead&7)==0)
  96.548 +	{
  96.549 +		memcpy( inOutByteArray, data + ( readOffset >> 3 ), numberOfBitsToRead>>3);
  96.550 +		readOffset+=numberOfBitsToRead;
  96.551 +		return true;
  96.552 +	}
  96.553 +
  96.554 +
  96.555 +
  96.556 +	BitSize_t offset = 0;
  96.557 +
  96.558 +	memset( inOutByteArray, 0, (size_t) BITS_TO_BYTES( numberOfBitsToRead ) );
  96.559 +
  96.560 +	while ( numberOfBitsToRead > 0 )
  96.561 +	{
  96.562 +		*( inOutByteArray + offset ) |= *( data + ( readOffset >> 3 ) ) << ( readOffsetMod8 ); // First half
  96.563 +
  96.564 +		if ( readOffsetMod8 > 0 && numberOfBitsToRead > 8 - ( readOffsetMod8 ) )   // If we have a second half, we didn't read enough bytes in the first half
  96.565 +			*( inOutByteArray + offset ) |= *( data + ( readOffset >> 3 ) + 1 ) >> ( 8 - ( readOffsetMod8 ) ); // Second half (overlaps byte boundary)
  96.566 +
  96.567 +		if (numberOfBitsToRead>=8)
  96.568 +		{
  96.569 +			numberOfBitsToRead -= 8;
  96.570 +			readOffset += 8;
  96.571 +			offset++;
  96.572 +		}
  96.573 +		else
  96.574 +		{
  96.575 +			int neg = (int) numberOfBitsToRead - 8;
  96.576 +
  96.577 +			if ( neg < 0 )   // Reading a partial byte for the last byte, shift right so the data is aligned on the right
  96.578 +			{
  96.579 +
  96.580 +				if ( alignBitsToRight )
  96.581 +					* ( inOutByteArray + offset ) >>= -neg;
  96.582 +
  96.583 +				readOffset += 8 + neg;
  96.584 +			}
  96.585 +			else
  96.586 +				readOffset += 8;
  96.587 +
  96.588 +			offset++;
  96.589 +
  96.590 +			numberOfBitsToRead=0;
  96.591 +		}		
  96.592 +	}
  96.593 +
  96.594 +	return true;
  96.595 +}
  96.596 +
  96.597 +// Assume the input source points to a compressed native type. Decompress and read it
  96.598 +bool BitStream::ReadCompressed( unsigned char* inOutByteArray,
  96.599 +							   const unsigned int size, const bool unsignedData )
  96.600 +{
  96.601 +	unsigned int currentByte = ( size >> 3 ) - 1;
  96.602 +
  96.603 +
  96.604 +	unsigned char byteMatch, halfByteMatch;
  96.605 +
  96.606 +	if ( unsignedData )
  96.607 +	{
  96.608 +		byteMatch = 0;
  96.609 +		halfByteMatch = 0;
  96.610 +	}
  96.611 +
  96.612 +	else
  96.613 +	{
  96.614 +		byteMatch = 0xFF;
  96.615 +		halfByteMatch = 0xF0;
  96.616 +	}
  96.617 +
  96.618 +	// Upper bytes are specified with a single 1 if they match byteMatch
  96.619 +	// From high byte to low byte, if high byte is a byteMatch then write a 1 bit. Otherwise write a 0 bit and then write the remaining bytes
  96.620 +	while ( currentByte > 0 )
  96.621 +	{
  96.622 +		// If we read a 1 then the data is byteMatch.
  96.623 +
  96.624 +		bool b;
  96.625 +
  96.626 +		if ( Read( b ) == false )
  96.627 +			return false;
  96.628 +
  96.629 +		if ( b )   // Check that bit
  96.630 +		{
  96.631 +			inOutByteArray[ currentByte ] = byteMatch;
  96.632 +			currentByte--;
  96.633 +		}
  96.634 +		else
  96.635 +		{
  96.636 +			// Read the rest of the bytes
  96.637 +
  96.638 +			if ( ReadBits( inOutByteArray, ( currentByte + 1 ) << 3 ) == false )
  96.639 +				return false;
  96.640 +
  96.641 +			return true;
  96.642 +		}
  96.643 +	}
  96.644 +
  96.645 +	// All but the first bytes are byteMatch.  If the upper half of the last byte is a 0 (positive) or 16 (negative) then what we read will be a 1 and the remaining 4 bits.
  96.646 +	// Otherwise we read a 0 and the 8 bytes
  96.647 +	//OVR_ASSERT(readOffset+1 <=numberOfBitsUsed); // If this assert is hit the stream wasn't long enough to read from
  96.648 +	if ( readOffset + 1 > numberOfBitsUsed )
  96.649 +		return false;
  96.650 +
  96.651 +	bool b=false;
  96.652 +
  96.653 +	if ( Read( b ) == false )
  96.654 +		return false;
  96.655 +
  96.656 +	if ( b )   // Check that bit
  96.657 +	{
  96.658 +
  96.659 +		if ( ReadBits( inOutByteArray + currentByte, 4 ) == false )
  96.660 +			return false;
  96.661 +
  96.662 +		inOutByteArray[ currentByte ] |= halfByteMatch; // We have to set the high 4 bits since these are set to 0 by ReadBits
  96.663 +	}
  96.664 +	else
  96.665 +	{
  96.666 +		if ( ReadBits( inOutByteArray + currentByte, 8 ) == false )
  96.667 +			return false;
  96.668 +	}
  96.669 +
  96.670 +	return true;
  96.671 +}
  96.672 +
  96.673 +// Reallocates (if necessary) in preparation of writing numberOfBitsToWrite
  96.674 +void BitStream::AddBitsAndReallocate( const BitSize_t numberOfBitsToWrite )
  96.675 +{
  96.676 +	BitSize_t newNumberOfBitsAllocated = numberOfBitsToWrite + numberOfBitsUsed;
  96.677 +
  96.678 +	if ( numberOfBitsToWrite + numberOfBitsUsed > 0 && ( ( numberOfBitsAllocated - 1 ) >> 3 ) < ( ( newNumberOfBitsAllocated - 1 ) >> 3 ) )   // If we need to allocate 1 or more new bytes
  96.679 +	{
  96.680 +#ifdef _DEBUG
  96.681 +		// If this assert hits then we need to specify true for the third parameter in the constructor
  96.682 +		// It needs to reallocate to hold all the data and can't do it unless we allocated to begin with
  96.683 +		// Often hits if you call Write or Serialize on a read-only bitstream
  96.684 +		OVR_ASSERT( copyData == true );
  96.685 +#endif
  96.686 +
  96.687 +		// Less memory efficient but saves on news and deletes
  96.688 +		/// Cap to 1 meg buffer to save on huge allocations
  96.689 +		newNumberOfBitsAllocated = ( numberOfBitsToWrite + numberOfBitsUsed ) * 2;
  96.690 +		if (newNumberOfBitsAllocated - ( numberOfBitsToWrite + numberOfBitsUsed ) > 1048576 )
  96.691 +			newNumberOfBitsAllocated = numberOfBitsToWrite + numberOfBitsUsed + 1048576;
  96.692 +
  96.693 +		//		BitSize_t newByteOffset = BITS_TO_BYTES( numberOfBitsAllocated );
  96.694 +		// Use realloc and free so we are more efficient than delete and new for resizing
  96.695 +		BitSize_t amountToAllocate = BITS_TO_BYTES( newNumberOfBitsAllocated );
  96.696 +		if (data==(unsigned char*)stackData)
  96.697 +		{
  96.698 +			if (amountToAllocate > BITSTREAM_STACK_ALLOCATION_SIZE)
  96.699 +			{
  96.700 +				data = ( unsigned char* ) OVR_ALLOC( (size_t) amountToAllocate);
  96.701 +				OVR_ASSERT(data);
  96.702 +                if (data)
  96.703 +				{
  96.704 +                    // need to copy the stack data over to our new memory area too
  96.705 +                    memcpy ((void *)data, (void *)stackData, (size_t) BITS_TO_BYTES( numberOfBitsAllocated ));
  96.706 +                }
  96.707 +			}
  96.708 +		}
  96.709 +		else
  96.710 +		{
  96.711 +			data = ( unsigned char* ) OVR_REALLOC( data, (size_t) amountToAllocate);
  96.712 +		}
  96.713 +
  96.714 +#ifdef _DEBUG
  96.715 +		OVR_ASSERT( data ); // Make sure realloc succeeded
  96.716 +#endif
  96.717 +		//  memset(data+newByteOffset, 0,  ((newNumberOfBitsAllocated-1)>>3) - ((numberOfBitsAllocated-1)>>3)); // Set the new data block to 0
  96.718 +	}
  96.719 +
  96.720 +	if ( newNumberOfBitsAllocated > numberOfBitsAllocated )
  96.721 +		numberOfBitsAllocated = newNumberOfBitsAllocated;
  96.722 +}
  96.723 +BitSize_t BitStream::GetNumberOfBitsAllocated(void) const
  96.724 +{
  96.725 +	return numberOfBitsAllocated;
  96.726 +}
  96.727 +void BitStream::PadWithZeroToByteLength( unsigned int bytes )
  96.728 +{
  96.729 +	if (GetNumberOfBytesUsed() < bytes)
  96.730 +	{
  96.731 +		AlignWriteToByteBoundary();
  96.732 +		unsigned int numToWrite = bytes - GetNumberOfBytesUsed();
  96.733 +		AddBitsAndReallocate( BYTES_TO_BITS(numToWrite) );
  96.734 +		memset(data+BITS_TO_BYTES(numberOfBitsUsed), 0, (size_t) numToWrite);
  96.735 +		numberOfBitsUsed+=BYTES_TO_BITS(numToWrite);
  96.736 +	}
  96.737 +}
  96.738 +
  96.739 +/* 
  96.740 +// Julius Goryavsky's version of Harley's algorithm.
  96.741 +// 17 elementary ops plus an indexed load, if the machine
  96.742 +// has "and not."
  96.743 +
  96.744 +int nlz10b(unsigned x) {
  96.745 +
  96.746 +   static char table[64] =
  96.747 +     {32,20,19, u, u,18, u, 7,  10,17, u, u,14, u, 6, u,
  96.748 +       u, 9, u,16, u, u, 1,26,   u,13, u, u,24, 5, u, u,
  96.749 +       u,21, u, 8,11, u,15, u,   u, u, u, 2,27, 0,25, u,
  96.750 +      22, u,12, u, u, 3,28, u,  23, u, 4,29, u, u,30,31};
  96.751 +
  96.752 +   x = x | (x >> 1);    // Propagate leftmost
  96.753 +   x = x | (x >> 2);    // 1-bit to the right.
  96.754 +   x = x | (x >> 4);
  96.755 +   x = x | (x >> 8);
  96.756 +   x = x & ~(x >> 16);
  96.757 +   x = x*0xFD7049FF;    // Activate this line or the following 3.
  96.758 +// x = (x << 9) - x;    // Multiply by 511.
  96.759 +// x = (x << 11) - x;   // Multiply by 2047.
  96.760 +// x = (x << 14) - x;   // Multiply by 16383.
  96.761 +   return table[x >> 26];
  96.762 +}
  96.763 +*/
  96.764 +int BitStream::NumberOfLeadingZeroes( int8_t x ) {return NumberOfLeadingZeroes((uint8_t)x);}
  96.765 +int BitStream::NumberOfLeadingZeroes( uint8_t x )
  96.766 +{
  96.767 +	uint8_t y;
  96.768 +	int n;
  96.769 +
  96.770 +	n = 8;
  96.771 +	y = x >> 4;  if (y != 0) {n = n - 4;  x = y;}
  96.772 +	y = x >> 2;  if (y != 0) {n = n - 2;  x = y;}
  96.773 +	y = x >> 1;  if (y != 0) return n - 2;
  96.774 +	return (int)(n - x);
  96.775 +}
  96.776 +int BitStream::NumberOfLeadingZeroes( int16_t x ) {return NumberOfLeadingZeroes((uint16_t)x);}
  96.777 +int BitStream::NumberOfLeadingZeroes( uint16_t x )
  96.778 +{
  96.779 +	uint16_t y;
  96.780 +	int n;
  96.781 +
  96.782 +	n = 16;
  96.783 +	y = x >> 8;  if (y != 0) {n = n - 8;  x = y;}
  96.784 +	y = x >> 4;  if (y != 0) {n = n - 4;  x = y;}
  96.785 +	y = x >> 2;  if (y != 0) {n = n - 2;  x = y;}
  96.786 +	y = x >> 1;  if (y != 0) return n - 2;
  96.787 +	return (int)(n - x);
  96.788 +}
  96.789 +int BitStream::NumberOfLeadingZeroes( int32_t x ) {return NumberOfLeadingZeroes((uint32_t)x);}
  96.790 +int BitStream::NumberOfLeadingZeroes( uint32_t x )
  96.791 +{
  96.792 +	uint32_t y;
  96.793 +	int n;
  96.794 +
  96.795 +	n = 32;
  96.796 +	y = x >>16;  if (y != 0) {n = n -16;  x = y;}
  96.797 +	y = x >> 8;  if (y != 0) {n = n - 8;  x = y;}
  96.798 +	y = x >> 4;  if (y != 0) {n = n - 4;  x = y;}
  96.799 +	y = x >> 2;  if (y != 0) {n = n - 2;  x = y;}
  96.800 +	y = x >> 1;  if (y != 0) return n - 2;
  96.801 +	return (int)(n - x);
  96.802 +}
  96.803 +int BitStream::NumberOfLeadingZeroes( int64_t x ) {return NumberOfLeadingZeroes((uint64_t)x);}
  96.804 +int BitStream::NumberOfLeadingZeroes( uint64_t x )
  96.805 +{
  96.806 +	uint64_t y;
  96.807 +	int n;
  96.808 +
  96.809 +	n = 64;
  96.810 +	y = x >>32;  if (y != 0) {n = n -32;  x = y;}
  96.811 +	y = x >>16;  if (y != 0) {n = n -16;  x = y;}
  96.812 +	y = x >> 8;  if (y != 0) {n = n - 8;  x = y;}
  96.813 +	y = x >> 4;  if (y != 0) {n = n - 4;  x = y;}
  96.814 +	y = x >> 2;  if (y != 0) {n = n - 2;  x = y;}
  96.815 +	y = x >> 1;  if (y != 0) return n - 2;
  96.816 +	return (int)(n - x);
  96.817 +}
  96.818 +
  96.819 +// Should hit if reads didn't match writes
  96.820 +void BitStream::AssertStreamEmpty( void )
  96.821 +{
  96.822 +	OVR_ASSERT( readOffset == numberOfBitsUsed );
  96.823 +}
  96.824 +void BitStream::PrintBits( char *out ) const
  96.825 +{
  96.826 +	if ( numberOfBitsUsed <= 0 )
  96.827 +	{
  96.828 +		OVR_strcpy(out, 128, "No bits\n" );
  96.829 +		return;
  96.830 +	}
  96.831 +
  96.832 +	unsigned int strIndex=0;
  96.833 +	for ( BitSize_t counter = 0; counter < BITS_TO_BYTES( numberOfBitsUsed ) && strIndex < 2000 ; counter++ )
  96.834 +	{
  96.835 +		BitSize_t stop;
  96.836 +
  96.837 +		if ( counter == ( numberOfBitsUsed - 1 ) >> 3 )
  96.838 +			stop = 8 - ( ( ( numberOfBitsUsed - 1 ) & 7 ) + 1 );
  96.839 +		else
  96.840 +			stop = 0;
  96.841 +
  96.842 +		for ( BitSize_t counter2 = 7; counter2 >= stop; counter2-- )
  96.843 +		{
  96.844 +			if ( ( data[ counter ] >> counter2 ) & 1 )
  96.845 +				out[strIndex++]='1';
  96.846 +			else
  96.847 +				out[strIndex++]='0';
  96.848 +
  96.849 +			if (counter2==0)
  96.850 +				break;
  96.851 +		}
  96.852 +
  96.853 +		out[strIndex++]=' ';
  96.854 +	}
  96.855 +
  96.856 +	out[strIndex++]='\n';
  96.857 +
  96.858 +	out[strIndex++]=0;
  96.859 +}
  96.860 +void BitStream::PrintBits( void ) const
  96.861 +{
  96.862 +	char out[2048];
  96.863 +	PrintBits(out);
  96.864 +	printf("%s", out);
  96.865 +}
  96.866 +void BitStream::PrintHex( char *out ) const
  96.867 +{
  96.868 +	BitSize_t i;
  96.869 +	for ( i=0; i < GetNumberOfBytesUsed(); i++)
  96.870 +	{
  96.871 +		OVR_sprintf(out+i*3, 128, "%02x ", data[i]);
  96.872 +	}
  96.873 +}
  96.874 +void BitStream::PrintHex( void ) const
  96.875 +{
  96.876 +	char out[2048];
  96.877 +	PrintHex(out);
  96.878 +	printf("%s", out);
  96.879 +}
  96.880 +
  96.881 +// Exposes the data for you to look at, like PrintBits does.
  96.882 +// Data will point to the stream.  Returns the length in bits of the stream.
  96.883 +BitSize_t BitStream::CopyData( unsigned char** _data ) const
  96.884 +{
  96.885 +#ifdef _DEBUG
  96.886 +	OVR_ASSERT( numberOfBitsUsed > 0 );
  96.887 +#endif
  96.888 +
  96.889 +	*_data = (unsigned char*) OVR_ALLOC( (size_t) BITS_TO_BYTES( numberOfBitsUsed ));
  96.890 +	memcpy( *_data, data, sizeof(unsigned char) * (size_t) ( BITS_TO_BYTES( numberOfBitsUsed ) ) );
  96.891 +	return numberOfBitsUsed;
  96.892 +}
  96.893 +
  96.894 +// Ignore data we don't intend to read
  96.895 +void BitStream::IgnoreBits( const BitSize_t numberOfBits )
  96.896 +{
  96.897 +	readOffset += numberOfBits;
  96.898 +}
  96.899 +
  96.900 +void BitStream::IgnoreBytes( const unsigned int numberOfBytes )
  96.901 +{
  96.902 +	IgnoreBits(BYTES_TO_BITS(numberOfBytes));
  96.903 +}
  96.904 +
  96.905 +// Move the write pointer to a position on the array.  Dangerous if you don't know what you are doing!
  96.906 +// Doesn't work with non-aligned data!
  96.907 +void BitStream::SetWriteOffset( const BitSize_t offset )
  96.908 +{
  96.909 +	numberOfBitsUsed = offset;
  96.910 +}
  96.911 +
  96.912 +/*
  96.913 +BitSize_t BitStream::GetWriteOffset( void ) const
  96.914 +{
  96.915 +return numberOfBitsUsed;
  96.916 +}
  96.917 +
  96.918 +// Returns the length in bits of the stream
  96.919 +BitSize_t BitStream::GetNumberOfBitsUsed( void ) const
  96.920 +{
  96.921 +return GetWriteOffset();
  96.922 +}
  96.923 +
  96.924 +// Returns the length in bytes of the stream
  96.925 +BitSize_t BitStream::GetNumberOfBytesUsed( void ) const
  96.926 +{
  96.927 +return BITS_TO_BYTES( numberOfBitsUsed );
  96.928 +}
  96.929 +
  96.930 +// Returns the number of bits into the stream that we have read
  96.931 +BitSize_t BitStream::GetReadOffset( void ) const
  96.932 +{
  96.933 +return readOffset;
  96.934 +}
  96.935 +
  96.936 +
  96.937 +// Sets the read bit index
  96.938 +void BitStream::SetReadOffset( const BitSize_t newReadOffset )
  96.939 +{
  96.940 +readOffset=newReadOffset;
  96.941 +}
  96.942 +
  96.943 +// Returns the number of bits left in the stream that haven't been read
  96.944 +BitSize_t BitStream::GetNumberOfUnreadBits( void ) const
  96.945 +{
  96.946 +return numberOfBitsUsed - readOffset;
  96.947 +}
  96.948 +// Exposes the internal data
  96.949 +unsigned char* BitStream::GetData( void ) const
  96.950 +{
  96.951 +return data;
  96.952 +}
  96.953 +
  96.954 +*/
  96.955 +// If we used the constructor version with copy data off, this makes sure it is set to on and the data pointed to is copied.
  96.956 +void BitStream::AssertCopyData( void )
  96.957 +{
  96.958 +	if ( copyData == false )
  96.959 +	{
  96.960 +		copyData = true;
  96.961 +
  96.962 +		if ( numberOfBitsAllocated > 0 )
  96.963 +		{
  96.964 +			unsigned char * newdata = ( unsigned char* ) OVR_ALLOC( (size_t) BITS_TO_BYTES( numberOfBitsAllocated ));
  96.965 +#ifdef _DEBUG
  96.966 +
  96.967 +			OVR_ASSERT( data );
  96.968 +#endif
  96.969 +
  96.970 +			memcpy( newdata, data, (size_t) BITS_TO_BYTES( numberOfBitsAllocated ) );
  96.971 +			data = newdata;
  96.972 +		}
  96.973 +
  96.974 +		else
  96.975 +			data = 0;
  96.976 +	}
  96.977 +}
  96.978 +bool BitStream::IsNetworkOrderInternal(void)
  96.979 +{
  96.980 +#if defined(_PS3) || defined(__PS3__) || defined(SN_TARGET_PS3)
  96.981 +	return true;
  96.982 +#elif defined(SN_TARGET_PSP2)
  96.983 +	return false;
  96.984 +#else
  96.985 +	static unsigned long htonlValue = htonl(12345);
  96.986 +	return htonlValue == 12345;
  96.987 +#endif
  96.988 +}
  96.989 +void BitStream::ReverseBytes(unsigned char *inByteArray, unsigned char *inOutByteArray, const unsigned int length)
  96.990 +{
  96.991 +	for (BitSize_t i=0; i < length; i++)
  96.992 +		inOutByteArray[i]=inByteArray[length-i-1];
  96.993 +}
  96.994 +void BitStream::ReverseBytesInPlace(unsigned char *inOutData,const unsigned int length)
  96.995 +{
  96.996 +	unsigned char temp;
  96.997 +	BitSize_t i;
  96.998 +	for (i=0; i < (length>>1); i++)
  96.999 +	{
 96.1000 +		temp = inOutData[i];
 96.1001 +		inOutData[i]=inOutData[length-i-1];
 96.1002 +		inOutData[length-i-1]=temp;
 96.1003 +	}
 96.1004 +}
 96.1005 +
 96.1006 +void BitStream::WriteAlignedVar8(const char *inByteArray)
 96.1007 +{
 96.1008 +	OVR_ASSERT((numberOfBitsUsed&7)==0);
 96.1009 +	AddBitsAndReallocate(1*8);
 96.1010 +	data[( numberOfBitsUsed >> 3 ) + 0] = inByteArray[0];
 96.1011 +	numberOfBitsUsed+=1*8;
 96.1012 +}
 96.1013 +bool BitStream::ReadAlignedVar8(char *inOutByteArray)
 96.1014 +{
 96.1015 +	OVR_ASSERT((readOffset&7)==0);
 96.1016 +	if ( readOffset + 1*8 > numberOfBitsUsed )
 96.1017 +		return false;
 96.1018 +
 96.1019 +	inOutByteArray[0] = data[( readOffset >> 3 ) + 0];
 96.1020 +	readOffset+=1*8;
 96.1021 +	return true;
 96.1022 +}
 96.1023 +void BitStream::WriteAlignedVar16(const char *inByteArray)
 96.1024 +{
 96.1025 +	OVR_ASSERT((numberOfBitsUsed&7)==0);
 96.1026 +	AddBitsAndReallocate(2*8);
 96.1027 +#ifndef __BITSTREAM_NATIVE_END
 96.1028 +	if (DoEndianSwap())
 96.1029 +	{
 96.1030 +		data[( numberOfBitsUsed >> 3 ) + 0] = inByteArray[1];
 96.1031 +		data[( numberOfBitsUsed >> 3 ) + 1] = inByteArray[0];
 96.1032 +	}
 96.1033 +	else
 96.1034 +#endif
 96.1035 +	{
 96.1036 +		data[( numberOfBitsUsed >> 3 ) + 0] = inByteArray[0];
 96.1037 +		data[( numberOfBitsUsed >> 3 ) + 1] = inByteArray[1];
 96.1038 +	}
 96.1039 +
 96.1040 +	numberOfBitsUsed+=2*8;
 96.1041 +}
 96.1042 +bool BitStream::ReadAlignedVar16(char *inOutByteArray)
 96.1043 +{
 96.1044 +	OVR_ASSERT((readOffset&7)==0);
 96.1045 +	if ( readOffset + 2*8 > numberOfBitsUsed )
 96.1046 +		return false;
 96.1047 +#ifndef __BITSTREAM_NATIVE_END
 96.1048 +	if (DoEndianSwap())
 96.1049 +	{
 96.1050 +		inOutByteArray[0] = data[( readOffset >> 3 ) + 1];
 96.1051 +		inOutByteArray[1] = data[( readOffset >> 3 ) + 0];
 96.1052 +	}
 96.1053 +	else
 96.1054 +#endif
 96.1055 +	{
 96.1056 +		inOutByteArray[0] = data[( readOffset >> 3 ) + 0];
 96.1057 +		inOutByteArray[1] = data[( readOffset >> 3 ) + 1];
 96.1058 +	}
 96.1059 +
 96.1060 +	readOffset+=2*8;
 96.1061 +	return true;
 96.1062 +}
 96.1063 +void BitStream::WriteAlignedVar32(const char *inByteArray)
 96.1064 +{
 96.1065 +	OVR_ASSERT((numberOfBitsUsed&7)==0);
 96.1066 +	AddBitsAndReallocate(4*8);
 96.1067 +#ifndef __BITSTREAM_NATIVE_END
 96.1068 +	if (DoEndianSwap())
 96.1069 +	{
 96.1070 +		data[( numberOfBitsUsed >> 3 ) + 0] = inByteArray[3];
 96.1071 +		data[( numberOfBitsUsed >> 3 ) + 1] = inByteArray[2];
 96.1072 +		data[( numberOfBitsUsed >> 3 ) + 2] = inByteArray[1];
 96.1073 +		data[( numberOfBitsUsed >> 3 ) + 3] = inByteArray[0];
 96.1074 +	}
 96.1075 +	else
 96.1076 +#endif
 96.1077 +	{
 96.1078 +		data[( numberOfBitsUsed >> 3 ) + 0] = inByteArray[0];
 96.1079 +		data[( numberOfBitsUsed >> 3 ) + 1] = inByteArray[1];
 96.1080 +		data[( numberOfBitsUsed >> 3 ) + 2] = inByteArray[2];
 96.1081 +		data[( numberOfBitsUsed >> 3 ) + 3] = inByteArray[3];
 96.1082 +	}
 96.1083 +
 96.1084 +	numberOfBitsUsed+=4*8;
 96.1085 +}
 96.1086 +bool BitStream::ReadAlignedVar32(char *inOutByteArray)
 96.1087 +{
 96.1088 +	OVR_ASSERT((readOffset&7)==0);
 96.1089 +	if ( readOffset + 4*8 > numberOfBitsUsed )
 96.1090 +		return false;
 96.1091 +#ifndef __BITSTREAM_NATIVE_END
 96.1092 +	if (DoEndianSwap())
 96.1093 +	{
 96.1094 +		inOutByteArray[0] = data[( readOffset >> 3 ) + 3];
 96.1095 +		inOutByteArray[1] = data[( readOffset >> 3 ) + 2];
 96.1096 +		inOutByteArray[2] = data[( readOffset >> 3 ) + 1];
 96.1097 +		inOutByteArray[3] = data[( readOffset >> 3 ) + 0];
 96.1098 +	}
 96.1099 +	else
 96.1100 +#endif
 96.1101 +	{
 96.1102 +		inOutByteArray[0] = data[( readOffset >> 3 ) + 0];
 96.1103 +		inOutByteArray[1] = data[( readOffset >> 3 ) + 1];
 96.1104 +		inOutByteArray[2] = data[( readOffset >> 3 ) + 2];
 96.1105 +		inOutByteArray[3] = data[( readOffset >> 3 ) + 3];
 96.1106 +	}
 96.1107 +
 96.1108 +	readOffset+=4*8;
 96.1109 +	return true;
 96.1110 +}
 96.1111 +bool BitStream::ReadFloat16( float &outFloat, float floatMin, float floatMax )
 96.1112 +{
 96.1113 +	uint16_t percentile;
 96.1114 +	if (Read(percentile))
 96.1115 +	{
 96.1116 +		OVR_ASSERT(floatMax>floatMin);
 96.1117 +		outFloat = floatMin + ((float) percentile / 65535.0f) * (floatMax-floatMin);
 96.1118 +		if (outFloat<floatMin)
 96.1119 +			outFloat=floatMin;
 96.1120 +		else if (outFloat>floatMax)
 96.1121 +			outFloat=floatMax;
 96.1122 +		return true;
 96.1123 +	}
 96.1124 +	return false;
 96.1125 +}
 96.1126 +bool BitStream::SerializeFloat16(bool writeToBitstream, float &inOutFloat, float floatMin, float floatMax)
 96.1127 +{
 96.1128 +	if (writeToBitstream)
 96.1129 +		WriteFloat16(inOutFloat, floatMin, floatMax);
 96.1130 +	else
 96.1131 +		return ReadFloat16(inOutFloat, floatMin, floatMax);
 96.1132 +	return true;
 96.1133 +}
 96.1134 +void BitStream::WriteFloat16( float inOutFloat, float floatMin, float floatMax )
 96.1135 +{
 96.1136 +	OVR_ASSERT(floatMax>floatMin);
 96.1137 +	if (inOutFloat>floatMax+.001)
 96.1138 +	{
 96.1139 +		OVR_ASSERT(inOutFloat<=floatMax+.001);
 96.1140 +	}
 96.1141 +	if (inOutFloat<floatMin-.001)
 96.1142 +	{
 96.1143 +		OVR_ASSERT(inOutFloat>=floatMin-.001);
 96.1144 +	}
 96.1145 +	float percentile=65535.0f * (inOutFloat-floatMin)/(floatMax-floatMin);
 96.1146 +	if (percentile<0.0)
 96.1147 +		percentile=0.0;
 96.1148 +	if (percentile>65535.0f)
 96.1149 +		percentile=65535.0f;
 96.1150 +	Write((uint16_t)percentile);
 96.1151 +}
 96.1152 +
 96.1153 +
 96.1154 +}} // OVR::Net
    97.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    97.2 +++ b/LibOVR/Src/Net/OVR_BitStream.h	Wed Jan 14 06:51:16 2015 +0200
    97.3 @@ -0,0 +1,1744 @@
    97.4 +/************************************************************************************
    97.5 +
    97.6 +PublicHeader:   n/a
    97.7 +Filename    :   OVR_BitStream.h
    97.8 +Content     :   A generic serialization toolkit for packing data to a binary stream.
    97.9 +Created     :   June 10, 2014
   97.10 +Authors     :   Kevin Jenkins
   97.11 +
   97.12 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   97.13 +
   97.14 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
   97.15 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
   97.16 +which is provided at the time of installation or download, or which 
   97.17 +otherwise accompanies this software in either electronic or hard copy form.
   97.18 +
   97.19 +You may obtain a copy of the License at
   97.20 +
   97.21 +http://www.oculusvr.com/licenses/LICENSE-3.2 
   97.22 +
   97.23 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
   97.24 +distributed under the License is distributed on an "AS IS" BASIS,
   97.25 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   97.26 +See the License for the specific language governing permissions and
   97.27 +limitations under the License.
   97.28 +
   97.29 +************************************************************************************/
   97.30 +
   97.31 +#ifndef OVR_Bitstream_h
   97.32 +#define OVR_Bitstream_h
   97.33 +
   97.34 +#include <math.h>
   97.35 +#include "../Kernel/OVR_Types.h"
   97.36 +#include "../Kernel/OVR_Std.h"
   97.37 +#include "../Kernel/OVR_String.h"
   97.38 +
   97.39 +namespace OVR { namespace Net {
   97.40 +
   97.41 +typedef uint32_t BitSize_t;
   97.42 +#define BITSTREAM_STACK_ALLOCATION_SIZE 256
   97.43 +#define BITS_TO_BYTES(x) (((x)+7)>>3)
   97.44 +#define BYTES_TO_BITS(x) ((x)<<3)
   97.45 +
   97.46 +
   97.47 +//-----------------------------------------------------------------------------
   97.48 +// BitStream
   97.49 +
   97.50 +// Generic serialization class to binary stream
   97.51 +class BitStream : public NewOverrideBase
   97.52 +{
   97.53 +public:
   97.54 +	/// Default Constructor
   97.55 +	BitStream();
   97.56 +
   97.57 +	/// \brief Create the bitstream, with some number of bytes to immediately allocate.
   97.58 +	/// \details There is no benefit to calling this, unless you know exactly how many bytes you need and it is greater than BITSTREAM_STACK_ALLOCATION_SIZE.
   97.59 +	/// In that case all it does is save you one or more realloc calls.
   97.60 +	/// \param[in] initialBytesToAllocate the number of bytes to pre-allocate.
   97.61 +	BitStream( const unsigned int initialBytesToAllocate );
   97.62 +
   97.63 +	/// \brief Initialize the BitStream, immediately setting the data it contains to a predefined pointer.
   97.64 +	/// \details Set \a _copyData to true if you want to make an internal copy of the data you are passing. Set it to false to just save a pointer to the data.
   97.65 +	/// You shouldn't call Write functions with \a _copyData as false, as this will write to unallocated memory
   97.66 +	/// 99% of the time you will use this function to cast Packet::data to a bitstream for reading, in which case you should write something as follows:
   97.67 +	/// \code
   97.68 +	/// RakNet::BitStream bs(packet->data, packet->length, false);
   97.69 +	/// \endcode
   97.70 +	/// \param[in] _data An array of bytes.
   97.71 +	/// \param[in] lengthInBytes Size of the \a _data.
   97.72 +	/// \param[in] _copyData true or false to make a copy of \a _data or not.
   97.73 +	BitStream( char* _data, const unsigned int lengthInBytes, bool _copyData );
   97.74 +
   97.75 +	// Destructor
   97.76 +	~BitStream();
   97.77 +
   97.78 +public:
   97.79 +	/// Resets the bitstream for reuse.
   97.80 +	void Reset( void );
   97.81 +
   97.82 +	/// \brief Bidirectional serialize/deserialize any integral type to/from a bitstream.  
   97.83 +	/// \details Undefine __BITSTREAM_NATIVE_END if you need endian swapping.
   97.84 +	/// \param[in] writeToBitstream true to write from your data to this bitstream.  False to read from this bitstream and write to your data
   97.85 +	/// \param[in] inOutTemplateVar The value to write
   97.86 +	/// \return true if \a writeToBitstream is true.  true if \a writeToBitstream is false and the read was successful.  false if \a writeToBitstream is false and the read was not successful.
   97.87 +	template <class templateType>
   97.88 +	bool Serialize(bool writeToBitstream, templateType &inOutTemplateVar);
   97.89 +
   97.90 +	/// \brief Bidirectional serialize/deserialize any integral type to/from a bitstream. 
   97.91 +	/// \details If the current value is different from the last value
   97.92 +	/// the current value will be written.  Otherwise, a single bit will be written
   97.93 +	/// \param[in] writeToBitstream true to write from your data to this bitstream.  False to read from this bitstream and write to your data
   97.94 +	/// \param[in] inOutCurrentValue The current value to write
   97.95 +	/// \param[in] lastValue The last value to compare against.  Only used if \a writeToBitstream is true.
   97.96 +	/// \return true if \a writeToBitstream is true.  true if \a writeToBitstream is false and the read was successful.  false if \a writeToBitstream is false and the read was not successful.
   97.97 +	template <class templateType>
   97.98 +	bool SerializeDelta(bool writeToBitstream, templateType &inOutCurrentValue, const templateType &lastValue);
   97.99 +
  97.100 +	/// \brief Bidirectional version of SerializeDelta when you don't know what the last value is, or there is no last value.
  97.101 +	/// \param[in] writeToBitstream true to write from your data to this bitstream.  False to read from this bitstream and write to your data
  97.102 +	/// \param[in] inOutCurrentValue The current value to write
  97.103 +	/// \return true if \a writeToBitstream is true.  true if \a writeToBitstream is false and the read was successful.  false if \a writeToBitstream is false and the read was not successful.
  97.104 +	template <class templateType>
  97.105 +	bool SerializeDelta(bool writeToBitstream, templateType &inOutCurrentValue);
  97.106 +
  97.107 +	/// \brief Bidirectional serialize/deserialize any integral type to/from a bitstream.
  97.108 +	/// \details Undefine __BITSTREAM_NATIVE_END if you need endian swapping.
  97.109 +	/// If you are not using __BITSTREAM_NATIVE_END the opposite is true for types larger than 1 byte
  97.110 +	/// For floating point, this is lossy, using 2 bytes for a float and 4 for a double.  The range must be between -1 and +1.
  97.111 +	/// For non-floating point, this is lossless, but only has benefit if you use less than half the bits of the type
  97.112 +	/// \param[in] writeToBitstream true to write from your data to this bitstream.  False to read from this bitstream and write to your data
  97.113 +	/// \param[in] inOutTemplateVar The value to write
  97.114 +	/// \return true if \a writeToBitstream is true.  true if \a writeToBitstream is false and the read was successful.  false if \a writeToBitstream is false and the read was not successful.
  97.115 +	template <class templateType>
  97.116 +	bool SerializeCompressed(bool writeToBitstream, templateType &inOutTemplateVar);
  97.117 +
  97.118 +	/// \brief Bidirectional serialize/deserialize any integral type to/from a bitstream.  
  97.119 +	/// \details If the current value is different from the last value
  97.120 +	/// the current value will be written.  Otherwise, a single bit will be written
  97.121 +	/// For floating point, this is lossy, using 2 bytes for a float and 4 for a double.  The range must be between -1 and +1.
  97.122 +	/// For non-floating point, this is lossless, but only has benefit if you use less than half the bits of the type
  97.123 +	/// If you are not using __BITSTREAM_NATIVE_END the opposite is true for types larger than 1 byte
  97.124 +	/// \param[in] writeToBitstream true to write from your data to this bitstream.  False to read from this bitstream and write to your data
  97.125 +	/// \param[in] inOutCurrentValue The current value to write
  97.126 +	/// \param[in] lastValue The last value to compare against.  Only used if \a writeToBitstream is true.
  97.127 +	/// \return true if \a writeToBitstream is true.  true if \a writeToBitstream is false and the read was successful.  false if \a writeToBitstream is false and the read was not successful.
  97.128 +	template <class templateType>
  97.129 +	bool SerializeCompressedDelta(bool writeToBitstream, templateType &inOutCurrentValue, const templateType &lastValue);
  97.130 +
  97.131 +	/// \brief Save as SerializeCompressedDelta(templateType &currentValue, const templateType &lastValue) when we have an unknown second parameter
  97.132 +	/// \return true on data read. False on insufficient data in bitstream
  97.133 +	template <class templateType>
  97.134 +	bool SerializeCompressedDelta(bool writeToBitstream, templateType &inOutTemplateVar);
  97.135 +
  97.136 +	/// \brief Bidirectional serialize/deserialize an array or casted stream or raw data.  This does NOT do endian swapping.
  97.137 +	/// \param[in] writeToBitstream true to write from your data to this bitstream.  False to read from this bitstream and write to your data
  97.138 +	/// \param[in] inOutByteArray a byte buffer
  97.139 +	/// \param[in] numberOfBytes the size of \a input in bytes
  97.140 +	/// \return true if \a writeToBitstream is true.  true if \a writeToBitstream is false and the read was successful.  false if \a writeToBitstream is false and the read was not successful.
  97.141 +	bool Serialize(bool writeToBitstream,  char* inOutByteArray, const unsigned int numberOfBytes );
  97.142 +
  97.143 +	/// \brief Serialize a float into 2 bytes, spanning the range between \a floatMin and \a floatMax
  97.144 +	/// \param[in] writeToBitstream true to write from your data to this bitstream.  False to read from this bitstream and write to your data
  97.145 +	/// \param[in] inOutFloat The float to write
  97.146 +	/// \param[in] floatMin Predetermined minimum value of f
  97.147 +	/// \param[in] floatMax Predetermined maximum value of f
  97.148 +	bool SerializeFloat16(bool writeToBitstream, float &inOutFloat, float floatMin, float floatMax);
  97.149 +
  97.150 +	/// Serialize one type casted to another (smaller) type, to save bandwidth
  97.151 +	/// serializationType should be uint8_t, uint16_t, uint24_t, or uint32_t
  97.152 +	/// Example: int num=53; SerializeCasted<uint8_t>(true, num); would use 1 byte to write what would otherwise be an integer (4 or 8 bytes)
  97.153 +	/// \param[in] writeToBitstream true to write from your data to this bitstream.  False to read from this bitstream and write to your data
  97.154 +	/// \param[in] value The value to serialize
  97.155 +	template <class serializationType, class sourceType >
  97.156 +	bool SerializeCasted( bool writeToBitstream, sourceType &value );
  97.157 +
  97.158 +	/// Given the minimum and maximum values for an integer type, figure out the minimum number of bits to represent the range
  97.159 +	/// Then serialize only those bits
  97.160 +	/// \note A static is used so that the required number of bits for (maximum-minimum) is only calculated once. This does require that \a minimum and \maximum are fixed values for a given line of code for the life of the program
  97.161 +	/// \param[in] writeToBitstream true to write from your data to this bitstream.  False to read from this bitstream and write to your data
  97.162 +	/// \param[in] value Integer value to write, which should be between \a minimum and \a maximum
  97.163 +	/// \param[in] minimum Minimum value of \a value
  97.164 +	/// \param[in] maximum Maximum value of \a value
  97.165 +	/// \param[in] allowOutsideRange If true, all sends will take an extra bit, however value can deviate from outside \a minimum and \a maximum. If false, will assert if the value deviates
  97.166 +	template <class templateType>
  97.167 +	bool SerializeBitsFromIntegerRange( bool writeToBitstream, templateType &value, const templateType minimum, const templateType maximum, bool allowOutsideRange=false );
  97.168 +	/// \param[in] requiredBits Primarily for internal use, called from above function() after calculating number of bits needed to represent maximum-minimum
  97.169 +	template <class templateType>
  97.170 +	bool SerializeBitsFromIntegerRange( bool writeToBitstream, templateType &value, const templateType minimum, const templateType maximum, const int requiredBits, bool allowOutsideRange=false );
  97.171 +
  97.172 +	/// \brief Bidirectional serialize/deserialize a normalized 3D vector, using (at most) 4 bytes + 3 bits instead of 12-24 bytes.  
  97.173 +	/// \details Will further compress y or z axis aligned vectors.
  97.174 +	/// Accurate to 1/32767.5.
  97.175 +	/// \param[in] writeToBitstream true to write from your data to this bitstream.  False to read from this bitstream and write to your data
  97.176 +	/// \param[in] x x
  97.177 +	/// \param[in] y y
  97.178 +	/// \param[in] z z
  97.179 +	/// \return true if \a writeToBitstream is true.  true if \a writeToBitstream is false and the read was successful.  false if \a writeToBitstream is false and the read was not successful.
  97.180 +	template <class templateType> // templateType for this function must be a float or double
  97.181 +	bool SerializeNormVector(bool writeToBitstream,  templateType &x, templateType &y, templateType &z );
  97.182 +
  97.183 +	/// \brief Bidirectional serialize/deserialize a vector, using 10 bytes instead of 12.
  97.184 +	/// \details Loses accuracy to about 3/10ths and only saves 2 bytes, so only use if accuracy is not important.
  97.185 +	/// \param[in] writeToBitstream true to write from your data to this bitstream.  False to read from this bitstream and write to your data
  97.186 +	/// \param[in] x x
  97.187 +	/// \param[in] y y
  97.188 +	/// \param[in] z z
  97.189 +	/// \return true if \a writeToBitstream is true.  true if \a writeToBitstream is false and the read was successful.  false if \a writeToBitstream is false and the read was not successful.
  97.190 +	template <class templateType> // templateType for this function must be a float or double
  97.191 +	bool SerializeVector(bool writeToBitstream,  templateType &x, templateType &y, templateType &z );
  97.192 +
  97.193 +	/// \brief Bidirectional serialize/deserialize a normalized quaternion in 6 bytes + 4 bits instead of 16 bytes. Slightly lossy.
  97.194 +	/// \param[in] writeToBitstream true to write from your data to this bitstream.  False to read from this bitstream and write to your data
  97.195 +	/// \param[in] w w
  97.196 +	/// \param[in] x x
  97.197 +	/// \param[in] y y
  97.198 +	/// \param[in] z z
  97.199 +	/// \return true if \a writeToBitstream is true.  true if \a writeToBitstream is false and the read was successful.  false if \a writeToBitstream is false and the read was not successful.
  97.200 +	template <class templateType> // templateType for this function must be a float or double
  97.201 +	bool SerializeNormQuat(bool writeToBitstream,  templateType &w, templateType &x, templateType &y, templateType &z);
  97.202 +
  97.203 +	/// \brief Bidirectional serialize/deserialize an orthogonal matrix by creating a quaternion, and writing 3 components of the quaternion in 2 bytes each.
  97.204 +	/// \details Use 6 bytes instead of 36
  97.205 +	/// Lossy, although the result is renormalized
  97.206 +	/// \return true on success, false on failure.
  97.207 +	template <class templateType> // templateType for this function must be a float or double
  97.208 +	bool SerializeOrthMatrix(
  97.209 +		bool writeToBitstream,
  97.210 +		templateType &m00, templateType &m01, templateType &m02,
  97.211 +		templateType &m10, templateType &m11, templateType &m12,
  97.212 +		templateType &m20, templateType &m21, templateType &m22 );
  97.213 +
  97.214 +	/// \brief Bidirectional serialize/deserialize numberToSerialize bits to/from the input. 
  97.215 +	/// \details Right aligned data means in the case of a partial byte, the bits are aligned
  97.216 +	/// from the right (bit 0) rather than the left (as in the normal
  97.217 +	/// internal representation) You would set this to true when
  97.218 +	/// writing user data, and false when copying bitstream data, such
  97.219 +	/// as writing one bitstream to another
  97.220 +	/// \param[in] writeToBitstream true to write from your data to this bitstream.  False to read from this bitstream and write to your data
  97.221 +	/// \param[in] inOutByteArray The data
  97.222 +	/// \param[in] numberOfBitsToSerialize The number of bits to write
  97.223 +	/// \param[in] rightAlignedBits if true data will be right aligned
  97.224 +	/// \return true if \a writeToBitstream is true.  true if \a writeToBitstream is false and the read was successful.  false if \a writeToBitstream is false and the read was not successful.
  97.225 +	bool SerializeBits(bool writeToBitstream, unsigned char* inOutByteArray, const BitSize_t numberOfBitsToSerialize, const bool rightAlignedBits = true );
  97.226 +
  97.227 +	/// \brief Write any integral type to a bitstream.  
  97.228 +	/// \details Undefine __BITSTREAM_NATIVE_END if you need endian swapping.
  97.229 +	/// \param[in] inTemplateVar The value to write
  97.230 +	template <class templateType>
  97.231 +	void Write(const templateType &inTemplateVar);
  97.232 +
  97.233 +	/// \brief Write the dereferenced pointer to any integral type to a bitstream.  
  97.234 +	/// \details Undefine __BITSTREAM_NATIVE_END if you need endian swapping.
  97.235 +	/// \param[in] inTemplateVar The value to write
  97.236 +	template <class templateType>
  97.237 +	void WritePtr(templateType *inTemplateVar);
  97.238 +
  97.239 +	/// \brief Write any integral type to a bitstream.  
  97.240 +	/// \details If the current value is different from the last value
  97.241 +	/// the current value will be written.  Otherwise, a single bit will be written
  97.242 +	/// \param[in] currentValue The current value to write
  97.243 +	/// \param[in] lastValue The last value to compare against
  97.244 +	template <class templateType>
  97.245 +	void WriteDelta(const templateType &currentValue, const templateType &lastValue);
  97.246 +
  97.247 +	/// \brief WriteDelta when you don't know what the last value is, or there is no last value.
  97.248 +	/// \param[in] currentValue The current value to write
  97.249 +	template <class templateType>
  97.250 +	void WriteDelta(const templateType &currentValue);
  97.251 +
  97.252 +	/// \brief Write any integral type to a bitstream.  
  97.253 +	/// \details Undefine __BITSTREAM_NATIVE_END if you need endian swapping.
  97.254 +	/// If you are not using __BITSTREAM_NATIVE_END the opposite is true for types larger than 1 byte
  97.255 +	/// For floating point, this is lossy, using 2 bytes for a float and 4 for a double.  The range must be between -1 and +1.
  97.256 +	/// For non-floating point, this is lossless, but only has benefit if you use less than half the bits of the type
  97.257 +	/// \param[in] inTemplateVar The value to write
  97.258 +	template <class templateType>
  97.259 +	void WriteCompressed(const templateType &inTemplateVar);
  97.260 +
  97.261 +	/// \brief Write any integral type to a bitstream.  
  97.262 +	/// \details If the current value is different from the last value
  97.263 +	/// the current value will be written.  Otherwise, a single bit will be written
  97.264 +	/// For floating point, this is lossy, using 2 bytes for a float and 4 for a double.  The range must be between -1 and +1.
  97.265 +	/// For non-floating point, this is lossless, but only has benefit if you use less than half the bits of the type
  97.266 +	/// If you are not using __BITSTREAM_NATIVE_END the opposite is true for types larger than 1 byte
  97.267 +	/// \param[in] currentValue The current value to write
  97.268 +	/// \param[in] lastValue The last value to compare against
  97.269 +	template <class templateType>
  97.270 +	void WriteCompressedDelta(const templateType &currentValue, const templateType &lastValue);
  97.271 +
  97.272 +	/// \brief Save as WriteCompressedDelta(const templateType &currentValue, const templateType &lastValue) when we have an unknown second parameter
  97.273 +	template <class templateType>
  97.274 +	void WriteCompressedDelta(const templateType &currentValue);
  97.275 +
  97.276 +	/// \brief Read any integral type from a bitstream.  
  97.277 +	/// \details Define __BITSTREAM_NATIVE_END if you need endian swapping.
  97.278 +	/// \param[in] outTemplateVar The value to read
  97.279 +	/// \return true on success, false on failure.
  97.280 +	template <class templateType>
  97.281 +	bool Read(templateType &outTemplateVar);
  97.282 +
  97.283 +	/// \brief Read any integral type from a bitstream.  
  97.284 +	/// \details If the written value differed from the value compared against in the write function,
  97.285 +	/// var will be updated.  Otherwise it will retain the current value.
  97.286 +	/// ReadDelta is only valid from a previous call to WriteDelta
  97.287 +	/// \param[in] outTemplateVar The value to read
  97.288 +	/// \return true on success, false on failure.
  97.289 +	template <class templateType>
  97.290 +	bool ReadDelta(templateType &outTemplateVar);
  97.291 +
  97.292 +	/// \brief Read any integral type from a bitstream.  
  97.293 +	/// \details Undefine __BITSTREAM_NATIVE_END if you need endian swapping.
  97.294 +	/// For floating point, this is lossy, using 2 bytes for a float and 4 for a double.  The range must be between -1 and +1.
  97.295 +	/// For non-floating point, this is lossless, but only has benefit if you use less than half the bits of the type
  97.296 +	/// If you are not using __BITSTREAM_NATIVE_END the opposite is true for types larger than 1 byte
  97.297 +	/// \param[in] outTemplateVar The value to read
  97.298 +	/// \return true on success, false on failure.
  97.299 +	template <class templateType>
  97.300 +	bool ReadCompressed(templateType &outTemplateVar);
  97.301 +
  97.302 +	/// \brief Read any integral type from a bitstream.  
  97.303 +	/// \details If the written value differed from the value compared against in the write function,
  97.304 +	/// var will be updated.  Otherwise it will retain the current value.
  97.305 +	/// the current value will be updated.
  97.306 +	/// For floating point, this is lossy, using 2 bytes for a float and 4 for a double.  The range must be between -1 and +1.
  97.307 +	/// For non-floating point, this is lossless, but only has benefit if you use less than half the bits of the type
  97.308 +	/// If you are not using __BITSTREAM_NATIVE_END the opposite is true for types larger than 1 byte
  97.309 +	/// ReadCompressedDelta is only valid from a previous call to WriteDelta
  97.310 +	/// \param[in] outTemplateVar The value to read
  97.311 +	/// \return true on success, false on failure.
  97.312 +	template <class templateType>
  97.313 +	bool ReadCompressedDelta(templateType &outTemplateVar);
  97.314 +
  97.315 +	/// \brief Read one bitstream to another.
  97.316 +	/// \param[in] numberOfBits bits to read
  97.317 +	/// \param bitStream the bitstream to read into from
  97.318 +	/// \return true on success, false on failure.
  97.319 +	bool Read( BitStream *bitStream, BitSize_t numberOfBits );
  97.320 +	bool Read( BitStream *bitStream );
  97.321 +	bool Read( BitStream &bitStream, BitSize_t numberOfBits );
  97.322 +	bool Read( BitStream &bitStream );
  97.323 +
  97.324 +	/// \brief Write an array or casted stream or raw data.  This does NOT do endian swapping.
  97.325 +	/// \param[in] inputByteArray a byte buffer
  97.326 +	/// \param[in] numberOfBytes the size of \a input in bytes
  97.327 +	void Write( const char* inputByteArray, const unsigned int numberOfBytes );
  97.328 +
  97.329 +	/// \brief Write one bitstream to another.
  97.330 +	/// \param[in] numberOfBits bits to write
  97.331 +	/// \param bitStream the bitstream to copy from
  97.332 +	void Write( BitStream *bitStream, BitSize_t numberOfBits );
  97.333 +	void Write( BitStream *bitStream );
  97.334 +	void Write( BitStream &bitStream, BitSize_t numberOfBits );
  97.335 +	void Write( BitStream &bitStream );\
  97.336 +
  97.337 +	/// \brief Write a float into 2 bytes, spanning the range between \a floatMin and \a floatMax
  97.338 +	/// \param[in] x The float to write
  97.339 +	/// \param[in] floatMin Predetermined minimum value of f
  97.340 +	/// \param[in] floatMax Predetermined maximum value of f
  97.341 +	void WriteFloat16( float x, float floatMin, float floatMax );
  97.342 +
  97.343 +	/// Write one type serialized as another (smaller) type, to save bandwidth
  97.344 +	/// serializationType should be uint8_t, uint16_t, uint24_t, or uint32_t
  97.345 +	/// Example: int num=53; WriteCasted<uint8_t>(num); would use 1 byte to write what would otherwise be an integer (4 or 8 bytes)
  97.346 +	/// \param[in] value The value to write
  97.347 +	template <class serializationType, class sourceType >
  97.348 +	void WriteCasted( const sourceType &value );
  97.349 +
  97.350 +	/// Given the minimum and maximum values for an integer type, figure out the minimum number of bits to represent the range
  97.351 +	/// Then write only those bits
  97.352 +	/// \note A static is used so that the required number of bits for (maximum-minimum) is only calculated once. This does require that \a minimum and \maximum are fixed values for a given line of code for the life of the program
  97.353 +	/// \param[in] value Integer value to write, which should be between \a minimum and \a maximum
  97.354 +	/// \param[in] minimum Minimum value of \a value
  97.355 +	/// \param[in] maximum Maximum value of \a value
  97.356 +	/// \param[in] allowOutsideRange If true, all sends will take an extra bit, however value can deviate from outside \a minimum and \a maximum. If false, will assert if the value deviates. This should match the corresponding value passed to Read().
  97.357 +	template <class templateType>
  97.358 +	void WriteBitsFromIntegerRange( const templateType value, const templateType minimum, const templateType maximum, bool allowOutsideRange=false );
  97.359 +	/// \param[in] requiredBits Primarily for internal use, called from above function() after calculating number of bits needed to represent maximum-minimum
  97.360 +	template <class templateType>
  97.361 +	void WriteBitsFromIntegerRange( const templateType value, const templateType minimum, const templateType maximum, const int requiredBits, bool allowOutsideRange=false );
  97.362 +
  97.363 +	/// \brief Write a normalized 3D vector, using (at most) 4 bytes + 3 bits instead of 12-24 bytes.  
  97.364 +	/// \details Will further compress y or z axis aligned vectors.
  97.365 +	/// Accurate to 1/32767.5.
  97.366 +	/// \param[in] x x
  97.367 +	/// \param[in] y y
  97.368 +	/// \param[in] z z
  97.369 +	template <class templateType> // templateType for this function must be a float or double
  97.370 +	void WriteNormVector( templateType x, templateType y, templateType z );
  97.371 +
  97.372 +	/// \brief Write a vector, using 10 bytes instead of 12.
  97.373 +	/// \details Loses accuracy to about 3/10ths and only saves 2 bytes, 
  97.374 +	/// so only use if accuracy is not important.
  97.375 +	/// \param[in] x x
  97.376 +	/// \param[in] y y
  97.377 +	/// \param[in] z z
  97.378 +	template <class templateType> // templateType for this function must be a float or double
  97.379 +	void WriteVector( templateType x, templateType y, templateType z );
  97.380 +
  97.381 +	/// \brief Write a normalized quaternion in 6 bytes + 4 bits instead of 16 bytes.  Slightly lossy.
  97.382 +	/// \param[in] w w
  97.383 +	/// \param[in] x x
  97.384 +	/// \param[in] y y
  97.385 +	/// \param[in] z z
  97.386 +	template <class templateType> // templateType for this function must be a float or double
  97.387 +	void WriteNormQuat( templateType w, templateType x, templateType y, templateType z);
  97.388 +
  97.389 +	/// \brief Write an orthogonal matrix by creating a quaternion, and writing 3 components of the quaternion in 2 bytes each.
  97.390 +	/// \details Use 6 bytes instead of 36
  97.391 +	/// Lossy, although the result is renormalized
  97.392 +	template <class templateType> // templateType for this function must be a float or double
  97.393 +	void WriteOrthMatrix(
  97.394 +		templateType m00, templateType m01, templateType m02,
  97.395 +		templateType m10, templateType m11, templateType m12,
  97.396 +		templateType m20, templateType m21, templateType m22 );
  97.397 +
  97.398 +	/// \brief Read an array or casted stream of byte.
  97.399 +	/// \details The array is raw data. There is no automatic endian conversion with this function
  97.400 +	/// \param[in] output The result byte array. It should be larger than @em numberOfBytes.
  97.401 +	/// \param[in] numberOfBytes The number of byte to read
  97.402 +	/// \return true on success false if there is some missing bytes.
  97.403 +	bool Read( char* output, const unsigned int numberOfBytes );
  97.404 +
  97.405 +	/// \brief Read a float into 2 bytes, spanning the range between \a floatMin and \a floatMax
  97.406 +	/// \param[in] outFloat The float to read
  97.407 +	/// \param[in] floatMin Predetermined minimum value of f
  97.408 +	/// \param[in] floatMax Predetermined maximum value of f
  97.409 +	bool ReadFloat16( float &outFloat, float floatMin, float floatMax );
  97.410 +
  97.411 +	/// Read one type serialized to another (smaller) type, to save bandwidth
  97.412 +	/// serializationType should be uint8_t, uint16_t, uint24_t, or uint32_t
  97.413 +	/// Example: int num; ReadCasted<uint8_t>(num); would read 1 bytefrom the stream, and put the value in an integer
  97.414 +	/// \param[in] value The value to write
  97.415 +	template <class serializationType, class sourceType >
  97.416 +	bool ReadCasted( sourceType &value );
  97.417 +
  97.418 +	/// Given the minimum and maximum values for an integer type, figure out the minimum number of bits to represent the range
  97.419 +	/// Then read only those bits
  97.420 +	/// \note A static is used so that the required number of bits for (maximum-minimum) is only calculated once. This does require that \a minimum and \maximum are fixed values for a given line of code for the life of the program
  97.421 +	/// \param[in] value Integer value to read, which should be between \a minimum and \a maximum
  97.422 +	/// \param[in] minimum Minimum value of \a value
  97.423 +	/// \param[in] maximum Maximum value of \a value
  97.424 +	/// \param[in] allowOutsideRange If true, all sends will take an extra bit, however value can deviate from outside \a minimum and \a maximum. If false, will assert if the value deviates. This should match the corresponding value passed to Write().
  97.425 +	template <class templateType>
  97.426 +	bool ReadBitsFromIntegerRange( templateType &value, const templateType minimum, const templateType maximum, bool allowOutsideRange=false );
  97.427 +	/// \param[in] requiredBits Primarily for internal use, called from above function() after calculating number of bits needed to represent maximum-minimum
  97.428 +	template <class templateType>
  97.429 +	bool ReadBitsFromIntegerRange( templateType &value, const templateType minimum, const templateType maximum, const int requiredBits, bool allowOutsideRange=false );
  97.430 +
  97.431 +	/// \brief Read a normalized 3D vector, using (at most) 4 bytes + 3 bits instead of 12-24 bytes.  
  97.432 +	/// \details Will further compress y or z axis aligned vectors.
  97.433 +	/// Accurate to 1/32767.5.
  97.434 +	/// \param[in] x x
  97.435 +	/// \param[in] y y
  97.436 +	/// \param[in] z z
  97.437 +	/// \return true on success, false on failure.
  97.438 +	template <class templateType> // templateType for this function must be a float or double
  97.439 +	bool ReadNormVector( templateType &x, templateType &y, templateType &z );
  97.440 +
  97.441 +	/// \brief Read 3 floats or doubles, using 10 bytes, where those float or doubles comprise a vector.
  97.442 +	/// \details Loses accuracy to about 3/10ths and only saves 2 bytes, 
  97.443 +	/// so only use if accuracy is not important.
  97.444 +	/// \param[in] x x
  97.445 +	/// \param[in] y y
  97.446 +	/// \param[in] z z
  97.447 +	/// \return true on success, false on failure.
  97.448 +	template <class templateType> // templateType for this function must be a float or double
  97.449 +	bool ReadVector( templateType &x, templateType &y, templateType &z );
  97.450 +
  97.451 +	/// \brief Read a normalized quaternion in 6 bytes + 4 bits instead of 16 bytes.
  97.452 +	/// \param[in] w w
  97.453 +	/// \param[in] x x
  97.454 +	/// \param[in] y y
  97.455 +	/// \param[in] z z
  97.456 +	/// \return true on success, false on failure.
  97.457 +	template <class templateType> // templateType for this function must be a float or double
  97.458 +	bool ReadNormQuat( templateType &w, templateType &x, templateType &y, templateType &z);
  97.459 +
  97.460 +	/// \brief Read an orthogonal matrix from a quaternion, reading 3 components of the quaternion in 2 bytes each and extrapolatig the 4th.
  97.461 +	/// \details Use 6 bytes instead of 36
  97.462 +	/// Lossy, although the result is renormalized
  97.463 +	/// \return true on success, false on failure.
  97.464 +	template <class templateType> // templateType for this function must be a float or double
  97.465 +	bool ReadOrthMatrix(
  97.466 +		templateType &m00, templateType &m01, templateType &m02,
  97.467 +		templateType &m10, templateType &m11, templateType &m12,
  97.468 +		templateType &m20, templateType &m21, templateType &m22 );
  97.469 +
  97.470 +	/// \brief Sets the read pointer back to the beginning of your data.
  97.471 +	void ResetReadPointer( void );
  97.472 +
  97.473 +	/// \brief Sets the write pointer back to the beginning of your data.
  97.474 +	void ResetWritePointer( void );
  97.475 +
  97.476 +	/// \brief This is good to call when you are done with the stream to make
  97.477 +	/// sure you didn't leave any data left over void
  97.478 +	void AssertStreamEmpty( void );
  97.479 +
  97.480 +	/// \brief RAKNET_DEBUG_PRINTF the bits in the stream.  Great for debugging.
  97.481 +	void PrintBits( char *out ) const;
  97.482 +	void PrintBits( void ) const;
  97.483 +	void PrintHex( char *out ) const;
  97.484 +	void PrintHex( void ) const;
  97.485 +
  97.486 +	/// \brief Ignore data we don't intend to read
  97.487 +	/// \param[in] numberOfBits The number of bits to ignore
  97.488 +	void IgnoreBits( const BitSize_t numberOfBits );
  97.489 +
  97.490 +	/// \brief Ignore data we don't intend to read
  97.491 +	/// \param[in] numberOfBits The number of bytes to ignore
  97.492 +	void IgnoreBytes( const unsigned int numberOfBytes );
  97.493 +
  97.494 +	/// \brief Move the write pointer to a position on the array.
  97.495 +	/// \param[in] offset the offset from the start of the array.
  97.496 +	/// \attention
  97.497 +	/// \details Dangerous if you don't know what you are doing!
  97.498 +	/// For efficiency reasons you can only write mid-stream if your data is byte aligned.
  97.499 +	void SetWriteOffset( const BitSize_t offset );
  97.500 +
  97.501 +	/// \brief Returns the length in bits of the stream
  97.502 +	inline BitSize_t GetNumberOfBitsUsed( void ) const {return GetWriteOffset();}
  97.503 +	inline BitSize_t GetWriteOffset( void ) const {return numberOfBitsUsed;}
  97.504 +
  97.505 +	/// \brief Returns the length in bytes of the stream
  97.506 +	inline BitSize_t GetNumberOfBytesUsed( void ) const {return BITS_TO_BYTES( numberOfBitsUsed );}
  97.507 +
  97.508 +	/// \brief Returns the number of bits into the stream that we have read
  97.509 +	inline BitSize_t GetReadOffset( void ) const {return readOffset;}
  97.510 +
  97.511 +	/// \brief Sets the read bit index
  97.512 +	void SetReadOffset( const BitSize_t newReadOffset ) {readOffset=newReadOffset;}
  97.513 +
  97.514 +	/// \brief Returns the number of bits left in the stream that haven't been read
  97.515 +	inline BitSize_t GetNumberOfUnreadBits( void ) const {return numberOfBitsUsed - readOffset;}
  97.516 +
  97.517 +	/// \brief Makes a copy of the internal data for you \a _data will point to
  97.518 +	/// the stream. Partial bytes are left aligned.
  97.519 +	/// \param[out] _data The allocated copy of GetData()
  97.520 +	/// \return The length in bits of the stream.
  97.521 +	BitSize_t CopyData( unsigned char** _data ) const;
  97.522 +
  97.523 +	/// \internal
  97.524 +	/// Set the stream to some initial data.
  97.525 +	void SetData( unsigned char *inByteArray );
  97.526 +
  97.527 +	/// Gets the data that BitStream is writing to / reading from.
  97.528 +	/// Partial bytes are left aligned.
  97.529 +	/// \return A pointer to the internal state
  97.530 +	inline char* GetData( void ) const {return (char*) data;}
  97.531 +
  97.532 +	/// \brief Write numberToWrite bits from the input source.
  97.533 +	/// \details Right aligned data means in the case of a partial byte, the bits are aligned
  97.534 +	/// from the right (bit 0) rather than the left (as in the normal
  97.535 +	/// internal representation) You would set this to true when
  97.536 +	/// writing user data, and false when copying bitstream data, such
  97.537 +	/// as writing one bitstream to another.
  97.538 +	/// \param[in] inByteArray The data
  97.539 +	/// \param[in] numberOfBitsToWrite The number of bits to write
  97.540 +	/// \param[in] rightAlignedBits if true data will be right aligned
  97.541 +	void WriteBits( const unsigned char* inByteArray, BitSize_t numberOfBitsToWrite, const bool rightAlignedBits = true );
  97.542 +
  97.543 +	/// \brief Align the bitstream to the byte boundary and then write the
  97.544 +	/// specified number of bits.  
  97.545 +	/// \details This is faster than WriteBits but
  97.546 +	/// wastes the bits to do the alignment and requires you to call
  97.547 +	/// ReadAlignedBits at the corresponding read position.
  97.548 +	/// \param[in] inByteArray The data
  97.549 +	/// \param[in] numberOfBytesToWrite The size of input.
  97.550 +	void WriteAlignedBytes( const unsigned char *inByteArray, const unsigned int numberOfBytesToWrite );
  97.551 +
  97.552 +	// Endian swap bytes already in the bitstream
  97.553 +	void EndianSwapBytes( int byteOffset, int length );
  97.554 +
  97.555 +	/// \brief Aligns the bitstream, writes inputLength, and writes input. Won't write beyond maxBytesToWrite
  97.556 +	/// \param[in] inByteArray The data
  97.557 +	/// \param[in] inputLength The size of input.
  97.558 +	/// \param[in] maxBytesToWrite Max bytes to write
  97.559 +	void WriteAlignedBytesSafe( const char *inByteArray, const unsigned int inputLength, const unsigned int maxBytesToWrite );
  97.560 +
  97.561 +	/// \brief Read bits, starting at the next aligned bits. 
  97.562 +	/// \details Note that the modulus 8 starting offset of the sequence must be the same as
  97.563 +	/// was used with WriteBits. This will be a problem with packet
  97.564 +	/// coalescence unless you byte align the coalesced packets.
  97.565 +	/// \param[in] inOutByteArray The byte array larger than @em numberOfBytesToRead
  97.566 +	/// \param[in] numberOfBytesToRead The number of byte to read from the internal state
  97.567 +	/// \return true if there is enough byte.
  97.568 +	bool ReadAlignedBytes( unsigned char *inOutByteArray, const unsigned int numberOfBytesToRead );
  97.569 +
  97.570 +	/// \brief Reads what was written by WriteAlignedBytesSafe.
  97.571 +	/// \param[in] inOutByteArray The data
  97.572 +	/// \param[in] maxBytesToRead Maximum number of bytes to read
  97.573 +	/// \return true on success, false on failure.
  97.574 +	bool ReadAlignedBytesSafe( char *inOutByteArray, int &inputLength, const int maxBytesToRead );
  97.575 +	bool ReadAlignedBytesSafe( char *inOutByteArray, unsigned int &inputLength, const unsigned int maxBytesToRead );
  97.576 +
  97.577 +	/// \brief Same as ReadAlignedBytesSafe() but allocates the memory for you using new, rather than assuming it is safe to write to
  97.578 +	/// \param[in] outByteArray outByteArray will be deleted if it is not a pointer to 0
  97.579 +	/// \return true on success, false on failure.
  97.580 +	bool ReadAlignedBytesSafeAlloc( char **outByteArray, int &inputLength, const unsigned int maxBytesToRead );
  97.581 +	bool ReadAlignedBytesSafeAlloc( char **outByteArray, unsigned int &inputLength, const unsigned int maxBytesToRead );
  97.582 +
  97.583 +	/// \brief Align the next write and/or read to a byte boundary.  
  97.584 +	/// \details This can be used to 'waste' bits to byte align for efficiency reasons It
  97.585 +	/// can also be used to force coalesced bitstreams to start on byte
  97.586 +	/// boundaries so so WriteAlignedBits and ReadAlignedBits both
  97.587 +	/// calculate the same offset when aligning.
  97.588 +	inline void AlignWriteToByteBoundary( void ) {numberOfBitsUsed += 8 - ( (( numberOfBitsUsed - 1 ) & 7) + 1 );}
  97.589 +
  97.590 +	/// \brief Align the next write and/or read to a byte boundary.  
  97.591 +	/// \details This can be used to 'waste' bits to byte align for efficiency reasons It
  97.592 +	/// can also be used to force coalesced bitstreams to start on byte
  97.593 +	/// boundaries so so WriteAlignedBits and ReadAlignedBits both
  97.594 +	/// calculate the same offset when aligning.
  97.595 +	inline void AlignReadToByteBoundary( void ) {readOffset += 8 - ( (( readOffset - 1 ) & 7 ) + 1 );}
  97.596 +
  97.597 +	/// \brief Read \a numberOfBitsToRead bits to the output source.
  97.598 +	/// \details alignBitsToRight should be set to true to convert internal
  97.599 +	/// bitstream data to userdata. It should be false if you used
  97.600 +	/// WriteBits with rightAlignedBits false
  97.601 +	/// \param[in] inOutByteArray The resulting bits array
  97.602 +	/// \param[in] numberOfBitsToRead The number of bits to read
  97.603 +	/// \param[in] alignBitsToRight if true bits will be right aligned.
  97.604 +	/// \return true if there is enough bits to read
  97.605 +	bool ReadBits( unsigned char *inOutByteArray, BitSize_t numberOfBitsToRead, const bool alignBitsToRight = true );
  97.606 +
  97.607 +	/// \brief Write a 0
  97.608 +	void Write0( void );
  97.609 +
  97.610 +	/// \brief Write a 1
  97.611 +	void Write1( void );
  97.612 +
  97.613 +	/// \brief Reads 1 bit and returns true if that bit is 1 and false if it is 0.
  97.614 +	bool ReadBit( void );
  97.615 +
  97.616 +	/// \brief If we used the constructor version with copy data off, this
  97.617 +	/// *makes sure it is set to on and the data pointed to is copied.
  97.618 +	void AssertCopyData( void );
  97.619 +
  97.620 +	/// \brief Use this if you pass a pointer copy to the constructor
  97.621 +	/// *(_copyData==false) and want to overallocate to prevent
  97.622 +	/// reallocation.
  97.623 +	void SetNumberOfBitsAllocated( const BitSize_t lengthInBits );
  97.624 +
  97.625 +	/// \brief Reallocates (if necessary) in preparation of writing numberOfBitsToWrite
  97.626 +	void AddBitsAndReallocate( const BitSize_t numberOfBitsToWrite );
  97.627 +
  97.628 +	/// \internal
  97.629 +	/// \return How many bits have been allocated internally
  97.630 +	BitSize_t GetNumberOfBitsAllocated(void) const;
  97.631 +
  97.632 +	/// Write zeros until the bitstream is filled up to \a bytes
  97.633 +	void PadWithZeroToByteLength( unsigned int bytes );
  97.634 +
  97.635 +	/// Get the number of leading zeros for a number
  97.636 +	/// \param[in] x Number to test
  97.637 +	static int NumberOfLeadingZeroes( uint8_t x );
  97.638 +	static int NumberOfLeadingZeroes( uint16_t x );
  97.639 +	static int NumberOfLeadingZeroes( uint32_t x );
  97.640 +	static int NumberOfLeadingZeroes( uint64_t x );
  97.641 +	static int NumberOfLeadingZeroes( int8_t x );
  97.642 +	static int NumberOfLeadingZeroes( int16_t x );
  97.643 +	static int NumberOfLeadingZeroes( int32_t x );
  97.644 +	static int NumberOfLeadingZeroes( int64_t x );
  97.645 +
  97.646 +	/// \internal Unrolled inner loop, for when performance is critical
  97.647 +	void WriteAlignedVar8(const char *inByteArray);
  97.648 +	/// \internal Unrolled inner loop, for when performance is critical
  97.649 +	bool ReadAlignedVar8(char *inOutByteArray);
  97.650 +	/// \internal Unrolled inner loop, for when performance is critical
  97.651 +	void WriteAlignedVar16(const char *inByteArray);
  97.652 +	/// \internal Unrolled inner loop, for when performance is critical
  97.653 +	bool ReadAlignedVar16(char *inOutByteArray);
  97.654 +	/// \internal Unrolled inner loop, for when performance is critical
  97.655 +	void WriteAlignedVar32(const char *inByteArray);
  97.656 +	/// \internal Unrolled inner loop, for when performance is critical
  97.657 +	bool ReadAlignedVar32(char *inOutByteArray);
  97.658 +
  97.659 +	inline void Write(const char * const inStringVar)
  97.660 +	{
  97.661 +		uint16_t l = (uint16_t) OVR_strlen(inStringVar);
  97.662 +		Write(l);
  97.663 +		WriteAlignedBytes((const unsigned char*) inStringVar, (const unsigned int) l);
  97.664 +	}
  97.665 +	inline void Write(const unsigned char * const inTemplateVar)
  97.666 +	{
  97.667 +		Write((const char*)inTemplateVar);
  97.668 +	}
  97.669 +	inline void Write(char * const inTemplateVar)
  97.670 +	{
  97.671 +		Write((const char*)inTemplateVar);
  97.672 +	}
  97.673 +	inline void Write(unsigned char * const inTemplateVar)
  97.674 +	{
  97.675 +		Write((const char*)inTemplateVar);
  97.676 +	}
  97.677 +
  97.678 +	/// ---- Member function template specialization declarations ----
  97.679 +	// Used for VC7
  97.680 +#if defined(OVR_CC_MSVC) && _MSC_VER == 1300
  97.681 +	/// Write a bool to a bitstream.
  97.682 +	/// \param[in] var The value to write
  97.683 +	template <>
  97.684 +	void Write(const bool &var);
  97.685 +
  97.686 +	/// Write a RakNetGUID to a bitsteam
  97.687 +	/// \param[in] var The value to write
  97.688 +	template <>
  97.689 +	void Write(const RakNetGuid &var);
  97.690 +
  97.691 +	/// Write a string to a bitstream
  97.692 +	/// \param[in] var The value to write
  97.693 +	template <>
  97.694 +	void Write(const char* const &var);
  97.695 +	template <>
  97.696 +	void Write(const unsigned char* const &var);
  97.697 +	template <>
  97.698 +	void Write(char* const &var);
  97.699 +	template <>
  97.700 +	void Write(unsigned char* const &var);
  97.701 +	template <>
  97.702 +	void Write(const OVR::String &var);
  97.703 +
  97.704 +	/// \brief Write a bool delta.  
  97.705 +	/// \details Same thing as just calling Write
  97.706 +	/// \param[in] currentValue The current value to write
  97.707 +	/// \param[in] lastValue The last value to compare against
  97.708 +	template <>
  97.709 +	void WriteDelta(const bool &currentValue, const bool &lastValue);
  97.710 +
  97.711 +	template <>
  97.712 +	void WriteCompressed(const bool &var);
  97.713 +
  97.714 +	/// For values between -1 and 1
  97.715 +	template <>
  97.716 +	void WriteCompressed(const float &var);
  97.717 +
  97.718 +	/// For values between -1 and 1
  97.719 +	template <>
  97.720 +	void WriteCompressed(const double &var);
  97.721 +	
  97.722 +	/// \brief Write a bool delta.  
  97.723 +	/// \details Same thing as just calling Write
  97.724 +	/// \param[in] currentValue The current value to write
  97.725 +	/// \param[in] lastValue The last value to compare against
  97.726 +	template <>
  97.727 +	void WriteCompressedDelta(const bool &currentValue, const bool &lastValue);
  97.728 +
  97.729 +	/// \brief Save as WriteCompressedDelta(bool currentValue, const templateType &lastValue) 
  97.730 +	/// when we have an unknown second bool
  97.731 +	template <>
  97.732 +	void WriteCompressedDelta(const bool &currentValue);
  97.733 +
  97.734 +	/// \brief Read a bool from a bitstream.
  97.735 +	/// \param[in] var The value to read
  97.736 +	/// \return true on success, false on failure.
  97.737 +	template <>
  97.738 +	bool Read(bool &var);
  97.739 +
  97.740 +	/// \brief Read a String from a bitstream.
  97.741 +	/// \param[in] var The value to read
  97.742 +	/// \return true on success, false on failure.
  97.743 +	template <>
  97.744 +	bool Read(char *&var);
  97.745 +	template <>
  97.746 +	bool Read(wchar_t *&var);
  97.747 +	template <>
  97.748 +	bool Read(unsigned char *&var);
  97.749 +
  97.750 +	/// \brief Read a bool from a bitstream.
  97.751 +	/// \param[in] var The value to read
  97.752 +	/// \return true on success, false on failure.
  97.753 +	template <>
  97.754 +	bool ReadDelta(bool &var);
  97.755 +
  97.756 +	template <>
  97.757 +	bool ReadCompressed(bool &var);
  97.758 +
  97.759 +	template <>
  97.760 +	bool ReadCompressed(float &var);
  97.761 +
  97.762 +	/// For values between -1 and 1
  97.763 +	/// \return true on success, false on failure.
  97.764 +	template <>
  97.765 +	bool ReadCompressed(double &var);
  97.766 +
  97.767 +	template <>
  97.768 +	bool ReadCompressed(char* &var);
  97.769 +	template <>
  97.770 +	bool ReadCompressed(wchar_t* &var);
  97.771 +	template <>
  97.772 +	bool ReadCompressed(unsigned char *&var);
  97.773 +	template <>
  97.774 +	bool ReadCompressed(OVR::String &var);
  97.775 +
  97.776 +	/// \brief Read a bool from a bitstream.
  97.777 +	/// \param[in] var The value to read
  97.778 +	/// \return true on success, false on failure.
  97.779 +	template <>
  97.780 +	bool ReadCompressedDelta(bool &var);
  97.781 +#endif
  97.782 +
  97.783 +	inline static bool DoEndianSwap(void) {
  97.784 +#ifndef __BITSTREAM_NATIVE_END
  97.785 +		return IsNetworkOrder()==false;
  97.786 +#else
  97.787 +		return false;
  97.788 +#endif
  97.789 +	}
  97.790 +	inline static bool IsBigEndian(void)
  97.791 +	{
  97.792 +		return IsNetworkOrder();
  97.793 +	}
  97.794 +	inline static bool IsNetworkOrder(void) {bool r = IsNetworkOrderInternal(); return r;}
  97.795 +	// Not inline, won't compile on PC due to winsock include errors
  97.796 +	static bool IsNetworkOrderInternal(void);
  97.797 +	static void ReverseBytes(unsigned char *inByteArray, unsigned char *inOutByteArray, const unsigned int length);
  97.798 +	static void ReverseBytesInPlace(unsigned char *inOutData,const unsigned int length);
  97.799 +
  97.800 +private:
  97.801 +
  97.802 +	BitStream( const BitStream & /*invalid*/) : numberOfBitsUsed(0), numberOfBitsAllocated(0), readOffset(0),data(NULL), copyData(false) {
  97.803 +		OVR_ASSERT(0);
  97.804 +	}
  97.805 +
  97.806 +	BitStream& operator = ( const BitStream& /*invalid*/ ) {
  97.807 +		OVR_ASSERT(0);
  97.808 +		static BitStream i;
  97.809 +		return i;
  97.810 +	}
  97.811 +
  97.812 +	/// \brief Assume the input source points to a native type, compress and write it.
  97.813 +	void WriteCompressed( const unsigned char* inByteArray, const unsigned int size, const bool unsignedData );
  97.814 +
  97.815 +	/// \brief Assume the input source points to a compressed native type. Decompress and read it.
  97.816 +	bool ReadCompressed( unsigned char* inOutByteArray,	const unsigned int size, const bool unsignedData );
  97.817 +
  97.818 +
  97.819 +	BitSize_t numberOfBitsUsed;
  97.820 +
  97.821 +	BitSize_t numberOfBitsAllocated;
  97.822 +
  97.823 +	BitSize_t readOffset;
  97.824 +
  97.825 +	unsigned char *data;
  97.826 +
  97.827 +	/// true if the internal buffer is copy of the data passed to the constructor
  97.828 +	bool copyData;
  97.829 +
  97.830 +	/// BitStreams that use less than BITSTREAM_STACK_ALLOCATION_SIZE use the stack, rather than the heap to store data.  It switches over if BITSTREAM_STACK_ALLOCATION_SIZE is exceeded
  97.831 +	unsigned char stackData[BITSTREAM_STACK_ALLOCATION_SIZE];
  97.832 +};
  97.833 +
  97.834 +template <class templateType>
  97.835 +inline bool BitStream::Serialize(bool writeToBitstream, templateType &inOutTemplateVar)
  97.836 +{
  97.837 +	if (writeToBitstream)
  97.838 +		Write(inOutTemplateVar);
  97.839 +	else
  97.840 +		return Read(inOutTemplateVar);
  97.841 +	return true;
  97.842 +}
  97.843 +
  97.844 +template <class templateType>
  97.845 +inline bool BitStream::SerializeDelta(bool writeToBitstream, templateType &inOutCurrentValue, const templateType &lastValue)
  97.846 +{
  97.847 +	if (writeToBitstream)
  97.848 +		WriteDelta(inOutCurrentValue, lastValue);
  97.849 +	else
  97.850 +		return ReadDelta(inOutCurrentValue);
  97.851 +	return true;
  97.852 +}
  97.853 +
  97.854 +template <class templateType>
  97.855 +inline bool BitStream::SerializeDelta(bool writeToBitstream, templateType &inOutCurrentValue)
  97.856 +{
  97.857 +	if (writeToBitstream)
  97.858 +		WriteDelta(inOutCurrentValue);
  97.859 +	else
  97.860 +		return ReadDelta(inOutCurrentValue);
  97.861 +	return true;
  97.862 +}
  97.863 +
  97.864 +template <class templateType>
  97.865 +inline bool BitStream::SerializeCompressed(bool writeToBitstream, templateType &inOutTemplateVar)
  97.866 +{
  97.867 +	if (writeToBitstream)
  97.868 +		WriteCompressed(inOutTemplateVar);
  97.869 +	else
  97.870 +		return ReadCompressed(inOutTemplateVar);
  97.871 +	return true;
  97.872 +}
  97.873 +
  97.874 +template <class templateType>
  97.875 +inline bool BitStream::SerializeCompressedDelta(bool writeToBitstream, templateType &inOutCurrentValue, const templateType &lastValue)
  97.876 +{
  97.877 +	if (writeToBitstream)
  97.878 +		WriteCompressedDelta(inOutCurrentValue,lastValue);
  97.879 +	else
  97.880 +		return ReadCompressedDelta(inOutCurrentValue);
  97.881 +	return true;
  97.882 +}
  97.883 +//Stoppedhere
  97.884 +template <class templateType>
  97.885 +inline bool BitStream::SerializeCompressedDelta(bool writeToBitstream, templateType &inOutCurrentValue)
  97.886 +{
  97.887 +	if (writeToBitstream)
  97.888 +		WriteCompressedDelta(inOutCurrentValue);
  97.889 +	else
  97.890 +		return ReadCompressedDelta(inOutCurrentValue);
  97.891 +	return true;
  97.892 +}
  97.893 +
  97.894 +inline bool BitStream::Serialize(bool writeToBitstream, char* inOutByteArray, const unsigned int numberOfBytes )
  97.895 +{
  97.896 +	if (writeToBitstream)
  97.897 +		Write(inOutByteArray, numberOfBytes);
  97.898 +	else
  97.899 +		return Read(inOutByteArray, numberOfBytes);
  97.900 +	return true;
  97.901 +}
  97.902 +
  97.903 +template <class serializationType, class sourceType >
  97.904 +bool BitStream::SerializeCasted( bool writeToBitstream, sourceType &value )
  97.905 +{
  97.906 +	if (writeToBitstream) WriteCasted<serializationType>(value);
  97.907 +	else return ReadCasted<serializationType>(value);
  97.908 +	return true;
  97.909 +}
  97.910 +
  97.911 +template <class templateType>
  97.912 +bool BitStream::SerializeBitsFromIntegerRange( bool writeToBitstream, templateType &value, const templateType minimum, const templateType maximum, bool allowOutsideRange )
  97.913 +{
  97.914 +	int requiredBits=BYTES_TO_BITS(sizeof(templateType))-NumberOfLeadingZeroes(templateType(maximum-minimum));
  97.915 +	return SerializeBitsFromIntegerRange(writeToBitstream,value,minimum,maximum,requiredBits,allowOutsideRange);
  97.916 +}
  97.917 +template <class templateType>
  97.918 +bool BitStream::SerializeBitsFromIntegerRange( bool writeToBitstream, templateType &value, const templateType minimum, const templateType maximum, const int requiredBits, bool allowOutsideRange )
  97.919 +{
  97.920 +	if (writeToBitstream) WriteBitsFromIntegerRange(value,minimum,maximum,requiredBits,allowOutsideRange);
  97.921 +	else return ReadBitsFromIntegerRange(value,minimum,maximum,requiredBits,allowOutsideRange);
  97.922 +	return true;
  97.923 +}
  97.924 +
  97.925 +template <class templateType>
  97.926 +inline bool BitStream::SerializeNormVector(bool writeToBitstream, templateType &x, templateType &y, templateType &z )
  97.927 +{
  97.928 +	if (writeToBitstream)
  97.929 +		WriteNormVector(x,y,z);
  97.930 +	else
  97.931 +		return ReadNormVector(x,y,z);
  97.932 +	return true;
  97.933 +}
  97.934 +
  97.935 +template <class templateType>
  97.936 +inline bool BitStream::SerializeVector(bool writeToBitstream,  templateType &x, templateType &y, templateType &z )
  97.937 +{
  97.938 +	if (writeToBitstream)
  97.939 +		WriteVector(x,y,z);
  97.940 +	else
  97.941 +		return ReadVector(x,y,z);
  97.942 +	return true;
  97.943 +}
  97.944 +
  97.945 +template <class templateType>
  97.946 +inline bool BitStream::SerializeNormQuat(bool writeToBitstream,  templateType &w, templateType &x, templateType &y, templateType &z)
  97.947 +{
  97.948 +	if (writeToBitstream)
  97.949 +		WriteNormQuat(w,x,y,z);
  97.950 +	else
  97.951 +		return ReadNormQuat(w,x,y,z);
  97.952 +	return true;
  97.953 +}
  97.954 +
  97.955 +template <class templateType>
  97.956 +inline bool BitStream::SerializeOrthMatrix(
  97.957 +	bool writeToBitstream,
  97.958 +	templateType &m00, templateType &m01, templateType &m02,
  97.959 +	templateType &m10, templateType &m11, templateType &m12,
  97.960 +	templateType &m20, templateType &m21, templateType &m22 )
  97.961 +{
  97.962 +	if (writeToBitstream)
  97.963 +		WriteOrthMatrix(m00,m01,m02,m10,m11,m12,m20,m21,m22);
  97.964 +	else
  97.965 +		return ReadOrthMatrix(m00,m01,m02,m10,m11,m12,m20,m21,m22);
  97.966 +	return true;
  97.967 +}
  97.968 +
  97.969 +inline bool BitStream::SerializeBits(bool writeToBitstream, unsigned char* inOutByteArray, const BitSize_t numberOfBitsToSerialize, const bool rightAlignedBits )
  97.970 +{
  97.971 +	if (writeToBitstream)
  97.972 +		WriteBits(inOutByteArray,numberOfBitsToSerialize,rightAlignedBits);
  97.973 +	else
  97.974 +		return ReadBits(inOutByteArray,numberOfBitsToSerialize,rightAlignedBits);
  97.975 +	return true;
  97.976 +}
  97.977 +
  97.978 +template <class templateType>
  97.979 +inline void BitStream::Write(const templateType &inTemplateVar)
  97.980 +{
  97.981 +#ifdef OVR_CC_MSVC
  97.982 +#pragma warning(disable:4127)   // conditional expression is constant
  97.983 +#endif
  97.984 +	if (sizeof(inTemplateVar)==1)
  97.985 +		WriteBits( ( unsigned char* ) & inTemplateVar, sizeof( templateType ) * 8, true );
  97.986 +	else
  97.987 +	{
  97.988 +#ifndef __BITSTREAM_NATIVE_END
  97.989 +		if (DoEndianSwap())
  97.990 +		{
  97.991 +			unsigned char output[sizeof(templateType)];
  97.992 +			ReverseBytes((unsigned char*)&inTemplateVar, output, sizeof(templateType));
  97.993 +			WriteBits( ( unsigned char* ) output, sizeof(templateType) * 8, true );
  97.994 +		}
  97.995 +		else
  97.996 +#endif
  97.997 +			WriteBits( ( unsigned char* ) & inTemplateVar, sizeof(templateType) * 8, true );
  97.998 +	}
  97.999 +}
 97.1000 +
 97.1001 +template <class templateType>
 97.1002 +inline void BitStream::WritePtr(templateType *inTemplateVar)
 97.1003 +{
 97.1004 +#ifdef OVR_CC_MSVC
 97.1005 +#pragma warning(disable:4127)   // conditional expression is constant
 97.1006 +#endif
 97.1007 +	if (sizeof(templateType)==1)
 97.1008 +		WriteBits( ( unsigned char* ) inTemplateVar, sizeof( templateType ) * 8, true );
 97.1009 +	else
 97.1010 +	{
 97.1011 +#ifndef __BITSTREAM_NATIVE_END
 97.1012 +		if (DoEndianSwap())
 97.1013 +		{
 97.1014 +			unsigned char output[sizeof(templateType)];
 97.1015 +			ReverseBytes((unsigned char*) inTemplateVar, output, sizeof(templateType));
 97.1016 +			WriteBits( ( unsigned char* ) output, sizeof(templateType) * 8, true );
 97.1017 +		}
 97.1018 +		else
 97.1019 +#endif
 97.1020 +			WriteBits( ( unsigned char* ) inTemplateVar, sizeof(templateType) * 8, true );
 97.1021 +	}
 97.1022 +}
 97.1023 +
 97.1024 +/// \brief Write a bool to a bitstream.
 97.1025 +/// \param[in] inTemplateVar The value to write
 97.1026 +template <>
 97.1027 +inline void BitStream::Write(const bool &inTemplateVar)
 97.1028 +{
 97.1029 +	if ( inTemplateVar )
 97.1030 +		Write1();
 97.1031 +	else
 97.1032 +		Write0();
 97.1033 +}
 97.1034 +
 97.1035 +
 97.1036 +/// \brief Write a string to a bitstream.
 97.1037 +/// \param[in] var The value to write
 97.1038 +template <>
 97.1039 +inline void BitStream::Write(const OVR::String &inTemplateVar)
 97.1040 +{
 97.1041 +	uint16_t l = (uint16_t) inTemplateVar.GetLength();
 97.1042 +	Write(l);
 97.1043 +	WriteAlignedBytes((const unsigned char*) inTemplateVar.ToCStr(), (const unsigned int) l);
 97.1044 +}
 97.1045 +template <>
 97.1046 +inline void BitStream::Write(const char * const &inStringVar)
 97.1047 +{
 97.1048 +	uint16_t l = (uint16_t) strlen(inStringVar);
 97.1049 +	Write(l);
 97.1050 +	WriteAlignedBytes((const unsigned char*) inStringVar, (const unsigned int) l);
 97.1051 +}
 97.1052 +template <>
 97.1053 +inline void BitStream::Write(const unsigned char * const &inTemplateVar)
 97.1054 +{
 97.1055 +	Write((const char*)inTemplateVar);
 97.1056 +}
 97.1057 +template <>
 97.1058 +inline void BitStream::Write(char * const &inTemplateVar)
 97.1059 +{
 97.1060 +	Write((const char*)inTemplateVar);
 97.1061 +}
 97.1062 +template <>
 97.1063 +inline void BitStream::Write(unsigned char * const &inTemplateVar)
 97.1064 +{
 97.1065 +	Write((const char*)inTemplateVar);
 97.1066 +}
 97.1067 +
 97.1068 +/// \brief Write any integral type to a bitstream.  
 97.1069 +/// \details If the current value is different from the last value
 97.1070 +/// the current value will be written.  Otherwise, a single bit will be written
 97.1071 +/// \param[in] currentValue The current value to write
 97.1072 +/// \param[in] lastValue The last value to compare against
 97.1073 +template <class templateType>
 97.1074 +inline void BitStream::WriteDelta(const templateType &currentValue, const templateType &lastValue)
 97.1075 +{
 97.1076 +	if (currentValue==lastValue)
 97.1077 +	{
 97.1078 +		Write(false);
 97.1079 +	}
 97.1080 +	else
 97.1081 +	{
 97.1082 +		Write(true);
 97.1083 +		Write(currentValue);
 97.1084 +	}
 97.1085 +}
 97.1086 +
 97.1087 +/// \brief Write a bool delta. Same thing as just calling Write
 97.1088 +/// \param[in] currentValue The current value to write
 97.1089 +/// \param[in] lastValue The last value to compare against
 97.1090 +template <>
 97.1091 +inline void BitStream::WriteDelta(const bool &currentValue, const bool &lastValue)
 97.1092 +{
 97.1093 +	(void) lastValue;
 97.1094 +
 97.1095 +	Write(currentValue);
 97.1096 +}
 97.1097 +
 97.1098 +/// \brief WriteDelta when you don't know what the last value is, or there is no last value.
 97.1099 +/// \param[in] currentValue The current value to write
 97.1100 +template <class templateType>
 97.1101 +inline void BitStream::WriteDelta(const templateType &currentValue)
 97.1102 +{
 97.1103 +	Write(true);
 97.1104 +	Write(currentValue);
 97.1105 +}
 97.1106 +
 97.1107 +/// \brief Write any integral type to a bitstream.  
 97.1108 +/// \details Undefine __BITSTREAM_NATIVE_END if you need endian swapping.
 97.1109 +/// For floating point, this is lossy, using 2 bytes for a float and 4 for a double.  The range must be between -1 and +1.
 97.1110 +/// For non-floating point, this is lossless, but only has benefit if you use less than half the bits of the type
 97.1111 +/// If you are not using __BITSTREAM_NATIVE_END the opposite is true for types larger than 1 byte
 97.1112 +/// \param[in] inTemplateVar The value to write
 97.1113 +template <class templateType>
 97.1114 +inline void BitStream::WriteCompressed(const templateType &inTemplateVar)
 97.1115 +{
 97.1116 +#ifdef OVR_CC_MSVC
 97.1117 +#pragma warning(disable:4127)   // conditional expression is constant
 97.1118 +#endif
 97.1119 +	if (sizeof(inTemplateVar)==1)
 97.1120 +		WriteCompressed( ( unsigned char* ) & inTemplateVar, sizeof( templateType ) * 8, true );
 97.1121 +	else
 97.1122 +	{
 97.1123 +#ifndef __BITSTREAM_NATIVE_END
 97.1124 +#ifdef OVR_CC_MSVC
 97.1125 +#pragma warning(disable:4244)   // '=' : conversion from 'unsigned long' to 'uint16_t', possible loss of data
 97.1126 +#endif
 97.1127 +
 97.1128 +		if (DoEndianSwap())
 97.1129 +		{
 97.1130 +			unsigned char output[sizeof(templateType)];
 97.1131 +			ReverseBytes((unsigned char*)&inTemplateVar, output, sizeof(templateType));
 97.1132 +			WriteCompressed( ( unsigned char* ) output, sizeof(templateType) * 8, true );
 97.1133 +		}
 97.1134 +		else
 97.1135 +#endif
 97.1136 +			WriteCompressed( ( unsigned char* ) & inTemplateVar, sizeof(templateType) * 8, true );
 97.1137 +	}
 97.1138 +}
 97.1139 +
 97.1140 +template <>
 97.1141 +inline void BitStream::WriteCompressed(const bool &inTemplateVar)
 97.1142 +{
 97.1143 +	Write(inTemplateVar);
 97.1144 +}
 97.1145 +
 97.1146 +/// For values between -1 and 1
 97.1147 +template <>
 97.1148 +inline void BitStream::WriteCompressed(const float &inTemplateVar)
 97.1149 +{
 97.1150 +	OVR_ASSERT(inTemplateVar > -1.01f && inTemplateVar < 1.01f);
 97.1151 +	float varCopy=inTemplateVar;
 97.1152 +	if (varCopy < -1.0f)
 97.1153 +		varCopy=-1.0f;
 97.1154 +	if (varCopy > 1.0f)
 97.1155 +		varCopy=1.0f;
 97.1156 +	Write((uint16_t)((varCopy+1.0f)*32767.5f));
 97.1157 +}
 97.1158 +
 97.1159 +/// For values between -1 and 1
 97.1160 +template <>
 97.1161 +inline void BitStream::WriteCompressed(const double &inTemplateVar)
 97.1162 +{
 97.1163 +	OVR_ASSERT(inTemplateVar > -1.01 && inTemplateVar < 1.01);
 97.1164 +	double varCopy=inTemplateVar;
 97.1165 +	if (varCopy < -1.0f)
 97.1166 +		varCopy=-1.0f;
 97.1167 +	if (varCopy > 1.0f)
 97.1168 +		varCopy=1.0f;
 97.1169 +	Write((uint32_t)((varCopy+1.0)*2147483648.0));
 97.1170 +}
 97.1171 +
 97.1172 +/// \brief Write any integral type to a bitstream.  
 97.1173 +/// \details If the current value is different from the last value
 97.1174 +/// the current value will be written.  Otherwise, a single bit will be written
 97.1175 +/// For floating point, this is lossy, using 2 bytes for a float and 4 for a double.  The range must be between -1 and +1.
 97.1176 +/// For non-floating point, this is lossless, but only has benefit if you use less than half the bits of the type
 97.1177 +/// If you are not using __BITSTREAM_NATIVE_END the opposite is true for types larger than 1 byte
 97.1178 +/// \param[in] currentValue The current value to write
 97.1179 +/// \param[in] lastValue The last value to compare against
 97.1180 +template <class templateType>
 97.1181 +inline void BitStream::WriteCompressedDelta(const templateType &currentValue, const templateType &lastValue)
 97.1182 +{
 97.1183 +	if (currentValue==lastValue)
 97.1184 +	{
 97.1185 +		Write(false);
 97.1186 +	}
 97.1187 +	else
 97.1188 +	{
 97.1189 +		Write(true);
 97.1190 +		WriteCompressed(currentValue);
 97.1191 +	}
 97.1192 +}
 97.1193 +
 97.1194 +/// \brief Write a bool delta.  Same thing as just calling Write
 97.1195 +/// \param[in] currentValue The current value to write
 97.1196 +/// \param[in] lastValue The last value to compare against
 97.1197 +template <>
 97.1198 +inline void BitStream::WriteCompressedDelta(const bool &currentValue, const bool &lastValue)
 97.1199 +{
 97.1200 +	(void) lastValue;
 97.1201 +
 97.1202 +	Write(currentValue);
 97.1203 +}
 97.1204 +
 97.1205 +/// \brief Save as WriteCompressedDelta(const templateType &currentValue, const templateType &lastValue) 
 97.1206 +/// when we have an unknown second parameter
 97.1207 +template <class templateType>
 97.1208 +inline void BitStream::WriteCompressedDelta(const templateType &currentValue)
 97.1209 +{
 97.1210 +	Write(true);
 97.1211 +	WriteCompressed(currentValue);
 97.1212 +}
 97.1213 +
 97.1214 +/// \brief Save as WriteCompressedDelta(bool currentValue, const templateType &lastValue) 
 97.1215 +/// when we have an unknown second bool
 97.1216 +template <>
 97.1217 +inline void BitStream::WriteCompressedDelta(const bool &currentValue)
 97.1218 +{
 97.1219 +	Write(currentValue);
 97.1220 +}
 97.1221 +
 97.1222 +/// \brief Read any integral type from a bitstream.  Define __BITSTREAM_NATIVE_END if you need endian swapping.
 97.1223 +/// \param[in] outTemplateVar The value to read
 97.1224 +template <class templateType>
 97.1225 +inline bool BitStream::Read(templateType &outTemplateVar)
 97.1226 +{
 97.1227 +#ifdef OVR_CC_MSVC
 97.1228 +#pragma warning(disable:4127)   // conditional expression is constant
 97.1229 +#endif
 97.1230 +	if (sizeof(outTemplateVar)==1)
 97.1231 +		return ReadBits( ( unsigned char* ) &outTemplateVar, sizeof(templateType) * 8, true );
 97.1232 +	else
 97.1233 +	{
 97.1234 +#ifndef __BITSTREAM_NATIVE_END
 97.1235 +#ifdef OVR_CC_MSVC
 97.1236 +#pragma warning(disable:4244)   // '=' : conversion from 'unsigned long' to 'uint16_t', possible loss of data
 97.1237 +#endif
 97.1238 +		if (DoEndianSwap())
 97.1239 +		{
 97.1240 +			unsigned char output[sizeof(templateType)];
 97.1241 +			if (ReadBits( ( unsigned char* ) output, sizeof(templateType) * 8, true ))
 97.1242 +			{
 97.1243 +				ReverseBytes(output, (unsigned char*)&outTemplateVar, sizeof(templateType));
 97.1244 +				return true;
 97.1245 +			}
 97.1246 +			return false;
 97.1247 +		}
 97.1248 +		else
 97.1249 +#endif
 97.1250 +			return ReadBits( ( unsigned char* ) & outTemplateVar, sizeof(templateType) * 8, true );
 97.1251 +	}
 97.1252 +}
 97.1253 +
 97.1254 +/// \brief Read a bool from a bitstream.
 97.1255 +/// \param[in] outTemplateVar The value to read
 97.1256 +template <>
 97.1257 +inline bool BitStream::Read(bool &outTemplateVar)
 97.1258 +{
 97.1259 +	if ( readOffset + 1 > numberOfBitsUsed )
 97.1260 +		return false;
 97.1261 +
 97.1262 +	if ( data[ readOffset >> 3 ] & ( 0x80 >> ( readOffset & 7 ) ) )   // Is it faster to just write it out here?
 97.1263 +		outTemplateVar = true;
 97.1264 +	else
 97.1265 +		outTemplateVar = false;
 97.1266 +
 97.1267 +	// Has to be on a different line for Mac
 97.1268 +	readOffset++;
 97.1269 +
 97.1270 +	return true;
 97.1271 +}
 97.1272 +
 97.1273 +template <>
 97.1274 +inline bool BitStream::Read(OVR::String &outTemplateVar)
 97.1275 +{
 97.1276 +	bool b;
 97.1277 +	uint16_t l;
 97.1278 +	b=Read(l);
 97.1279 +	if (b && l>0)
 97.1280 +	{
 97.1281 +		AlignReadToByteBoundary();
 97.1282 +		outTemplateVar.AssignString((const char*) (data + ( readOffset >> 3 )), (size_t) l);
 97.1283 +		IgnoreBytes(l);
 97.1284 +	}
 97.1285 +	else
 97.1286 +	{
 97.1287 +		AlignReadToByteBoundary();
 97.1288 +	}
 97.1289 +	return b;
 97.1290 +}
 97.1291 +template <>
 97.1292 +inline bool BitStream::Read(char *&varString)
 97.1293 +{
 97.1294 +	bool b;
 97.1295 +	uint16_t l;
 97.1296 +	b=Read(l);
 97.1297 +	if (b && l>0)
 97.1298 +	{
 97.1299 +		memcpy(varString, data + ( readOffset >> 3 ), l);
 97.1300 +		IgnoreBytes(l);
 97.1301 +	}
 97.1302 +	else
 97.1303 +	{
 97.1304 +		AlignReadToByteBoundary();
 97.1305 +	}
 97.1306 +	return b;
 97.1307 +}
 97.1308 +template <>
 97.1309 +inline bool BitStream::Read(unsigned char *&varString)
 97.1310 +{
 97.1311 +	bool b;
 97.1312 +	uint16_t l;
 97.1313 +	b=Read(l);
 97.1314 +	if (b && l>0)
 97.1315 +	{
 97.1316 +		memcpy(varString, data + ( readOffset >> 3 ), l);
 97.1317 +		IgnoreBytes(l);
 97.1318 +	}
 97.1319 +	else
 97.1320 +	{
 97.1321 +		AlignReadToByteBoundary();
 97.1322 +	}
 97.1323 +	return b;
 97.1324 +}
 97.1325 +
 97.1326 +/// \brief Read any integral type from a bitstream.  
 97.1327 +/// \details If the written value differed from the value compared against in the write function,
 97.1328 +/// var will be updated.  Otherwise it will retain the current value.
 97.1329 +/// ReadDelta is only valid from a previous call to WriteDelta
 97.1330 +/// \param[in] outTemplateVar The value to read
 97.1331 +template <class templateType>
 97.1332 +inline bool BitStream::ReadDelta(templateType &outTemplateVar)
 97.1333 +{
 97.1334 +	bool dataWritten;
 97.1335 +	bool success;
 97.1336 +	success=Read(dataWritten);
 97.1337 +	if (dataWritten)
 97.1338 +		success=Read(outTemplateVar);
 97.1339 +	return success;
 97.1340 +}
 97.1341 +
 97.1342 +/// \brief Read a bool from a bitstream.
 97.1343 +/// \param[in] outTemplateVar The value to read
 97.1344 +template <>
 97.1345 +inline bool BitStream::ReadDelta(bool &outTemplateVar)
 97.1346 +{
 97.1347 +	return Read(outTemplateVar);
 97.1348 +}
 97.1349 +
 97.1350 +/// \brief Read any integral type from a bitstream.  
 97.1351 +/// \details Undefine __BITSTREAM_NATIVE_END if you need endian swapping.
 97.1352 +/// For floating point, this is lossy, using 2 bytes for a float and 4 for a double.  The range must be between -1 and +1.
 97.1353 +/// For non-floating point, this is lossless, but only has benefit if you use less than half the bits of the type
 97.1354 +/// If you are not using __BITSTREAM_NATIVE_END the opposite is true for types larger than 1 byte
 97.1355 +/// \param[in] outTemplateVar The value to read
 97.1356 +template <class templateType>
 97.1357 +inline bool BitStream::ReadCompressed(templateType &outTemplateVar)
 97.1358 +{
 97.1359 +#ifdef OVR_CC_MSVC
 97.1360 +#pragma warning(disable:4127)   // conditional expression is constant
 97.1361 +#endif
 97.1362 +	if (sizeof(outTemplateVar)==1)
 97.1363 +		return ReadCompressed( ( unsigned char* ) &outTemplateVar, sizeof(templateType) * 8, true );
 97.1364 +	else
 97.1365 +	{
 97.1366 +#ifndef __BITSTREAM_NATIVE_END
 97.1367 +		if (DoEndianSwap())
 97.1368 +		{
 97.1369 +			unsigned char output[sizeof(templateType)];
 97.1370 +			if (ReadCompressed( ( unsigned char* ) output, sizeof(templateType) * 8, true ))
 97.1371 +			{
 97.1372 +				ReverseBytes(output, (unsigned char*)&outTemplateVar, sizeof(templateType));
 97.1373 +				return true;
 97.1374 +			}
 97.1375 +			return false;
 97.1376 +		}
 97.1377 +		else
 97.1378 +#endif
 97.1379 +			return ReadCompressed( ( unsigned char* ) & outTemplateVar, sizeof(templateType) * 8, true );
 97.1380 +	}
 97.1381 +}
 97.1382 +
 97.1383 +template <>
 97.1384 +inline bool BitStream::ReadCompressed(bool &outTemplateVar)
 97.1385 +{
 97.1386 +	return Read(outTemplateVar);
 97.1387 +}
 97.1388 +
 97.1389 +/// For values between -1 and 1
 97.1390 +template <>
 97.1391 +inline bool BitStream::ReadCompressed(float &outTemplateVar)
 97.1392 +{
 97.1393 +	uint16_t compressedFloat;
 97.1394 +	if (Read(compressedFloat))
 97.1395 +	{
 97.1396 +		outTemplateVar = ((float)compressedFloat / 32767.5f - 1.0f);
 97.1397 +		return true;
 97.1398 +	}
 97.1399 +	return false;
 97.1400 +}
 97.1401 +
 97.1402 +/// For values between -1 and 1
 97.1403 +template <>
 97.1404 +inline bool BitStream::ReadCompressed(double &outTemplateVar)
 97.1405 +{
 97.1406 +	uint32_t compressedFloat;
 97.1407 +	if (Read(compressedFloat))
 97.1408 +	{
 97.1409 +		outTemplateVar = ((double)compressedFloat / 2147483648.0 - 1.0);
 97.1410 +		return true;
 97.1411 +	}
 97.1412 +	return false;
 97.1413 +}
 97.1414 +
 97.1415 +/// \brief Read any integral type from a bitstream.  
 97.1416 +/// \details If the written value differed from the value compared against in the write function,
 97.1417 +/// var will be updated.  Otherwise it will retain the current value.
 97.1418 +/// the current value will be updated.
 97.1419 +/// For floating point, this is lossy, using 2 bytes for a float and 4 for a double.  The range must be between -1 and +1.
 97.1420 +/// For non-floating point, this is lossless, but only has benefit if you use less than half the bits of the type
 97.1421 +/// If you are not using __BITSTREAM_NATIVE_END the opposite is true for types larger than 1 byte
 97.1422 +/// ReadCompressedDelta is only valid from a previous call to WriteDelta
 97.1423 +/// \param[in] outTemplateVar The value to read
 97.1424 +template <class templateType>
 97.1425 +inline bool BitStream::ReadCompressedDelta(templateType &outTemplateVar)
 97.1426 +{
 97.1427 +	bool dataWritten;
 97.1428 +	bool success;
 97.1429 +	success=Read(dataWritten);
 97.1430 +	if (dataWritten)
 97.1431 +		success=ReadCompressed(outTemplateVar);
 97.1432 +	return success;
 97.1433 +}
 97.1434 +
 97.1435 +/// \brief Read a bool from a bitstream.
 97.1436 +/// \param[in] outTemplateVar The value to read
 97.1437 +template <>
 97.1438 +inline bool BitStream::ReadCompressedDelta(bool &outTemplateVar)
 97.1439 +{
 97.1440 +	return Read(outTemplateVar);
 97.1441 +}
 97.1442 +
 97.1443 +template <class destinationType, class sourceType >
 97.1444 +void BitStream::WriteCasted( const sourceType &value )
 97.1445 +{
 97.1446 +	destinationType val = (destinationType) value;
 97.1447 +	Write(val);
 97.1448 +}
 97.1449 +
 97.1450 +template <class templateType>
 97.1451 +void BitStream::WriteBitsFromIntegerRange( const templateType value, const templateType minimum,const templateType maximum, bool allowOutsideRange )
 97.1452 +{
 97.1453 +	int requiredBits=BYTES_TO_BITS(sizeof(templateType))-NumberOfLeadingZeroes(templateType(maximum-minimum));
 97.1454 +	WriteBitsFromIntegerRange(value,minimum,maximum,requiredBits,allowOutsideRange);
 97.1455 +}
 97.1456 +template <class templateType>
 97.1457 +void BitStream::WriteBitsFromIntegerRange( const templateType value, const templateType minimum,const templateType maximum, const int requiredBits, bool allowOutsideRange )
 97.1458 +{
 97.1459 +	OVR_ASSERT(maximum>=minimum);
 97.1460 +	OVR_ASSERT(allowOutsideRange==true || (value>=minimum && value<=maximum));
 97.1461 +	if (allowOutsideRange)
 97.1462 +	{
 97.1463 +		if (value<minimum || value>maximum)
 97.1464 +		{
 97.1465 +			Write(true);
 97.1466 +			Write(value);
 97.1467 +			return;
 97.1468 +		}
 97.1469 +		Write(false);
 97.1470 +	}
 97.1471 +	templateType valueOffMin=value-minimum;
 97.1472 +	if (IsBigEndian()==true)
 97.1473 +	{
 97.1474 +		unsigned char output[sizeof(templateType)];
 97.1475 +		ReverseBytes((unsigned char*)&valueOffMin, output, sizeof(templateType));
 97.1476 +		WriteBits(output,requiredBits);
 97.1477 +	}
 97.1478 +	else
 97.1479 +	{
 97.1480 +		WriteBits((unsigned char*) &valueOffMin,requiredBits);
 97.1481 +	}
 97.1482 +}
 97.1483 +
 97.1484 +template <class templateType> // templateType for this function must be a float or double
 97.1485 +void BitStream::WriteNormVector( templateType x, templateType y, templateType z )
 97.1486 +{
 97.1487 +#ifdef _DEBUG
 97.1488 +	OVR_ASSERT(x <= 1.01 && y <= 1.01 && z <= 1.01 && x >= -1.01 && y >= -1.01 && z >= -1.01);
 97.1489 +#endif
 97.1490 +
 97.1491 +	WriteFloat16((float)x,-1.0f,1.0f);
 97.1492 +	WriteFloat16((float)y,-1.0f,1.0f);
 97.1493 +	WriteFloat16((float)z,-1.0f,1.0f);
 97.1494 +}
 97.1495 +
 97.1496 +template <class templateType> // templateType for this function must be a float or double
 97.1497 +void BitStream::WriteVector( templateType x, templateType y, templateType z )
 97.1498 +{
 97.1499 +	templateType magnitude = sqrt(x * x + y * y + z * z);
 97.1500 +	Write((float)magnitude);
 97.1501 +	if (magnitude > 0.00001f)
 97.1502 +	{
 97.1503 +		WriteCompressed((float)(x/magnitude));
 97.1504 +		WriteCompressed((float)(y/magnitude));
 97.1505 +		WriteCompressed((float)(z/magnitude));
 97.1506 +		//	Write((uint16_t)((x/magnitude+1.0f)*32767.5f));
 97.1507 +		//	Write((uint16_t)((y/magnitude+1.0f)*32767.5f));
 97.1508 +		//	Write((uint16_t)((z/magnitude+1.0f)*32767.5f));
 97.1509 +	}
 97.1510 +}
 97.1511 +
 97.1512 +template <class templateType> // templateType for this function must be a float or double
 97.1513 +void BitStream::WriteNormQuat( templateType w, templateType x, templateType y, templateType z)
 97.1514 +{
 97.1515 +	Write((bool)(w<0.0));
 97.1516 +	Write((bool)(x<0.0));
 97.1517 +	Write((bool)(y<0.0));
 97.1518 +	Write((bool)(z<0.0));
 97.1519 +	Write((uint16_t)(fabs(x)*65535.0));
 97.1520 +	Write((uint16_t)(fabs(y)*65535.0));
 97.1521 +	Write((uint16_t)(fabs(z)*65535.0));
 97.1522 +	// Leave out w and calculate it on the target
 97.1523 +}
 97.1524 +
 97.1525 +template <class templateType> // templateType for this function must be a float or double
 97.1526 +void BitStream::WriteOrthMatrix(
 97.1527 +	templateType m00, templateType m01, templateType m02,
 97.1528 +	templateType m10, templateType m11, templateType m12,
 97.1529 +	templateType m20, templateType m21, templateType m22 )
 97.1530 +{
 97.1531 +
 97.1532 +	double qw;
 97.1533 +	double qx;
 97.1534 +	double qy;
 97.1535 +	double qz;
 97.1536 +
 97.1537 +	// Convert matrix to quat
 97.1538 +	// http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/
 97.1539 +	float sum;
 97.1540 +	sum = 1 + m00 + m11 + m22;
 97.1541 +	if (sum < 0.0f) sum=0.0f;
 97.1542 +	qw = sqrt( sum  ) / 2;
 97.1543 +	sum = 1 + m00 - m11 - m22;
 97.1544 +	if (sum < 0.0f) sum=0.0f;
 97.1545 +	qx = sqrt( sum  ) / 2;
 97.1546 +	sum = 1 - m00 + m11 - m22;
 97.1547 +	if (sum < 0.0f) sum=0.0f;
 97.1548 +	qy = sqrt( sum  ) / 2;
 97.1549 +	sum = 1 - m00 - m11 + m22;
 97.1550 +	if (sum < 0.0f) sum=0.0f;
 97.1551 +	qz = sqrt( sum  ) / 2;
 97.1552 +	if (qw < 0.0) qw=0.0;
 97.1553 +	if (qx < 0.0) qx=0.0;
 97.1554 +	if (qy < 0.0) qy=0.0;
 97.1555 +	if (qz < 0.0) qz=0.0;
 97.1556 +#ifdef OVR_OS_WIN32
 97.1557 +	qx = _copysign( (double) qx, (double) (m21 - m12) );
 97.1558 +	qy = _copysign( (double) qy, (double) (m02 - m20) );
 97.1559 +	qz = _copysign( (double) qz, (double) (m10 - m01) );
 97.1560 +#else
 97.1561 +	qx = copysign( (double) qx, (double) (m21 - m12) );
 97.1562 +	qy = copysign( (double) qy, (double) (m02 - m20) );
 97.1563 +	qz = copysign( (double) qz, (double) (m10 - m01) );
 97.1564 +#endif
 97.1565 +
 97.1566 +	WriteNormQuat(qw,qx,qy,qz);
 97.1567 +}
 97.1568 +
 97.1569 +template <class serializationType, class sourceType >
 97.1570 +bool BitStream::ReadCasted( sourceType &value )
 97.1571 +{
 97.1572 +	serializationType val;
 97.1573 +	bool success = Read(val);
 97.1574 +	value=(sourceType) val;
 97.1575 +	return success;
 97.1576 +}
 97.1577 +
 97.1578 +template <class templateType>
 97.1579 +bool BitStream::ReadBitsFromIntegerRange( templateType &value, const templateType minimum, const templateType maximum, bool allowOutsideRange )
 97.1580 +{
 97.1581 +	int requiredBits=BYTES_TO_BITS(sizeof(templateType))-NumberOfLeadingZeroes(templateType(maximum-minimum));
 97.1582 +	return ReadBitsFromIntegerRange(value,minimum,maximum,requiredBits,allowOutsideRange);
 97.1583 +}
 97.1584 +template <class templateType>
 97.1585 +bool BitStream::ReadBitsFromIntegerRange( templateType &value, const templateType minimum, const templateType maximum, const int requiredBits, bool allowOutsideRange )
 97.1586 +{
 97.1587 +	OVR_ASSERT_AND_UNUSED(maximum>=minimum, maximum);
 97.1588 +	if (allowOutsideRange)
 97.1589 +	{
 97.1590 +		bool isOutsideRange;
 97.1591 +		Read(isOutsideRange);
 97.1592 +		if (isOutsideRange)
 97.1593 +			return Read(value);
 97.1594 +	}
 97.1595 +	unsigned char output[sizeof(templateType)];
 97.1596 +	memset(output,0,sizeof(output));
 97.1597 +	bool success = ReadBits(output,requiredBits);
 97.1598 +	if (success)
 97.1599 +	{
 97.1600 +		if (IsBigEndian()==true)
 97.1601 +			ReverseBytesInPlace(output,sizeof(output));
 97.1602 +		memcpy(&value,output,sizeof(output));
 97.1603 +
 97.1604 +		value+=minimum;
 97.1605 +	}
 97.1606 +
 97.1607 +	return success;
 97.1608 +}
 97.1609 +
 97.1610 +template <class templateType> // templateType for this function must be a float or double
 97.1611 +bool BitStream::ReadNormVector( templateType &x, templateType &y, templateType &z )
 97.1612 +{
 97.1613 +	float xIn,yIn,zIn;
 97.1614 +	ReadFloat16(xIn,-1.0f,1.0f);
 97.1615 +	ReadFloat16(yIn,-1.0f,1.0f);
 97.1616 +	ReadFloat16(zIn,-1.0f,1.0f);
 97.1617 +	x=xIn;
 97.1618 +	y=yIn;
 97.1619 +	z=zIn;
 97.1620 +	return true;
 97.1621 +}
 97.1622 +
 97.1623 +template <class templateType> // templateType for this function must be a float or double
 97.1624 +bool BitStream::ReadVector( templateType &x, templateType &y, templateType &z )
 97.1625 +{
 97.1626 +	float magnitude;
 97.1627 +	//uint16_t sx,sy,sz;
 97.1628 +	if (!Read(magnitude))
 97.1629 +		return false;
 97.1630 +	if (magnitude>0.00001f)
 97.1631 +	{
 97.1632 +		//	Read(sx);
 97.1633 +		//	Read(sy);
 97.1634 +		//	if (!Read(sz))
 97.1635 +		//		return false;
 97.1636 +		//	x=((float)sx / 32767.5f - 1.0f) * magnitude;
 97.1637 +		//	y=((float)sy / 32767.5f - 1.0f) * magnitude;
 97.1638 +		//	z=((float)sz / 32767.5f - 1.0f) * magnitude;
 97.1639 +		float cx=0.0f,cy=0.0f,cz=0.0f;
 97.1640 +		ReadCompressed(cx);
 97.1641 +		ReadCompressed(cy);
 97.1642 +		if (!ReadCompressed(cz))
 97.1643 +			return false;
 97.1644 +		x=cx;
 97.1645 +		y=cy;
 97.1646 +		z=cz;
 97.1647 +		x*=magnitude;
 97.1648 +		y*=magnitude;
 97.1649 +		z*=magnitude;
 97.1650 +	}
 97.1651 +	else
 97.1652 +	{
 97.1653 +		x=0.0;
 97.1654 +		y=0.0;
 97.1655 +		z=0.0;
 97.1656 +	}
 97.1657 +	return true;
 97.1658 +}
 97.1659 +
 97.1660 +template <class templateType> // templateType for this function must be a float or double
 97.1661 +bool BitStream::ReadNormQuat( templateType &w, templateType &x, templateType &y, templateType &z)
 97.1662 +{
 97.1663 +	bool cwNeg=false, cxNeg=false, cyNeg=false, czNeg=false;
 97.1664 +	uint16_t cx,cy,cz;
 97.1665 +	Read(cwNeg);
 97.1666 +	Read(cxNeg);
 97.1667 +	Read(cyNeg);
 97.1668 +	Read(czNeg);
 97.1669 +	Read(cx);
 97.1670 +	Read(cy);
 97.1671 +	if (!Read(cz))
 97.1672 +		return false;
 97.1673 +
 97.1674 +	// Calculate w from x,y,z
 97.1675 +	x=(templateType)(cx/65535.0);
 97.1676 +	y=(templateType)(cy/65535.0);
 97.1677 +	z=(templateType)(cz/65535.0);
 97.1678 +	if (cxNeg) x=-x;
 97.1679 +	if (cyNeg) y=-y;
 97.1680 +	if (czNeg) z=-z;
 97.1681 +	float difference = 1.0f - x*x - y*y - z*z;
 97.1682 +	if (difference < 0.0f)
 97.1683 +		difference=0.0f;
 97.1684 +	w = (templateType)(sqrt(difference));
 97.1685 +	if (cwNeg)
 97.1686 +		w=-w;
 97.1687 +
 97.1688 +	return true;
 97.1689 +}
 97.1690 +
 97.1691 +template <class templateType> // templateType for this function must be a float or double
 97.1692 +bool BitStream::ReadOrthMatrix(
 97.1693 +	templateType &m00, templateType &m01, templateType &m02,
 97.1694 +	templateType &m10, templateType &m11, templateType &m12,
 97.1695 +	templateType &m20, templateType &m21, templateType &m22 )
 97.1696 +{
 97.1697 +	float qw,qx,qy,qz;
 97.1698 +	if (!ReadNormQuat(qw,qx,qy,qz))
 97.1699 +		return false;
 97.1700 +
 97.1701 +	// Quat to orthogonal rotation matrix
 97.1702 +	// http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToMatrix/index.htm
 97.1703 +	double sqw = (double)qw*(double)qw;
 97.1704 +	double sqx = (double)qx*(double)qx;
 97.1705 +	double sqy = (double)qy*(double)qy;
 97.1706 +	double sqz = (double)qz*(double)qz;
 97.1707 +	m00 =  (templateType)(sqx - sqy - sqz + sqw); // since sqw + sqx + sqy + sqz =1
 97.1708 +	m11 = (templateType)(-sqx + sqy - sqz + sqw);
 97.1709 +	m22 = (templateType)(-sqx - sqy + sqz + sqw);
 97.1710 +
 97.1711 +	double tmp1 = (double)qx*(double)qy;
 97.1712 +	double tmp2 = (double)qz*(double)qw;
 97.1713 +	m10 = (templateType)(2.0 * (tmp1 + tmp2));
 97.1714 +	m01 = (templateType)(2.0 * (tmp1 - tmp2));
 97.1715 +
 97.1716 +	tmp1 = (double)qx*(double)qz;
 97.1717 +	tmp2 = (double)qy*(double)qw;
 97.1718 +	m20 =(templateType)(2.0 * (tmp1 - tmp2));
 97.1719 +	m02 = (templateType)(2.0 * (tmp1 + tmp2));
 97.1720 +	tmp1 = (double)qy*(double)qz;
 97.1721 +	tmp2 = (double)qx*(double)qw;
 97.1722 +	m21 = (templateType)(2.0 * (tmp1 + tmp2));
 97.1723 +	m12 = (templateType)(2.0 * (tmp1 - tmp2));
 97.1724 +
 97.1725 +	return true;
 97.1726 +}
 97.1727 +
 97.1728 +template <class templateType>
 97.1729 +BitStream& operator<<(BitStream& out, templateType& c)
 97.1730 +{
 97.1731 +	out.Write(c);
 97.1732 +	return out;
 97.1733 +}
 97.1734 +template <class templateType>
 97.1735 +BitStream& operator>>(BitStream& in, templateType& c)
 97.1736 +{
 97.1737 +	bool success = in.Read(c);
 97.1738 +	(void)success;
 97.1739 +
 97.1740 +	OVR_ASSERT(success);
 97.1741 +	return in;
 97.1742 +}
 97.1743 +
 97.1744 +
 97.1745 +}} // OVR::Net
 97.1746 +
 97.1747 +#endif
    98.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    98.2 +++ b/LibOVR/Src/Net/OVR_MessageIDTypes.h	Wed Jan 14 06:51:16 2015 +0200
    98.3 @@ -0,0 +1,39 @@
    98.4 +/************************************************************************************
    98.5 +
    98.6 +Filename    :   OVR_MessageIDTypes.h
    98.7 +Content     :   Enumeration list indicating what type of message is being sent
    98.8 +Created     :   July 3, 2014
    98.9 +Authors     :   Kevin Jenkins
   98.10 +
   98.11 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   98.12 +
   98.13 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
   98.14 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
   98.15 +which is provided at the time of installation or download, or which 
   98.16 +otherwise accompanies this software in either electronic or hard copy form.
   98.17 +
   98.18 +You may obtain a copy of the License at
   98.19 +
   98.20 +http://www.oculusvr.com/licenses/LICENSE-3.2 
   98.21 +
   98.22 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
   98.23 +distributed under the License is distributed on an "AS IS" BASIS,
   98.24 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   98.25 +See the License for the specific language governing permissions and
   98.26 +limitations under the License.
   98.27 +
   98.28 +************************************************************************************/
   98.29 +
   98.30 +namespace OVR { namespace Net {
   98.31 +
   98.32 +/// First byte of a network message
   98.33 +typedef unsigned char MessageID;
   98.34 +
   98.35 +enum DefaultMessageIDTypes
   98.36 +{
   98.37 +    OVRID_RPC1,
   98.38 +    OVRID_END = 128,
   98.39 +    OVRID_LATENCY_TESTER_1,
   98.40 +};
   98.41 +
   98.42 +}} // namespace OVR::Net
    99.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    99.2 +++ b/LibOVR/Src/Net/OVR_NetworkPlugin.cpp	Wed Jan 14 06:51:16 2015 +0200
    99.3 @@ -0,0 +1,70 @@
    99.4 +/************************************************************************************
    99.5 +
    99.6 +Filename    :   OVR_NetworkPlugin.cpp
    99.7 +Content     :   Base class for an extension to the network objects.
    99.8 +Created     :   June 10, 2014
    99.9 +Authors     :   Kevin Jenkins
   99.10 +
   99.11 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
   99.12 +
   99.13 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
   99.14 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
   99.15 +which is provided at the time of installation or download, or which 
   99.16 +otherwise accompanies this software in either electronic or hard copy form.
   99.17 +
   99.18 +You may obtain a copy of the License at
   99.19 +
   99.20 +http://www.oculusvr.com/licenses/LICENSE-3.2 
   99.21 +
   99.22 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
   99.23 +distributed under the License is distributed on an "AS IS" BASIS,
   99.24 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   99.25 +See the License for the specific language governing permissions and
   99.26 +limitations under the License.
   99.27 +
   99.28 +************************************************************************************/
   99.29 +
   99.30 +#include "OVR_NetworkPlugin.h"
   99.31 +
   99.32 +namespace OVR { namespace Net { namespace Plugins {
   99.33 +
   99.34 +
   99.35 +//-----------------------------------------------------------------------------
   99.36 +// Plugin identifier to assign next
   99.37 +
   99.38 +//static uint8_t pluginIdNext = 0;
   99.39 +
   99.40 +
   99.41 +//-----------------------------------------------------------------------------
   99.42 +// NetworkPlugin
   99.43 +
   99.44 +NetworkPlugin::NetworkPlugin()
   99.45 +{
   99.46 +	pSession = 0;
   99.47 +	//PluginId = pluginIdNext++;
   99.48 +}
   99.49 +
   99.50 +NetworkPlugin::~NetworkPlugin()
   99.51 +{
   99.52 +}
   99.53 +
   99.54 +void NetworkPlugin::OnAddedToSession(Session* _pSession)
   99.55 +{
   99.56 +	if (pSession != 0)
   99.57 +	{
   99.58 +		pSession->RemoveSessionListener(this);
   99.59 +	}
   99.60 +
   99.61 +	pSession = _pSession;
   99.62 +}
   99.63 +
   99.64 +void NetworkPlugin::OnRemovedFromSession(Session* _pSession)
   99.65 +{
   99.66 +	OVR_UNUSED(_pSession);
   99.67 +	OVR_ASSERT(_pSession == pSession);
   99.68 +
   99.69 +	pSession = 0;
   99.70 +}
   99.71 +
   99.72 +
   99.73 +}}} // OVR::Net::Plugins
   100.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   100.2 +++ b/LibOVR/Src/Net/OVR_NetworkPlugin.h	Wed Jan 14 06:51:16 2015 +0200
   100.3 @@ -0,0 +1,60 @@
   100.4 +/************************************************************************************
   100.5 +
   100.6 +PublicHeader:   n/a
   100.7 +Filename    :   OVR_NetworkPlugin.h
   100.8 +Content     :   Base class for an extension to the network objects.
   100.9 +Created     :   June 10, 2014
  100.10 +Authors     :   Kevin Jenkins
  100.11 +
  100.12 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
  100.13 +
  100.14 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
  100.15 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
  100.16 +which is provided at the time of installation or download, or which 
  100.17 +otherwise accompanies this software in either electronic or hard copy form.
  100.18 +
  100.19 +You may obtain a copy of the License at
  100.20 +
  100.21 +http://www.oculusvr.com/licenses/LICENSE-3.2 
  100.22 +
  100.23 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
  100.24 +distributed under the License is distributed on an "AS IS" BASIS,
  100.25 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  100.26 +See the License for the specific language governing permissions and
  100.27 +limitations under the License.
  100.28 +
  100.29 +************************************************************************************/
  100.30 +
  100.31 +#ifndef OVR_NetworkPlugin_h
  100.32 +#define OVR_NetworkPlugin_h
  100.33 +
  100.34 +#include "OVR_Session.h"
  100.35 +
  100.36 +namespace OVR { namespace Net { namespace Plugins {
  100.37 +
  100.38 +
  100.39 +//-----------------------------------------------------------------------------
  100.40 +// NetworkPlugin
  100.41 +
  100.42 +// NetworkPlugins use Session and SessionListener to provide network functionality
  100.43 +// independent of the transport medium.
  100.44 +// Uses the chain of command design pattern such that plugins can invoke or intercept
  100.45 +// network events via the Session.
  100.46 +class NetworkPlugin : public SessionListener
  100.47 +{
  100.48 +public:
  100.49 +	NetworkPlugin();
  100.50 +	virtual ~NetworkPlugin();
  100.51 +
  100.52 +protected:
  100.53 +	virtual void OnAddedToSession(Session* _pSession);
  100.54 +	virtual void OnRemovedFromSession(Session* _pSession);
  100.55 +
  100.56 +	Session *pSession;
  100.57 +	//uint8_t PluginId;
  100.58 +};
  100.59 +
  100.60 +
  100.61 +}}} // OVR::Net::Plugins
  100.62 +
  100.63 +#endif
   101.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   101.2 +++ b/LibOVR/Src/Net/OVR_NetworkTypes.h	Wed Jan 14 06:51:16 2015 +0200
   101.3 @@ -0,0 +1,42 @@
   101.4 +/************************************************************************************
   101.5 +
   101.6 +PublicHeader:   n/a
   101.7 +Filename    :   OVR_NetworkTypes.h
   101.8 +Content     :   Shared header for network types
   101.9 +Created     :   June 12, 2014
  101.10 +Authors     :   Kevin Jenkins
  101.11 +
  101.12 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
  101.13 +
  101.14 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License");
  101.15 +you may not use the Oculus VR Rift SDK except in compliance with the License,
  101.16 +which is provided at the time of installation or download, or which
  101.17 +otherwise accompanies this software in either electronic or hard copy form.
  101.18 +
  101.19 +You may obtain a copy of the License at
  101.20 +
  101.21 +http://www.oculusvr.com/licenses/LICENSE-3.2
  101.22 +
  101.23 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK
  101.24 +distributed under the License is distributed on an "AS IS" BASIS,
  101.25 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  101.26 +See the License for the specific language governing permissions and
  101.27 +limitations under the License.
  101.28 +
  101.29 +************************************************************************************/
  101.30 +
  101.31 +#ifndef OVR_NetworkTypes_h
  101.32 +#define OVR_NetworkTypes_h
  101.33 +
  101.34 +#include "../Kernel/OVR_Types.h"
  101.35 +
  101.36 +namespace OVR {	namespace Net {
  101.37 +
  101.38 +
  101.39 +typedef uint64_t NetworkID;
  101.40 +const NetworkID InvalidNetworkID = ~((NetworkID)0);
  101.41 +
  101.42 +
  101.43 +} } // OVR::Net
  101.44 +
  101.45 +#endif
   102.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   102.2 +++ b/LibOVR/Src/Net/OVR_PacketizedTCPSocket.cpp	Wed Jan 14 06:51:16 2015 +0200
   102.3 @@ -0,0 +1,215 @@
   102.4 +/************************************************************************************
   102.5 +
   102.6 +Filename    :   OVR_PacketizedTCPSocket.cpp
   102.7 +Content     :   TCP with automated message framing.
   102.8 +Created     :   June 10, 2014
   102.9 +Authors     :   Kevin Jenkins
  102.10 +
  102.11 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
  102.12 +
  102.13 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
  102.14 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
  102.15 +which is provided at the time of installation or download, or which 
  102.16 +otherwise accompanies this software in either electronic or hard copy form.
  102.17 +
  102.18 +You may obtain a copy of the License at
  102.19 +
  102.20 +http://www.oculusvr.com/licenses/LICENSE-3.2 
  102.21 +
  102.22 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
  102.23 +distributed under the License is distributed on an "AS IS" BASIS,
  102.24 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  102.25 +See the License for the specific language governing permissions and
  102.26 +limitations under the License.
  102.27 +
  102.28 +************************************************************************************/
  102.29 +
  102.30 +#include "OVR_PacketizedTCPSocket.h"
  102.31 +
  102.32 +namespace OVR { namespace Net {
  102.33 +
  102.34 +
  102.35 +//-----------------------------------------------------------------------------
  102.36 +// Constants
  102.37 +
  102.38 +static const int LENGTH_FIELD_BYTES = 4;
  102.39 +
  102.40 +
  102.41 +//-----------------------------------------------------------------------------
  102.42 +// PacketizedTCPSocket
  102.43 +
  102.44 +PacketizedTCPSocket::PacketizedTCPSocket()
  102.45 +{
  102.46 +	pRecvBuff = 0;
  102.47 +	pRecvBuffSize = 0;
  102.48 +	Transport = TransportType_PacketizedTCP;
  102.49 +}
  102.50 +
  102.51 +PacketizedTCPSocket::PacketizedTCPSocket(SocketHandle _sock, bool isListenSocket) : PacketizedTCPSocketBase(_sock, isListenSocket)
  102.52 +{
  102.53 +	pRecvBuff = 0;
  102.54 +	pRecvBuffSize = 0;
  102.55 +	Transport = TransportType_PacketizedTCP;
  102.56 +}
  102.57 +
  102.58 +PacketizedTCPSocket::~PacketizedTCPSocket()
  102.59 +{
  102.60 +	OVR_FREE(pRecvBuff);
  102.61 +}
  102.62 +
  102.63 +int PacketizedTCPSocket::Send(const void* pData, int bytes)
  102.64 +{
  102.65 +    Lock::Locker locker(&sendLock);
  102.66 +
  102.67 +	if (bytes <= 0)
  102.68 +	{
  102.69 +		return -1;
  102.70 +	}
  102.71 +
  102.72 +	// Convert length to 4 endian-neutral bytes
  102.73 +	uint32_t lengthWord = bytes;
  102.74 +	uint8_t lengthBytes[LENGTH_FIELD_BYTES] = {
  102.75 +		(uint8_t)lengthWord,
  102.76 +		(uint8_t)(lengthWord >> 8),
  102.77 +		(uint8_t)(lengthWord >> 16),
  102.78 +		(uint8_t)(lengthWord >> 24)
  102.79 +	};
  102.80 +
  102.81 +	int s = PacketizedTCPSocketBase::Send(lengthBytes, LENGTH_FIELD_BYTES);
  102.82 +	if (s > 0)
  102.83 +	{
  102.84 +		return PacketizedTCPSocketBase::Send(pData,bytes);
  102.85 +	}
  102.86 +	else
  102.87 +	{
  102.88 +		return s;
  102.89 +	}
  102.90 +}
  102.91 +
  102.92 +int PacketizedTCPSocket::SendAndConcatenate(const void** pDataArray, int* dataLengthArray, int arrayCount)
  102.93 +{
  102.94 +    Lock::Locker locker(&sendLock);
  102.95 +
  102.96 +    if (arrayCount == 0)
  102.97 +		return 0;
  102.98 +
  102.99 +	int totalBytes = 0;
 102.100 +	for (int i = 0; i < arrayCount; i++)
 102.101 +		totalBytes += dataLengthArray[i];
 102.102 +
 102.103 +	// Convert length to 4 endian-neutral bytes
 102.104 +	uint32_t lengthWord = totalBytes;
 102.105 +	uint8_t lengthBytes[LENGTH_FIELD_BYTES] = {
 102.106 +		(uint8_t)lengthWord,
 102.107 +		(uint8_t)(lengthWord >> 8),
 102.108 +		(uint8_t)(lengthWord >> 16),
 102.109 +		(uint8_t)(lengthWord >> 24)
 102.110 +	};
 102.111 +
 102.112 +	int s = PacketizedTCPSocketBase::Send(lengthBytes, LENGTH_FIELD_BYTES);
 102.113 +	if (s > 0)
 102.114 +	{
 102.115 +		for (int i = 0; i < arrayCount; i++)
 102.116 +		{
 102.117 +			PacketizedTCPSocketBase::Send(pDataArray[i], dataLengthArray[i]);
 102.118 +		}
 102.119 +	}
 102.120 +
 102.121 +	return s;
 102.122 +}
 102.123 +
 102.124 +void PacketizedTCPSocket::OnRecv(SocketEvent_TCP* eventHandler, uint8_t* pData, int bytesRead)
 102.125 +{
 102.126 +	uint8_t* dataSource = NULL;
 102.127 +	int dataSourceSize = 0;
 102.128 +
 102.129 +	recvBuffLock.DoLock();
 102.130 +
 102.131 +	if (pRecvBuff == NULL)
 102.132 +	{
 102.133 +		dataSource = pData;
 102.134 +		dataSourceSize = bytesRead;
 102.135 +	}
 102.136 +	else
 102.137 +	{
 102.138 +		uint8_t* pRecvBuffNew = (uint8_t*)OVR_REALLOC(pRecvBuff, bytesRead + pRecvBuffSize);
 102.139 +		if (!pRecvBuffNew)
 102.140 +		{
 102.141 +			OVR_FREE(pRecvBuff);
 102.142 +			pRecvBuff = NULL;
 102.143 +			pRecvBuffSize = 0;
 102.144 +			recvBuffLock.Unlock();
 102.145 +			return;
 102.146 +		}
 102.147 +		else
 102.148 +		{
 102.149 +			pRecvBuff = pRecvBuffNew;
 102.150 +
 102.151 +			memcpy(pRecvBuff + pRecvBuffSize, pData, bytesRead);
 102.152 +
 102.153 +			dataSourceSize = pRecvBuffSize + bytesRead;
 102.154 +			dataSource = pRecvBuff;
 102.155 +		}
 102.156 +	}
 102.157 +
 102.158 +	int bytesReadFromStream;
 102.159 +	while (bytesReadFromStream = BytesFromStream(dataSource, dataSourceSize),
 102.160 +		   LENGTH_FIELD_BYTES + bytesReadFromStream <= dataSourceSize)
 102.161 +	{
 102.162 +		dataSource += LENGTH_FIELD_BYTES;
 102.163 +		dataSourceSize -= LENGTH_FIELD_BYTES;
 102.164 +
 102.165 +		TCPSocket::OnRecv(eventHandler, dataSource, bytesReadFromStream);
 102.166 +
 102.167 +		dataSource += bytesReadFromStream;
 102.168 +		dataSourceSize -= bytesReadFromStream;
 102.169 +	}
 102.170 +
 102.171 +	if (dataSourceSize > 0)
 102.172 +	{
 102.173 +        if (dataSource != NULL)
 102.174 +        {
 102.175 +            if (pRecvBuff == NULL)
 102.176 +            {
 102.177 +                pRecvBuff = (uint8_t*)OVR_ALLOC(dataSourceSize);
 102.178 +                if (!pRecvBuff)
 102.179 +                {
 102.180 +                    pRecvBuffSize = 0;
 102.181 +                    recvBuffLock.Unlock();
 102.182 +                    return;
 102.183 +                }
 102.184 +                else
 102.185 +                {
 102.186 +                    memcpy(pRecvBuff, dataSource, dataSourceSize);
 102.187 +                }
 102.188 +            }
 102.189 +            else
 102.190 +            {
 102.191 +                memmove(pRecvBuff, dataSource, dataSourceSize);
 102.192 +            }
 102.193 +        }
 102.194 +	}
 102.195 +	else
 102.196 +	{
 102.197 +		if (pRecvBuff != NULL)
 102.198 +			OVR_FREE(pRecvBuff);
 102.199 +
 102.200 +		pRecvBuff = NULL;
 102.201 +	}
 102.202 +	pRecvBuffSize = dataSourceSize;
 102.203 +
 102.204 +	recvBuffLock.Unlock();
 102.205 +}
 102.206 +
 102.207 +int PacketizedTCPSocket::BytesFromStream(uint8_t* pData, int bytesRead)
 102.208 +{
 102.209 +	if (pData != 0 && bytesRead >= LENGTH_FIELD_BYTES)
 102.210 +	{
 102.211 +		return pData[0] | ((uint32_t)pData[1] << 8) | ((uint32_t)pData[2] << 16) | ((uint32_t)pData[3] << 24);
 102.212 +	}
 102.213 +
 102.214 +	return 0;
 102.215 +}
 102.216 +
 102.217 +
 102.218 +}} // OVR::Net
   103.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   103.2 +++ b/LibOVR/Src/Net/OVR_PacketizedTCPSocket.h	Wed Jan 14 06:51:16 2015 +0200
   103.3 @@ -0,0 +1,87 @@
   103.4 +/************************************************************************************
   103.5 +
   103.6 +PublicHeader:   n/a
   103.7 +Filename    :   OVR_PacketizedTCPSocket.cpp
   103.8 +Content     :   TCP with automated message framing.
   103.9 +Created     :   June 10, 2014
  103.10 +Authors     :   Kevin Jenkins
  103.11 +
  103.12 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
  103.13 +
  103.14 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
  103.15 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
  103.16 +which is provided at the time of installation or download, or which 
  103.17 +otherwise accompanies this software in either electronic or hard copy form.
  103.18 +
  103.19 +You may obtain a copy of the License at
  103.20 +
  103.21 +http://www.oculusvr.com/licenses/LICENSE-3.2 
  103.22 +
  103.23 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
  103.24 +distributed under the License is distributed on an "AS IS" BASIS,
  103.25 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  103.26 +See the License for the specific language governing permissions and
  103.27 +limitations under the License.
  103.28 +
  103.29 +************************************************************************************/
  103.30 +
  103.31 +#ifndef OVR_PacketizedTCPSocket_h
  103.32 +#define OVR_PacketizedTCPSocket_h
  103.33 +
  103.34 +#include "OVR_Socket.h"
  103.35 +#include "../Kernel/OVR_Allocator.h"
  103.36 +#include "../Kernel/OVR_Atomic.h"
  103.37 +
  103.38 +#ifdef OVR_OS_WIN32
  103.39 +#include "OVR_Win32_Socket.h"
  103.40 +#else
  103.41 +#include "OVR_Unix_Socket.h"
  103.42 +#endif
  103.43 +
  103.44 +namespace OVR { namespace Net {
  103.45 +
  103.46 +
  103.47 +//-----------------------------------------------------------------------------
  103.48 +// NetworkPlugin
  103.49 +
  103.50 +// Packetized TCP base socket
  103.51 +class PacketizedTCPSocketBase : public TCPSocket
  103.52 +{
  103.53 +public:
  103.54 +	PacketizedTCPSocketBase() {}
  103.55 +	PacketizedTCPSocketBase(SocketHandle _sock, bool isListenSocket) : TCPSocket(_sock, isListenSocket) {}
  103.56 +};
  103.57 +
  103.58 +
  103.59 +//-----------------------------------------------------------------------------
  103.60 +// PacketizedTCPSocket
  103.61 +
  103.62 +// Uses TCP but is message aligned rather than stream aligned
  103.63 +// Alternative to reliable UDP
  103.64 +class PacketizedTCPSocket : public PacketizedTCPSocketBase
  103.65 +{
  103.66 +public:
  103.67 +	PacketizedTCPSocket();
  103.68 +	PacketizedTCPSocket(SocketHandle _sock, bool isListenSocket);
  103.69 +	virtual ~PacketizedTCPSocket();
  103.70 +
  103.71 +public:
  103.72 +	virtual int Send(const void* pData, int bytes);
  103.73 +	virtual int SendAndConcatenate(const void** pDataArray, int *dataLengthArray, int arrayCount);
  103.74 +
  103.75 +protected:
  103.76 +	virtual void OnRecv(SocketEvent_TCP* eventHandler, uint8_t* pData, int bytesRead);
  103.77 +
  103.78 +	int BytesFromStream(uint8_t* pData, int bytesRead);
  103.79 +
  103.80 +    Lock   sendLock;
  103.81 +    Lock   recvBuffLock;
  103.82 +
  103.83 +	uint8_t* pRecvBuff;     // Queued receive buffered data
  103.84 +	int    pRecvBuffSize; // Size of receive queue in bytes
  103.85 +};
  103.86 +
  103.87 +
  103.88 +}} // OVR::Net
  103.89 +
  103.90 +#endif
   104.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   104.2 +++ b/LibOVR/Src/Net/OVR_RPC1.cpp	Wed Jan 14 06:51:16 2015 +0200
   104.3 @@ -0,0 +1,270 @@
   104.4 +/************************************************************************************
   104.5 +
   104.6 +Filename    :   OVR_RPC1.cpp
   104.7 +Content     :   A network plugin that provides remote procedure call functionality.
   104.8 +Created     :   June 10, 2014
   104.9 +Authors     :   Kevin Jenkins
  104.10 +
  104.11 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
  104.12 +
  104.13 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
  104.14 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
  104.15 +which is provided at the time of installation or download, or which 
  104.16 +otherwise accompanies this software in either electronic or hard copy form.
  104.17 +
  104.18 +You may obtain a copy of the License at
  104.19 +
  104.20 +http://www.oculusvr.com/licenses/LICENSE-3.2 
  104.21 +
  104.22 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
  104.23 +distributed under the License is distributed on an "AS IS" BASIS,
  104.24 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  104.25 +See the License for the specific language governing permissions and
  104.26 +limitations under the License.
  104.27 +
  104.28 +************************************************************************************/
  104.29 +
  104.30 +#include "OVR_RPC1.h"
  104.31 +#include "OVR_BitStream.h"
  104.32 +#include "../Kernel/OVR_Threads.h" // Thread::MSleep
  104.33 +#include "OVR_MessageIDTypes.h"
  104.34 +
  104.35 +namespace OVR { namespace Net { namespace Plugins {
  104.36 +
  104.37 +
  104.38 +//-----------------------------------------------------------------------------
  104.39 +// Types
  104.40 +
  104.41 +enum {
  104.42 +	ID_RPC4_SIGNAL,
  104.43 +	CALL_BLOCKING,
  104.44 +	RPC_ERROR_FUNCTION_NOT_REGISTERED,
  104.45 +	ID_RPC4_RETURN,
  104.46 +};
  104.47 +
  104.48 +
  104.49 +//-----------------------------------------------------------------------------
  104.50 +// RPC1
  104.51 +
  104.52 +RPC1::RPC1()
  104.53 +{
  104.54 +	blockingOnThisConnection = 0;
  104.55 +	blockingReturnValue = new BitStream();
  104.56 +}
  104.57 +
  104.58 +RPC1::~RPC1()
  104.59 +{
  104.60 +	slotHash.Clear();
  104.61 +	delete blockingReturnValue;
  104.62 +}
  104.63 +
  104.64 +void RPC1::RegisterSlot(OVR::String sharedIdentifier,  OVR::Observer<RPCSlot>* rpcSlotObserver )
  104.65 +{
  104.66 +	slotHash.AddObserverToSubject(sharedIdentifier, rpcSlotObserver);
  104.67 +}
  104.68 +
  104.69 +bool RPC1::RegisterBlockingFunction(OVR::String uniqueID, RPCDelegate blockingFunction)
  104.70 +{
  104.71 +	if (registeredBlockingFunctions.Get(uniqueID))
  104.72 +		return false;
  104.73 +
  104.74 +	registeredBlockingFunctions.Set(uniqueID, blockingFunction);
  104.75 +	return true;
  104.76 +}
  104.77 +
  104.78 +void RPC1::UnregisterBlockingFunction(OVR::String uniqueID)
  104.79 +{
  104.80 +	registeredBlockingFunctions.Remove(uniqueID);
  104.81 +}
  104.82 +
  104.83 +bool RPC1::CallBlocking( OVR::String uniqueID, OVR::Net::BitStream* bitStream, Ptr<Connection> pConnection, OVR::Net::BitStream* returnData )
  104.84 +{
  104.85 +    // If invalid parameters,
  104.86 +    if (!pConnection)
  104.87 +    {
  104.88 +        // Note: This may happen if the endpoint disconnects just before the call
  104.89 +        return false;
  104.90 +    }
  104.91 +
  104.92 +	OVR::Net::BitStream out;
  104.93 +	out.Write((MessageID) OVRID_RPC1);
  104.94 +	out.Write((MessageID) CALL_BLOCKING);
  104.95 +	out.Write(uniqueID);
  104.96 +	if (bitStream)
  104.97 +	{
  104.98 +		bitStream->ResetReadPointer();
  104.99 +		out.AlignWriteToByteBoundary();
 104.100 +		out.Write(bitStream);
 104.101 +	}
 104.102 +
 104.103 +	SendParameters sp(pConnection, out.GetData(), out.GetNumberOfBytesUsed());
 104.104 +
 104.105 +    if (returnData)
 104.106 +    {
 104.107 +        returnData->Reset();
 104.108 +    }
 104.109 +
 104.110 +    // Only one thread call at a time
 104.111 +    Lock::Locker singleRPCLocker(&singleRPCLock);
 104.112 +
 104.113 +    // Note this does not prevent multiple calls at a time because .Wait will unlock it below.
 104.114 +    // The purpose of this mutex is to synchronize the polling thread and this one, not prevent
 104.115 +    // multiple threads from invoking RPC.
 104.116 +    Mutex::Locker locker(&callBlockingMutex);
 104.117 +
 104.118 +    blockingReturnValue->Reset();
 104.119 +    blockingOnThisConnection = pConnection;
 104.120 +
 104.121 +    int bytesSent = pSession->Send(&sp);
 104.122 +    if (bytesSent == sp.Bytes)
 104.123 +    {
 104.124 +        while (blockingOnThisConnection == pConnection)
 104.125 +        {
 104.126 +            callBlockingWait.Wait(&callBlockingMutex);
 104.127 +        }
 104.128 +    }
 104.129 +	else
 104.130 +	{
 104.131 +		return false;
 104.132 +	}
 104.133 +
 104.134 +    if (returnData)
 104.135 +    {
 104.136 +        returnData->Write(blockingReturnValue);
 104.137 +        returnData->ResetReadPointer();
 104.138 +    }
 104.139 +
 104.140 +	return true;
 104.141 +}
 104.142 +
 104.143 +bool RPC1::Signal(OVR::String sharedIdentifier, OVR::Net::BitStream* bitStream, Ptr<Connection> pConnection)
 104.144 +{
 104.145 +	OVR::Net::BitStream out;
 104.146 +	out.Write((MessageID) OVRID_RPC1);
 104.147 +	out.Write((MessageID) ID_RPC4_SIGNAL);
 104.148 +	//out.Write(PluginId);
 104.149 +	out.Write(sharedIdentifier);
 104.150 +	if (bitStream)
 104.151 +	{
 104.152 +		bitStream->ResetReadPointer();
 104.153 +		out.AlignWriteToByteBoundary();
 104.154 +		out.Write(bitStream);
 104.155 +	}
 104.156 +	SendParameters sp(pConnection, out.GetData(), out.GetNumberOfBytesUsed());
 104.157 +	int32_t bytesSent = pSession->Send(&sp);
 104.158 +	return bytesSent == sp.Bytes;
 104.159 +}
 104.160 +void RPC1::BroadcastSignal(OVR::String sharedIdentifier, OVR::Net::BitStream* bitStream)
 104.161 +{
 104.162 +    OVR::Net::BitStream out;
 104.163 +    out.Write((MessageID) OVRID_RPC1);
 104.164 +    out.Write((MessageID) ID_RPC4_SIGNAL);
 104.165 +    //out.Write(PluginId);
 104.166 +    out.Write(sharedIdentifier);
 104.167 +    if (bitStream)
 104.168 +    {
 104.169 +        bitStream->ResetReadPointer();
 104.170 +        out.AlignWriteToByteBoundary();
 104.171 +        out.Write(bitStream);
 104.172 +    }
 104.173 +    BroadcastParameters p(out.GetData(), out.GetNumberOfBytesUsed());
 104.174 +    pSession->Broadcast(&p);
 104.175 +}
 104.176 +void RPC1::OnReceive(ReceivePayload *pPayload, ListenerReceiveResult *lrrOut)
 104.177 +{
 104.178 +	OVR_UNUSED(lrrOut);
 104.179 +
 104.180 +    if (pPayload->pData[0] == OVRID_RPC1)
 104.181 +    {
 104.182 +		OVR_ASSERT(pPayload->Bytes >= 2);
 104.183 +
 104.184 +		OVR::Net::BitStream bsIn((char*)pPayload->pData, pPayload->Bytes, false);
 104.185 +		bsIn.IgnoreBytes(2);
 104.186 +
 104.187 +        if (pPayload->pData[1] == RPC_ERROR_FUNCTION_NOT_REGISTERED)
 104.188 +        {
 104.189 +            Mutex::Locker locker(&callBlockingMutex);
 104.190 +
 104.191 +            blockingReturnValue->Reset();
 104.192 +            blockingOnThisConnection = 0;
 104.193 +            callBlockingWait.NotifyAll();
 104.194 +        }
 104.195 +        else if (pPayload->pData[1] == ID_RPC4_RETURN)
 104.196 +        {
 104.197 +            Mutex::Locker locker(&callBlockingMutex);
 104.198 +
 104.199 +            blockingReturnValue->Reset();
 104.200 +			blockingReturnValue->Write(bsIn);
 104.201 +            blockingOnThisConnection = 0;
 104.202 +            callBlockingWait.NotifyAll();
 104.203 +		}
 104.204 +        else if (pPayload->pData[1] == CALL_BLOCKING)
 104.205 +        {
 104.206 +			OVR::String uniqueId;
 104.207 +			bsIn.Read(uniqueId);
 104.208 +
 104.209 +			RPCDelegate *bf = registeredBlockingFunctions.Get(uniqueId);
 104.210 +			if (bf==0)
 104.211 +			{
 104.212 +				OVR::Net::BitStream bsOut;
 104.213 +				bsOut.Write((unsigned char) OVRID_RPC1);
 104.214 +				bsOut.Write((unsigned char) RPC_ERROR_FUNCTION_NOT_REGISTERED);
 104.215 +
 104.216 +				SendParameters sp(pPayload->pConnection, bsOut.GetData(), bsOut.GetNumberOfBytesUsed());
 104.217 +				pSession->Send(&sp);
 104.218 +
 104.219 +				return;
 104.220 +			}
 104.221 +
 104.222 +			OVR::Net::BitStream returnData;
 104.223 +			bsIn.AlignReadToByteBoundary();
 104.224 +			(*bf)(&bsIn, &returnData, pPayload);
 104.225 +
 104.226 +			OVR::Net::BitStream out;
 104.227 +			out.Write((MessageID) OVRID_RPC1);
 104.228 +			out.Write((MessageID) ID_RPC4_RETURN);
 104.229 +			returnData.ResetReadPointer();
 104.230 +			out.AlignWriteToByteBoundary();
 104.231 +			out.Write(returnData);
 104.232 +
 104.233 +			SendParameters sp(pPayload->pConnection, out.GetData(), out.GetNumberOfBytesUsed());
 104.234 +			pSession->Send(&sp);
 104.235 +		}
 104.236 +		else if (pPayload->pData[1]==ID_RPC4_SIGNAL)
 104.237 +		{
 104.238 +			OVR::String sharedIdentifier;
 104.239 +			bsIn.Read(sharedIdentifier);
 104.240 +
 104.241 +			Observer<RPCSlot> *o = slotHash.GetSubject(sharedIdentifier);
 104.242 +
 104.243 +			if (o)
 104.244 +			{
 104.245 +				bsIn.AlignReadToByteBoundary();
 104.246 +
 104.247 +				if (o)
 104.248 +				{
 104.249 +					OVR::Net::BitStream serializedParameters(bsIn.GetData() + bsIn.GetReadOffset()/8, bsIn.GetNumberOfUnreadBits()/8, false);
 104.250 +
 104.251 +					o->Call(&serializedParameters, pPayload);
 104.252 +				}
 104.253 +			}
 104.254 +		}
 104.255 +	}
 104.256 +}
 104.257 +
 104.258 +void RPC1::OnDisconnected(Connection* conn)
 104.259 +{
 104.260 +    if (blockingOnThisConnection == conn)
 104.261 +    {
 104.262 +        blockingOnThisConnection = 0;
 104.263 +        callBlockingWait.NotifyAll();
 104.264 +    }
 104.265 +}
 104.266 +
 104.267 +void RPC1::OnConnected(Connection* conn)
 104.268 +{
 104.269 +    OVR_UNUSED(conn);
 104.270 +}
 104.271 +
 104.272 +
 104.273 +}}} // OVR::Net::Plugins
   105.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   105.2 +++ b/LibOVR/Src/Net/OVR_RPC1.h	Wed Jan 14 06:51:16 2015 +0200
   105.3 @@ -0,0 +1,105 @@
   105.4 +/************************************************************************************
   105.5 +
   105.6 +PublicHeader:   n/a
   105.7 +Filename    :   OVR_RPC1.h
   105.8 +Content     :   A network plugin that provides remote procedure call functionality.
   105.9 +Created     :   June 10, 2014
  105.10 +Authors     :   Kevin Jenkins
  105.11 +
  105.12 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
  105.13 +
  105.14 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
  105.15 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
  105.16 +which is provided at the time of installation or download, or which 
  105.17 +otherwise accompanies this software in either electronic or hard copy form.
  105.18 +
  105.19 +You may obtain a copy of the License at
  105.20 +
  105.21 +http://www.oculusvr.com/licenses/LICENSE-3.2 
  105.22 +
  105.23 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
  105.24 +distributed under the License is distributed on an "AS IS" BASIS,
  105.25 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  105.26 +See the License for the specific language governing permissions and
  105.27 +limitations under the License.
  105.28 +
  105.29 +************************************************************************************/
  105.30 +
  105.31 +#ifndef OVR_Net_RPC_h
  105.32 +#define OVR_Net_RPC_h
  105.33 +
  105.34 +#include "OVR_NetworkPlugin.h"
  105.35 +#include "../Kernel/OVR_Hash.h"
  105.36 +#include "../Kernel/OVR_String.h"
  105.37 +#include "OVR_BitStream.h"
  105.38 +#include "../Kernel/OVR_Threads.h"
  105.39 +#include "../Kernel/OVR_Delegates.h"
  105.40 +#include "../Kernel//OVR_Observer.h"
  105.41 +
  105.42 +namespace OVR { namespace Net { namespace Plugins {
  105.43 +
  105.44 +
  105.45 +typedef Delegate3<void, BitStream*, BitStream*, ReceivePayload*> RPCDelegate;
  105.46 +typedef Delegate2<void, BitStream*, ReceivePayload*> RPCSlot;
  105.47 +// typedef void ( *Slot ) ( OVR::Net::BitStream *userData, OVR::Net::ReceivePayload *pPayload );
  105.48 +
  105.49 +/// NetworkPlugin that maps strings to function pointers. Can invoke the functions using blocking calls with return values, or signal/slots. Networked parameters serialized with BitStream
  105.50 +class RPC1 : public NetworkPlugin, public NewOverrideBase
  105.51 +{
  105.52 +public:
  105.53 +	RPC1();
  105.54 +	virtual ~RPC1();
  105.55 +
  105.56 +	/// Register a slot, which is a function pointer to one or more implementations that supports this function signature
  105.57 +	/// When a signal occurs, all slots with the same identifier are called.
  105.58 +	/// \param[in] sharedIdentifier A string to identify the slot. Recommended to be the same as the name of the function.
  105.59 +	/// \param[in] functionPtr Pointer to the function.
  105.60 +	/// \param[in] callPriority Slots are called by order of the highest callPriority first. For slots with the same priority, they are called in the order they are registered
  105.61 +	void RegisterSlot(OVR::String sharedIdentifier,  OVR::Observer<RPCSlot> *rpcSlotObserver);
  105.62 +
  105.63 +	/// \brief Same as \a RegisterFunction, but is called with CallBlocking() instead of Call() and returns a value to the caller
  105.64 +	bool RegisterBlockingFunction(OVR::String uniqueID, RPCDelegate blockingFunction);
  105.65 +
  105.66 +	/// \brief Same as UnregisterFunction, except for a blocking function
  105.67 +	void UnregisterBlockingFunction(OVR::String uniqueID);
  105.68 +
  105.69 +	// \brief Same as call, but don't return until the remote system replies.
  105.70 +	/// Broadcasting parameter does not exist, this can only call one remote system
  105.71 +	/// \note This function does not return until the remote system responds, disconnects, or was never connected to begin with
  105.72 +	/// \param[in] Identifier originally passed to RegisterBlockingFunction() on the remote system(s)
  105.73 +	/// \param[in] bitStream bitStream encoded data to send to the function callback
  105.74 +	/// \param[in] pConnection connection to send on
  105.75 +	/// \param[out] returnData Written to by the function registered with RegisterBlockingFunction.
  105.76 +	/// \return true if successfully called. False on disconnect, function not registered, or not connected to begin with
  105.77 +	bool CallBlocking( OVR::String uniqueID, OVR::Net::BitStream * bitStream, Ptr<Connection> pConnection, OVR::Net::BitStream *returnData = NULL );
  105.78 +
  105.79 +	/// Calls zero or more functions identified by sharedIdentifier registered with RegisterSlot()
  105.80 +	/// \param[in] sharedIdentifier parameter of the same name passed to RegisterSlot() on the remote system
  105.81 +	/// \param[in] bitStream bitStream encoded data to send to the function callback
  105.82 +	/// \param[in] pConnection connection to send on
  105.83 +	bool Signal(OVR::String sharedIdentifier, OVR::Net::BitStream * bitStream, Ptr<Connection> pConnection);
  105.84 +    void BroadcastSignal(OVR::String sharedIdentifier, OVR::Net::BitStream * bitStream);
  105.85 +
  105.86 +
  105.87 +protected:
  105.88 +	virtual void OnReceive(ReceivePayload *pPayload, ListenerReceiveResult *lrrOut);
  105.89 +
  105.90 +    virtual void OnDisconnected(Connection* conn);
  105.91 +    virtual void OnConnected(Connection* conn);
  105.92 +
  105.93 +	Hash< String, RPCDelegate, String::HashFunctor > registeredBlockingFunctions;
  105.94 +	ObserverHash< RPCSlot > slotHash;
  105.95 +
  105.96 +    // Synchronization for RPC caller
  105.97 +    Lock            singleRPCLock;
  105.98 +    Mutex           callBlockingMutex;
  105.99 +    WaitCondition   callBlockingWait;
 105.100 +
 105.101 +    Net::BitStream* blockingReturnValue;
 105.102 +	Ptr<Connection> blockingOnThisConnection;
 105.103 +};
 105.104 +
 105.105 +
 105.106 +}}} // OVR::Net::Plugins
 105.107 +
 105.108 +#endif // OVR_Net_RPC_h
   106.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   106.2 +++ b/LibOVR/Src/Net/OVR_Session.cpp	Wed Jan 14 06:51:16 2015 +0200
   106.3 @@ -0,0 +1,736 @@
   106.4 +/************************************************************************************
   106.5 +
   106.6 +Filename    :   OVR_Session.h
   106.7 +Content     :   One network session that provides connection/disconnection events.
   106.8 +Created     :   June 10, 2014
   106.9 +Authors     :   Kevin Jenkins, Chris Taylor
  106.10 +
  106.11 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
  106.12 +
  106.13 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
  106.14 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
  106.15 +which is provided at the time of installation or download, or which 
  106.16 +otherwise accompanies this software in either electronic or hard copy form.
  106.17 +
  106.18 +You may obtain a copy of the License at
  106.19 +
  106.20 +http://www.oculusvr.com/licenses/LICENSE-3.2 
  106.21 +
  106.22 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
  106.23 +distributed under the License is distributed on an "AS IS" BASIS,
  106.24 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  106.25 +See the License for the specific language governing permissions and
  106.26 +limitations under the License.
  106.27 +
  106.28 +************************************************************************************/
  106.29 +
  106.30 +#include "OVR_Session.h"
  106.31 +#include "OVR_PacketizedTCPSocket.h"
  106.32 +#include "../Kernel/OVR_Log.h"
  106.33 +#include "../Service/Service_NetSessionCommon.h"
  106.34 +
  106.35 +namespace OVR { namespace Net {
  106.36 +
  106.37 +
  106.38 +//-----------------------------------------------------------------------------
  106.39 +// Protocol
  106.40 +
  106.41 +static const char* OfficialHelloString = "OculusVR_Hello";
  106.42 +static const char* OfficialAuthorizedString = "OculusVR_Authorized";
  106.43 +
  106.44 +void RPC_C2S_Hello::Generate(Net::BitStream* bs)
  106.45 +{
  106.46 +    RPC_C2S_Hello hello;
  106.47 +    hello.HelloString = OfficialHelloString;
  106.48 +    hello.MajorVersion = RPCVersion_Major;
  106.49 +    hello.MinorVersion = RPCVersion_Minor;
  106.50 +    hello.PatchVersion = RPCVersion_Patch;
  106.51 +    hello.Serialize(bs);
  106.52 +}
  106.53 +
  106.54 +bool RPC_C2S_Hello::Validate()
  106.55 +{
  106.56 +    return MajorVersion == RPCVersion_Major &&
  106.57 +           MinorVersion <= RPCVersion_Minor &&
  106.58 +           HelloString.CompareNoCase(OfficialHelloString) == 0;
  106.59 +}
  106.60 +
  106.61 +void RPC_S2C_Authorization::Generate(Net::BitStream* bs, String errorString)
  106.62 +{
  106.63 +    RPC_S2C_Authorization auth;
  106.64 +    if (errorString.IsEmpty())
  106.65 +    {
  106.66 +        auth.AuthString = OfficialAuthorizedString;
  106.67 +    }
  106.68 +    else
  106.69 +    {
  106.70 +        auth.AuthString = errorString;
  106.71 +    }
  106.72 +    auth.MajorVersion = RPCVersion_Major;
  106.73 +    auth.MinorVersion = RPCVersion_Minor;
  106.74 +    auth.PatchVersion = RPCVersion_Patch;
  106.75 +    auth.Serialize(bs);
  106.76 +}
  106.77 +
  106.78 +bool RPC_S2C_Authorization::Validate()
  106.79 +{
  106.80 +    return AuthString.CompareNoCase(OfficialAuthorizedString) == 0;
  106.81 +}
  106.82 +
  106.83 +
  106.84 +//-----------------------------------------------------------------------------
  106.85 +// Session
  106.86 +
  106.87 +void Session::Shutdown()
  106.88 +{
  106.89 +    {
  106.90 +        Lock::Locker locker(&SocketListenersLock);
  106.91 +
  106.92 +        const int count = SocketListeners.GetSizeI();
  106.93 +        for (int i = 0; i < count; ++i)
  106.94 +        {
  106.95 +            SocketListeners[i]->Close();
  106.96 +        }
  106.97 +    }
  106.98 +
  106.99 +    Lock::Locker locker(&ConnectionsLock);
 106.100 +
 106.101 +    const int count = AllConnections.GetSizeI();
 106.102 +    for (int i = 0; i < count; ++i)
 106.103 +    {
 106.104 +        Connection* arrayItem = AllConnections[i].GetPtr();
 106.105 +
 106.106 +        if (arrayItem->Transport == TransportType_PacketizedTCP)
 106.107 +        {
 106.108 +            PacketizedTCPConnection* ptcp = (PacketizedTCPConnection*)arrayItem;
 106.109 +
 106.110 +            ptcp->pSocket->Close();
 106.111 +        }
 106.112 +    }
 106.113 +}
 106.114 +
 106.115 +SessionResult Session::Listen(ListenerDescription* pListenerDescription)
 106.116 +{
 106.117 +	if (pListenerDescription->Transport == TransportType_PacketizedTCP)
 106.118 +	{
 106.119 +		BerkleyListenerDescription* bld = (BerkleyListenerDescription*)pListenerDescription;
 106.120 +		TCPSocket* tcpSocket = (TCPSocket*)bld->BoundSocketToListenWith.GetPtr();
 106.121 +
 106.122 +        if (tcpSocket->Listen() < 0)
 106.123 +        {
 106.124 +            return SessionResult_ListenFailure;
 106.125 +        }
 106.126 +
 106.127 +		Lock::Locker locker(&SocketListenersLock);
 106.128 +        SocketListeners.PushBack(tcpSocket);
 106.129 +	}
 106.130 +    else if (pListenerDescription->Transport == TransportType_Loopback)
 106.131 +	{
 106.132 +		HasLoopbackListener = true;
 106.133 +	}
 106.134 +    else
 106.135 +    {
 106.136 +        OVR_ASSERT(false);
 106.137 +    }
 106.138 +
 106.139 +	return SessionResult_OK;
 106.140 +}
 106.141 +
 106.142 +SessionResult Session::Connect(ConnectParameters *cp)
 106.143 +{
 106.144 +    if (cp->Transport == TransportType_PacketizedTCP)
 106.145 +    {
 106.146 +        ConnectParametersBerkleySocket* cp2 = (ConnectParametersBerkleySocket*)cp;
 106.147 +        Ptr<PacketizedTCPConnection> c;
 106.148 +
 106.149 +        {
 106.150 +            Lock::Locker locker(&ConnectionsLock);
 106.151 +
 106.152 +            int connIndex;
 106.153 +            Ptr<PacketizedTCPConnection> conn = findConnectionBySocket(AllConnections, cp2->BoundSocketToConnectWith, &connIndex);
 106.154 +            if (conn)
 106.155 +            {
 106.156 +                return SessionResult_AlreadyConnected;
 106.157 +            }
 106.158 +
 106.159 +            TCPSocketBase* tcpSock = (TCPSocketBase*)cp2->BoundSocketToConnectWith.GetPtr();
 106.160 +
 106.161 +            int ret = tcpSock->Connect(&cp2->RemoteAddress);
 106.162 +            if (ret < 0)
 106.163 +            {
 106.164 +                return SessionResult_ConnectFailure;
 106.165 +            }
 106.166 +
 106.167 +            Ptr<Connection> newConnection = AllocConnection(cp2->Transport);
 106.168 +            if (!newConnection)
 106.169 +            {
 106.170 +                return SessionResult_ConnectFailure;
 106.171 +            }
 106.172 +
 106.173 +            c = (PacketizedTCPConnection*)newConnection.GetPtr();
 106.174 +            c->pSocket = (TCPSocket*) cp2->BoundSocketToConnectWith.GetPtr();
 106.175 +            c->Address = cp2->RemoteAddress;
 106.176 +            c->Transport = cp2->Transport;
 106.177 +            c->SetState(Client_Connecting);
 106.178 +
 106.179 +            AllConnections.PushBack(c);
 106.180 +
 106.181 +        }
 106.182 +
 106.183 +        if (cp2->Blocking)
 106.184 +        {
 106.185 +            c->WaitOnConnecting();
 106.186 +        }
 106.187 +
 106.188 +        if (c->State == State_Connected)
 106.189 +        {
 106.190 +            return SessionResult_OK;
 106.191 +        }
 106.192 +        else if (c->State == Client_Connecting)
 106.193 +        {
 106.194 +            return SessionResult_ConnectInProgress;
 106.195 +        }
 106.196 +        else
 106.197 +        {
 106.198 +            return SessionResult_ConnectFailure;
 106.199 +        }
 106.200 +    }
 106.201 +    else if (cp->Transport == TransportType_Loopback)
 106.202 +	{
 106.203 +		if (HasLoopbackListener)
 106.204 +		{
 106.205 +            Ptr<Connection> c = AllocConnection(cp->Transport);
 106.206 +            if (!c)
 106.207 +            {
 106.208 +                return SessionResult_ConnectFailure;
 106.209 +            }
 106.210 +
 106.211 +            c->Transport = cp->Transport;
 106.212 +            c->SetState(State_Connected);
 106.213 +
 106.214 +            {
 106.215 +                Lock::Locker locker(&ConnectionsLock);
 106.216 +                AllConnections.PushBack(c);
 106.217 +            }
 106.218 +
 106.219 +			invokeSessionEvent(&SessionListener::OnConnectionRequestAccepted, c);
 106.220 +		}
 106.221 +		else
 106.222 +		{
 106.223 +            OVR_ASSERT(false);
 106.224 +		}
 106.225 +	}
 106.226 +    else
 106.227 +    {
 106.228 +        OVR_ASSERT(false);
 106.229 +    }
 106.230 +
 106.231 +	return SessionResult_OK;
 106.232 +}
 106.233 +
 106.234 +SessionResult Session::ListenPTCP(OVR::Net::BerkleyBindParameters *bbp)
 106.235 +{
 106.236 +	Ptr<PacketizedTCPSocket> listenSocket = *new OVR::Net::PacketizedTCPSocket();
 106.237 +    if (listenSocket->Bind(bbp) == INVALID_SOCKET)
 106.238 +    {
 106.239 +        return SessionResult_BindFailure;
 106.240 +    }
 106.241 +
 106.242 +	BerkleyListenerDescription bld;
 106.243 +	bld.BoundSocketToListenWith = listenSocket.GetPtr();
 106.244 +    bld.Transport = TransportType_PacketizedTCP;
 106.245 +
 106.246 +    return Listen(&bld);
 106.247 +}
 106.248 +
 106.249 +SessionResult Session::ConnectPTCP(OVR::Net::BerkleyBindParameters* bbp, SockAddr* remoteAddress, bool blocking)
 106.250 +{
 106.251 +    ConnectParametersBerkleySocket cp(NULL, remoteAddress, blocking, TransportType_PacketizedTCP);
 106.252 +    Ptr<PacketizedTCPSocket> connectSocket = *new PacketizedTCPSocket();
 106.253 +
 106.254 +	cp.BoundSocketToConnectWith = connectSocket.GetPtr();
 106.255 +    if (connectSocket->Bind(bbp) == INVALID_SOCKET)
 106.256 +    {
 106.257 +        return SessionResult_BindFailure;
 106.258 +    }
 106.259 +
 106.260 +	return Connect(&cp);
 106.261 +}
 106.262 +
 106.263 +Ptr<PacketizedTCPConnection> Session::findConnectionBySockAddr(SockAddr* address)
 106.264 +{
 106.265 +    const int count = AllConnections.GetSizeI();
 106.266 +    for (int i = 0; i < count; ++i)
 106.267 +    {
 106.268 +        Connection* arrayItem = AllConnections[i].GetPtr();
 106.269 +
 106.270 +        if (arrayItem->Transport == TransportType_PacketizedTCP)
 106.271 +        {
 106.272 +            PacketizedTCPConnection* conn = (PacketizedTCPConnection*)arrayItem;
 106.273 +
 106.274 +            if (conn->Address == *address)
 106.275 +            {
 106.276 +                return conn;
 106.277 +            }
 106.278 +        }
 106.279 +    }
 106.280 +
 106.281 +    return 0;
 106.282 +}
 106.283 +
 106.284 +int Session::Send(SendParameters *payload)
 106.285 +{
 106.286 +	if (payload->pConnection->Transport == TransportType_Loopback)
 106.287 +	{
 106.288 +		Lock::Locker locker(&SessionListenersLock);
 106.289 +
 106.290 +        const int count = SessionListeners.GetSizeI();
 106.291 +        for (int i = 0; i < count; ++i)
 106.292 +		{
 106.293 +			SessionListener* sl = SessionListeners[i];
 106.294 +
 106.295 +            // FIXME: This looks like it needs to be reviewed at some point..
 106.296 +			ReceivePayload rp;
 106.297 +			rp.Bytes = payload->Bytes;
 106.298 +			rp.pConnection = payload->pConnection;
 106.299 +			rp.pData = (uint8_t*)payload->pData; // FIXME
 106.300 +			ListenerReceiveResult lrr = LRR_CONTINUE;
 106.301 +			sl->OnReceive(&rp, &lrr);
 106.302 +            if (lrr == LRR_RETURN)
 106.303 +            {
 106.304 +                return payload->Bytes;
 106.305 +            }
 106.306 +			else if (lrr == LRR_BREAK)
 106.307 +			{
 106.308 +				break;
 106.309 +			}	
 106.310 +		}
 106.311 +
 106.312 +		return payload->Bytes;
 106.313 +	}
 106.314 +    else if (payload->pConnection->Transport == TransportType_PacketizedTCP)
 106.315 +	{
 106.316 +		PacketizedTCPConnection* conn = (PacketizedTCPConnection*)payload->pConnection.GetPtr();
 106.317 +
 106.318 +        return conn->pSocket->Send(payload->pData, payload->Bytes);
 106.319 +	}
 106.320 +    else
 106.321 +    {
 106.322 +        OVR_ASSERT(false);
 106.323 +    }
 106.324 +
 106.325 +    return 0;
 106.326 +}
 106.327 +void Session::Broadcast(BroadcastParameters *payload)
 106.328 +{
 106.329 +    SendParameters sp;
 106.330 +    sp.Bytes=payload->Bytes;
 106.331 +    sp.pData=payload->pData;
 106.332 +
 106.333 +    {
 106.334 +        Lock::Locker locker(&ConnectionsLock);
 106.335 +
 106.336 +        const int connectionCount = FullConnections.GetSizeI();
 106.337 +        for (int i = 0; i < connectionCount; ++i)
 106.338 +        {
 106.339 +            sp.pConnection = FullConnections[i];
 106.340 +            Send(&sp);
 106.341 +        }    
 106.342 +    }
 106.343 +}
 106.344 +// DO NOT CALL Poll() FROM MULTIPLE THREADS due to allBlockingTcpSockets being a member
 106.345 +void Session::Poll(bool listeners)
 106.346 +{
 106.347 +    allBlockingTcpSockets.Clear();
 106.348 +
 106.349 +	if (listeners)
 106.350 +	{
 106.351 +		Lock::Locker locker(&SocketListenersLock);
 106.352 +
 106.353 +        const int listenerCount = SocketListeners.GetSizeI();
 106.354 +        for (int i = 0; i < listenerCount; ++i)
 106.355 +		{
 106.356 +            allBlockingTcpSockets.PushBack(SocketListeners[i]);
 106.357 +		}
 106.358 +	}
 106.359 +
 106.360 +    {
 106.361 +        Lock::Locker locker(&ConnectionsLock);
 106.362 +
 106.363 +        const int connectionCount = AllConnections.GetSizeI();
 106.364 +        for (int i = 0; i < connectionCount; ++i)
 106.365 +        {
 106.366 +            Connection* arrayItem = AllConnections[i].GetPtr();
 106.367 +
 106.368 +            if (arrayItem->Transport == TransportType_PacketizedTCP)
 106.369 +            {
 106.370 +                PacketizedTCPConnection* ptcp = (PacketizedTCPConnection*)arrayItem;
 106.371 +
 106.372 +                allBlockingTcpSockets.PushBack(ptcp->pSocket);
 106.373 +            }
 106.374 +            else
 106.375 +            {
 106.376 +                OVR_ASSERT(false);
 106.377 +            }
 106.378 +        }
 106.379 +    }
 106.380 +
 106.381 +    const int count = allBlockingTcpSockets.GetSizeI();
 106.382 +	if (count > 0)
 106.383 +	{
 106.384 +        TCPSocketPollState state;
 106.385 +
 106.386 +        // Add all the sockets for polling,
 106.387 +        for (int i = 0; i < count; ++i)
 106.388 +        {
 106.389 +            Net::TCPSocket* sock = allBlockingTcpSockets[i].GetPtr();
 106.390 +
 106.391 +            // If socket handle is invalid,
 106.392 +            if (sock->GetSocketHandle() == INVALID_SOCKET)
 106.393 +            {
 106.394 +                OVR_DEBUG_LOG(("[Session] Detected an invalid socket handle - Treating it as a disconnection."));
 106.395 +                sock->IsConnecting = false;
 106.396 +                TCP_OnClosed(sock);
 106.397 +            }
 106.398 +            else
 106.399 +            {
 106.400 +                state.Add(sock);
 106.401 +            }
 106.402 +        }
 106.403 +
 106.404 +        // If polling returns with an event,
 106.405 +        if (state.Poll(allBlockingTcpSockets[0]->GetBlockingTimeoutUsec(), allBlockingTcpSockets[0]->GetBlockingTimeoutSec()))
 106.406 +        {
 106.407 +            // Handle any events for each socket
 106.408 +            for (int i = 0; i < count; ++i)
 106.409 +            {
 106.410 +                state.HandleEvent(allBlockingTcpSockets[i], this);
 106.411 +            }
 106.412 +        }
 106.413 +	}
 106.414 +}
 106.415 +
 106.416 +void Session::AddSessionListener(SessionListener* se)
 106.417 +{
 106.418 +	Lock::Locker locker(&SessionListenersLock);
 106.419 +
 106.420 +    const int count = SessionListeners.GetSizeI();
 106.421 +    for (int i = 0; i < count; ++i)
 106.422 +    {
 106.423 +        if (SessionListeners[i] == se)
 106.424 +        {
 106.425 +            // Already added
 106.426 +            return;
 106.427 +        }
 106.428 +    }
 106.429 +
 106.430 +    SessionListeners.PushBack(se);
 106.431 +	se->OnAddedToSession(this);
 106.432 +}
 106.433 +
 106.434 +void Session::RemoveSessionListener(SessionListener* se)
 106.435 +{
 106.436 +	Lock::Locker locker(&SessionListenersLock);
 106.437 +
 106.438 +    const int count = SessionListeners.GetSizeI();
 106.439 +	for (int i = 0; i < count; ++i)
 106.440 +	{
 106.441 +        if (SessionListeners[i] == se)
 106.442 +		{
 106.443 +            se->OnRemovedFromSession(this);
 106.444 +
 106.445 +            SessionListeners.RemoveAtUnordered(i);
 106.446 +            break;
 106.447 +		}
 106.448 +	}
 106.449 +}
 106.450 +SInt32 Session::GetActiveSocketsCount()
 106.451 +{
 106.452 +    Lock::Locker locker1(&SocketListenersLock);
 106.453 +    Lock::Locker locker2(&ConnectionsLock);
 106.454 +    return SocketListeners.GetSize() + AllConnections.GetSize()>0;
 106.455 +}
 106.456 +Ptr<Connection> Session::AllocConnection(TransportType transport)
 106.457 +{
 106.458 +    switch (transport)
 106.459 +    {
 106.460 +    case TransportType_Loopback:      return *new Connection();
 106.461 +    case TransportType_TCP:           return *new TCPConnection();
 106.462 +    case TransportType_PacketizedTCP: return *new PacketizedTCPConnection();
 106.463 +    default:
 106.464 +        OVR_ASSERT(false);
 106.465 +        break;
 106.466 +    }
 106.467 +
 106.468 +    return NULL;
 106.469 +}
 106.470 +
 106.471 +Ptr<PacketizedTCPConnection> Session::findConnectionBySocket(Array< Ptr<Connection> >& connectionArray, Socket* s, int *connectionIndex)
 106.472 +{
 106.473 +    const int count = connectionArray.GetSizeI();
 106.474 +    for (int i = 0; i < count; ++i)
 106.475 +    {
 106.476 +        Connection* arrayItem = connectionArray[i].GetPtr();
 106.477 +
 106.478 +        if (arrayItem->Transport == TransportType_PacketizedTCP)
 106.479 +        {
 106.480 +            PacketizedTCPConnection* ptc = (PacketizedTCPConnection*)arrayItem;
 106.481 +
 106.482 +            if (ptc->pSocket == s)
 106.483 +            {
 106.484 +                if (connectionIndex)
 106.485 +                {
 106.486 +                    *connectionIndex = i;
 106.487 +                }
 106.488 +                return ptc;
 106.489 +            }
 106.490 +        }
 106.491 +    }
 106.492 +
 106.493 +    return NULL;
 106.494 +}
 106.495 +
 106.496 +int Session::invokeSessionListeners(ReceivePayload* rp)
 106.497 +{
 106.498 +    Lock::Locker locker(&SessionListenersLock);
 106.499 +
 106.500 +    const int count = SessionListeners.GetSizeI();
 106.501 +    for (int j = 0; j < count; ++j)
 106.502 +    {
 106.503 +        ListenerReceiveResult lrr = LRR_CONTINUE;
 106.504 +        SessionListeners[j]->OnReceive(rp, &lrr);
 106.505 +
 106.506 +        if (lrr == LRR_RETURN || lrr == LRR_BREAK)
 106.507 +        {
 106.508 +            break;
 106.509 +        }
 106.510 +    }
 106.511 +
 106.512 +    return rp->Bytes;
 106.513 +}
 106.514 +
 106.515 +void Session::TCP_OnRecv(Socket* pSocket, uint8_t* pData, int bytesRead)
 106.516 +{
 106.517 +	// KevinJ: 9/2/2014 Fix deadlock - Watchdog calls Broadcast(), which locks ConnectionsLock().
 106.518 +	// Lock::Locker locker(&ConnectionsLock);
 106.519 +
 106.520 +    // Look for the connection in the full connection list first
 106.521 +    int connIndex;
 106.522 +	ConnectionsLock.DoLock();
 106.523 +    Ptr<PacketizedTCPConnection> conn = findConnectionBySocket(AllConnections, pSocket, &connIndex);
 106.524 +	ConnectionsLock.Unlock();
 106.525 +    if (conn)
 106.526 +    {
 106.527 +        if (conn->State == State_Connected)
 106.528 +        {
 106.529 +            ReceivePayload rp;
 106.530 +            rp.Bytes = bytesRead;
 106.531 +            rp.pConnection = conn;
 106.532 +            rp.pData = pData;
 106.533 +
 106.534 +            // Call listeners
 106.535 +            invokeSessionListeners(&rp);
 106.536 +        }
 106.537 +        else if (conn->State == Client_ConnectedWait)
 106.538 +        {
 106.539 +            // Check the version data from the message
 106.540 +            BitStream bsIn((char*)pData, bytesRead, false);
 106.541 +
 106.542 +            RPC_S2C_Authorization auth;
 106.543 +            if (!auth.Deserialize(&bsIn) ||
 106.544 +                !auth.Validate())
 106.545 +            {
 106.546 +                LogError("{ERR-001} [Session] REJECTED: OVRService did not authorize us: %s", auth.AuthString.ToCStr());
 106.547 +
 106.548 +                conn->SetState(State_Zombie);
 106.549 +                invokeSessionEvent(&SessionListener::OnIncompatibleProtocol, conn);
 106.550 +            }
 106.551 +            else
 106.552 +            {
 106.553 +                // Read remote version
 106.554 +                conn->RemoteMajorVersion = auth.MajorVersion;
 106.555 +                conn->RemoteMinorVersion = auth.MinorVersion;
 106.556 +                conn->RemotePatchVersion = auth.PatchVersion;
 106.557 +
 106.558 +                // Mark as connected
 106.559 +                conn->SetState(State_Connected);
 106.560 +				ConnectionsLock.DoLock();
 106.561 +				int connIndex2;
 106.562 +				if (findConnectionBySocket(AllConnections, pSocket, &connIndex2)==conn && findConnectionBySocket(FullConnections, pSocket, &connIndex2)==NULL)
 106.563 +				{
 106.564 +					FullConnections.PushBack(conn);
 106.565 +				}
 106.566 +				ConnectionsLock.Unlock();
 106.567 +                invokeSessionEvent(&SessionListener::OnConnectionRequestAccepted, conn);
 106.568 +            }
 106.569 +        }
 106.570 +        else if (conn->State == Server_ConnectedWait)
 106.571 +        {
 106.572 +            // Check the version data from the message
 106.573 +            BitStream bsIn((char*)pData, bytesRead, false);
 106.574 +
 106.575 +            RPC_C2S_Hello hello;
 106.576 +            if (!hello.Deserialize(&bsIn) ||
 106.577 +                !hello.Validate())
 106.578 +            {
 106.579 +                LogError("{ERR-002} [Session] REJECTED: Rift application is using an incompatible version %d.%d.%d (my version=%d.%d.%d)",
 106.580 +                         hello.MajorVersion, hello.MinorVersion, hello.PatchVersion,
 106.581 +                         RPCVersion_Major, RPCVersion_Minor, RPCVersion_Patch);
 106.582 +
 106.583 +                conn->SetState(State_Zombie);
 106.584 +
 106.585 +                // Send auth response
 106.586 +                BitStream bsOut;
 106.587 +                RPC_S2C_Authorization::Generate(&bsOut, "Incompatible protocol version.  Please make sure your OVRService and SDK are both up to date.");
 106.588 +                conn->pSocket->Send(bsOut.GetData(), bsOut.GetNumberOfBytesUsed());
 106.589 +            }
 106.590 +            else
 106.591 +            {
 106.592 +                // Read remote version
 106.593 +                conn->RemoteMajorVersion = hello.MajorVersion;
 106.594 +                conn->RemoteMinorVersion = hello.MinorVersion;
 106.595 +                conn->RemotePatchVersion = hello.PatchVersion;
 106.596 +
 106.597 +                // Send auth response
 106.598 +                BitStream bsOut;
 106.599 +                RPC_S2C_Authorization::Generate(&bsOut);
 106.600 +                conn->pSocket->Send(bsOut.GetData(), bsOut.GetNumberOfBytesUsed());
 106.601 +
 106.602 +                // Mark as connected
 106.603 +                conn->SetState(State_Connected);
 106.604 +				ConnectionsLock.DoLock();
 106.605 +				int connIndex2;
 106.606 +				if (findConnectionBySocket(AllConnections, pSocket, &connIndex2)==conn && findConnectionBySocket(FullConnections, pSocket, &connIndex2)==NULL)
 106.607 +				{
 106.608 +					FullConnections.PushBack(conn);
 106.609 +				}
 106.610 +				ConnectionsLock.Unlock();
 106.611 +                invokeSessionEvent(&SessionListener::OnNewIncomingConnection, conn);
 106.612 +
 106.613 +            }
 106.614 +        }
 106.615 +        else
 106.616 +        {
 106.617 +            OVR_ASSERT(false);
 106.618 +        }
 106.619 +    }
 106.620 +}
 106.621 +
 106.622 +void Session::TCP_OnClosed(TCPSocket* s)
 106.623 +{
 106.624 +	Lock::Locker locker(&ConnectionsLock);
 106.625 +
 106.626 +    // If found in the full connection list,
 106.627 +    int connIndex;
 106.628 +    Ptr<PacketizedTCPConnection> conn = findConnectionBySocket(AllConnections, s, &connIndex);
 106.629 +    if (conn)
 106.630 +    {
 106.631 +        AllConnections.RemoveAtUnordered(connIndex);
 106.632 +
 106.633 +        // If in the full connection list,
 106.634 +        if (findConnectionBySocket(FullConnections, s, &connIndex))
 106.635 +        {
 106.636 +            FullConnections.RemoveAtUnordered(connIndex);
 106.637 +        }
 106.638 +
 106.639 +        // Generate an appropriate event for the current state
 106.640 +        switch (conn->State)
 106.641 +        {
 106.642 +        case Client_Connecting:
 106.643 +            invokeSessionEvent(&SessionListener::OnConnectionAttemptFailed, conn);
 106.644 +            break;
 106.645 +        case Client_ConnectedWait:
 106.646 +        case Server_ConnectedWait:
 106.647 +            invokeSessionEvent(&SessionListener::OnHandshakeAttemptFailed, conn);
 106.648 +            break;
 106.649 +        case State_Connected:
 106.650 +        case State_Zombie:
 106.651 +            invokeSessionEvent(&SessionListener::OnDisconnected, conn);
 106.652 +            break;
 106.653 +        default:
 106.654 +            OVR_ASSERT(false);
 106.655 +            break;
 106.656 +        }
 106.657 +
 106.658 +        conn->SetState(State_Zombie);
 106.659 +    }
 106.660 +}
 106.661 +
 106.662 +void Session::TCP_OnAccept(TCPSocket* pListener, SockAddr* pSockAddr, SocketHandle newSock)
 106.663 +{
 106.664 +    OVR_UNUSED(pListener);
 106.665 +	OVR_ASSERT(pListener->Transport == TransportType_PacketizedTCP);
 106.666 +
 106.667 +
 106.668 +	Ptr<PacketizedTCPSocket> newSocket = *new PacketizedTCPSocket(newSock, false);
 106.669 +    // If pSockAddr is not localhost, then close newSock
 106.670 +    if (pSockAddr->IsLocalhost()==false)
 106.671 +    {
 106.672 +        newSocket->Close();
 106.673 +        return;
 106.674 +    }
 106.675 +
 106.676 +	if (newSocket)
 106.677 +	{
 106.678 +		Ptr<Connection> b = AllocConnection(TransportType_PacketizedTCP);
 106.679 +		Ptr<PacketizedTCPConnection> c = (PacketizedTCPConnection*)b.GetPtr();
 106.680 +		c->pSocket = newSocket;
 106.681 +		c->Address = *pSockAddr;
 106.682 +        c->State = Server_ConnectedWait;
 106.683 +
 106.684 +        {
 106.685 +            Lock::Locker locker(&ConnectionsLock);
 106.686 +            AllConnections.PushBack(c);
 106.687 +        }
 106.688 +
 106.689 +        // Server does not send the first packet.  It waits for the client to send its version
 106.690 +	}
 106.691 +}
 106.692 +
 106.693 +void Session::TCP_OnConnected(TCPSocket *s)
 106.694 +{
 106.695 +    Lock::Locker locker(&ConnectionsLock);
 106.696 +
 106.697 +    // If connection was found,
 106.698 +    PacketizedTCPConnection* conn = findConnectionBySocket(AllConnections, s);
 106.699 +    if (conn)
 106.700 +    {
 106.701 +        OVR_ASSERT(conn->State == Client_Connecting);
 106.702 +
 106.703 +        // Send hello message
 106.704 +        BitStream bsOut;
 106.705 +        RPC_C2S_Hello::Generate(&bsOut);
 106.706 +        conn->pSocket->Send(bsOut.GetData(), bsOut.GetNumberOfBytesUsed());
 106.707 +
 106.708 +        // Just update state but do not generate any notifications yet
 106.709 +        conn->State = Client_ConnectedWait;
 106.710 +    }
 106.711 +}
 106.712 +
 106.713 +void Session::invokeSessionEvent(void(SessionListener::*f)(Connection*), Connection* conn)
 106.714 +{
 106.715 +    Lock::Locker locker(&SessionListenersLock);
 106.716 +
 106.717 +    const int count = SessionListeners.GetSizeI();
 106.718 +    for (int i = 0; i < count; ++i)
 106.719 +    {
 106.720 +        (SessionListeners[i]->*f)(conn);
 106.721 +    }
 106.722 +}
 106.723 +
 106.724 +Ptr<Connection> Session::GetConnectionAtIndex(int index)
 106.725 +{
 106.726 +    Lock::Locker locker(&ConnectionsLock);
 106.727 +
 106.728 +    const int count = FullConnections.GetSizeI();
 106.729 +
 106.730 +    if (index < count)
 106.731 +    {
 106.732 +        return FullConnections[index];
 106.733 +    }
 106.734 +
 106.735 +    return NULL;
 106.736 +}
 106.737 +
 106.738 +
 106.739 +}} // OVR::Net
   107.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   107.2 +++ b/LibOVR/Src/Net/OVR_Session.h	Wed Jan 14 06:51:16 2015 +0200
   107.3 @@ -0,0 +1,513 @@
   107.4 +/************************************************************************************
   107.5 +
   107.6 +PublicHeader:   n/a
   107.7 +Filename    :   OVR_Session.h
   107.8 +Content     :   One network session that provides connection/disconnection events.
   107.9 +Created     :   June 10, 2014
  107.10 +Authors     :   Kevin Jenkins, Chris Taylor
  107.11 +
  107.12 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
  107.13 +
  107.14 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
  107.15 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
  107.16 +which is provided at the time of installation or download, or which 
  107.17 +otherwise accompanies this software in either electronic or hard copy form.
  107.18 +
  107.19 +You may obtain a copy of the License at
  107.20 +
  107.21 +http://www.oculusvr.com/licenses/LICENSE-3.2 
  107.22 +
  107.23 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
  107.24 +distributed under the License is distributed on an "AS IS" BASIS,
  107.25 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  107.26 +See the License for the specific language governing permissions and
  107.27 +limitations under the License.
  107.28 +
  107.29 +************************************************************************************/
  107.30 +
  107.31 +#ifndef OVR_Session_h
  107.32 +#define OVR_Session_h
  107.33 +
  107.34 +#include "OVR_Socket.h"
  107.35 +#include "OVR_PacketizedTCPSocket.h"
  107.36 +#include "../Kernel/OVR_Array.h"
  107.37 +#include "../Kernel/OVR_Threads.h"
  107.38 +#include "../Kernel/OVR_Atomic.h"
  107.39 +#include "../Kernel/OVR_RefCount.h"
  107.40 +
  107.41 +namespace OVR { namespace Net {
  107.42 +
  107.43 +class Session;
  107.44 +
  107.45 +
  107.46 +//-----------------------------------------------------------------------------
  107.47 +// Based on Semantic Versioning ( http://semver.org/ )
  107.48 +//
  107.49 +// Please update changelog below:
  107.50 +// 1.0.0 - [SDK 0.4.0] Initial version (July 21, 2014)
  107.51 +// 1.1.0 - Add Get/SetDriverMode_1, HMDCountUpdate_1
  107.52 +//         Version mismatch results (July 28, 2014)
  107.53 +//-----------------------------------------------------------------------------
  107.54 +
  107.55 +static const uint16_t RPCVersion_Major = 1; // MAJOR version when you make incompatible API changes,
  107.56 +static const uint16_t RPCVersion_Minor = 2; // MINOR version when you add functionality in a backwards-compatible manner, and
  107.57 +static const uint16_t RPCVersion_Patch = 0; // PATCH version when you make backwards-compatible bug fixes.
  107.58 +
  107.59 +// Client starts communication by sending its version number.
  107.60 +struct RPC_C2S_Hello
  107.61 +{
  107.62 +    RPC_C2S_Hello() :
  107.63 +        MajorVersion(0),
  107.64 +        MinorVersion(0),
  107.65 +        PatchVersion(0)
  107.66 +    {
  107.67 +    }
  107.68 +
  107.69 +    String HelloString;
  107.70 +
  107.71 +    // Client version info
  107.72 +    uint16_t MajorVersion, MinorVersion, PatchVersion;
  107.73 +
  107.74 +    void Serialize(Net::BitStream* bs)
  107.75 +    {
  107.76 +        bs->Write(HelloString);
  107.77 +        bs->Write(MajorVersion);
  107.78 +        bs->Write(MinorVersion);
  107.79 +        bs->Write(PatchVersion);
  107.80 +    }
  107.81 +
  107.82 +    bool Deserialize(Net::BitStream* bs)
  107.83 +    {
  107.84 +        bs->Read(HelloString);
  107.85 +        bs->Read(MajorVersion);
  107.86 +        bs->Read(MinorVersion);
  107.87 +        return bs->Read(PatchVersion);
  107.88 +    }
  107.89 +
  107.90 +    static void Generate(Net::BitStream* bs);
  107.91 +
  107.92 +    bool Validate();
  107.93 +};
  107.94 +
  107.95 +// Server responds with an authorization accepted message, including the server's version number
  107.96 +struct RPC_S2C_Authorization
  107.97 +{
  107.98 +    RPC_S2C_Authorization() :
  107.99 +        MajorVersion(0),
 107.100 +        MinorVersion(0),
 107.101 +        PatchVersion(0)
 107.102 +    {
 107.103 +    }
 107.104 +
 107.105 +    String AuthString;
 107.106 +
 107.107 +    // Server version info
 107.108 +    uint16_t MajorVersion, MinorVersion, PatchVersion;
 107.109 +
 107.110 +    void Serialize(Net::BitStream* bs)
 107.111 +    {
 107.112 +        bs->Write(AuthString);
 107.113 +        bs->Write(MajorVersion);
 107.114 +        bs->Write(MinorVersion);
 107.115 +        bs->Write(PatchVersion);
 107.116 +    }
 107.117 +
 107.118 +    bool Deserialize(Net::BitStream* bs)
 107.119 +    {
 107.120 +        bs->Read(AuthString);
 107.121 +        bs->Read(MajorVersion);
 107.122 +        bs->Read(MinorVersion);
 107.123 +        return bs->Read(PatchVersion);
 107.124 +    }
 107.125 +
 107.126 +    static void Generate(Net::BitStream* bs, String errorString = "");
 107.127 +
 107.128 +    bool Validate();
 107.129 +};
 107.130 +
 107.131 +
 107.132 +//-----------------------------------------------------------------------------
 107.133 +// Result of a session function
 107.134 +enum SessionResult
 107.135 +{
 107.136 +	SessionResult_OK,
 107.137 +	SessionResult_BindFailure,
 107.138 +	SessionResult_ListenFailure,
 107.139 +	SessionResult_ConnectFailure,
 107.140 +    SessionResult_ConnectInProgress,
 107.141 +    SessionResult_AlreadyConnected,
 107.142 +};
 107.143 +
 107.144 +
 107.145 +//-----------------------------------------------------------------------------
 107.146 +// Connection state
 107.147 +enum EConnectionState
 107.148 +{
 107.149 +    State_Zombie,          // Disconnected
 107.150 +
 107.151 +    // Client-only:
 107.152 +    Client_Connecting,     // Waiting for TCP connection
 107.153 +    Client_ConnectedWait,  // Connected! Waiting for server to authorize
 107.154 +
 107.155 +    // Server-only:
 107.156 +    Server_ConnectedWait,  // Connected! Waiting for client handshake
 107.157 +
 107.158 +    State_Connected        // Connected
 107.159 +};
 107.160 +
 107.161 +
 107.162 +//-----------------------------------------------------------------------------
 107.163 +// Generic connection over any transport
 107.164 +class Connection : public RefCountBase<Connection>
 107.165 +{
 107.166 +public:
 107.167 +    Connection() :
 107.168 +        Transport(TransportType_None),
 107.169 +        State(State_Zombie),
 107.170 +        RemoteMajorVersion(0),
 107.171 +        RemoteMinorVersion(0),
 107.172 +        RemotePatchVersion(0)
 107.173 +    {
 107.174 +    }
 107.175 +	virtual ~Connection() // Allow delete from base
 107.176 +    {
 107.177 +    }
 107.178 +
 107.179 +public:
 107.180 +    virtual void SetState(EConnectionState s) {State = s;}
 107.181 +
 107.182 +    TransportType    Transport;
 107.183 +    EConnectionState State;
 107.184 +
 107.185 +    // Version number read from remote host just before connection completes
 107.186 +    int              RemoteMajorVersion;
 107.187 +    int              RemoteMinorVersion;
 107.188 +    int              RemotePatchVersion;
 107.189 +};
 107.190 +
 107.191 +
 107.192 +//-----------------------------------------------------------------------------
 107.193 +// Generic network connection over any network transport
 107.194 +class NetworkConnection : public Connection
 107.195 +{
 107.196 +protected:
 107.197 +    NetworkConnection()
 107.198 +	{
 107.199 +	}
 107.200 +    virtual ~NetworkConnection()
 107.201 +    {
 107.202 +    }
 107.203 +
 107.204 +public:
 107.205 +    virtual void SetState(EConnectionState s)
 107.206 +    {
 107.207 +        if (s != State)
 107.208 +        {
 107.209 +            Mutex::Locker locker(&StateMutex);
 107.210 +
 107.211 +            if (s != State)
 107.212 +            {
 107.213 +                State = s;
 107.214 +
 107.215 +                if (State != Client_Connecting)
 107.216 +                {
 107.217 +                    ConnectingWait.NotifyAll();
 107.218 +                }
 107.219 +            }
 107.220 +        }
 107.221 +    }
 107.222 +
 107.223 +    void WaitOnConnecting()
 107.224 +    {
 107.225 +        Mutex::Locker locker(&StateMutex);
 107.226 +
 107.227 +        while (State == Client_Connecting)
 107.228 +        {
 107.229 +            ConnectingWait.Wait(&StateMutex);
 107.230 +        }
 107.231 +    }
 107.232 +
 107.233 +	SockAddr      Address;
 107.234 +    Mutex         StateMutex;
 107.235 +    WaitCondition ConnectingWait;
 107.236 +};
 107.237 +
 107.238 +
 107.239 +//-----------------------------------------------------------------------------
 107.240 +// TCP Connection
 107.241 +class TCPConnection : public NetworkConnection
 107.242 +{
 107.243 +public:
 107.244 +    TCPConnection()
 107.245 +    {
 107.246 +    }
 107.247 +    virtual ~TCPConnection()
 107.248 +    {
 107.249 +    }
 107.250 +
 107.251 +public:
 107.252 +	Ptr<TCPSocket> pSocket;
 107.253 +};
 107.254 +
 107.255 +
 107.256 +//-----------------------------------------------------------------------------
 107.257 +// Packetized TCP Connection
 107.258 +class PacketizedTCPConnection : public TCPConnection
 107.259 +{
 107.260 +public:
 107.261 +	PacketizedTCPConnection()
 107.262 +    {
 107.263 +        Transport = TransportType_PacketizedTCP;
 107.264 +    }
 107.265 +    virtual ~PacketizedTCPConnection()
 107.266 +    {
 107.267 +    }
 107.268 +};
 107.269 +
 107.270 +
 107.271 +//-----------------------------------------------------------------------------
 107.272 +// Generic socket listener description
 107.273 +class ListenerDescription
 107.274 +{
 107.275 +public:
 107.276 +    ListenerDescription() :
 107.277 +        Transport(TransportType_None)
 107.278 +    {
 107.279 +    }
 107.280 +
 107.281 +    TransportType Transport;
 107.282 +};
 107.283 +
 107.284 +
 107.285 +//-----------------------------------------------------------------------------
 107.286 +// Description for a Berkley socket listener
 107.287 +class BerkleyListenerDescription : public ListenerDescription
 107.288 +{
 107.289 +public:
 107.290 +	static const int DefaultMaxIncomingConnections =  64;
 107.291 +	static const int DefaultMaxConnections         = 128;
 107.292 +
 107.293 +	BerkleyListenerDescription() :
 107.294 +		MaxIncomingConnections(DefaultMaxIncomingConnections),
 107.295 +		MaxConnections(DefaultMaxConnections)
 107.296 +	{
 107.297 +	}
 107.298 +
 107.299 +	Ptr<BerkleySocket> BoundSocketToListenWith;
 107.300 +    int                MaxIncomingConnections;
 107.301 +    int                MaxConnections;
 107.302 +};
 107.303 +
 107.304 +
 107.305 +//-----------------------------------------------------------------------------
 107.306 +// Receive payload
 107.307 +struct ReceivePayload
 107.308 +{
 107.309 +	Connection* pConnection; // Source connection
 107.310 +	uint8_t*    pData;       // Pointer to data received
 107.311 +	int         Bytes;       // Number of bytes of data received
 107.312 +};
 107.313 +
 107.314 +//-----------------------------------------------------------------------------
 107.315 +// Broadcast parameters
 107.316 +class BroadcastParameters
 107.317 +{
 107.318 +public:
 107.319 +    BroadcastParameters() :
 107.320 +        pData(NULL),
 107.321 +        Bytes(0)
 107.322 +    {
 107.323 +    }
 107.324 +
 107.325 +    BroadcastParameters(const void* _pData, int _bytes) :
 107.326 +        pData(_pData),
 107.327 +        Bytes(_bytes)
 107.328 +    {
 107.329 +    }
 107.330 +
 107.331 +public:
 107.332 +    const void*     pData;       // Pointer to data to send
 107.333 +    int             Bytes;       // Number of bytes of data received
 107.334 +};
 107.335 +
 107.336 +//-----------------------------------------------------------------------------
 107.337 +// Send parameters
 107.338 +class SendParameters
 107.339 +{
 107.340 +public:
 107.341 +	SendParameters() :
 107.342 +		pData(NULL),
 107.343 +		Bytes(0)
 107.344 +	{
 107.345 +	}
 107.346 +	SendParameters(Ptr<Connection> _pConnection, const void* _pData, int _bytes) :
 107.347 +		pConnection(_pConnection),
 107.348 +		pData(_pData),
 107.349 +		Bytes(_bytes)
 107.350 +	{
 107.351 +	}
 107.352 +
 107.353 +public:
 107.354 +	Ptr<Connection> pConnection; // Connection to use
 107.355 +	const void*     pData;       // Pointer to data to send
 107.356 +	int             Bytes;       // Number of bytes of data received
 107.357 +};
 107.358 +
 107.359 +
 107.360 +//-----------------------------------------------------------------------------
 107.361 +// Parameters to connect
 107.362 +struct ConnectParameters
 107.363 +{
 107.364 +public:
 107.365 +	ConnectParameters() :
 107.366 +		Transport(TransportType_None)
 107.367 +	{
 107.368 +	}
 107.369 +
 107.370 +	TransportType Transport;
 107.371 +};
 107.372 +
 107.373 +struct ConnectParametersBerkleySocket : public ConnectParameters
 107.374 +{
 107.375 +	SockAddr           RemoteAddress;
 107.376 +	Ptr<BerkleySocket> BoundSocketToConnectWith;
 107.377 +    bool               Blocking;
 107.378 +
 107.379 +    ConnectParametersBerkleySocket(BerkleySocket* s, SockAddr* addr, bool blocking,
 107.380 +                                   TransportType transport) :
 107.381 +        RemoteAddress(*addr),
 107.382 +        BoundSocketToConnectWith(s),
 107.383 +        Blocking(blocking)
 107.384 +    {
 107.385 +        Transport = transport;
 107.386 +    }
 107.387 +};
 107.388 +
 107.389 +
 107.390 +//-----------------------------------------------------------------------------
 107.391 +// Listener receive result
 107.392 +enum ListenerReceiveResult
 107.393 +{
 107.394 +	/// The SessionListener used this message and it shouldn't be given to the user.
 107.395 +	LRR_RETURN = 0,
 107.396 +
 107.397 +	/// The SessionListener is going to hold on to this message.  Do not deallocate it but do not pass it to other plugins either.
 107.398 +	LRR_BREAK,
 107.399 +
 107.400 +    /// This message will be processed by other SessionListeners, and at last by the user.
 107.401 +    LRR_CONTINUE,
 107.402 +};
 107.403 +
 107.404 +
 107.405 +//-----------------------------------------------------------------------------
 107.406 +// SessionListener
 107.407 +
 107.408 +// Callback interface for network events such as connecting, disconnecting, getting data, independent of the transport medium
 107.409 +class SessionListener
 107.410 +{
 107.411 +public:
 107.412 +	virtual ~SessionListener(){}
 107.413 +
 107.414 +	// Data events
 107.415 +    virtual void OnReceive(ReceivePayload* pPayload, ListenerReceiveResult* lrrOut) { OVR_UNUSED2(pPayload, lrrOut);  }
 107.416 +
 107.417 +	// Connection was closed
 107.418 +    virtual void OnDisconnected(Connection* conn) = 0;
 107.419 +
 107.420 +	// Connection was created (some data was exchanged to verify protocol compatibility too)
 107.421 +    virtual void OnConnected(Connection* conn) = 0;
 107.422 +
 107.423 +    // Server accepted client
 107.424 +    virtual void OnNewIncomingConnection(Connection* conn)     { OnConnected(conn); }
 107.425 +    // Client was accepted
 107.426 +    virtual void OnConnectionRequestAccepted(Connection* conn) { OnConnected(conn); }
 107.427 +
 107.428 +    // Connection attempt failed for some reason
 107.429 +    virtual void OnConnectionAttemptFailed(Connection* conn)   { OnDisconnected(conn); }
 107.430 +
 107.431 +    // Incompatible protocol
 107.432 +    virtual void OnIncompatibleProtocol(Connection* conn)      { OnConnectionAttemptFailed(conn); }
 107.433 +    // Disconnected during initial handshake
 107.434 +    virtual void OnHandshakeAttemptFailed(Connection* conn)    { OnConnectionAttemptFailed(conn); }
 107.435 +
 107.436 +	// Other
 107.437 +    virtual void OnAddedToSession(Session* session)            { OVR_UNUSED(session); }
 107.438 +    virtual void OnRemovedFromSession(Session* session)        { OVR_UNUSED(session); }
 107.439 +};
 107.440 +
 107.441 +
 107.442 +//-----------------------------------------------------------------------------
 107.443 +// Session
 107.444 +
 107.445 +//  Interface for network events such as listening on a socket, sending data, connecting, and disconnecting. Works independently of the transport medium and also implements loopback
 107.446 +class Session : public SocketEvent_TCP, public NewOverrideBase
 107.447 +{
 107.448 +    // Implement a policy to avoid releasing memory backing allBlockingTcpSockets
 107.449 +	struct ArrayNoShrinkPolicy : ArrayDefaultPolicy
 107.450 +	{
 107.451 +		bool NeverShrinking() const { return 1; }
 107.452 +	};
 107.453 +
 107.454 +public:
 107.455 +    Session() :
 107.456 +        HasLoopbackListener(false)
 107.457 +    {
 107.458 +    }
 107.459 +    virtual ~Session()
 107.460 +    {
 107.461 +        // Ensure memory backing the sockets array is released
 107.462 +		allBlockingTcpSockets.ClearAndRelease();
 107.463 +    }
 107.464 +
 107.465 +	virtual SessionResult Listen(ListenerDescription* pListenerDescription);
 107.466 +	virtual SessionResult Connect(ConnectParameters* cp);
 107.467 +	virtual int           Send(SendParameters* payload);
 107.468 +    virtual void          Broadcast(BroadcastParameters* payload);
 107.469 +    // DO NOT CALL Poll() FROM MULTIPLE THREADS due to allBlockingTcpSockets being a member
 107.470 +    virtual void          Poll(bool listeners = true);
 107.471 +	virtual void          AddSessionListener(SessionListener* se);
 107.472 +	virtual void          RemoveSessionListener(SessionListener* se);
 107.473 +    virtual SInt32        GetActiveSocketsCount();
 107.474 +
 107.475 +    // Packetized TCP convenience functions
 107.476 +    virtual SessionResult ListenPTCP(BerkleyBindParameters* bbp);
 107.477 +    virtual SessionResult ConnectPTCP(BerkleyBindParameters* bbp, SockAddr* RemoteAddress, bool blocking);
 107.478 +
 107.479 +    // Closes all the sockets; useful for interrupting the socket polling during shutdown
 107.480 +    void            Shutdown();
 107.481 +
 107.482 +    // Get count of successful connections (past handshake point)
 107.483 +    int             GetConnectionCount() const
 107.484 +    {
 107.485 +        return FullConnections.GetSizeI();
 107.486 +    }
 107.487 +    Ptr<Connection> GetConnectionAtIndex(int index);
 107.488 +
 107.489 +protected:
 107.490 +	virtual Ptr<Connection> AllocConnection(TransportType transportType);
 107.491 +
 107.492 +    Lock SocketListenersLock, ConnectionsLock, SessionListenersLock;
 107.493 +    bool                      HasLoopbackListener; // Has loopback listener installed?
 107.494 +	Array< Ptr<TCPSocket> >   SocketListeners;     // List of active sockets
 107.495 +    Array< Ptr<Connection> >  AllConnections;      // List of active connections stuck at the versioning handshake
 107.496 +    Array< Ptr<Connection> >  FullConnections;     // List of active connections past the versioning handshake
 107.497 +    Array< SessionListener* > SessionListeners;    // List of session listeners
 107.498 +    Array< Ptr< Net::TCPSocket >, ArrayNoShrinkPolicy > allBlockingTcpSockets; // Preallocated blocking sockets array
 107.499 +
 107.500 +    // Tools
 107.501 +    Ptr<PacketizedTCPConnection> findConnectionBySocket(Array< Ptr<Connection> >& connectionArray, Socket* s, int *connectionIndex = NULL); // Call with ConnectionsLock held
 107.502 +    Ptr<PacketizedTCPConnection> findConnectionBySockAddr(SockAddr* address); // Call with ConnectionsLock held
 107.503 +    int                   invokeSessionListeners(ReceivePayload*);
 107.504 +    void                  invokeSessionEvent(void(SessionListener::*f)(Connection*), Connection* pConnection);
 107.505 +
 107.506 +	// TCP
 107.507 +	virtual void          TCP_OnRecv(Socket* pSocket, uint8_t* pData, int bytesRead);
 107.508 +	virtual void          TCP_OnClosed(TCPSocket* pSocket);
 107.509 +	virtual void          TCP_OnAccept(TCPSocket* pListener, SockAddr* pSockAddr, SocketHandle newSock);
 107.510 +	virtual void          TCP_OnConnected(TCPSocket* pSocket);
 107.511 +};
 107.512 +
 107.513 +
 107.514 +}} // OVR::Net
 107.515 +
 107.516 +#endif
   108.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   108.2 +++ b/LibOVR/Src/Net/OVR_Socket.cpp	Wed Jan 14 06:51:16 2015 +0200
   108.3 @@ -0,0 +1,94 @@
   108.4 +/************************************************************************************
   108.5 +
   108.6 +Filename    :   OVR_Socket.cpp
   108.7 +Content     :   Socket common data shared between all platforms.
   108.8 +Created     :   June 10, 2014
   108.9 +Authors     :   Kevin Jenkins, Chris Taylor
  108.10 +
  108.11 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
  108.12 +
  108.13 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
  108.14 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
  108.15 +which is provided at the time of installation or download, or which 
  108.16 +otherwise accompanies this software in either electronic or hard copy form.
  108.17 +
  108.18 +You may obtain a copy of the License at
  108.19 +
  108.20 +http://www.oculusvr.com/licenses/LICENSE-3.2 
  108.21 +
  108.22 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
  108.23 +distributed under the License is distributed on an "AS IS" BASIS,
  108.24 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  108.25 +See the License for the specific language governing permissions and
  108.26 +limitations under the License.
  108.27 +
  108.28 +************************************************************************************/
  108.29 +
  108.30 +#include "OVR_Socket.h"
  108.31 +
  108.32 +namespace OVR { namespace Net {
  108.33 +
  108.34 +
  108.35 +//-----------------------------------------------------------------------------
  108.36 +// Socket
  108.37 +
  108.38 +Socket::Socket() :
  108.39 +	Transport(TransportType_None)
  108.40 +{
  108.41 +}
  108.42 +
  108.43 +
  108.44 +//-----------------------------------------------------------------------------
  108.45 +// BerkleyBindParameters
  108.46 +
  108.47 +BerkleyBindParameters::BerkleyBindParameters() :
  108.48 +	Port(0),
  108.49 +    Address(),
  108.50 +    blockingTimeout(0x7fffffff)
  108.51 +{
  108.52 +}
  108.53 +
  108.54 +//-----------------------------------------------------------------------------
  108.55 +// BerkleySocket
  108.56 +
  108.57 +BerkleySocket::BerkleySocket() :
  108.58 +	TheSocket(INVALID_SOCKET)
  108.59 +  //TimeoutUsec(0) // Initialized by SetBlockingTimeout
  108.60 +  //TimeoutSec(0)  // "
  108.61 +{
  108.62 +    SetBlockingTimeout(1000);
  108.63 +}
  108.64 +
  108.65 +BerkleySocket::~BerkleySocket()
  108.66 +{
  108.67 +	// Close socket on destruction
  108.68 +	Close();
  108.69 +}
  108.70 +
  108.71 +
  108.72 +//-----------------------------------------------------------------------------
  108.73 +// UDPSocketBase
  108.74 +
  108.75 +UDPSocketBase::UDPSocketBase()
  108.76 +{
  108.77 +	Transport = TransportType_UDP;
  108.78 +}
  108.79 +
  108.80 +
  108.81 +//-----------------------------------------------------------------------------
  108.82 +// TCPSocketBase
  108.83 +
  108.84 +TCPSocketBase::TCPSocketBase()
  108.85 +  : IsListenSocket(false)
  108.86 +{
  108.87 +	Transport = TransportType_TCP;
  108.88 +}
  108.89 +
  108.90 +TCPSocketBase::TCPSocketBase(SocketHandle handle)
  108.91 +  : IsListenSocket(false)
  108.92 +{
  108.93 +	TheSocket = handle;
  108.94 +}
  108.95 +
  108.96 +
  108.97 +}} // OVR::Net
   109.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   109.2 +++ b/LibOVR/Src/Net/OVR_Socket.h	Wed Jan 14 06:51:16 2015 +0200
   109.3 @@ -0,0 +1,242 @@
   109.4 +/************************************************************************************
   109.5 +
   109.6 +PublicHeader:   n/a
   109.7 +Filename    :   OVR_Socket.h
   109.8 +Content     :   Socket common data shared between all platforms.
   109.9 +Created     :   June 10, 2014
  109.10 +Authors     :   Kevin Jenkins, Chris Taylor
  109.11 +
  109.12 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
  109.13 +
  109.14 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
  109.15 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
  109.16 +which is provided at the time of installation or download, or which 
  109.17 +otherwise accompanies this software in either electronic or hard copy form.
  109.18 +
  109.19 +You may obtain a copy of the License at
  109.20 +
  109.21 +http://www.oculusvr.com/licenses/LICENSE-3.2 
  109.22 +
  109.23 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
  109.24 +distributed under the License is distributed on an "AS IS" BASIS,
  109.25 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  109.26 +See the License for the specific language governing permissions and
  109.27 +limitations under the License.
  109.28 +
  109.29 +************************************************************************************/
  109.30 +
  109.31 +#ifndef OVR_Socket_h
  109.32 +#define OVR_Socket_h
  109.33 +
  109.34 +#include "../Kernel/OVR_Types.h"
  109.35 +#include "../Kernel/OVR_Timer.h"
  109.36 +#include "../Kernel/OVR_Allocator.h"
  109.37 +#include "../Kernel/OVR_RefCount.h"
  109.38 +#include "../Kernel/OVR_String.h"
  109.39 +
  109.40 +// OS-specific socket headers
  109.41 +#if defined(OVR_OS_WIN32)
  109.42 +#include <WinSock2.h>
  109.43 +#include <WS2tcpip.h>
  109.44 +#define WIN32_LEAN_AND_MEAN
  109.45 +#include <windows.h>
  109.46 +#else
  109.47 +# include <unistd.h>
  109.48 +# include <sys/types.h>
  109.49 +# include <netinet/in.h>
  109.50 +#ifdef OVR_OS_ANDROID
  109.51 +#include <sys/socket.h>
  109.52 +#endif
  109.53 +#endif
  109.54 +
  109.55 +namespace OVR { namespace Net {
  109.56 +
  109.57 +class SockAddr;
  109.58 +class UDPSocket;
  109.59 +class TCPSocket;
  109.60 +
  109.61 +
  109.62 +//-----------------------------------------------------------------------------
  109.63 +// Portable numeric Socket handle
  109.64 +#if defined(OVR_OS_WIN32)
  109.65 +typedef SOCKET SocketHandle;
  109.66 +#else
  109.67 +typedef int SocketHandle;
  109.68 +static const SocketHandle INVALID_SOCKET = -1;
  109.69 +static const int SOCKET_ERROR = -1;
  109.70 +#endif
  109.71 +
  109.72 +
  109.73 +//-----------------------------------------------------------------------------
  109.74 +// Types of network transport
  109.75 +enum TransportType
  109.76 +{
  109.77 +	TransportType_None,          // No transport (useful placeholder for invalid states)
  109.78 +	TransportType_Loopback,      // Loopback transport: Class talks to itself
  109.79 +	TransportType_TCP,           // TCP/IPv4/v6
  109.80 +	TransportType_UDP,           // UDP/IPv4/v6
  109.81 +	TransportType_PacketizedTCP  // Packetized TCP: Message framing is automatic
  109.82 +};
  109.83 +
  109.84 +
  109.85 +//-----------------------------------------------------------------------------
  109.86 +// Abstraction for a network socket. Inheritance hierarchy
  109.87 +// modeled after RakNet so that future support can be added
  109.88 +// for Linux, Windows RT, consoles, etc.
  109.89 +class Socket : public RefCountBase<Socket>
  109.90 +{
  109.91 +public:
  109.92 +	Socket();
  109.93 +	virtual void Close() = 0;
  109.94 +
  109.95 +public:
  109.96 +	TransportType Transport; // Type of transport
  109.97 +};
  109.98 +
  109.99 +
 109.100 +//-----------------------------------------------------------------------------
 109.101 +// Bind parameters for Berkley sockets
 109.102 +struct BerkleyBindParameters
 109.103 +{
 109.104 +public:
 109.105 +	BerkleyBindParameters();
 109.106 +
 109.107 +public:
 109.108 +	uint16_t Port;     // Port
 109.109 +	String Address;
 109.110 +    uint32_t blockingTimeout;
 109.111 +};
 109.112 +
 109.113 +
 109.114 +//-----------------------------------------------------------------------------
 109.115 +// Berkley socket
 109.116 +class BerkleySocket : public Socket
 109.117 +{
 109.118 +public:
 109.119 +	BerkleySocket();
 109.120 +	virtual ~BerkleySocket();
 109.121 +
 109.122 +	virtual void   Close();
 109.123 +	virtual int32_t GetSockname(SockAddr* pSockAddrOut);
 109.124 +	virtual void   SetBlockingTimeout(int timeoutMs) // milliseconds
 109.125 +	{
 109.126 +        TimeoutSec = timeoutMs / 1000;
 109.127 +        TimeoutUsec = (timeoutMs % 1000) * 1000;
 109.128 +	}
 109.129 +    int            GetBlockingTimeoutUsec() const
 109.130 +    {
 109.131 +        return TimeoutUsec;
 109.132 +    }
 109.133 +    int            GetBlockingTimeoutSec() const
 109.134 +    {
 109.135 +        return TimeoutSec;
 109.136 +    }
 109.137 +    SocketHandle   GetSocketHandle() const
 109.138 +    {
 109.139 +        return TheSocket;
 109.140 +    }
 109.141 +
 109.142 +protected:
 109.143 +	SocketHandle TheSocket;           // Socket handle
 109.144 +    int TimeoutUsec, TimeoutSec;
 109.145 +};
 109.146 +
 109.147 +
 109.148 +//-----------------------------------------------------------------------------
 109.149 +// UDP socket events
 109.150 +class SocketEvent_UDP
 109.151 +{
 109.152 +public:
 109.153 +	virtual ~SocketEvent_UDP(){}
 109.154 +
 109.155 +	virtual void UDP_OnRecv(Socket* pSocket, uint8_t* pData,
 109.156 +							uint32_t bytesRead, SockAddr* pSockAddr)
 109.157 +	{
 109.158 +		OVR_UNUSED4(pSocket, pData, bytesRead, pSockAddr);
 109.159 +	}
 109.160 +};
 109.161 +
 109.162 +
 109.163 +//-----------------------------------------------------------------------------
 109.164 +// TCP socket events
 109.165 +class SocketEvent_TCP
 109.166 +{
 109.167 +public:
 109.168 +	virtual ~SocketEvent_TCP(){}
 109.169 +
 109.170 +	virtual void TCP_OnRecv     (Socket* pSocket,
 109.171 +                                 uint8_t* pData,
 109.172 +                                 int bytesRead)
 109.173 +	{
 109.174 +		OVR_UNUSED3(pSocket, pData, bytesRead);
 109.175 +	}
 109.176 +	virtual void TCP_OnClosed   (TCPSocket* pSocket)
 109.177 +	{
 109.178 +		OVR_UNUSED(pSocket);
 109.179 +	}
 109.180 +	virtual void TCP_OnAccept   (TCPSocket* pListener,
 109.181 +                                 SockAddr* pSockAddr,
 109.182 +								 SocketHandle newSock)
 109.183 +	{
 109.184 +		OVR_UNUSED3(pListener, pSockAddr, newSock);
 109.185 +	}
 109.186 +	virtual void TCP_OnConnected(TCPSocket* pSocket)
 109.187 +	{
 109.188 +		OVR_UNUSED(pSocket);
 109.189 +	}
 109.190 +};
 109.191 +
 109.192 +
 109.193 +//-----------------------------------------------------------------------------
 109.194 +// UDP Berkley socket
 109.195 +
 109.196 +// Base class for UDP sockets, code shared between platforms
 109.197 +class UDPSocketBase : public BerkleySocket
 109.198 +{
 109.199 +public:
 109.200 +	UDPSocketBase();
 109.201 +
 109.202 +public:
 109.203 +	virtual SocketHandle Bind(BerkleyBindParameters* pBindParameters) = 0;
 109.204 +	virtual int          Send(const void* pData,
 109.205 +                              int bytes,
 109.206 +                              SockAddr* pSockAddr) = 0;
 109.207 +	virtual void         Poll(SocketEvent_UDP* eventHandler) = 0;
 109.208 +
 109.209 +protected:
 109.210 +	virtual void         OnRecv(SocketEvent_UDP* eventHandler,
 109.211 +                                uint8_t* pData,
 109.212 +								int bytesRead,
 109.213 +                                SockAddr* address) = 0;
 109.214 +};
 109.215 +
 109.216 +
 109.217 +//-----------------------------------------------------------------------------
 109.218 +// TCP Berkley socket
 109.219 +
 109.220 +// Base class for TCP sockets, code shared between platforms
 109.221 +class TCPSocketBase : public BerkleySocket
 109.222 +{
 109.223 +public:
 109.224 +	TCPSocketBase();
 109.225 +	TCPSocketBase(SocketHandle handle);
 109.226 +
 109.227 +public:
 109.228 +	virtual SocketHandle Bind(BerkleyBindParameters* pBindParameters) = 0;
 109.229 +	virtual int          Listen() = 0;
 109.230 +	virtual int          Connect(SockAddr* pSockAddr) = 0;
 109.231 +	virtual int          Send(const void* pData,
 109.232 +                              int bytes) = 0;
 109.233 +protected:
 109.234 +	virtual void         OnRecv(SocketEvent_TCP* eventHandler,
 109.235 +                                uint8_t* pData,
 109.236 +                                int bytesRead) = 0;
 109.237 +
 109.238 +protected:
 109.239 +	bool IsListenSocket; // Is the socket listening (acting as a server)?
 109.240 +};
 109.241 +
 109.242 +
 109.243 +}} // OVR::Net
 109.244 +
 109.245 +#endif
   110.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   110.2 +++ b/LibOVR/Src/Net/OVR_Unix_Socket.cpp	Wed Jan 14 06:51:16 2015 +0200
   110.3 @@ -0,0 +1,600 @@
   110.4 +/************************************************************************************
   110.5 +
   110.6 +Filename    :   OVR_Unix_Socket.cpp
   110.7 +Content     :   Berkley sockets networking implementation
   110.8 +Created     :   July 1, 2014
   110.9 +Authors     :   Kevin Jenkins
  110.10 +
  110.11 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
  110.12 +
  110.13 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
  110.14 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
  110.15 +which is provided at the time of installation or download, or which 
  110.16 +otherwise accompanies this software in either electronic or hard copy form.
  110.17 +
  110.18 +You may obtain a copy of the License at
  110.19 +
  110.20 +http://www.oculusvr.com/licenses/LICENSE-3.2 
  110.21 +
  110.22 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
  110.23 +distributed under the License is distributed on an "AS IS" BASIS,
  110.24 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  110.25 +See the License for the specific language governing permissions and
  110.26 +limitations under the License.
  110.27 +
  110.28 +************************************************************************************/
  110.29 +
  110.30 +#include "OVR_Unix_Socket.h"
  110.31 +#include "../Kernel/OVR_Std.h"
  110.32 +#include "../Kernel/OVR_Allocator.h"
  110.33 +#include "../Kernel/OVR_Threads.h" // Thread::MSleep
  110.34 +#include "../Kernel/OVR_Log.h"
  110.35 +
  110.36 +#include <errno.h>
  110.37 +
  110.38 +namespace OVR { namespace Net {
  110.39 +
  110.40 +//-----------------------------------------------------------------------------
  110.41 +// BerkleySocket
  110.42 +
  110.43 +void BerkleySocket::Close()
  110.44 +{
  110.45 +	if (TheSocket != INVALID_SOCKET)
  110.46 +	{
  110.47 +		close(TheSocket);
  110.48 +		TheSocket = INVALID_SOCKET;
  110.49 +	}
  110.50 +}
  110.51 +
  110.52 +SInt32 BerkleySocket::GetSockname(SockAddr *pSockAddrOut)
  110.53 +{
  110.54 +	struct sockaddr_in6 sa;
  110.55 +	memset(&sa,0,sizeof(sa));
  110.56 +	socklen_t size = sizeof(sa);
  110.57 +	SInt32 i = getsockname(TheSocket, (sockaddr*)&sa, &size);
  110.58 +	if (i>=0)
  110.59 +	{
  110.60 +		pSockAddrOut->Set(&sa);
  110.61 +	}
  110.62 +	return i;
  110.63 +}
  110.64 +
  110.65 +
  110.66 +//-----------------------------------------------------------------------------
  110.67 +// BitStream overloads for SockAddr
  110.68 +
  110.69 +BitStream& operator<<(BitStream& out, SockAddr& in)
  110.70 +{
  110.71 +	out.WriteBits((const unsigned char*) &in.Addr6, sizeof(in.Addr6)*8, true);
  110.72 +	return out;
  110.73 +}
  110.74 +
  110.75 +BitStream& operator>>(BitStream& in, SockAddr& out)
  110.76 +{
  110.77 +	bool success = in.ReadBits((unsigned char*) &out.Addr6, sizeof(out.Addr6)*8, true);
  110.78 +	OVR_ASSERT(success);
  110.79 +	OVR_UNUSED(success);
  110.80 +	return in;
  110.81 +}
  110.82 +
  110.83 +
  110.84 +//-----------------------------------------------------------------------------
  110.85 +// SockAddr
  110.86 +
  110.87 +SockAddr::SockAddr()
  110.88 +{
  110.89 +}
  110.90 +
  110.91 +SockAddr::SockAddr(SockAddr* address)
  110.92 +{
  110.93 +	Set(&address->Addr6);
  110.94 +}
  110.95 +
  110.96 +SockAddr::SockAddr(sockaddr_storage* storage)
  110.97 +{
  110.98 +	Set(storage);
  110.99 +}
 110.100 +
 110.101 +SockAddr::SockAddr(sockaddr_in6* address)
 110.102 +{
 110.103 +	Set(address);
 110.104 +}
 110.105 +
 110.106 +SockAddr::SockAddr(const char* hostAddress, UInt16 port, int sockType)
 110.107 +{
 110.108 +	Set(hostAddress, port, sockType);
 110.109 +}
 110.110 +
 110.111 +void SockAddr::Set(const sockaddr_storage* storage)
 110.112 +{
 110.113 +	memcpy(&Addr6, storage, sizeof(Addr6));
 110.114 +}
 110.115 +
 110.116 +void SockAddr::Set(const sockaddr_in6* address)
 110.117 +{
 110.118 +	memcpy(&Addr6, address, sizeof(Addr6));
 110.119 +}
 110.120 +
 110.121 +void SockAddr::Set(const char* hostAddress, UInt16 port, int sockType)
 110.122 +{
 110.123 +	memset(&Addr6, 0, sizeof(Addr6));
 110.124 +
 110.125 +	struct addrinfo hints;
 110.126 +
 110.127 +	// make sure the struct is empty
 110.128 +	memset(&hints, 0, sizeof (addrinfo));
 110.129 +
 110.130 +	hints.ai_socktype = sockType; // SOCK_DGRAM or SOCK_STREAM
 110.131 +	hints.ai_flags = AI_PASSIVE;     // fill in my IP for me
 110.132 +	hints.ai_family = AF_UNSPEC ;
 110.133 +
 110.134 +    if (SOCK_DGRAM == sockType)
 110.135 +    {
 110.136 +        hints.ai_protocol = IPPROTO_UDP;
 110.137 +    }
 110.138 +    else if (SOCK_STREAM == sockType)
 110.139 +    {
 110.140 +        hints.ai_protocol = IPPROTO_TCP;
 110.141 +    }
 110.142 +
 110.143 +    struct addrinfo* servinfo = NULL;  // will point to the results
 110.144 +
 110.145 +	char portStr[32];
 110.146 +	OVR_itoa(port, portStr, sizeof(portStr), 10);
 110.147 +	int errcode = getaddrinfo(hostAddress, portStr, &hints, &servinfo);
 110.148 +
 110.149 +    if (0 != errcode)
 110.150 +    {
 110.151 +        OVR::LogError("getaddrinfo error: %s", gai_strerror(errcode));
 110.152 +    }
 110.153 +
 110.154 +    OVR_ASSERT(servinfo);
 110.155 +
 110.156 +    if (servinfo)
 110.157 +    {
 110.158 +        memcpy(&Addr6, servinfo->ai_addr, sizeof(Addr6));
 110.159 +
 110.160 +        freeaddrinfo(servinfo);
 110.161 +    }
 110.162 +}
 110.163 +
 110.164 +UInt16 SockAddr::GetPort()
 110.165 +{
 110.166 +	return htons(Addr6.sin6_port);
 110.167 +}
 110.168 +
 110.169 +String SockAddr::ToString(bool writePort, char portDelineator) const
 110.170 +{
 110.171 +    char dest[INET6_ADDRSTRLEN + 1];
 110.172 +
 110.173 +	int ret = getnameinfo((struct sockaddr*)&Addr6,
 110.174 +						  sizeof(struct sockaddr_in6),
 110.175 +						  dest,
 110.176 +						  INET6_ADDRSTRLEN,
 110.177 +						  NULL,
 110.178 +						  0,
 110.179 +						  NI_NUMERICHOST);
 110.180 +	if (ret != 0)
 110.181 +	{
 110.182 +		dest[0] = '\0';
 110.183 +	}
 110.184 +
 110.185 +	if (writePort)
 110.186 +	{
 110.187 +		unsigned char ch[2];
 110.188 +		ch[0]=portDelineator;
 110.189 +		ch[1]=0;
 110.190 +		OVR_strcat(dest, 16, (const char*) ch);
 110.191 +		OVR_itoa(ntohs(Addr6.sin6_port), dest+strlen(dest), 16, 10);
 110.192 +	}
 110.193 +
 110.194 +    return String(dest);
 110.195 +}
 110.196 +bool SockAddr::IsLocalhost() const
 110.197 +{
 110.198 +    static const unsigned char localhost_bytes[] =
 110.199 +    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
 110.200 +
 110.201 +    return memcmp(Addr6.sin6_addr.s6_addr, localhost_bytes, 16) == 0;
 110.202 +}
 110.203 +bool SockAddr::operator==( const SockAddr& right ) const
 110.204 +{
 110.205 +	return memcmp(&Addr6, &right.Addr6, sizeof(Addr6)) == 0;
 110.206 +}
 110.207 +
 110.208 +bool SockAddr::operator!=( const SockAddr& right ) const
 110.209 +{
 110.210 +	return !(*this == right);
 110.211 +}
 110.212 +
 110.213 +bool SockAddr::operator>( const SockAddr& right ) const
 110.214 +{
 110.215 +	return memcmp(&Addr6, &right.Addr6, sizeof(Addr6)) > 0;
 110.216 +}
 110.217 +
 110.218 +bool SockAddr::operator<( const SockAddr& right ) const
 110.219 +{
 110.220 +	return memcmp(&Addr6, &right.Addr6, sizeof(Addr6)) < 0;
 110.221 +}
 110.222 +
 110.223 +
 110.224 +// Returns true on success
 110.225 +static bool SetSocketOptions(SocketHandle sock)
 110.226 +{
 110.227 +    bool failed = false;
 110.228 +    int sock_opt;
 110.229 +    int sockError = 0;
 110.230 +
 110.231 +    // This doubles the max throughput rate
 110.232 +    sock_opt=1024*256;
 110.233 +    sockError = setsockopt(sock, SOL_SOCKET, SO_RCVBUF, ( char * ) & sock_opt, sizeof ( sock_opt ) );
 110.234 +    if (sockError != 0)
 110.235 +    {
 110.236 +		int errsv = errno;
 110.237 +        OVR::LogError("[Socket] Failed SO_RCVBUF setsockopt, errno: %d", errsv);
 110.238 +        failed = true;
 110.239 +    }
 110.240 +    
 110.241 +    // This doesn't make much difference: 10% maybe
 110.242 +    // Not supported on console 2
 110.243 +    sock_opt=1024*16;
 110.244 +    sockError = setsockopt(sock, SOL_SOCKET, SO_SNDBUF, ( char * ) & sock_opt, sizeof ( sock_opt ) );
 110.245 +    if (sockError != 0)
 110.246 +    {
 110.247 +		int errsv = errno;
 110.248 +        OVR::LogError("[Socket] Failed SO_SNDBUF setsockopt, errno: %d", errsv);
 110.249 +        failed = true;
 110.250 +    }
 110.251 +
 110.252 +    // NOTE: This should be OVR_OS_BSD, not Mac.
 110.253 +#ifdef OVR_OS_MAC
 110.254 +    int value = 1;
 110.255 +    sockError = setsockopt(sock, SOL_SOCKET, SO_NOSIGPIPE, &value, sizeof(value));
 110.256 +    if (sockError != 0)
 110.257 +    {
 110.258 +        int errsv = errno;
 110.259 +        OVR::LogError("[Socket] Failed SO_NOSIGPIPE setsockopt, errno: %d", errsv);
 110.260 +        failed = true;
 110.261 +    }
 110.262 +#endif
 110.263 +
 110.264 +    // Reuse address is only needed for posix platforms, as it is the default
 110.265 +    // on Windows platforms.
 110.266 +    int optval = 1;
 110.267 +    sockError = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(int));
 110.268 +    if (sockError != 0)
 110.269 +    {
 110.270 +		int errsv = errno;
 110.271 +        OVR::LogError("[Socket] Failed SO_REUSEADDR setsockopt, errno: %d", errsv);
 110.272 +        failed = true;
 110.273 +    }
 110.274 +
 110.275 +    return !failed;
 110.276 +}
 110.277 +
 110.278 +void _Ioctlsocket(SocketHandle sock, unsigned long nonblocking)
 110.279 +{
 110.280 +	int flags = fcntl(sock, F_GETFL, 0);
 110.281 +	if (flags < 0) return; // return false
 110.282 +	if (nonblocking == 0)	{ flags &= ~O_NONBLOCK; }
 110.283 +	else					{ flags |= O_NONBLOCK;  }
 110.284 +	fcntl(sock, F_SETFL, flags);
 110.285 +}
 110.286 +
 110.287 +static SocketHandle BindShared(int ai_family, int ai_socktype, BerkleyBindParameters *pBindParameters)
 110.288 +{
 110.289 +	SocketHandle sock;
 110.290 +
 110.291 +	struct addrinfo hints;
 110.292 +	memset(&hints, 0, sizeof (addrinfo)); // make sure the struct is empty
 110.293 +	hints.ai_family = ai_family;
 110.294 +	hints.ai_socktype = ai_socktype;
 110.295 +	hints.ai_flags = AI_PASSIVE;     // fill in my IP for me
 110.296 +	struct addrinfo *servinfo=0, *aip;  // will point to the results
 110.297 +	char portStr[32];
 110.298 +	OVR_itoa(pBindParameters->Port, portStr, sizeof(portStr), 10);
 110.299 +
 110.300 +    int errcode = 0;
 110.301 +	if (!pBindParameters->Address.IsEmpty())
 110.302 +		errcode = getaddrinfo(pBindParameters->Address.ToCStr(), portStr, &hints, &servinfo);
 110.303 +	else
 110.304 +		errcode = getaddrinfo(0, portStr, &hints, &servinfo);
 110.305 +
 110.306 +    if (0 != errcode)
 110.307 +    {
 110.308 +        OVR::LogError("getaddrinfo error: %s", gai_strerror(errcode));
 110.309 +    }
 110.310 +
 110.311 +	for (aip = servinfo; aip != NULL; aip = aip->ai_next)
 110.312 +	{
 110.313 +		// Open socket. The address type depends on what
 110.314 +		// getaddrinfo() gave us.
 110.315 +		sock = socket(aip->ai_family, aip->ai_socktype, aip->ai_protocol);
 110.316 +		if (sock != 0)
 110.317 +		{
 110.318 +            SetSocketOptions(sock);
 110.319 +			int ret = bind( sock, aip->ai_addr, (int) aip->ai_addrlen );
 110.320 +			if (ret>=0)
 110.321 +			{
 110.322 +				// The actual socket is always non-blocking
 110.323 +				// I control blocking or not using WSAEventSelect
 110.324 +				_Ioctlsocket(sock, 1);
 110.325 +                freeaddrinfo(servinfo);
 110.326 +				return sock;
 110.327 +			}
 110.328 +			else
 110.329 +			{
 110.330 +				close(sock);
 110.331 +			}
 110.332 +		}
 110.333 +	}
 110.334 +
 110.335 +    if (servinfo) { freeaddrinfo(servinfo); }
 110.336 +	return INVALID_SOCKET;
 110.337 +}
 110.338 +
 110.339 +
 110.340 +//-----------------------------------------------------------------------------
 110.341 +// UDPSocket
 110.342 +
 110.343 +UDPSocket::UDPSocket()
 110.344 +{
 110.345 +	RecvBuf = new UByte[RecvBufSize];
 110.346 +}
 110.347 +
 110.348 +UDPSocket::~UDPSocket()
 110.349 +{
 110.350 +	delete[] RecvBuf;
 110.351 +}
 110.352 +
 110.353 +SocketHandle UDPSocket::Bind(BerkleyBindParameters *pBindParameters)
 110.354 +{
 110.355 +	SocketHandle s = BindShared(AF_INET6, SOCK_DGRAM, pBindParameters);
 110.356 +	if (s < 0)
 110.357 +		return s;
 110.358 +
 110.359 +	Close();
 110.360 +	TheSocket = s;
 110.361 +
 110.362 +	return TheSocket;
 110.363 +}
 110.364 +
 110.365 +void UDPSocket::OnRecv(SocketEvent_UDP* eventHandler, UByte* pData, int bytesRead, SockAddr* address)
 110.366 +{
 110.367 +	eventHandler->UDP_OnRecv(this, pData, bytesRead, address);
 110.368 +}
 110.369 +
 110.370 +int UDPSocket::Send(const void* pData, int bytes, SockAddr* address)
 110.371 +{
 110.372 +    // NOTE: This should be OVR_OS_BSD
 110.373 +#ifdef OVR_OS_MAC
 110.374 +    int flags = 0;
 110.375 +#else
 110.376 +    int flags = MSG_NOSIGNAL;
 110.377 +#endif
 110.378 +
 110.379 +	return (int)sendto(TheSocket, (const char*)pData, bytes, flags, (const sockaddr*)&address->Addr6, sizeof(address->Addr6));
 110.380 +}
 110.381 +
 110.382 +void UDPSocket::Poll(SocketEvent_UDP *eventHandler)
 110.383 +{
 110.384 +	struct sockaddr_storage win32_addr;
 110.385 +	socklen_t fromlen;
 110.386 +	int bytesRead;
 110.387 +
 110.388 +    // FIXME: Implement blocking poll wait for UDP
 110.389 +
 110.390 +	// While some bytes are read,
 110.391 +	while (fromlen = sizeof(win32_addr), // Must set fromlen each time
 110.392 +		   bytesRead = (int)recvfrom(TheSocket, (char*)RecvBuf, RecvBufSize, 0, (sockaddr*)&win32_addr, &fromlen),
 110.393 +		   bytesRead > 0)
 110.394 +	{
 110.395 +		SockAddr address(&win32_addr); // Wrap address
 110.396 +
 110.397 +		OnRecv(eventHandler, RecvBuf, bytesRead, &address);
 110.398 +	}
 110.399 +}
 110.400 +
 110.401 +
 110.402 +//-----------------------------------------------------------------------------
 110.403 +// TCPSocket
 110.404 +
 110.405 +TCPSocket::TCPSocket()
 110.406 +{
 110.407 +	IsConnecting = false;
 110.408 +	IsListenSocket = false;
 110.409 +}
 110.410 +TCPSocket::TCPSocket(SocketHandle boundHandle, bool isListenSocket)
 110.411 +{
 110.412 +	TheSocket = boundHandle;
 110.413 +	IsListenSocket = isListenSocket;
 110.414 +	IsConnecting = false;
 110.415 +	SetSocketOptions(TheSocket);
 110.416 +
 110.417 +	// The actual socket is always non-blocking
 110.418 +	_Ioctlsocket(TheSocket, 1);
 110.419 +}
 110.420 +
 110.421 +TCPSocket::~TCPSocket()
 110.422 +{
 110.423 +}
 110.424 +
 110.425 +void TCPSocket::OnRecv(SocketEvent_TCP* eventHandler, UByte* pData, int bytesRead)
 110.426 +{
 110.427 +	eventHandler->TCP_OnRecv(this, pData, bytesRead);
 110.428 +}
 110.429 +
 110.430 +SocketHandle TCPSocket::Bind(BerkleyBindParameters* pBindParameters)
 110.431 +{	
 110.432 +	SocketHandle s = BindShared(AF_INET6, SOCK_STREAM, pBindParameters);
 110.433 +	if (s < 0)
 110.434 +		return s;
 110.435 +
 110.436 +	Close();
 110.437 +
 110.438 +    SetBlockingTimeout(pBindParameters->blockingTimeout);
 110.439 +    TheSocket = s;
 110.440 +
 110.441 +	return TheSocket;
 110.442 +}
 110.443 +
 110.444 +int TCPSocket::Listen()
 110.445 +{
 110.446 +    if (IsListenSocket)
 110.447 +    {
 110.448 +        return 0;
 110.449 +    }
 110.450 +
 110.451 +	int i = listen(TheSocket, SOMAXCONN);
 110.452 +	if (i >= 0)
 110.453 +	{
 110.454 +		IsListenSocket = true;
 110.455 +	}
 110.456 +
 110.457 +	return i;
 110.458 +}
 110.459 +
 110.460 +int TCPSocket::Connect(SockAddr* address)
 110.461 +{
 110.462 +	int retval;
 110.463 +
 110.464 +	retval = connect(TheSocket, (struct sockaddr *) &address->Addr6, sizeof(address->Addr6));
 110.465 +	if (retval < 0)
 110.466 +	{
 110.467 +		int errsv = errno;
 110.468 +        // EINPROGRESS should not be checked on windows but should
 110.469 +        // be checked on POSIX platforms.
 110.470 +		if (errsv == EWOULDBLOCK || errsv == EINPROGRESS)
 110.471 +		{
 110.472 +            IsConnecting = true;
 110.473 +            return 0;
 110.474 +		}
 110.475 +
 110.476 +		OVR::LogText( "TCPSocket::Connect failed:Error code - %d\n", errsv );
 110.477 +	}
 110.478 +
 110.479 +	return retval;
 110.480 +}
 110.481 +
 110.482 +int TCPSocket::Send(const void* pData, int bytes)
 110.483 +{
 110.484 +	if (bytes <= 0)
 110.485 +	{
 110.486 +		return 0;
 110.487 +	}
 110.488 +	else
 110.489 +	{
 110.490 +		return (int)send(TheSocket, (const char*)pData, bytes, 0);
 110.491 +	}
 110.492 +}
 110.493 +
 110.494 +
 110.495 +//// TCPSocketPollState
 110.496 +
 110.497 +TCPSocketPollState::TCPSocketPollState()
 110.498 +{
 110.499 +    FD_ZERO(&readFD);
 110.500 +    FD_ZERO(&exceptionFD);
 110.501 +    FD_ZERO(&writeFD);
 110.502 +    largestDescriptor = INVALID_SOCKET;
 110.503 +}
 110.504 +
 110.505 +bool TCPSocketPollState::IsValid() const
 110.506 +{
 110.507 +    return largestDescriptor != INVALID_SOCKET;
 110.508 +}
 110.509 +
 110.510 +void TCPSocketPollState::Add(TCPSocket* tcpSocket)
 110.511 +{
 110.512 +    if (!tcpSocket)
 110.513 +    {
 110.514 +        return;
 110.515 +    }
 110.516 +
 110.517 +    SocketHandle handle = tcpSocket->GetSocketHandle();
 110.518 +
 110.519 +    if (handle == INVALID_SOCKET)
 110.520 +    {
 110.521 +        return;
 110.522 +    }
 110.523 +
 110.524 +    if (largestDescriptor == INVALID_SOCKET ||
 110.525 +        largestDescriptor < handle)
 110.526 +    {
 110.527 +        largestDescriptor = handle;
 110.528 +    }
 110.529 +
 110.530 +    FD_SET(handle, &readFD);
 110.531 +    FD_SET(handle, &exceptionFD);
 110.532 +
 110.533 +    if (tcpSocket->IsConnecting)
 110.534 +    {
 110.535 +        FD_SET(handle, &writeFD);
 110.536 +    }
 110.537 +}
 110.538 +
 110.539 +bool TCPSocketPollState::Poll(long usec, long seconds)
 110.540 +{
 110.541 +    timeval tv;
 110.542 +    tv.tv_sec = seconds;
 110.543 +    tv.tv_usec = (int)usec;
 110.544 +
 110.545 +    return select(largestDescriptor + 1, &readFD, &writeFD, &exceptionFD, &tv) > 0;
 110.546 +}
 110.547 +
 110.548 +void TCPSocketPollState::HandleEvent(TCPSocket* tcpSocket, SocketEvent_TCP* eventHandler)
 110.549 +{
 110.550 +    if (!tcpSocket || !eventHandler)
 110.551 +    {
 110.552 +        return;
 110.553 +    }
 110.554 +
 110.555 +    SocketHandle handle = tcpSocket->GetSocketHandle();
 110.556 +
 110.557 +    if (tcpSocket->IsConnecting && FD_ISSET(handle, &writeFD))
 110.558 +    {
 110.559 +        tcpSocket->IsConnecting = false;
 110.560 +        eventHandler->TCP_OnConnected(tcpSocket);
 110.561 +    }
 110.562 +
 110.563 +    if (FD_ISSET(handle, &readFD))
 110.564 +    {
 110.565 +        if (!tcpSocket->IsListenSocket)
 110.566 +        {
 110.567 +            static const int BUFF_SIZE = 8096;
 110.568 +            char data[BUFF_SIZE];
 110.569 +
 110.570 +            int bytesRead = (int)recv(handle, data, BUFF_SIZE, 0);
 110.571 +            if (bytesRead > 0)
 110.572 +            {
 110.573 +                tcpSocket->OnRecv(eventHandler, (UByte*)data, bytesRead);
 110.574 +            }
 110.575 +            else // Disconnection event:
 110.576 +            {
 110.577 +                tcpSocket->IsConnecting = false;
 110.578 +                eventHandler->TCP_OnClosed(tcpSocket);
 110.579 +            }
 110.580 +        }
 110.581 +        else
 110.582 +        {
 110.583 +            struct sockaddr_storage sockAddr;
 110.584 +            socklen_t sockAddrSize = sizeof(sockAddr);
 110.585 +
 110.586 +            SocketHandle newSock = accept(handle, (sockaddr*)&sockAddr, (socklen_t*)&sockAddrSize);
 110.587 +            if (newSock > 0)
 110.588 +            {
 110.589 +                SockAddr sa(&sockAddr);
 110.590 +                eventHandler->TCP_OnAccept(tcpSocket, &sa, newSock);
 110.591 +            }
 110.592 +        }
 110.593 +    }
 110.594 +
 110.595 +    if (FD_ISSET(handle, &exceptionFD))
 110.596 +    {
 110.597 +        tcpSocket->IsConnecting = false;
 110.598 +        eventHandler->TCP_OnClosed(tcpSocket);
 110.599 +    }
 110.600 +}
 110.601 +
 110.602 +
 110.603 +}} // namespace OVR::Net
   111.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   111.2 +++ b/LibOVR/Src/Net/OVR_Unix_Socket.h	Wed Jan 14 06:51:16 2015 +0200
   111.3 @@ -0,0 +1,152 @@
   111.4 +/************************************************************************************
   111.5 +
   111.6 +PublicHeader:   n/a
   111.7 +Filename    :   OVR_Unix_Socket.h
   111.8 +Content     :   Berkley sockets networking implementation
   111.9 +Created     :   July 1, 2014
  111.10 +Authors     :   Kevin Jenkins
  111.11 +
  111.12 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
  111.13 +
  111.14 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
  111.15 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
  111.16 +which is provided at the time of installation or download, or which 
  111.17 +otherwise accompanies this software in either electronic or hard copy form.
  111.18 +
  111.19 +You may obtain a copy of the License at
  111.20 +
  111.21 +http://www.oculusvr.com/licenses/LICENSE-3.2 
  111.22 +
  111.23 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
  111.24 +distributed under the License is distributed on an "AS IS" BASIS,
  111.25 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  111.26 +See the License for the specific language governing permissions and
  111.27 +limitations under the License.
  111.28 +
  111.29 +************************************************************************************/
  111.30 +
  111.31 +#ifndef OVR_Unix_Socket_h
  111.32 +#define OVR_Unix_Socket_h
  111.33 +
  111.34 +#include "OVR_Socket.h"
  111.35 +#include "OVR_BitStream.h"
  111.36 +
  111.37 +#include <sys/types.h>
  111.38 +#include <sys/socket.h>
  111.39 +#include <netinet/in.h>
  111.40 +#include <arpa/inet.h>
  111.41 +#include <netdb.h>
  111.42 +#include <fcntl.h>
  111.43 +
  111.44 +namespace OVR { namespace Net { 
  111.45 +
  111.46 +//-----------------------------------------------------------------------------
  111.47 +// SockAddr
  111.48 +
  111.49 +// Abstraction for IPV6 socket address, with various convenience functions
  111.50 +class SockAddr
  111.51 +{
  111.52 +public:
  111.53 +	SockAddr();
  111.54 +	SockAddr(SockAddr* sa);
  111.55 +	SockAddr(sockaddr_storage* sa);
  111.56 +	SockAddr(sockaddr_in6* sa);
  111.57 +	SockAddr(const char* hostAddress, UInt16 port, int sockType);
  111.58 +
  111.59 +public:
  111.60 +	void   Set(const sockaddr_storage* sa);
  111.61 +	void   Set(const sockaddr_in6* sa);
  111.62 +	void   Set(const char* hostAddress, UInt16 port, int sockType); // SOCK_DGRAM or SOCK_STREAM
  111.63 +
  111.64 +	UInt16 GetPort();
  111.65 +
  111.66 +    String ToString(bool writePort, char portDelineator) const;
  111.67 +
  111.68 +    bool   IsLocalhost() const;
  111.69 +
  111.70 +	void   Serialize(BitStream* bs);
  111.71 +	bool   Deserialize(BitStream);
  111.72 +
  111.73 +	bool   operator==( const SockAddr& right ) const;
  111.74 +	bool   operator!=( const SockAddr& right ) const;
  111.75 +	bool   operator >( const SockAddr& right ) const;
  111.76 +	bool   operator <( const SockAddr& right ) const;
  111.77 +
  111.78 +public:
  111.79 +	sockaddr_in6 Addr6;
  111.80 +};
  111.81 +
  111.82 +
  111.83 +//-----------------------------------------------------------------------------
  111.84 +// UDP Socket
  111.85 +
  111.86 +// Windows version of TCP socket
  111.87 +class UDPSocket : public UDPSocketBase
  111.88 +{
  111.89 +public:
  111.90 +	UDPSocket();
  111.91 +	virtual ~UDPSocket();
  111.92 +
  111.93 +public:
  111.94 +	virtual SocketHandle Bind(BerkleyBindParameters* pBindParameters);
  111.95 +	virtual int          Send(const void* pData, int bytes, SockAddr* address);
  111.96 +	virtual void         Poll(SocketEvent_UDP* eventHandler);
  111.97 +
  111.98 +protected:
  111.99 +	static const int RecvBufSize = 1048576;
 111.100 +	UByte* RecvBuf;
 111.101 +
 111.102 +	virtual void         OnRecv(SocketEvent_UDP* eventHandler, UByte* pData,
 111.103 +								int bytesRead, SockAddr* address);
 111.104 +};
 111.105 +
 111.106 +
 111.107 +//-----------------------------------------------------------------------------
 111.108 +// TCP Socket
 111.109 +
 111.110 +// Windows version of TCP socket
 111.111 +class TCPSocket : public TCPSocketBase
 111.112 +{
 111.113 +    friend class TCPSocketPollState;
 111.114 +
 111.115 +public:
 111.116 +	TCPSocket();
 111.117 +	TCPSocket(SocketHandle boundHandle, bool isListenSocket);
 111.118 +	virtual ~TCPSocket();
 111.119 +
 111.120 +public:
 111.121 +	virtual SocketHandle Bind(BerkleyBindParameters* pBindParameters);
 111.122 +	virtual int          Listen();
 111.123 +	virtual int          Connect(SockAddr* address);
 111.124 +	virtual int          Send(const void* pData, int bytes);
 111.125 +
 111.126 +protected:
 111.127 +	virtual void         OnRecv(SocketEvent_TCP* eventHandler, UByte* pData,
 111.128 +								int bytesRead);
 111.129 +
 111.130 +public:
 111.131 +	bool IsConnecting; // Is in the process of connecting?
 111.132 +};
 111.133 +
 111.134 +
 111.135 +//-----------------------------------------------------------------------------
 111.136 +// TCPSocketPollState
 111.137 +
 111.138 +// Polls multiple blocking TCP sockets at once
 111.139 +class TCPSocketPollState
 111.140 +{
 111.141 +    fd_set readFD, exceptionFD, writeFD;
 111.142 +    SocketHandle largestDescriptor;
 111.143 +
 111.144 +public:
 111.145 +    TCPSocketPollState();
 111.146 +    bool IsValid() const;
 111.147 +    void Add(TCPSocket* tcpSocket);
 111.148 +    bool Poll(long usec = 30000, long seconds = 0);
 111.149 +    void HandleEvent(TCPSocket* tcpSocket, SocketEvent_TCP* eventHandler);
 111.150 +};
 111.151 +
 111.152 +
 111.153 +}} // OVR::Net
 111.154 +
 111.155 +#endif
   112.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   112.2 +++ b/LibOVR/Src/OVR_CAPI.cpp	Wed Jan 14 06:51:16 2015 +0200
   112.3 @@ -0,0 +1,1289 @@
   112.4 +/************************************************************************************
   112.5 +
   112.6 +Filename    :   OVR_CAPI.cpp
   112.7 +Content     :   Experimental simple C interface to the HMD - version 1.
   112.8 +Created     :   November 30, 2013
   112.9 +Authors     :   Michael Antonov
  112.10 +
  112.11 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
  112.12 +
  112.13 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
  112.14 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
  112.15 +which is provided at the time of installation or download, or which 
  112.16 +otherwise accompanies this software in either electronic or hard copy form.
  112.17 +
  112.18 +You may obtain a copy of the License at
  112.19 +
  112.20 +http://www.oculusvr.com/licenses/LICENSE-3.2 
  112.21 +
  112.22 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
  112.23 +distributed under the License is distributed on an "AS IS" BASIS,
  112.24 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  112.25 +See the License for the specific language governing permissions and
  112.26 +limitations under the License.
  112.27 +
  112.28 +************************************************************************************/
  112.29 +
  112.30 +#include "OVR_CAPI.h"
  112.31 +#include "Kernel/OVR_Timer.h"
  112.32 +#include "Kernel/OVR_Math.h"
  112.33 +#include "Kernel/OVR_System.h"
  112.34 +#include "OVR_Stereo.h"
  112.35 +#include "OVR_Profile.h"
  112.36 +#include "../Include/OVR_Version.h"
  112.37 +
  112.38 +#include "CAPI/CAPI_HMDState.h"
  112.39 +#include "CAPI/CAPI_FrameTimeManager.h"
  112.40 +
  112.41 +#include "Service/Service_NetClient.h"
  112.42 +#ifdef OVR_SINGLE_PROCESS
  112.43 +#include "Service/Service_NetServer.h"
  112.44 +#endif
  112.45 +
  112.46 +#ifdef OVR_OS_WIN32
  112.47 +#include "Displays/OVR_Win32_ShimFunctions.h"
  112.48 +#endif
  112.49 +
  112.50 +
  112.51 +using namespace OVR;
  112.52 +using namespace OVR::Util::Render;
  112.53 +using namespace OVR::Tracking;
  112.54 +
  112.55 +//-------------------------------------------------------------------------------------
  112.56 +// Math
  112.57 +namespace OVR {
  112.58 +
  112.59 +
  112.60 +// ***** FovPort
  112.61 +
  112.62 +// C-interop support: FovPort <-> ovrFovPort
  112.63 +FovPort::FovPort(const ovrFovPort &src)
  112.64 +    : UpTan(src.UpTan), DownTan(src.DownTan), LeftTan(src.LeftTan), RightTan(src.RightTan)
  112.65 +{ }    
  112.66 +
  112.67 +FovPort::operator ovrFovPort () const
  112.68 +{
  112.69 +    ovrFovPort result;
  112.70 +    result.LeftTan  = LeftTan;
  112.71 +    result.RightTan = RightTan;
  112.72 +    result.UpTan    = UpTan;
  112.73 +    result.DownTan  = DownTan;
  112.74 +    return result;
  112.75 +}
  112.76 +
  112.77 +// Converts Fov Tan angle units to [-1,1] render target NDC space
  112.78 +Vector2f FovPort::TanAngleToRendertargetNDC(Vector2f const &tanEyeAngle)
  112.79 +{  
  112.80 +    ScaleAndOffset2D eyeToSourceNDC = CreateNDCScaleAndOffsetFromFov(*this);
  112.81 +    return tanEyeAngle * eyeToSourceNDC.Scale + eyeToSourceNDC.Offset;
  112.82 +}
  112.83 +
  112.84 +// ***** SensorDataType
  112.85 +
  112.86 +SensorDataType::SensorDataType(const ovrSensorData& s)
  112.87 +{
  112.88 +    Acceleration = s.Accelerometer;
  112.89 +    RotationRate = s.Gyro;
  112.90 +    MagneticField = s.Magnetometer;
  112.91 +    Temperature = s.Temperature;
  112.92 +    AbsoluteTimeSeconds = s.TimeInSeconds;
  112.93 +}
  112.94 +
  112.95 +SensorDataType::operator ovrSensorData () const
  112.96 +{
  112.97 +    ovrSensorData result;
  112.98 +    result.Accelerometer = Acceleration;
  112.99 +    result.Gyro = RotationRate;
 112.100 +    result.Magnetometer = MagneticField;
 112.101 +    result.Temperature = Temperature;
 112.102 +    result.TimeInSeconds = (float) AbsoluteTimeSeconds;
 112.103 +    return result;
 112.104 +}
 112.105 +
 112.106 +
 112.107 +// ***** SensorState
 112.108 +
 112.109 +TrackingState::TrackingState(const ovrTrackingState& s)
 112.110 +{
 112.111 +    HeadPose    = s.HeadPose;
 112.112 +    CameraPose  = s.CameraPose;
 112.113 +    LeveledCameraPose = s.LeveledCameraPose;
 112.114 +    RawSensorData = s.RawSensorData;
 112.115 +    StatusFlags = s.StatusFlags;
 112.116 +    LastVisionProcessingTime = s.LastVisionProcessingTime;
 112.117 +    LastVisionFrameLatency = s.LastVisionFrameLatency;
 112.118 +    LastCameraFrameCounter = s.LastCameraFrameCounter;
 112.119 +}
 112.120 +
 112.121 +TrackingState::operator ovrTrackingState() const
 112.122 +{
 112.123 +    ovrTrackingState result;
 112.124 +    result.HeadPose     = HeadPose;
 112.125 +    result.CameraPose   = CameraPose;
 112.126 +    result.LeveledCameraPose = LeveledCameraPose;
 112.127 +    result.RawSensorData  = RawSensorData;
 112.128 +    result.StatusFlags  = StatusFlags;
 112.129 +    result.LastVisionProcessingTime = LastVisionProcessingTime;
 112.130 +    result.LastVisionFrameLatency = LastVisionFrameLatency;
 112.131 +    result.LastCameraFrameCounter = LastCameraFrameCounter;
 112.132 +    return result;
 112.133 +}
 112.134 +
 112.135 +
 112.136 +} // namespace OVR
 112.137 +
 112.138 +//-------------------------------------------------------------------------------------
 112.139 +
 112.140 +using namespace OVR::CAPI;
 112.141 +
 112.142 +#ifdef __cplusplus 
 112.143 +extern "C" {
 112.144 +#endif
 112.145 +
 112.146 +
 112.147 +// Used to generate projection from ovrEyeDesc::Fov
 112.148 +OVR_EXPORT ovrMatrix4f ovrMatrix4f_Projection(ovrFovPort fov, float znear, float zfar, ovrBool rightHanded)
 112.149 +{
 112.150 +    return CreateProjection(rightHanded ? true : false, fov, znear, zfar);
 112.151 +}
 112.152 +
 112.153 +
 112.154 +OVR_EXPORT ovrMatrix4f ovrMatrix4f_OrthoSubProjection(ovrMatrix4f projection, ovrVector2f orthoScale,
 112.155 +                                                      float orthoDistance, float hmdToEyeViewOffsetX)
 112.156 +{
 112.157 +
 112.158 +    float orthoHorizontalOffset = hmdToEyeViewOffsetX / orthoDistance;
 112.159 +
 112.160 +    // Current projection maps real-world vector (x,y,1) to the RT.
 112.161 +    // We want to find the projection that maps the range [-FovPixels/2,FovPixels/2] to
 112.162 +    // the physical [-orthoHalfFov,orthoHalfFov]
 112.163 +    // Note moving the offset from M[0][2]+M[1][2] to M[0][3]+M[1][3] - this means
 112.164 +    // we don't have to feed in Z=1 all the time.
 112.165 +    // The horizontal offset math is a little hinky because the destination is
 112.166 +    // actually [-orthoHalfFov+orthoHorizontalOffset,orthoHalfFov+orthoHorizontalOffset]
 112.167 +    // So we need to first map [-FovPixels/2,FovPixels/2] to
 112.168 +    //                         [-orthoHalfFov+orthoHorizontalOffset,orthoHalfFov+orthoHorizontalOffset]:
 112.169 +    // x1 = x0 * orthoHalfFov/(FovPixels/2) + orthoHorizontalOffset;
 112.170 +    //    = x0 * 2*orthoHalfFov/FovPixels + orthoHorizontalOffset;
 112.171 +    // But then we need the same mapping as the existing projection matrix, i.e.
 112.172 +    // x2 = x1 * Projection.M[0][0] + Projection.M[0][2];
 112.173 +    //    = x0 * (2*orthoHalfFov/FovPixels + orthoHorizontalOffset) * Projection.M[0][0] + Projection.M[0][2];
 112.174 +    //    = x0 * Projection.M[0][0]*2*orthoHalfFov/FovPixels +
 112.175 +    //      orthoHorizontalOffset*Projection.M[0][0] + Projection.M[0][2];
 112.176 +    // So in the new projection matrix we need to scale by Projection.M[0][0]*2*orthoHalfFov/FovPixels and
 112.177 +    // offset by orthoHorizontalOffset*Projection.M[0][0] + Projection.M[0][2].
 112.178 +
 112.179 +    Matrix4f ortho;
 112.180 +    ortho.M[0][0] = projection.M[0][0] * orthoScale.x;
 112.181 +    ortho.M[0][1] = 0.0f;
 112.182 +    ortho.M[0][2] = 0.0f;
 112.183 +    ortho.M[0][3] = -projection.M[0][2] + ( orthoHorizontalOffset * projection.M[0][0] );
 112.184 +
 112.185 +    ortho.M[1][0] = 0.0f;
 112.186 +    ortho.M[1][1] = -projection.M[1][1] * orthoScale.y;       // Note sign flip (text rendering uses Y=down).
 112.187 +    ortho.M[1][2] = 0.0f;
 112.188 +    ortho.M[1][3] = -projection.M[1][2];
 112.189 +
 112.190 +    /*
 112.191 +    if ( fabsf ( zNear - zFar ) < 0.001f )
 112.192 +    {
 112.193 +        ortho.M[2][0] = 0.0f;
 112.194 +        ortho.M[2][1] = 0.0f;
 112.195 +        ortho.M[2][2] = 0.0f;
 112.196 +        ortho.M[2][3] = zFar;
 112.197 +    }
 112.198 +    else
 112.199 +    {
 112.200 +        ortho.M[2][0] = 0.0f;
 112.201 +        ortho.M[2][1] = 0.0f;
 112.202 +        ortho.M[2][2] = zFar / (zNear - zFar);
 112.203 +        ortho.M[2][3] = (zFar * zNear) / (zNear - zFar);
 112.204 +    }
 112.205 +    */
 112.206 +
 112.207 +    // MA: Undo effect of sign
 112.208 +    ortho.M[2][0] = 0.0f;
 112.209 +    ortho.M[2][1] = 0.0f;
 112.210 +    //ortho.M[2][2] = projection.M[2][2] * projection.M[3][2] * -1.0f; // reverse right-handedness
 112.211 +    ortho.M[2][2] = 0.0f;
 112.212 +    ortho.M[2][3] = 0.0f;
 112.213 +        //projection.M[2][3];
 112.214 +
 112.215 +    // No perspective correction for ortho.
 112.216 +    ortho.M[3][0] = 0.0f;
 112.217 +    ortho.M[3][1] = 0.0f;
 112.218 +    ortho.M[3][2] = 0.0f;
 112.219 +    ortho.M[3][3] = 1.0f;
 112.220 +
 112.221 +    return ortho;
 112.222 +}
 112.223 +
 112.224 +
 112.225 +OVR_EXPORT double ovr_GetTimeInSeconds()
 112.226 +{
 112.227 +    return Timer::GetSeconds();
 112.228 +}
 112.229 +
 112.230 +// Waits until the specified absolute time.
 112.231 +OVR_EXPORT double ovr_WaitTillTime(double absTime)
 112.232 +{
 112.233 +    double       initialTime = ovr_GetTimeInSeconds();
 112.234 +    double       newTime     = initialTime;
 112.235 +    
 112.236 +    while(newTime < absTime)
 112.237 +    {
 112.238 +        for (int j = 0; j < 5; j++)
 112.239 +            OVR_PROCESSOR_PAUSE();
 112.240 +
 112.241 +        newTime = ovr_GetTimeInSeconds();
 112.242 +    }
 112.243 +
 112.244 +    // How long we waited
 112.245 +    return newTime - initialTime;
 112.246 +}
 112.247 +
 112.248 +
 112.249 +//-------------------------------------------------------------------------------------
 112.250 +
 112.251 +// 1. Init/shutdown.
 112.252 +
 112.253 +static ovrBool CAPI_SystemInitCalled = 0;
 112.254 +static ovrBool CAPI_ovrInitializeCalled = 0;
 112.255 +
 112.256 +static OVR::Service::NetClient* CAPI_pNetClient = 0;
 112.257 +
 112.258 +OVR_EXPORT ovrBool ovr_InitializeRenderingShim()
 112.259 +{
 112.260 +    OVR::System::DirectDisplayInitialize();
 112.261 +    return OVR::System::DirectDisplayEnabled();
 112.262 +}
 112.263 +
 112.264 +OVR_EXPORT ovrBool ovr_Initialize()
 112.265 +{
 112.266 +    if (CAPI_ovrInitializeCalled)
 112.267 +        return 1;
 112.268 +
 112.269 +    // We must set up the system for the plugin to work
 112.270 +    if (!OVR::System::IsInitialized())
 112.271 +    {
 112.272 +        OVR::System::Init(OVR::Log::ConfigureDefaultLog(OVR::LogMask_All));
 112.273 +        CAPI_SystemInitCalled = 1;
 112.274 +    }
 112.275 +
 112.276 +    if (!OVR::System::DirectDisplayEnabled() && !OVR::Display::InCompatibilityMode(false))
 112.277 +    {
 112.278 +        OVR_ASSERT(false);
 112.279 +        return 0;
 112.280 +    }
 112.281 +
 112.282 +    CAPI_pNetClient = NetClient::GetInstance();
 112.283 +
 112.284 +#ifdef OVR_SINGLE_PROCESS
 112.285 +
 112.286 +    // If the server could not start running,
 112.287 +    if (Service::NetServer::GetInstance()->IsInitialized())
 112.288 +    {
 112.289 +        CAPI_pNetClient->Connect(true);
 112.290 +    }
 112.291 +    else
 112.292 +    {
 112.293 +        // This normally will happen if the OVRService is running in the background,
 112.294 +        // or another SingleProcess-mode app is running in the background.
 112.295 +        // In this case, it's using the hardware and we should not also attempt to use
 112.296 +        // the hardware.
 112.297 +        LogError("{ERR-079} [LibOVR] Server is already running");
 112.298 +    }
 112.299 +#else
 112.300 +    CAPI_pNetClient->Connect(true);
 112.301 +#endif
 112.302 +
 112.303 +    CAPI_ovrInitializeCalled = 1;
 112.304 +
 112.305 +    return 1;
 112.306 +}
 112.307 +
 112.308 +OVR_EXPORT void ovr_Shutdown()
 112.309 +{  
 112.310 +    // We should clean up the system to be complete
 112.311 +    if (OVR::System::IsInitialized() && CAPI_SystemInitCalled)
 112.312 +    {
 112.313 +        OVR::System::Destroy();
 112.314 +    }
 112.315 +
 112.316 +    CAPI_SystemInitCalled = 0;
 112.317 +    CAPI_ovrInitializeCalled = 0;
 112.318 +}
 112.319 +
 112.320 +
 112.321 +// There is a thread safety issue with ovrHmd_Detect in that multiple calls from different
 112.322 +// threads can corrupt the global array state. This would lead to two problems:
 112.323 +//  a) Create(index) enumerator may miss or overshoot items. Probably not a big deal
 112.324 +//     as game logic can easily be written to only do Detect(s)/Creates in one place.
 112.325 +//     The alternative would be to return list handle.
 112.326 +//  b) TBD: Un-mutexed Detect access from two threads could lead to crash. We should
 112.327 +//         probably check this.
 112.328 +//
 112.329 +
 112.330 +OVR_EXPORT int ovrHmd_Detect()
 112.331 +{
 112.332 +    if (!CAPI_ovrInitializeCalled)
 112.333 +        return 0;
 112.334 +
 112.335 +    return CAPI_pNetClient->Hmd_Detect();
 112.336 +}
 112.337 +
 112.338 +
 112.339 +// ovrHmd_Create us explicitly separated from ConfigureTracking and ConfigureRendering to allow creation of 
 112.340 +// a relatively light-weight handle that would reference the device going forward and would 
 112.341 +// survive future ovrHmd_Detect calls. That is once ovrHMD is returned, index is no longer
 112.342 +// necessary and can be changed by a ovrHmd_Detect call.
 112.343 +OVR_EXPORT ovrHmd ovrHmd_Create(int index)
 112.344 +{
 112.345 +    if (!CAPI_ovrInitializeCalled)
 112.346 +        return 0;
 112.347 +
 112.348 +    double t0 = Timer::GetSeconds();
 112.349 +    HMDNetworkInfo netInfo;
 112.350 +
 112.351 +    // There may be some delay before the HMD is fully detected.
 112.352 +    // Since we are also trying to create the HMD immediately it may lose this race and
 112.353 +    // get "NO HMD DETECTED."  Wait a bit longer to avoid this.
 112.354 +    while (!CAPI_pNetClient->Hmd_Create(index, &netInfo) ||
 112.355 +           netInfo.NetId == InvalidVirtualHmdId)
 112.356 +    {
 112.357 +        // If two seconds elapse and still no HMD detected,
 112.358 +        if (Timer::GetSeconds() - t0 > 2.)
 112.359 +        {
 112.360 +            if (!NetClient::GetInstance()->IsConnected(false, false))
 112.361 +            {
 112.362 +                NetClient::GetInstance()->SetLastError("Not connected to service");
 112.363 +            }
 112.364 +            else
 112.365 +            {
 112.366 +                NetClient::GetInstance()->SetLastError("No HMD Detected");
 112.367 +            }
 112.368 +
 112.369 +            return 0;
 112.370 +        }
 112.371 +    }
 112.372 +
 112.373 +    // Create HMD State object
 112.374 +    HMDState* hmds = HMDState::CreateHMDState(CAPI_pNetClient, netInfo);
 112.375 +    if (!hmds)
 112.376 +    {
 112.377 +        CAPI_pNetClient->Hmd_Release(netInfo.NetId);
 112.378 +
 112.379 +        NetClient::GetInstance()->SetLastError("Unable to create HMD state");
 112.380 +        return 0;
 112.381 +    }
 112.382 +
 112.383 +    // Reset frame timing so that FrameTimeManager values are properly initialized in AppRendered mode.
 112.384 +    ovrHmd_ResetFrameTiming(hmds->pHmdDesc, 0);
 112.385 +
 112.386 +    return hmds->pHmdDesc;
 112.387 +}
 112.388 +
 112.389 +
 112.390 +OVR_EXPORT ovrBool ovrHmd_AttachToWindow( ovrHmd hmd, void* window,
 112.391 +                                         const ovrRecti* destMirrorRect,
 112.392 +                                         const ovrRecti* sourceRenderTargetRect )
 112.393 +{
 112.394 +    OVR_UNUSED( destMirrorRect );
 112.395 +    OVR_UNUSED( sourceRenderTargetRect );
 112.396 +
 112.397 +    if (!CAPI_ovrInitializeCalled)
 112.398 +        return false;
 112.399 +
 112.400 +    if (!hmd || !hmd->Handle)
 112.401 +        return false;
 112.402 +#ifndef OVR_OS_MAC
 112.403 +    HMDState* hmds = (HMDState*)hmd->Handle;
 112.404 +    CAPI_pNetClient->Hmd_AttachToWindow(hmds->GetNetId(), window);
 112.405 +    hmds->pWindow = window;
 112.406 +#endif
 112.407 +#ifdef OVR_OS_WIN32
 112.408 +    Win32::DisplayShim::GetInstance().hWindow = (HWND)window;
 112.409 +#endif
 112.410 +#ifdef OVR_OS_MAC
 112.411 +    OVR_UNUSED(window);
 112.412 +#endif
 112.413 +
 112.414 +    return true;
 112.415 +}
 112.416 +
 112.417 +OVR_EXPORT ovrHmd ovrHmd_CreateDebug(ovrHmdType type)
 112.418 +{
 112.419 +    if (!CAPI_ovrInitializeCalled)
 112.420 +        return 0;
 112.421 +
 112.422 +    HMDState* hmds = HMDState::CreateHMDState(type);
 112.423 +
 112.424 +    return hmds->pHmdDesc;
 112.425 +}
 112.426 +
 112.427 +OVR_EXPORT void ovrHmd_Destroy(ovrHmd hmddesc)
 112.428 +{
 112.429 +    if (!hmddesc || !hmddesc->Handle)
 112.430 +        return;
 112.431 +    
 112.432 +    // TBD: Any extra shutdown?
 112.433 +    HMDState* hmds = (HMDState*)hmddesc->Handle;
 112.434 +        
 112.435 +    {   // Thread checker in its own scope, to avoid access after 'delete'.
 112.436 +        // Essentially just checks that no other RenderAPI function is executing.
 112.437 +        ThreadChecker::Scope checkScope(&hmds->RenderAPIThreadChecker, "ovrHmd_Destroy");
 112.438 +    }    
 112.439 +
 112.440 +#ifdef OVR_OS_WIN32
 112.441 +    if (hmds->pWindow)
 112.442 +    {
 112.443 +        // ? ok to call
 112.444 +        //CAPI_pNetClient->Hmd_AttachToWindow(hmds->GetNetId(), 0);
 112.445 +        hmds->pWindow = 0;
 112.446 +        Win32::DisplayShim::GetInstance().hWindow = (HWND)0;
 112.447 +    }    
 112.448 +#endif
 112.449 +
 112.450 +    delete (HMDState*)hmddesc->Handle;
 112.451 +}
 112.452 +
 112.453 +
 112.454 +OVR_EXPORT const char* ovrHmd_GetLastError(ovrHmd hmddesc)
 112.455 +{
 112.456 +    if (!CAPI_ovrInitializeCalled)
 112.457 +    {
 112.458 +        return "System initialize not called";
 112.459 +    }
 112.460 +
 112.461 +    VirtualHmdId netId = InvalidVirtualHmdId;
 112.462 +
 112.463 +    if (hmddesc && hmddesc->Handle)
 112.464 +    {
 112.465 +        HMDState* p = (HMDState*)hmddesc->Handle;
 112.466 +        netId = p->GetNetId();
 112.467 +    }
 112.468 +
 112.469 +    return CAPI_pNetClient->Hmd_GetLastError(netId);
 112.470 +}
 112.471 +
 112.472 +#define OVR_VERSION_LIBOVR_PFX "libOVR:"
 112.473 +
 112.474 +// Returns version string representing libOVR version. Static, so
 112.475 +// string remains valid for app lifespan
 112.476 +OVR_EXPORT const char* ovr_GetVersionString()
 112.477 +{
 112.478 +	static const char* version = OVR_VERSION_LIBOVR_PFX OVR_VERSION_STRING;
 112.479 +    return version + sizeof(OVR_VERSION_LIBOVR_PFX) - 1;
 112.480 +}
 112.481 +
 112.482 +
 112.483 +
 112.484 +//-------------------------------------------------------------------------------------
 112.485 +
 112.486 +// Returns capability bits that are enabled at this time; described by ovrHmdCapBits.
 112.487 +// Note that this value is different font ovrHmdDesc::Caps, which describes what
 112.488 +// capabilities are available.
 112.489 +OVR_EXPORT unsigned int ovrHmd_GetEnabledCaps(ovrHmd hmddesc)
 112.490 +{
 112.491 +    HMDState* p = (HMDState*)hmddesc->Handle;
 112.492 +    return p ? p->EnabledHmdCaps : 0;
 112.493 +}
 112.494 +
 112.495 +// Modifies capability bits described by ovrHmdCapBits that can be modified,
 112.496 +// such as ovrHmdCap_LowPersistance.
 112.497 +OVR_EXPORT void ovrHmd_SetEnabledCaps(ovrHmd hmddesc, unsigned int capsBits)
 112.498 +{
 112.499 +    HMDState* p = (HMDState*)hmddesc->Handle;
 112.500 +    if (p)
 112.501 +    {
 112.502 +        p->SetEnabledHmdCaps(capsBits);
 112.503 +    }
 112.504 +}
 112.505 +
 112.506 +
 112.507 +//-------------------------------------------------------------------------------------
 112.508 +// *** Sensor
 112.509 +
 112.510 +// Sensor APIs are separated from Create & Configure for several reasons:
 112.511 +//  - They need custom parameters that control allocation of heavy resources
 112.512 +//    such as Vision tracking, which you don't want to create unless necessary.
 112.513 +//  - A game may want to switch some sensor settings based on user input, 
 112.514 +//    or at lease enable/disable features such as Vision for debugging.
 112.515 +//  - The same or syntactically similar sensor interface is likely to be used if we 
 112.516 +//    introduce controllers.
 112.517 +//
 112.518 +//  - Sensor interface functions are all Thread-safe, unlike the frame/render API
 112.519 +//    functions that have different rules (all frame access functions
 112.520 +//    must be on render thread)
 112.521 +
 112.522 +OVR_EXPORT ovrBool ovrHmd_ConfigureTracking(ovrHmd hmddesc, unsigned int supportedCaps,
 112.523 +                                                            unsigned int requiredCaps)
 112.524 +{
 112.525 +    if (hmddesc)
 112.526 +    {
 112.527 +        HMDState* p = (HMDState*)hmddesc->Handle;
 112.528 +        return p->ConfigureTracking(supportedCaps, requiredCaps);
 112.529 +    }
 112.530 +
 112.531 +    return 0;
 112.532 +}
 112.533 +
 112.534 +OVR_EXPORT void ovrHmd_RecenterPose(ovrHmd hmddesc)
 112.535 +{
 112.536 +    if (hmddesc)
 112.537 +    {
 112.538 +        HMDState* p = (HMDState*)hmddesc->Handle;
 112.539 +        p->TheSensorStateReader.RecenterPose();
 112.540 +    }
 112.541 +}
 112.542 +
 112.543 +OVR_EXPORT ovrTrackingState ovrHmd_GetTrackingState(ovrHmd hmddesc, double absTime)
 112.544 +{
 112.545 +    ovrTrackingState result;
 112.546 +
 112.547 +    if (hmddesc)
 112.548 +    {
 112.549 +        HMDState* p = (HMDState*)hmddesc->Handle;
 112.550 +        result = p->PredictedTrackingState(absTime);
 112.551 +
 112.552 +        // Instrument data from eye pose
 112.553 +        p->LagStats.InstrumentEyePose(result);
 112.554 +    }
 112.555 +    else
 112.556 +        memset(&result, 0, sizeof(result));
 112.557 +
 112.558 +#ifdef OVR_OS_WIN32
 112.559 +        // Set up display code for Windows
 112.560 +        Win32::DisplayShim::GetInstance().Active = (result.StatusFlags & ovrStatus_HmdConnected) != 0;
 112.561 +#endif
 112.562 +
 112.563 +    return result;
 112.564 +}
 112.565 +
 112.566 +
 112.567 +//-------------------------------------------------------------------------------------
 112.568 +// *** General Setup
 112.569 +
 112.570 +// Per HMD -> calculateIdealPixelSize
 112.571 +OVR_EXPORT ovrSizei ovrHmd_GetFovTextureSize(ovrHmd hmddesc, ovrEyeType eye, ovrFovPort fov,
 112.572 +                                             float pixelsPerDisplayPixel)
 112.573 +{
 112.574 +    ovrHmdStruct *  hmd = hmddesc->Handle;
 112.575 +    if (!hmd) return Sizei(0);
 112.576 +    
 112.577 +    HMDState* hmds = (HMDState*)hmd;
 112.578 +    return hmds->RenderState.GetFOVTextureSize(eye, fov, pixelsPerDisplayPixel);
 112.579 +}
 112.580 +
 112.581 +
 112.582 +//-------------------------------------------------------------------------------------
 112.583 +
 112.584 +
 112.585 +OVR_EXPORT 
 112.586 +ovrBool ovrHmd_ConfigureRendering( ovrHmd hmddesc,
 112.587 +                                   const ovrRenderAPIConfig* apiConfig,
 112.588 +                                   unsigned int distortionCaps,
 112.589 +                                   const ovrFovPort eyeFovIn[2],
 112.590 +                                   ovrEyeRenderDesc eyeRenderDescOut[2] )
 112.591 +{
 112.592 +    ovrHmdStruct *  hmd = hmddesc->Handle;
 112.593 +    if (!hmd) return 0;
 112.594 +    return ((HMDState*)hmd)->ConfigureRendering(eyeRenderDescOut, eyeFovIn,
 112.595 +                                                apiConfig, distortionCaps);
 112.596 +}
 112.597 +
 112.598 +
 112.599 +
 112.600 +// TBD: MA - Deprecated, need alternative
 112.601 +void ovrHmd_SetVsync(ovrHmd hmddesc, ovrBool vsync)
 112.602 +{
 112.603 +    ovrHmdStruct *  hmd = hmddesc->Handle;
 112.604 +    if (!hmd) return;
 112.605 +
 112.606 +    return ((HMDState*)hmd)->TimeManager.SetVsync(vsync? true : false);
 112.607 +}
 112.608 +
 112.609 +
 112.610 +OVR_EXPORT ovrFrameTiming ovrHmd_BeginFrame(ovrHmd hmddesc, unsigned int frameIndex)
 112.611 +{           
 112.612 +    HMDState* hmds = (HMDState*)hmddesc->Handle;
 112.613 +    if (!hmds)
 112.614 +    {
 112.615 +        ovrFrameTiming f;
 112.616 +        memset(&f, 0, sizeof(f));
 112.617 +        return f;
 112.618 +    }
 112.619 +
 112.620 +    // Check: Proper configure and threading state for the call.
 112.621 +    hmds->checkRenderingConfigured("ovrHmd_BeginFrame");
 112.622 +	OVR_DEBUG_LOG_COND(hmds->BeginFrameCalled, ("ovrHmd_BeginFrame called multiple times."));
 112.623 +    ThreadChecker::Scope checkScope(&hmds->RenderAPIThreadChecker, "ovrHmd_BeginFrame");
 112.624 +    
 112.625 +    hmds->BeginFrameCalled   = true;
 112.626 +    hmds->BeginFrameThreadId = OVR::GetCurrentThreadId();
 112.627 +
 112.628 +    return ovrHmd_BeginFrameTiming(hmddesc, frameIndex);
 112.629 +}
 112.630 +
 112.631 +
 112.632 +// Renders textures to frame buffer
 112.633 +OVR_EXPORT void ovrHmd_EndFrame(ovrHmd hmddesc,
 112.634 +                                const ovrPosef renderPose[2],
 112.635 +                                const ovrTexture eyeTexture[2])
 112.636 +{
 112.637 +    HMDState* hmds = (HMDState*)hmddesc->Handle;
 112.638 +    if (!hmds) return;
 112.639 +
 112.640 +    // Instrument when the EndFrame() call started
 112.641 +    hmds->LagStats.InstrumentEndFrameStart(ovr_GetTimeInSeconds());
 112.642 +
 112.643 +    hmds->SubmitEyeTextures(renderPose, eyeTexture);
 112.644 +
 112.645 +    // Debug state checks: Must be in BeginFrame, on the same thread.
 112.646 +    hmds->checkBeginFrameScope("ovrHmd_EndFrame");
 112.647 +    ThreadChecker::Scope checkScope(&hmds->RenderAPIThreadChecker, "ovrHmd_EndFrame");  
 112.648 +    
 112.649 +    hmds->pRenderer->SetLatencyTestColor(hmds->LatencyTestActive ? hmds->LatencyTestDrawColor : NULL);
 112.650 +
 112.651 +    ovrHmd_GetLatencyTest2DrawColor(hmddesc, NULL); // We don't actually need to draw color, so send NULL
 112.652 +    
 112.653 +    if (hmds->pRenderer)
 112.654 +    {
 112.655 +        hmds->pRenderer->SaveGraphicsState();
 112.656 +
 112.657 +        // See if we need to show the HSWDisplay.
 112.658 +        if (hmds->pHSWDisplay) // Until we know that these are valid, assume any of them can't be.
 112.659 +        {
 112.660 +            ovrHSWDisplayState hswDisplayState;
 112.661 +            hmds->pHSWDisplay->TickState(&hswDisplayState, true);  // This may internally call HASWarning::Display.
 112.662 +
 112.663 +            if (hswDisplayState.Displayed)
 112.664 +            {
 112.665 +                hmds->pHSWDisplay->Render(ovrEye_Left, &eyeTexture[ovrEye_Left]);
 112.666 +                hmds->pHSWDisplay->Render(ovrEye_Right, &eyeTexture[ovrEye_Right]);
 112.667 +            }
 112.668 +        }
 112.669 +
 112.670 +        hmds->pRenderer->EndFrame(true);
 112.671 +        hmds->pRenderer->RestoreGraphicsState();
 112.672 +    }
 112.673 +
 112.674 +    // Call after present
 112.675 +    ovrHmd_EndFrameTiming(hmddesc);
 112.676 +
 112.677 +    // Instrument latency tester
 112.678 +    hmds->LagStats.InstrumentLatencyTimings(hmds->TimeManager);
 112.679 +
 112.680 +    // Instrument when the EndFrame() call ended
 112.681 +    hmds->LagStats.InstrumentEndFrameEnd(ovr_GetTimeInSeconds());
 112.682 +
 112.683 +    // Out of BeginFrame
 112.684 +    hmds->BeginFrameThreadId = 0;
 112.685 +    hmds->BeginFrameCalled   = false;
 112.686 +}
 112.687 +
 112.688 +
 112.689 +// Not exposed as part of public API
 112.690 +OVR_EXPORT void ovrHmd_RegisterPostDistortionCallback(ovrHmd hmddesc, PostDistortionCallback callback)
 112.691 +{
 112.692 +    HMDState* hmds = (HMDState*)hmddesc->Handle;
 112.693 +    if (!hmds) return;
 112.694 +
 112.695 +    if (hmds->pRenderer)
 112.696 +    {
 112.697 +        hmds->pRenderer->RegisterPostDistortionCallback(callback);
 112.698 +    }
 112.699 +}
 112.700 +
 112.701 +
 112.702 +
 112.703 +//-------------------------------------------------------------------------------------
 112.704 +// ***** Frame Timing logic
 112.705 +
 112.706 +
 112.707 +OVR_EXPORT ovrFrameTiming ovrHmd_GetFrameTiming(ovrHmd hmddesc, unsigned int frameIndex)
 112.708 +{
 112.709 +    ovrHmdStruct *  hmd = hmddesc->Handle;
 112.710 +    ovrFrameTiming f;
 112.711 +    memset(&f, 0, sizeof(f));
 112.712 +
 112.713 +    HMDState* hmds = (HMDState*)hmd;
 112.714 +    if (hmds)
 112.715 +    {
 112.716 +        FrameTimeManager::Timing frameTiming = hmds->TimeManager.GetFrameTiming(frameIndex);
 112.717 +
 112.718 +        f.ThisFrameSeconds       = frameTiming.ThisFrameTime;
 112.719 +        f.NextFrameSeconds       = frameTiming.NextFrameTime;
 112.720 +        f.TimewarpPointSeconds   = frameTiming.TimewarpPointTime;
 112.721 +        f.ScanoutMidpointSeconds = frameTiming.MidpointTime;
 112.722 +        f.EyeScanoutSeconds[0]   = frameTiming.EyeRenderTimes[0];
 112.723 +        f.EyeScanoutSeconds[1]   = frameTiming.EyeRenderTimes[1];
 112.724 +
 112.725 +         // Compute DeltaSeconds.
 112.726 +        f.DeltaSeconds = (hmds->LastGetFrameTimeSeconds == 0.0f) ? 0.0f :
 112.727 +                         (float) (f.ThisFrameSeconds - hmds->LastFrameTimeSeconds);    
 112.728 +        hmds->LastGetFrameTimeSeconds = f.ThisFrameSeconds;
 112.729 +        if (f.DeltaSeconds > 1.0f)
 112.730 +            f.DeltaSeconds = 1.0f;
 112.731 +    }
 112.732 +        
 112.733 +    return f;
 112.734 +}
 112.735 +
 112.736 +OVR_EXPORT ovrFrameTiming ovrHmd_BeginFrameTiming(ovrHmd hmddesc, unsigned int frameIndex)
 112.737 +{
 112.738 +    ovrHmdStruct *  hmd = hmddesc->Handle;
 112.739 +    ovrFrameTiming f;
 112.740 +    memset(&f, 0, sizeof(f));
 112.741 +
 112.742 +    HMDState* hmds = (HMDState*)hmd;
 112.743 +    if (!hmds) return f;
 112.744 +
 112.745 +    // Check: Proper state for the call.    
 112.746 +    OVR_DEBUG_LOG_COND(hmds->BeginFrameTimingCalled,
 112.747 +                      ("ovrHmd_BeginFrameTiming called multiple times."));    
 112.748 +    hmds->BeginFrameTimingCalled = true;
 112.749 +
 112.750 +    double thisFrameTime = hmds->TimeManager.BeginFrame(frameIndex);        
 112.751 +
 112.752 +    const FrameTimeManager::Timing &frameTiming = hmds->TimeManager.GetFrameTiming();
 112.753 +
 112.754 +    f.ThisFrameSeconds      = thisFrameTime;
 112.755 +    f.NextFrameSeconds      = frameTiming.NextFrameTime;
 112.756 +    f.TimewarpPointSeconds  = frameTiming.TimewarpPointTime;
 112.757 +    f.ScanoutMidpointSeconds= frameTiming.MidpointTime;
 112.758 +    f.EyeScanoutSeconds[0]  = frameTiming.EyeRenderTimes[0];
 112.759 +    f.EyeScanoutSeconds[1]  = frameTiming.EyeRenderTimes[1];
 112.760 +
 112.761 +    // Compute DeltaSeconds.
 112.762 +    f.DeltaSeconds = (hmds->LastFrameTimeSeconds == 0.0f) ? 0.0f :
 112.763 +                     (float) (thisFrameTime - hmds->LastFrameTimeSeconds);
 112.764 +    hmds->LastFrameTimeSeconds = thisFrameTime;
 112.765 +    if (f.DeltaSeconds > 1.0f)
 112.766 +        f.DeltaSeconds = 1.0f;
 112.767 +
 112.768 +    return f;
 112.769 +}
 112.770 +
 112.771 +
 112.772 +OVR_EXPORT void ovrHmd_EndFrameTiming(ovrHmd hmddesc)
 112.773 +{
 112.774 +    HMDState* hmds = (HMDState*)hmddesc->Handle;
 112.775 +    if (!hmds) return;
 112.776 +
 112.777 +    // Debug state checks: Must be in BeginFrameTiming, on the same thread.
 112.778 +    hmds->checkBeginFrameTimingScope("ovrHmd_EndTiming");
 112.779 +   // MA TBD: Correct check or not?
 112.780 +   // ThreadChecker::Scope checkScope(&hmds->RenderAPIThreadChecker, "ovrHmd_EndFrame");
 112.781 +
 112.782 +    hmds->TimeManager.EndFrame();   
 112.783 +    hmds->BeginFrameTimingCalled = false;
 112.784 +
 112.785 +    bool dk2LatencyTest = (hmds->EnabledHmdCaps & ovrHmdCap_DynamicPrediction) != 0;
 112.786 +    if (dk2LatencyTest)
 112.787 +    {
 112.788 +        Util::FrameTimeRecordSet recordset;
 112.789 +        hmds->TheLatencyTestStateReader.GetRecordSet(recordset);
 112.790 +        hmds->TimeManager.UpdateFrameLatencyTrackingAfterEndFrame( hmds->LatencyTest2DrawColor,
 112.791 +            recordset);
 112.792 +    }
 112.793 +}
 112.794 +
 112.795 +
 112.796 +OVR_EXPORT void ovrHmd_ResetFrameTiming(ovrHmd hmddesc,  unsigned int frameIndex) 
 112.797 +{
 112.798 +    HMDState* hmds = (HMDState*)hmddesc->Handle;
 112.799 +    if (!hmds) return;
 112.800 +    
 112.801 +    hmds->TimeManager.ResetFrameTiming(frameIndex, 
 112.802 +                                       false,
 112.803 +                                       hmds->RenderingConfigured);
 112.804 +    hmds->LastFrameTimeSeconds    = 0.0;
 112.805 +    hmds->LastGetFrameTimeSeconds = 0.0;
 112.806 +}
 112.807 +
 112.808 +OVR_EXPORT void ovrHmd_GetEyePoses(ovrHmd hmd, unsigned int frameIndex, ovrVector3f hmdToEyeViewOffset[2],
 112.809 +                                   ovrPosef outEyePoses[2], ovrTrackingState* outHmdTrackingState)
 112.810 +{
 112.811 +    HMDState* hmds = (HMDState*)hmd->Handle;
 112.812 +    if (!hmds) return;
 112.813 +
 112.814 +    hmds->LatencyTestActive = hmds->ProcessLatencyTest(hmds->LatencyTestDrawColor);
 112.815 +    
 112.816 +    ovrTrackingState hmdTrackingState = hmds->TimeManager.GetEyePredictionTracking(hmd, ovrEye_Count, frameIndex);
 112.817 +    ovrPosef hmdPose = hmdTrackingState.HeadPose.ThePose;
 112.818 +
 112.819 +    // caller passed in a valid pointer, so copy to output
 112.820 +    if(outHmdTrackingState)
 112.821 +       *outHmdTrackingState = hmdTrackingState;
 112.822 +
 112.823 +    // Currently HmdToEyeViewOffset is only a 3D vector
 112.824 +    // (Negate HmdToEyeViewOffset because offset is a view matrix offset and not a camera offset)
 112.825 +    outEyePoses[0] = Posef(hmdPose.Orientation, ((Posef)hmdPose).Apply(-((Vector3f)hmdToEyeViewOffset[0])));
 112.826 +    outEyePoses[1] = Posef(hmdPose.Orientation, ((Posef)hmdPose).Apply(-((Vector3f)hmdToEyeViewOffset[1])));
 112.827 +
 112.828 + 	// Instrument data from eye pose
 112.829 +    hmds->LagStats.InstrumentEyePose(hmdTrackingState);
 112.830 +}
 112.831 +
 112.832 +ovrPosef ovrHmd_GetHmdPosePerEye(ovrHmd hmd, ovrEyeType eye)
 112.833 +{
 112.834 +    HMDState* hmds = (HMDState*)hmd->Handle;
 112.835 +    if (!hmds) return ovrPosef();    
 112.836 +
 112.837 +    // This isn't a great place, but since we removed ovrHmd_BeginEyeRender...
 112.838 +    // Only process latency tester for drawing the left eye (assumes left eye is drawn first)
 112.839 +    if (hmds->pRenderer && eye == 0)
 112.840 +    {
 112.841 +        hmds->LatencyTestActive = hmds->ProcessLatencyTest(hmds->LatencyTestDrawColor);
 112.842 +    }
 112.843 +
 112.844 +    hmds->checkBeginFrameTimingScope("ovrHmd_GetEyePose");
 112.845 +    return hmds->TimeManager.GetEyePredictionPose(hmd, eye);
 112.846 +}
 112.847 +
 112.848 +OVR_EXPORT void ovrHmd_AddDistortionTimeMeasurement(ovrHmd hmddesc, double distortionTimeSeconds)
 112.849 +{
 112.850 +    if (!hmddesc)
 112.851 +        return;
 112.852 +    HMDState* hmds = (HMDState*)hmddesc->Handle;
 112.853 +
 112.854 +    hmds->checkBeginFrameTimingScope("ovrHmd_GetTimewarpEyeMatrices");   
 112.855 +    hmds->TimeManager.AddDistortionTimeMeasurement(distortionTimeSeconds);
 112.856 +}
 112.857 +
 112.858 +
 112.859 +
 112.860 +OVR_EXPORT void ovrHmd_GetEyeTimewarpMatricesDebug(ovrHmd hmddesc, ovrEyeType eye,
 112.861 +                                              ovrPosef renderPose, ovrMatrix4f twmOut[2],double debugTimingOffsetInSeconds)
 112.862 +{
 112.863 +    if (!hmddesc)
 112.864 +        return;
 112.865 +    HMDState* hmds = (HMDState*)hmddesc->Handle;
 112.866 +
 112.867 +    // Debug checks: BeginFrame was called, on the same thread.
 112.868 +    hmds->checkBeginFrameTimingScope("ovrHmd_GetTimewarpEyeMatrices");   
 112.869 +
 112.870 +    hmds->TimeManager.GetTimewarpMatrices(hmddesc, eye, renderPose, twmOut, debugTimingOffsetInSeconds);
 112.871 +
 112.872 +    /*
 112.873 +    // MA: Took this out because new latency test approach just sames
 112.874 +    //     the sample times in FrameTimeManager.
 112.875 +    // TODO: if no timewarp, then test latency in begin eye render
 112.876 +    if (eye == 0)
 112.877 +    {        
 112.878 +        hmds->ProcessLatencyTest2(hmds->LatencyTest2DrawColor, -1.0f);
 112.879 +    }
 112.880 +    */
 112.881 +}
 112.882 +
 112.883 +
 112.884 +OVR_EXPORT void ovrHmd_GetEyeTimewarpMatrices(ovrHmd hmddesc, ovrEyeType eye,
 112.885 +                                              ovrPosef renderPose, ovrMatrix4f twmOut[2])
 112.886 +{
 112.887 +    return(ovrHmd_GetEyeTimewarpMatricesDebug(hmddesc, eye, renderPose, twmOut, 0.0));
 112.888 +}
 112.889 +
 112.890 +
 112.891 +
 112.892 +OVR_EXPORT ovrEyeRenderDesc ovrHmd_GetRenderDesc(ovrHmd hmddesc,
 112.893 +                                                 ovrEyeType eyeType, ovrFovPort fov)
 112.894 +{
 112.895 +    HMDState* hmds = (HMDState*)hmddesc->Handle;
 112.896 +    ovrEyeRenderDesc erd;
 112.897 +   
 112.898 +    if (!hmds)
 112.899 +    {
 112.900 +        memset(&erd, 0, sizeof(erd));
 112.901 +        return erd;
 112.902 +    }
 112.903 +
 112.904 +    return hmds->RenderState.CalcRenderDesc(eyeType, fov);
 112.905 +}
 112.906 +
 112.907 +
 112.908 +
 112.909 +#define OVR_OFFSET_OF(s, field) ((size_t)&((s*)0)->field)
 112.910 +
 112.911 +
 112.912 +
 112.913 +
 112.914 +OVR_EXPORT ovrBool ovrHmd_CreateDistortionMeshDebug( ovrHmd hmddesc,
 112.915 +                                                ovrEyeType eyeType, ovrFovPort fov,
 112.916 +                                                unsigned int distortionCaps,
 112.917 +                                                ovrDistortionMesh *meshData,
 112.918 +												float debugEyeReliefOverrideInMetres)
 112.919 +{
 112.920 +    // The 'internal' function below can be found in CAPI_HMDState.
 112.921 +    // Not ideal, but navigating the convolutions of what compiles
 112.922 +    // where, meant they are in the few places which actually lets these compile.
 112.923 +    // Please relocate (if you wish) to a more meaningful place if you can navigate the compiler gymnastics :)
 112.924 +    return(ovrHmd_CreateDistortionMeshInternal( hmddesc->Handle,
 112.925 +                                                eyeType, fov,
 112.926 +                                                distortionCaps,
 112.927 +                                                meshData,
 112.928 +                                                debugEyeReliefOverrideInMetres));
 112.929 +
 112.930 +}
 112.931 +OVR_EXPORT ovrBool ovrHmd_CreateDistortionMesh( ovrHmd hmddesc,
 112.932 +                                                ovrEyeType eyeType, ovrFovPort fov,
 112.933 +                                                unsigned int distortionCaps,
 112.934 +                                                ovrDistortionMesh *meshData)
 112.935 +{
 112.936 +    return(ovrHmd_CreateDistortionMeshDebug( hmddesc, eyeType, fov, distortionCaps,meshData, 0));
 112.937 +}
 112.938 +
 112.939 +
 112.940 +
 112.941 +// Frees distortion mesh allocated by ovrHmd_GenerateDistortionMesh. meshData elements
 112.942 +// are set to null and 0s after the call.
 112.943 +OVR_EXPORT void ovrHmd_DestroyDistortionMesh(ovrDistortionMesh* meshData)
 112.944 +{
 112.945 +    if (meshData->pVertexData)
 112.946 +        DistortionMeshDestroy((DistortionMeshVertexData*)meshData->pVertexData,
 112.947 +                              meshData->pIndexData);
 112.948 +    meshData->pVertexData = 0;
 112.949 +    meshData->pIndexData  = 0;
 112.950 +    meshData->VertexCount = 0;
 112.951 +    meshData->IndexCount  = 0;
 112.952 +}
 112.953 +
 112.954 +
 112.955 +
 112.956 +// Computes updated 'uvScaleOffsetOut' to be used with a distortion if render target size or
 112.957 +// viewport changes after the fact. This can be used to adjust render size every frame, if desired.
 112.958 +OVR_EXPORT void ovrHmd_GetRenderScaleAndOffset( ovrFovPort fov,
 112.959 +                                                ovrSizei textureSize, ovrRecti renderViewport,
 112.960 +                                                ovrVector2f uvScaleOffsetOut[2] )
 112.961 +{        
 112.962 +    // Find the mapping from TanAngle space to target NDC space.
 112.963 +    ScaleAndOffset2D  eyeToSourceNDC = CreateNDCScaleAndOffsetFromFov(fov);
 112.964 +    // Find the mapping from TanAngle space to textureUV space.
 112.965 +    ScaleAndOffset2D  eyeToSourceUV  = CreateUVScaleAndOffsetfromNDCScaleandOffset(
 112.966 +                                         eyeToSourceNDC,
 112.967 +                                         renderViewport, textureSize );
 112.968 +
 112.969 +    uvScaleOffsetOut[0] = eyeToSourceUV.Scale;
 112.970 +    uvScaleOffsetOut[1] = eyeToSourceUV.Offset;
 112.971 +}
 112.972 +
 112.973 +
 112.974 +//-------------------------------------------------------------------------------------
 112.975 +// ***** Latency Test interface
 112.976 +
 112.977 +OVR_EXPORT ovrBool ovrHmd_GetLatencyTestDrawColor(ovrHmd hmddesc, unsigned char rgbColorOut[3])
 112.978 +{
 112.979 +    HMDState* p = (HMDState*)hmddesc->Handle;
 112.980 +    rgbColorOut[0] = p->LatencyTestDrawColor[0];
 112.981 +    rgbColorOut[1] = p->LatencyTestDrawColor[1];
 112.982 +    rgbColorOut[2] = p->LatencyTestDrawColor[2];
 112.983 +    return p->LatencyTestActive;
 112.984 +}
 112.985 +
 112.986 +OVR_EXPORT ovrBool ovrHmd_ProcessLatencyTest(ovrHmd hmddesc, unsigned char rgbColorOut[3])
 112.987 +{
 112.988 +    OVR_UNUSED(hmddesc);
 112.989 +    return NetClient::GetInstance()->LatencyUtil_ProcessInputs(Timer::GetSeconds(), rgbColorOut);
 112.990 +}
 112.991 +
 112.992 +OVR_EXPORT const char*  ovrHmd_GetLatencyTestResult(ovrHmd hmddesc)
 112.993 +{
 112.994 +    OVR_UNUSED(hmddesc);
 112.995 +    return NetClient::GetInstance()->LatencyUtil_GetResultsString();
 112.996 +}
 112.997 +
 112.998 +OVR_EXPORT ovrBool ovrHmd_GetLatencyTest2DrawColor(ovrHmd hmddesc, unsigned char rgbColorOut[3])
 112.999 +{
112.1000 +    HMDState* hmds = (HMDState*)hmddesc->Handle;
112.1001 +    if (!hmds) return false;
112.1002 +
112.1003 +    // TBD: Move directly into renderer
112.1004 +    bool dk2LatencyTest = (hmds->EnabledHmdCaps & ovrHmdCap_DynamicPrediction) != 0;
112.1005 +    if (dk2LatencyTest)
112.1006 +    {
112.1007 +        hmds->TimeManager.GetFrameLatencyTestDrawColor(hmds->LatencyTest2DrawColor);
112.1008 +        if(rgbColorOut != NULL)
112.1009 +        {
112.1010 +            rgbColorOut[0] = hmds->LatencyTest2DrawColor[0];
112.1011 +            rgbColorOut[1] = hmds->LatencyTest2DrawColor[1];
112.1012 +            rgbColorOut[2] = hmds->LatencyTest2DrawColor[2];
112.1013 +        }
112.1014 +
112.1015 +        if(hmds->pRenderer != NULL)
112.1016 +            hmds->pRenderer->SetLatencyTest2Color(hmds->LatencyTest2DrawColor);
112.1017 +    }
112.1018 +    else
112.1019 +    {
112.1020 +        if(hmds->pRenderer != NULL)
112.1021 +            hmds->pRenderer->SetLatencyTest2Color(NULL);
112.1022 +    }
112.1023 +
112.1024 +    return dk2LatencyTest;
112.1025 +}
112.1026 +
112.1027 +
112.1028 +OVR_EXPORT double ovrHmd_GetMeasuredLatencyTest2(ovrHmd hmddesc)
112.1029 +{
112.1030 +    HMDState* p = (HMDState*)hmddesc->Handle;
112.1031 +
112.1032 +    // MA Test
112.1033 +    float latencyRender, latencyTimewarp, latencyPostPresent;
112.1034 +
112.1035 +    p->TimeManager.GetLatencyTimings(latencyRender, latencyTimewarp, latencyPostPresent);
112.1036 +    return latencyPostPresent;
112.1037 +}
112.1038 +
112.1039 +
112.1040 +//-------------------------------------------------------------------------------------
112.1041 +// ***** Health and Safety Warning Display interface
112.1042 +//
112.1043 +
112.1044 +OVR_EXPORT void ovrHmd_GetHSWDisplayState(ovrHmd hmd, ovrHSWDisplayState *hswDisplayState)
112.1045 +{
112.1046 +    OVR::CAPI::HMDState* pHMDState = (OVR::CAPI::HMDState*)hmd->Handle;
112.1047 +
112.1048 +    if (pHMDState)
112.1049 +    {
112.1050 +        OVR::CAPI::HSWDisplay* pHSWDisplay = pHMDState->pHSWDisplay;
112.1051 +
112.1052 +        if(pHSWDisplay)
112.1053 +            pHSWDisplay->TickState(hswDisplayState); // This may internally call HSWDisplay::Display.
112.1054 +    }
112.1055 +}
112.1056 +
112.1057 +OVR_EXPORT ovrBool ovrHmd_DismissHSWDisplay(ovrHmd hmd)
112.1058 +{
112.1059 +    OVR::CAPI::HMDState* pHMDState = (OVR::CAPI::HMDState*)hmd->Handle;
112.1060 +
112.1061 +    if (pHMDState)
112.1062 +    {
112.1063 +        OVR::CAPI::HSWDisplay* pHSWDisplay = pHMDState->pHSWDisplay;
112.1064 +
112.1065 +        if(pHSWDisplay)
112.1066 +            return (pHSWDisplay->Dismiss() ? 1 : 0);
112.1067 +    }
112.1068 +
112.1069 +    return false;
112.1070 +}
112.1071 +
112.1072 +
112.1073 +// -----------------------------------------------------------------------------------
112.1074 +// ***** Property Access
112.1075 +OVR_EXPORT ovrBool ovrHmd_GetBool(ovrHmd hmddesc,
112.1076 +                                  const char* propertyName,
112.1077 +                                  ovrBool defaultVal)
112.1078 +{
112.1079 +    OVR_ASSERT(propertyName);
112.1080 +    if (hmddesc)
112.1081 +    {
112.1082 +        HMDState* hmds = (HMDState*)hmddesc->Handle;
112.1083 +        OVR_ASSERT(hmds);
112.1084 +        if (hmds)
112.1085 +        {
112.1086 +            return hmds->getBoolValue(propertyName, (defaultVal != 0));
112.1087 +        }
112.1088 +    }
112.1089 +
112.1090 +    return NetClient::GetInstance()->GetBoolValue(InvalidVirtualHmdId, propertyName, (defaultVal != 0)) ? 1 : 0;
112.1091 +}
112.1092 +
112.1093 +OVR_EXPORT ovrBool ovrHmd_SetBool(ovrHmd hmddesc,
112.1094 +                                  const char* propertyName,
112.1095 +                                  ovrBool value)
112.1096 +{
112.1097 +    OVR_ASSERT(propertyName);
112.1098 +    if (hmddesc)
112.1099 +    {
112.1100 +        HMDState* hmds = (HMDState*)hmddesc->Handle;
112.1101 +        OVR_ASSERT(hmds);
112.1102 +        if (hmds)
112.1103 +        {
112.1104 +            return hmds->setBoolValue(propertyName, value != 0) ? 1 : 0;
112.1105 +        }
112.1106 +    }
112.1107 +
112.1108 +    return NetClient::GetInstance()->SetBoolValue(InvalidVirtualHmdId, propertyName, (value != 0)) ? 1 : 0;
112.1109 +}
112.1110 +
112.1111 +OVR_EXPORT int ovrHmd_GetInt(ovrHmd hmddesc,
112.1112 +                             const char* propertyName,
112.1113 +                             int defaultVal)
112.1114 +{
112.1115 +    OVR_ASSERT(propertyName);
112.1116 +    if (hmddesc)
112.1117 +    {
112.1118 +        HMDState* hmds = (HMDState*)hmddesc->Handle;
112.1119 +        OVR_ASSERT(hmds);
112.1120 +        if (hmds)
112.1121 +        {
112.1122 +            return hmds->getIntValue(propertyName, defaultVal);
112.1123 +        }
112.1124 +    }
112.1125 +
112.1126 +    return NetClient::GetInstance()->GetIntValue(InvalidVirtualHmdId, propertyName, defaultVal);
112.1127 +}
112.1128 +
112.1129 +OVR_EXPORT ovrBool ovrHmd_SetInt(ovrHmd hmddesc,
112.1130 +                                 const char* propertyName,
112.1131 +                                 int value)
112.1132 +{
112.1133 +    OVR_ASSERT(propertyName);
112.1134 +    if (hmddesc)
112.1135 +    {
112.1136 +        HMDState* hmds = (HMDState*)hmddesc->Handle;
112.1137 +        OVR_ASSERT(hmds);
112.1138 +        if (hmds)
112.1139 +        {
112.1140 +            return hmds->setIntValue(propertyName, value) ? 1 : 0;
112.1141 +        }
112.1142 +    }
112.1143 +
112.1144 +    return NetClient::GetInstance()->SetIntValue(InvalidVirtualHmdId, propertyName, value) ? 1 : 0;
112.1145 +}
112.1146 +
112.1147 +OVR_EXPORT float ovrHmd_GetFloat(ovrHmd hmddesc,
112.1148 +                                 const char* propertyName,
112.1149 +                                 float defaultVal)
112.1150 +{
112.1151 +    OVR_ASSERT(propertyName);
112.1152 +    if (hmddesc)
112.1153 +    {
112.1154 +        HMDState* hmds = (HMDState*)hmddesc->Handle;
112.1155 +        OVR_ASSERT(hmds);
112.1156 +        if (hmds)
112.1157 +        {
112.1158 +            return hmds->getFloatValue(propertyName, defaultVal);
112.1159 +        }
112.1160 +    }
112.1161 +
112.1162 +    return (float)NetClient::GetInstance()->GetNumberValue(InvalidVirtualHmdId, propertyName, defaultVal);
112.1163 +}
112.1164 +
112.1165 +OVR_EXPORT ovrBool ovrHmd_SetFloat(ovrHmd hmddesc,
112.1166 +                                   const char* propertyName,
112.1167 +                                   float value)
112.1168 +{
112.1169 +    OVR_ASSERT(propertyName);
112.1170 +    if (hmddesc)
112.1171 +    {
112.1172 +        HMDState* hmds = (HMDState*)hmddesc->Handle;
112.1173 +        OVR_ASSERT(hmds);
112.1174 +        if (hmds)
112.1175 +        {
112.1176 +            return hmds->setFloatValue(propertyName, value) ? 1 : 0;
112.1177 +        }
112.1178 +    }
112.1179 +
112.1180 +    return NetClient::GetInstance()->SetNumberValue(InvalidVirtualHmdId, propertyName, value) ? 1 : 0;
112.1181 +}
112.1182 +
112.1183 +OVR_EXPORT unsigned int ovrHmd_GetFloatArray(ovrHmd hmddesc,
112.1184 +                                             const char* propertyName,
112.1185 +                                             float values[],
112.1186 +                                             unsigned int arraySize)
112.1187 +{
112.1188 +    OVR_ASSERT(propertyName);
112.1189 +    OVR_ASSERT(hmddesc);
112.1190 +    if (hmddesc)
112.1191 +    {
112.1192 +        HMDState* hmds = (HMDState*)hmddesc->Handle;
112.1193 +        OVR_ASSERT(hmds);
112.1194 +        if (hmds)
112.1195 +        {
112.1196 +            return hmds->getFloatArray(propertyName, values, arraySize);
112.1197 +        }
112.1198 +    }
112.1199 +
112.1200 +    // FIXME: Currently it takes a few lines of code to do this, so just not supported for now.
112.1201 +    return 0;
112.1202 +}
112.1203 +
112.1204 +// Modify float[] property; false if property doesn't exist or is readonly.
112.1205 +OVR_EXPORT ovrBool ovrHmd_SetFloatArray(ovrHmd hmddesc,
112.1206 +                                        const char* propertyName,
112.1207 +                                        float values[],
112.1208 +                                        unsigned int arraySize)
112.1209 +{
112.1210 +    OVR_ASSERT(propertyName);
112.1211 +    OVR_ASSERT(hmddesc);
112.1212 +    if (hmddesc)
112.1213 +    {
112.1214 +        HMDState* hmds = (HMDState*)hmddesc->Handle;
112.1215 +        OVR_ASSERT(hmds);
112.1216 +        if (hmds)
112.1217 +        {
112.1218 +            return hmds->setFloatArray(propertyName, values, arraySize) ? 1 : 0;
112.1219 +        }
112.1220 +    }
112.1221 +
112.1222 +    // FIXME: Currently it takes a few lines of code to do this, so just not supported for now.
112.1223 +    return 0;
112.1224 +}
112.1225 +
112.1226 +OVR_EXPORT const char* ovrHmd_GetString(ovrHmd hmddesc,
112.1227 +                                        const char* propertyName,
112.1228 +                                        const char* defaultVal)
112.1229 +{
112.1230 +    OVR_ASSERT(propertyName);
112.1231 +    if (hmddesc)
112.1232 +    {
112.1233 +        HMDState* hmds = (HMDState*)hmddesc->Handle;
112.1234 +        if (hmds)
112.1235 +        {
112.1236 +            return hmds->getString(propertyName, defaultVal);
112.1237 +        }
112.1238 +    }
112.1239 +
112.1240 +    return NetClient::GetInstance()->GetStringValue(InvalidVirtualHmdId, propertyName, defaultVal);
112.1241 +}
112.1242 + 
112.1243 +OVR_EXPORT ovrBool ovrHmd_SetString(ovrHmd hmddesc,
112.1244 +                                    const char* propertyName,
112.1245 +                                    const char* value)
112.1246 +{
112.1247 +    OVR_ASSERT(propertyName);
112.1248 +    if (hmddesc)
112.1249 +    {
112.1250 +        HMDState* hmds = (HMDState*)hmddesc->Handle;
112.1251 +        if (hmds)
112.1252 +        {
112.1253 +            return hmds->setString(propertyName, value) ? 1 : 0;
112.1254 +        }
112.1255 +    }
112.1256 +
112.1257 +    return NetClient::GetInstance()->SetStringValue(InvalidVirtualHmdId, propertyName, value) ? 1 : 0;
112.1258 +}
112.1259 +
112.1260 +// -----------------------------------------------------------------------------------
112.1261 +// ***** Logging
112.1262 +
112.1263 +OVR_EXPORT ovrBool ovrHmd_StartPerfLog(ovrHmd hmd, const char* fileName, const char* userData1)
112.1264 +{
112.1265 +    OVR_ASSERT(fileName && fileName[0]);
112.1266 +
112.1267 +    OVR::CAPI::HMDState* pHMDState = (OVR::CAPI::HMDState*)hmd->Handle;
112.1268 +
112.1269 +    if (pHMDState)
112.1270 +    {
112.1271 +        ovrBool started = pHMDState->LagStatsCSV.Start(fileName, userData1) ? 1 : 0;
112.1272 +        if (started)
112.1273 +            pHMDState->LagStats.AddResultsObserver(pHMDState->LagStatsCSV.GetObserver());
112.1274 +        return started;
112.1275 +    }
112.1276 +    return 0;
112.1277 +}
112.1278 +OVR_EXPORT ovrBool ovrHmd_StopPerfLog(ovrHmd hmd)
112.1279 +{
112.1280 +    OVR::CAPI::HMDState* pHMDState = (OVR::CAPI::HMDState*)hmd->Handle;
112.1281 +
112.1282 +    if (pHMDState)
112.1283 +    {
112.1284 +        return pHMDState->LagStatsCSV.Stop() ? 1 : 0;
112.1285 +    }
112.1286 +    return false;
112.1287 +}
112.1288 +
112.1289 +
112.1290 +#ifdef __cplusplus 
112.1291 +} // extern "C"
112.1292 +#endif
   113.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   113.2 +++ b/LibOVR/Src/OVR_CAPI.h	Wed Jan 14 06:51:16 2015 +0200
   113.3 @@ -0,0 +1,950 @@
   113.4 +/************************************************************************************
   113.5 +
   113.6 +Filename    :   OVR_CAPI.h
   113.7 +Content     :   C Interface to Oculus tracking and rendering.
   113.8 +Created     :   November 23, 2013
   113.9 +Authors     :   Michael Antonov
  113.10 +
  113.11 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
  113.12 +
  113.13 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License");
  113.14 +you may not use the Oculus VR Rift SDK except in compliance with the License,
  113.15 +which is provided at the time of installation or download, or which
  113.16 +otherwise accompanies this software in either electronic or hard copy form.
  113.17 +
  113.18 +You may obtain a copy of the License at
  113.19 +
  113.20 +http://www.oculusvr.com/licenses/LICENSE-3.2
  113.21 +
  113.22 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK
  113.23 +distributed under the License is distributed on an "AS IS" BASIS,
  113.24 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  113.25 +See the License for the specific language governing permissions and
  113.26 +limitations under the License.
  113.27 +
  113.28 +************************************************************************************/
  113.29 +
  113.30 +/// @file OVR_CAPI.h
  113.31 +/// Exposes all general Rift functionality.
  113.32 +
  113.33 +#ifndef OVR_CAPI_h
  113.34 +#define OVR_CAPI_h
  113.35 +
  113.36 +#include <stdint.h>
  113.37 +
  113.38 +#include "OVR_CAPI_Keys.h"
  113.39 +
  113.40 +typedef char ovrBool;
  113.41 +
  113.42 +//-----------------------------------------------------------------------------------
  113.43 +// ***** OVR_EXPORT definition
  113.44 +
  113.45 +#if !defined(OVR_EXPORT)
  113.46 +    #ifdef OVR_OS_WIN32
  113.47 +        #define OVR_EXPORT __declspec(dllexport)
  113.48 +    #else
  113.49 +        #define OVR_EXPORT
  113.50 +    #endif
  113.51 +#endif
  113.52 +
  113.53 +
  113.54 +
  113.55 +//-----------------------------------------------------------------------------------
  113.56 +// ***** OVR_ALIGNAS definition
  113.57 +//
  113.58 +#if !defined(OVR_ALIGNAS)
  113.59 +    // C++11 alignas
  113.60 +    #if defined(__GNUC__) && (((__GNUC__ * 100) + __GNUC_MINOR__) >= 408) && (defined(__GXX_EXPERIMENTAL_CXX0X__) || (__cplusplus >= 201103L))
  113.61 +        #define OVR_ALIGNAS(n) alignas(n)
  113.62 +    #elif defined(__clang__) && !defined(__APPLE__) && (((__clang_major__ * 100) + __clang_minor__) >= 300) && (__cplusplus >= 201103L)
  113.63 +        #define OVR_ALIGNAS(n) alignas(n)
  113.64 +    #elif defined(__clang__) && defined(__APPLE__) && (((__clang_major__ * 100) + __clang_minor__) >= 401) && (__cplusplus >= 201103L)
  113.65 +        #define OVR_ALIGNAS(n) alignas(n)
  113.66 +    #elif defined(_MSC_VER) && (_MSC_VER >= 1900)
  113.67 +        #define OVR_ALIGNAS(n) alignas(n)
  113.68 +    #elif defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 408)
  113.69 +        #define OVR_ALIGNAS(n) alignas(n)
  113.70 +
  113.71 +    // Pre-C++11 alignas fallbacks
  113.72 +    #elif defined(__GNUC__) || defined(__clang__)
  113.73 +        #define OVR_ALIGNAS(n) __attribute__((aligned(n)))
  113.74 +    #elif defined(_MSC_VER) || defined(__INTEL_COMPILER)
  113.75 +        #define OVR_ALIGNAS(n) __declspec(align(n))             // For Microsoft the alignment must be a literal integer.
  113.76 +    #elif defined(__CC_ARM)
  113.77 +        #define OVR_ALIGNAS(n) __align(n)
  113.78 +    #else
  113.79 +        #error Need to define OVR_ALIGNAS
  113.80 +    #endif
  113.81 +#endif
  113.82 +
  113.83 +#if defined(_MSC_VER)
  113.84 +    #pragma warning(push)
  113.85 +    #pragma warning(disable: 4324) // structure was padded due to __declspec(align())
  113.86 +#endif
  113.87 +
  113.88 +
  113.89 +//#define ENABLE_LATENCY_TESTER
  113.90 +
  113.91 +//-----------------------------------------------------------------------------------
  113.92 +// ***** Simple Math Structures
  113.93 +
  113.94 +/// A 2D vector with integer components.
  113.95 +typedef struct ovrVector2i_
  113.96 +{
  113.97 +    int x, y;
  113.98 +} ovrVector2i;
  113.99 +
 113.100 +/// A 2D size with integer components.
 113.101 +typedef struct ovrSizei_
 113.102 +{
 113.103 +    int w, h;
 113.104 +} ovrSizei;
 113.105 +/// A 2D rectangle with a position and size.
 113.106 +/// All components are integers.
 113.107 +typedef struct ovrRecti_
 113.108 +{
 113.109 +    ovrVector2i Pos;
 113.110 +    ovrSizei    Size;
 113.111 +} ovrRecti;
 113.112 +
 113.113 +/// A quaternion rotation.
 113.114 +typedef struct ovrQuatf_
 113.115 +{
 113.116 +    float x, y, z, w;
 113.117 +} ovrQuatf;
 113.118 +
 113.119 +/// A 2D vector with float components.
 113.120 +typedef struct ovrVector2f_
 113.121 +{
 113.122 +    float x, y;
 113.123 +} ovrVector2f;
 113.124 +
 113.125 +/// A 3D vector with float components.
 113.126 +typedef struct ovrVector3f_
 113.127 +{
 113.128 +    float x, y, z;
 113.129 +} ovrVector3f;
 113.130 +
 113.131 +/// A 4x4 matrix with float elements.
 113.132 +typedef struct ovrMatrix4f_
 113.133 +{
 113.134 +    float M[4][4];
 113.135 +} ovrMatrix4f;
 113.136 +
 113.137 +/// Position and orientation together.
 113.138 +typedef struct ovrPosef_
 113.139 +{
 113.140 +    ovrQuatf     Orientation;
 113.141 +    ovrVector3f  Position;
 113.142 +} ovrPosef;
 113.143 +
 113.144 +/// A full pose (rigid body) configuration with first and second derivatives.
 113.145 +typedef struct ovrPoseStatef_
 113.146 +{
 113.147 +    ovrPosef     ThePose;               ///< The body's position and orientation.
 113.148 +    ovrVector3f  AngularVelocity;       ///< The body's angular velocity in radians per second.
 113.149 +    ovrVector3f  LinearVelocity;        ///< The body's velocity in meters per second.
 113.150 +    ovrVector3f  AngularAcceleration;   ///< The body's angular acceleration in radians per second per second.
 113.151 +    ovrVector3f  LinearAcceleration;    ///< The body's acceleration in meters per second per second.
 113.152 +    double       TimeInSeconds;         ///< Absolute time of this state sample.
 113.153 +} ovrPoseStatef;
 113.154 +
 113.155 +/// Field Of View (FOV) in tangent of the angle units.
 113.156 +/// As an example, for a standard 90 degree vertical FOV, we would
 113.157 +/// have: { UpTan = tan(90 degrees / 2), DownTan = tan(90 degrees / 2) }.
 113.158 +typedef struct ovrFovPort_
 113.159 +{
 113.160 +    /// The tangent of the angle between the viewing vector and the top edge of the field of view.
 113.161 +    float UpTan;
 113.162 +    /// The tangent of the angle between the viewing vector and the bottom edge of the field of view.
 113.163 +    float DownTan;
 113.164 +    /// The tangent of the angle between the viewing vector and the left edge of the field of view.
 113.165 +    float LeftTan;
 113.166 +    /// The tangent of the angle between the viewing vector and the right edge of the field of view.
 113.167 +    float RightTan;
 113.168 +} ovrFovPort;
 113.169 +
 113.170 +//-----------------------------------------------------------------------------------
 113.171 +// ***** HMD Types
 113.172 +
 113.173 +/// Enumerates all HMD types that we support.
 113.174 +typedef enum
 113.175 +{
 113.176 +    ovrHmd_None             = 0,
 113.177 +    ovrHmd_DK1              = 3,
 113.178 +    ovrHmd_DKHD             = 4,
 113.179 +    ovrHmd_DK2              = 6,
 113.180 +    ovrHmd_Other             // Some HMD other then the one in the enumeration.
 113.181 +} ovrHmdType;
 113.182 +
 113.183 +/// HMD capability bits reported by device.
 113.184 +typedef enum
 113.185 +{
 113.186 +    // Read-only flags.
 113.187 +    ovrHmdCap_Present           = 0x0001,   /// The HMD is plugged in and detected by the system.
 113.188 +    ovrHmdCap_Available         = 0x0002,   /// The HMD and its sensor are available for ownership use.
 113.189 +											/// i.e. it is not already owned by another application.
 113.190 +    ovrHmdCap_Captured          = 0x0004,   /// Set to 'true' if we captured ownership of this HMD.
 113.191 +
 113.192 +    // These flags are intended for use with the new driver display mode.
 113.193 +    ovrHmdCap_ExtendDesktop     = 0x0008,   /// (read only) Means the display driver is in compatibility mode.
 113.194 +
 113.195 +    // Modifiable flags (through ovrHmd_SetEnabledCaps).
 113.196 +    ovrHmdCap_NoMirrorToWindow  = 0x2000,   /// Disables mirroring of HMD output to the window. This may improve 
 113.197 +											/// rendering performance slightly (only if 'ExtendDesktop' is off).
 113.198 +    ovrHmdCap_DisplayOff        = 0x0040,   /// Turns off HMD screen and output (only if 'ExtendDesktop' is off).
 113.199 +
 113.200 +    ovrHmdCap_LowPersistence    = 0x0080,   /// HMD supports low persistence mode.
 113.201 +    ovrHmdCap_DynamicPrediction = 0x0200,   /// Adjust prediction dynamically based on internally measured latency.
 113.202 +    ovrHmdCap_DirectPentile     = 0x0400,   /// Write directly in pentile color mapping format
 113.203 +    ovrHmdCap_NoVSync           = 0x1000,   /// Support rendering without VSync for debugging.
 113.204 +
 113.205 +    // These bits can be modified by ovrHmd_SetEnabledCaps.
 113.206 +    ovrHmdCap_Writable_Mask     = 0x32F0,
 113.207 +
 113.208 +    /// These flags are currently passed into the service. May change without notice.
 113.209 +    ovrHmdCap_Service_Mask      = 0x22F0
 113.210 +} ovrHmdCaps;
 113.211 +
 113.212 +
 113.213 +/// Tracking capability bits reported by the device.
 113.214 +/// Used with ovrHmd_ConfigureTracking.
 113.215 +typedef enum
 113.216 +{
 113.217 +    ovrTrackingCap_Orientation      = 0x0010,   /// Supports orientation tracking (IMU).
 113.218 +    ovrTrackingCap_MagYawCorrection = 0x0020,   /// Supports yaw drift correction via a magnetometer or other means.
 113.219 +    ovrTrackingCap_Position         = 0x0040,   /// Supports positional tracking.
 113.220 +    /// Overrides the other flags. Indicates that the application
 113.221 +    /// doesn't care about tracking settings. This is the internal
 113.222 +    /// default before ovrHmd_ConfigureTracking is called.
 113.223 +    ovrTrackingCap_Idle             = 0x0100,
 113.224 +} ovrTrackingCaps;
 113.225 +
 113.226 +/// Distortion capability bits reported by device.
 113.227 +/// Used with ovrHmd_ConfigureRendering and ovrHmd_CreateDistortionMesh.
 113.228 +typedef enum
 113.229 +{
 113.230 +    ovrDistortionCap_Chromatic          =   0x01,     /// Supports chromatic aberration correction.
 113.231 +    ovrDistortionCap_TimeWarp           =   0x02,     /// Supports timewarp.
 113.232 +    // 0x04 unused
 113.233 +    ovrDistortionCap_Vignette           =   0x08,     /// Supports vignetting around the edges of the view.
 113.234 +    ovrDistortionCap_NoRestore          =   0x10,     /// Do not save and restore the graphics and compute state when rendering distortion.
 113.235 +    ovrDistortionCap_FlipInput          =   0x20,     /// Flip the vertical texture coordinate of input images.
 113.236 +    ovrDistortionCap_SRGB               =   0x40,     /// Assume input images are in sRGB gamma-corrected color space.
 113.237 +    ovrDistortionCap_Overdrive          =   0x80,     /// Overdrive brightness transitions to reduce artifacts on DK2+ displays
 113.238 +    ovrDistortionCap_HqDistortion       =  0x100,     /// High-quality sampling of distortion buffer for anti-aliasing
 113.239 +    ovrDistortionCap_LinuxDevFullscreen =  0x200,     /// Indicates window is fullscreen on a device when set. The SDK will automatically apply distortion mesh rotation if needed.
 113.240 +    ovrDistortionCap_ComputeShader      =  0x400,     /// Using compute shader (DX11+ only)
 113.241 +
 113.242 +    ovrDistortionCap_ProfileNoTimewarpSpinWaits = 0x10000,  /// Use when profiling with timewarp to remove false positives
 113.243 +} ovrDistortionCaps;
 113.244 +
 113.245 +/// Specifies which eye is being used for rendering.
 113.246 +/// This type explicitly does not include a third "NoStereo" option, as such is
 113.247 +/// not required for an HMD-centered API.
 113.248 +typedef enum
 113.249 +{
 113.250 +    ovrEye_Left  = 0,
 113.251 +    ovrEye_Right = 1,
 113.252 +    ovrEye_Count = 2
 113.253 +} ovrEyeType;
 113.254 +
 113.255 +/// This is a complete descriptor of the HMD.
 113.256 +typedef struct ovrHmdDesc_
 113.257 +{
 113.258 +    /// Internal handle of this HMD.
 113.259 +    struct ovrHmdStruct* Handle;
 113.260 +
 113.261 +    /// This HMD's type.
 113.262 +    ovrHmdType  Type;
 113.263 +    
 113.264 +    /// Name string describing the product: "Oculus Rift DK1", etc.
 113.265 +    const char* ProductName;
 113.266 +    const char* Manufacturer;
 113.267 +    
 113.268 +    /// HID Vendor and ProductId of the device.
 113.269 +    short       VendorId;
 113.270 +    short       ProductId;
 113.271 +    /// Sensor (and display) serial number.
 113.272 +    char        SerialNumber[24];
 113.273 +    /// Sensor firmware version.
 113.274 +    short       FirmwareMajor;
 113.275 +    short       FirmwareMinor;
 113.276 +    /// External tracking camera frustum dimensions (if present).
 113.277 +    float       CameraFrustumHFovInRadians;
 113.278 +    float       CameraFrustumVFovInRadians;
 113.279 +    float       CameraFrustumNearZInMeters;
 113.280 +    float       CameraFrustumFarZInMeters;
 113.281 +
 113.282 +    /// Capability bits described by ovrHmdCaps.
 113.283 +    unsigned int HmdCaps;
 113.284 +	/// Capability bits described by ovrTrackingCaps.
 113.285 +    unsigned int TrackingCaps;
 113.286 +    /// Capability bits described by ovrDistortionCaps.
 113.287 +    unsigned int DistortionCaps;
 113.288 +
 113.289 +    /// These define the recommended and maximum optical FOVs for the HMD.
 113.290 +    ovrFovPort  DefaultEyeFov[ovrEye_Count];
 113.291 +    ovrFovPort  MaxEyeFov[ovrEye_Count];
 113.292 +
 113.293 +    /// Preferred eye rendering order for best performance.
 113.294 +    /// Can help reduce latency on sideways-scanned screens.
 113.295 +    ovrEyeType  EyeRenderOrder[ovrEye_Count];
 113.296 +
 113.297 +    /// Resolution of the full HMD screen (both eyes) in pixels.
 113.298 +    ovrSizei    Resolution;
 113.299 +    /// Location of the application window on the desktop (or 0,0).
 113.300 +    ovrVector2i WindowsPos;
 113.301 +
 113.302 +    /// Display that the HMD should present on.
 113.303 +    /// TBD: It may be good to remove this information relying on WindowPos instead.
 113.304 +    /// Ultimately, we may need to come up with a more convenient alternative,
 113.305 +    /// such as API-specific functions that return adapter, or something that will
 113.306 +    /// work with our monitor driver.
 113.307 +    /// Windows: (e.g. "\\\\.\\DISPLAY3", can be used in EnumDisplaySettings/CreateDC).
 113.308 +    const char* DisplayDeviceName;
 113.309 +    /// MacOS:
 113.310 +    int         DisplayId;
 113.311 +
 113.312 +} ovrHmdDesc;
 113.313 +
 113.314 +/// Simple type ovrHmd is used in ovrHmd_* calls.
 113.315 +typedef const ovrHmdDesc * ovrHmd;
 113.316 +
 113.317 +/// Bit flags describing the current status of sensor tracking.
 113.318 +typedef enum
 113.319 +{
 113.320 +    ovrStatus_OrientationTracked    = 0x0001,   /// Orientation is currently tracked (connected and in use).
 113.321 +    ovrStatus_PositionTracked       = 0x0002,   /// Position is currently tracked (false if out of range).
 113.322 +    ovrStatus_CameraPoseTracked     = 0x0004,   /// Camera pose is currently tracked.
 113.323 +    ovrStatus_PositionConnected     = 0x0020,   /// Position tracking hardware is connected.
 113.324 +    ovrStatus_HmdConnected          = 0x0080    /// HMD Display is available and connected.
 113.325 +} ovrStatusBits;
 113.326 +
 113.327 +/// Specifies a reading we can query from the sensor.
 113.328 +typedef struct ovrSensorData_
 113.329 +{
 113.330 +    ovrVector3f    Accelerometer;    /// Acceleration reading in m/s^2.
 113.331 +    ovrVector3f    Gyro;             /// Rotation rate in rad/s.
 113.332 +    ovrVector3f    Magnetometer;     /// Magnetic field in Gauss.
 113.333 +    float          Temperature;      /// Temperature of the sensor in degrees Celsius.
 113.334 +    float          TimeInSeconds;    /// Time when the reported IMU reading took place, in seconds.
 113.335 +} ovrSensorData;
 113.336 +
 113.337 +/// Tracking state at a given absolute time (describes predicted HMD pose etc).
 113.338 +/// Returned by ovrHmd_GetTrackingState.
 113.339 +typedef struct ovrTrackingState_
 113.340 +{
 113.341 +    /// Predicted head pose (and derivatives) at the requested absolute time.
 113.342 +    /// The look-ahead interval is equal to (HeadPose.TimeInSeconds - RawSensorData.TimeInSeconds).
 113.343 +    ovrPoseStatef  HeadPose;
 113.344 +
 113.345 +    /// Current pose of the external camera (if present).
 113.346 +    /// This pose includes camera tilt (roll and pitch). For a leveled coordinate
 113.347 +    /// system use LeveledCameraPose.
 113.348 +    ovrPosef       CameraPose;
 113.349 +
 113.350 +    /// Camera frame aligned with gravity.
 113.351 +    /// This value includes position and yaw of the camera, but not roll and pitch.
 113.352 +    /// It can be used as a reference point to render real-world objects in the correct location.
 113.353 +    ovrPosef       LeveledCameraPose;
 113.354 +
 113.355 +    /// The most recent sensor data received from the HMD.
 113.356 +    ovrSensorData  RawSensorData;
 113.357 +
 113.358 +    /// Tracking status described by ovrStatusBits.
 113.359 +    unsigned int   StatusFlags;
 113.360 +
 113.361 +    //// 0.4.1
 113.362 +
 113.363 +    // Measures the time from receiving the camera frame until vision CPU processing completes.
 113.364 +    double LastVisionProcessingTime;
 113.365 +
 113.366 +    //// 0.4.3
 113.367 +
 113.368 +    // Measures the time from exposure until the pose is available for the frame, including processing time.
 113.369 +    double LastVisionFrameLatency;
 113.370 +
 113.371 +    /// Tag the vision processing results to a certain frame counter number.
 113.372 +    uint32_t LastCameraFrameCounter;
 113.373 +} ovrTrackingState;
 113.374 +
 113.375 +/// Frame timing data reported by ovrHmd_BeginFrameTiming() or ovrHmd_BeginFrame().
 113.376 +typedef struct ovrFrameTiming_
 113.377 +{
 113.378 +    /// The amount of time that has passed since the previous frame's
 113.379 +	/// ThisFrameSeconds value (usable for movement scaling).
 113.380 +    /// This will be clamped to no more than 0.1 seconds to prevent
 113.381 +    /// excessive movement after pauses due to loading or initialization.
 113.382 +    float           DeltaSeconds;
 113.383 +
 113.384 +    /// It is generally expected that the following holds:
 113.385 +    /// ThisFrameSeconds < TimewarpPointSeconds < NextFrameSeconds < 
 113.386 +    /// EyeScanoutSeconds[EyeOrder[0]] <= ScanoutMidpointSeconds <= EyeScanoutSeconds[EyeOrder[1]].
 113.387 +
 113.388 +    /// Absolute time value when rendering of this frame began or is expected to
 113.389 +    /// begin. Generally equal to NextFrameSeconds of the previous frame. Can be used
 113.390 +    /// for animation timing.
 113.391 +    double          ThisFrameSeconds;
 113.392 +    /// Absolute point when IMU expects to be sampled for this frame.
 113.393 +    double          TimewarpPointSeconds;
 113.394 +    /// Absolute time when frame Present followed by GPU Flush will finish and the next frame begins.
 113.395 +    double          NextFrameSeconds;
 113.396 +
 113.397 +    /// Time when half of the screen will be scanned out. Can be passed as an absolute time
 113.398 +	/// to ovrHmd_GetTrackingState() to get the predicted general orientation.
 113.399 +    double          ScanoutMidpointSeconds;
 113.400 +    /// Timing points when each eye will be scanned out to display. Used when rendering each eye.
 113.401 +    double          EyeScanoutSeconds[2];
 113.402 +} ovrFrameTiming;
 113.403 +
 113.404 +/// Rendering information for each eye. Computed by either ovrHmd_ConfigureRendering()
 113.405 +/// or ovrHmd_GetRenderDesc() based on the specified FOV. Note that the rendering viewport
 113.406 +/// is not included here as it can be specified separately and modified per frame through:
 113.407 +///    (a) ovrHmd_GetRenderScaleAndOffset in the case of client rendered distortion,
 113.408 +/// or (b) passing different values via ovrTexture in the case of SDK rendered distortion.
 113.409 +typedef struct ovrEyeRenderDesc_
 113.410 +{
 113.411 +    ovrEyeType  Eye;                        ///< The eye index this instance corresponds to.
 113.412 +    ovrFovPort  Fov;                        ///< The field of view.
 113.413 +	ovrRecti    DistortedViewport;          ///< Distortion viewport.
 113.414 +    ovrVector2f PixelsPerTanAngleAtCenter;  ///< How many display pixels will fit in tan(angle) = 1.
 113.415 +    ovrVector3f HmdToEyeViewOffset;         ///< Translation to be applied to view matrix for each eye offset.
 113.416 +} ovrEyeRenderDesc;
 113.417 +
 113.418 +//-----------------------------------------------------------------------------------
 113.419 +// ***** Platform-independent Rendering Configuration
 113.420 +
 113.421 +/// These types are used to hide platform-specific details when passing
 113.422 +/// render device, OS, and texture data to the API.
 113.423 +///
 113.424 +/// The benefit of having these wrappers versus platform-specific API functions is
 113.425 +/// that they allow game glue code to be portable. A typical example is an
 113.426 +/// engine that has multiple back ends, say GL and D3D. Portable code that calls
 113.427 +/// these back ends may also use LibOVR. To do this, back ends can be modified
 113.428 +/// to return portable types such as ovrTexture and ovrRenderAPIConfig.
 113.429 +typedef enum
 113.430 +{
 113.431 +    ovrRenderAPI_None,
 113.432 +    ovrRenderAPI_OpenGL,
 113.433 +    ovrRenderAPI_Android_GLES,  // May include extra native window pointers, etc.
 113.434 +    ovrRenderAPI_D3D9,
 113.435 +    ovrRenderAPI_D3D10,
 113.436 +    ovrRenderAPI_D3D11,
 113.437 +    ovrRenderAPI_Count
 113.438 +} ovrRenderAPIType;
 113.439 +
 113.440 +/// Platform-independent part of rendering API-configuration data.
 113.441 +/// It is a part of ovrRenderAPIConfig, passed to ovrHmd_Configure.
 113.442 +typedef struct OVR_ALIGNAS(8) ovrRenderAPIConfigHeader_
 113.443 +{
 113.444 +    ovrRenderAPIType API;
 113.445 +    ovrSizei         BackBufferSize;    // Previously named RTSize.
 113.446 +    int              Multisample;
 113.447 +} ovrRenderAPIConfigHeader;
 113.448 +
 113.449 +/// Contains platform-specific information for rendering.
 113.450 +typedef struct OVR_ALIGNAS(8) ovrRenderAPIConfig_
 113.451 +{
 113.452 +    ovrRenderAPIConfigHeader Header;
 113.453 +    uintptr_t                PlatformData[8];
 113.454 +} ovrRenderAPIConfig;
 113.455 +
 113.456 +/// Platform-independent part of the eye texture descriptor.
 113.457 +/// It is a part of ovrTexture, passed to ovrHmd_EndFrame.
 113.458 +/// If RenderViewport is all zeros then the full texture will be used.
 113.459 +typedef struct OVR_ALIGNAS(8) ovrTextureHeader_
 113.460 +{
 113.461 +    ovrRenderAPIType API;
 113.462 +    ovrSizei         TextureSize;
 113.463 +    ovrRecti         RenderViewport;  // Pixel viewport in texture that holds eye image.
 113.464 +    uint32_t         _PAD0_;
 113.465 +} ovrTextureHeader;
 113.466 +
 113.467 +/// Contains platform-specific information about a texture.
 113.468 +typedef struct OVR_ALIGNAS(8) ovrTexture_
 113.469 +{
 113.470 +    ovrTextureHeader Header;
 113.471 +    uintptr_t        PlatformData[8];
 113.472 +} ovrTexture;
 113.473 +
 113.474 +
 113.475 +// -----------------------------------------------------------------------------------
 113.476 +// ***** API Interfaces
 113.477 +
 113.478 +// Basic steps to use the API:
 113.479 +//
 113.480 +// Setup:
 113.481 +//  * ovrInitialize()
 113.482 +//  * ovrHMD hmd = ovrHmd_Create(0)
 113.483 +//  * Use hmd members and ovrHmd_GetFovTextureSize() to determine graphics configuration.
 113.484 +//  * Call ovrHmd_ConfigureTracking() to configure and initialize tracking.
 113.485 +//  * Call ovrHmd_ConfigureRendering() to setup graphics for SDK rendering,
 113.486 +//    which is the preferred approach.
 113.487 +//    Please refer to "Client Distorton Rendering" below if you prefer to do that instead.
 113.488 +//  * If the ovrHmdCap_ExtendDesktop flag is not set, then use ovrHmd_AttachToWindow to
 113.489 +//    associate the relevant application window with the hmd.
 113.490 +//  * Allocate render target textures as needed.
 113.491 +//
 113.492 +// Game Loop:
 113.493 +//  * Call ovrHmd_BeginFrame() to get the current frame timing information.
 113.494 +//  * Render each eye using ovrHmd_GetEyePoses or ovrHmd_GetHmdPosePerEye to get
 113.495 +//    the predicted hmd pose and each eye pose.
 113.496 +//  * Call ovrHmd_EndFrame() to render the distorted textures to the back buffer
 113.497 +//    and present them on the hmd.
 113.498 +//
 113.499 +// Shutdown:
 113.500 +//  * ovrHmd_Destroy(hmd)
 113.501 +//  * ovr_Shutdown()
 113.502 +//
 113.503 +
 113.504 +#ifdef __cplusplus
 113.505 +extern "C" {
 113.506 +#endif
 113.507 +
 113.508 +// ovr_InitializeRenderingShim initializes the rendering shim appart from everything
 113.509 +// else in LibOVR. This may be helpful if the application prefers to avoid
 113.510 +// creating any OVR resources (allocations, service connections, etc) at this point.
 113.511 +// ovr_InitializeRenderingShim does not bring up anything within LibOVR except the
 113.512 +// necessary hooks to enable the Direct-to-Rift functionality.
 113.513 +//
 113.514 +// Either ovr_InitializeRenderingShim() or ovr_Initialize() must be called before any
 113.515 +// Direct3D or OpenGL initilization is done by applictaion (creation of devices, etc).
 113.516 +// ovr_Initialize() must still be called after to use the rest of LibOVR APIs.
 113.517 +OVR_EXPORT ovrBool  ovr_InitializeRenderingShim();
 113.518 +
 113.519 +// Library init/shutdown, must be called around all other OVR code.
 113.520 +// No other functions calls besides ovr_InitializeRenderingShim are allowed
 113.521 +// before ovr_Initialize succeeds or after ovr_Shutdown.
 113.522 +/// Initializes all Oculus functionality.
 113.523 +OVR_EXPORT ovrBool  ovr_Initialize();
 113.524 +/// Shuts down all Oculus functionality.
 113.525 +OVR_EXPORT void     ovr_Shutdown();
 113.526 +
 113.527 +/// Returns version string representing libOVR version. Static, so
 113.528 +/// string remains valid for app lifespan
 113.529 +OVR_EXPORT const char* ovr_GetVersionString();
 113.530 +
 113.531 +/// Detects or re-detects HMDs and reports the total number detected.
 113.532 +/// Users can get information about each HMD by calling ovrHmd_Create with an index.
 113.533 +OVR_EXPORT int      ovrHmd_Detect();
 113.534 +
 113.535 +/// Creates a handle to an HMD which doubles as a description structure.
 113.536 +/// Index can [0 .. ovrHmd_Detect()-1]. Index mappings can cange after each ovrHmd_Detect call.
 113.537 +/// If not null, then the returned handle must be freed with ovrHmd_Destroy.
 113.538 +OVR_EXPORT ovrHmd   ovrHmd_Create(int index);
 113.539 +OVR_EXPORT void     ovrHmd_Destroy(ovrHmd hmd);
 113.540 +
 113.541 +/// Creates a 'fake' HMD used for debugging only. This is not tied to specific hardware,
 113.542 +/// but may be used to debug some of the related rendering.
 113.543 +OVR_EXPORT ovrHmd   ovrHmd_CreateDebug(ovrHmdType type);
 113.544 +
 113.545 +/// Returns last error for HMD state. Returns null for no error.
 113.546 +/// String is valid until next call or GetLastError or HMD is destroyed.
 113.547 +/// Pass null hmd to get global errors (during create etc).
 113.548 +OVR_EXPORT const char* ovrHmd_GetLastError(ovrHmd hmd);
 113.549 +
 113.550 +/// Platform specific function to specify the application window whose output will be 
 113.551 +/// displayed on the HMD. Only used if the ovrHmdCap_ExtendDesktop flag is false.
 113.552 +///   Windows: SwapChain associated with this window will be displayed on the HMD.
 113.553 +///            Specify 'destMirrorRect' in window coordinates to indicate an area
 113.554 +///            of the render target output that will be mirrored from 'sourceRenderTargetRect'.
 113.555 +///            Null pointers mean "full size".
 113.556 +/// @note Source and dest mirror rects are not yet implemented.
 113.557 +OVR_EXPORT ovrBool ovrHmd_AttachToWindow(ovrHmd hmd, void* window,
 113.558 +										 const ovrRecti* destMirrorRect,
 113.559 +										 const ovrRecti* sourceRenderTargetRect);
 113.560 +
 113.561 +/// Returns capability bits that are enabled at this time as described by ovrHmdCaps.
 113.562 +/// Note that this value is different font ovrHmdDesc::HmdCaps, which describes what
 113.563 +/// capabilities are available for that HMD.
 113.564 +OVR_EXPORT unsigned int ovrHmd_GetEnabledCaps(ovrHmd hmd);
 113.565 +
 113.566 +/// Modifies capability bits described by ovrHmdCaps that can be modified,
 113.567 +/// such as ovrHmdCap_LowPersistance.
 113.568 +OVR_EXPORT void         ovrHmd_SetEnabledCaps(ovrHmd hmd, unsigned int hmdCaps);
 113.569 +
 113.570 +//-------------------------------------------------------------------------------------
 113.571 +// ***** Tracking Interface
 113.572 +
 113.573 +/// All tracking interface functions are thread-safe, allowing tracking state to be sampled
 113.574 +/// from different threads.
 113.575 +/// ConfigureTracking starts sensor sampling, enabling specified capabilities,
 113.576 +///    described by ovrTrackingCaps.
 113.577 +///  - supportedTrackingCaps specifies support that is requested. The function will succeed
 113.578 +///   even if these caps are not available (i.e. sensor or camera is unplugged). Support
 113.579 +///    will automatically be enabled if such device is plugged in later. Software should
 113.580 +///    check ovrTrackingState.StatusFlags for real-time status.
 113.581 +///  - requiredTrackingCaps specify sensor capabilities required at the time of the call.
 113.582 +///    If they are not available, the function will fail. Pass 0 if only specifying
 113.583 +///    supportedTrackingCaps.
 113.584 +///  - Pass 0 for both supportedTrackingCaps and requiredTrackingCaps to disable tracking.
 113.585 +OVR_EXPORT ovrBool  ovrHmd_ConfigureTracking(ovrHmd hmd, unsigned int supportedTrackingCaps,
 113.586 +													     unsigned int requiredTrackingCaps);
 113.587 +
 113.588 +/// Re-centers the sensor orientation.
 113.589 +/// Normally this will recenter the (x,y,z) translational components and the yaw
 113.590 +/// component of orientation.
 113.591 +OVR_EXPORT void     ovrHmd_RecenterPose(ovrHmd hmd);
 113.592 +
 113.593 +/// Returns tracking state reading based on the specified absolute system time.
 113.594 +/// Pass an absTime value of 0.0 to request the most recent sensor reading. In this case
 113.595 +/// both PredictedPose and SamplePose will have the same value.
 113.596 +/// ovrHmd_GetEyePoses relies on this function internally.
 113.597 +/// This may also be used for more refined timing of FrontBuffer rendering logic, etc.
 113.598 +OVR_EXPORT ovrTrackingState ovrHmd_GetTrackingState(ovrHmd hmd, double absTime);
 113.599 +
 113.600 +//-------------------------------------------------------------------------------------
 113.601 +// ***** Graphics Setup
 113.602 +
 113.603 +/// Calculates the recommended texture size for rendering a given eye within the HMD
 113.604 +/// with a given FOV cone. Higher FOV will generally require larger textures to
 113.605 +/// maintain quality.
 113.606 +///  - pixelsPerDisplayPixel specifies the ratio of the number of render target pixels
 113.607 +///    to display pixels at the center of distortion. 1.0 is the default value. Lower
 113.608 +///    values can improve performance.
 113.609 +OVR_EXPORT ovrSizei ovrHmd_GetFovTextureSize(ovrHmd hmd, ovrEyeType eye, ovrFovPort fov,
 113.610 +                                             float pixelsPerDisplayPixel);
 113.611 +
 113.612 +//-------------------------------------------------------------------------------------
 113.613 +// *****  Rendering API Thread Safety
 113.614 +
 113.615 +//  All of rendering functions including the configure and frame functions
 113.616 +// are *NOT thread safe*. It is ok to use ConfigureRendering on one thread and handle
 113.617 +//  frames on another thread, but explicit synchronization must be done since
 113.618 +//  functions that depend on configured state are not reentrant.
 113.619 +//
 113.620 +//  As an extra requirement, any of the following calls must be done on
 113.621 +//  the render thread, which is the same thread that calls ovrHmd_BeginFrame
 113.622 +//  or ovrHmd_BeginFrameTiming.
 113.623 +//    - ovrHmd_EndFrame
 113.624 +//    - ovrHmd_GetEyeTimewarpMatrices
 113.625 +
 113.626 +//-------------------------------------------------------------------------------------
 113.627 +// *****  SDK Distortion Rendering Functions
 113.628 +
 113.629 +// These functions support rendering of distortion by the SDK through direct
 113.630 +// access to the underlying rendering API, such as D3D or GL.
 113.631 +// This is the recommended approach since it allows better support for future
 113.632 +// Oculus hardware, and enables a range of low-level optimizations.
 113.633 +
 113.634 +/// Configures rendering and fills in computed render parameters.
 113.635 +/// This function can be called multiple times to change rendering settings.
 113.636 +/// eyeRenderDescOut is a pointer to an array of two ovrEyeRenderDesc structs
 113.637 +/// that are used to return complete rendering information for each eye.
 113.638 +///  - apiConfig provides D3D/OpenGL specific parameters. Pass null
 113.639 +///    to shutdown rendering and release all resources.
 113.640 +///  - distortionCaps describe desired distortion settings.
 113.641 +OVR_EXPORT ovrBool ovrHmd_ConfigureRendering( ovrHmd hmd,
 113.642 +                                              const ovrRenderAPIConfig* apiConfig,
 113.643 +                                              unsigned int distortionCaps,
 113.644 +                                              const ovrFovPort eyeFovIn[2],
 113.645 +                                              ovrEyeRenderDesc eyeRenderDescOut[2] );
 113.646 +
 113.647 +
 113.648 +/// Begins a frame, returning timing information.
 113.649 +/// This should be called at the beginning of the game rendering loop (on the render thread).
 113.650 +/// Pass 0 for the frame index if not using ovrHmd_GetFrameTiming.
 113.651 +OVR_EXPORT ovrFrameTiming ovrHmd_BeginFrame(ovrHmd hmd, unsigned int frameIndex);
 113.652 +
 113.653 +/// Ends a frame, submitting the rendered textures to the frame buffer.
 113.654 +/// - RenderViewport within each eyeTexture can change per frame if necessary.
 113.655 +/// - 'renderPose' will typically be the value returned from ovrHmd_GetEyePoses,
 113.656 +///   ovrHmd_GetHmdPosePerEye but can be different if a different head pose was
 113.657 +///   used for rendering.
 113.658 +/// - This may perform distortion and scaling internally, assuming is it not
 113.659 +///   delegated to another thread.
 113.660 +/// - Must be called on the same thread as BeginFrame.
 113.661 +/// - *** This Function will call Present/SwapBuffers and potentially wait for GPU Sync ***.
 113.662 +OVR_EXPORT void     ovrHmd_EndFrame(ovrHmd hmd,
 113.663 +                                    const ovrPosef renderPose[2],
 113.664 +                                    const ovrTexture eyeTexture[2]);
 113.665 +
 113.666 +/// Returns predicted head pose in outHmdTrackingState and offset eye poses in outEyePoses
 113.667 +/// as an atomic operation. Caller need not worry about applying HmdToEyeViewOffset to the
 113.668 +/// returned outEyePoses variables.
 113.669 +/// - Thread-safe function where caller should increment frameIndex with every frame
 113.670 +///   and pass the index where applicable to functions called on the  rendering thread.
 113.671 +/// - hmdToEyeViewOffset[2] can be ovrEyeRenderDesc.HmdToEyeViewOffset returned from 
 113.672 +///   ovrHmd_ConfigureRendering or ovrHmd_GetRenderDesc. For monoscopic rendering,
 113.673 +///   use a vector that is the average of the two vectors for both eyes.
 113.674 +/// - If frameIndex is not being used, pass in 0.
 113.675 +/// - Assuming outEyePoses are used for rendering, it should be passed into ovrHmd_EndFrame.
 113.676 +/// - If called doesn't need outHmdTrackingState, it can be NULL
 113.677 +OVR_EXPORT void ovrHmd_GetEyePoses(ovrHmd hmd, unsigned int frameIndex, ovrVector3f hmdToEyeViewOffset[2],
 113.678 +                                   ovrPosef outEyePoses[2], ovrTrackingState* outHmdTrackingState);
 113.679 +
 113.680 +/// Function was previously called ovrHmd_GetEyePose
 113.681 +/// Returns the predicted head pose to use when rendering the specified eye.
 113.682 +/// - Important: Caller must apply HmdToEyeViewOffset before using ovrPosef for rendering
 113.683 +/// - Must be called between ovrHmd_BeginFrameTiming and ovrHmd_EndFrameTiming.
 113.684 +/// - If the pose is used for rendering the eye, it should be passed to ovrHmd_EndFrame.
 113.685 +/// - Parameter 'eye' is used for prediction timing only
 113.686 +OVR_EXPORT ovrPosef ovrHmd_GetHmdPosePerEye(ovrHmd hmd, ovrEyeType eye);
 113.687 +
 113.688 +
 113.689 +//-------------------------------------------------------------------------------------
 113.690 +// *****  Client Distortion Rendering Functions
 113.691 +
 113.692 +// These functions provide the distortion data and render timing support necessary to allow
 113.693 +// client rendering of distortion. Client-side rendering involves the following steps:
 113.694 +//
 113.695 +//  1. Setup ovrEyeDesc based on the desired texture size and FOV.
 113.696 +//     Call ovrHmd_GetRenderDesc to get the necessary rendering parameters for each eye.
 113.697 +//
 113.698 +//  2. Use ovrHmd_CreateDistortionMesh to generate the distortion mesh.
 113.699 +//
 113.700 +//  3. Use ovrHmd_BeginFrameTiming, ovrHmd_GetEyePoses, and ovrHmd_BeginFrameTiming in
 113.701 +//     the rendering loop to obtain timing and predicted head orientation when rendering each eye.
 113.702 +//      - When using timewarp, use ovr_WaitTillTime after the rendering and gpu flush, followed
 113.703 +//        by ovrHmd_GetEyeTimewarpMatrices to obtain the timewarp matrices used
 113.704 +//        by the distortion pixel shader. This will minimize latency.
 113.705 +//
 113.706 +
 113.707 +/// Computes the distortion viewport, view adjust, and other rendering parameters for
 113.708 +/// the specified eye. This can be used instead of ovrHmd_ConfigureRendering to do
 113.709 +/// setup for client rendered distortion.
 113.710 +OVR_EXPORT ovrEyeRenderDesc ovrHmd_GetRenderDesc(ovrHmd hmd,
 113.711 +                                                 ovrEyeType eyeType, ovrFovPort fov);
 113.712 +
 113.713 +
 113.714 +/// Describes a vertex used by the distortion mesh. This is intended to be converted into
 113.715 +/// the engine-specific format. Some fields may be unused based on the ovrDistortionCaps
 113.716 +/// flags selected. TexG and TexB, for example, are not used if chromatic correction is
 113.717 +/// not requested.
 113.718 +typedef struct ovrDistortionVertex_
 113.719 +{
 113.720 +    ovrVector2f ScreenPosNDC;    ///< [-1,+1],[-1,+1] over the entire framebuffer.
 113.721 +    float       TimeWarpFactor;  ///< Lerp factor between time-warp matrices. Can be encoded in Pos.z.
 113.722 +    float       VignetteFactor;  ///< Vignette fade factor. Can be encoded in Pos.w.
 113.723 +    ovrVector2f TanEyeAnglesR;   ///< The tangents of the horizontal and vertical eye angles for the red channel.
 113.724 +	ovrVector2f TanEyeAnglesG;   ///< The tangents of the horizontal and vertical eye angles for the green channel.
 113.725 +	ovrVector2f TanEyeAnglesB;   ///< The tangents of the horizontal and vertical eye angles for the blue channel.
 113.726 +} ovrDistortionVertex;
 113.727 +
 113.728 +/// Describes a full set of distortion mesh data, filled in by ovrHmd_CreateDistortionMesh.
 113.729 +/// Contents of this data structure, if not null, should be freed by ovrHmd_DestroyDistortionMesh.
 113.730 +typedef struct ovrDistortionMesh_
 113.731 +{
 113.732 +    ovrDistortionVertex* pVertexData; ///< The distortion vertices representing each point in the mesh.
 113.733 +    unsigned short*      pIndexData;  ///< Indices for connecting the mesh vertices into polygons.
 113.734 +    unsigned int         VertexCount; ///< The number of vertices in the mesh.
 113.735 +    unsigned int         IndexCount;  ///< The number of indices in the mesh.
 113.736 +} ovrDistortionMesh;
 113.737 +
 113.738 +/// Generate distortion mesh per eye.
 113.739 +/// Distortion capabilities will depend on 'distortionCaps' flags. Users should 
 113.740 +/// render using the appropriate shaders based on their settings.
 113.741 +/// Distortion mesh data will be allocated and written into the ovrDistortionMesh data structure,
 113.742 +/// which should be explicitly freed with ovrHmd_DestroyDistortionMesh.
 113.743 +/// Users should call ovrHmd_GetRenderScaleAndOffset to get uvScale and Offset values for rendering.
 113.744 +/// The function shouldn't fail unless theres is a configuration or memory error, in which case
 113.745 +/// ovrDistortionMesh values will be set to null.
 113.746 +/// This is the only function in the SDK reliant on eye relief, currently imported from profiles,
 113.747 +/// or overridden here.
 113.748 +OVR_EXPORT ovrBool  ovrHmd_CreateDistortionMesh( ovrHmd hmd,
 113.749 +                                                 ovrEyeType eyeType, ovrFovPort fov,
 113.750 +                                                 unsigned int distortionCaps,
 113.751 +                                                 ovrDistortionMesh *meshData);
 113.752 +OVR_EXPORT ovrBool ovrHmd_CreateDistortionMeshDebug( ovrHmd hmddesc,
 113.753 +                                                     ovrEyeType eyeType, ovrFovPort fov,
 113.754 +                                                     unsigned int distortionCaps,
 113.755 +                                                     ovrDistortionMesh *meshData,
 113.756 +												     float debugEyeReliefOverrideInMetres);
 113.757 +
 113.758 +
 113.759 +/// Used to free the distortion mesh allocated by ovrHmd_GenerateDistortionMesh. meshData elements
 113.760 +/// are set to null and zeroes after the call.
 113.761 +OVR_EXPORT void     ovrHmd_DestroyDistortionMesh( ovrDistortionMesh* meshData );
 113.762 +
 113.763 +/// Computes updated 'uvScaleOffsetOut' to be used with a distortion if render target size or
 113.764 +/// viewport changes after the fact. This can be used to adjust render size every frame if desired.
 113.765 +OVR_EXPORT void     ovrHmd_GetRenderScaleAndOffset( ovrFovPort fov,
 113.766 +                                                    ovrSizei textureSize, ovrRecti renderViewport,
 113.767 +                                                    ovrVector2f uvScaleOffsetOut[2] );
 113.768 +
 113.769 +/// Thread-safe timing function for the main thread. Caller should increment frameIndex
 113.770 +/// with every frame and pass the index where applicable to functions called on the
 113.771 +/// rendering thread.
 113.772 +OVR_EXPORT ovrFrameTiming ovrHmd_GetFrameTiming(ovrHmd hmd, unsigned int frameIndex);
 113.773 +
 113.774 +/// Called at the beginning of the frame on the rendering thread.
 113.775 +/// Pass frameIndex == 0 if ovrHmd_GetFrameTiming isn't being used. Otherwise,
 113.776 +/// pass the same frame index as was used for GetFrameTiming on the main thread.
 113.777 +OVR_EXPORT ovrFrameTiming ovrHmd_BeginFrameTiming(ovrHmd hmd, unsigned int frameIndex);
 113.778 +
 113.779 +/// Marks the end of client distortion rendered frame, tracking the necessary timing information.
 113.780 +/// This function must be called immediately after Present/SwapBuffers + GPU sync. GPU sync is
 113.781 +/// important before this call to reduce latency and ensure proper timing.
 113.782 +OVR_EXPORT void     ovrHmd_EndFrameTiming(ovrHmd hmd);
 113.783 +
 113.784 +/// Initializes and resets frame time tracking. This is typically not necessary, but
 113.785 +/// is helpful if game changes vsync state or video mode. vsync is assumed to be on if this
 113.786 +/// isn't called. Resets internal frame index to the specified number.
 113.787 +OVR_EXPORT void     ovrHmd_ResetFrameTiming(ovrHmd hmd, unsigned int frameIndex);
 113.788 +
 113.789 +/// Computes timewarp matrices used by distortion mesh shader, these are used to adjust
 113.790 +/// for head orientation change since the last call to ovrHmd_GetEyePoses
 113.791 +/// when rendering this eye. The ovrDistortionVertex::TimeWarpFactor is used to blend between the
 113.792 +/// matrices, usually representing two different sides of the screen.
 113.793 +/// Must be called on the same thread as ovrHmd_BeginFrameTiming.
 113.794 +OVR_EXPORT void     ovrHmd_GetEyeTimewarpMatrices     (ovrHmd hmd, ovrEyeType eye,
 113.795 +                                                       ovrPosef renderPose, ovrMatrix4f twmOut[2]);
 113.796 +OVR_EXPORT void     ovrHmd_GetEyeTimewarpMatricesDebug(ovrHmd hmd, ovrEyeType eye,
 113.797 +                                                       ovrPosef renderPose, ovrMatrix4f twmOut[2],
 113.798 +													   double debugTimingOffsetInSeconds);
 113.799 +
 113.800 +
 113.801 +
 113.802 +
 113.803 +//-------------------------------------------------------------------------------------
 113.804 +// ***** Stateless math setup functions
 113.805 +
 113.806 +/// Used to generate projection from ovrEyeDesc::Fov.
 113.807 +OVR_EXPORT ovrMatrix4f ovrMatrix4f_Projection( ovrFovPort fov,
 113.808 +                                               float znear, float zfar, ovrBool rightHanded );
 113.809 +
 113.810 +/// Used for 2D rendering, Y is down
 113.811 +/// orthoScale = 1.0f / pixelsPerTanAngleAtCenter
 113.812 +/// orthoDistance = distance from camera, such as 0.8m
 113.813 +OVR_EXPORT ovrMatrix4f ovrMatrix4f_OrthoSubProjection(ovrMatrix4f projection, ovrVector2f orthoScale,
 113.814 +                                                      float orthoDistance, float hmdToEyeViewOffsetX);
 113.815 +
 113.816 +/// Returns global, absolute high-resolution time in seconds. This is the same
 113.817 +/// value as used in sensor messages.
 113.818 +OVR_EXPORT double   ovr_GetTimeInSeconds();
 113.819 +
 113.820 +/// Waits until the specified absolute time.
 113.821 +OVR_EXPORT double   ovr_WaitTillTime(double absTime);
 113.822 +
 113.823 +// -----------------------------------------------------------------------------------
 113.824 +// ***** Latency Test interface
 113.825 +
 113.826 +/// Does latency test processing and returns 'TRUE' if specified rgb color should
 113.827 +/// be used to clear the screen.
 113.828 +OVR_EXPORT ovrBool      ovrHmd_ProcessLatencyTest(ovrHmd hmd, unsigned char rgbColorOut[3]);
 113.829 +
 113.830 +/// Returns non-null string once with latency test result, when it is available.
 113.831 +/// Buffer is valid until next call.
 113.832 +OVR_EXPORT const char*  ovrHmd_GetLatencyTestResult(ovrHmd hmd);
 113.833 +
 113.834 +/// Returns the latency testing color in rgbColorOut to render when using a DK2
 113.835 +/// Returns false if this feature is disabled or not-applicable (e.g. using a DK1)
 113.836 +OVR_EXPORT ovrBool      ovrHmd_GetLatencyTest2DrawColor(ovrHmd hmddesc, unsigned char rgbColorOut[3]);
 113.837 +
 113.838 +//-------------------------------------------------------------------------------------
 113.839 +// ***** Health and Safety Warning Display interface
 113.840 +//
 113.841 +
 113.842 +/// Used by ovrhmd_GetHSWDisplayState to report the current display state.
 113.843 +typedef struct ovrHSWDisplayState_
 113.844 +{
 113.845 +    /// If true then the warning should be currently visible
 113.846 +    /// and the following variables have meaning. Else there is no
 113.847 +    /// warning being displayed for this application on the given HMD.
 113.848 +    ovrBool Displayed;       ///< True if the Health&Safety Warning is currently displayed.
 113.849 +    double  StartTime;       ///< Absolute time when the warning was first displayed. See ovr_GetTimeInSeconds().
 113.850 +    double  DismissibleTime; ///< Earliest absolute time when the warning can be dismissed. May be a time in the past.
 113.851 +} ovrHSWDisplayState;
 113.852 +
 113.853 +/// Returns the current state of the HSW display. If the application is doing the rendering of
 113.854 +/// the HSW display then this function serves to indicate that the warning should be
 113.855 +/// currently displayed. If the application is using SDK-based eye rendering then the SDK by
 113.856 +/// default automatically handles the drawing of the HSW display. An application that uses
 113.857 +/// application-based eye rendering should use this function to know when to start drawing the
 113.858 +/// HSW display itself and can optionally use it in conjunction with ovrhmd_DismissHSWDisplay
 113.859 +/// as described below.
 113.860 +///
 113.861 +/// Example usage for application-based rendering:
 113.862 +///    bool HSWDisplayCurrentlyDisplayed = false; // global or class member variable
 113.863 +///    ovrHSWDisplayState hswDisplayState;
 113.864 +///    ovrhmd_GetHSWDisplayState(Hmd, &hswDisplayState);
 113.865 +///
 113.866 +///    if (hswDisplayState.Displayed && !HSWDisplayCurrentlyDisplayed) {
 113.867 +///        <insert model into the scene that stays in front of the user>
 113.868 +///        HSWDisplayCurrentlyDisplayed = true;
 113.869 +///    }
 113.870 +OVR_EXPORT void ovrHmd_GetHSWDisplayState(ovrHmd hmd, ovrHSWDisplayState *hasWarningState);
 113.871 +
 113.872 +/// Dismisses the HSW display if the warning is dismissible and the earliest dismissal time
 113.873 +/// has occurred. Returns true if the display is valid and could be dismissed. The application
 113.874 +/// should recognize that the HSW display is being displayed (via ovrhmd_GetHSWDisplayState)
 113.875 +/// and if so then call this function when the appropriate user input to dismiss the warning
 113.876 +/// occurs.
 113.877 +///
 113.878 +/// Example usage :
 113.879 +///    void ProcessEvent(int key) {
 113.880 +///        if (key == escape) {
 113.881 +///            ovrHSWDisplayState hswDisplayState;
 113.882 +///            ovrhmd_GetHSWDisplayState(hmd, &hswDisplayState);
 113.883 +///
 113.884 +///            if (hswDisplayState.Displayed && ovrhmd_DismissHSWDisplay(hmd)) {
 113.885 +///                <remove model from the scene>
 113.886 +///                HSWDisplayCurrentlyDisplayed = false;
 113.887 +///            }
 113.888 +///        }
 113.889 +///    }
 113.890 +OVR_EXPORT ovrBool ovrHmd_DismissHSWDisplay(ovrHmd hmd);
 113.891 +
 113.892 +/// Get boolean property. Returns first element if property is a boolean array.
 113.893 +/// Returns defaultValue if property doesn't exist.
 113.894 +OVR_EXPORT ovrBool      ovrHmd_GetBool(ovrHmd hmd, const char* propertyName, ovrBool defaultVal);
 113.895 +
 113.896 +/// Modify bool property; false if property doesn't exist or is readonly.
 113.897 +OVR_EXPORT ovrBool      ovrHmd_SetBool(ovrHmd hmd, const char* propertyName, ovrBool value);
 113.898 +
 113.899 +/// Get integer property. Returns first element if property is an integer array.
 113.900 +/// Returns defaultValue if property doesn't exist.
 113.901 +OVR_EXPORT int          ovrHmd_GetInt(ovrHmd hmd, const char* propertyName, int defaultVal);
 113.902 +
 113.903 +/// Modify integer property; false if property doesn't exist or is readonly.
 113.904 +OVR_EXPORT ovrBool      ovrHmd_SetInt(ovrHmd hmd, const char* propertyName, int value);
 113.905 +
 113.906 +/// Get float property. Returns first element if property is a float array.
 113.907 +/// Returns defaultValue if property doesn't exist.
 113.908 +OVR_EXPORT float        ovrHmd_GetFloat(ovrHmd hmd, const char* propertyName, float defaultVal);
 113.909 +
 113.910 +/// Modify float property; false if property doesn't exist or is readonly.
 113.911 +OVR_EXPORT ovrBool      ovrHmd_SetFloat(ovrHmd hmd, const char* propertyName, float value);
 113.912 +
 113.913 +/// Get float[] property. Returns the number of elements filled in, 0 if property doesn't exist.
 113.914 +/// Maximum of arraySize elements will be written.
 113.915 +OVR_EXPORT unsigned int ovrHmd_GetFloatArray(ovrHmd hmd, const char* propertyName,
 113.916 +                                            float values[], unsigned int arraySize);
 113.917 +
 113.918 +/// Modify float[] property; false if property doesn't exist or is readonly.
 113.919 +OVR_EXPORT ovrBool      ovrHmd_SetFloatArray(ovrHmd hmd, const char* propertyName,
 113.920 +                                             float values[], unsigned int arraySize);
 113.921 +
 113.922 +/// Get string property. Returns first element if property is a string array.
 113.923 +/// Returns defaultValue if property doesn't exist.
 113.924 +/// String memory is guaranteed to exist until next call to GetString or GetStringArray, or HMD is destroyed.
 113.925 +OVR_EXPORT const char*  ovrHmd_GetString(ovrHmd hmd, const char* propertyName,
 113.926 +                                        const char* defaultVal);
 113.927 +
 113.928 +/// Set string property
 113.929 +OVR_EXPORT ovrBool ovrHmd_SetString(ovrHmd hmddesc, const char* propertyName,
 113.930 +                                    const char* value);
 113.931 +
 113.932 +// -----------------------------------------------------------------------------------
 113.933 +// ***** Logging
 113.934 +
 113.935 +/// Start performance logging. guid is optional and if included is written with each file entry.
 113.936 +/// If called while logging is already active with the same filename, only the guid will be updated
 113.937 +/// If called while logging is already active with a different filename, ovrHmd_StopPerfLog() will be called, followed by ovrHmd_StartPerfLog()
 113.938 +OVR_EXPORT ovrBool ovrHmd_StartPerfLog(ovrHmd hmd, const char* fileName, const char* userData1);
 113.939 +/// Stop performance logging.
 113.940 +OVR_EXPORT ovrBool ovrHmd_StopPerfLog(ovrHmd hmd);
 113.941 +
 113.942 +
 113.943 +#ifdef __cplusplus
 113.944 +} // extern "C"
 113.945 +#endif
 113.946 +
 113.947 +
 113.948 +#if defined(_MSC_VER)
 113.949 +    #pragma warning(pop)
 113.950 +#endif
 113.951 +
 113.952 +
 113.953 +#endif // OVR_CAPI_h
   114.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   114.2 +++ b/LibOVR/Src/OVR_CAPI_GL.h	Wed Jan 14 06:51:16 2015 +0200
   114.3 @@ -0,0 +1,76 @@
   114.4 +/************************************************************************************
   114.5 +
   114.6 +Filename    :   OVR_CAPI_GL.h
   114.7 +Content     :   GL specific structures used by the CAPI interface.
   114.8 +Created     :   November 7, 2013
   114.9 +Authors     :   Lee Cooper
  114.10 +
  114.11 +Copyright   :   Copyright 2013 Oculus VR, LLC. All Rights reserved.
  114.12 +
  114.13 +Use of this software is subject to the terms of the Oculus Inc license
  114.14 +agreement provided at the time of installation or download, or which
  114.15 +otherwise accompanies this software in either electronic or hard copy form.
  114.16 +
  114.17 +************************************************************************************/
  114.18 +#ifndef OVR_CAPI_GL_h
  114.19 +#define OVR_CAPI_GL_h
  114.20 +
  114.21 +/// @file OVR_CAPI_GL.h
  114.22 +/// OpenGL rendering support.
  114.23 +
  114.24 +#include "OVR_CAPI.h"
  114.25 +#if defined(__APPLE__)
  114.26 +    #include <OpenGL/gl.h>
  114.27 +#else
  114.28 +    #include <GL/gl.h>
  114.29 +#endif
  114.30 +
  114.31 +
  114.32 +/// Used to configure slave GL rendering (i.e. for devices created externally).
  114.33 +typedef struct OVR_ALIGNAS(8) ovrGLConfigData_s
  114.34 +{
  114.35 +    /// General device settings.
  114.36 +    ovrRenderAPIConfigHeader Header;
  114.37 +
  114.38 +#if defined(OVR_OS_WIN32)
  114.39 +    /// The optional window handle. If unset, rendering will use the current window.
  114.40 +    HWND Window;
  114.41 +    /// The optional device context. If unset, rendering will use a new context.
  114.42 +    HDC  DC;
  114.43 +#elif defined (OVR_OS_LINUX)
  114.44 +    /// Optional display. If unset, will issue glXGetCurrentDisplay when context
  114.45 +    /// is current.
  114.46 +    struct _XDisplay* Disp;
  114.47 +#endif
  114.48 +} ovrGLConfigData;
  114.49 +
  114.50 +/// Contains OpenGL-specific rendering information.
  114.51 +union ovrGLConfig
  114.52 +{
  114.53 +    /// General device settings.
  114.54 +    ovrRenderAPIConfig Config;
  114.55 +    /// OpenGL-specific settings.
  114.56 +    ovrGLConfigData    OGL;
  114.57 +};
  114.58 +
  114.59 +/// Used to pass GL eye texture data to ovrHmd_EndFrame.
  114.60 +typedef struct OVR_ALIGNAS(8) ovrGLTextureData_s
  114.61 +{
  114.62 +    /// General device settings.
  114.63 +    ovrTextureHeader Header;
  114.64 +    /// The OpenGL name for this texture.
  114.65 +    GLuint           TexId;       
  114.66 +} ovrGLTextureData;
  114.67 +
  114.68 +static_assert(offsetof(ovrGLTextureData, TexId) == offsetof(ovrTexture, PlatformData), "Mismatch of structs that are presumed binary equivalents.");
  114.69 +
  114.70 +/// Contains OpenGL-specific texture information.
  114.71 +typedef union ovrGLTexture_s
  114.72 +{
  114.73 +    /// General device settings.
  114.74 +    ovrTexture       Texture;
  114.75 +    /// OpenGL-specific settings.
  114.76 +    ovrGLTextureData OGL;
  114.77 +} ovrGLTexture;
  114.78 +
  114.79 +#endif	// OVR_CAPI_GL_h
   115.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   115.2 +++ b/LibOVR/Src/OVR_CAPI_Keys.h	Wed Jan 14 06:51:16 2015 +0200
   115.3 @@ -0,0 +1,56 @@
   115.4 +/************************************************************************************
   115.5 +
   115.6 +Filename    :   OVR_CAPI.h
   115.7 +Content     :   Keys for CAPI calls
   115.8 +Created     :   September 25, 2014
   115.9 +Authors     :   
  115.10 +
  115.11 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
  115.12 +
  115.13 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License");
  115.14 +you may not use the Oculus VR Rift SDK except in compliance with the License,
  115.15 +which is provided at the time of installation or download, or which
  115.16 +otherwise accompanies this software in either electronic or hard copy form.
  115.17 +
  115.18 +You may obtain a copy of the License at
  115.19 +
  115.20 +http://www.oculusvr.com/licenses/LICENSE-3.2
  115.21 +
  115.22 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK
  115.23 +distributed under the License is distributed on an "AS IS" BASIS,
  115.24 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  115.25 +See the License for the specific language governing permissions and
  115.26 +limitations under the License.
  115.27 +
  115.28 +************************************************************************************/
  115.29 +
  115.30 +
  115.31 +
  115.32 +#define OVR_KEY_USER                        "User"              // string
  115.33 +#define OVR_KEY_NAME                        "Name"              // string
  115.34 +#define OVR_KEY_GENDER                      "Gender"            // string
  115.35 +#define OVR_KEY_PLAYER_HEIGHT               "PlayerHeight"      // float
  115.36 +#define OVR_KEY_EYE_HEIGHT                  "EyeHeight"         // float
  115.37 +#define OVR_KEY_IPD                         "IPD"               // float
  115.38 +#define OVR_KEY_NECK_TO_EYE_DISTANCE        "NeckEyeDistance"   // float[2]
  115.39 +#define OVR_KEY_EYE_RELIEF_DIAL             "EyeReliefDial"     // int
  115.40 +#define OVR_KEY_EYE_TO_NOSE_DISTANCE        "EyeToNoseDist"     // float[2]
  115.41 +#define OVR_KEY_MAX_EYE_TO_PLATE_DISTANCE   "MaxEyeToPlateDist" // float[2]
  115.42 +#define OVR_KEY_EYE_CUP                     "EyeCup"            // char[16]
  115.43 +#define OVR_KEY_CUSTOM_EYE_RENDER           "CustomEyeRender"   // bool
  115.44 +#define OVR_KEY_CAMERA_POSITION				"CenteredFromWorld" // double[7]
  115.45 +
  115.46 +// Default measurements empirically determined at Oculus to make us happy
  115.47 +// The neck model numbers were derived as an average of the male and female averages from ANSUR-88
  115.48 +// NECK_TO_EYE_HORIZONTAL = H22 - H43 = INFRAORBITALE_BACK_OF_HEAD - TRAGION_BACK_OF_HEAD
  115.49 +// NECK_TO_EYE_VERTICAL = H21 - H15 = GONION_TOP_OF_HEAD - ECTOORBITALE_TOP_OF_HEAD
  115.50 +// These were determined to be the best in a small user study, clearly beating out the previous default values
  115.51 +#define OVR_DEFAULT_GENDER                  "Unknown"
  115.52 +#define OVR_DEFAULT_PLAYER_HEIGHT           1.778f
  115.53 +#define OVR_DEFAULT_EYE_HEIGHT              1.675f
  115.54 +#define OVR_DEFAULT_IPD                     0.064f
  115.55 +#define OVR_DEFAULT_NECK_TO_EYE_HORIZONTAL  0.0805f
  115.56 +#define OVR_DEFAULT_NECK_TO_EYE_VERTICAL    0.075f
  115.57 +#define OVR_DEFAULT_EYE_RELIEF_DIAL         3
  115.58 +#define OVR_DEFAULT_CAMERA_POSITION			{0,0,0,1,0,0,0}
  115.59 +
   116.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   116.2 +++ b/LibOVR/Src/OVR_JSON.cpp	Wed Jan 14 06:51:16 2015 +0200
   116.3 @@ -0,0 +1,1287 @@
   116.4 +/************************************************************************************
   116.5 +
   116.6 +PublicHeader:   None
   116.7 +Filename    :   OVR_JSON.h
   116.8 +Content     :   JSON format reader and writer
   116.9 +Created     :   April 9, 2013
  116.10 +Author      :   Brant Lewis
  116.11 +Notes       :
  116.12 +  The code is a derivative of the cJSON library written by Dave Gamble and subject 
  116.13 +  to the following permissive copyright.
  116.14 +
  116.15 +  Copyright (c) 2009 Dave Gamble
  116.16 + 
  116.17 +  Permission is hereby granted, free of charge, to any person obtaining a copy
  116.18 +  of this software and associated documentation files (the "Software"), to deal
  116.19 +  in the Software without restriction, including without limitation the rights
  116.20 +  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  116.21 +  copies of the Software, and to permit persons to whom the Software is
  116.22 +  furnished to do so, subject to the following conditions:
  116.23 + 
  116.24 +  The above copyright notice and this permission notice shall be included in
  116.25 +  all copies or substantial portions of the Software.
  116.26 + 
  116.27 +  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  116.28 +  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  116.29 +  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  116.30 +  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  116.31 +  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  116.32 +  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  116.33 +  THE SOFTWARE.
  116.34 +
  116.35 +
  116.36 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
  116.37 +
  116.38 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
  116.39 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
  116.40 +which is provided at the time of installation or download, or which 
  116.41 +otherwise accompanies this software in either electronic or hard copy form.
  116.42 +
  116.43 +You may obtain a copy of the License at
  116.44 +
  116.45 +http://www.oculusvr.com/licenses/LICENSE-3.2 
  116.46 +
  116.47 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
  116.48 +distributed under the License is distributed on an "AS IS" BASIS,
  116.49 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  116.50 +See the License for the specific language governing permissions and
  116.51 +limitations under the License.
  116.52 +
  116.53 +************************************************************************************/
  116.54 +
  116.55 +#include <string.h>
  116.56 +#include <stdio.h>
  116.57 +#include <math.h>
  116.58 +#include <stdlib.h>
  116.59 +#include <float.h>
  116.60 +#include <limits.h>
  116.61 +#include <ctype.h>
  116.62 +#include "OVR_JSON.h"
  116.63 +#include "Kernel/OVR_SysFile.h"
  116.64 +#include "Kernel/OVR_Log.h"
  116.65 +
  116.66 +#ifdef OVR_OS_LINUX
  116.67 +#include <locale.h>
  116.68 +#endif
  116.69 +
  116.70 +namespace OVR {
  116.71 +
  116.72 +
  116.73 +//-----------------------------------------------------------------------------
  116.74 +// Create a new copy of a string
  116.75 +static char* JSON_strdup(const char* str)
  116.76 +{
  116.77 +    size_t len  = OVR_strlen(str) + 1;
  116.78 +    char* copy = (char*)OVR_ALLOC(len);
  116.79 +    if (!copy)
  116.80 +        return 0;
  116.81 +    memcpy(copy, str, len);
  116.82 +    return copy;
  116.83 +}
  116.84 +
  116.85 +
  116.86 +//-----------------------------------------------------------------------------
  116.87 +// Render the number from the given item into a string.
  116.88 +static char* PrintInt(int valueint)
  116.89 +{
  116.90 +    char *str;
  116.91 +    str = (char*)OVR_ALLOC(21);	// 2^64+1 can be represented in 21 chars.
  116.92 +    if (str)
  116.93 +    {
  116.94 +        OVR_sprintf(str, 21, "%d", valueint);
  116.95 +    }
  116.96 +    return str;
  116.97 +}
  116.98 +
  116.99 +
 116.100 +//-----------------------------------------------------------------------------
 116.101 +// Render the number from the given item into a string.
 116.102 +static char* PrintNumber(double d)
 116.103 +{
 116.104 +    char *str;
 116.105 +    int valueint = (int)d;
 116.106 +	if (fabs(((double)valueint)-d)<=DBL_EPSILON && d<=INT_MAX && d>=INT_MIN)
 116.107 +	{
 116.108 +        return PrintInt(valueint);
 116.109 +	}
 116.110 +	else
 116.111 +	{
 116.112 +		str=(char*)OVR_ALLOC(64);	// This is a nice tradeoff.
 116.113 +		if (str)
 116.114 +		{
 116.115 +			if (fabs(floor(d)-d)<=DBL_EPSILON && fabs(d)<1.0e60)
 116.116 +                OVR_sprintf(str, 64, "%.0f", d);
 116.117 +			else if (fabs(d)<1.0e-6 || fabs(d)>1.0e9)
 116.118 +                OVR_sprintf(str, 64, "%e", d);
 116.119 +			else
 116.120 +                OVR_sprintf(str, 64, "%f", d);
 116.121 +		}
 116.122 +	}
 116.123 +	return str;
 116.124 +}
 116.125 +
 116.126 +
 116.127 +// Parse the input text into an un-escaped cstring, and populate item.
 116.128 +static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
 116.129 +
 116.130 +// Helper to assign error sting and return 0.
 116.131 +const char* AssignError(const char** perror, const char *errorMessage)
 116.132 +{
 116.133 +    if (perror)
 116.134 +        *perror = errorMessage;
 116.135 +    return 0;
 116.136 +}
 116.137 +
 116.138 +//-----------------------------------------------------------------------------
 116.139 +// ***** JSON Node class
 116.140 +
 116.141 +JSON::JSON(JSONItemType itemType) :
 116.142 +    Type(itemType), dValue(0.)
 116.143 +{
 116.144 +}
 116.145 +
 116.146 +JSON::~JSON()
 116.147 +{
 116.148 +    JSON* child = Children.GetFirst();
 116.149 +    while (!Children.IsNull(child))
 116.150 +    {
 116.151 +        child->RemoveNode();
 116.152 +        child->Release();
 116.153 +        child = Children.GetFirst();
 116.154 +    }
 116.155 +}
 116.156 +
 116.157 +//-----------------------------------------------------------------------------
 116.158 +// Parse the input text to generate a number, and populate the result into item
 116.159 +// Returns the text position after the parsed number
 116.160 +const char* JSON::parseNumber(const char *num)
 116.161 +{
 116.162 +    const char* num_start = num;
 116.163 +    double      n=0, scale=0;
 116.164 +    int         subscale     = 0,
 116.165 +                signsubscale = 1;
 116.166 +    bool positiveSign = true;
 116.167 +    char localeSeparator = '.';
 116.168 +
 116.169 +#ifdef OVR_OS_LINUX
 116.170 +    // We should switch to a locale aware parsing function, such as atof. We
 116.171 +    // will probably want to go farther and enforce the 'C' locale on all JSON
 116.172 +    // output/input.
 116.173 +    struct lconv* localeConv = localeconv();
 116.174 +    localeSeparator = localeConv->decimal_point[0];
 116.175 +#endif
 116.176 +
 116.177 +    // Could use sscanf for this?
 116.178 +    if (*num == '-')
 116.179 +    {
 116.180 +        positiveSign = false;
 116.181 +        num++;	// Has sign?
 116.182 +    }
 116.183 +    if (*num == '0')
 116.184 +    {
 116.185 +        num++;			// is zero
 116.186 +    }
 116.187 +
 116.188 +    if (*num>='1' && *num<='9')	
 116.189 +    {
 116.190 +        do
 116.191 +        {
 116.192 +            n = (n*10.0) + (*num++ - '0');
 116.193 +        }
 116.194 +        while (*num>='0' && *num<='9');	// Number?
 116.195 +    }
 116.196 +
 116.197 +    if ((*num=='.' || *num==localeSeparator) && num[1]>='0' && num[1]<='9')
 116.198 +    {
 116.199 +        num++;
 116.200 +        do
 116.201 +        {
 116.202 +            n=(n*10.0)+(*num++ -'0');
 116.203 +            scale--;
 116.204 +        }
 116.205 +        while (*num>='0' && *num<='9');  // Fractional part?
 116.206 +    }
 116.207 +
 116.208 +	if (*num=='e' || *num=='E')		// Exponent?
 116.209 +	{
 116.210 +        num++;
 116.211 +        if (*num == '+')
 116.212 +        {
 116.213 +            num++;
 116.214 +        }
 116.215 +        else if (*num=='-')
 116.216 +        {
 116.217 +            signsubscale=-1;
 116.218 +            num++;		// With sign?
 116.219 +        }
 116.220 +
 116.221 +        while (*num >= '0' && *num <= '9')
 116.222 +        {
 116.223 +            subscale = (subscale * 10) + (*num++ - '0');	// Number?
 116.224 +        }
 116.225 +	}
 116.226 +
 116.227 +    // Number = +/- number.fraction * 10^+/- exponent
 116.228 +    n *= pow(10.0, (scale + subscale*signsubscale));
 116.229 +
 116.230 +    if (!positiveSign)
 116.231 +    {
 116.232 +        n = -n;
 116.233 +    }
 116.234 +
 116.235 +    // Assign parsed value.
 116.236 +    Type = JSON_Number;
 116.237 +    dValue = n;
 116.238 +    Value.AssignString(num_start, num - num_start);
 116.239 +
 116.240 +	return num;
 116.241 +}
 116.242 +
 116.243 +// Parses a hex string up to the specified number of digits.
 116.244 +// Returns the first character after the string.
 116.245 +const char* ParseHex(unsigned* val, unsigned digits, const char* str)
 116.246 +{
 116.247 +    *val = 0;
 116.248 +
 116.249 +    for(unsigned digitCount = 0; digitCount < digits; digitCount++, str++)
 116.250 +    {
 116.251 +        unsigned v = *str;
 116.252 +
 116.253 +        if ((v >= '0') && (v <= '9'))
 116.254 +            v -= '0';
 116.255 +        else if ((v >= 'a') && (v <= 'f'))
 116.256 +            v = 10 + v - 'a';
 116.257 +        else if ((v >= 'A') && (v <= 'F'))
 116.258 +            v = 10 + v - 'A';
 116.259 +        else
 116.260 +            break;
 116.261 +
 116.262 +        *val = *val * 16 + v;
 116.263 +    }
 116.264 +
 116.265 +    return str;
 116.266 +}
 116.267 +
 116.268 +//-----------------------------------------------------------------------------
 116.269 +// Parses the input text into a string item and returns the text position after
 116.270 +// the parsed string
 116.271 +const char* JSON::parseString(const char* str, const char** perror)
 116.272 +{
 116.273 +	const char* ptr = str+1;
 116.274 +    const char* p;
 116.275 +    char*       ptr2;
 116.276 +    char*       out;
 116.277 +    int         len=0;
 116.278 +    unsigned    uc, uc2;
 116.279 +	
 116.280 +    if (*str!='\"')
 116.281 +    {
 116.282 +        return AssignError(perror, "Syntax Error: Missing quote");
 116.283 +    }
 116.284 +	
 116.285 +	while (*ptr!='\"' && *ptr && ++len)
 116.286 +    {   
 116.287 +        if (*ptr++ == '\\') ptr++;	// Skip escaped quotes.
 116.288 +    }
 116.289 +	
 116.290 +    // This is how long we need for the string, roughly.
 116.291 +	out=(char*)OVR_ALLOC(len+1);
 116.292 +	if (!out)
 116.293 +        return 0;
 116.294 +	
 116.295 +	ptr = str+1;
 116.296 +    ptr2= out;
 116.297 +
 116.298 +	while (*ptr!='\"' && *ptr)
 116.299 +	{
 116.300 +		if (*ptr!='\\')
 116.301 +        {
 116.302 +            *ptr2++ = *ptr++;
 116.303 +        }
 116.304 +		else
 116.305 +		{
 116.306 +			ptr++;
 116.307 +			switch (*ptr)
 116.308 +			{
 116.309 +				case 'b': *ptr2++ = '\b';	break;
 116.310 +				case 'f': *ptr2++ = '\f';	break;
 116.311 +				case 'n': *ptr2++ = '\n';	break;
 116.312 +				case 'r': *ptr2++ = '\r';	break;
 116.313 +				case 't': *ptr2++ = '\t';	break;
 116.314 +
 116.315 +                // Transcode utf16 to utf8.
 116.316 +                case 'u':
 116.317 +
 116.318 +                    // Get the unicode char.
 116.319 +                    p = ParseHex(&uc, 4, ptr + 1);
 116.320 +                    if (ptr != p)
 116.321 +                        ptr = p - 1;
 116.322 +
 116.323 +					if ((uc>=0xDC00 && uc<=0xDFFF) || uc==0)
 116.324 +                        break;	// Check for invalid.
 116.325 +
 116.326 +                    // UTF16 surrogate pairs.
 116.327 +					if (uc>=0xD800 && uc<=0xDBFF)
 116.328 +					{
 116.329 +						if (ptr[1]!='\\' || ptr[2]!='u')
 116.330 +                            break;	// Missing second-half of surrogate.
 116.331 +
 116.332 +                        p= ParseHex(&uc2, 4, ptr + 3);
 116.333 +                        if (ptr != p)
 116.334 +                            ptr = p - 1;
 116.335 +                        
 116.336 +						if (uc2<0xDC00 || uc2>0xDFFF)
 116.337 +                            break;	// Invalid second-half of surrogate.
 116.338 +
 116.339 +						uc = 0x10000 + (((uc&0x3FF)<<10) | (uc2&0x3FF));
 116.340 +					}
 116.341 +
 116.342 +					len=4;
 116.343 +                    
 116.344 +                    if (uc<0x80)
 116.345 +                        len=1;
 116.346 +                    else if (uc<0x800)
 116.347 +                        len=2;
 116.348 +                    else if (uc<0x10000)
 116.349 +                        len=3;
 116.350 +                    
 116.351 +                    ptr2+=len;
 116.352 +					
 116.353 +					switch (len)
 116.354 +                    {
 116.355 +						case 4: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
 116.356 +							//no break, fall through
 116.357 +						case 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
 116.358 +							//no break
 116.359 +						case 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
 116.360 +							//no break
 116.361 +						case 1: *--ptr2 = (char)(uc | firstByteMark[len]);
 116.362 +							//no break
 116.363 +					}
 116.364 +					ptr2+=len;
 116.365 +					break;
 116.366 +
 116.367 +                default:
 116.368 +                    *ptr2++ = *ptr;
 116.369 +                    break;
 116.370 +			}
 116.371 +			ptr++;
 116.372 +		}
 116.373 +	}
 116.374 +
 116.375 +	*ptr2 = 0;
 116.376 +	if (*ptr=='\"')
 116.377 +        ptr++;
 116.378 +	
 116.379 +    // Make a copy of the string 
 116.380 +    Value=out;
 116.381 +    OVR_FREE(out);
 116.382 +	Type=JSON_String;
 116.383 +
 116.384 +	return ptr;
 116.385 +}
 116.386 +
 116.387 +//-----------------------------------------------------------------------------
 116.388 +// Render the string provided to an escaped version that can be printed.
 116.389 +char* PrintString(const char* str)
 116.390 +{
 116.391 +	const char *ptr;
 116.392 +    char *ptr2,*out;
 116.393 +    int len=0;
 116.394 +    unsigned char token;
 116.395 +	
 116.396 +	if (!str)
 116.397 +        return JSON_strdup("");
 116.398 +	ptr=str;
 116.399 +    
 116.400 +    token=*ptr;
 116.401 +    while (token && ++len)\
 116.402 +    {
 116.403 +        if (strchr("\"\\\b\f\n\r\t",token))
 116.404 +            len++;
 116.405 +        else if (token<32) 
 116.406 +            len+=5;
 116.407 +        ptr++;
 116.408 +        token=*ptr;
 116.409 +    }
 116.410 +	
 116.411 +	int buff_size = len+3;
 116.412 +    out=(char*)OVR_ALLOC(buff_size);
 116.413 +	if (!out)
 116.414 +        return 0;
 116.415 +
 116.416 +	ptr2 = out;
 116.417 +    ptr  = str;
 116.418 +	*ptr2++ = '\"';
 116.419 +
 116.420 +	while (*ptr)
 116.421 +	{
 116.422 +		if ((unsigned char)*ptr>31 && *ptr!='\"' && *ptr!='\\') 
 116.423 +            *ptr2++=*ptr++;
 116.424 +		else
 116.425 +		{
 116.426 +			*ptr2++='\\';
 116.427 +			switch (token=*ptr++)
 116.428 +			{
 116.429 +				case '\\':	*ptr2++='\\';	break;
 116.430 +				case '\"':	*ptr2++='\"';	break;
 116.431 +				case '\b':	*ptr2++='b';	break;
 116.432 +				case '\f':	*ptr2++='f';	break;
 116.433 +				case '\n':	*ptr2++='n';	break;
 116.434 +				case '\r':	*ptr2++='r';	break;
 116.435 +				case '\t':	*ptr2++='t';	break;
 116.436 +				default: 
 116.437 +                    OVR_sprintf(ptr2, buff_size - (ptr2-out), "u%04x",token);
 116.438 +                    ptr2+=5;
 116.439 +                    break;	// Escape and print.
 116.440 +			}
 116.441 +		}
 116.442 +	}
 116.443 +	*ptr2++='\"';
 116.444 +    *ptr2++=0;
 116.445 +	return out;
 116.446 +}
 116.447 +
 116.448 +//-----------------------------------------------------------------------------
 116.449 +// Utility to jump whitespace and cr/lf
 116.450 +static const char* skip(const char* in)
 116.451 +{
 116.452 +    while (in && *in && (unsigned char)*in<=' ') 
 116.453 +        in++; 
 116.454 +    return in;
 116.455 +}
 116.456 +
 116.457 +//-----------------------------------------------------------------------------
 116.458 +// Parses the supplied buffer of JSON text and returns a JSON object tree
 116.459 +// The returned object must be Released after use
 116.460 +JSON* JSON::Parse(const char* buff, const char** perror)
 116.461 +{
 116.462 +    const char* end = 0;
 116.463 +	JSON*       json = new JSON();
 116.464 +	
 116.465 +	if (!json)
 116.466 +    {
 116.467 +        AssignError(perror, "Error: Failed to allocate memory");
 116.468 +        return 0;
 116.469 +    }
 116.470 + 
 116.471 +	end = json->parseValue(skip(buff), perror);
 116.472 +	if (!end)
 116.473 +    {
 116.474 +        json->Release();
 116.475 +        return NULL;
 116.476 +    }	// parse failure. ep is set.
 116.477 +
 116.478 +    return json;
 116.479 +}
 116.480 +
 116.481 +//-----------------------------------------------------------------------------
 116.482 +// This version works for buffers that are not null terminated strings.
 116.483 +JSON* JSON::ParseBuffer(const char *buff, int len, const char** perror)
 116.484 +{
 116.485 +	// Our JSON parser does not support length-based parsing,
 116.486 +	// so ensure it is null-terminated.
 116.487 +	char *termStr = new char[len + 1];
 116.488 +	memcpy(termStr, buff, len);
 116.489 +	termStr[len] = '\0';
 116.490 +
 116.491 +	JSON *objJson = Parse(termStr, perror);
 116.492 +
 116.493 +	delete[]termStr;
 116.494 +
 116.495 +	return objJson;
 116.496 +}
 116.497 +
 116.498 +//-----------------------------------------------------------------------------
 116.499 +// Parser core - when encountering text, process appropriately.
 116.500 +const char* JSON::parseValue(const char* buff, const char** perror)
 116.501 +{
 116.502 +    if (perror)
 116.503 +        *perror = 0;
 116.504 +
 116.505 +	if (!buff)
 116.506 +        return NULL;	// Fail on null.
 116.507 +
 116.508 +	if (!strncmp(buff,"null",4))
 116.509 +    {
 116.510 +        Type = JSON_Null;
 116.511 +        return buff+4;
 116.512 +    }
 116.513 +	if (!strncmp(buff,"false",5))
 116.514 +    { 
 116.515 +        Type   = JSON_Bool;
 116.516 +        Value  = "false";
 116.517 +        dValue = 0.;
 116.518 +        return buff+5;
 116.519 +    }
 116.520 +	if (!strncmp(buff,"true",4))
 116.521 +    {
 116.522 +        Type   = JSON_Bool;
 116.523 +        Value  = "true";
 116.524 +        dValue = 1.;
 116.525 +        return buff + 4;
 116.526 +    }
 116.527 +	if (*buff=='\"')
 116.528 +    {
 116.529 +        return parseString(buff, perror);
 116.530 +    }
 116.531 +	if (*buff=='-' || (*buff>='0' && *buff<='9'))
 116.532 +    { 
 116.533 +        return parseNumber(buff);
 116.534 +    }
 116.535 +	if (*buff=='[')
 116.536 +    { 
 116.537 +        return parseArray(buff, perror);
 116.538 +    }
 116.539 +	if (*buff=='{')
 116.540 +    {
 116.541 +        return parseObject(buff, perror);
 116.542 +    }
 116.543 +
 116.544 +    return AssignError(perror, "Syntax Error: Invalid syntax");
 116.545 +}
 116.546 +
 116.547 +
 116.548 +//-----------------------------------------------------------------------------
 116.549 +// Render a value to text. 
 116.550 +char* JSON::PrintValue(int depth, bool fmt)
 116.551 +{
 116.552 +	char *out=0;
 116.553 +
 116.554 +    switch (Type)
 116.555 +	{
 116.556 +        case JSON_Null:	    out = JSON_strdup("null");	break;
 116.557 +        case JSON_Bool:
 116.558 +            if ((int)dValue == 0)
 116.559 +                out = JSON_strdup("false");
 116.560 +            else
 116.561 +                out = JSON_strdup("true");
 116.562 +            break;
 116.563 +        case JSON_Number:	out = PrintNumber(dValue); break;
 116.564 +        case JSON_String:	out = PrintString(Value); break;
 116.565 +        case JSON_Array:	out = PrintArray(depth, fmt); break;
 116.566 +        case JSON_Object:	out = PrintObject(depth, fmt); break;
 116.567 +        case JSON_None: OVR_ASSERT_LOG(false, ("Bad JSON type.")); break;
 116.568 +	}
 116.569 +	return out;
 116.570 +}
 116.571 +
 116.572 +//-----------------------------------------------------------------------------
 116.573 +// Build an array object from input text and returns the text position after
 116.574 +// the parsed array
 116.575 +const char* JSON::parseArray(const char* buff, const char** perror)
 116.576 +{
 116.577 +	JSON *child;
 116.578 +	if (*buff!='[')
 116.579 +    {
 116.580 +        return AssignError(perror, "Syntax Error: Missing opening bracket");
 116.581 +    }
 116.582 +
 116.583 +	Type=JSON_Array;
 116.584 +	buff=skip(buff+1);
 116.585 +	
 116.586 +    if (*buff==']')
 116.587 +        return buff+1;	// empty array.
 116.588 +
 116.589 +    child = new JSON();
 116.590 +	if (!child)
 116.591 +        return 0;		 // memory fail
 116.592 +    Children.PushBack(child);
 116.593 +	
 116.594 +    buff=skip(child->parseValue(skip(buff), perror));	// skip any spacing, get the buff. 
 116.595 +	if (!buff)
 116.596 +        return 0;
 116.597 +
 116.598 +	while (*buff==',')
 116.599 +	{
 116.600 +		JSON *new_item = new JSON();
 116.601 +		if (!new_item)
 116.602 +            return AssignError(perror, "Error: Failed to allocate memory");
 116.603 +		
 116.604 +        Children.PushBack(new_item);
 116.605 +
 116.606 +		buff=skip(new_item->parseValue(skip(buff+1), perror));
 116.607 +		if (!buff)
 116.608 +            return AssignError(perror, "Error: Failed to allocate memory");
 116.609 +	}
 116.610 +
 116.611 +	if (*buff==']')
 116.612 +        return buff+1;	// end of array
 116.613 +
 116.614 +    return AssignError(perror, "Syntax Error: Missing ending bracket");
 116.615 +}
 116.616 +
 116.617 +//-----------------------------------------------------------------------------
 116.618 +// Render an array to text.  The returned text must be freed
 116.619 +char* JSON::PrintArray(int depth, bool fmt)
 116.620 +{
 116.621 +	char **  entries;
 116.622 +	char *   out = 0, *ptr,*ret;
 116.623 +    intptr_t len = 5;
 116.624 +	
 116.625 +    bool fail = false;
 116.626 +	
 116.627 +	// How many entries in the array? 
 116.628 +    int numentries = GetItemCount();
 116.629 +	if (!numentries)
 116.630 +	{
 116.631 +		out=(char*)OVR_ALLOC(3);
 116.632 +		if (out)
 116.633 +            OVR_strcpy(out, 3, "[]");
 116.634 +		return out;
 116.635 +	}
 116.636 +	// Allocate an array to hold the values for each
 116.637 +	entries=(char**)OVR_ALLOC(numentries*sizeof(char*));
 116.638 +	if (!entries)
 116.639 +        return 0;
 116.640 +	memset(entries,0,numentries*sizeof(char*));
 116.641 +
 116.642 +	//// Retrieve all the results:
 116.643 +    JSON* child = Children.GetFirst();
 116.644 +    for (int i=0; i<numentries; i++)
 116.645 +	{
 116.646 +		//JSON* child = Children[i];
 116.647 +        ret=child->PrintValue(depth+1, fmt);
 116.648 +		entries[i]=ret;
 116.649 +		if (ret)
 116.650 +            len+=OVR_strlen(ret)+2+(fmt?1:0);
 116.651 +        else
 116.652 +        {
 116.653 +            fail = true;
 116.654 +            break;
 116.655 +        }
 116.656 +        child = Children.GetNext(child);
 116.657 +	}
 116.658 +	
 116.659 +	// If we didn't fail, try to malloc the output string 
 116.660 +	if (!fail)
 116.661 +        out=(char*)OVR_ALLOC(len);
 116.662 +	// If that fails, we fail. 
 116.663 +	if (!out)
 116.664 +        fail = true;
 116.665 +
 116.666 +	// Handle failure.
 116.667 +	if (fail)
 116.668 +	{
 116.669 +		for (int i=0; i<numentries; i++) 
 116.670 +        {
 116.671 +            if (entries[i])
 116.672 +                OVR_FREE(entries[i]);
 116.673 +        }
 116.674 +		OVR_FREE(entries);
 116.675 +		return 0;
 116.676 +	}
 116.677 +	
 116.678 +	// Compose the output array.
 116.679 +	*out='[';
 116.680 +	ptr=out+1;
 116.681 +    *ptr=0;
 116.682 +	for (int i=0; i<numentries; i++)
 116.683 +	{
 116.684 +		OVR_strcpy(ptr, len - (ptr-out), entries[i]);
 116.685 +        ptr+=OVR_strlen(entries[i]);
 116.686 +		if (i!=numentries-1)
 116.687 +        {
 116.688 +            *ptr++=',';
 116.689 +            if (fmt)
 116.690 +                *ptr++=' ';
 116.691 +            *ptr=0;
 116.692 +        }
 116.693 +		OVR_FREE(entries[i]);
 116.694 +	}
 116.695 +	OVR_FREE(entries);
 116.696 +	*ptr++=']';
 116.697 +    *ptr++=0;
 116.698 +	return out;	
 116.699 +}
 116.700 +
 116.701 +//-----------------------------------------------------------------------------
 116.702 +// Build an object from the supplied text and returns the text position after
 116.703 +// the parsed object
 116.704 +const char* JSON::parseObject(const char* buff, const char** perror)
 116.705 +{
 116.706 +	if (*buff!='{')
 116.707 +    {
 116.708 +        return AssignError(perror, "Syntax Error: Missing opening brace");
 116.709 +    }
 116.710 +	
 116.711 +	Type=JSON_Object;
 116.712 +	buff=skip(buff+1);
 116.713 +	if (*buff=='}')
 116.714 +        return buff+1;	// empty array.
 116.715 +	
 116.716 +    JSON* child = new JSON();
 116.717 +    Children.PushBack(child);
 116.718 +
 116.719 +	buff=skip(child->parseString(skip(buff), perror));
 116.720 +	if (!buff) 
 116.721 +        return 0;
 116.722 +	child->Name = child->Value;
 116.723 +    child->Value.Clear();
 116.724 +	
 116.725 +    if (*buff!=':')
 116.726 +    {
 116.727 +        return AssignError(perror, "Syntax Error: Missing colon");
 116.728 +    }
 116.729 +
 116.730 +	buff=skip(child->parseValue(skip(buff+1), perror));	// skip any spacing, get the value.
 116.731 +	if (!buff)
 116.732 +        return 0;
 116.733 +	
 116.734 +	while (*buff==',')
 116.735 +	{
 116.736 +        child = new JSON();
 116.737 +		if (!child)
 116.738 +            return 0; // memory fail
 116.739 +		
 116.740 +        Children.PushBack(child);
 116.741 +
 116.742 +		buff=skip(child->parseString(skip(buff+1), perror));
 116.743 +		if (!buff)
 116.744 +            return 0;
 116.745 +		
 116.746 +        child->Name=child->Value;
 116.747 +        child->Value.Clear();
 116.748 +		
 116.749 +        if (*buff!=':')
 116.750 +        {
 116.751 +            return AssignError(perror, "Syntax Error: Missing colon");
 116.752 +        }	// fail!
 116.753 +		
 116.754 +        // Skip any spacing, get the value.
 116.755 +        buff=skip(child->parseValue(skip(buff+1), perror));
 116.756 +		if (!buff)
 116.757 +            return 0;
 116.758 +	}
 116.759 +	
 116.760 +	if (*buff=='}')
 116.761 +        return buff+1;	// end of array 
 116.762 +	
 116.763 +    return AssignError(perror, "Syntax Error: Missing closing brace");
 116.764 +}
 116.765 +
 116.766 +//-----------------------------------------------------------------------------
 116.767 +// Render an object to text.  The returned string must be freed
 116.768 +char* JSON::PrintObject(int depth, bool fmt)
 116.769 +{
 116.770 +	char**   entries = 0, **names = 0;
 116.771 +	char*    out = 0;
 116.772 +    char*    ptr, *ret, *str;
 116.773 +    intptr_t len = 7, i = 0, j;
 116.774 +    bool     fail = false;
 116.775 +	
 116.776 +    // Count the number of entries.
 116.777 +    int numentries = GetItemCount();
 116.778 +    
 116.779 +	// Explicitly handle empty object case
 116.780 +	if (numentries == 0)
 116.781 +	{
 116.782 +		out=(char*)OVR_ALLOC(fmt?depth+4:4);
 116.783 +		if (!out)
 116.784 +            return 0;
 116.785 +		ptr=out;
 116.786 +        *ptr++='{';
 116.787 +		
 116.788 +        if (fmt)
 116.789 +        {
 116.790 +            *ptr++='\n';
 116.791 +            for (i=0;i<depth-1;i++)
 116.792 +                *ptr++='\t';
 116.793 +        }
 116.794 +		*ptr++='}';
 116.795 +        *ptr++=0;
 116.796 +		return out;
 116.797 +	}
 116.798 +	// Allocate space for the names and the objects
 116.799 +	entries=(char**)OVR_ALLOC(numentries*sizeof(char*));
 116.800 +	if (!entries)
 116.801 +        return 0;
 116.802 +	names=(char**)OVR_ALLOC(numentries*sizeof(char*));
 116.803 +	
 116.804 +    if (!names)
 116.805 +    {
 116.806 +        OVR_FREE(entries);
 116.807 +        return 0;
 116.808 +    }
 116.809 +	memset(entries,0,sizeof(char*)*numentries);
 116.810 +	memset(names,0,sizeof(char*)*numentries);
 116.811 +
 116.812 +	// Collect all the results into our arrays:
 116.813 +    depth++;
 116.814 +    if (fmt)
 116.815 +        len+=depth;
 116.816 +
 116.817 +    JSON* child = Children.GetFirst();
 116.818 +    while (!Children.IsNull(child))
 116.819 +	{
 116.820 +		names[i]     = str = PrintString(child->Name);
 116.821 +		entries[i++] = ret = child->PrintValue(depth, fmt);
 116.822 +
 116.823 +		if (str && ret)
 116.824 +        {
 116.825 +            len += OVR_strlen(ret)+OVR_strlen(str)+2+(fmt?3+depth:0);
 116.826 +        }
 116.827 +        else
 116.828 +        {
 116.829 +            fail = true;
 116.830 +            break;
 116.831 +        }
 116.832 +		
 116.833 +        child = Children.GetNext(child);
 116.834 +	}
 116.835 +	
 116.836 +	// Try to allocate the output string
 116.837 +	if (!fail)
 116.838 +        out=(char*)OVR_ALLOC(len);
 116.839 +	if (!out)
 116.840 +        fail=true;
 116.841 +
 116.842 +	// Handle failure
 116.843 +	if (fail)
 116.844 +	{
 116.845 +		for (i=0;i<numentries;i++)
 116.846 +        {
 116.847 +            if (names[i])
 116.848 +                OVR_FREE(names[i]);
 116.849 +            
 116.850 +            if (entries[i])
 116.851 +                OVR_FREE(entries[i]);}
 116.852 +		
 116.853 +        OVR_FREE(names);
 116.854 +        OVR_FREE(entries);
 116.855 +		return 0;
 116.856 +	}
 116.857 +	
 116.858 +	// Compose the output:
 116.859 +	*out = '{';
 116.860 +    ptr  = out+1;
 116.861 +    if (fmt)
 116.862 +    {
 116.863 +#ifdef OVR_OS_WIN32
 116.864 +        *ptr++ = '\r';
 116.865 +#endif
 116.866 +        *ptr++ = '\n';
 116.867 +    }
 116.868 +    *ptr = 0;
 116.869 +	
 116.870 +    for (i=0; i<numentries; i++)
 116.871 +	{
 116.872 +		if (fmt)
 116.873 +        {
 116.874 +            for (j = 0; j < depth; j++)
 116.875 +            {
 116.876 +                *ptr++ = '\t';
 116.877 +            }
 116.878 +        }
 116.879 +		OVR_strcpy(ptr, len - (ptr-out), names[i]);
 116.880 +        ptr   += OVR_strlen(names[i]);
 116.881 +		*ptr++ =':';
 116.882 +        
 116.883 +        if (fmt)
 116.884 +        {
 116.885 +            *ptr++ = '\t';
 116.886 +        }
 116.887 +		
 116.888 +        OVR_strcpy(ptr, len - (ptr-out), entries[i]);
 116.889 +        ptr+=OVR_strlen(entries[i]);
 116.890 +		
 116.891 +        if (i != numentries - 1)
 116.892 +        {
 116.893 +            *ptr++ = ',';
 116.894 +        }
 116.895 +		
 116.896 +        if (fmt)
 116.897 +        {
 116.898 +#ifdef OVR_OS_WIN32
 116.899 +            *ptr++ = '\r';
 116.900 +#endif
 116.901 +            *ptr++ = '\n';
 116.902 +        }
 116.903 +        *ptr = 0;
 116.904 +		
 116.905 +        OVR_FREE(names[i]);
 116.906 +        OVR_FREE(entries[i]);
 116.907 +	}
 116.908 +	
 116.909 +	OVR_FREE(names);
 116.910 +    OVR_FREE(entries);
 116.911 +	
 116.912 +    if (fmt)
 116.913 +    {
 116.914 +        for (i = 0; i < depth - 1; i++)
 116.915 +        {
 116.916 +            *ptr++ = '\t';
 116.917 +        }
 116.918 +    }
 116.919 +	*ptr++='}';
 116.920 +    *ptr++=0;
 116.921 +	
 116.922 +    return out;	
 116.923 +}
 116.924 +
 116.925 +
 116.926 +
 116.927 +// Returns the number of child items in the object
 116.928 +// Counts the number of items in the object.
 116.929 +unsigned JSON::GetItemCount() const
 116.930 +{
 116.931 +    unsigned count = 0;
 116.932 +    for (const JSON* p = Children.GetFirst(); !Children.IsNull(p); p = p->pNext)
 116.933 +    {
 116.934 +        count++;
 116.935 +    }
 116.936 +    return count;
 116.937 +}
 116.938 +
 116.939 +JSON* JSON::GetItemByIndex(unsigned index)
 116.940 +{
 116.941 +    unsigned i     = 0;
 116.942 +    JSON*    child = 0;
 116.943 +
 116.944 +    if (!Children.IsEmpty())
 116.945 +    {
 116.946 +        child = Children.GetFirst();
 116.947 +
 116.948 +        while (i < index)
 116.949 +        {   
 116.950 +            if (Children.IsNull(child->pNext))
 116.951 +            {
 116.952 +                child = 0;
 116.953 +                break;
 116.954 +            }
 116.955 +            child = child->pNext;
 116.956 +            i++;
 116.957 +        }
 116.958 +    }
 116.959 +  
 116.960 +    return child;
 116.961 +}
 116.962 +
 116.963 +// Returns the child item with the given name or NULL if not found
 116.964 +JSON* JSON::GetItemByName(const char* name)
 116.965 +{
 116.966 +    JSON* child = 0;
 116.967 +
 116.968 +    if (!Children.IsEmpty())
 116.969 +    {
 116.970 +        child = Children.GetFirst();
 116.971 +
 116.972 +        while (OVR_strcmp(child->Name, name) != 0)
 116.973 +        {   
 116.974 +            if (Children.IsNull(child->pNext))
 116.975 +            {
 116.976 +                child = 0;
 116.977 +                break;
 116.978 +            }
 116.979 +            child = child->pNext;
 116.980 +        }
 116.981 +    }
 116.982 +
 116.983 +    return child;
 116.984 +}
 116.985 +
 116.986 +//-----------------------------------------------------------------------------
 116.987 +// Adds a new item to the end of the child list
 116.988 +void JSON::AddItem(const char *string, JSON *item)
 116.989 +{
 116.990 +    if (item)
 116.991 +    {
 116.992 +        item->Name = string;
 116.993 +        Children.PushBack(item);
 116.994 +    }
 116.995 +}
 116.996 +
 116.997 +/*
 116.998 +
 116.999 +// Removes and frees the items at the given index
116.1000 +void JSON::DeleteItem(unsigned int index)
116.1001 +{
116.1002 +    unsigned int num_items = 0;
116.1003 +    JSON* child = Children.GetFirst();
116.1004 +    while (!Children.IsNull(child) && num_items < index)
116.1005 +    {   
116.1006 +        num_items++;
116.1007 +        child = Children.GetNext(child);
116.1008 +    }
116.1009 +
116.1010 +    if (!Children.IsNull(child))
116.1011 +    
116.1012 +        child->RemoveNode();
116.1013 +        child->Release();
116.1014 +    }
116.1015 +}
116.1016 +
116.1017 +// Replaces and frees the item at the give index with the new item
116.1018 +void JSON::ReplaceItem(unsigned int index, JSON* new_item)
116.1019 +{
116.1020 +    unsigned int num_items = 0;
116.1021 +    JSON* child = Children.GetFirst();
116.1022 +    while (!Children.IsNull(child) && num_items < index)
116.1023 +    {   
116.1024 +        num_items++;
116.1025 +        child = Children.GetNext(child);
116.1026 +    }
116.1027 +
116.1028 +    if (!Children.IsNull(child))
116.1029 +    {
116.1030 +        child->ReplaceNodeWith(new_item);
116.1031 +        child->Release();        
116.1032 +    }
116.1033 +}
116.1034 +*/
116.1035 +
116.1036 +// Removes and frees the last child item
116.1037 +void JSON::RemoveLast()
116.1038 +{
116.1039 +    JSON* child = Children.GetLast();
116.1040 +    if (!Children.IsNull(child))
116.1041 +    {
116.1042 +        child->RemoveNode();
116.1043 +        child->Release();
116.1044 +    }
116.1045 +}
116.1046 +
116.1047 +JSON* JSON::CreateBool(bool b)
116.1048 +{
116.1049 +    JSON *item = new JSON(JSON_Bool);
116.1050 +    if (item)
116.1051 +    {
116.1052 +        item->dValue = b ? 1. : 0.;
116.1053 +        item->Value = b ? "true" : "false";
116.1054 +    }
116.1055 +    return item;
116.1056 +}
116.1057 +
116.1058 +JSON* JSON::CreateNumber(double num)
116.1059 +{
116.1060 +    JSON *item = new JSON(JSON_Number);
116.1061 +    if (item)
116.1062 +    {
116.1063 +        item->dValue = num;
116.1064 +    }
116.1065 +    return item;
116.1066 +}
116.1067 +
116.1068 +JSON* JSON::CreateInt(int num)
116.1069 +{
116.1070 +    JSON *item = new JSON(JSON_Number);
116.1071 +    if (item)
116.1072 +    {
116.1073 +        item->dValue = num;
116.1074 +    }
116.1075 +    return item;
116.1076 +}
116.1077 +
116.1078 +JSON* JSON::CreateString(const char *s)
116.1079 +{
116.1080 +    JSON *item = new JSON(JSON_String);
116.1081 +    if (item && s)
116.1082 +    {
116.1083 +        item->Value = s;
116.1084 +    }
116.1085 +    return item;
116.1086 +}
116.1087 +
116.1088 +
116.1089 +//-----------------------------------------------------------------------------
116.1090 +// Get elements by name
116.1091 +double JSON::GetNumberByName(const char *name, double defValue)
116.1092 +{
116.1093 +	JSON* item = GetItemByName(name);
116.1094 +	if (!item || item->Type != JSON_Number)
116.1095 +    {
116.1096 +		return defValue;
116.1097 +	}
116.1098 +	else
116.1099 +    {
116.1100 +		return item->dValue;
116.1101 +	}
116.1102 +}
116.1103 +
116.1104 +int JSON::GetIntByName(const char *name, int defValue)
116.1105 +{
116.1106 +	JSON* item = GetItemByName(name);
116.1107 +	if (!item || item->Type != JSON_Number)
116.1108 +    {
116.1109 +		return defValue;
116.1110 +	}
116.1111 +	else
116.1112 +    {
116.1113 +		return (int)item->dValue;
116.1114 +	}
116.1115 +}
116.1116 +
116.1117 +bool JSON::GetBoolByName(const char *name, bool defValue)
116.1118 +{
116.1119 +	JSON* item = GetItemByName(name);
116.1120 +	if (!item || item->Type != JSON_Bool)
116.1121 +    {
116.1122 +		return defValue;
116.1123 +	}
116.1124 +	else
116.1125 +    {
116.1126 +		return (int)item->dValue != 0;
116.1127 +	}
116.1128 +}
116.1129 +
116.1130 +String JSON::GetStringByName(const char *name, const String &defValue)
116.1131 +{
116.1132 +	JSON* item = GetItemByName(name);
116.1133 +	if (!item || item->Type != JSON_String)
116.1134 +    {
116.1135 +		return defValue;
116.1136 +	}
116.1137 +	else
116.1138 +    {
116.1139 +		return item->Value;
116.1140 +	}
116.1141 +}
116.1142 +
116.1143 +//-----------------------------------------------------------------------------
116.1144 +// Adds an element to an array object type
116.1145 +void JSON::AddArrayElement(JSON *item)
116.1146 +{
116.1147 +    if (item)
116.1148 +    {
116.1149 +        Children.PushBack(item);
116.1150 +    }
116.1151 +}
116.1152 +
116.1153 +// Inserts an element into a valid array position
116.1154 +void JSON::InsertArrayElement(int index, JSON *item)
116.1155 +{
116.1156 +    if (!item)
116.1157 +    {
116.1158 +        return;
116.1159 +    }
116.1160 +
116.1161 +    if (index == 0)
116.1162 +    {
116.1163 +        Children.PushFront(item);
116.1164 +        return;
116.1165 +    }
116.1166 +
116.1167 +    JSON* iter = Children.GetFirst();
116.1168 +    int i=0;
116.1169 +    while (iter && i<index)
116.1170 +    {
116.1171 +        iter = Children.GetNext(iter);
116.1172 +        i++;
116.1173 +    }
116.1174 +
116.1175 +    if (iter)
116.1176 +        iter->InsertNodeBefore(item);
116.1177 +    else
116.1178 +        Children.PushBack(item);
116.1179 +}
116.1180 +
116.1181 +// Returns the size of an array
116.1182 +int JSON::GetArraySize()
116.1183 +{
116.1184 +    if (Type == JSON_Array)
116.1185 +    {
116.1186 +        return GetItemCount();
116.1187 +    }
116.1188 +
116.1189 +    return 0;
116.1190 +}
116.1191 +
116.1192 +// Returns the number value an the give array index
116.1193 +double JSON::GetArrayNumber(int index)
116.1194 +{
116.1195 +    if (Type == JSON_Array)
116.1196 +    {
116.1197 +        JSON* number = GetItemByIndex(index);
116.1198 +        return number ? number->dValue : 0.0;
116.1199 +    }
116.1200 +
116.1201 +    return 0;
116.1202 +}
116.1203 +
116.1204 +// Returns the string value at the given array index
116.1205 +const char* JSON::GetArrayString(int index)
116.1206 +{
116.1207 +    if (Type == JSON_Array)
116.1208 +    {
116.1209 +        JSON* number = GetItemByIndex(index);
116.1210 +        return number ? number->Value : 0;
116.1211 +    }
116.1212 +
116.1213 +    return 0;
116.1214 +}
116.1215 +
116.1216 +JSON* JSON::Copy()
116.1217 +{
116.1218 +    JSON* copy = new JSON(Type);
116.1219 +    copy->Name = Name;
116.1220 +    copy->Value = Value;
116.1221 +    copy->dValue = dValue;
116.1222 +
116.1223 +    JSON* child = Children.GetFirst();
116.1224 +    while (!Children.IsNull(child))
116.1225 +    {
116.1226 +        copy->Children.PushBack(child->Copy());
116.1227 +        child = Children.GetNext(child);
116.1228 +    }
116.1229 +
116.1230 +    return copy;
116.1231 +}
116.1232 +
116.1233 +//-----------------------------------------------------------------------------
116.1234 +// Loads and parses the given JSON file pathname and returns a JSON object tree.
116.1235 +// The returned object must be Released after use.
116.1236 +JSON* JSON::Load(const char* path, const char** perror)
116.1237 +{
116.1238 +    SysFile f;
116.1239 +    if (!f.Open(path, File::Open_Read, File::Mode_Read))
116.1240 +    {
116.1241 +        AssignError(perror, "Failed to open file");
116.1242 +        return NULL;
116.1243 +    }
116.1244 +
116.1245 +    int    len   = f.GetLength();
116.1246 +    uint8_t* buff  = (uint8_t*)OVR_ALLOC(len + 1);
116.1247 +    int    bytes = f.Read(buff, len);
116.1248 +    f.Close();
116.1249 +
116.1250 +    if (bytes == 0 || bytes != len)
116.1251 +    {
116.1252 +        OVR_FREE(buff);
116.1253 +        return NULL;
116.1254 +    }
116.1255 +
116.1256 +	// Ensure the result is null-terminated since Parse() expects null-terminated input.
116.1257 +	buff[len] = '\0';
116.1258 +
116.1259 +    JSON* json = JSON::Parse((char*)buff, perror);
116.1260 +    OVR_FREE(buff);
116.1261 +    return json;
116.1262 +}
116.1263 +
116.1264 +//-----------------------------------------------------------------------------
116.1265 +// Serializes the JSON object and writes to the give file path
116.1266 +bool JSON::Save(const char* path)
116.1267 +{
116.1268 +    SysFile f;
116.1269 +    if (!f.Open(path, File::Open_Write | File::Open_Create | File::Open_Truncate, File::Mode_Write))
116.1270 +        return false;
116.1271 +
116.1272 +    char* text = PrintValue(0, true);
116.1273 +    if (text)
116.1274 +    {
116.1275 +        intptr_t len   = OVR_strlen(text);
116.1276 +        OVR_ASSERT(len <= (intptr_t)(int)len);
116.1277 +
116.1278 +        int   bytes = f.Write((uint8_t*)text, (int)len);
116.1279 +        f.Close();
116.1280 +        OVR_FREE(text);
116.1281 +        return (bytes == len);
116.1282 +    }
116.1283 +    else
116.1284 +    {
116.1285 +        return false;
116.1286 +    }
116.1287 +}
116.1288 +
116.1289 +
116.1290 +} // namespace OVR
   117.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   117.2 +++ b/LibOVR/Src/OVR_JSON.h	Wed Jan 14 06:51:16 2015 +0200
   117.3 @@ -0,0 +1,165 @@
   117.4 +/************************************************************************************
   117.5 +
   117.6 +PublicHeader:   None
   117.7 +Filename    :   OVR_JSON.h
   117.8 +Content     :   JSON format reader and writer
   117.9 +Created     :   April 9, 2013
  117.10 +Author      :   Brant Lewis
  117.11 +Notes       :
  117.12 +
  117.13 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
  117.14 +
  117.15 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
  117.16 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
  117.17 +which is provided at the time of installation or download, or which 
  117.18 +otherwise accompanies this software in either electronic or hard copy form.
  117.19 +
  117.20 +You may obtain a copy of the License at
  117.21 +
  117.22 +http://www.oculusvr.com/licenses/LICENSE-3.2 
  117.23 +
  117.24 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
  117.25 +distributed under the License is distributed on an "AS IS" BASIS,
  117.26 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  117.27 +See the License for the specific language governing permissions and
  117.28 +limitations under the License.
  117.29 +
  117.30 +************************************************************************************/
  117.31 +
  117.32 +#ifndef OVR_JSON_H
  117.33 +#define OVR_JSON_H
  117.34 +
  117.35 +#include "Kernel/OVR_RefCount.h"
  117.36 +#include "Kernel/OVR_String.h"
  117.37 +#include "Kernel/OVR_List.h"
  117.38 +
  117.39 +namespace OVR {  
  117.40 +
  117.41 +// JSONItemType describes the type of JSON item, specifying the type of
  117.42 +// data that can be obtained from it.
  117.43 +enum JSONItemType
  117.44 +{
  117.45 +    JSON_None      = 0,
  117.46 +    JSON_Null      = 1,
  117.47 +    JSON_Bool      = 2,
  117.48 +    JSON_Number    = 3,
  117.49 +    JSON_String    = 4,
  117.50 +    JSON_Array     = 5,
  117.51 +    JSON_Object    = 6
  117.52 +};
  117.53 +
  117.54 +//-----------------------------------------------------------------------------
  117.55 +// ***** JSON
  117.56 +
  117.57 +// JSON object represents a JSON node that can be either a root of the JSON tree
  117.58 +// or a child item. Every node has a type that describes what is is.
  117.59 +// New JSON trees are typically loaded JSON::Load or created with JSON::Parse.
  117.60 +
  117.61 +class JSON : public RefCountBase<JSON>, public ListNode<JSON>
  117.62 +{
  117.63 +protected:
  117.64 +    List<JSON>      Children;
  117.65 +
  117.66 +public:
  117.67 +    JSONItemType    Type;       // Type of this JSON node.
  117.68 +    String          Name;       // Name part of the {Name, Value} pair in a parent object.
  117.69 +    String          Value;
  117.70 +    double          dValue;
  117.71 +
  117.72 +public:
  117.73 +    ~JSON();
  117.74 +
  117.75 +    // *** Creation of NEW JSON objects
  117.76 +
  117.77 +    static JSON*    CreateObject() { return new JSON(JSON_Object);}
  117.78 +    static JSON*    CreateNull()   { return new JSON(JSON_Null); }
  117.79 +    static JSON*    CreateArray()  { return new JSON(JSON_Array); }
  117.80 +    static JSON*    CreateBool(bool b);
  117.81 +    static JSON*    CreateNumber(double num);
  117.82 +    static JSON*    CreateInt(int num);
  117.83 +    static JSON*    CreateString(const char *s);
  117.84 +
  117.85 +    // Creates a new JSON object from parsing string.
  117.86 +    // Returns null pointer and fills in *perror in case of parse error.
  117.87 +    static JSON*    Parse(const char* buff, const char** perror = 0);
  117.88 +
  117.89 +	// This version works for buffers that are not null terminated strings.
  117.90 +	static JSON*	ParseBuffer(const char *buff, int len, const char** perror = 0);
  117.91 +
  117.92 +    // Loads and parses a JSON object from a file.
  117.93 +    // Returns 0 and assigns perror with error message on fail.
  117.94 +    static JSON*    Load(const char* path, const char** perror = 0);
  117.95 +
  117.96 +    // Saves a JSON object to a file.
  117.97 +    bool            Save(const char* path);
  117.98 +
  117.99 +    // *** Object Member Access
 117.100 +
 117.101 +    // These provide access to child items of the list.
 117.102 +    bool            HasItems() const         { return Children.IsEmpty(); }
 117.103 +    // Returns first/last child item, or null if child list is empty
 117.104 +    JSON*           GetFirstItem()           { return (!Children.IsEmpty()) ? Children.GetFirst() : 0; }
 117.105 +    JSON*           GetLastItem()            { return (!Children.IsEmpty()) ? Children.GetLast() : 0; }
 117.106 +
 117.107 +    // Counts the number of items in the object; these methods are inefficient.
 117.108 +    unsigned        GetItemCount() const;
 117.109 +    JSON*           GetItemByIndex(unsigned i);
 117.110 +    JSON*           GetItemByName(const char* name);
 117.111 +
 117.112 +	// Accessors by name
 117.113 +	double			GetNumberByName(const char *name, double defValue = 0.0);
 117.114 +	int				GetIntByName(const char *name, int defValue = 0);
 117.115 +	bool			GetBoolByName(const char *name, bool defValue = false);
 117.116 +	String			GetStringByName(const char *name, const String &defValue = "");
 117.117 +
 117.118 +    // Returns next item in a list of children; 0 if no more items exist.
 117.119 +    JSON*           GetNextItem(JSON* item)  { return Children.IsNull(item->pNext) ? 0 : item->pNext; }
 117.120 +    JSON*           GetPrevItem(JSON* item)  { return Children.IsNull(item->pPrev) ? 0 : item->pPrev; }
 117.121 +
 117.122 +
 117.123 +    // Child item access functions
 117.124 +    void            AddItem(const char *string, JSON* item);
 117.125 +    void            AddNullItem(const char* name)                    { AddItem(name, CreateNull()); }
 117.126 +    void            AddBoolItem(const char* name, bool b)            { AddItem(name, CreateBool(b)); }
 117.127 +    void            AddIntItem(const char* name, int n)              { AddItem(name, CreateInt(n)); }
 117.128 +    void            AddNumberItem(const char* name, double n)        { AddItem(name, CreateNumber(n)); }
 117.129 +    void            AddStringItem(const char* name, const char* s)   { AddItem(name, CreateString(s)); }
 117.130 +//    void            ReplaceItem(unsigned index, JSON* new_item);
 117.131 +//    void            DeleteItem(unsigned index);
 117.132 +    void            RemoveLast();
 117.133 +
 117.134 +    // *** Array Element Access
 117.135 +
 117.136 +    // Add new elements to the end of array.
 117.137 +    void            AddArrayElement(JSON *item);
 117.138 +    void            InsertArrayElement(int index, JSON* item);
 117.139 +    void            AddArrayNumber(double n)        { AddArrayElement(CreateNumber(n)); }
 117.140 +    void            AddArrayInt(int n)              { AddArrayElement(CreateInt(n)); }
 117.141 +    void            AddArrayString(const char* s)   { AddArrayElement(CreateString(s)); }
 117.142 +
 117.143 +    // Accessed array elements; currently inefficient.
 117.144 +    int             GetArraySize();
 117.145 +    double          GetArrayNumber(int index);
 117.146 +    const char*     GetArrayString(int index);
 117.147 +
 117.148 +    JSON*           Copy();  // Create a copy of this object
 117.149 +
 117.150 +protected:
 117.151 +    JSON(JSONItemType itemType = JSON_Object);
 117.152 +
 117.153 +    // JSON Parsing helper functions.
 117.154 +    const char*     parseValue(const char *buff, const char** perror);
 117.155 +    const char*     parseNumber(const char *num);
 117.156 +    const char*     parseArray(const char* value, const char** perror);
 117.157 +    const char*     parseObject(const char* value, const char** perror);
 117.158 +    const char*     parseString(const char* str, const char** perror);
 117.159 +
 117.160 +    char*           PrintValue(int depth, bool fmt);
 117.161 +    char*           PrintObject(int depth, bool fmt);
 117.162 +    char*           PrintArray(int depth, bool fmt);
 117.163 +};
 117.164 +
 117.165 +
 117.166 +}
 117.167 +
 117.168 +#endif
   118.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   118.2 +++ b/LibOVR/Src/OVR_Profile.cpp	Wed Jan 14 06:51:16 2015 +0200
   118.3 @@ -0,0 +1,1627 @@
   118.4 +/************************************************************************************
   118.5 +
   118.6 +PublicHeader:   None
   118.7 +Filename    :   OVR_Profile.cpp
   118.8 +Content     :   Structs and functions for loading and storing device profile settings
   118.9 +Created     :   February 14, 2013
  118.10 +Notes       :
  118.11 +   
  118.12 +   Profiles are used to store per-user settings that can be transferred and used
  118.13 +   across multiple applications.  For example, player IPD can be configured once 
  118.14 +   and reused for a unified experience across games.  Configuration and saving of profiles
  118.15 +   can be accomplished in game via the Profile API or by the official Oculus Configuration
  118.16 +   Utility.
  118.17 +
  118.18 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
  118.19 +
  118.20 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
  118.21 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
  118.22 +which is provided at the time of installation or download, or which 
  118.23 +otherwise accompanies this software in either electronic or hard copy form.
  118.24 +
  118.25 +You may obtain a copy of the License at
  118.26 +
  118.27 +http://www.oculusvr.com/licenses/LICENSE-3.2 
  118.28 +
  118.29 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
  118.30 +distributed under the License is distributed on an "AS IS" BASIS,
  118.31 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  118.32 +See the License for the specific language governing permissions and
  118.33 +limitations under the License.
  118.34 +
  118.35 +************************************************************************************/
  118.36 +
  118.37 +#include "OVR_Profile.h"
  118.38 +#include "OVR_JSON.h"
  118.39 +#include "Kernel/OVR_SysFile.h"
  118.40 +#include "Kernel/OVR_Allocator.h"
  118.41 +#include "OVR_Stereo.h"
  118.42 +
  118.43 +#ifdef OVR_OS_WIN32
  118.44 +#define WIN32_LEAN_AND_MEAN
  118.45 +#include <Windows.h>
  118.46 +#include <Shlobj.h>
  118.47 +#elif defined(OVR_OS_MS) // Other Microsoft OSs
  118.48 +// Nothing, thanks.
  118.49 +#else
  118.50 +#include <dirent.h>
  118.51 +#include <sys/stat.h>
  118.52 +
  118.53 +#ifdef OVR_OS_LINUX
  118.54 +#include <unistd.h>
  118.55 +#include <pwd.h>
  118.56 +#endif
  118.57 +
  118.58 +#endif
  118.59 +
  118.60 +#define PROFILE_VERSION 2.0
  118.61 +#define MAX_PROFILE_MAJOR_VERSION 2
  118.62 +#define MAX_DEVICE_PROFILE_MAJOR_VERSION 1
  118.63 +
  118.64 +
  118.65 +namespace OVR {
  118.66 +
  118.67 +
  118.68 +//-----------------------------------------------------------------------------
  118.69 +// ProfileDeviceKey
  118.70 +
  118.71 +ProfileDeviceKey::ProfileDeviceKey(const HMDInfo* info) :
  118.72 +    Valid(false)
  118.73 +{
  118.74 +    if (info)
  118.75 +    {
  118.76 +        PrintedSerial = info->PrintedSerial;
  118.77 +        ProductName = SanitizeProductName(info->ProductName);
  118.78 +        ProductId = info->ProductId;
  118.79 +        HmdType = info->HmdType;
  118.80 +
  118.81 +        if (ProductId != 0)
  118.82 +        {
  118.83 +            Valid = true;
  118.84 +        }
  118.85 +    }
  118.86 +    else
  118.87 +    {
  118.88 +        ProductId = 0;
  118.89 +        HmdType = HmdType_None;
  118.90 +    }
  118.91 +}
  118.92 +
  118.93 +String ProfileDeviceKey::SanitizeProductName(String productName)
  118.94 +{
  118.95 +    String result;
  118.96 +
  118.97 +    if (!productName.IsEmpty())
  118.98 +    {
  118.99 +        const char* product_name = productName.ToCStr();
 118.100 +
 118.101 +        // First strip off "Oculus"
 118.102 +        const char* oculus = strstr(product_name, "Oculus ");
 118.103 +        if (oculus)
 118.104 +        {
 118.105 +            product_name = oculus + OVR_strlen("Oculus ");
 118.106 +        }
 118.107 +
 118.108 +        // And remove spaces from the name
 118.109 +        for (const char* s = product_name; *s != 0; s++)
 118.110 +        {
 118.111 +            if (*s != ' ')
 118.112 +            {
 118.113 +                result.AppendChar(*s);
 118.114 +            }
 118.115 +        }
 118.116 +    }
 118.117 +
 118.118 +    return result;
 118.119 +}
 118.120 +
 118.121 +
 118.122 +
 118.123 +//-----------------------------------------------------------------------------
 118.124 +// Returns the pathname of the JSON file containing the stored profiles
 118.125 +String GetBaseOVRPath(bool create_dir)
 118.126 +{
 118.127 +    String path;
 118.128 +
 118.129 +#if defined(OVR_OS_WIN32)
 118.130 +
 118.131 +    TCHAR data_path[MAX_PATH];
 118.132 +    SHGetFolderPath(0, CSIDL_LOCAL_APPDATA, NULL, 0, data_path);
 118.133 +    path = String(data_path);
 118.134 +    
 118.135 +    path += "/Oculus";
 118.136 +
 118.137 +    if (create_dir)
 118.138 +    {   // Create the Oculus directory if it doesn't exist
 118.139 +        WCHAR wpath[128];
 118.140 +        OVR::UTF8Util::DecodeString(wpath, path.ToCStr());
 118.141 +
 118.142 +        DWORD attrib = GetFileAttributes(wpath);
 118.143 +        bool exists = attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_DIRECTORY);
 118.144 +        if (!exists)
 118.145 +        {   
 118.146 +            CreateDirectory(wpath, NULL);
 118.147 +        }
 118.148 +    }
 118.149 +
 118.150 +#elif defined(OVR_OS_OS) // Other Microsoft OSs
 118.151 +
 118.152 +    // TODO: figure this out.
 118.153 +    OVR_UNUSED ( create_dir );
 118.154 +    path = "";
 118.155 +        
 118.156 +#elif defined(OVR_OS_MAC)
 118.157 +
 118.158 +    const char* home = getenv("HOME");
 118.159 +    path = home;
 118.160 +    path += "/Library/Preferences/Oculus";
 118.161 +
 118.162 +    if (create_dir)
 118.163 +    {   // Create the Oculus directory if it doesn't exist
 118.164 +        DIR* dir = opendir(path);
 118.165 +        if (dir == NULL)
 118.166 +        {
 118.167 +            mkdir(path, S_IRWXU | S_IRWXG | S_IRWXO);
 118.168 +        }
 118.169 +        else
 118.170 +        {
 118.171 +            closedir(dir);
 118.172 +        }
 118.173 +    }
 118.174 +
 118.175 +#else
 118.176 +
 118.177 +    const char* home = getenv("HOME");
 118.178 +    path = home;
 118.179 +    path += "/.config/Oculus";
 118.180 +
 118.181 +    if (create_dir)
 118.182 +    {   // Create the Oculus directory if it doesn't exist
 118.183 +        DIR* dir = opendir(path);
 118.184 +        if (dir == NULL)
 118.185 +        {
 118.186 +            mkdir(path, S_IRWXU | S_IRWXG | S_IRWXO);
 118.187 +        }
 118.188 +        else
 118.189 +        {
 118.190 +            closedir(dir);
 118.191 +        }
 118.192 +    }
 118.193 +
 118.194 +#endif
 118.195 +
 118.196 +    return path;
 118.197 +}
 118.198 +
 118.199 +String ProfileManager::GetProfilePath()
 118.200 +{
 118.201 +    return BasePath + "/ProfileDB.json";
 118.202 +}
 118.203 +
 118.204 +static JSON* FindTaggedData(JSON* data, const char** tag_names, const char** qtags, int num_qtags)
 118.205 +{
 118.206 +    if (data == NULL || !(data->Name == "TaggedData") || data->Type != JSON_Array)
 118.207 +        return NULL;
 118.208 +
 118.209 +    JSON* tagged_item = data->GetFirstItem();
 118.210 +    while (tagged_item)
 118.211 +    {
 118.212 +        JSON* tags = tagged_item->GetItemByName("tags");
 118.213 +        if (tags->Type == JSON_Array && num_qtags == tags->GetArraySize())
 118.214 +        {   // Check for a full tag match on each item
 118.215 +            int num_matches = 0;
 118.216 +            
 118.217 +            for (int k=0; k<num_qtags; k++)
 118.218 +            {
 118.219 +                JSON* tag = tags->GetFirstItem();
 118.220 +                while (tag)
 118.221 +                {
 118.222 +                    JSON* tagval = tag->GetFirstItem();
 118.223 +                    if (tagval && tagval->Name == tag_names[k])
 118.224 +                    {
 118.225 +                        if (tagval->Value == qtags[k])
 118.226 +                            num_matches++;
 118.227 +                        break;
 118.228 +                    }
 118.229 +                    tag = tags->GetNextItem(tag);
 118.230 +                }
 118.231 +            }
 118.232 +
 118.233 +            // if all tags were matched then copy the values into this Profile
 118.234 +            if (num_matches == num_qtags)
 118.235 +            {
 118.236 +                JSON* vals = tagged_item->GetItemByName("vals");
 118.237 +                return vals;
 118.238 +            }
 118.239 +        }
 118.240 +
 118.241 +        tagged_item = data->GetNextItem(tagged_item);
 118.242 +    }
 118.243 +
 118.244 +    return NULL;
 118.245 +}
 118.246 +
 118.247 +static void FilterTaggedData(JSON* data, const char* tag_name, const char* qtag, Array<JSON*>& items)
 118.248 +{
 118.249 +    if (data == NULL || !(data->Name == "TaggedData") || data->Type != JSON_Array)
 118.250 +        return;
 118.251 +
 118.252 +    JSON* tagged_item = data->GetFirstItem();
 118.253 +    while (tagged_item)
 118.254 +    {
 118.255 +        JSON* tags = tagged_item->GetItemByName("tags");
 118.256 +        if (tags->Type == JSON_Array)
 118.257 +        {   // Check for a tag match on the requested tag
 118.258 +            
 118.259 +            JSON* tag = tags->GetFirstItem();
 118.260 +            while (tag)
 118.261 +            {
 118.262 +                JSON* tagval = tag->GetFirstItem();
 118.263 +                if (tagval && tagval->Name == tag_name)
 118.264 +                {
 118.265 +                    if (tagval->Value == qtag)
 118.266 +                    {   // Add this item to the output list
 118.267 +                        items.PushBack(tagged_item);
 118.268 +                    }
 118.269 +                    break;
 118.270 +                }
 118.271 +                tag = tags->GetNextItem(tag);
 118.272 +            }
 118.273 +        }
 118.274 +
 118.275 +        tagged_item = data->GetNextItem(tagged_item);
 118.276 +    }
 118.277 +}
 118.278 +
 118.279 +
 118.280 +//-----------------------------------------------------------------------------
 118.281 +// ***** ProfileManager
 118.282 +
 118.283 +template<> ProfileManager* OVR::SystemSingletonBase<ProfileManager>::SlowGetInstance()
 118.284 +{
 118.285 +    static OVR::Lock lock;
 118.286 +    OVR::Lock::Locker locker(&lock);
 118.287 +    if (!SingletonInstance) SingletonInstance = new ProfileManager(true);
 118.288 +    return SingletonInstance;
 118.289 +}
 118.290 +
 118.291 +ProfileManager::ProfileManager(bool sys_register) :
 118.292 +    Changed(false)
 118.293 +{
 118.294 +    // Attempt to get the base path automatically, but this may fail
 118.295 +    BasePath = GetBaseOVRPath(false);
 118.296 +
 118.297 +    if (sys_register)
 118.298 +        PushDestroyCallbacks();
 118.299 +}
 118.300 +
 118.301 +ProfileManager::~ProfileManager()
 118.302 +{
 118.303 +    ClearProfileData();
 118.304 +}
 118.305 +
 118.306 +void ProfileManager::OnSystemDestroy()
 118.307 +{
 118.308 +    delete this;
 118.309 +}
 118.310 +
 118.311 +// In the service process it is important to set the base path because this cannot be detected automatically
 118.312 +void ProfileManager::SetBasePath(String basePath)
 118.313 +{
 118.314 +    if (basePath != BasePath)
 118.315 +    {
 118.316 +        BasePath = basePath;
 118.317 +        LoadCache(false);
 118.318 +    }
 118.319 +}
 118.320 +
 118.321 +// Clear the local profile cache
 118.322 +void ProfileManager::ClearProfileData()
 118.323 +{
 118.324 +    Lock::Locker lockScope(&ProfileLock);
 118.325 +
 118.326 +    ProfileCache.Clear();
 118.327 +    Changed = false;
 118.328 +}
 118.329 +
 118.330 +// Serializes the profiles to disk.
 118.331 +void ProfileManager::Save()
 118.332 +{
 118.333 +    Lock::Locker lockScope(&ProfileLock);
 118.334 +
 118.335 +    if (ProfileCache == NULL)
 118.336 +        return;
 118.337 +
 118.338 +    // Save the profile to disk
 118.339 +    BasePath = GetBaseOVRPath(true);  // create the base directory if it doesn't exist
 118.340 +    String path = GetProfilePath();
 118.341 +    ProfileCache->Save(path);
 118.342 +    Changed = false;
 118.343 +}
 118.344 +
 118.345 +// Returns a profile with all system default values
 118.346 +Profile* ProfileManager::GetDefaultProfile(HmdTypeEnum device)
 118.347 +{
 118.348 +    // In the absence of any data, set some reasonable profile defaults.
 118.349 +    // However, this is not future proof and developers should still
 118.350 +    // provide reasonable default values for queried fields.
 118.351 +    
 118.352 +    // Biometric data
 118.353 +    Profile* profile = CreateProfile();
 118.354 +    profile->SetValue(OVR_KEY_USER,               "default");
 118.355 +    profile->SetValue(OVR_KEY_NAME,               "Default");
 118.356 +    profile->SetValue(OVR_KEY_GENDER,             OVR_DEFAULT_GENDER);
 118.357 +    profile->SetFloatValue(OVR_KEY_PLAYER_HEIGHT, OVR_DEFAULT_PLAYER_HEIGHT);
 118.358 +    profile->SetFloatValue(OVR_KEY_EYE_HEIGHT,    OVR_DEFAULT_EYE_HEIGHT);
 118.359 +    profile->SetFloatValue(OVR_KEY_IPD,           OVR_DEFAULT_IPD);
 118.360 +    float half_ipd[2] = { OVR_DEFAULT_IPD / 2, OVR_DEFAULT_IPD / 2 };
 118.361 +    profile->SetFloatValues(OVR_KEY_EYE_TO_NOSE_DISTANCE, half_ipd, 2);
 118.362 +    float dist[2] = {OVR_DEFAULT_NECK_TO_EYE_HORIZONTAL, OVR_DEFAULT_NECK_TO_EYE_VERTICAL};
 118.363 +    profile->SetFloatValues(OVR_KEY_NECK_TO_EYE_DISTANCE, dist, 2);
 118.364 +    
 118.365 +    // Device specific data
 118.366 +    if (device != HmdType_None)
 118.367 +    {
 118.368 +        if (device == HmdType_CrystalCoveProto || device == HmdType_DK2)
 118.369 +        {
 118.370 +            profile->SetValue("EyeCup", "A");
 118.371 +            profile->SetIntValue(OVR_KEY_EYE_RELIEF_DIAL, OVR_DEFAULT_EYE_RELIEF_DIAL);
 118.372 +
 118.373 +            // TODO: These defaults are a little bogus and designed for continuity with 0.3
 118.374 +            // eye-relief values.  We need better measurement-based numbers in future releases
 118.375 +            float max_eye_plate[2] = { 0.01965f + 0.018f, 0.01965f + 0.018f };
 118.376 +            profile->SetFloatValues(OVR_KEY_MAX_EYE_TO_PLATE_DISTANCE, max_eye_plate, 2);
 118.377 +        }
 118.378 +        else
 118.379 +        {   // DK1 and DKHD variants
 118.380 +            profile->SetValue("EyeCup", "A");
 118.381 +            profile->SetIntValue(OVR_KEY_EYE_RELIEF_DIAL, OVR_DEFAULT_EYE_RELIEF_DIAL);
 118.382 +
 118.383 +            // TODO: These defaults are a little bogus and designed for continuity with 0.3
 118.384 +            // DK1 distortion.  We need better measurement-based numbers in future releases
 118.385 +            float max_eye_plate[2] = { 0.02357f + 0.017f, 0.02357f + 0.017f };
 118.386 +            profile->SetFloatValues(OVR_KEY_MAX_EYE_TO_PLATE_DISTANCE, max_eye_plate, 2);
 118.387 +        }
 118.388 +    }
 118.389 +
 118.390 +    return profile;
 118.391 +}
 118.392 +
 118.393 +//------------------------------------------------------------------------------
 118.394 +void ProfileManager::Read()
 118.395 +{
 118.396 +    LoadCache(false);
 118.397 +}
 118.398 +
 118.399 +// Populates the local profile cache.  This occurs on the first access of the profile
 118.400 +// data.  All profile operations are performed against the local cache until the
 118.401 +// ProfileManager is released or goes out of scope at which time the cache is serialized
 118.402 +// to disk.
 118.403 +void ProfileManager::LoadCache(bool create)
 118.404 +{
 118.405 +    Lock::Locker lockScope(&ProfileLock);
 118.406 +
 118.407 +    ClearProfileData();
 118.408 +
 118.409 +    String path = GetProfilePath();
 118.410 +
 118.411 +    Ptr<JSON> root = *JSON::Load(path);
 118.412 +    if (root == NULL)
 118.413 +    {   
 118.414 +        path = BasePath + "/Profiles.json";  // look for legacy profile
 118.415 +        root = *JSON::Load(path);
 118.416 +        
 118.417 +        if (root == NULL)
 118.418 +        {
 118.419 +            if (create)
 118.420 +            {   // Generate a skeleton profile database
 118.421 +                root = *JSON::CreateObject();
 118.422 +                root->AddNumberItem("Oculus Profile Version", 2.0);
 118.423 +                root->AddItem("Users", JSON::CreateArray());
 118.424 +                root->AddItem("TaggedData", JSON::CreateArray());
 118.425 +                ProfileCache = root;
 118.426 +            }
 118.427 +            
 118.428 +            return;
 118.429 +        }
 118.430 +
 118.431 +        // Verify the legacy version
 118.432 +        JSON* version_item = root->GetFirstItem();
 118.433 +        if (version_item->Name == "Oculus Profile Version")
 118.434 +        {
 118.435 +            int major = atoi(version_item->Value.ToCStr());
 118.436 +            if (major != 1)
 118.437 +                return;   // don't use the file on unsupported major version number
 118.438 +        }
 118.439 +        else
 118.440 +        {
 118.441 +            return;      // invalid file
 118.442 +        }
 118.443 +
 118.444 +        // Convert the legacy format to the new database format
 118.445 +        LoadV1Profiles(root);
 118.446 +    }
 118.447 +    else
 118.448 +    {
 118.449 +        // Verify the file format and version
 118.450 +        JSON* version_item = root->GetFirstItem();
 118.451 +        if (version_item && version_item->Name == "Oculus Profile Version")
 118.452 +        {
 118.453 +            int major = atoi(version_item->Value.ToCStr());
 118.454 +            if (major != 2)
 118.455 +                return;   // don't use the file on unsupported major version number
 118.456 +        }
 118.457 +        else
 118.458 +        {
 118.459 +            return;       // invalid file 
 118.460 +        }
 118.461 +
 118.462 +        ProfileCache = root;   // store the database contents for traversal
 118.463 +    }
 118.464 +}
 118.465 +
 118.466 +void ProfileManager::LoadV1Profiles(JSON* v1)
 118.467 +{
 118.468 +    JSON* item0 = v1->GetFirstItem();
 118.469 +    JSON* item1 = v1->GetNextItem(item0);
 118.470 +    JSON* item2 = v1->GetNextItem(item1);
 118.471 +
 118.472 +    OVR_ASSERT(item1 && item2);
 118.473 +    if(!item1 || !item2)
 118.474 +        return;
 118.475 +
 118.476 +    // Create the new profile database
 118.477 +    Ptr<JSON> root = *JSON::CreateObject();
 118.478 +    root->AddNumberItem("Oculus Profile Version", 2.0);
 118.479 +    root->AddItem("Users", JSON::CreateArray());
 118.480 +    root->AddItem("TaggedData", JSON::CreateArray());
 118.481 +    ProfileCache = root;
 118.482 +
 118.483 +    const char* default_dk1_user = item1->Value;
 118.484 +    
 118.485 +    // Read the number of profiles
 118.486 +    int   profileCount = (int)item2->dValue;
 118.487 +    JSON* profileItem  = item2;
 118.488 +
 118.489 +    for (int p=0; p<profileCount; p++)
 118.490 +    {
 118.491 +        profileItem = root->GetNextItem(profileItem);
 118.492 +        if (profileItem == NULL)
 118.493 +            break;
 118.494 +
 118.495 +        if (profileItem->Name == "Profile")
 118.496 +        {
 118.497 +            // Read the required Name field
 118.498 +            const char* profileName;
 118.499 +            JSON* item = profileItem->GetFirstItem();
 118.500 +        
 118.501 +            if (item && (item->Name == "Name"))
 118.502 +            {   
 118.503 +                profileName = item->Value;
 118.504 +            }
 118.505 +            else
 118.506 +            {
 118.507 +                return;   // invalid field
 118.508 +            }
 118.509 +            
 118.510 +            // Read the user profile fields
 118.511 +            if (CreateUser(profileName, profileName))
 118.512 +            {
 118.513 +                const char* tag_names[2] = {"User", "Product"};
 118.514 +                const char* tags[2];
 118.515 +                tags[0] = profileName;
 118.516 +
 118.517 +                Ptr<Profile> user_profile = *CreateProfile();
 118.518 +                user_profile->SetValue(OVR_KEY_NAME, profileName);
 118.519 +
 118.520 +                float neckeye[2] = { 0, 0 };
 118.521 +
 118.522 +                item = profileItem->GetNextItem(item);
 118.523 +                while (item)
 118.524 +                {
 118.525 +                    if (item->Type != JSON_Object)
 118.526 +                    {
 118.527 +                        if (item->Name == OVR_KEY_PLAYER_HEIGHT)
 118.528 +                        {   // Add an explicit eye height
 118.529 +
 118.530 +                        }
 118.531 +                        if (item->Name == "NeckEyeHori")
 118.532 +                            neckeye[0] = (float)item->dValue;
 118.533 +                        else if (item->Name == "NeckEyeVert")
 118.534 +                            neckeye[1] = (float)item->dValue;
 118.535 +                        else 
 118.536 +                            user_profile->SetValue(item);
 118.537 +                    }
 118.538 +                    else
 118.539 +                    {   
 118.540 +                        // Add the user/device tag values
 118.541 +                        const char* device_name = item->Name.ToCStr();
 118.542 +                        Ptr<Profile> device_profile = *CreateProfile();
 118.543 +
 118.544 +                        JSON* device_item = item->GetFirstItem();
 118.545 +                        while (device_item)
 118.546 +                        {
 118.547 +                            device_profile->SetValue(device_item);
 118.548 +                            device_item = item->GetNextItem(device_item);
 118.549 +                        }
 118.550 +
 118.551 +                        tags[1] = device_name;
 118.552 +                        SetTaggedProfile(tag_names, tags, 2, device_profile);
 118.553 +                    }
 118.554 +
 118.555 +                    item = profileItem->GetNextItem(item);
 118.556 +                }
 118.557 +
 118.558 +                // Add an explicit eye-height field
 118.559 +                float player_height = user_profile->GetFloatValue(OVR_KEY_PLAYER_HEIGHT,
 118.560 +                                                                  OVR_DEFAULT_PLAYER_HEIGHT);
 118.561 +                if (player_height > 0)
 118.562 +                {
 118.563 +                    char gender[16];
 118.564 +                    user_profile->GetValue(OVR_KEY_GENDER, gender, 16);
 118.565 +        
 118.566 +                    const float EYE_TO_HEADTOP_RATIO =   0.44538f;
 118.567 +                    const float MALE_AVG_HEAD_HEIGHT =   0.232f;
 118.568 +                    const float FEMALE_AVG_HEAD_HEIGHT = 0.218f;
 118.569 +     
 118.570 +                    // compute distance from top of skull to the eye
 118.571 +                    float head_height;
 118.572 +                    if (OVR_strcmp(gender, "Female") == 0)
 118.573 +                        head_height = FEMALE_AVG_HEAD_HEIGHT;
 118.574 +                    else
 118.575 +                        head_height = MALE_AVG_HEAD_HEIGHT;
 118.576 +
 118.577 +                    float skull = EYE_TO_HEADTOP_RATIO * head_height;
 118.578 +                    float eye_height = player_height - skull;
 118.579 +
 118.580 +                    user_profile->SetFloatValue(OVR_KEY_EYE_HEIGHT, eye_height);
 118.581 +                }
 118.582 +
 118.583 +                // Convert NeckEye values to an array
 118.584 +                if (neckeye[0] > 0 && neckeye[1] > 0)
 118.585 +                    user_profile->SetFloatValues(OVR_KEY_NECK_TO_EYE_DISTANCE, neckeye, 2);
 118.586 +
 118.587 +                // Add the user tag values
 118.588 +                SetTaggedProfile(tag_names, tags, 1, user_profile);
 118.589 +            }
 118.590 +        }
 118.591 +    }
 118.592 +
 118.593 +    // since V1 profiles were only for DK1, the assign the user to all DK1's
 118.594 +    const char* tag_names[1] = { "Product" };
 118.595 +    const char* tags[1] = { "RiftDK1" };
 118.596 +    Ptr<Profile> product_profile = *CreateProfile();
 118.597 +    product_profile->SetValue("DefaultUser", default_dk1_user);
 118.598 +    SetTaggedProfile(tag_names, tags, 1, product_profile);
 118.599 +}
 118.600 +
 118.601 +// Returns the number of stored profiles for this device type
 118.602 +int ProfileManager::GetUserCount()
 118.603 +{
 118.604 +    Lock::Locker lockScope(&ProfileLock);
 118.605 +
 118.606 +    if (ProfileCache == NULL)
 118.607 +    {   // Load the cache
 118.608 +        LoadCache(false);
 118.609 +        if (ProfileCache == NULL)
 118.610 +            return 0;
 118.611 +    }
 118.612 +
 118.613 +    JSON* users = ProfileCache->GetItemByName("Users");
 118.614 +    if (users == NULL)
 118.615 +        return 0;
 118.616 +
 118.617 +    return users->GetItemCount();
 118.618 +}
 118.619 +
 118.620 +bool ProfileManager::CreateUser(const char* user, const char* name)
 118.621 +{
 118.622 +    Lock::Locker lockScope(&ProfileLock);
 118.623 +
 118.624 +    if (ProfileCache == NULL)
 118.625 +    {   // Load the cache
 118.626 +        LoadCache(true);
 118.627 +        if (ProfileCache == NULL)
 118.628 +            return false;
 118.629 +    }
 118.630 +
 118.631 +    JSON* users = ProfileCache->GetItemByName("Users");
 118.632 +    if (users == NULL)
 118.633 +    {   // Generate the User section
 118.634 +        users = JSON::CreateArray();
 118.635 +        ProfileCache->AddItem("Users", users);
 118.636 +//TODO: Insert this before the TaggedData
 118.637 +    }
 118.638 +
 118.639 +    // Search for the pre-existence of this user
 118.640 +    JSON* user_item = users->GetFirstItem();
 118.641 +    int index = 0;
 118.642 +    while (user_item)
 118.643 +    {
 118.644 +        JSON* userid = user_item->GetItemByName("User");
 118.645 +        int compare = OVR_strcmp(user, userid->Value);
 118.646 +        if (compare == 0)
 118.647 +        {   // The user already exists so simply update the fields
 118.648 +            JSON* name_item = user_item->GetItemByName("Name");
 118.649 +            if (name_item && OVR_strcmp(name, name_item->Value) != 0)
 118.650 +            {
 118.651 +                name_item->Value = name;
 118.652 +                Changed = true;
 118.653 +            }
 118.654 +            return true;
 118.655 +        }
 118.656 +        else if (compare < 0)
 118.657 +        {   // A new user should be placed before this item
 118.658 +            break;
 118.659 +        }
 118.660 +        
 118.661 +        user_item = users->GetNextItem(user_item);
 118.662 +        index++;
 118.663 +    }
 118.664 +
 118.665 +    // Create and fill the user struct
 118.666 +    JSON* new_user = JSON::CreateObject();
 118.667 +    new_user->AddStringItem(OVR_KEY_USER, user);
 118.668 +    new_user->AddStringItem(OVR_KEY_NAME, name);
 118.669 +    // user_item->AddStringItem("Password", password);
 118.670 +
 118.671 +    if (user_item == NULL)
 118.672 +        users->AddArrayElement(new_user);
 118.673 +    else
 118.674 +        users->InsertArrayElement(index, new_user);
 118.675 +
 118.676 +    Changed = true;
 118.677 +    return true;
 118.678 +}
 118.679 +
 118.680 +bool ProfileManager::HasUser(const char* user)
 118.681 +{
 118.682 +	Lock::Locker lockScope(&ProfileLock);
 118.683 +
 118.684 +	if (ProfileCache == NULL)
 118.685 +	{   // Load the cache
 118.686 +		LoadCache(false);
 118.687 +		if (ProfileCache == NULL)
 118.688 +			return false;
 118.689 +	}
 118.690 +
 118.691 +	JSON* users = ProfileCache->GetItemByName("Users");
 118.692 +	if (users == NULL)
 118.693 +		return false;
 118.694 +
 118.695 +	// Remove this user from the User table
 118.696 +	JSON* user_item = users->GetFirstItem();
 118.697 +	while (user_item)
 118.698 +	{
 118.699 +		JSON* userid = user_item->GetItemByName("User");
 118.700 +		if (OVR_strcmp(user, userid->Value) == 0)
 118.701 +		{   
 118.702 +			return true;
 118.703 +		}
 118.704 +
 118.705 +		user_item = users->GetNextItem(user_item);
 118.706 +	}
 118.707 +
 118.708 +	return false;
 118.709 +}
 118.710 +
 118.711 +// Returns the user id of a specific user in the list.  The returned 
 118.712 +// memory is locally allocated and should not be stored or deleted.  Returns NULL
 118.713 +// if the index is invalid
 118.714 +const char* ProfileManager::GetUser(unsigned int index)
 118.715 +{
 118.716 +    Lock::Locker lockScope(&ProfileLock);
 118.717 +
 118.718 +    if (ProfileCache == NULL)
 118.719 +    {   // Load the cache
 118.720 +        LoadCache(false);
 118.721 +        if (ProfileCache == NULL)
 118.722 +            return NULL;
 118.723 +    }
 118.724 +
 118.725 +    JSON* users = ProfileCache->GetItemByName("Users");
 118.726 +    
 118.727 +    if (users && index < users->GetItemCount())
 118.728 +    {
 118.729 +        JSON* user_item = users->GetItemByIndex(index);
 118.730 +        if (user_item)
 118.731 +        {
 118.732 +            JSON* user = user_item->GetFirstItem();
 118.733 +            if (user)
 118.734 +            {
 118.735 +                JSON* userid = user_item->GetItemByName(OVR_KEY_USER);
 118.736 +                if (userid)
 118.737 +                    return userid->Value.ToCStr();
 118.738 +            }
 118.739 +        }
 118.740 +    }
 118.741 +    
 118.742 +
 118.743 +    return NULL;
 118.744 +}
 118.745 +
 118.746 +bool ProfileManager::RemoveUser(const char* user)
 118.747 +{
 118.748 +    Lock::Locker lockScope(&ProfileLock);
 118.749 +
 118.750 +    if (ProfileCache == NULL)
 118.751 +    {   // Load the cache
 118.752 +        LoadCache(false);
 118.753 +        if (ProfileCache == NULL)
 118.754 +            return true;
 118.755 +    }
 118.756 +
 118.757 +    JSON* users = ProfileCache->GetItemByName("Users");
 118.758 +    if (users == NULL)
 118.759 +        return true;
 118.760 +
 118.761 +    // Remove this user from the User table
 118.762 +    JSON* user_item = users->GetFirstItem();
 118.763 +    while (user_item)
 118.764 +    {
 118.765 +        JSON* userid = user_item->GetItemByName("User");
 118.766 +        if (OVR_strcmp(user, userid->Value) == 0)
 118.767 +        {   // Delete the user entry
 118.768 +            user_item->RemoveNode();
 118.769 +            user_item->Release();
 118.770 +            Changed = true;
 118.771 +            break;
 118.772 +        }
 118.773 +        
 118.774 +        user_item = users->GetNextItem(user_item);
 118.775 +    }
 118.776 +
 118.777 +    // Now remove all data entries with this user tag
 118.778 +    JSON* tagged_data = ProfileCache->GetItemByName("TaggedData");
 118.779 +    Array<JSON*> user_items;
 118.780 +    FilterTaggedData(tagged_data, "User", user, user_items);
 118.781 +    for (unsigned int i=0; i<user_items.GetSize(); i++)
 118.782 +    {
 118.783 +        user_items[i]->RemoveNode();
 118.784 +        user_items[i]->Release();
 118.785 +        Changed = true;
 118.786 +    }
 118.787 + 
 118.788 +    return Changed;
 118.789 +}
 118.790 +
 118.791 +Profile* ProfileManager::CreateProfile()
 118.792 +{
 118.793 +    Profile* profile = new Profile(BasePath);
 118.794 +    return profile;
 118.795 +}
 118.796 +
 118.797 +const char* ProfileManager::GetDefaultUser(const ProfileDeviceKey& deviceKey)
 118.798 +{
 118.799 +    const char* product_str = deviceKey.ProductName.IsEmpty() ? NULL : deviceKey.ProductName.ToCStr();
 118.800 +    const char* serial_str = deviceKey.PrintedSerial.IsEmpty() ? NULL : deviceKey.PrintedSerial.ToCStr();
 118.801 +
 118.802 +    return GetDefaultUser(product_str, serial_str);
 118.803 +}
 118.804 +
 118.805 +// Returns the name of the profile that is marked as the current default user.
 118.806 +const char* ProfileManager::GetDefaultUser(const char* product, const char* serial)
 118.807 +{
 118.808 +    const char* tag_names[2] = {"Product", "Serial"};
 118.809 +    const char* tags[2];
 118.810 +
 118.811 +    if (product && serial)
 118.812 +    {
 118.813 +        tags[0] = product;
 118.814 +        tags[1] = serial;
 118.815 +        // Look for a default user on this specific device
 118.816 +        Ptr<Profile> p = *GetTaggedProfile(tag_names, tags, 2);
 118.817 +        if (p == NULL)
 118.818 +        {   // Look for a default user on this product
 118.819 +            p = *GetTaggedProfile(tag_names, tags, 1);
 118.820 +        }
 118.821 +
 118.822 +        if (p)
 118.823 +        {   
 118.824 +            const char* user = p->GetValue("DefaultUser");
 118.825 +            if (user != NULL && user[0] != 0)
 118.826 +            {
 118.827 +                TempBuff = user;
 118.828 +                return TempBuff.ToCStr();
 118.829 +            }
 118.830 +        }
 118.831 +    }
 118.832 +
 118.833 +    return NULL;
 118.834 +}
 118.835 +
 118.836 +//-----------------------------------------------------------------------------
 118.837 +bool ProfileManager::SetDefaultUser(const ProfileDeviceKey& deviceKey, const char* user)
 118.838 +{
 118.839 +    const char* tag_names[2] = {"Product", "Serial"};
 118.840 +    const char* tags[2];
 118.841 +
 118.842 +    const char* product_str = deviceKey.ProductName.IsEmpty() ? NULL : deviceKey.ProductName.ToCStr();
 118.843 +    const char* serial_str = deviceKey.PrintedSerial.IsEmpty() ? NULL : deviceKey.PrintedSerial.ToCStr();
 118.844 +
 118.845 +    if (product_str && serial_str)
 118.846 +    {
 118.847 +        tags[0] = product_str;
 118.848 +        tags[1] = serial_str;
 118.849 +
 118.850 +        Ptr<Profile> p = *CreateProfile();
 118.851 +        p->SetValue("DefaultUser", user);
 118.852 +        return SetTaggedProfile(tag_names, tags, 2, p);
 118.853 +    }
 118.854 +
 118.855 +    return false;
 118.856 +}
 118.857 +
 118.858 +//-----------------------------------------------------------------------------
 118.859 +Profile* ProfileManager::GetTaggedProfile(const char** tag_names, const char** tags, int num_tags)
 118.860 +{
 118.861 +    Lock::Locker lockScope(&ProfileLock);
 118.862 +
 118.863 +    if (ProfileCache == NULL)
 118.864 +    {   // Load the cache
 118.865 +        LoadCache(false);
 118.866 +        if (ProfileCache == NULL)
 118.867 +            return NULL;
 118.868 +    }
 118.869 +
 118.870 +    JSON* tagged_data = ProfileCache->GetItemByName("TaggedData");
 118.871 +    OVR_ASSERT(tagged_data);
 118.872 +    if (tagged_data == NULL)
 118.873 +        return NULL;
 118.874 +    
 118.875 +    Profile* profile = new Profile(BasePath);
 118.876 +    
 118.877 +    JSON* vals = FindTaggedData(tagged_data, tag_names, tags, num_tags);
 118.878 +    if (vals)
 118.879 +    {   
 118.880 +        JSON* item = vals->GetFirstItem();
 118.881 +        while (item)
 118.882 +        {
 118.883 +            //printf("Add %s, %s\n", item->Name.ToCStr(), item->Value.ToCStr());
 118.884 +            //profile->Settings.Set(item->Name, item->Value);
 118.885 +            profile->SetValue(item);
 118.886 +            item = vals->GetNextItem(item);
 118.887 +        }
 118.888 +
 118.889 +        return profile;
 118.890 +    }
 118.891 +    else
 118.892 +    {
 118.893 +        profile->Release();
 118.894 +        return NULL;
 118.895 +    }
 118.896 +}
 118.897 +
 118.898 +//-----------------------------------------------------------------------------
 118.899 +bool ProfileManager::SetTaggedProfile(const char** tag_names, const char** tags, int num_tags, Profile* profile)
 118.900 +{
 118.901 +    Lock::Locker lockScope(&ProfileLock);
 118.902 +
 118.903 +    if (ProfileCache == NULL)
 118.904 +    {   // Load the cache
 118.905 +        LoadCache(true);
 118.906 +        if (ProfileCache == NULL)
 118.907 +            return false;  // TODO: Generate a new profile DB
 118.908 +    }
 118.909 +
 118.910 +    JSON* tagged_data = ProfileCache->GetItemByName("TaggedData");
 118.911 +    OVR_ASSERT(tagged_data);
 118.912 +    if (tagged_data == NULL)
 118.913 +        return false;
 118.914 +
 118.915 +    // Get the cached tagged data section
 118.916 +    JSON* vals = FindTaggedData(tagged_data, tag_names, tags, num_tags);
 118.917 +    if (vals == NULL)
 118.918 +    {  
 118.919 +        JSON* tagged_item = JSON::CreateObject();
 118.920 +        JSON* taglist = JSON::CreateArray();
 118.921 +        for (int i=0; i<num_tags; i++)
 118.922 +        {
 118.923 +            JSON* k = JSON::CreateObject();
 118.924 +            k->AddStringItem(tag_names[i], tags[i]);
 118.925 +            taglist->AddArrayElement(k);
 118.926 +        }
 118.927 +
 118.928 +        vals = JSON::CreateObject();
 118.929 +        
 118.930 +        tagged_item->AddItem("tags", taglist);
 118.931 +        tagged_item->AddItem("vals", vals);
 118.932 +        tagged_data->AddArrayElement(tagged_item);
 118.933 +    }
 118.934 +
 118.935 +    // Now add or update each profile setting in cache
 118.936 +    for (unsigned int i=0; i<profile->Values.GetSize(); i++)
 118.937 +    {
 118.938 +        JSON* value = profile->Values[i];
 118.939 +        
 118.940 +        bool found = false;
 118.941 +        JSON* item = vals->GetFirstItem();
 118.942 +        while (item)
 118.943 +        {
 118.944 +            if (value->Name == item->Name)
 118.945 +            {
 118.946 +                // Don't allow a pre-existing type to be overridden
 118.947 +                OVR_ASSERT(value->Type == item->Type);
 118.948 +
 118.949 +                if (value->Type == item->Type)
 118.950 +                {   // Check for the same value
 118.951 +                    if (value->Type == JSON_Array)
 118.952 +                    {   // Update each array item
 118.953 +                        if (item->GetArraySize() == value->GetArraySize())
 118.954 +                        {   // Update each value (assumed to be basic types and not array of objects)
 118.955 +                            JSON* value_element = value->GetFirstItem();
 118.956 +                            JSON* item_element = item->GetFirstItem();
 118.957 +                            while (item_element && value_element)
 118.958 +                            {
 118.959 +                                if (value_element->Type == JSON_String)
 118.960 +                                {
 118.961 +                                    if (item_element->Value != value_element->Value)
 118.962 +                                    {   // Overwrite the changed value and mark for file update
 118.963 +                                        item_element->Value = value_element->Value;
 118.964 +                                        Changed = true;
 118.965 +                                    }
 118.966 +                                }
 118.967 +                                else {
 118.968 +                                    if (item_element->dValue != value_element->dValue)
 118.969 +                                    {   // Overwrite the changed value and mark for file update
 118.970 +                                        item_element->dValue = value_element->dValue;
 118.971 +                                        Changed = true;
 118.972 +                                    }
 118.973 +                                }
 118.974 +                                
 118.975 +                                value_element = value->GetNextItem(value_element);
 118.976 +                                item_element = item->GetNextItem(item_element);
 118.977 +                            }
 118.978 +                        }
 118.979 +                        else
 118.980 +                        {   // if the array size changed, simply create a new one                            
 118.981 +// TODO: Create the new array
 118.982 +                        }
 118.983 +                    }
 118.984 +                    else if (value->Type == JSON_String)
 118.985 +                    {
 118.986 +                        if (item->Value != value->Value)
 118.987 +                        {   // Overwrite the changed value and mark for file update
 118.988 +                            item->Value = value->Value;
 118.989 +                            Changed = true;
 118.990 +                        }
 118.991 +                    }
 118.992 +                    else {
 118.993 +                        if (item->dValue != value->dValue)
 118.994 +                        {   // Overwrite the changed value and mark for file update
 118.995 +                            item->dValue = value->dValue;
 118.996 +                            Changed = true;
 118.997 +                        }
 118.998 +                    }
 118.999 +                }
118.1000 +                else
118.1001 +                {
118.1002 +                    return false;
118.1003 +                }
118.1004 +
118.1005 +                found = true;
118.1006 +                break;
118.1007 +            }
118.1008 +            
118.1009 +            item = vals->GetNextItem(item);
118.1010 +        }
118.1011 +
118.1012 +        if (!found)
118.1013 +        {   // Add the new value
118.1014 +            Changed = true;
118.1015 +
118.1016 +            if (value->Type == JSON_String)
118.1017 +                vals->AddStringItem(value->Name, value->Value);
118.1018 +            else if (value->Type == JSON_Bool)
118.1019 +                vals->AddBoolItem(value->Name, ((int)value->dValue != 0));
118.1020 +            else if (value->Type == JSON_Number)
118.1021 +                vals->AddNumberItem(value->Name, value->dValue);
118.1022 +            else if (value->Type == JSON_Array)
118.1023 +                vals->AddItem(value->Name, value->Copy());
118.1024 +            else
118.1025 +            {
118.1026 +                OVR_ASSERT(false);
118.1027 +                Changed = false;
118.1028 +            }
118.1029 +        }
118.1030 +    }
118.1031 +
118.1032 +    return true;
118.1033 +}
118.1034 +
118.1035 +//-----------------------------------------------------------------------------
118.1036 +Profile* ProfileManager::GetDefaultUserProfile(const ProfileDeviceKey& deviceKey)
118.1037 +{
118.1038 +    const char* userName = GetDefaultUser(deviceKey);
118.1039 +
118.1040 +    Profile* profile = GetProfile(deviceKey, userName);
118.1041 +
118.1042 +    if (!profile)
118.1043 +    {
118.1044 +        profile = GetDefaultProfile(deviceKey.HmdType);
118.1045 +    }
118.1046 +
118.1047 +    return profile;
118.1048 +}
118.1049 +
118.1050 +//-----------------------------------------------------------------------------
118.1051 +Profile* ProfileManager::GetProfile(const ProfileDeviceKey& deviceKey, const char* user)
118.1052 +{
118.1053 +    Lock::Locker lockScope(&ProfileLock);
118.1054 +
118.1055 +    if (ProfileCache == NULL)
118.1056 +    {   // Load the cache
118.1057 +        LoadCache(false);
118.1058 +        if (ProfileCache == NULL)
118.1059 +            return NULL;
118.1060 +    }
118.1061 +    
118.1062 +    Profile* profile = new Profile(BasePath);
118.1063 +
118.1064 +    if (deviceKey.Valid)
118.1065 +    {
118.1066 +        if (!profile->LoadDeviceProfile(deviceKey) && (user == NULL))
118.1067 +        {
118.1068 +            profile->Release();
118.1069 +            return NULL;
118.1070 +        }
118.1071 +    }
118.1072 +    
118.1073 +    if (user)
118.1074 +    {
118.1075 +        const char* product_str = deviceKey.ProductName.IsEmpty() ? NULL : deviceKey.ProductName.ToCStr();
118.1076 +        const char* serial_str = deviceKey.PrintedSerial.IsEmpty() ? NULL : deviceKey.PrintedSerial.ToCStr();
118.1077 +
118.1078 +        if (!profile->LoadProfile(ProfileCache.GetPtr(), user, product_str, serial_str))
118.1079 +        {
118.1080 +            profile->Release();
118.1081 +            return NULL;
118.1082 +        }
118.1083 +    }
118.1084 +
118.1085 +    return profile;
118.1086 +}
118.1087 +
118.1088 +
118.1089 +//-----------------------------------------------------------------------------
118.1090 +// ***** Profile
118.1091 +
118.1092 +Profile::~Profile()
118.1093 +{
118.1094 +    ValMap.Clear();
118.1095 +    for (unsigned int i=0; i<Values.GetSize(); i++)
118.1096 +        Values[i]->Release();
118.1097 +
118.1098 +    Values.Clear();
118.1099 +}
118.1100 +
118.1101 +bool Profile::Close()
118.1102 +{
118.1103 +    // TODO:
118.1104 +    return true;
118.1105 +}
118.1106 +
118.1107 +//-----------------------------------------------------------------------------
118.1108 +void Profile::CopyItems(JSON* root, String prefix)
118.1109 +{
118.1110 +    JSON* item = root->GetFirstItem();
118.1111 +    while (item)
118.1112 +    {
118.1113 +        String item_name;
118.1114 +        if (prefix.IsEmpty())
118.1115 +            item_name = item->Name;
118.1116 +        else
118.1117 +            item_name = prefix + "." + item->Name;
118.1118 +
118.1119 +        if (item->Type == JSON_Object)
118.1120 +        {   // recursively copy the children
118.1121 +            
118.1122 +            CopyItems(item, item_name);
118.1123 +        }
118.1124 +        else
118.1125 +        {
118.1126 +            //Settings.Set(item_name, item->Value);
118.1127 +            SetValue(item);
118.1128 +        }
118.1129 +
118.1130 +        item = root->GetNextItem(item);
118.1131 +    }
118.1132 +}
118.1133 +
118.1134 +//-----------------------------------------------------------------------------
118.1135 +bool Profile::LoadDeviceFile(unsigned int productId, const char* printedSerialNumber)
118.1136 +{
118.1137 +    if (printedSerialNumber[0] == 0)
118.1138 +        return false;
118.1139 +
118.1140 +    String path = BasePath + "/Devices.json";
118.1141 +
118.1142 +    // Load the device profiles
118.1143 +    Ptr<JSON> root = *JSON::Load(path);
118.1144 +    if (root == NULL)
118.1145 +        return false;
118.1146 +
118.1147 +    // Quick sanity check of the file type and format before we parse it
118.1148 +    JSON* version = root->GetFirstItem();
118.1149 +    if (version && version->Name == "Oculus Device Profile Version")
118.1150 +    {   
118.1151 +        int major = atoi(version->Value.ToCStr());
118.1152 +        if (major > MAX_DEVICE_PROFILE_MAJOR_VERSION)
118.1153 +            return false;   // don't parse the file on unsupported major version number
118.1154 +    }
118.1155 +    else
118.1156 +    {
118.1157 +        return false;
118.1158 +    }   
118.1159 +
118.1160 +    JSON* device = root->GetNextItem(version);
118.1161 +    while (device)
118.1162 +    {   
118.1163 +        if (device->Name == "Device")
118.1164 +        {   
118.1165 +            JSON* product_item = device->GetItemByName("ProductID");
118.1166 +            JSON* serial_item = device->GetItemByName("Serial");
118.1167 +            if (product_item && serial_item &&
118.1168 +                (product_item->dValue == productId) && (serial_item->Value == printedSerialNumber))
118.1169 +            {   
118.1170 +                // found the entry for this device so recursively copy all the settings to the profile
118.1171 +                CopyItems(device, "");
118.1172 +                return true;   
118.1173 +            }
118.1174 +        }
118.1175 +
118.1176 +        device = root->GetNextItem(device);
118.1177 +    }
118.1178 +    
118.1179 +    return false;
118.1180 +}
118.1181 +
118.1182 +#if 0
118.1183 +//-----------------------------------------------------------------------------
118.1184 +static int BCDByte(unsigned int byte)
118.1185 +{
118.1186 +    int digit1 = (byte >> 4) & 0x000f;
118.1187 +    int digit2 = byte & 0x000f;
118.1188 +    int decimal = digit1 * 10 + digit2;
118.1189 +    return decimal;
118.1190 +}
118.1191 +#endif
118.1192 +
118.1193 +//-----------------------------------------------------------------------------
118.1194 +bool Profile::LoadDeviceProfile(const ProfileDeviceKey& deviceKey)
118.1195 +{
118.1196 +    bool success = false;
118.1197 +    if (!deviceKey.Valid)
118.1198 +            return false;
118.1199 +
118.1200 +#if 0
118.1201 +        int dev_major = BCDByte((sinfo.Version >> 8) & 0x00ff);
118.1202 +        OVR_UNUSED(dev_major);
118.1203 +        //int dev_minor = BCDByte(sinfo.Version & 0xff);
118.1204 +      
118.1205 +        //if (dev_minor > 18)
118.1206 +        //{   // If the firmware supports hardware stored profiles then grab the device profile
118.1207 +            // from the sensor
118.1208 +            // TBD:  Implement this
118.1209 +        //}
118.1210 +        //else
118.1211 +        {
118.1212 +#endif
118.1213 +            // Grab the model and serial number from the device and use it to access the device
118.1214 +            // profile file stored on the local machine
118.1215 +        success = LoadDeviceFile(deviceKey.ProductId, deviceKey.PrintedSerial);
118.1216 +    //}
118.1217 +
118.1218 +    return success;
118.1219 +}
118.1220 +
118.1221 +//-----------------------------------------------------------------------------
118.1222 +bool Profile::LoadUser(JSON* root, 
118.1223 +                         const char* user,
118.1224 +                          const char* model_name,
118.1225 +                          const char* device_serial)
118.1226 +{
118.1227 +    if (user == NULL)
118.1228 +        return false;
118.1229 +
118.1230 +    // For legacy files, convert to old style names
118.1231 +    //if (model_name && OVR_strcmp(model_name, "Oculus Rift DK1") == 0)
118.1232 +    //    model_name = "RiftDK1";
118.1233 +    
118.1234 +    bool user_found = false;
118.1235 +    JSON* data = root->GetItemByName("TaggedData");
118.1236 +    if (data)
118.1237 +    {   
118.1238 +        const char* tag_names[3];
118.1239 +        const char* tags[3];
118.1240 +        tag_names[0] = "User";
118.1241 +        tags[0] = user;
118.1242 +        int num_tags = 1;
118.1243 +
118.1244 +        if (model_name)
118.1245 +        {
118.1246 +            tag_names[num_tags] = "Product";
118.1247 +            tags[num_tags] = model_name;
118.1248 +            num_tags++;
118.1249 +        }
118.1250 +
118.1251 +        if (device_serial)
118.1252 +        {
118.1253 +            tag_names[num_tags] = "Serial";
118.1254 +            tags[num_tags] = device_serial;
118.1255 +            num_tags++;
118.1256 +        }
118.1257 +
118.1258 +        // Retrieve all tag permutations
118.1259 +        for (int combos=1; combos<=num_tags; combos++)
118.1260 +        {
118.1261 +            for (int i=0; i<(num_tags - combos + 1); i++)
118.1262 +            {
118.1263 +                JSON* vals = FindTaggedData(data, tag_names+i, tags+i, combos);
118.1264 +                if (vals)
118.1265 +                {   
118.1266 +                    if (i==0)   // This tag-combination contains a user match
118.1267 +                        user_found = true;
118.1268 +
118.1269 +                    // Add the values to the Profile.  More specialized multi-tag values
118.1270 +                    // will take precedence over and overwrite generalized ones 
118.1271 +                    // For example: ("Me","RiftDK1").IPD would overwrite ("Me").IPD
118.1272 +                    JSON* item = vals->GetFirstItem();
118.1273 +                    while (item)
118.1274 +                    {
118.1275 +                        //printf("Add %s, %s\n", item->Name.ToCStr(), item->Value.ToCStr());
118.1276 +                        //Settings.Set(item->Name, item->Value);
118.1277 +                        SetValue(item);
118.1278 +                        item = vals->GetNextItem(item);
118.1279 +                    }
118.1280 +                }
118.1281 +            }
118.1282 +        }
118.1283 +    }
118.1284 +
118.1285 +    if (user_found)
118.1286 +        SetValue(OVR_KEY_USER, user);
118.1287 +
118.1288 +    return user_found;
118.1289 +}
118.1290 +
118.1291 +
118.1292 +//-----------------------------------------------------------------------------
118.1293 +bool Profile::LoadProfile(JSON* root,
118.1294 +                          const char* user,
118.1295 +                          const char* device_model,
118.1296 +                          const char* device_serial)
118.1297 +{
118.1298 +    if (!LoadUser(root, user, device_model, device_serial))
118.1299 +        return false;
118.1300 +
118.1301 +    return true;
118.1302 +}
118.1303 +
118.1304 +
118.1305 +//-----------------------------------------------------------------------------
118.1306 +char* Profile::GetValue(const char* key, char* val, int val_length) const
118.1307 +{
118.1308 +    JSON* value = NULL;
118.1309 +    if (ValMap.Get(key, &value))
118.1310 +    {
118.1311 +        OVR_strcpy(val, val_length, value->Value.ToCStr());
118.1312 +        return val;
118.1313 +    }
118.1314 +    else
118.1315 +    {
118.1316 +        val[0] = 0;
118.1317 +        return NULL;
118.1318 +    }
118.1319 +}
118.1320 +
118.1321 +//-----------------------------------------------------------------------------
118.1322 +const char* Profile::GetValue(const char* key)
118.1323 +{
118.1324 +    // Non-reentrant query.  The returned buffer can only be used until the next call
118.1325 +    // to GetValue()
118.1326 +    JSON* value = NULL;
118.1327 +    if (ValMap.Get(key, &value))
118.1328 +    {
118.1329 +        TempVal = value->Value;
118.1330 +        return TempVal.ToCStr();
118.1331 +    }
118.1332 +    else
118.1333 +    {
118.1334 +        return NULL;
118.1335 +    }
118.1336 +}
118.1337 +
118.1338 +//-----------------------------------------------------------------------------
118.1339 +int Profile::GetNumValues(const char* key) const
118.1340 +{
118.1341 +    JSON* value = NULL;
118.1342 +    if (ValMap.Get(key, &value))
118.1343 +    {  
118.1344 +        if (value->Type == JSON_Array)
118.1345 +            return value->GetArraySize();
118.1346 +        else
118.1347 +            return 1;
118.1348 +    }
118.1349 +    else
118.1350 +        return 0;        
118.1351 +}
118.1352 +
118.1353 +//-----------------------------------------------------------------------------
118.1354 +bool Profile::GetBoolValue(const char* key, bool default_val) const
118.1355 +{
118.1356 +    JSON* value = NULL;
118.1357 +    if (ValMap.Get(key, &value) && value->Type == JSON_Bool)
118.1358 +        return (value->dValue != 0);
118.1359 +    else
118.1360 +        return default_val;
118.1361 +}
118.1362 +
118.1363 +//-----------------------------------------------------------------------------
118.1364 +int Profile::GetIntValue(const char* key, int default_val) const
118.1365 +{
118.1366 +    JSON* value = NULL;
118.1367 +    if (ValMap.Get(key, &value) && value->Type == JSON_Number)
118.1368 +        return (int)(value->dValue);
118.1369 +    else
118.1370 +        return default_val;
118.1371 +}
118.1372 +
118.1373 +//-----------------------------------------------------------------------------
118.1374 +float Profile::GetFloatValue(const char* key, float default_val) const
118.1375 +{
118.1376 +    JSON* value = NULL;
118.1377 +    if (ValMap.Get(key, &value) && value->Type == JSON_Number)
118.1378 +        return (float)(value->dValue);
118.1379 +    else
118.1380 +        return default_val;
118.1381 +}
118.1382 +
118.1383 +//-----------------------------------------------------------------------------
118.1384 +int Profile::GetFloatValues(const char* key, float* values, int num_vals) const
118.1385 +{
118.1386 +    JSON* value = NULL;
118.1387 +    if (ValMap.Get(key, &value) && value->Type == JSON_Array)
118.1388 +    {
118.1389 +        int val_count = Alg::Min(value->GetArraySize(), num_vals);
118.1390 +        JSON* item = value->GetFirstItem();
118.1391 +        int count=0;
118.1392 +        while (item && count < val_count)
118.1393 +        {
118.1394 +            if (item->Type == JSON_Number)
118.1395 +                values[count] = (float)item->dValue;
118.1396 +            else
118.1397 +                break;
118.1398 +
118.1399 +            count++;
118.1400 +            item = value->GetNextItem(item);
118.1401 +        }
118.1402 +
118.1403 +        return count;
118.1404 +    }
118.1405 +    else
118.1406 +    {
118.1407 +        return 0;
118.1408 +    }
118.1409 +}
118.1410 +
118.1411 +//-----------------------------------------------------------------------------
118.1412 +double Profile::GetDoubleValue(const char* key, double default_val) const
118.1413 +{
118.1414 +    JSON* value = NULL;
118.1415 +    if (ValMap.Get(key, &value) && value->Type == JSON_Number)
118.1416 +        return value->dValue;
118.1417 +    else
118.1418 +        return default_val;
118.1419 +}
118.1420 +
118.1421 +//-----------------------------------------------------------------------------
118.1422 +int Profile::GetDoubleValues(const char* key, double* values, int num_vals) const
118.1423 +{
118.1424 +    JSON* value = NULL;
118.1425 +    if (ValMap.Get(key, &value) && value->Type == JSON_Array)
118.1426 +    {
118.1427 +        int val_count = Alg::Min(value->GetArraySize(), num_vals);
118.1428 +        JSON* item = value->GetFirstItem();
118.1429 +        int count=0;
118.1430 +        while (item && count < val_count)
118.1431 +        {
118.1432 +            if (item->Type == JSON_Number)
118.1433 +                values[count] = item->dValue;
118.1434 +            else
118.1435 +                break;
118.1436 +
118.1437 +            count++;
118.1438 +            item = value->GetNextItem(item);
118.1439 +        }
118.1440 +
118.1441 +        return count;
118.1442 +    }
118.1443 +    return 0;
118.1444 +}
118.1445 +
118.1446 +//-----------------------------------------------------------------------------
118.1447 +void Profile::SetValue(JSON* val)
118.1448 +{
118.1449 +    if (val == NULL)
118.1450 +        return;
118.1451 +
118.1452 +    if (val->Type == JSON_Number)
118.1453 +        SetDoubleValue(val->Name, val->dValue);
118.1454 +    else if (val->Type == JSON_Bool)
118.1455 +        SetBoolValue(val->Name, (val->dValue != 0));
118.1456 +    else if (val->Type == JSON_String)
118.1457 +        SetValue(val->Name, val->Value);
118.1458 +    else if (val->Type == JSON_Array)
118.1459 +    {
118.1460 +        // Create a copy of the array
118.1461 +        JSON* value = val->Copy();
118.1462 +        Values.PushBack(value);
118.1463 +        ValMap.Set(value->Name, value);
118.1464 +    }
118.1465 +}
118.1466 +
118.1467 +//-----------------------------------------------------------------------------
118.1468 +void Profile::SetValue(const char* key, const char* val)
118.1469 +{
118.1470 +    if (key == NULL || val == NULL)
118.1471 +        return;
118.1472 +
118.1473 +    JSON* value = NULL;
118.1474 +    if (ValMap.Get(key, &value))
118.1475 +    {
118.1476 +        value->Value = val;
118.1477 +    }
118.1478 +    else
118.1479 +    {
118.1480 +        value = JSON::CreateString(val);
118.1481 +        value->Name = key;
118.1482 +
118.1483 +        Values.PushBack(value);
118.1484 +        ValMap.Set(key, value);
118.1485 +    }
118.1486 +}
118.1487 +
118.1488 +//-----------------------------------------------------------------------------
118.1489 +void Profile::SetBoolValue(const char* key, bool val)
118.1490 +{
118.1491 +    if (key == NULL)
118.1492 +        return;
118.1493 +
118.1494 +    JSON* value = NULL;
118.1495 +    if (ValMap.Get(key, &value))
118.1496 +    {
118.1497 +        value->dValue = val;
118.1498 +    }
118.1499 +    else
118.1500 +    {
118.1501 +        value = JSON::CreateBool(val);
118.1502 +        value->Name = key;
118.1503 +
118.1504 +        Values.PushBack(value);
118.1505 +        ValMap.Set(key, value);
118.1506 +    }
118.1507 +}
118.1508 +
118.1509 +//-----------------------------------------------------------------------------
118.1510 +void Profile::SetIntValue(const char* key, int val)
118.1511 +{
118.1512 +    SetDoubleValue(key, val);
118.1513 +}
118.1514 +
118.1515 +//-----------------------------------------------------------------------------
118.1516 +void Profile::SetFloatValue(const char* key, float val)
118.1517 +{
118.1518 +    SetDoubleValue(key, val);
118.1519 +}
118.1520 +
118.1521 +//-----------------------------------------------------------------------------
118.1522 +void Profile::SetFloatValues(const char* key, const float* vals, int num_vals)
118.1523 +{
118.1524 +    JSON* value = NULL;
118.1525 +    int val_count = 0;
118.1526 +    if (ValMap.Get(key, &value))
118.1527 +    {
118.1528 +        if (value->Type == JSON_Array)
118.1529 +        {
118.1530 +            // truncate the existing array if fewer entries provided
118.1531 +            int num_existing_vals = value->GetArraySize();
118.1532 +            for (int i=num_vals; i<num_existing_vals; i++)
118.1533 +                value->RemoveLast();
118.1534 +            
118.1535 +            JSON* item = value->GetFirstItem();
118.1536 +            while (item && val_count < num_vals)
118.1537 +            {
118.1538 +                if (item->Type == JSON_Number)
118.1539 +                    item->dValue = vals[val_count];
118.1540 +
118.1541 +                item = value->GetNextItem(item);
118.1542 +                val_count++;
118.1543 +            }
118.1544 +        }
118.1545 +        else
118.1546 +        {
118.1547 +            return;  // Maybe we should change the data type?
118.1548 +        }
118.1549 +    }
118.1550 +    else
118.1551 +    {
118.1552 +        value = JSON::CreateArray();
118.1553 +        value->Name = key;
118.1554 +
118.1555 +        Values.PushBack(value);
118.1556 +        ValMap.Set(key, value);
118.1557 +    }
118.1558 +
118.1559 +    for (; val_count < num_vals; val_count++)
118.1560 +        value->AddArrayNumber(vals[val_count]);
118.1561 +}
118.1562 +
118.1563 +//-----------------------------------------------------------------------------
118.1564 +void Profile::SetDoubleValue(const char* key, double val)
118.1565 +{
118.1566 +    JSON* value = NULL;
118.1567 +    if (ValMap.Get(key, &value))
118.1568 +    {
118.1569 +        value->dValue = val;
118.1570 +    }
118.1571 +    else
118.1572 +    {
118.1573 +        value = JSON::CreateNumber(val);
118.1574 +        value->Name = key;
118.1575 +
118.1576 +        Values.PushBack(value);
118.1577 +        ValMap.Set(key, value);
118.1578 +    }
118.1579 +}
118.1580 +
118.1581 +//-----------------------------------------------------------------------------
118.1582 +void Profile::SetDoubleValues(const char* key, const double* vals, int num_vals)
118.1583 +{
118.1584 +    JSON* value = NULL;
118.1585 +    int val_count = 0;
118.1586 +    if (ValMap.Get(key, &value))
118.1587 +    {
118.1588 +        if (value->Type == JSON_Array)
118.1589 +        {
118.1590 +            // truncate the existing array if fewer entries provided
118.1591 +            int num_existing_vals = value->GetArraySize();
118.1592 +            for (int i=num_vals; i<num_existing_vals; i++)
118.1593 +                value->RemoveLast();
118.1594 +            
118.1595 +            JSON* item = value->GetFirstItem();
118.1596 +            while (item && val_count < num_vals)
118.1597 +            {
118.1598 +                if (item->Type == JSON_Number)
118.1599 +                    item->dValue = vals[val_count];
118.1600 +
118.1601 +                item = value->GetNextItem(item);
118.1602 +                val_count++;
118.1603 +            }
118.1604 +        }
118.1605 +        else
118.1606 +        {
118.1607 +            return;  // Maybe we should change the data type?
118.1608 +        }
118.1609 +    }
118.1610 +    else
118.1611 +    {
118.1612 +        value = JSON::CreateArray();
118.1613 +        value->Name = key;
118.1614 +
118.1615 +        Values.PushBack(value);
118.1616 +        ValMap.Set(key, value);
118.1617 +    }
118.1618 +
118.1619 +    for (; val_count < num_vals; val_count++)
118.1620 +        value->AddArrayNumber(vals[val_count]);
118.1621 +}
118.1622 +
118.1623 +//------------------------------------------------------------------------------
118.1624 +bool Profile::IsDefaultProfile()
118.1625 +{
118.1626 +    return 0 == OVR::String::CompareNoCase("Default", GetValue(OVR_KEY_NAME));
118.1627 +}
118.1628 +
118.1629 +
118.1630 +}  // namespace OVR
   119.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   119.2 +++ b/LibOVR/Src/OVR_Profile.h	Wed Jan 14 06:51:16 2015 +0200
   119.3 @@ -0,0 +1,222 @@
   119.4 +/************************************************************************************
   119.5 +
   119.6 +Filename    :   OVR_Profile.h
   119.7 +Content     :   Structs and functions for loading and storing device profile settings
   119.8 +Created     :   February 14, 2013
   119.9 +Notes       :
  119.10 +   Profiles are used to store per-user settings that can be transferred and used
  119.11 +   across multiple applications.  For example, player IPD can be configured once 
  119.12 +   and reused for a unified experience across games.  Configuration and saving of profiles
  119.13 +   can be accomplished in game via the Profile API or by the official Oculus Configuration
  119.14 +   Utility.
  119.15 +
  119.16 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
  119.17 +
  119.18 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
  119.19 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
  119.20 +which is provided at the time of installation or download, or which 
  119.21 +otherwise accompanies this software in either electronic or hard copy form.
  119.22 +
  119.23 +You may obtain a copy of the License at
  119.24 +
  119.25 +http://www.oculusvr.com/licenses/LICENSE-3.2 
  119.26 +
  119.27 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
  119.28 +distributed under the License is distributed on an "AS IS" BASIS,
  119.29 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  119.30 +See the License for the specific language governing permissions and
  119.31 +limitations under the License.
  119.32 +
  119.33 +************************************************************************************/
  119.34 +
  119.35 +#ifndef OVR_Profile_h
  119.36 +#define OVR_Profile_h
  119.37 +
  119.38 +#include "OVR_CAPI_Keys.h"
  119.39 +
  119.40 +#include "Sensors/OVR_DeviceConstants.h"
  119.41 +#include "Kernel/OVR_String.h"
  119.42 +#include "Kernel/OVR_RefCount.h"
  119.43 +#include "Kernel/OVR_Array.h"
  119.44 +#include "Kernel/OVR_StringHash.h"
  119.45 +#include "Kernel/OVR_System.h"
  119.46 +
  119.47 +namespace OVR {
  119.48 +
  119.49 +class HMDInfo; // Opaque forward declaration
  119.50 +class Profile;
  119.51 +class JSON;
  119.52 +
  119.53 +
  119.54 +// Device key for looking up profiles
  119.55 +struct ProfileDeviceKey
  119.56 +{
  119.57 +    ProfileDeviceKey(const HMDInfo* info);
  119.58 +
  119.59 +	// Initialized properly?
  119.60 +	bool Valid;
  119.61 +
  119.62 +    // The HMD type
  119.63 +    HmdTypeEnum HmdType;
  119.64 +
  119.65 +	// This is the 12 character serial number printed on the HMD
  119.66 +	String PrintedSerial;
  119.67 +
  119.68 +	// This is the product name string of the USB sensor device
  119.69 +	// Note: It has been modified from the original to remove spaces and strip off "Oculus"
  119.70 +	String ProductName;
  119.71 +
  119.72 +	// This is the product id from the HID info of the USB sensor device
  119.73 +	unsigned ProductId;
  119.74 +
  119.75 +    static String SanitizeProductName(String productName);
  119.76 +};
  119.77 +
  119.78 +
  119.79 +// -----------------------------------------------------------------------------
  119.80 +// ***** ProfileManager
  119.81 +
  119.82 +// Profiles are interfaced through a ProfileManager object.  Applications should
  119.83 +// create a ProfileManager each time they intend to read or write user profile data.
  119.84 +// The scope of the ProfileManager object defines when disk I/O is performed.  Disk
  119.85 +// reads are performed on the first profile access and disk writes are performed when
  119.86 +// the ProfileManager goes out of scope.  All profile interactions between these times
  119.87 +// are performed in local memory and are fast.  A typical profile interaction might
  119.88 +// look like this:
  119.89 +//
  119.90 +// {
  119.91 +//     Ptr<ProfileManager> pm      = *ProfileManager::Create();
  119.92 +//     Ptr<Profile>        profile = pm->LoadProfile(Profile_RiftDK1,
  119.93 +//                                                   pm->GetDefaultProfileName(Profile_RiftDK1));
  119.94 +//     if (profile)
  119.95 +//     {   // Retrieve the current profile settings
  119.96 +//     }
  119.97 +// }   // Profile will be destroyed and any disk I/O completed when going out of scope
  119.98 +class ProfileManager : public NewOverrideBase, public SystemSingletonBase<ProfileManager>
  119.99 +{
 119.100 +    friend class OVR::SystemSingletonBase<ProfileManager>;
 119.101 +
 119.102 +protected:
 119.103 +    ProfileManager(bool sys_register);
 119.104 +    virtual ~ProfileManager();
 119.105 +    virtual void OnSystemDestroy();
 119.106 +
 119.107 +protected:
 119.108 +    // Synchronize ProfileManager access since it may be accessed from multiple threads,
 119.109 +    // as it's shared through DeviceManager.
 119.110 +    Lock                ProfileLock;
 119.111 +    Ptr<JSON>           ProfileCache;
 119.112 +    bool                Changed;
 119.113 +    String              TempBuff;
 119.114 +    String              BasePath;
 119.115 +    
 119.116 +public:
 119.117 +    // In the service process it is important to set the base path because this cannot be detected automatically
 119.118 +    void                SetBasePath(String basePath);
 119.119 +
 119.120 +    int                 GetUserCount();
 119.121 +    const char*         GetUser(unsigned int index);
 119.122 +    bool                CreateUser(const char* user, const char* name);
 119.123 +	bool				HasUser(const char* user);
 119.124 +    bool                RemoveUser(const char* user);
 119.125 +    const char*         GetDefaultUser(const ProfileDeviceKey& deviceKey);
 119.126 +    bool                SetDefaultUser(const ProfileDeviceKey& deviceKey, const char* user);
 119.127 +
 119.128 +    virtual Profile*    CreateProfile();
 119.129 +    Profile*            GetProfile(const ProfileDeviceKey& deviceKey, const char* user);
 119.130 +    Profile*            GetDefaultUserProfile(const ProfileDeviceKey& deviceKey);
 119.131 +    Profile*            GetDefaultProfile(HmdTypeEnum device);
 119.132 +    Profile*            GetTaggedProfile(const char** key_names, const char** keys, int num_keys);
 119.133 +    bool                SetTaggedProfile(const char** key_names, const char** keys, int num_keys, Profile* profile);
 119.134 +    
 119.135 +    // Force re-reading the settings
 119.136 +    void                Read();
 119.137 +
 119.138 +protected:
 119.139 +    // Force writing the settings
 119.140 +    void                ClearProfileData();
 119.141 +    void                Save();
 119.142 +
 119.143 +    String              GetProfilePath();
 119.144 +    void                LoadCache(bool create);
 119.145 +    void                LoadV1Profiles(JSON* v1);
 119.146 +    const char*         GetDefaultUser(const char* product, const char* serial);
 119.147 +};
 119.148 +
 119.149 +
 119.150 +//-------------------------------------------------------------------
 119.151 +// ***** Profile
 119.152 +
 119.153 +// The base profile for all users.  This object is not created directly.
 119.154 +// Instead derived device objects provide add specific device members to 
 119.155 +// the base profile
 119.156 +class Profile : public RefCountBase<Profile>
 119.157 +{
 119.158 +protected:
 119.159 +    OVR::Hash<String, JSON*, String::HashFunctor>   ValMap;
 119.160 +    OVR::Array<JSON*>   Values;  
 119.161 +    OVR::String         TempVal;
 119.162 +    String              BasePath;
 119.163 +
 119.164 +public:
 119.165 +    ~Profile();
 119.166 +
 119.167 +    int                 GetNumValues(const char* key) const;
 119.168 +    const char*         GetValue(const char* key);
 119.169 +    char*               GetValue(const char* key, char* val, int val_length) const;
 119.170 +    bool                GetBoolValue(const char* key, bool default_val) const;
 119.171 +    int                 GetIntValue(const char* key, int default_val) const;
 119.172 +    float               GetFloatValue(const char* key, float default_val) const;
 119.173 +    int                 GetFloatValues(const char* key, float* values, int num_vals) const;
 119.174 +    double              GetDoubleValue(const char* key, double default_val) const;
 119.175 +    int                 GetDoubleValues(const char* key, double* values, int num_vals) const;
 119.176 +
 119.177 +    void                SetValue(const char* key, const char* val);
 119.178 +    void                SetBoolValue(const char* key, bool val);
 119.179 +    void                SetIntValue(const char* key, int val);
 119.180 +    void                SetFloatValue(const char* key, float val);
 119.181 +    void                SetFloatValues(const char* key, const float* vals, int num_vals);
 119.182 +    void                SetDoubleValue(const char* key, double val);
 119.183 +    void                SetDoubleValues(const char* key, const double* vals, int num_vals);
 119.184 +
 119.185 +    bool                IsDefaultProfile();
 119.186 +    
 119.187 +    bool Close();
 119.188 +
 119.189 +protected:
 119.190 +	Profile(String basePath) :
 119.191 +		BasePath(basePath)
 119.192 +	{
 119.193 +	}
 119.194 +    
 119.195 +    void                SetValue(JSON* val);
 119.196 +
 119.197 +	static bool         LoadProfile(const ProfileDeviceKey& deviceKey,
 119.198 +                                    const char* user,
 119.199 +                                    Profile** profile);
 119.200 +    void                CopyItems(JSON* root, String prefix);
 119.201 +    
 119.202 +    bool                LoadDeviceFile(unsigned int device_id, const char* serial);
 119.203 +	bool                LoadDeviceProfile(const ProfileDeviceKey& deviceKey);
 119.204 +
 119.205 +    bool                LoadProfile(JSON* root,
 119.206 +                                    const char* user,
 119.207 +                                    const char* device_model,
 119.208 +                                    const char* device_serial);
 119.209 +
 119.210 +    bool                LoadUser(JSON* root,
 119.211 +                                 const char* user,
 119.212 +                                 const char* device_name,
 119.213 +                                 const char* device_serial);
 119.214 +
 119.215 +    friend class ProfileManager;
 119.216 +    friend class WProfileManager;
 119.217 +};
 119.218 +
 119.219 +// This path should be passed into the ProfileManager
 119.220 +String GetBaseOVRPath(bool create_dir);
 119.221 +
 119.222 +
 119.223 +} // namespace OVR
 119.224 +
 119.225 +#endif // OVR_Profile_h
   120.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   120.2 +++ b/LibOVR/Src/OVR_SerialFormat.cpp	Wed Jan 14 06:51:16 2015 +0200
   120.3 @@ -0,0 +1,451 @@
   120.4 +/************************************************************************************
   120.5 +
   120.6 +Filename    :   OVR_System.cpp
   120.7 +Content     :   General kernel initialization/cleanup, including that
   120.8 +                of the memory allocator.
   120.9 +Created     :   September 19, 2012
  120.10 +Notes       : 
  120.11 +
  120.12 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
  120.13 +
  120.14 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
  120.15 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
  120.16 +which is provided at the time of installation or download, or which 
  120.17 +otherwise accompanies this software in either electronic or hard copy form.
  120.18 +
  120.19 +You may obtain a copy of the License at
  120.20 +
  120.21 +http://www.oculusvr.com/licenses/LICENSE-3.2 
  120.22 +
  120.23 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
  120.24 +distributed under the License is distributed on an "AS IS" BASIS,
  120.25 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  120.26 +See the License for the specific language governing permissions and
  120.27 +limitations under the License.
  120.28 +
  120.29 +************************************************************************************/
  120.30 +
  120.31 +#include "OVR_SerialFormat.h"
  120.32 +
  120.33 +#ifdef SERIAL_FORMAT_UNIT_TEST
  120.34 +#include "Kernel/OVR_Log.h"
  120.35 +#endif
  120.36 +
  120.37 +namespace OVR {
  120.38 +
  120.39 +
  120.40 +//// Serial Format Detection
  120.41 +
  120.42 +SerialFormatType DetectBufferFormat(uint8_t firstByte, int sizeInBytes)
  120.43 +{
  120.44 +	switch (firstByte)
  120.45 +	{
  120.46 +	case SerialFormatType_DK2:
  120.47 +		if (sizeInBytes == 12)
  120.48 +		{
  120.49 +			return SerialFormatType_DK2;
  120.50 +		}
  120.51 +		break;
  120.52 +	default:
  120.53 +		break;
  120.54 +	}
  120.55 +
  120.56 +	return SerialFormatType_Invalid;
  120.57 +}
  120.58 +
  120.59 +
  120.60 +//// DK2 Helpers
  120.61 +
  120.62 +static bool ValidDK2ProductId(int x)
  120.63 +{
  120.64 +	switch (x)
  120.65 +	{
  120.66 +	case DK2ProductId_DK1:
  120.67 +	case DK2ProductId_DK2:
  120.68 +	case DK2ProductId_Refurb:
  120.69 +		return true;
  120.70 +	default:
  120.71 +		break;
  120.72 +	}
  120.73 +
  120.74 +	return false;
  120.75 +}
  120.76 +
  120.77 +static bool ValidDK2PartId(int x)
  120.78 +{
  120.79 +	switch (x)
  120.80 +	{
  120.81 +	case DK2PartId_HMD:
  120.82 +	case DK2PartId_PTC:
  120.83 +	case DK2PartId_Carton:
  120.84 +		return true;
  120.85 +	default:
  120.86 +		break;
  120.87 +	}
  120.88 +
  120.89 +	return false;
  120.90 +}
  120.91 +
  120.92 +
  120.93 +//// DK2BinarySerialFormat
  120.94 +
  120.95 +bool DK2BinarySerialFormat::FromBuffer(const uint8_t buffer[12], bool allowUnknownTypes)
  120.96 +{
  120.97 +	// Format Type must be 0
  120.98 +	
  120.99 +	int formatType = buffer[0];
 120.100 +
 120.101 +	if (formatType != SerialFormatType_DK2)
 120.102 +	{
 120.103 +		return false;
 120.104 +	}
 120.105 +
 120.106 +	// Product Id
 120.107 +
 120.108 +	int productId = buffer[1] >> 4;
 120.109 +
 120.110 +	if (!allowUnknownTypes && !ValidDK2ProductId(productId))
 120.111 +	{
 120.112 +		return false;
 120.113 +	}
 120.114 +
 120.115 +	ProductId = (DK2ProductId)productId;
 120.116 +
 120.117 +	// Part Id
 120.118 +
 120.119 +	int partId = buffer[1] & 15;
 120.120 +
 120.121 +	if (!allowUnknownTypes && !ValidDK2PartId(partId))
 120.122 +	{
 120.123 +		return false;
 120.124 +	}
 120.125 +
 120.126 +	PartId = (DK2PartId)partId;
 120.127 +
 120.128 +	// Minutes Since Epoch (May 1, 2014)
 120.129 +
 120.130 +	MinutesSinceEpoch = buffer[4] | ((uint32_t)buffer[3] << 8) | ((uint32_t)buffer[2] << 16);
 120.131 +
 120.132 +	// Unit number on that day
 120.133 +
 120.134 +	UnitNumber = buffer[6] | ((uint32_t)buffer[5] << 8);
 120.135 +
 120.136 +	// Hash of MAC address
 120.137 +
 120.138 +	MacHash[0] = buffer[7];
 120.139 +	MacHash[1] = buffer[8];
 120.140 +	MacHash[2] = buffer[9];
 120.141 +	MacHash[3] = buffer[10];
 120.142 +	MacHash[4] = buffer[11];
 120.143 +
 120.144 +	return true;
 120.145 +}
 120.146 +
 120.147 +void DK2BinarySerialFormat::ToBuffer(uint8_t buffer[12])
 120.148 +{
 120.149 +	// Serialize to buffer
 120.150 +	buffer[0] = SerialFormatType_DK2;
 120.151 +	buffer[1] = (uint8_t)((ProductId << 4) | (PartId));
 120.152 +	buffer[2] = (uint8_t)(MinutesSinceEpoch >> 16);
 120.153 +	buffer[3] = (uint8_t)(MinutesSinceEpoch >> 8);
 120.154 +	buffer[4] = (uint8_t)MinutesSinceEpoch;
 120.155 +	buffer[5] = (uint8_t)(UnitNumber >> 8);
 120.156 +	buffer[6] = (uint8_t)UnitNumber;
 120.157 +
 120.158 +	buffer[7] = MacHash[0];
 120.159 +	buffer[8] = MacHash[1];
 120.160 +	buffer[9] = MacHash[2];
 120.161 +	buffer[10] = MacHash[3];
 120.162 +	buffer[11] = MacHash[4];
 120.163 +}
 120.164 +
 120.165 +bool DK2BinarySerialFormat::operator==(const DK2BinarySerialFormat& rhs)
 120.166 +{
 120.167 +	if (ProductId != rhs.ProductId)
 120.168 +		return false;
 120.169 +	if (PartId != rhs.PartId)
 120.170 +		return false;
 120.171 +	if (MinutesSinceEpoch != rhs.MinutesSinceEpoch)
 120.172 +		return false;
 120.173 +	if (UnitNumber != rhs.UnitNumber)
 120.174 +		return false;
 120.175 +	for (int ii = 0; ii < 5; ++ii)
 120.176 +	{
 120.177 +		if (MacHash[ii] != rhs.MacHash[ii])
 120.178 +			return false;
 120.179 +	}
 120.180 +	return true;
 120.181 +}
 120.182 +
 120.183 +
 120.184 +//// DK2PrintedSerialFormat
 120.185 +
 120.186 +// Base-32 Crockford decoding rules:
 120.187 +// 0 o O => 0
 120.188 +// 1 i | I L l => 1
 120.189 +// 2, 3, 4, 5, 6, 7, 8, 9 => 2 - 9
 120.190 +// a, b, c, d, e, f, g, h => 10 - 17
 120.191 +// j, k => 18, 19
 120.192 +// m, n => 20, 21
 120.193 +// p, q, r, s, t => 22, 23, 24, 25, 26
 120.194 +// v, w, x, y, z => 27, 28, 29, 30, 31
 120.195 +static const char Base32FromChar[256] = {
 120.196 +	// Null - Unit Separator
 120.197 +	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
 120.198 +	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
 120.199 +	// (sp)!"#$%&'()*+,-./
 120.200 +	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
 120.201 +	// 0123456789:;<=>?
 120.202 +	 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, -1, -1, -1, -1, -1, -1,
 120.203 +	// @ - _ (upper case)
 120.204 +	-1, 10, 11, 12, 13, 14, 15, 16, 17,  1, 18, 19,  1, 20, 21,  0,
 120.205 +	22, 23, 24, 25, 26, -1, 27, 28, 29, 30, 31, -1, -1, -1, -1, -1,
 120.206 +	// ` - DEL (lower case)
 120.207 +	-1, 10, 11, 12, 13, 14, 15, 16, 17,  1, 18, 19,  1, 20, 21,  0,
 120.208 +	22, 23, 24, 25, 26, -1, 27, 28, 29, 30, 31, -1,  1, -1, -1, -1,
 120.209 +
 120.210 +	// Extended ASCII:
 120.211 +	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
 120.212 +	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
 120.213 +
 120.214 +	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
 120.215 +	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
 120.216 +
 120.217 +	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
 120.218 +	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
 120.219 +
 120.220 +	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
 120.221 +	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
 120.222 +};
 120.223 +
 120.224 +// Base-32 Crockford encoding rules:
 120.225 +// 0-9 => 0-9
 120.226 +// 10 - 17 => a, b, c, d, e, f, g, h
 120.227 +// 18, 19 => j, k
 120.228 +// 20, 21 => m, n
 120.229 +// 22, 23, 24, 25, 26 => p, q, r, s, t
 120.230 +// 27, 28, 29, 30, 31 => v, w, x, y, z
 120.231 +static const char* CharFromBase32 = "0123456789ABCDEFGHJKMNPQRSTVWXYZ";
 120.232 +
 120.233 +bool DK2PrintedSerialFormat::FromBase32(const char* str, bool allowUnknownTypes)
 120.234 +{
 120.235 +	// Note: Truncated strings get caught by returning negative values from the table like other invalid characters
 120.236 +
 120.237 +	// Product Id
 120.238 +
 120.239 +	int productId = Base32FromChar[(unsigned char)str[0]];
 120.240 +	if (productId < 0 || (!allowUnknownTypes && !ValidDK2ProductId(productId)))
 120.241 +	{
 120.242 +		return false;
 120.243 +	}
 120.244 +
 120.245 +	ProductId = (DK2ProductId)productId;
 120.246 +
 120.247 +	// Label Type
 120.248 +
 120.249 +	int labelType = Base32FromChar[(unsigned char)str[1]];
 120.250 +	if (labelType < 0 || (!allowUnknownTypes && !ValidDK2PartId(labelType)))
 120.251 +	{
 120.252 +		return false;
 120.253 +	}
 120.254 +
 120.255 +	LabelType = (DK2LabelType)labelType;
 120.256 +
 120.257 +	uint8_t dataBytes[7];
 120.258 +	for (int ii = 0; ii < 7; ++ii)
 120.259 +	{
 120.260 +		int c = Base32FromChar[(unsigned char)str[2 + ii]];
 120.261 +		if (c < 0) return false;
 120.262 +		dataBytes[ii] = (uint8_t)c;
 120.263 +	}
 120.264 +
 120.265 +	// Minutes Since Epoch
 120.266 +
 120.267 +	MinutesSinceEpoch = dataBytes[3] | ((uint32_t)dataBytes[2] << 5) | ((uint32_t)dataBytes[1] << 10) | ((uint32_t)dataBytes[0] << 15);
 120.268 +
 120.269 +	// Unit Number
 120.270 +
 120.271 +	UnitNumber = dataBytes[6] | ((uint32_t)dataBytes[5] << 5) | ((uint32_t)dataBytes[4] << 10);
 120.272 +
 120.273 +	// MAC Hash
 120.274 +
 120.275 +	for (int ii = 0; ii < 3; ++ii)
 120.276 +	{
 120.277 +		int c = Base32FromChar[(unsigned char)str[9 + ii]];
 120.278 +		if (c < 0)
 120.279 +		{
 120.280 +			return false;
 120.281 +		}
 120.282 +
 120.283 +		MacHashLow[ii] = (uint8_t)c;
 120.284 +	}
 120.285 +
 120.286 +	// String must be exactly 12 characters
 120.287 +	if (str[12] != '\0')
 120.288 +	{
 120.289 +		return false;
 120.290 +	}
 120.291 +
 120.292 +	return true;
 120.293 +}
 120.294 +
 120.295 +String DK2PrintedSerialFormat::ToBase32()
 120.296 +{
 120.297 +	String s;
 120.298 +
 120.299 +	s += CharFromBase32[ProductId];
 120.300 +	s += CharFromBase32[LabelType];
 120.301 +	s += CharFromBase32[(MinutesSinceEpoch >> 15) & 31];
 120.302 +	s += CharFromBase32[(MinutesSinceEpoch >> 10) & 31];
 120.303 +	s += CharFromBase32[(MinutesSinceEpoch >> 5) & 31];
 120.304 +	s += CharFromBase32[MinutesSinceEpoch & 31];
 120.305 +	s += CharFromBase32[(UnitNumber >> 10) & 31];
 120.306 +	s += CharFromBase32[(UnitNumber >> 5) & 31];
 120.307 +	s += CharFromBase32[UnitNumber & 31];
 120.308 +	s += CharFromBase32[MacHashLow[0] & 31];
 120.309 +	s += CharFromBase32[MacHashLow[1] & 31];
 120.310 +	s += CharFromBase32[MacHashLow[2] & 31];
 120.311 +
 120.312 +	return s;
 120.313 +}
 120.314 +
 120.315 +bool DK2PrintedSerialFormat::operator==(const DK2PrintedSerialFormat& rhs)
 120.316 +{
 120.317 +	if (ProductId != rhs.ProductId)
 120.318 +		return false;
 120.319 +	if (LabelType != rhs.LabelType)
 120.320 +		return false;
 120.321 +	if (MinutesSinceEpoch != rhs.MinutesSinceEpoch)
 120.322 +		return false;
 120.323 +	if (UnitNumber != rhs.UnitNumber)
 120.324 +		return false;
 120.325 +	for (int ii = 0; ii < 3; ++ii)
 120.326 +	{
 120.327 +		if (MacHashLow[ii] != rhs.MacHashLow[ii])
 120.328 +			return false;
 120.329 +	}
 120.330 +	return true;
 120.331 +}
 120.332 +
 120.333 +bool DK2PrintedSerialFormat::operator==(const DK2BinarySerialFormat& rhs)
 120.334 +{
 120.335 +	if (ProductId != rhs.ProductId)
 120.336 +		return false;
 120.337 +	if (LabelType != rhs.PartId)
 120.338 +		return false;
 120.339 +	if (MinutesSinceEpoch != rhs.MinutesSinceEpoch)
 120.340 +		return false;
 120.341 +	if (UnitNumber != rhs.UnitNumber)
 120.342 +		return false;
 120.343 +	for (int ii = 0; ii < 3; ++ii)
 120.344 +	{
 120.345 +		if (MacHashLow[ii] != (rhs.MacHash[ii] & 31))
 120.346 +			return false;
 120.347 +	}
 120.348 +	return true;
 120.349 +}
 120.350 +
 120.351 +void DK2PrintedSerialFormat::FromBinary(const DK2BinarySerialFormat& bin)
 120.352 +{
 120.353 +	ProductId = bin.ProductId;
 120.354 +	LabelType = bin.PartId;
 120.355 +	MinutesSinceEpoch = bin.MinutesSinceEpoch;
 120.356 +	UnitNumber = bin.UnitNumber;
 120.357 +	MacHashLow[0] = bin.MacHash[0] & 31;
 120.358 +	MacHashLow[1] = bin.MacHash[1] & 31;
 120.359 +	MacHashLow[2] = bin.MacHash[2] & 31;
 120.360 +}
 120.361 +
 120.362 +
 120.363 +//// Unit Tests
 120.364 +
 120.365 +#ifdef SERIAL_FORMAT_UNIT_TEST
 120.366 +
 120.367 +int DecodeBase32(char ch)
 120.368 +{
 120.369 +    if (ch >= '2' && ch <= '9')
 120.370 +        return 2 + ch - '2';
 120.371 +    if (ch >= 'a' && ch <= 'h')
 120.372 +        return 10 + ch - 'a';
 120.373 +    if (ch >= 'A' && ch <= 'H')
 120.374 +        return 10 + ch - 'A';
 120.375 +    if (ch >= 'j' && ch <= 'k')
 120.376 +        return 18 + ch - 'j';
 120.377 +    if (ch >= 'J' && ch <= 'K')
 120.378 +        return 18 + ch - 'J';
 120.379 +    if (ch >= 'm' && ch <= 'n')
 120.380 +        return 20 + ch - 'm';
 120.381 +    if (ch >= 'M' && ch <= 'N')
 120.382 +        return 20 + ch - 'M';
 120.383 +    if (ch >= 'p' && ch <= 't')
 120.384 +        return 22 + ch - 'p';
 120.385 +    if (ch >= 'P' && ch <= 'T')
 120.386 +        return 22 + ch - 'P';
 120.387 +    if (ch >= 'v' && ch <= 'z')
 120.388 +        return 27 + ch - 'v';
 120.389 +    if (ch >= 'V' && ch <= 'Z')
 120.390 +        return 27 + ch - 'V';
 120.391 +
 120.392 +    switch (ch)
 120.393 +    {
 120.394 +    case '0':
 120.395 +    case 'o':
 120.396 +    case 'O':
 120.397 +        return 0;
 120.398 +    case '1':
 120.399 +    case 'i':
 120.400 +    case '|':
 120.401 +    case 'I':
 120.402 +    case 'L':
 120.403 +    case 'l':
 120.404 +        return 1;
 120.405 +    }
 120.406 +
 120.407 +    return -1;
 120.408 +}
 120.409 +
 120.410 +void TestSerialFormatStuff()
 120.411 +{
 120.412 +    for (int ii = 0; ii < 256; ++ii)
 120.413 +    {
 120.414 +        OVR_ASSERT(Base32FromChar[ii] == (char)DecodeBase32((char)ii));
 120.415 +    }
 120.416 +
 120.417 +    DK2BinarySerialFormat sa;
 120.418 +    sa.ProductId = DK2ProductId_DK2;
 120.419 +    sa.PartId = DK2PartId_HMD;
 120.420 +    sa.MinutesSinceEpoch = 65000;
 120.421 +    sa.UnitNumber = 2;
 120.422 +    sa.MacHash[0] = 0xa1;
 120.423 +    sa.MacHash[1] = 0xb2;
 120.424 +    sa.MacHash[2] = 0xc3;
 120.425 +    sa.MacHash[3] = 0xd4;
 120.426 +    sa.MacHash[4] = 0xe5;
 120.427 +
 120.428 +    uint8_t buffer[12];
 120.429 +    sa.ToBuffer(buffer);
 120.430 +
 120.431 +    DK2BinarySerialFormat sb;
 120.432 +    bool success = sb.FromBuffer(buffer);
 120.433 +    OVR_ASSERT(success);
 120.434 +    OVR_UNUSED(success);
 120.435 +
 120.436 +    OVR_ASSERT(sa == sb);
 120.437 +
 120.438 +    DK2PrintedSerialFormat psn;
 120.439 +    psn.FromBinary(sb);
 120.440 +
 120.441 +    OVR_ASSERT(psn == sa);
 120.442 +
 120.443 +    String s = psn.ToBase32();
 120.444 +
 120.445 +    DK2PrintedSerialFormat psn2;
 120.446 +    psn2.FromBase32(s.ToCStr());
 120.447 +
 120.448 +    OVR_ASSERT(psn == psn2);
 120.449 +}
 120.450 +
 120.451 +#endif // SERIAL_FORMAT_UNIT_TEST
 120.452 +
 120.453 +
 120.454 +} // OVR
   121.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   121.2 +++ b/LibOVR/Src/OVR_SerialFormat.h	Wed Jan 14 06:51:16 2015 +0200
   121.3 @@ -0,0 +1,128 @@
   121.4 +/************************************************************************************
   121.5 +
   121.6 +PublicHeader:   n/a
   121.7 +Filename    :   OVR_SerialFormat.h
   121.8 +Content     :   Serial Number format tools
   121.9 +Created     :   June 12, 2014
  121.10 +
  121.11 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
  121.12 +
  121.13 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
  121.14 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
  121.15 +which is provided at the time of installation or download, or which 
  121.16 +otherwise accompanies this software in either electronic or hard copy form.
  121.17 +
  121.18 +You may obtain a copy of the License at
  121.19 +
  121.20 +http://www.oculusvr.com/licenses/LICENSE-3.2 
  121.21 +
  121.22 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
  121.23 +distributed under the License is distributed on an "AS IS" BASIS,
  121.24 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  121.25 +See the License for the specific language governing permissions and
  121.26 +limitations under the License.
  121.27 +
  121.28 +************************************************************************************/
  121.29 +
  121.30 +#ifndef OVR_SerialFormat_h
  121.31 +#define OVR_SerialFormat_h
  121.32 +
  121.33 +#include "Kernel/OVR_Types.h"
  121.34 +#include "Kernel/OVR_String.h"
  121.35 +
  121.36 +namespace OVR {
  121.37 +
  121.38 +
  121.39 +//-----------------------------------------------------------------------------
  121.40 +// SerialFormatType enumeration
  121.41 +
  121.42 +enum SerialFormatType
  121.43 +{
  121.44 +	SerialFormatType_Invalid = -1, // Invalid format
  121.45 +	SerialFormatType_DK2 = 0,	   // Format used for DK2
  121.46 +};
  121.47 +
  121.48 +// Returns the expected serial format based on the first byte of the buffer
  121.49 +SerialFormatType DetectBufferFormat(uint8_t firstByte, int sizeInBytes);
  121.50 +
  121.51 +
  121.52 +//-----------------------------------------------------------------------------
  121.53 +// DK2 Serial Format
  121.54 +
  121.55 +enum DK2ProductId
  121.56 +{
  121.57 +	DK2ProductId_DK1    = 1, // DK1
  121.58 +	DK2ProductId_DK2    = 2, // Product Id used for initial DK2 launch
  121.59 +	DK2ProductId_Refurb = 3, // Refurbished DK2
  121.60 +};
  121.61 +
  121.62 +enum DK2PartId
  121.63 +{
  121.64 +	DK2PartId_HMD    = 0, // HMD
  121.65 +	DK2PartId_PTC    = 1, // PTC(camera)
  121.66 +	DK2PartId_Carton = 2, // Carton: An HMD + PTC combo (should not be stamped on a component) AKA Overpack
  121.67 +};
  121.68 +
  121.69 +typedef DK2PartId DK2LabelType; // Printed Serial Number version
  121.70 +
  121.71 +
  121.72 +// DK2 tool for reading/writing the binary serial format
  121.73 +class DK2BinarySerialFormat
  121.74 +{
  121.75 +public:
  121.76 +	static const SerialFormatType FormatType = SerialFormatType_DK2; // first byte
  121.77 +
  121.78 +	DK2ProductId ProductId;         // [4 bits] 2 = DK2
  121.79 +	DK2PartId    PartId;            // [4 bits] 0 means HMD, 1 means PTC(camera)
  121.80 +	int          MinutesSinceEpoch; // [3 bytes] Number of minutes that have elapsed since the epoch: May 1st, 2014
  121.81 +	// [0] = high byte, [1] = middle byte, [2] = low byte
  121.82 +	int          UnitNumber;        // [2 bytes] Value that increments each time a new serial number is created.  Resets to zero each day
  121.83 +	// [0] = high byte, [1] = low byte
  121.84 +	uint8_t      MacHash[5];        // [5 bytes] 5 most significant bytes of MD5 hash from first ethernet adapter mac address
  121.85 +
  121.86 +	bool operator==(const DK2BinarySerialFormat& rhs);
  121.87 +
  121.88 +public:
  121.89 +	// Returns false if the input is invalid in some way
  121.90 +	bool FromBuffer(const uint8_t buffer[12], bool allowUnknownTypes = false);
  121.91 +
  121.92 +	// Fills the provided buffer with 12 bytes
  121.93 +	void ToBuffer(uint8_t buffer[12]);
  121.94 +};
  121.95 +
  121.96 +
  121.97 +// DK2 tool for reading/writing the printed serial format
  121.98 +class DK2PrintedSerialFormat
  121.99 +{
 121.100 +public:
 121.101 +	DK2ProductId ProductId;         // [1 char] 2 = DK2, 3 = Reconditioned bundle
 121.102 +	DK2LabelType LabelType;         // [1 char] 0 means HMD, 1 means PTC(camera), 2 means Overpack(bundle)
 121.103 +	int          MinutesSinceEpoch; // [4 char] Number of minutes that have elapsed since the epoch: May 1st, 2014
 121.104 +	int          UnitNumber;        // [3 char] Value that increments each time a new serial number is created.  Resets to zero each day
 121.105 +	uint8_t      MacHashLow[3];     // [3 char] 3 least significant bytes of mac hash
 121.106 +
 121.107 +	bool operator==(const DK2PrintedSerialFormat& rhs);
 121.108 +	bool operator==(const DK2BinarySerialFormat& rhs);
 121.109 +
 121.110 +public:
 121.111 +	// Convert from binary to printed
 121.112 +	void FromBinary(const DK2BinarySerialFormat& bin);
 121.113 +
 121.114 +	// Returns false if the input is invalid in some way
 121.115 +	// Convert from a 12 character printed serial number
 121.116 +	bool FromBase32(const char* str, bool allowUnknownTypes = false);
 121.117 +
 121.118 +	// Returns a long human-readable base32 string (20 characters), NOT a printed serial number
 121.119 +	String ToBase32();
 121.120 +};
 121.121 +
 121.122 +
 121.123 +//#define SERIAL_FORMAT_UNIT_TEST
 121.124 +#ifdef SERIAL_FORMAT_UNIT_TEST
 121.125 +void TestSerialFormatStuff();
 121.126 +#endif
 121.127 +
 121.128 +
 121.129 +} // OVR
 121.130 +
 121.131 +#endif // OVR_SerialFormat_h
   122.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   122.2 +++ b/LibOVR/Src/OVR_Stereo.cpp	Wed Jan 14 06:51:16 2015 +0200
   122.3 @@ -0,0 +1,1874 @@
   122.4 +/************************************************************************************
   122.5 +
   122.6 +Filename    :   OVR_Stereo.cpp
   122.7 +Content     :   Stereo rendering functions
   122.8 +Created     :   November 30, 2013
   122.9 +Authors     :   Tom Fosyth
  122.10 +
  122.11 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
  122.12 +
  122.13 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
  122.14 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
  122.15 +which is provided at the time of installation or download, or which 
  122.16 +otherwise accompanies this software in either electronic or hard copy form.
  122.17 +
  122.18 +You may obtain a copy of the License at
  122.19 +
  122.20 +http://www.oculusvr.com/licenses/LICENSE-3.2 
  122.21 +
  122.22 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
  122.23 +distributed under the License is distributed on an "AS IS" BASIS,
  122.24 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  122.25 +See the License for the specific language governing permissions and
  122.26 +limitations under the License.
  122.27 +
  122.28 +*************************************************************************************/
  122.29 +
  122.30 +#include "OVR_Stereo.h"
  122.31 +#include "OVR_Profile.h"
  122.32 +#include "Kernel/OVR_Log.h"
  122.33 +#include "Kernel/OVR_Alg.h"
  122.34 +
  122.35 +//To allow custom distortion to be introduced to CatMulSpline.
  122.36 +float (*CustomDistortion)(float) = NULL;
  122.37 +float (*CustomDistortionInv)(float) = NULL;
  122.38 +
  122.39 +
  122.40 +namespace OVR {
  122.41 +
  122.42 +
  122.43 +using namespace Alg;
  122.44 +
  122.45 +//-----------------------------------------------------------------------------------
  122.46 +
  122.47 +// Inputs are 4 points (pFitX[0],pFitY[0]) through (pFitX[3],pFitY[3])
  122.48 +// Result is four coefficients in pResults[0] through pResults[3] such that
  122.49 +//      y = pResult[0] + x * ( pResult[1] + x * ( pResult[2] + x * ( pResult[3] ) ) );
  122.50 +// passes through all four input points.
  122.51 +// Return is true if it succeeded, false if it failed (because two control points
  122.52 +// have the same pFitX value).
  122.53 +bool FitCubicPolynomial ( float *pResult, const float *pFitX, const float *pFitY )
  122.54 +{
  122.55 +    float d0 = ( ( pFitX[0]-pFitX[1] ) * ( pFitX[0]-pFitX[2] ) * ( pFitX[0]-pFitX[3] ) );
  122.56 +    float d1 = ( ( pFitX[1]-pFitX[2] ) * ( pFitX[1]-pFitX[3] ) * ( pFitX[1]-pFitX[0] ) );
  122.57 +    float d2 = ( ( pFitX[2]-pFitX[3] ) * ( pFitX[2]-pFitX[0] ) * ( pFitX[2]-pFitX[1] ) );
  122.58 +    float d3 = ( ( pFitX[3]-pFitX[0] ) * ( pFitX[3]-pFitX[1] ) * ( pFitX[3]-pFitX[2] ) );
  122.59 +
  122.60 +    if ( ( d0 == 0.0f ) || ( d1 == 0.0f ) || ( d2 == 0.0f ) || ( d3 == 0.0f ) )
  122.61 +    {
  122.62 +        return false;
  122.63 +    }
  122.64 +
  122.65 +    float f0 = pFitY[0] / d0;
  122.66 +    float f1 = pFitY[1] / d1;
  122.67 +    float f2 = pFitY[2] / d2;
  122.68 +    float f3 = pFitY[3] / d3;
  122.69 +
  122.70 +    pResult[0] = -( f0*pFitX[1]*pFitX[2]*pFitX[3]
  122.71 +                  + f1*pFitX[0]*pFitX[2]*pFitX[3]
  122.72 +                  + f2*pFitX[0]*pFitX[1]*pFitX[3]
  122.73 +                  + f3*pFitX[0]*pFitX[1]*pFitX[2] );
  122.74 +    pResult[1] = f0*(pFitX[1]*pFitX[2] + pFitX[2]*pFitX[3] + pFitX[3]*pFitX[1])
  122.75 +               + f1*(pFitX[0]*pFitX[2] + pFitX[2]*pFitX[3] + pFitX[3]*pFitX[0])
  122.76 +               + f2*(pFitX[0]*pFitX[1] + pFitX[1]*pFitX[3] + pFitX[3]*pFitX[0])
  122.77 +               + f3*(pFitX[0]*pFitX[1] + pFitX[1]*pFitX[2] + pFitX[2]*pFitX[0]);
  122.78 +    pResult[2] = -( f0*(pFitX[1]+pFitX[2]+pFitX[3])
  122.79 +                  + f1*(pFitX[0]+pFitX[2]+pFitX[3])
  122.80 +                  + f2*(pFitX[0]+pFitX[1]+pFitX[3])
  122.81 +                  + f3*(pFitX[0]+pFitX[1]+pFitX[2]) );
  122.82 +    pResult[3] = f0 + f1 + f2 + f3;
  122.83 +
  122.84 +    return true;
  122.85 +}
  122.86 +
  122.87 +#define TPH_SPLINE_STATISTICS 0
  122.88 +#if TPH_SPLINE_STATISTICS
  122.89 +static float max_scaledVal = 0;
  122.90 +static float average_total_out_of_range = 0;
  122.91 +static float average_out_of_range;
  122.92 +static int num_total = 0;
  122.93 +static int num_out_of_range = 0;
  122.94 +static int num_out_of_range_over_1 = 0;
  122.95 +static int num_out_of_range_over_2 = 0;
  122.96 +static int num_out_of_range_over_3 = 0;
  122.97 +static float percent_out_of_range;
  122.98 +#endif
  122.99 +
 122.100 +float EvalCatmullRom10Spline ( float const *K, float scaledVal )
 122.101 +{
 122.102 +    int const NumSegments = LensConfig::NumCoefficients;
 122.103 +
 122.104 +	#if TPH_SPLINE_STATISTICS
 122.105 +	//Value should be in range of 0 to (NumSegments-1) (typically 10) if spline is valid. Right?
 122.106 +	if (scaledVal > (NumSegments-1))
 122.107 +	{
 122.108 +		num_out_of_range++;
 122.109 +		average_total_out_of_range+=scaledVal;
 122.110 +		average_out_of_range = average_total_out_of_range / ((float) num_out_of_range); 
 122.111 +		percent_out_of_range = 100.0f*(num_out_of_range)/num_total;
 122.112 +	}
 122.113 +	if (scaledVal > (NumSegments-1+1)) num_out_of_range_over_1++;
 122.114 +	if (scaledVal > (NumSegments-1+2)) num_out_of_range_over_2++;
 122.115 +	if (scaledVal > (NumSegments-1+3)) num_out_of_range_over_3++;
 122.116 +	num_total++;
 122.117 +	if (scaledVal > max_scaledVal)
 122.118 +	{
 122.119 +		max_scaledVal = scaledVal;
 122.120 +		max_scaledVal = scaledVal;
 122.121 +	}
 122.122 +	#endif
 122.123 +
 122.124 +    float scaledValFloor = floorf ( scaledVal );
 122.125 +    scaledValFloor = Alg::Max ( 0.0f, Alg::Min ( (float)(NumSegments-1), scaledValFloor ) );
 122.126 +    float t = scaledVal - scaledValFloor;
 122.127 +    int k = (int)scaledValFloor;
 122.128 +
 122.129 +    float p0, p1;
 122.130 +    float m0, m1;
 122.131 +    switch ( k )
 122.132 +    {
 122.133 +    case 0:
 122.134 +        // Curve starts at 1.0 with gradient K[1]-K[0]
 122.135 +        p0 = 1.0f;
 122.136 +        m0 =        ( K[1] - K[0] );    // general case would have been (K[1]-K[-1])/2
 122.137 +        p1 = K[1];
 122.138 +        m1 = 0.5f * ( K[2] - K[0] );
 122.139 +        break;
 122.140 +    default:
 122.141 +        // General case
 122.142 +        p0 = K[k  ];
 122.143 +        m0 = 0.5f * ( K[k+1] - K[k-1] );
 122.144 +        p1 = K[k+1];
 122.145 +        m1 = 0.5f * ( K[k+2] - K[k  ] );
 122.146 +        break;
 122.147 +    case NumSegments-2:
 122.148 +        // Last tangent is just the slope of the last two points.
 122.149 +        p0 = K[NumSegments-2];
 122.150 +        m0 = 0.5f * ( K[NumSegments-1] - K[NumSegments-2] );
 122.151 +        p1 = K[NumSegments-1];
 122.152 +        m1 = K[NumSegments-1] - K[NumSegments-2];
 122.153 +        break;
 122.154 +    case NumSegments-1:
 122.155 +        // Beyond the last segment it's just a straight line
 122.156 +        p0 = K[NumSegments-1];
 122.157 +        m0 = K[NumSegments-1] - K[NumSegments-2];
 122.158 +        p1 = p0 + m0;
 122.159 +        m1 = m0;
 122.160 +        break;
 122.161 +    }
 122.162 +
 122.163 +    float omt = 1.0f - t;
 122.164 +    float res  = ( p0 * ( 1.0f + 2.0f *   t ) + m0 *   t ) * omt * omt
 122.165 +               + ( p1 * ( 1.0f + 2.0f * omt ) - m1 * omt ) *   t *   t;
 122.166 +
 122.167 +    return res;
 122.168 +}
 122.169 +
 122.170 +
 122.171 +
 122.172 +
 122.173 +// Converts a Profile eyecup string into an eyecup enumeration
 122.174 +void SetEyeCup(HmdRenderInfo* renderInfo, const char* cup)
 122.175 +{
 122.176 +    if (OVR_strcmp(cup, "A") == 0)
 122.177 +        renderInfo->EyeCups = EyeCup_DK1A;
 122.178 +    else if (OVR_strcmp(cup, "B") == 0)
 122.179 +        renderInfo->EyeCups = EyeCup_DK1B;
 122.180 +    else if (OVR_strcmp(cup, "C") == 0)
 122.181 +        renderInfo->EyeCups = EyeCup_DK1C;
 122.182 +    else if (OVR_strcmp(cup, "Orange A") == 0)
 122.183 +        renderInfo->EyeCups =  EyeCup_OrangeA;
 122.184 +    else if (OVR_strcmp(cup, "Red A") == 0)
 122.185 +        renderInfo->EyeCups = EyeCup_RedA;
 122.186 +    else if (OVR_strcmp(cup, "Pink A") == 0)
 122.187 +        renderInfo->EyeCups = EyeCup_PinkA;
 122.188 +    else if (OVR_strcmp(cup, "Blue A") == 0)
 122.189 +        renderInfo->EyeCups = EyeCup_BlueA;
 122.190 +    else
 122.191 +        renderInfo->EyeCups = EyeCup_DK1A;
 122.192 +}
 122.193 +
 122.194 +
 122.195 +
 122.196 +//-----------------------------------------------------------------------------------
 122.197 +
 122.198 +
 122.199 +// The result is a scaling applied to the distance.
 122.200 +float LensConfig::DistortionFnScaleRadiusSquared (float rsq) const
 122.201 +{
 122.202 +    float scale = 1.0f;
 122.203 +    switch ( Eqn )
 122.204 +    {
 122.205 +    case Distortion_Poly4:
 122.206 +        // This version is deprecated! Prefer one of the other two.
 122.207 +        scale = ( K[0] + rsq * ( K[1] + rsq * ( K[2] + rsq * K[3] ) ) );
 122.208 +        break;
 122.209 +    case Distortion_RecipPoly4:
 122.210 +        scale = 1.0f / ( K[0] + rsq * ( K[1] + rsq * ( K[2] + rsq * K[3] ) ) );
 122.211 +        break;
 122.212 +    case Distortion_CatmullRom10:{
 122.213 +        // A Catmull-Rom spline through the values 1.0, K[1], K[2] ... K[10]
 122.214 +        // evenly spaced in R^2 from 0.0 to MaxR^2
 122.215 +        // K[0] controls the slope at radius=0.0, rather than the actual value.
 122.216 +        const int NumSegments = LensConfig::NumCoefficients;
 122.217 +        OVR_ASSERT ( NumSegments <= NumCoefficients );
 122.218 +        float scaledRsq = (float)(NumSegments-1) * rsq / ( MaxR * MaxR );
 122.219 +        scale = EvalCatmullRom10Spline ( K, scaledRsq );
 122.220 +
 122.221 +
 122.222 +		//Intercept, and overrule if needed
 122.223 +		if (CustomDistortion)
 122.224 +		{
 122.225 +			scale = CustomDistortion(rsq);
 122.226 +		}
 122.227 +
 122.228 +        }break;
 122.229 +    default:
 122.230 +        OVR_ASSERT ( false );
 122.231 +        break;
 122.232 +    }
 122.233 +    return scale;
 122.234 +}
 122.235 +
 122.236 +// x,y,z components map to r,g,b
 122.237 +Vector3f LensConfig::DistortionFnScaleRadiusSquaredChroma (float rsq) const
 122.238 +{
 122.239 +    float scale = DistortionFnScaleRadiusSquared ( rsq );
 122.240 +    Vector3f scaleRGB;
 122.241 +    scaleRGB.x = scale * ( 1.0f + ChromaticAberration[0] + rsq * ChromaticAberration[1] );     // Red
 122.242 +    scaleRGB.y = scale;                                                                        // Green
 122.243 +    scaleRGB.z = scale * ( 1.0f + ChromaticAberration[2] + rsq * ChromaticAberration[3] );     // Blue
 122.244 +    return scaleRGB;
 122.245 +}
 122.246 +
 122.247 +// DistortionFnInverse computes the inverse of the distortion function on an argument.
 122.248 +float LensConfig::DistortionFnInverse(float r) const
 122.249 +{    
 122.250 +    OVR_ASSERT((r <= 20.0f));
 122.251 +
 122.252 +    float s, d;
 122.253 +    float delta = r * 0.25f;
 122.254 +
 122.255 +    // Better to start guessing too low & take longer to converge than too high
 122.256 +    // and hit singularities. Empirically, r * 0.5f is too high in some cases.
 122.257 +    s = r * 0.25f;
 122.258 +    d = fabs(r - DistortionFn(s));
 122.259 +
 122.260 +    for (int i = 0; i < 20; i++)
 122.261 +    {
 122.262 +        float sUp   = s + delta;
 122.263 +        float sDown = s - delta;
 122.264 +        float dUp   = fabs(r - DistortionFn(sUp));
 122.265 +        float dDown = fabs(r - DistortionFn(sDown));
 122.266 +
 122.267 +        if (dUp < d)
 122.268 +        {
 122.269 +            s = sUp;
 122.270 +            d = dUp;
 122.271 +        }
 122.272 +        else if (dDown < d)
 122.273 +        {
 122.274 +            s = sDown;
 122.275 +            d = dDown;
 122.276 +        }
 122.277 +        else
 122.278 +        {
 122.279 +            delta *= 0.5f;
 122.280 +        }
 122.281 +    }
 122.282 +
 122.283 +    return s;
 122.284 +}
 122.285 +
 122.286 +
 122.287 +
 122.288 +float LensConfig::DistortionFnInverseApprox(float r) const
 122.289 +{
 122.290 +    float rsq = r * r;
 122.291 +    float scale = 1.0f;
 122.292 +    switch ( Eqn )
 122.293 +    {
 122.294 +    case Distortion_Poly4:
 122.295 +        // Deprecated
 122.296 +        OVR_ASSERT ( false );
 122.297 +        break;
 122.298 +    case Distortion_RecipPoly4:
 122.299 +        scale = 1.0f / ( InvK[0] + rsq * ( InvK[1] + rsq * ( InvK[2] + rsq * InvK[3] ) ) );
 122.300 +        break;
 122.301 +    case Distortion_CatmullRom10:{
 122.302 +        // A Catmull-Rom spline through the values 1.0, K[1], K[2] ... K[9]
 122.303 +        // evenly spaced in R^2 from 0.0 to MaxR^2
 122.304 +        // K[0] controls the slope at radius=0.0, rather than the actual value.
 122.305 +        const int NumSegments = LensConfig::NumCoefficients;
 122.306 +        OVR_ASSERT ( NumSegments <= NumCoefficients );
 122.307 +        float scaledRsq = (float)(NumSegments-1) * rsq / ( MaxInvR * MaxInvR );
 122.308 +        scale = EvalCatmullRom10Spline ( InvK, scaledRsq );
 122.309 +
 122.310 +		//Intercept, and overrule if needed
 122.311 +		if (CustomDistortionInv)
 122.312 +		{
 122.313 +			scale = CustomDistortionInv(rsq);
 122.314 +		}
 122.315 +
 122.316 +        }break;
 122.317 +    default:
 122.318 +        OVR_ASSERT ( false );
 122.319 +        break;
 122.320 +    }
 122.321 +    return r * scale;
 122.322 +}
 122.323 +
 122.324 +void LensConfig::SetUpInverseApprox()
 122.325 +{
 122.326 +    float maxR = MaxInvR;
 122.327 +
 122.328 +    switch ( Eqn )
 122.329 +    {
 122.330 +    case Distortion_Poly4:
 122.331 +        // Deprecated
 122.332 +        OVR_ASSERT ( false );
 122.333 +        break;
 122.334 +    case Distortion_RecipPoly4:{
 122.335 +
 122.336 +        float sampleR[4];
 122.337 +        float sampleRSq[4];
 122.338 +        float sampleInv[4];
 122.339 +        float sampleFit[4];
 122.340 +
 122.341 +        // Found heuristically...
 122.342 +        sampleR[0] = 0.0f;
 122.343 +        sampleR[1] = maxR * 0.4f;
 122.344 +        sampleR[2] = maxR * 0.8f;
 122.345 +        sampleR[3] = maxR * 1.5f;
 122.346 +        for ( int i = 0; i < 4; i++ )
 122.347 +        {
 122.348 +            sampleRSq[i] = sampleR[i] * sampleR[i];
 122.349 +            sampleInv[i] = DistortionFnInverse ( sampleR[i] );
 122.350 +            sampleFit[i] = sampleR[i] / sampleInv[i];
 122.351 +        }
 122.352 +        sampleFit[0] = 1.0f;
 122.353 +        FitCubicPolynomial ( InvK, sampleRSq, sampleFit );
 122.354 +
 122.355 +    #if 0
 122.356 +        // Should be a nearly exact match on the chosen points.
 122.357 +        OVR_ASSERT ( fabs ( DistortionFnInverse ( sampleR[0] ) - DistortionFnInverseApprox ( sampleR[0] ) ) / maxR < 0.0001f );
 122.358 +        OVR_ASSERT ( fabs ( DistortionFnInverse ( sampleR[1] ) - DistortionFnInverseApprox ( sampleR[1] ) ) / maxR < 0.0001f );
 122.359 +        OVR_ASSERT ( fabs ( DistortionFnInverse ( sampleR[2] ) - DistortionFnInverseApprox ( sampleR[2] ) ) / maxR < 0.0001f );
 122.360 +        OVR_ASSERT ( fabs ( DistortionFnInverse ( sampleR[3] ) - DistortionFnInverseApprox ( sampleR[3] ) ) / maxR < 0.0001f );
 122.361 +        // Should be a decent match on the rest of the range.
 122.362 +        const int maxCheck = 20;
 122.363 +        for ( int i = 0; i < maxCheck; i++ )
 122.364 +        {
 122.365 +            float checkR = (float)i * maxR / (float)maxCheck;
 122.366 +            float realInv = DistortionFnInverse       ( checkR );
 122.367 +            float testInv = DistortionFnInverseApprox ( checkR );
 122.368 +            float error = fabsf ( realInv - testInv ) / maxR;
 122.369 +            OVR_ASSERT ( error < 0.1f );
 122.370 +        }
 122.371 +    #endif
 122.372 +
 122.373 +        }break;
 122.374 +    case Distortion_CatmullRom10:{
 122.375 +
 122.376 +        const int NumSegments = LensConfig::NumCoefficients;
 122.377 +        OVR_ASSERT ( NumSegments <= NumCoefficients );
 122.378 +        for ( int i = 1; i < NumSegments; i++ )
 122.379 +        {
 122.380 +            float scaledRsq = (float)i;
 122.381 +            float rsq = scaledRsq * MaxInvR * MaxInvR / (float)( NumSegments - 1);
 122.382 +            float r = sqrtf ( rsq );
 122.383 +            float inv = DistortionFnInverse ( r );
 122.384 +            InvK[i] = inv / r;
 122.385 +            InvK[0] = 1.0f;     // TODO: fix this.
 122.386 +        }
 122.387 +
 122.388 +#if 0
 122.389 +        const int maxCheck = 20;
 122.390 +        for ( int i = 0; i <= maxCheck; i++ )
 122.391 +        {
 122.392 +            float checkR = (float)i * MaxInvR / (float)maxCheck;
 122.393 +            float realInv = DistortionFnInverse       ( checkR );
 122.394 +            float testInv = DistortionFnInverseApprox ( checkR );
 122.395 +            float error = fabsf ( realInv - testInv ) / MaxR;
 122.396 +            OVR_ASSERT ( error < 0.01f );
 122.397 +        }
 122.398 +#endif
 122.399 +
 122.400 +        }break;
 122.401 +
 122.402 +    default:
 122.403 +        break;
 122.404 +    }
 122.405 +}
 122.406 +
 122.407 +
 122.408 +void LensConfig::SetToIdentity()
 122.409 +{
 122.410 +    for ( int i = 0; i < NumCoefficients; i++ )
 122.411 +    {
 122.412 +        K[i] = 0.0f;
 122.413 +        InvK[i] = 0.0f;
 122.414 +    }
 122.415 +    Eqn = Distortion_RecipPoly4;
 122.416 +    K[0] = 1.0f;
 122.417 +    InvK[0] = 1.0f;
 122.418 +    MaxR = 1.0f;
 122.419 +    MaxInvR = 1.0f;
 122.420 +    ChromaticAberration[0] = 0.0f;
 122.421 +    ChromaticAberration[1] = 0.0f;
 122.422 +    ChromaticAberration[2] = 0.0f;
 122.423 +    ChromaticAberration[3] = 0.0f;
 122.424 +    MetersPerTanAngleAtCenter = 0.05f;
 122.425 +}
 122.426 +
 122.427 +
 122.428 +enum LensConfigStoredVersion
 122.429 +{
 122.430 +    LCSV_CatmullRom10Version1 = 1
 122.431 +};
 122.432 +
 122.433 +// DO NOT CHANGE THESE ONCE THEY HAVE BEEN BAKED INTO FIRMWARE.
 122.434 +// If something needs to change, add a new one!
 122.435 +struct LensConfigStored_CatmullRom10Version1
 122.436 +{
 122.437 +    // All these items must be fixed-length integers - no "float", no "int", etc.
 122.438 +    uint16_t    VersionNumber;      // Must be LCSV_CatmullRom10Version1
 122.439 +
 122.440 +    uint16_t    K[11];
 122.441 +    uint16_t    MaxR;
 122.442 +    uint16_t    MetersPerTanAngleAtCenter;
 122.443 +    uint16_t    ChromaticAberration[4];
 122.444 +    // InvK and MaxInvR are calculated on load.
 122.445 +};
 122.446 +
 122.447 +uint16_t EncodeFixedPointUInt16 ( float val, uint16_t zeroVal, int fractionalBits )
 122.448 +{
 122.449 +    OVR_ASSERT ( ( fractionalBits >= 0 ) && ( fractionalBits < 31 ) );
 122.450 +    float valWhole = val * (float)( 1 << fractionalBits );
 122.451 +    valWhole += (float)zeroVal + 0.5f;
 122.452 +    valWhole = floorf ( valWhole );
 122.453 +    OVR_ASSERT ( ( valWhole >= 0.0f ) && ( valWhole < (float)( 1 << 16 ) ) );
 122.454 +    return (uint16_t)valWhole;
 122.455 +}
 122.456 +
 122.457 +float DecodeFixedPointUInt16 ( uint16_t val, uint16_t zeroVal, int fractionalBits )
 122.458 +{
 122.459 +    OVR_ASSERT ( ( fractionalBits >= 0 ) && ( fractionalBits < 31 ) );
 122.460 +    float valFloat = (float)val;
 122.461 +    valFloat -= (float)zeroVal;
 122.462 +    valFloat *= 1.0f / (float)( 1 << fractionalBits );
 122.463 +    return valFloat;
 122.464 +}
 122.465 +
 122.466 +
 122.467 +// Returns true on success.
 122.468 +bool LoadLensConfig ( LensConfig *presult, uint8_t const *pbuffer, int bufferSizeInBytes )
 122.469 +{
 122.470 +    if ( bufferSizeInBytes < 2 )
 122.471 +    {
 122.472 +        // Can't even tell the version number!
 122.473 +        return false;
 122.474 +    }
 122.475 +    uint16_t version = DecodeUInt16 ( pbuffer + 0 );
 122.476 +    switch ( version )
 122.477 +    {
 122.478 +    case LCSV_CatmullRom10Version1:
 122.479 +        {
 122.480 +            if ( bufferSizeInBytes < (int)sizeof(LensConfigStored_CatmullRom10Version1) )
 122.481 +            {
 122.482 +                return false;
 122.483 +            }
 122.484 +            LensConfigStored_CatmullRom10Version1 lcs;
 122.485 +            lcs.VersionNumber               = DecodeUInt16 ( pbuffer + 0 );
 122.486 +            for ( int i = 0; i < 11; i++ )
 122.487 +            {
 122.488 +                lcs.K[i]                    = DecodeUInt16 ( pbuffer + 2 + 2*i );
 122.489 +            }
 122.490 +            lcs.MaxR                        = DecodeUInt16 ( pbuffer + 24 );
 122.491 +            lcs.MetersPerTanAngleAtCenter   = DecodeUInt16 ( pbuffer + 26 );
 122.492 +            for ( int i = 0; i < 4; i++ )
 122.493 +            {
 122.494 +                lcs.ChromaticAberration[i]  = DecodeUInt16 ( pbuffer + 28 + 2*i );
 122.495 +            }
 122.496 +            OVR_COMPILER_ASSERT ( sizeof(lcs) ==                       36 );
 122.497 +
 122.498 +            // Convert to the real thing.
 122.499 +            LensConfig result;
 122.500 +            result.Eqn = Distortion_CatmullRom10;
 122.501 +            for ( int i = 0; i < 11; i++ )
 122.502 +            {
 122.503 +                // K[] are mostly 1.something. They may get significantly bigger, but they never hit 0.0.
 122.504 +                result.K[i] = DecodeFixedPointUInt16 ( lcs.K[i], 0, 14 );
 122.505 +            }
 122.506 +            // MaxR is tan(angle), so always >0, typically just over 1.0 (45 degrees half-fov),
 122.507 +            // but may get arbitrarily high. tan(76)=4 is a very reasonable limit!
 122.508 +            result.MaxR = DecodeFixedPointUInt16 ( lcs.MaxR, 0, 14 );
 122.509 +            // MetersPerTanAngleAtCenter is also known as focal length!
 122.510 +            // Typically around 0.04 for our current screens, minimum of 0, sensible maximum of 0.125 (i.e. 3 "extra" bits of fraction)
 122.511 +            result.MetersPerTanAngleAtCenter = DecodeFixedPointUInt16 ( lcs.MetersPerTanAngleAtCenter, 0, 16+3 );
 122.512 +            for ( int i = 0; i < 4; i++ )
 122.513 +            {
 122.514 +                // ChromaticAberration[] are mostly 0.0something, centered on 0.0. Largest seen is 0.04, so set max to 0.125 (i.e. 3 "extra" bits of fraction)
 122.515 +                result.ChromaticAberration[i] = DecodeFixedPointUInt16 ( lcs.ChromaticAberration[i], 0x8000, 16+3 );
 122.516 +            }
 122.517 +            result.MaxInvR = result.DistortionFn ( result.MaxR );
 122.518 +            result.SetUpInverseApprox();
 122.519 +
 122.520 +            OVR_ASSERT ( version == lcs.VersionNumber );
 122.521 +
 122.522 +            *presult = result;
 122.523 +        }
 122.524 +        break;
 122.525 +    default:
 122.526 +        // Unknown format.
 122.527 +        return false;
 122.528 +        break;
 122.529 +    }
 122.530 +    return true;
 122.531 +}
 122.532 +
 122.533 +// Returns number of bytes needed.
 122.534 +int SaveLensConfigSizeInBytes ( LensConfig const &config )
 122.535 +{
 122.536 +    OVR_UNUSED ( config );
 122.537 +    return sizeof ( LensConfigStored_CatmullRom10Version1 );
 122.538 +}
 122.539 +
 122.540 +// Returns true on success.
 122.541 +bool SaveLensConfig ( uint8_t *pbuffer, int bufferSizeInBytes, LensConfig const &config )
 122.542 +{
 122.543 +    if ( bufferSizeInBytes < (int)sizeof ( LensConfigStored_CatmullRom10Version1 ) )
 122.544 +    {
 122.545 +        return false;
 122.546 +    }
 122.547 +
 122.548 +    // Construct the values.
 122.549 +    LensConfigStored_CatmullRom10Version1 lcs;
 122.550 +    lcs.VersionNumber = LCSV_CatmullRom10Version1;
 122.551 +    for ( int i = 0; i < 11; i++ )
 122.552 +    {
 122.553 +        // K[] are mostly 1.something. They may get significantly bigger, but they never hit 0.0.
 122.554 +        lcs.K[i] = EncodeFixedPointUInt16 ( config.K[i], 0, 14 );
 122.555 +    }
 122.556 +    // MaxR is tan(angle), so always >0, typically just over 1.0 (45 degrees half-fov),
 122.557 +    // but may get arbitrarily high. tan(76)=4 is a very reasonable limit!
 122.558 +    lcs.MaxR = EncodeFixedPointUInt16 ( config.MaxR, 0, 14 );
 122.559 +    // MetersPerTanAngleAtCenter is also known as focal length!
 122.560 +    // Typically around 0.04 for our current screens, minimum of 0, sensible maximum of 0.125 (i.e. 3 "extra" bits of fraction)
 122.561 +    lcs.MetersPerTanAngleAtCenter = EncodeFixedPointUInt16 ( config.MetersPerTanAngleAtCenter, 0, 16+3 );
 122.562 +    for ( int i = 0; i < 4; i++ )
 122.563 +    {
 122.564 +        // ChromaticAberration[] are mostly 0.0something, centered on 0.0. Largest seen is 0.04, so set max to 0.125 (i.e. 3 "extra" bits of fraction)
 122.565 +        lcs.ChromaticAberration[i] = EncodeFixedPointUInt16 ( config.ChromaticAberration[i], 0x8000, 16+3 );
 122.566 +    }
 122.567 +
 122.568 +
 122.569 +    // Now store them out, sensitive to endianness.
 122.570 +    EncodeUInt16 (      pbuffer + 0,        lcs.VersionNumber );
 122.571 +    for ( int i = 0; i < 11; i++ )
 122.572 +    {
 122.573 +        EncodeUInt16 (  pbuffer + 2 + 2*i,  lcs.K[i] );
 122.574 +    }
 122.575 +    EncodeUInt16 (      pbuffer + 24,       lcs.MaxR );
 122.576 +    EncodeUInt16 (      pbuffer + 26,       lcs.MetersPerTanAngleAtCenter );
 122.577 +    for ( int i = 0; i < 4; i++ )
 122.578 +    {
 122.579 +        EncodeUInt16 (  pbuffer + 28 + 2*i, lcs.ChromaticAberration[i] );
 122.580 +    }
 122.581 +    OVR_COMPILER_ASSERT (         36        == sizeof(lcs) );
 122.582 +
 122.583 +    return true;
 122.584 +}
 122.585 +
 122.586 +#ifdef OVR_BUILD_DEBUG
 122.587 +void TestSaveLoadLensConfig ( LensConfig const &config )
 122.588 +{
 122.589 +    OVR_ASSERT ( config.Eqn == Distortion_CatmullRom10 );
 122.590 +    // As a test, make sure this can be encoded and decoded correctly.
 122.591 +    const int bufferSize = 256;
 122.592 +    uint8_t buffer[bufferSize];
 122.593 +    OVR_ASSERT ( SaveLensConfigSizeInBytes ( config ) < bufferSize );
 122.594 +    bool success;
 122.595 +    success = SaveLensConfig ( buffer, bufferSize, config );
 122.596 +    OVR_ASSERT ( success );
 122.597 +    LensConfig testConfig;
 122.598 +    success = LoadLensConfig ( &testConfig, buffer, bufferSize );
 122.599 +    OVR_ASSERT ( success );
 122.600 +    OVR_ASSERT ( testConfig.Eqn == config.Eqn );
 122.601 +    for ( int i = 0; i < 11; i++ )
 122.602 +    {
 122.603 +        OVR_ASSERT ( fabs ( testConfig.K[i] - config.K[i] ) < 0.0001f );
 122.604 +    }
 122.605 +    OVR_ASSERT ( fabsf ( testConfig.MaxR - config.MaxR ) < 0.0001f );
 122.606 +    OVR_ASSERT ( fabsf ( testConfig.MetersPerTanAngleAtCenter - config.MetersPerTanAngleAtCenter ) < 0.00001f );
 122.607 +    for ( int i = 0; i < 4; i++ )
 122.608 +    {
 122.609 +        OVR_ASSERT ( fabsf ( testConfig.ChromaticAberration[i] - config.ChromaticAberration[i] ) < 0.00001f );
 122.610 +    }
 122.611 +}
 122.612 +#endif
 122.613 +
 122.614 +
 122.615 +
 122.616 +//-----------------------------------------------------------------------------------
 122.617 +
 122.618 +// TBD: There is a question of whether this is the best file for CreateDebugHMDInfo. As long as there are many
 122.619 +// constants for HmdRenderInfo here as well it is ok. The alternative would be OVR_Common_HMDDevice.cpp, but
 122.620 +// that's specialized per platform... should probably move it there onces the code is in the common base class.
 122.621 +
 122.622 +HMDInfo CreateDebugHMDInfo(HmdTypeEnum hmdType)
 122.623 +{
 122.624 +    HMDInfo info;    
 122.625 +
 122.626 +    if ((hmdType != HmdType_DK1) &&
 122.627 +        (hmdType != HmdType_CrystalCoveProto) &&
 122.628 +        (hmdType != HmdType_DK2))
 122.629 +    {
 122.630 +        LogText("Debug HMDInfo - HmdType not supported. Defaulting to DK1.\n");
 122.631 +        hmdType = HmdType_DK1;
 122.632 +    }
 122.633 +
 122.634 +    // The alternative would be to initialize info.HmdType to HmdType_None instead. If we did that,
 122.635 +    // code wouldn't be "maximally compatible" and devs wouldn't know what device we are
 122.636 +    // simulating... so if differentiation becomes necessary we better add Debug flag in the future.
 122.637 +    info.HmdType      = hmdType;
 122.638 +    info.Manufacturer = "Oculus VR";    
 122.639 +
 122.640 +    switch(hmdType)
 122.641 +    {
 122.642 +    case HmdType_DK1:
 122.643 +        info.ProductName                            = "Oculus Rift DK1";
 122.644 +        info.ResolutionInPixels                     = Sizei ( 1280, 800 );
 122.645 +        info.ScreenSizeInMeters                     = Sizef ( 0.1498f, 0.0936f );
 122.646 +        info.ScreenGapSizeInMeters                  = 0.0f;
 122.647 +        info.CenterFromTopInMeters                  = 0.0468f;
 122.648 +        info.LensSeparationInMeters                 = 0.0635f;
 122.649 +        info.PelOffsetR                             = Vector2f ( 0.0f, 0.0f );
 122.650 +        info.PelOffsetB                             = Vector2f ( 0.0f, 0.0f );
 122.651 +        info.Shutter.Type                           = HmdShutter_RollingTopToBottom;
 122.652 +        info.Shutter.VsyncToNextVsync               = ( 1.0f / 60.0f );
 122.653 +        info.Shutter.VsyncToFirstScanline           = 0.000052f;
 122.654 +        info.Shutter.FirstScanlineToLastScanline    = 0.016580f;
 122.655 +        info.Shutter.PixelSettleTime                = 0.015f;
 122.656 +        info.Shutter.PixelPersistence               = ( 1.0f / 60.0f );
 122.657 +        break;
 122.658 +
 122.659 +    case HmdType_CrystalCoveProto:
 122.660 +        info.ProductName                            = "Oculus Rift Crystal Cove";        
 122.661 +        info.ResolutionInPixels                     = Sizei ( 1920, 1080 );
 122.662 +        info.ScreenSizeInMeters                     = Sizef ( 0.12576f, 0.07074f );
 122.663 +        info.ScreenGapSizeInMeters                  = 0.0f;
 122.664 +        info.CenterFromTopInMeters                  = info.ScreenSizeInMeters.h * 0.5f;
 122.665 +        info.LensSeparationInMeters                 = 0.0635f;
 122.666 +        info.PelOffsetR                             = Vector2f ( 0.0f, 0.0f );
 122.667 +        info.PelOffsetB                             = Vector2f ( 0.0f, 0.0f );
 122.668 +        info.Shutter.Type                           = HmdShutter_RollingRightToLeft;
 122.669 +        info.Shutter.VsyncToNextVsync               = ( 1.0f / 76.0f );
 122.670 +        info.Shutter.VsyncToFirstScanline           = 0.0000273f;
 122.671 +        info.Shutter.FirstScanlineToLastScanline    = 0.0131033f;
 122.672 +        info.Shutter.PixelSettleTime                = 0.0f;
 122.673 +        info.Shutter.PixelPersistence               = 0.18f * info.Shutter.VsyncToNextVsync;
 122.674 +        break;
 122.675 +
 122.676 +    case HmdType_DK2:
 122.677 +        info.ProductName                            = "Oculus Rift DK2";        
 122.678 +        info.ResolutionInPixels                     = Sizei ( 1920, 1080 );
 122.679 +        info.ScreenSizeInMeters                     = Sizef ( 0.12576f, 0.07074f );
 122.680 +        info.ScreenGapSizeInMeters                  = 0.0f;
 122.681 +        info.CenterFromTopInMeters                  = info.ScreenSizeInMeters.h * 0.5f;
 122.682 +        info.LensSeparationInMeters                 = 0.0635f;
 122.683 +        info.PelOffsetR                             = Vector2f ( 0.5f, 0.5f );
 122.684 +        info.PelOffsetB                             = Vector2f ( 0.5f, 0.5f );
 122.685 +        info.Shutter.Type                           = HmdShutter_RollingRightToLeft;
 122.686 +        info.Shutter.VsyncToNextVsync               = ( 1.0f / 76.0f );
 122.687 +        info.Shutter.VsyncToFirstScanline           = 0.0000273f;
 122.688 +        info.Shutter.FirstScanlineToLastScanline    = 0.0131033f;
 122.689 +        info.Shutter.PixelSettleTime                = 0.0f;
 122.690 +        info.Shutter.PixelPersistence               = 0.18f * info.Shutter.VsyncToNextVsync;
 122.691 +        break;
 122.692 +
 122.693 +    default:
 122.694 +        break;
 122.695 +    }
 122.696 +
 122.697 +    return info;
 122.698 +}
 122.699 +
 122.700 +
 122.701 +HmdRenderInfo GenerateHmdRenderInfoFromHmdInfo ( HMDInfo const &hmdInfo,
 122.702 +                                                 Profile const *profile,
 122.703 +                                                 DistortionEqnType distortionType /*= Distortion_CatmullRom10*/,
 122.704 +                                                 EyeCupType eyeCupOverride /*= EyeCup_LAST*/ )
 122.705 +{
 122.706 +    HmdRenderInfo renderInfo;
 122.707 +    
 122.708 +    OVR_ASSERT(profile);  // profiles are required
 122.709 +    if(!profile)
 122.710 +        return renderInfo;
 122.711 +
 122.712 +    renderInfo.HmdType                              = hmdInfo.HmdType;
 122.713 +    renderInfo.ResolutionInPixels                   = hmdInfo.ResolutionInPixels;
 122.714 +    renderInfo.ScreenSizeInMeters                   = hmdInfo.ScreenSizeInMeters;
 122.715 +    renderInfo.CenterFromTopInMeters                = hmdInfo.CenterFromTopInMeters;
 122.716 +    renderInfo.ScreenGapSizeInMeters                = hmdInfo.ScreenGapSizeInMeters;
 122.717 +    renderInfo.LensSeparationInMeters               = hmdInfo.LensSeparationInMeters;
 122.718 +    renderInfo.PelOffsetR                           = hmdInfo.PelOffsetR;
 122.719 +    renderInfo.PelOffsetB                           = hmdInfo.PelOffsetB;
 122.720 +
 122.721 +    OVR_ASSERT ( sizeof(renderInfo.Shutter) == sizeof(hmdInfo.Shutter) );   // Try to keep the files in sync!
 122.722 +    renderInfo.Shutter.Type                         = hmdInfo.Shutter.Type;
 122.723 +    renderInfo.Shutter.VsyncToNextVsync             = hmdInfo.Shutter.VsyncToNextVsync;
 122.724 +    renderInfo.Shutter.VsyncToFirstScanline         = hmdInfo.Shutter.VsyncToFirstScanline;
 122.725 +    renderInfo.Shutter.FirstScanlineToLastScanline  = hmdInfo.Shutter.FirstScanlineToLastScanline;
 122.726 +    renderInfo.Shutter.PixelSettleTime              = hmdInfo.Shutter.PixelSettleTime;
 122.727 +    renderInfo.Shutter.PixelPersistence             = hmdInfo.Shutter.PixelPersistence;
 122.728 +
 122.729 +    renderInfo.LensDiameterInMeters                 = 0.035f;
 122.730 +    renderInfo.LensSurfaceToMidplateInMeters        = 0.025f;
 122.731 +    renderInfo.EyeCups                              = EyeCup_DK1A;
 122.732 +
 122.733 +#if 0       // Device settings are out of date - don't use them.
 122.734 +    if (Contents & Contents_Distortion)
 122.735 +    {
 122.736 +        memcpy(renderInfo.DistortionK, DistortionK, sizeof(float)*4);
 122.737 +        renderInfo.DistortionEqn = Distortion_RecipPoly4;
 122.738 +    }
 122.739 +#endif
 122.740 +
 122.741 +    // Defaults in case of no user profile.
 122.742 +    renderInfo.EyeLeft.NoseToPupilInMeters   = 0.032f;
 122.743 +    renderInfo.EyeLeft.ReliefInMeters        = 0.012f;
 122.744 +
 122.745 +    // 10mm eye-relief laser numbers for DK1 lenses.
 122.746 +    // These are a decent seed for finding eye-relief and IPD.
 122.747 +    // These are NOT used for rendering!
 122.748 +    // Rendering distortions are now in GenerateLensConfigFromEyeRelief()
 122.749 +    // So, if you're hacking in new distortions, don't do it here!
 122.750 +    renderInfo.EyeLeft.Distortion.SetToIdentity();
 122.751 +    renderInfo.EyeLeft.Distortion.MetersPerTanAngleAtCenter = 0.0449f;
 122.752 +    renderInfo.EyeLeft.Distortion.Eqn       = Distortion_RecipPoly4;
 122.753 +    renderInfo.EyeLeft.Distortion.K[0]      =  1.0f;
 122.754 +    renderInfo.EyeLeft.Distortion.K[1]      = -0.494165344f;
 122.755 +    renderInfo.EyeLeft.Distortion.K[2]      = 0.587046423f;
 122.756 +    renderInfo.EyeLeft.Distortion.K[3]      = -0.841887126f;
 122.757 +    renderInfo.EyeLeft.Distortion.MaxR      = 1.0f;
 122.758 +
 122.759 +    renderInfo.EyeLeft.Distortion.ChromaticAberration[0] = -0.006f;
 122.760 +    renderInfo.EyeLeft.Distortion.ChromaticAberration[1] =  0.0f;
 122.761 +    renderInfo.EyeLeft.Distortion.ChromaticAberration[2] =  0.014f;
 122.762 +    renderInfo.EyeLeft.Distortion.ChromaticAberration[3] =  0.0f;
 122.763 +
 122.764 +    renderInfo.EyeRight = renderInfo.EyeLeft;
 122.765 +
 122.766 +    // Obtain data from profile.
 122.767 +    char eyecup[16];
 122.768 +    if (profile->GetValue(OVR_KEY_EYE_CUP, eyecup, 16))
 122.769 +    {
 122.770 +        SetEyeCup(&renderInfo, eyecup);
 122.771 +    }
 122.772 +    
 122.773 +    switch ( hmdInfo.HmdType )
 122.774 +    {
 122.775 +    case HmdType_None:
 122.776 +    case HmdType_DKProto:
 122.777 +    case HmdType_DK1:
 122.778 +        // Slight hack to improve usability.
 122.779 +        // If you have a DKHD-style lens profile enabled,
 122.780 +        // but you plug in DK1 and forget to change the profile,
 122.781 +        // obviously you don't want those lens numbers.
 122.782 +        if ( ( renderInfo.EyeCups != EyeCup_DK1A ) &&
 122.783 +             ( renderInfo.EyeCups != EyeCup_DK1B ) &&
 122.784 +             ( renderInfo.EyeCups != EyeCup_DK1C ) )
 122.785 +        {
 122.786 +            renderInfo.EyeCups = EyeCup_DK1A;
 122.787 +        }
 122.788 +        break;
 122.789 +
 122.790 +    case HmdType_DKHD2Proto:
 122.791 +        renderInfo.EyeCups = EyeCup_DKHD2A;
 122.792 +        break;
 122.793 +    case HmdType_CrystalCoveProto:
 122.794 +        renderInfo.EyeCups = EyeCup_PinkA;
 122.795 +        break;
 122.796 +    case HmdType_DK2:
 122.797 +        renderInfo.EyeCups = EyeCup_DK2A;
 122.798 +        break;
 122.799 +    default:
 122.800 +        break;
 122.801 +    }
 122.802 +
 122.803 +    if ( eyeCupOverride != EyeCup_LAST )
 122.804 +    {
 122.805 +        renderInfo.EyeCups = eyeCupOverride;
 122.806 +    }
 122.807 +
 122.808 +    switch ( renderInfo.EyeCups )
 122.809 +    {
 122.810 +    case EyeCup_DK1A:
 122.811 +    case EyeCup_DK1B:
 122.812 +    case EyeCup_DK1C:
 122.813 +        renderInfo.LensDiameterInMeters                   = 0.035f;
 122.814 +        renderInfo.LensSurfaceToMidplateInMeters          = 0.02357f;
 122.815 +        // Not strictly lens-specific, but still wise to set a reasonable default for relief.
 122.816 +        renderInfo.EyeLeft.ReliefInMeters                 = 0.010f; 
 122.817 +        renderInfo.EyeRight.ReliefInMeters                = 0.010f; 
 122.818 +        break;
 122.819 +    case EyeCup_DKHD2A:
 122.820 +        renderInfo.LensDiameterInMeters                   = 0.035f;
 122.821 +        renderInfo.LensSurfaceToMidplateInMeters          = 0.02357f;
 122.822 +        // Not strictly lens-specific, but still wise to set a reasonable default for relief.
 122.823 +        renderInfo.EyeLeft.ReliefInMeters                 = 0.010f; 
 122.824 +        renderInfo.EyeRight.ReliefInMeters                = 0.010f; 
 122.825 +        break;
 122.826 +    case EyeCup_PinkA:
 122.827 +    case EyeCup_DK2A:
 122.828 +        renderInfo.LensDiameterInMeters                   = 0.04f;      // approximate
 122.829 +        renderInfo.LensSurfaceToMidplateInMeters          = 0.01965f;
 122.830 +        // Not strictly lens-specific, but still wise to set a reasonable default for relief.
 122.831 +        renderInfo.EyeLeft.ReliefInMeters                 = 0.012f;
 122.832 +        renderInfo.EyeRight.ReliefInMeters                = 0.012f;
 122.833 +        break;
 122.834 +    default: OVR_ASSERT ( false ); break;
 122.835 +    }
 122.836 +
 122.837 +    Profile* def = ProfileManager::GetInstance()->GetDefaultProfile(hmdInfo.HmdType);
 122.838 +
 122.839 +    // Set the eye position
 122.840 +    // Use the user profile value unless they have elected to use the defaults
 122.841 +    if (!profile->GetBoolValue(OVR_KEY_CUSTOM_EYE_RENDER, true))
 122.842 +        profile = def;  // use the default
 122.843 +
 122.844 +    char user[32];
 122.845 +    profile->GetValue(OVR_KEY_USER, user, 32);   // for debugging purposes
 122.846 +
 122.847 +    // TBD: Maybe we should separate custom camera positioning from custom distortion rendering ??
 122.848 +    float eye2nose[2] = { OVR_DEFAULT_IPD / 2, OVR_DEFAULT_IPD / 2 };
 122.849 +    if (profile->GetFloatValues(OVR_KEY_EYE_TO_NOSE_DISTANCE, eye2nose, 2) == 2)
 122.850 +    {   
 122.851 +        renderInfo.EyeLeft.NoseToPupilInMeters = eye2nose[0];
 122.852 +        renderInfo.EyeRight.NoseToPupilInMeters = eye2nose[1];
 122.853 +    }
 122.854 +    else
 122.855 +    {   // Legacy profiles may not include half-ipd, so use the regular IPD value instead
 122.856 +        float ipd = profile->GetFloatValue(OVR_KEY_IPD, OVR_DEFAULT_IPD);
 122.857 +        renderInfo.EyeLeft.NoseToPupilInMeters = 0.5f * ipd;
 122.858 +        renderInfo.EyeRight.NoseToPupilInMeters = 0.5f * ipd;
 122.859 +    }
 122.860 +        
 122.861 +    float eye2plate[2];
 122.862 +    if ((profile->GetFloatValues(OVR_KEY_MAX_EYE_TO_PLATE_DISTANCE, eye2plate, 2) == 2) ||
 122.863 +        (def->GetFloatValues(OVR_KEY_MAX_EYE_TO_PLATE_DISTANCE, eye2plate, 2) == 2))
 122.864 +    {   // Subtract the eye-cup height from the plate distance to get the eye-to-lens distance
 122.865 +        // This measurement should be the the distance at maximum dial setting
 122.866 +        // We still need to adjust with the dial offset
 122.867 +        renderInfo.EyeLeft.ReliefInMeters = eye2plate[0] - renderInfo.LensSurfaceToMidplateInMeters;
 122.868 +        renderInfo.EyeRight.ReliefInMeters = eye2plate[1] - renderInfo.LensSurfaceToMidplateInMeters;
 122.869 +
 122.870 +        // Adjust the eye relief with the dial setting (from the assumed max eye relief)
 122.871 +        int dial = profile->GetIntValue(OVR_KEY_EYE_RELIEF_DIAL, OVR_DEFAULT_EYE_RELIEF_DIAL);
 122.872 +        renderInfo.EyeLeft.ReliefInMeters -= ((10 - dial) * 0.001f);
 122.873 +        renderInfo.EyeRight.ReliefInMeters -= ((10 - dial) * 0.001f);
 122.874 +    }
 122.875 +    else
 122.876 +    {
 122.877 +        // We shouldn't be here.  The user or default profile should have the eye relief
 122.878 +        OVR_ASSERT(false);
 122.879 +
 122.880 +        // Set the eye relief with the user configured dial setting
 122.881 +		//int dial = profile->GetIntValue(OVR_KEY_EYE_RELIEF_DIAL, OVR_DEFAULT_EYE_RELIEF_DIAL);
 122.882 +
 122.883 +        // Assume a default of 7 to 17 mm eye relief based on the dial.  This corresponds
 122.884 +        // to the sampled and tuned distortion range on the DK1.
 122.885 +        //renderInfo.EyeLeft.ReliefInMeters = 0.007f + (dial * 0.001f);
 122.886 +        //renderInfo.EyeRight.ReliefInMeters = 0.007f + (dial * 0.001f);
 122.887 +    }
 122.888 +
 122.889 +    def->Release();
 122.890 +
 122.891 +
 122.892 +    // Now we know where the eyes are relative to the lenses, we can compute a distortion for each.
 122.893 +    // TODO: incorporate lateral offset in distortion generation.
 122.894 +    // TODO: we used a distortion to calculate eye-relief, and now we're making a distortion from that eye-relief. Close the loop!
 122.895 +
 122.896 +    for ( int eyeNum = 0; eyeNum < 2; eyeNum++ )
 122.897 +    {
 122.898 +        HmdRenderInfo::EyeConfig *pHmdEyeConfig = ( eyeNum == 0 ) ? &(renderInfo.EyeLeft) : &(renderInfo.EyeRight);
 122.899 +
 122.900 +        float eye_relief = pHmdEyeConfig->ReliefInMeters;
 122.901 +        LensConfig distortionConfig = GenerateLensConfigFromEyeRelief ( eye_relief, renderInfo, distortionType );
 122.902 +        pHmdEyeConfig->Distortion = distortionConfig;
 122.903 +    }
 122.904 +
 122.905 +    return renderInfo;
 122.906 +}
 122.907 +
 122.908 +
 122.909 +LensConfig GenerateLensConfigFromEyeRelief ( float eyeReliefInMeters, HmdRenderInfo const &hmd, DistortionEqnType distortionType /*= Distortion_CatmullRom10*/ )
 122.910 +{
 122.911 +    struct DistortionDescriptor
 122.912 +    {
 122.913 +        float EyeRelief;
 122.914 +        // The three places we're going to sample & lerp the curve at.
 122.915 +        // One sample is always at 0.0, and the distortion scale should be 1.0 or else!
 122.916 +        // Only use for poly4 numbers - CR has an implicit scale.
 122.917 +        float SampleRadius[3];
 122.918 +        // Where the distortion has actually been measured/calibrated out to.
 122.919 +        // Don't try to hallucinate data out beyond here.
 122.920 +        float MaxRadius;
 122.921 +        // The config itself.
 122.922 +        LensConfig Config;
 122.923 +    };
 122.924 +
 122.925 +	static const int MaxDistortions = 10;
 122.926 +	DistortionDescriptor distortions[MaxDistortions];
 122.927 +	for (int i = 0; i < MaxDistortions; i++)
 122.928 +    {
 122.929 +        distortions[i].EyeRelief = 0.0f;
 122.930 +        memset(distortions[i].SampleRadius, 0, sizeof(distortions[i].SampleRadius));
 122.931 +        distortions[i].MaxRadius = 1.0f;
 122.932 +        distortions[i].Config.SetToIdentity(); // Note: This line causes a false Microsoft static analysis error -cat
 122.933 +    }
 122.934 +    int numDistortions = 0;
 122.935 +    int defaultDistortion = 0;     // index of the default distortion curve to use if zero eye relief supplied
 122.936 +
 122.937 +    if ( ( hmd.EyeCups == EyeCup_DK1A ) ||
 122.938 +         ( hmd.EyeCups == EyeCup_DK1B ) ||
 122.939 +         ( hmd.EyeCups == EyeCup_DK1C ) )
 122.940 +    {
 122.941 +
 122.942 +        numDistortions = 0;
 122.943 +                
 122.944 +        // Tuned at minimum dial setting - extended to r^2 == 1.8
 122.945 +        distortions[numDistortions].Config.Eqn = Distortion_CatmullRom10;
 122.946 +        distortions[numDistortions].EyeRelief                            = 0.012760465f - 0.005f;
 122.947 +        distortions[numDistortions].Config.MetersPerTanAngleAtCenter     = 0.0425f;
 122.948 +        distortions[numDistortions].Config.K[0]                          = 1.0000f;
 122.949 +        distortions[numDistortions].Config.K[1]                          = 1.06505f;
 122.950 +        distortions[numDistortions].Config.K[2]                          = 1.14725f;
 122.951 +        distortions[numDistortions].Config.K[3]                          = 1.2705f;
 122.952 +        distortions[numDistortions].Config.K[4]                          = 1.48f;
 122.953 +        distortions[numDistortions].Config.K[5]                          = 1.87f;
 122.954 +        distortions[numDistortions].Config.K[6]                          = 2.534f;
 122.955 +        distortions[numDistortions].Config.K[7]                          = 3.6f;
 122.956 +        distortions[numDistortions].Config.K[8]                          = 5.1f;
 122.957 +        distortions[numDistortions].Config.K[9]                          = 7.4f;
 122.958 +        distortions[numDistortions].Config.K[10]                         = 11.0f;
 122.959 +        distortions[numDistortions].MaxRadius                            = sqrt(1.8f);
 122.960 +        defaultDistortion = numDistortions;                      // this is the default
 122.961 +        numDistortions++;
 122.962 +        
 122.963 +        // Tuned at middle dial setting
 122.964 +        distortions[numDistortions].Config.Eqn = Distortion_CatmullRom10;
 122.965 +        distortions[numDistortions].EyeRelief                            = 0.012760465f;  // my average eye-relief
 122.966 +        distortions[numDistortions].Config.MetersPerTanAngleAtCenter     = 0.0425f;
 122.967 +        distortions[numDistortions].Config.K[0]                          = 1.0f;
 122.968 +        distortions[numDistortions].Config.K[1]                          = 1.032407264f;
 122.969 +        distortions[numDistortions].Config.K[2]                          = 1.07160462f;
 122.970 +        distortions[numDistortions].Config.K[3]                          = 1.11998388f;
 122.971 +        distortions[numDistortions].Config.K[4]                          = 1.1808606f;
 122.972 +        distortions[numDistortions].Config.K[5]                          = 1.2590494f;
 122.973 +        distortions[numDistortions].Config.K[6]                          = 1.361915f;
 122.974 +        distortions[numDistortions].Config.K[7]                          = 1.5014339f;
 122.975 +        distortions[numDistortions].Config.K[8]                          = 1.6986004f;
 122.976 +        distortions[numDistortions].Config.K[9]                          = 1.9940577f;
 122.977 +        distortions[numDistortions].Config.K[10]                         = 2.4783147f;
 122.978 +        distortions[numDistortions].MaxRadius                            = 1.0f;
 122.979 +        numDistortions++;
 122.980 +
 122.981 +        // Tuned at maximum dial setting
 122.982 +        distortions[numDistortions].Config.Eqn = Distortion_CatmullRom10;
 122.983 +        distortions[numDistortions].EyeRelief                            = 0.012760465f + 0.005f;
 122.984 +        distortions[numDistortions].Config.MetersPerTanAngleAtCenter     = 0.0425f;
 122.985 +        distortions[numDistortions].Config.K[0]                          = 1.0102f;
 122.986 +        distortions[numDistortions].Config.K[1]                          = 1.0371f;
 122.987 +        distortions[numDistortions].Config.K[2]                          = 1.0831f;
 122.988 +        distortions[numDistortions].Config.K[3]                          = 1.1353f;
 122.989 +        distortions[numDistortions].Config.K[4]                          = 1.2f;
 122.990 +        distortions[numDistortions].Config.K[5]                          = 1.2851f;
 122.991 +        distortions[numDistortions].Config.K[6]                          = 1.3979f;
 122.992 +        distortions[numDistortions].Config.K[7]                          = 1.56f;
 122.993 +        distortions[numDistortions].Config.K[8]                          = 1.8f;
 122.994 +        distortions[numDistortions].Config.K[9]                          = 2.25f;
 122.995 +        distortions[numDistortions].Config.K[10]                         = 3.0f;
 122.996 +        distortions[numDistortions].MaxRadius                            = 1.0f;
 122.997 +        numDistortions++;
 122.998 +        
 122.999 +
122.1000 +        
122.1001 +        // Chromatic aberration doesn't seem to change with eye relief.
122.1002 +        for ( int i = 0; i < numDistortions; i++ )
122.1003 +        {
122.1004 +            distortions[i].Config.ChromaticAberration[0]        = -0.006f;
122.1005 +            distortions[i].Config.ChromaticAberration[1]        =  0.0f;
122.1006 +            distortions[i].Config.ChromaticAberration[2]        =  0.014f;
122.1007 +            distortions[i].Config.ChromaticAberration[3]        =  0.0f;
122.1008 +        }
122.1009 +    }
122.1010 +    else if ( hmd.EyeCups == EyeCup_DKHD2A )
122.1011 +    {
122.1012 +        // Tuned DKHD2 lens
122.1013 +        numDistortions = 0;
122.1014 +       
122.1015 +        distortions[numDistortions].Config.Eqn = Distortion_CatmullRom10;
122.1016 +        distortions[numDistortions].EyeRelief                            = 0.010f;
122.1017 +        distortions[numDistortions].Config.MetersPerTanAngleAtCenter     = 0.0425f;
122.1018 +        distortions[numDistortions].Config.K[0]                          = 1.0f;
122.1019 +        distortions[numDistortions].Config.K[1]                          = 1.0425f;
122.1020 +        distortions[numDistortions].Config.K[2]                          = 1.0826f;
122.1021 +        distortions[numDistortions].Config.K[3]                          = 1.130f;
122.1022 +        distortions[numDistortions].Config.K[4]                          = 1.185f;
122.1023 +        distortions[numDistortions].Config.K[5]                          = 1.250f;
122.1024 +        distortions[numDistortions].Config.K[6]                          = 1.338f;
122.1025 +        distortions[numDistortions].Config.K[7]                          = 1.455f;
122.1026 +        distortions[numDistortions].Config.K[8]                          = 1.620f;
122.1027 +        distortions[numDistortions].Config.K[9]                          = 1.840f;
122.1028 +        distortions[numDistortions].Config.K[10]                         = 2.200f;
122.1029 +        distortions[numDistortions].MaxRadius                            = 1.0f;
122.1030 +        
122.1031 +        defaultDistortion = numDistortions;   // this is the default
122.1032 +        numDistortions++;
122.1033 +
122.1034 +        distortions[numDistortions] = distortions[0];
122.1035 +        distortions[numDistortions].EyeRelief = 0.020f;
122.1036 +        numDistortions++;
122.1037 +
122.1038 +        // Chromatic aberration doesn't seem to change with eye relief.
122.1039 +        for ( int i = 0; i < numDistortions; i++ )
122.1040 +        {
122.1041 +            distortions[i].Config.ChromaticAberration[0]        = -0.006f;
122.1042 +            distortions[i].Config.ChromaticAberration[1]        =  0.0f;
122.1043 +            distortions[i].Config.ChromaticAberration[2]        =  0.014f;
122.1044 +            distortions[i].Config.ChromaticAberration[3]        =  0.0f;
122.1045 +        }
122.1046 +    }
122.1047 +    else if ( hmd.EyeCups == EyeCup_PinkA || hmd.EyeCups == EyeCup_DK2A )
122.1048 +    {
122.1049 +        // Tuned Crystal Cove & DK2 Lens (CES & GDC)
122.1050 +        numDistortions = 0;
122.1051 +       
122.1052 +        
122.1053 +        distortions[numDistortions].EyeRelief                            = 0.008f;
122.1054 +        distortions[numDistortions].Config.MetersPerTanAngleAtCenter     = 0.036f;
122.1055 +        // TODO: Need to retune this distortion for minimum eye relief
122.1056 +        distortions[numDistortions].Config.Eqn = Distortion_CatmullRom10;
122.1057 +        distortions[numDistortions].Config.K[0]                          = 1.003f;
122.1058 +        distortions[numDistortions].Config.K[1]                          = 1.02f;
122.1059 +        distortions[numDistortions].Config.K[2]                          = 1.042f;
122.1060 +        distortions[numDistortions].Config.K[3]                          = 1.066f;
122.1061 +        distortions[numDistortions].Config.K[4]                          = 1.094f;
122.1062 +        distortions[numDistortions].Config.K[5]                          = 1.126f;
122.1063 +        distortions[numDistortions].Config.K[6]                          = 1.162f;
122.1064 +        distortions[numDistortions].Config.K[7]                          = 1.203f;
122.1065 +        distortions[numDistortions].Config.K[8]                          = 1.25f;
122.1066 +        distortions[numDistortions].Config.K[9]                          = 1.31f;
122.1067 +        distortions[numDistortions].Config.K[10]                         = 1.38f;
122.1068 +        distortions[numDistortions].MaxRadius                            = 1.0f;
122.1069 +        
122.1070 +        distortions[numDistortions].Config.ChromaticAberration[0]        = -0.0112f;
122.1071 +        distortions[numDistortions].Config.ChromaticAberration[1]        = -0.015f;
122.1072 +        distortions[numDistortions].Config.ChromaticAberration[2]        =  0.0187f;
122.1073 +        distortions[numDistortions].Config.ChromaticAberration[3]        =  0.015f;
122.1074 +        
122.1075 +        numDistortions++;
122.1076 +
122.1077 +
122.1078 +
122.1079 +
122.1080 +
122.1081 +        distortions[numDistortions].EyeRelief                            = 0.018f;
122.1082 +        distortions[numDistortions].Config.MetersPerTanAngleAtCenter     = 0.036f;
122.1083 +
122.1084 +        distortions[numDistortions].Config.Eqn = Distortion_CatmullRom10;
122.1085 +        distortions[numDistortions].Config.K[0]                          = 1.003f;
122.1086 +        distortions[numDistortions].Config.K[1]                          = 1.02f;
122.1087 +        distortions[numDistortions].Config.K[2]                          = 1.042f;
122.1088 +        distortions[numDistortions].Config.K[3]                          = 1.066f;
122.1089 +        distortions[numDistortions].Config.K[4]                          = 1.094f;
122.1090 +        distortions[numDistortions].Config.K[5]                          = 1.126f;
122.1091 +        distortions[numDistortions].Config.K[6]                          = 1.162f;
122.1092 +        distortions[numDistortions].Config.K[7]                          = 1.203f;
122.1093 +        distortions[numDistortions].Config.K[8]                          = 1.25f;
122.1094 +        distortions[numDistortions].Config.K[9]                          = 1.31f;
122.1095 +        distortions[numDistortions].Config.K[10]                         = 1.38f;
122.1096 +        distortions[numDistortions].MaxRadius                            = 1.0f;
122.1097 +
122.1098 +        distortions[numDistortions].Config.ChromaticAberration[0]        = -0.015f;
122.1099 +        distortions[numDistortions].Config.ChromaticAberration[1]        = -0.02f;
122.1100 +        distortions[numDistortions].Config.ChromaticAberration[2]        =  0.025f;
122.1101 +        distortions[numDistortions].Config.ChromaticAberration[3]        =  0.02f;
122.1102 +        
122.1103 +        defaultDistortion = numDistortions;   // this is the default
122.1104 +        numDistortions++;
122.1105 +        
122.1106 +        /*
122.1107 +        // Orange Lens on DK2
122.1108 +        distortions[numDistortions].EyeRelief                            = 0.010f;
122.1109 +        distortions[numDistortions].Config.MetersPerTanAngleAtCenter     = 0.031f;
122.1110 +
122.1111 +        distortions[numDistortions].Config.Eqn = Distortion_CatmullRom10;
122.1112 +        distortions[numDistortions].Config.K[0]                          = 1.00f;
122.1113 +        distortions[numDistortions].Config.K[1]                          = 1.0169f;
122.1114 +        distortions[numDistortions].Config.K[2]                          = 1.0378f;
122.1115 +        distortions[numDistortions].Config.K[3]                          = 1.0648f;
122.1116 +        distortions[numDistortions].Config.K[4]                          = 1.0990f;
122.1117 +        distortions[numDistortions].Config.K[5]                          = 1.141f;
122.1118 +        distortions[numDistortions].Config.K[6]                          = 1.192f;
122.1119 +        distortions[numDistortions].Config.K[7]                          = 1.255f;
122.1120 +        distortions[numDistortions].Config.K[8]                          = 1.335f;
122.1121 +        distortions[numDistortions].Config.K[9]                          = 1.435f;
122.1122 +        distortions[numDistortions].Config.K[10]                         = 1.56f;
122.1123 +        distortions[numDistortions].MaxRadius                            = 1.0f;
122.1124 +        */
122.1125 +    }
122.1126 +    else
122.1127 +    {
122.1128 +        // Unknown lens.
122.1129 +        // Use DK1 black lens settings, just so we can continue to run with something.
122.1130 +        distortions[0].EyeRelief = 0.005f;
122.1131 +        distortions[0].Config.MetersPerTanAngleAtCenter = 0.043875f;
122.1132 +        distortions[0].Config.Eqn = Distortion_RecipPoly4;
122.1133 +        distortions[0].Config.K[0] = 1.0f;
122.1134 +        distortions[0].Config.K[1] = -0.3999f;
122.1135 +        distortions[0].Config.K[2] =  0.2408f;
122.1136 +        distortions[0].Config.K[3] = -0.4589f;
122.1137 +        distortions[0].SampleRadius[0] = 0.2f;
122.1138 +        distortions[0].SampleRadius[1] = 0.4f;
122.1139 +        distortions[0].SampleRadius[2] = 0.6f;
122.1140 +
122.1141 +        distortions[1] = distortions[0];
122.1142 +        distortions[1].EyeRelief = 0.010f;
122.1143 +        numDistortions = 2;
122.1144 +
122.1145 +        // Chromatic aberration doesn't seem to change with eye relief.
122.1146 +        for ( int i = 0; i < numDistortions; i++ )
122.1147 +        {
122.1148 +            // These are placeholder, they have not been tuned!
122.1149 +            distortions[i].Config.ChromaticAberration[0]        =  0.0f;
122.1150 +            distortions[i].Config.ChromaticAberration[1]        =  0.0f;
122.1151 +            distortions[i].Config.ChromaticAberration[2]        =  0.0f;
122.1152 +            distortions[i].Config.ChromaticAberration[3]        =  0.0f;
122.1153 +        }
122.1154 +    }
122.1155 +
122.1156 +	OVR_ASSERT(numDistortions < MaxDistortions);
122.1157 +
122.1158 +    DistortionDescriptor *pUpper = NULL;
122.1159 +    DistortionDescriptor *pLower = NULL;
122.1160 +    float lerpVal = 0.0f;
122.1161 +    if (eyeReliefInMeters == 0)
122.1162 +    {   // Use a constant default distortion if an invalid eye-relief is supplied
122.1163 +        pLower = &(distortions[defaultDistortion]);
122.1164 +        pUpper = &(distortions[defaultDistortion]);
122.1165 +        lerpVal = 0.0f;
122.1166 +    }
122.1167 +    else
122.1168 +    {
122.1169 +        for ( int i = 0; i < numDistortions-1; i++ )
122.1170 +        {
122.1171 +            OVR_ASSERT ( distortions[i].EyeRelief < distortions[i+1].EyeRelief );
122.1172 +            if ( ( distortions[i].EyeRelief <= eyeReliefInMeters ) && ( distortions[i+1].EyeRelief > eyeReliefInMeters ) )
122.1173 +            {
122.1174 +                pLower = &(distortions[i]);
122.1175 +                pUpper = &(distortions[i+1]);
122.1176 +                lerpVal = ( eyeReliefInMeters - pLower->EyeRelief ) / ( pUpper->EyeRelief - pLower->EyeRelief );
122.1177 +                // No break here - I want the ASSERT to check everything every time!
122.1178 +            }
122.1179 +        }
122.1180 +    }
122.1181 +
122.1182 +    if ( pUpper == NULL )
122.1183 +    {
122.1184 +#if 0
122.1185 +        // Outside the range, so extrapolate rather than interpolate.
122.1186 +        if ( distortions[0].EyeRelief > eyeReliefInMeters )
122.1187 +        { 
122.1188 +            pLower = &(distortions[0]);
122.1189 +            pUpper = &(distortions[1]);
122.1190 +        }
122.1191 +        else
122.1192 +        {
122.1193 +            OVR_ASSERT ( distortions[numDistortions-1].EyeRelief <= eyeReliefInMeters );
122.1194 +            pLower = &(distortions[numDistortions-2]);
122.1195 +            pUpper = &(distortions[numDistortions-1]);
122.1196 +        }
122.1197 +        lerpVal = ( eyeReliefInMeters - pLower->EyeRelief ) / ( pUpper->EyeRelief - pLower->EyeRelief );
122.1198 +#else
122.1199 +        // Do not extrapolate, just clamp - slightly worried about people putting in bogus settings.
122.1200 +        if ( distortions[0].EyeRelief > eyeReliefInMeters )
122.1201 +        {
122.1202 +            pLower = &(distortions[0]);
122.1203 +            pUpper = &(distortions[0]);
122.1204 +        }
122.1205 +        else
122.1206 +        {
122.1207 +            OVR_ASSERT ( distortions[numDistortions-1].EyeRelief <= eyeReliefInMeters );
122.1208 +            pLower = &(distortions[numDistortions-1]);
122.1209 +            pUpper = &(distortions[numDistortions-1]);
122.1210 +        }
122.1211 +        lerpVal = 0.0f;
122.1212 +#endif
122.1213 +    }
122.1214 +    float invLerpVal = 1.0f - lerpVal;
122.1215 +
122.1216 +    pLower->Config.MaxR = pLower->MaxRadius;
122.1217 +    pUpper->Config.MaxR = pUpper->MaxRadius;
122.1218 +
122.1219 +    LensConfig result;
122.1220 +    // Where is the edge of the lens - no point modelling further than this.
122.1221 +    float maxValidRadius = invLerpVal * pLower->MaxRadius + lerpVal * pUpper->MaxRadius;
122.1222 +    result.MaxR = maxValidRadius;
122.1223 +
122.1224 +    switch ( distortionType )
122.1225 +    {
122.1226 +    case Distortion_Poly4:
122.1227 +        // Deprecated
122.1228 +        OVR_ASSERT ( false );
122.1229 +        break;
122.1230 +    case Distortion_RecipPoly4:{
122.1231 +        // Lerp control points and fit an equation to them.
122.1232 +        float fitX[4];
122.1233 +        float fitY[4];
122.1234 +        fitX[0] = 0.0f;
122.1235 +        fitY[0] = 1.0f;
122.1236 +        for ( int ctrlPt = 1; ctrlPt < 4; ctrlPt ++ )
122.1237 +        {
122.1238 +            // SampleRadius is not valid for Distortion_RecipPoly4 types.
122.1239 +            float radiusLerp = ( invLerpVal * pLower->MaxRadius + lerpVal * pUpper->MaxRadius ) * ( (float)ctrlPt / 4.0f );
122.1240 +            float radiusLerpSq = radiusLerp * radiusLerp;
122.1241 +            float fitYLower = pLower->Config.DistortionFnScaleRadiusSquared ( radiusLerpSq );
122.1242 +            float fitYUpper = pUpper->Config.DistortionFnScaleRadiusSquared ( radiusLerpSq );
122.1243 +            fitX[ctrlPt] = radiusLerpSq;
122.1244 +            fitY[ctrlPt] = 1.0f / ( invLerpVal * fitYLower + lerpVal * fitYUpper );
122.1245 +        }
122.1246 +
122.1247 +        result.Eqn = Distortion_RecipPoly4;
122.1248 +        bool bSuccess = FitCubicPolynomial ( result.K, fitX, fitY );
122.1249 +        OVR_ASSERT ( bSuccess );
122.1250 +        OVR_UNUSED ( bSuccess );
122.1251 +
122.1252 +        // Set up the fast inverse.
122.1253 +        float maxRDist = result.DistortionFn ( maxValidRadius );
122.1254 +        result.MaxInvR = maxRDist;
122.1255 +        result.SetUpInverseApprox();
122.1256 +
122.1257 +        }break;
122.1258 +
122.1259 +    case Distortion_CatmullRom10:{
122.1260 +
122.1261 +        // Evenly sample & lerp points on the curve.
122.1262 +        const int NumSegments = LensConfig::NumCoefficients;
122.1263 +        result.MaxR = maxValidRadius;
122.1264 +        // Directly interpolate the K0 values
122.1265 +        result.K[0] = invLerpVal * pLower->Config.K[0] + lerpVal * pUpper->Config.K[0];
122.1266 +
122.1267 +        // Sample and interpolate the distortion curves to derive K[1] ... K[n]
122.1268 +        for ( int ctrlPt = 1; ctrlPt < NumSegments; ctrlPt++ )
122.1269 +        {
122.1270 +            float radiusSq = ( (float)ctrlPt / (float)(NumSegments-1) ) * maxValidRadius * maxValidRadius;
122.1271 +            float fitYLower = pLower->Config.DistortionFnScaleRadiusSquared ( radiusSq );
122.1272 +            float fitYUpper = pUpper->Config.DistortionFnScaleRadiusSquared ( radiusSq );
122.1273 +            float fitLerp = invLerpVal * fitYLower + lerpVal * fitYUpper;
122.1274 +            result.K[ctrlPt] = fitLerp;
122.1275 +        }
122.1276 +
122.1277 +        result.Eqn = Distortion_CatmullRom10;
122.1278 +
122.1279 +        for ( int ctrlPt = 1; ctrlPt < NumSegments; ctrlPt++ )
122.1280 +        {
122.1281 +            float radiusSq = ( (float)ctrlPt / (float)(NumSegments-1) ) * maxValidRadius * maxValidRadius;
122.1282 +            float val = result.DistortionFnScaleRadiusSquared ( radiusSq );            
122.1283 +            OVR_ASSERT ( Alg::Abs ( val - result.K[ctrlPt] ) < 0.0001f );
122.1284 +            OVR_UNUSED1(val); // For release build.
122.1285 +        }
122.1286 +
122.1287 +        // Set up the fast inverse.
122.1288 +        float maxRDist = result.DistortionFn ( maxValidRadius );
122.1289 +        result.MaxInvR = maxRDist;
122.1290 +        result.SetUpInverseApprox();
122.1291 +
122.1292 +        }break;
122.1293 +
122.1294 +    default: OVR_ASSERT ( false ); break;
122.1295 +    }
122.1296 +
122.1297 +
122.1298 +    // Chromatic aberration.
122.1299 +    result.ChromaticAberration[0] = invLerpVal * pLower->Config.ChromaticAberration[0] + lerpVal * pUpper->Config.ChromaticAberration[0];
122.1300 +    result.ChromaticAberration[1] = invLerpVal * pLower->Config.ChromaticAberration[1] + lerpVal * pUpper->Config.ChromaticAberration[1];
122.1301 +    result.ChromaticAberration[2] = invLerpVal * pLower->Config.ChromaticAberration[2] + lerpVal * pUpper->Config.ChromaticAberration[2];
122.1302 +    result.ChromaticAberration[3] = invLerpVal * pLower->Config.ChromaticAberration[3] + lerpVal * pUpper->Config.ChromaticAberration[3];
122.1303 +
122.1304 +    // Scale.
122.1305 +    result.MetersPerTanAngleAtCenter =  pLower->Config.MetersPerTanAngleAtCenter * invLerpVal +
122.1306 +                                        pUpper->Config.MetersPerTanAngleAtCenter * lerpVal;
122.1307 +    /*
122.1308 +    // Commented out - Causes ASSERT with no HMD plugged in
122.1309 +#ifdef OVR_BUILD_DEBUG
122.1310 +    if ( distortionType == Distortion_CatmullRom10 )
122.1311 +    {
122.1312 +        TestSaveLoadLensConfig ( result );
122.1313 +    }
122.1314 +#endif
122.1315 +    */
122.1316 +    return result;
122.1317 +}
122.1318 +
122.1319 +
122.1320 +DistortionRenderDesc CalculateDistortionRenderDesc ( StereoEye eyeType, HmdRenderInfo const &hmd,
122.1321 +                                                     const LensConfig *pLensOverride /*= NULL */ )
122.1322 +{
122.1323 +    // From eye relief, IPD and device characteristics, we get the distortion mapping.
122.1324 +    // This distortion does the following things:
122.1325 +    // 1. It undoes the distortion that happens at the edges of the lens.
122.1326 +    // 2. It maps the undistorted field into "retina" space.
122.1327 +    // So the input is a pixel coordinate - the physical pixel on the display itself.
122.1328 +    // The output is the real-world direction of the ray from this pixel as it comes out of the lens and hits the eye.
122.1329 +    // However we typically think of rays "coming from" the eye, so the direction (TanAngleX,TanAngleY,1) is the direction
122.1330 +    //      that the pixel appears to be in real-world space, where AngleX and AngleY are relative to the straight-ahead vector.
122.1331 +    // If your renderer is a raytracer, you can use this vector directly (normalize as appropriate).
122.1332 +    // However in standard rasterisers, we have rendered a 2D image and are putting it in front of the eye,
122.1333 +    //      so we then need a mapping from this space to the [-1,1] UV coordinate space, which depends on exactly
122.1334 +    //      where "in space" the app wants to put that rendertarget.
122.1335 +    //      Where in space, and how large this rendertarget is, is completely up to the app and/or user,
122.1336 +    //      though of course we can provide some useful hints.
122.1337 +
122.1338 +    // TODO: Use IPD and eye relief to modify distortion (i.e. non-radial component)
122.1339 +    // TODO: cope with lenses that don't produce collimated light.
122.1340 +    //       This means that IPD relative to the lens separation changes the light vergence,
122.1341 +    //       and so we actually need to change where the image is displayed.
122.1342 +
122.1343 +    const HmdRenderInfo::EyeConfig &hmdEyeConfig = ( eyeType == StereoEye_Left ) ? hmd.EyeLeft : hmd.EyeRight;
122.1344 +
122.1345 +    DistortionRenderDesc localDistortion;
122.1346 +    localDistortion.Lens = hmdEyeConfig.Distortion;
122.1347 +
122.1348 +    if ( pLensOverride != NULL )
122.1349 +    {
122.1350 +        localDistortion.Lens = *pLensOverride;
122.1351 +    }
122.1352 +
122.1353 +    Sizef pixelsPerMeter(hmd.ResolutionInPixels.w / ( hmd.ScreenSizeInMeters.w - hmd.ScreenGapSizeInMeters ),
122.1354 +                         hmd.ResolutionInPixels.h / hmd.ScreenSizeInMeters.h);
122.1355 +
122.1356 +    localDistortion.PixelsPerTanAngleAtCenter = (pixelsPerMeter * localDistortion.Lens.MetersPerTanAngleAtCenter).ToVector();
122.1357 +    // Same thing, scaled to [-1,1] for each eye, rather than pixels.
122.1358 +
122.1359 +    localDistortion.TanEyeAngleScale = Vector2f(0.25f, 0.5f).EntrywiseMultiply(
122.1360 +                                       (hmd.ScreenSizeInMeters / localDistortion.Lens.MetersPerTanAngleAtCenter).ToVector());
122.1361 +    
122.1362 +    // <--------------left eye------------------><-ScreenGapSizeInMeters-><--------------right eye----------------->
122.1363 +    // <------------------------------------------ScreenSizeInMeters.Width----------------------------------------->
122.1364 +    //                            <----------------LensSeparationInMeters--------------->
122.1365 +    // <--centerFromLeftInMeters->
122.1366 +    //                            ^
122.1367 +    //                      Center of lens
122.1368 +
122.1369 +    // Find the lens centers in scale of [-1,+1] (NDC) in left eye.
122.1370 +    float visibleWidthOfOneEye = 0.5f * ( hmd.ScreenSizeInMeters.w - hmd.ScreenGapSizeInMeters );
122.1371 +    float centerFromLeftInMeters = ( hmd.ScreenSizeInMeters.w - hmd.LensSeparationInMeters ) * 0.5f;
122.1372 +    localDistortion.LensCenter.x = (     centerFromLeftInMeters / visibleWidthOfOneEye          ) * 2.0f - 1.0f;
122.1373 +    localDistortion.LensCenter.y = ( hmd.CenterFromTopInMeters  / hmd.ScreenSizeInMeters.h ) * 2.0f - 1.0f;
122.1374 +    if ( eyeType == StereoEye_Right )
122.1375 +    {
122.1376 +        localDistortion.LensCenter.x = -localDistortion.LensCenter.x;
122.1377 +    }
122.1378 +
122.1379 +    return localDistortion;
122.1380 +}
122.1381 +
122.1382 +FovPort CalculateFovFromEyePosition ( float eyeReliefInMeters,
122.1383 +                                      float offsetToRightInMeters,
122.1384 +                                      float offsetDownwardsInMeters,
122.1385 +                                      float lensDiameterInMeters,
122.1386 +                                      float extraEyeRotationInRadians /*= 0.0f*/ )
122.1387 +{
122.1388 +    // 2D view of things:
122.1389 +    //       |-|            <--- offsetToRightInMeters (in this case, it is negative)
122.1390 +    // |=======C=======|    <--- lens surface (C=center)
122.1391 +    //  \    |       _/
122.1392 +    //   \   R     _/
122.1393 +    //    \  |   _/
122.1394 +    //     \ | _/
122.1395 +    //      \|/
122.1396 +    //       O  <--- center of pupil
122.1397 +
122.1398 +    // (technically the lens is round rather than square, so it's not correct to
122.1399 +    // separate vertical and horizontal like this, but it's close enough)
122.1400 +    float halfLensDiameter = lensDiameterInMeters * 0.5f;
122.1401 +    FovPort fovPort;
122.1402 +    fovPort.UpTan    = ( halfLensDiameter + offsetDownwardsInMeters ) / eyeReliefInMeters;
122.1403 +    fovPort.DownTan  = ( halfLensDiameter - offsetDownwardsInMeters ) / eyeReliefInMeters;
122.1404 +    fovPort.LeftTan  = ( halfLensDiameter + offsetToRightInMeters   ) / eyeReliefInMeters;
122.1405 +    fovPort.RightTan = ( halfLensDiameter - offsetToRightInMeters   ) / eyeReliefInMeters;
122.1406 +
122.1407 +    if ( extraEyeRotationInRadians > 0.0f )
122.1408 +    {
122.1409 +        // That's the basic looking-straight-ahead eye position relative to the lens.
122.1410 +        // But if you look left, the pupil moves left as the eyeball rotates, which
122.1411 +        // means you can see more to the right than this geometry suggests.
122.1412 +        // So add in the bounds for the extra movement of the pupil.
122.1413 +
122.1414 +        // Beyond 30 degrees does not increase FOV because the pupil starts moving backwards more than sideways.
122.1415 +        extraEyeRotationInRadians = Alg::Min ( DegreeToRad ( 30.0f ), Alg::Max ( 0.0f, extraEyeRotationInRadians ) );
122.1416 +        
122.1417 +        // The rotation of the eye is a bit more complex than a simple circle.  The center of rotation
122.1418 +        // at 13.5mm from cornea is slightly further back than the actual center of the eye.
122.1419 +        // Additionally the rotation contains a small lateral component as the muscles pull the eye
122.1420 +        const float eyeballCenterToPupil = 0.0135f;  // center of eye rotation
122.1421 +        const float eyeballLateralPull = 0.001f * (extraEyeRotationInRadians / DegreeToRad ( 30.0f));  // lateral motion as linear function 
122.1422 +        float extraTranslation = eyeballCenterToPupil * sinf ( extraEyeRotationInRadians ) + eyeballLateralPull;
122.1423 +        float extraRelief = eyeballCenterToPupil * ( 1.0f - cosf ( extraEyeRotationInRadians ) );
122.1424 +
122.1425 +        fovPort.UpTan    = Alg::Max ( fovPort.UpTan   , ( halfLensDiameter + offsetDownwardsInMeters + extraTranslation ) / ( eyeReliefInMeters + extraRelief ) );
122.1426 +        fovPort.DownTan  = Alg::Max ( fovPort.DownTan , ( halfLensDiameter - offsetDownwardsInMeters + extraTranslation ) / ( eyeReliefInMeters + extraRelief ) );
122.1427 +        fovPort.LeftTan  = Alg::Max ( fovPort.LeftTan , ( halfLensDiameter + offsetToRightInMeters   + extraTranslation ) / ( eyeReliefInMeters + extraRelief ) );
122.1428 +        fovPort.RightTan = Alg::Max ( fovPort.RightTan, ( halfLensDiameter - offsetToRightInMeters   + extraTranslation ) / ( eyeReliefInMeters + extraRelief ) );
122.1429 +    }
122.1430 +
122.1431 +    return fovPort;
122.1432 +}
122.1433 +
122.1434 +
122.1435 +
122.1436 +FovPort CalculateFovFromHmdInfo ( StereoEye eyeType,
122.1437 +                                  DistortionRenderDesc const &distortion,
122.1438 +                                  HmdRenderInfo const &hmd,
122.1439 +                                  float extraEyeRotationInRadians /*= 0.0f*/ )
122.1440 +{
122.1441 +    FovPort fovPort;
122.1442 +    float eyeReliefInMeters;
122.1443 +    float offsetToRightInMeters;
122.1444 +    if ( eyeType == StereoEye_Right )
122.1445 +    {
122.1446 +        eyeReliefInMeters     = hmd.EyeRight.ReliefInMeters;
122.1447 +        offsetToRightInMeters = hmd.EyeRight.NoseToPupilInMeters - 0.5f * hmd.LensSeparationInMeters;
122.1448 +    }
122.1449 +    else
122.1450 +    {
122.1451 +        eyeReliefInMeters     = hmd.EyeLeft.ReliefInMeters;
122.1452 +        offsetToRightInMeters = -(hmd.EyeLeft.NoseToPupilInMeters - 0.5f * hmd.LensSeparationInMeters);
122.1453 +    }
122.1454 +
122.1455 +    // Limit the eye-relief to 6 mm for FOV calculations since this just tends to spread off-screen
122.1456 +    // and get clamped anyways on DK1 (but in Unity it continues to spreads and causes 
122.1457 +    // unnecessarily large render targets)
122.1458 +    eyeReliefInMeters = Alg::Max(eyeReliefInMeters, 0.006f);
122.1459 +
122.1460 +    // Central view.
122.1461 +    fovPort = CalculateFovFromEyePosition ( eyeReliefInMeters,
122.1462 +                                            offsetToRightInMeters,
122.1463 +                                            0.0f,
122.1464 +                                            hmd.LensDiameterInMeters,
122.1465 +                                            extraEyeRotationInRadians );
122.1466 +
122.1467 +    // clamp to the screen
122.1468 +    fovPort = ClampToPhysicalScreenFov ( eyeType, distortion, fovPort );
122.1469 +       
122.1470 +    return fovPort;
122.1471 +}
122.1472 +
122.1473 +
122.1474 +
122.1475 +FovPort GetPhysicalScreenFov ( StereoEye eyeType, DistortionRenderDesc const &distortion )
122.1476 +{
122.1477 +    OVR_UNUSED1 ( eyeType );
122.1478 +
122.1479 +    FovPort resultFovPort;
122.1480 +
122.1481 +    // Figure out the boundaries of the screen. We take the middle pixel of the screen,
122.1482 +    // move to each of the four screen edges, and transform those back into TanAngle space.
122.1483 +    Vector2f dmiddle = distortion.LensCenter;
122.1484 +
122.1485 +    // The gotcha is that for some distortion functions, the map will "wrap around"
122.1486 +    // for screen pixels that are not actually visible to the user (especially on DK1,
122.1487 +    // which has a lot of invisible pixels), and map to pixels that are close to the middle.
122.1488 +    // This means the edges of the screen will actually be
122.1489 +    // "closer" than the visible bounds, so we'll clip too aggressively.
122.1490 +
122.1491 +    // Solution - step gradually towards the boundary, noting the maximum distance.
122.1492 +    struct FunctionHider
122.1493 +    {
122.1494 +        static FovPort FindRange ( Vector2f from, Vector2f to, int numSteps,
122.1495 +                                          DistortionRenderDesc const &distortionL )
122.1496 +        {
122.1497 +            FovPort result;
122.1498 +            result.UpTan    = 0.0f;
122.1499 +            result.DownTan  = 0.0f;
122.1500 +            result.LeftTan  = 0.0f;
122.1501 +            result.RightTan = 0.0f;
122.1502 +
122.1503 +            float stepScale = 1.0f / ( numSteps - 1 );
122.1504 +            for ( int step = 0; step < numSteps; step++ )
122.1505 +            {
122.1506 +                float    lerpFactor  = stepScale * (float)step;
122.1507 +                Vector2f sample      = from + (to - from) * lerpFactor;
122.1508 +                Vector2f tanEyeAngle = TransformScreenNDCToTanFovSpace ( distortionL, sample );
122.1509 +
122.1510 +                result.LeftTan  = Alg::Max ( result.LeftTan,  -tanEyeAngle.x );
122.1511 +                result.RightTan = Alg::Max ( result.RightTan,  tanEyeAngle.x );
122.1512 +                result.UpTan    = Alg::Max ( result.UpTan,    -tanEyeAngle.y );
122.1513 +                result.DownTan  = Alg::Max ( result.DownTan,   tanEyeAngle.y );
122.1514 +            }
122.1515 +            return result;
122.1516 +        }
122.1517 +    };
122.1518 +
122.1519 +    FovPort leftFovPort  = FunctionHider::FindRange( dmiddle, Vector2f( -1.0f, dmiddle.y ), 10, distortion );
122.1520 +    FovPort rightFovPort = FunctionHider::FindRange( dmiddle, Vector2f( 1.0f, dmiddle.y ),  10, distortion );
122.1521 +    FovPort upFovPort    = FunctionHider::FindRange( dmiddle, Vector2f( dmiddle.x, -1.0f ), 10, distortion );
122.1522 +    FovPort downFovPort  = FunctionHider::FindRange( dmiddle, Vector2f( dmiddle.x, 1.0f ),  10, distortion );
122.1523 +    
122.1524 +    resultFovPort.LeftTan  = leftFovPort.LeftTan;
122.1525 +    resultFovPort.RightTan = rightFovPort.RightTan;
122.1526 +    resultFovPort.UpTan    = upFovPort.UpTan;
122.1527 +    resultFovPort.DownTan  = downFovPort.DownTan;
122.1528 +
122.1529 +    return resultFovPort;
122.1530 +}
122.1531 +
122.1532 +FovPort ClampToPhysicalScreenFov( StereoEye eyeType, DistortionRenderDesc const &distortion,
122.1533 +                                         FovPort inputFovPort )
122.1534 +{
122.1535 +    FovPort resultFovPort;
122.1536 +    FovPort phsyicalFovPort = GetPhysicalScreenFov ( eyeType, distortion );
122.1537 +    resultFovPort.LeftTan  = Alg::Min ( inputFovPort.LeftTan,  phsyicalFovPort.LeftTan );
122.1538 +    resultFovPort.RightTan = Alg::Min ( inputFovPort.RightTan, phsyicalFovPort.RightTan );
122.1539 +    resultFovPort.UpTan    = Alg::Min ( inputFovPort.UpTan,    phsyicalFovPort.UpTan );
122.1540 +    resultFovPort.DownTan  = Alg::Min ( inputFovPort.DownTan,  phsyicalFovPort.DownTan );
122.1541 +
122.1542 +    return resultFovPort;
122.1543 +}
122.1544 +
122.1545 +Sizei CalculateIdealPixelSize ( StereoEye eyeType, DistortionRenderDesc const &distortion,
122.1546 +                                FovPort tanHalfFov, float pixelsPerDisplayPixel )
122.1547 +{
122.1548 +    OVR_UNUSED(eyeType);   // might be useful in the future if we do overlapping fovs
122.1549 +
122.1550 +    Sizei result;    
122.1551 +    // TODO: if the app passes in a FOV that doesn't cover the centre, use the distortion values for the nearest edge/corner to match pixel size.
122.1552 +    result.w  = (int)(0.5f + pixelsPerDisplayPixel * distortion.PixelsPerTanAngleAtCenter.x * ( tanHalfFov.LeftTan + tanHalfFov.RightTan ) );
122.1553 +    result.h = (int)(0.5f + pixelsPerDisplayPixel * distortion.PixelsPerTanAngleAtCenter.y * ( tanHalfFov.UpTan   + tanHalfFov.DownTan  ) );
122.1554 +    return result;
122.1555 +}
122.1556 +
122.1557 +Recti GetFramebufferViewport ( StereoEye eyeType, HmdRenderInfo const &hmd )
122.1558 +{
122.1559 +    Recti result;
122.1560 +    result.w = hmd.ResolutionInPixels.w/2;
122.1561 +    result.h = hmd.ResolutionInPixels.h;
122.1562 +    result.x = 0;
122.1563 +    result.y = 0;
122.1564 +    if ( eyeType == StereoEye_Right )
122.1565 +    {
122.1566 +        result.x = (hmd.ResolutionInPixels.w+1)/2;      // Round up, not down.
122.1567 +    }
122.1568 +    return result;
122.1569 +}
122.1570 +
122.1571 +
122.1572 +ScaleAndOffset2D CreateNDCScaleAndOffsetFromFov ( FovPort tanHalfFov )
122.1573 +{
122.1574 +    float projXScale = 2.0f / ( tanHalfFov.LeftTan + tanHalfFov.RightTan );
122.1575 +    float projXOffset = ( tanHalfFov.LeftTan - tanHalfFov.RightTan ) * projXScale * 0.5f;
122.1576 +    float projYScale = 2.0f / ( tanHalfFov.UpTan + tanHalfFov.DownTan );
122.1577 +    float projYOffset = ( tanHalfFov.UpTan - tanHalfFov.DownTan ) * projYScale * 0.5f;
122.1578 +
122.1579 +    ScaleAndOffset2D result;
122.1580 +    result.Scale    = Vector2f(projXScale, projYScale);
122.1581 +    result.Offset   = Vector2f(projXOffset, projYOffset);
122.1582 +    // Hey - why is that Y.Offset negated?
122.1583 +    // It's because a projection matrix transforms from world coords with Y=up,
122.1584 +    // whereas this is from NDC which is Y=down.
122.1585 +
122.1586 +    return result;
122.1587 +}
122.1588 +
122.1589 +
122.1590 +ScaleAndOffset2D CreateUVScaleAndOffsetfromNDCScaleandOffset ( ScaleAndOffset2D scaleAndOffsetNDC,
122.1591 +                                                               Recti renderedViewport,
122.1592 +                                                               Sizei renderTargetSize )
122.1593 +{
122.1594 +    // scaleAndOffsetNDC takes you to NDC space [-1,+1] within the given viewport on the rendertarget.
122.1595 +    // We want a scale to instead go to actual UV coordinates you can sample with,
122.1596 +    // which need [0,1] and ignore the viewport.
122.1597 +    ScaleAndOffset2D result;
122.1598 +    // Scale [-1,1] to [0,1]
122.1599 +    result.Scale  = scaleAndOffsetNDC.Scale * 0.5f;
122.1600 +    result.Offset = scaleAndOffsetNDC.Offset * 0.5f + Vector2f(0.5f);
122.1601 +    
122.1602 +    // ...but we will have rendered to a subsection of the RT, so scale for that.
122.1603 +    Vector2f scale(  (float)renderedViewport.w / (float)renderTargetSize.w,
122.1604 +                     (float)renderedViewport.h / (float)renderTargetSize.h );
122.1605 +    Vector2f offset( (float)renderedViewport.x / (float)renderTargetSize.w,
122.1606 +                     (float)renderedViewport.y / (float)renderTargetSize.h );
122.1607 +
122.1608 +	result.Scale  = result.Scale.EntrywiseMultiply(scale);
122.1609 +    result.Offset  = result.Offset.EntrywiseMultiply(scale) + offset;
122.1610 +    return result;
122.1611 +}
122.1612 +
122.1613 +
122.1614 +
122.1615 +Matrix4f CreateProjection( bool rightHanded, FovPort tanHalfFov,
122.1616 +                           float zNear /*= 0.01f*/, float zFar /*= 10000.0f*/ )
122.1617 +{
122.1618 +    // A projection matrix is very like a scaling from NDC, so we can start with that.
122.1619 +    ScaleAndOffset2D scaleAndOffset = CreateNDCScaleAndOffsetFromFov ( tanHalfFov );
122.1620 +
122.1621 +    float handednessScale = 1.0f;
122.1622 +    if ( rightHanded )
122.1623 +    {
122.1624 +        handednessScale = -1.0f;
122.1625 +    }
122.1626 +
122.1627 +    Matrix4f projection;
122.1628 +    // Produces X result, mapping clip edges to [-w,+w]
122.1629 +    projection.M[0][0] = scaleAndOffset.Scale.x;
122.1630 +    projection.M[0][1] = 0.0f;
122.1631 +    projection.M[0][2] = handednessScale * scaleAndOffset.Offset.x;
122.1632 +    projection.M[0][3] = 0.0f;
122.1633 +
122.1634 +    // Produces Y result, mapping clip edges to [-w,+w]
122.1635 +    // Hey - why is that YOffset negated?
122.1636 +    // It's because a projection matrix transforms from world coords with Y=up,
122.1637 +    // whereas this is derived from an NDC scaling, which is Y=down.
122.1638 +    projection.M[1][0] = 0.0f;
122.1639 +    projection.M[1][1] = scaleAndOffset.Scale.y;
122.1640 +    projection.M[1][2] = handednessScale * -scaleAndOffset.Offset.y;
122.1641 +    projection.M[1][3] = 0.0f;
122.1642 +
122.1643 +    // Produces Z-buffer result - app needs to fill this in with whatever Z range it wants.
122.1644 +    // We'll just use some defaults for now.
122.1645 +    projection.M[2][0] = 0.0f;
122.1646 +    projection.M[2][1] = 0.0f;
122.1647 +    projection.M[2][2] = -handednessScale * zFar / (zNear - zFar);
122.1648 +    projection.M[2][3] = (zFar * zNear) / (zNear - zFar);
122.1649 +
122.1650 +    // Produces W result (= Z in)
122.1651 +    projection.M[3][0] = 0.0f;
122.1652 +    projection.M[3][1] = 0.0f;
122.1653 +    projection.M[3][2] = handednessScale;
122.1654 +    projection.M[3][3] = 0.0f;
122.1655 +
122.1656 +    return projection;
122.1657 +}
122.1658 +
122.1659 +
122.1660 +Matrix4f CreateOrthoSubProjection ( bool rightHanded, StereoEye eyeType,
122.1661 +                                    float tanHalfFovX, float tanHalfFovY,
122.1662 +                                    float unitsX, float unitsY,
122.1663 +                                    float distanceFromCamera, float interpupillaryDistance,
122.1664 +                                    Matrix4f const &projection,
122.1665 +                                    float zNear /*= 0.0f*/, float zFar /*= 0.0f*/ )
122.1666 +{
122.1667 +    OVR_UNUSED1 ( rightHanded );
122.1668 +
122.1669 +    float orthoHorizontalOffset = interpupillaryDistance * 0.5f / distanceFromCamera;
122.1670 +    switch ( eyeType )
122.1671 +    {
122.1672 +    case StereoEye_Center:
122.1673 +        orthoHorizontalOffset = 0.0f;
122.1674 +        break;
122.1675 +    case StereoEye_Left:
122.1676 +        break;
122.1677 +    case StereoEye_Right:
122.1678 +        orthoHorizontalOffset = -orthoHorizontalOffset;
122.1679 +        break;
122.1680 +    default: OVR_ASSERT ( false ); break;
122.1681 +    }
122.1682 +
122.1683 +    // Current projection maps real-world vector (x,y,1) to the RT.
122.1684 +    // We want to find the projection that maps the range [-FovPixels/2,FovPixels/2] to
122.1685 +    // the physical [-orthoHalfFov,orthoHalfFov]
122.1686 +    // Note moving the offset from M[0][2]+M[1][2] to M[0][3]+M[1][3] - this means
122.1687 +    // we don't have to feed in Z=1 all the time.
122.1688 +    // The horizontal offset math is a little hinky because the destination is
122.1689 +    // actually [-orthoHalfFov+orthoHorizontalOffset,orthoHalfFov+orthoHorizontalOffset]
122.1690 +    // So we need to first map [-FovPixels/2,FovPixels/2] to
122.1691 +    //                         [-orthoHalfFov+orthoHorizontalOffset,orthoHalfFov+orthoHorizontalOffset]:
122.1692 +    // x1 = x0 * orthoHalfFov/(FovPixels/2) + orthoHorizontalOffset;
122.1693 +    //    = x0 * 2*orthoHalfFov/FovPixels + orthoHorizontalOffset;
122.1694 +    // But then we need the sam mapping as the existing projection matrix, i.e.
122.1695 +    // x2 = x1 * Projection.M[0][0] + Projection.M[0][2];
122.1696 +    //    = x0 * (2*orthoHalfFov/FovPixels + orthoHorizontalOffset) * Projection.M[0][0] + Projection.M[0][2];
122.1697 +    //    = x0 * Projection.M[0][0]*2*orthoHalfFov/FovPixels +
122.1698 +    //      orthoHorizontalOffset*Projection.M[0][0] + Projection.M[0][2];
122.1699 +    // So in the new projection matrix we need to scale by Projection.M[0][0]*2*orthoHalfFov/FovPixels and
122.1700 +    // offset by orthoHorizontalOffset*Projection.M[0][0] + Projection.M[0][2].
122.1701 +
122.1702 +    float orthoScaleX = 2.0f * tanHalfFovX / unitsX;
122.1703 +    float orthoScaleY = 2.0f * tanHalfFovY / unitsY;
122.1704 +    Matrix4f ortho;
122.1705 +    ortho.M[0][0] = projection.M[0][0] * orthoScaleX;
122.1706 +    ortho.M[0][1] = 0.0f;
122.1707 +    ortho.M[0][2] = 0.0f;
122.1708 +    ortho.M[0][3] = -projection.M[0][2] + ( orthoHorizontalOffset * projection.M[0][0] );
122.1709 +
122.1710 +    ortho.M[1][0] = 0.0f;
122.1711 +    ortho.M[1][1] = -projection.M[1][1] * orthoScaleY;       // Note sign flip (text rendering uses Y=down).
122.1712 +    ortho.M[1][2] = 0.0f;
122.1713 +    ortho.M[1][3] = -projection.M[1][2];
122.1714 +
122.1715 +    if ( fabsf ( zNear - zFar ) < 0.001f )
122.1716 +    {
122.1717 +        ortho.M[2][0] = 0.0f;
122.1718 +        ortho.M[2][1] = 0.0f;
122.1719 +        ortho.M[2][2] = 0.0f;
122.1720 +        ortho.M[2][3] = zFar;
122.1721 +    }
122.1722 +    else
122.1723 +    {
122.1724 +        ortho.M[2][0] = 0.0f;
122.1725 +        ortho.M[2][1] = 0.0f;
122.1726 +        ortho.M[2][2] = zFar / (zNear - zFar);
122.1727 +        ortho.M[2][3] = (zFar * zNear) / (zNear - zFar);
122.1728 +    }
122.1729 +
122.1730 +    // No perspective correction for ortho.
122.1731 +    ortho.M[3][0] = 0.0f;
122.1732 +    ortho.M[3][1] = 0.0f;
122.1733 +    ortho.M[3][2] = 0.0f;
122.1734 +    ortho.M[3][3] = 1.0f;
122.1735 +
122.1736 +    return ortho;
122.1737 +}
122.1738 +
122.1739 +
122.1740 +//-----------------------------------------------------------------------------------
122.1741 +// A set of "forward-mapping" functions, mapping from framebuffer space to real-world and/or texture space.
122.1742 +
122.1743 +// This mimics the first half of the distortion shader's function.
122.1744 +Vector2f TransformScreenNDCToTanFovSpace( DistortionRenderDesc const &distortion,
122.1745 +                                          const Vector2f &framebufferNDC )
122.1746 +{
122.1747 +    // Scale to TanHalfFov space, but still distorted.
122.1748 +    Vector2f tanEyeAngleDistorted;
122.1749 +    tanEyeAngleDistorted.x = ( framebufferNDC.x - distortion.LensCenter.x ) * distortion.TanEyeAngleScale.x;
122.1750 +    tanEyeAngleDistorted.y = ( framebufferNDC.y - distortion.LensCenter.y ) * distortion.TanEyeAngleScale.y;
122.1751 +    // Distort.
122.1752 +    float radiusSquared = ( tanEyeAngleDistorted.x * tanEyeAngleDistorted.x )
122.1753 +                        + ( tanEyeAngleDistorted.y * tanEyeAngleDistorted.y );
122.1754 +    float distortionScale = distortion.Lens.DistortionFnScaleRadiusSquared ( radiusSquared );
122.1755 +    Vector2f tanEyeAngle;
122.1756 +    tanEyeAngle.x = tanEyeAngleDistorted.x * distortionScale;
122.1757 +    tanEyeAngle.y = tanEyeAngleDistorted.y * distortionScale;
122.1758 +
122.1759 +    return tanEyeAngle;
122.1760 +}
122.1761 +
122.1762 +// Same, with chromatic aberration correction.
122.1763 +void TransformScreenNDCToTanFovSpaceChroma ( Vector2f *resultR, Vector2f *resultG, Vector2f *resultB, 
122.1764 +                                             DistortionRenderDesc const &distortion,
122.1765 +                                             const Vector2f &framebufferNDC )
122.1766 +{
122.1767 +    // Scale to TanHalfFov space, but still distorted.
122.1768 +    Vector2f tanEyeAngleDistorted;
122.1769 +    tanEyeAngleDistorted.x = ( framebufferNDC.x - distortion.LensCenter.x ) * distortion.TanEyeAngleScale.x;
122.1770 +    tanEyeAngleDistorted.y = ( framebufferNDC.y - distortion.LensCenter.y ) * distortion.TanEyeAngleScale.y;
122.1771 +    // Distort.
122.1772 +    float radiusSquared = ( tanEyeAngleDistorted.x * tanEyeAngleDistorted.x )
122.1773 +                        + ( tanEyeAngleDistorted.y * tanEyeAngleDistorted.y );
122.1774 +    Vector3f distortionScales = distortion.Lens.DistortionFnScaleRadiusSquaredChroma ( radiusSquared );
122.1775 +    *resultR = tanEyeAngleDistorted * distortionScales.x;
122.1776 +    *resultG = tanEyeAngleDistorted * distortionScales.y;
122.1777 +    *resultB = tanEyeAngleDistorted * distortionScales.z;
122.1778 +}
122.1779 +
122.1780 +// This mimics the second half of the distortion shader's function.
122.1781 +Vector2f TransformTanFovSpaceToRendertargetTexUV( ScaleAndOffset2D const &eyeToSourceUV,
122.1782 +                                                  Vector2f const &tanEyeAngle )
122.1783 +{
122.1784 +    Vector2f textureUV;
122.1785 +    textureUV.x = tanEyeAngle.x * eyeToSourceUV.Scale.x + eyeToSourceUV.Offset.x;
122.1786 +    textureUV.y = tanEyeAngle.y * eyeToSourceUV.Scale.y + eyeToSourceUV.Offset.y;
122.1787 +    return textureUV;
122.1788 +}
122.1789 +
122.1790 +Vector2f TransformTanFovSpaceToRendertargetNDC( ScaleAndOffset2D const &eyeToSourceNDC,
122.1791 +                                                Vector2f const &tanEyeAngle )
122.1792 +{
122.1793 +    Vector2f textureNDC;
122.1794 +    textureNDC.x = tanEyeAngle.x * eyeToSourceNDC.Scale.x + eyeToSourceNDC.Offset.x;
122.1795 +    textureNDC.y = tanEyeAngle.y * eyeToSourceNDC.Scale.y + eyeToSourceNDC.Offset.y;
122.1796 +    return textureNDC;
122.1797 +}
122.1798 +
122.1799 +Vector2f TransformScreenPixelToScreenNDC( Recti const &distortionViewport,
122.1800 +                                          Vector2f const &pixel )
122.1801 +{
122.1802 +    // Move to [-1,1] NDC coords.
122.1803 +    Vector2f framebufferNDC;
122.1804 +    framebufferNDC.x = -1.0f + 2.0f * ( ( pixel.x - (float)distortionViewport.x ) / (float)distortionViewport.w );
122.1805 +    framebufferNDC.y = -1.0f + 2.0f * ( ( pixel.y - (float)distortionViewport.y ) / (float)distortionViewport.h );
122.1806 +    return framebufferNDC;
122.1807 +}
122.1808 +
122.1809 +Vector2f TransformScreenPixelToTanFovSpace( Recti const &distortionViewport,
122.1810 +                                            DistortionRenderDesc const &distortion,
122.1811 +                                            Vector2f const &pixel )
122.1812 +{
122.1813 +    return TransformScreenNDCToTanFovSpace( distortion,
122.1814 +                TransformScreenPixelToScreenNDC( distortionViewport, pixel ) );
122.1815 +}
122.1816 +
122.1817 +Vector2f TransformScreenNDCToRendertargetTexUV( DistortionRenderDesc const &distortion,
122.1818 +                                                StereoEyeParams const &eyeParams,
122.1819 +                                                Vector2f const &pixel )
122.1820 +{
122.1821 +    return TransformTanFovSpaceToRendertargetTexUV ( eyeParams,
122.1822 +                TransformScreenNDCToTanFovSpace ( distortion, pixel ) );
122.1823 +}
122.1824 +
122.1825 +Vector2f TransformScreenPixelToRendertargetTexUV( Recti const &distortionViewport,
122.1826 +                                                  DistortionRenderDesc const &distortion,
122.1827 +                                                  StereoEyeParams const &eyeParams,
122.1828 +                                                  Vector2f const &pixel )
122.1829 +{
122.1830 +    return TransformTanFovSpaceToRendertargetTexUV ( eyeParams,
122.1831 +                TransformScreenPixelToTanFovSpace ( distortionViewport, distortion, pixel ) );
122.1832 +}
122.1833 +
122.1834 +
122.1835 +//-----------------------------------------------------------------------------------
122.1836 +// A set of "reverse-mapping" functions, mapping from real-world and/or texture space back to the framebuffer.
122.1837 +
122.1838 +Vector2f TransformTanFovSpaceToScreenNDC( DistortionRenderDesc const &distortion,
122.1839 +                                          const Vector2f &tanEyeAngle, bool usePolyApprox /*= false*/ )
122.1840 +{
122.1841 +    float tanEyeAngleRadius = tanEyeAngle.Length();
122.1842 +    float tanEyeAngleDistortedRadius = distortion.Lens.DistortionFnInverseApprox ( tanEyeAngleRadius );
122.1843 +    if ( !usePolyApprox )
122.1844 +    {
122.1845 +        tanEyeAngleDistortedRadius = distortion.Lens.DistortionFnInverse ( tanEyeAngleRadius );
122.1846 +    }
122.1847 +    Vector2f tanEyeAngleDistorted = tanEyeAngle;
122.1848 +    if ( tanEyeAngleRadius > 0.0f )
122.1849 +    {   
122.1850 +        tanEyeAngleDistorted = tanEyeAngle * ( tanEyeAngleDistortedRadius / tanEyeAngleRadius );
122.1851 +    }
122.1852 +
122.1853 +    Vector2f framebufferNDC;
122.1854 +    framebufferNDC.x = ( tanEyeAngleDistorted.x / distortion.TanEyeAngleScale.x ) + distortion.LensCenter.x;
122.1855 +    framebufferNDC.y = ( tanEyeAngleDistorted.y / distortion.TanEyeAngleScale.y ) + distortion.LensCenter.y;
122.1856 +
122.1857 +    return framebufferNDC;
122.1858 +}
122.1859 +
122.1860 +Vector2f TransformRendertargetNDCToTanFovSpace( const ScaleAndOffset2D &eyeToSourceNDC,
122.1861 +                                                const Vector2f &textureNDC )
122.1862 +{
122.1863 +    Vector2f tanEyeAngle = (textureNDC - eyeToSourceNDC.Offset) / eyeToSourceNDC.Scale;
122.1864 +    return tanEyeAngle;
122.1865 +}
122.1866 +
122.1867 +
122.1868 +
122.1869 +} //namespace OVR
122.1870 +
122.1871 +//Just want to make a copy disentangled from all these namespaces!
122.1872 +float ExtEvalCatmullRom10Spline ( float const *K, float scaledVal )
122.1873 +{
122.1874 +	return(OVR::EvalCatmullRom10Spline ( K, scaledVal ));
122.1875 +}
122.1876 +
122.1877 +
   123.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   123.2 +++ b/LibOVR/Src/OVR_Stereo.h	Wed Jan 14 06:51:16 2015 +0200
   123.3 @@ -0,0 +1,681 @@
   123.4 +/************************************************************************************
   123.5 +
   123.6 +Filename    :   OVR_Stereo.h
   123.7 +Content     :   Stereo rendering functions
   123.8 +Created     :   November 30, 2013
   123.9 +Authors     :   Tom Fosyth
  123.10 +
  123.11 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
  123.12 +
  123.13 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
  123.14 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
  123.15 +which is provided at the time of installation or download, or which 
  123.16 +otherwise accompanies this software in either electronic or hard copy form.
  123.17 +
  123.18 +You may obtain a copy of the License at
  123.19 +
  123.20 +http://www.oculusvr.com/licenses/LICENSE-3.2 
  123.21 +
  123.22 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
  123.23 +distributed under the License is distributed on an "AS IS" BASIS,
  123.24 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  123.25 +See the License for the specific language governing permissions and
  123.26 +limitations under the License.
  123.27 +
  123.28 +*************************************************************************************/
  123.29 +
  123.30 +#ifndef OVR_Stereo_h
  123.31 +#define OVR_Stereo_h
  123.32 +
  123.33 +#include "Sensors/OVR_DeviceConstants.h"
  123.34 +#include "Displays/OVR_Display.h"
  123.35 +#include "OVR_Profile.h"
  123.36 +
  123.37 +// CAPI Forward declaration.
  123.38 +typedef struct ovrFovPort_ ovrFovPort;
  123.39 +typedef struct ovrRecti_ ovrRecti;
  123.40 +
  123.41 +namespace OVR {
  123.42 +
  123.43 +class SensorDevice; // Opaque forward declaration
  123.44 +
  123.45 +
  123.46 +//-----------------------------------------------------------------------------------
  123.47 +// ***** Stereo Enumerations
  123.48 +
  123.49 +// StereoEye specifies which eye we are rendering for; it is used to
  123.50 +// retrieve StereoEyeParams.
  123.51 +enum StereoEye
  123.52 +{
  123.53 +    StereoEye_Center,
  123.54 +    StereoEye_Left,
  123.55 +    StereoEye_Right    
  123.56 +};
  123.57 +
  123.58 +
  123.59 +//-----------------------------------------------------------------------------------
  123.60 +// ***** FovPort
  123.61 +
  123.62 +// FovPort describes Field Of View (FOV) of a viewport.
  123.63 +// This class has values for up, down, left and right, stored in 
  123.64 +// tangent of the angle units to simplify calculations.
  123.65 +//
  123.66 +// As an example, for a standard 90 degree vertical FOV, we would 
  123.67 +// have: { UpTan = tan(90 degrees / 2), DownTan = tan(90 degrees / 2) }.
  123.68 +//
  123.69 +// CreateFromRadians/Degrees helper functions can be used to
  123.70 +// access FOV in different units.
  123.71 +
  123.72 +struct FovPort
  123.73 +{
  123.74 +    float UpTan;
  123.75 +    float DownTan;
  123.76 +    float LeftTan;
  123.77 +    float RightTan;
  123.78 +
  123.79 +    FovPort ( float sideTan = 0.0f ) :
  123.80 +        UpTan(sideTan), DownTan(sideTan), LeftTan(sideTan), RightTan(sideTan) { }
  123.81 +    FovPort ( float u, float d, float l, float r ) :
  123.82 +        UpTan(u), DownTan(d), LeftTan(l), RightTan(r) { }
  123.83 +
  123.84 +    // C-interop support: FovPort <-> ovrFovPort (implementation in OVR_CAPI.cpp).
  123.85 +    FovPort(const ovrFovPort& src);
  123.86 +    operator ovrFovPort () const;
  123.87 +
  123.88 +    static FovPort CreateFromRadians(float horizontalFov, float verticalFov)
  123.89 +    {
  123.90 +        FovPort result;
  123.91 +        result.UpTan    = tanf (   verticalFov * 0.5f );
  123.92 +        result.DownTan  = tanf (   verticalFov * 0.5f );
  123.93 +        result.LeftTan  = tanf ( horizontalFov * 0.5f );
  123.94 +        result.RightTan = tanf ( horizontalFov * 0.5f );
  123.95 +        return result;
  123.96 +    }
  123.97 +
  123.98 +    static FovPort CreateFromDegrees(float horizontalFovDegrees,
  123.99 +                                     float verticalFovDegrees)
 123.100 +    {
 123.101 +        return CreateFromRadians(DegreeToRad(horizontalFovDegrees),
 123.102 +                                 DegreeToRad(verticalFovDegrees));
 123.103 +    }
 123.104 +
 123.105 +    //  Get Horizontal/Vertical components of Fov in radians.
 123.106 +    float GetVerticalFovRadians() const     { return atanf(UpTan)    + atanf(DownTan); }
 123.107 +    float GetHorizontalFovRadians() const   { return atanf(LeftTan)  + atanf(RightTan); }
 123.108 +    //  Get Horizontal/Vertical components of Fov in degrees.
 123.109 +    float GetVerticalFovDegrees() const     { return RadToDegree(GetVerticalFovRadians()); }
 123.110 +    float GetHorizontalFovDegrees() const   { return RadToDegree(GetHorizontalFovRadians()); }
 123.111 +
 123.112 +    // Compute maximum tangent value among all four sides.
 123.113 +    float GetMaxSideTan() const
 123.114 +    {
 123.115 +        return Alg::Max(Alg::Max(UpTan, DownTan), Alg::Max(LeftTan, RightTan));
 123.116 +    }
 123.117 +
 123.118 +    // Converts Fov Tan angle units to [-1,1] render target NDC space
 123.119 +    Vector2f TanAngleToRendertargetNDC(Vector2f const &tanEyeAngle);
 123.120 +
 123.121 +
 123.122 +    // Compute per-channel minimum and maximum of Fov.
 123.123 +    static FovPort Min(const FovPort& a, const FovPort& b)
 123.124 +    {   
 123.125 +        FovPort fov( Alg::Min( a.UpTan   , b.UpTan    ),   
 123.126 +                     Alg::Min( a.DownTan , b.DownTan  ),
 123.127 +                     Alg::Min( a.LeftTan , b.LeftTan  ),
 123.128 +                     Alg::Min( a.RightTan, b.RightTan ) );
 123.129 +        return fov;
 123.130 +    }
 123.131 +
 123.132 +    static FovPort Max(const FovPort& a, const FovPort& b)
 123.133 +    {   
 123.134 +        FovPort fov( Alg::Max( a.UpTan   , b.UpTan    ),   
 123.135 +                     Alg::Max( a.DownTan , b.DownTan  ),
 123.136 +                     Alg::Max( a.LeftTan , b.LeftTan  ),
 123.137 +                     Alg::Max( a.RightTan, b.RightTan ) );
 123.138 +        return fov;
 123.139 +    }
 123.140 +};
 123.141 +
 123.142 +
 123.143 +//-----------------------------------------------------------------------------------
 123.144 +// ***** ScaleAndOffset
 123.145 +
 123.146 +struct ScaleAndOffset2D
 123.147 +{
 123.148 +    Vector2f Scale;
 123.149 +    Vector2f Offset;
 123.150 +
 123.151 +    ScaleAndOffset2D(float sx = 0.0f, float sy = 0.0f, float ox = 0.0f, float oy = 0.0f)
 123.152 +      : Scale(sx, sy), Offset(ox, oy)        
 123.153 +    { }
 123.154 +};
 123.155 +
 123.156 +
 123.157 +//-----------------------------------------------------------------------------------
 123.158 +// ***** Misc. utility functions.
 123.159 +
 123.160 +// Inputs are 4 points (pFitX[0],pFitY[0]) through (pFitX[3],pFitY[3])
 123.161 +// Result is four coefficients in pResults[0] through pResults[3] such that
 123.162 +//      y = pResult[0] + x * ( pResult[1] + x * ( pResult[2] + x * ( pResult[3] ) ) );
 123.163 +// passes through all four input points.
 123.164 +// Return is true if it succeeded, false if it failed (because two control points
 123.165 +// have the same pFitX value).
 123.166 +bool FitCubicPolynomial ( float *pResult, const float *pFitX, const float *pFitY );
 123.167 +
 123.168 +//-----------------------------------------------------------------------------------
 123.169 +// ***** LensConfig
 123.170 +
 123.171 +// LensConfig describes the configuration of a single lens in an HMD.
 123.172 +// - Eqn and K[] describe a distortion function.
 123.173 +// - MetersPerTanAngleAtCenter is the relationship between distance on a
 123.174 +//   screen (at the center of the lens), and the angle variance of the light after it
 123.175 +//   has passed through the lens.
 123.176 +// - ChromaticAberration is an array of parameters for controlling
 123.177 +//   additional Red and Blue scaling in order to reduce chromatic aberration
 123.178 +//   caused by the Rift lenses.
 123.179 +struct LensConfig
 123.180 +{
 123.181 +    LensConfig()
 123.182 +      : Eqn(Distortion_CatmullRom10)
 123.183 +      //K()
 123.184 +      , MaxR(0.0f)
 123.185 +      , MetersPerTanAngleAtCenter(0.0f)
 123.186 +      //ChromaticAberration()
 123.187 +      //InvK()
 123.188 +      , MaxInvR(0.0f)
 123.189 +    {
 123.190 +        memset(&K, 0, sizeof(K));
 123.191 +        memset(&ChromaticAberration, 0, sizeof(ChromaticAberration));
 123.192 +        memset(&InvK, 0, sizeof(InvK));
 123.193 +    }
 123.194 +    
 123.195 +    // The result is a scaling applied to the distance from the center of the lens.
 123.196 +    float    DistortionFnScaleRadiusSquared (float rsq) const;
 123.197 +    // x,y,z components map to r,g,b scales.
 123.198 +    Vector3f DistortionFnScaleRadiusSquaredChroma (float rsq) const;
 123.199 +
 123.200 +    // DistortionFn applies distortion to the argument.
 123.201 +    // Input: the distance in TanAngle/NIC space from the optical center to the input pixel.
 123.202 +    // Output: the resulting distance after distortion.
 123.203 +    float DistortionFn(float r) const
 123.204 +    {
 123.205 +        return r * DistortionFnScaleRadiusSquared ( r * r );
 123.206 +    }
 123.207 +
 123.208 +    // DistortionFnInverse computes the inverse of the distortion function on an argument.
 123.209 +    float DistortionFnInverse(float r) const;
 123.210 +
 123.211 +    // Also computes the inverse, but using a polynomial approximation. Warning - it's just an approximation!
 123.212 +    float DistortionFnInverseApprox(float r) const;
 123.213 +    // Sets up InvK[].
 123.214 +    void SetUpInverseApprox();
 123.215 +
 123.216 +    // Sets a bunch of sensible defaults.
 123.217 +    void SetToIdentity();
 123.218 +
 123.219 +
 123.220 +
 123.221 +    enum { NumCoefficients = 11 };
 123.222 +
 123.223 +    DistortionEqnType   Eqn;
 123.224 +    float               K[NumCoefficients];
 123.225 +    float               MaxR;       // The highest R you're going to query for - the curve is unpredictable beyond it.
 123.226 +
 123.227 +    float               MetersPerTanAngleAtCenter;
 123.228 +
 123.229 +    // Additional per-channel scaling is applied after distortion:
 123.230 +    //  Index [0] - Red channel constant coefficient.
 123.231 +    //  Index [1] - Red channel r^2 coefficient.
 123.232 +    //  Index [2] - Blue channel constant coefficient.
 123.233 +    //  Index [3] - Blue channel r^2 coefficient.
 123.234 +    float               ChromaticAberration[4];
 123.235 +
 123.236 +    float               InvK[NumCoefficients];
 123.237 +    float               MaxInvR;
 123.238 +};
 123.239 +
 123.240 +
 123.241 +// For internal use - storing and loading lens config data
 123.242 +
 123.243 +// Returns true on success.
 123.244 +bool LoadLensConfig ( LensConfig *presult, uint8_t const *pbuffer, int bufferSizeInBytes );
 123.245 +
 123.246 +// Returns number of bytes needed.
 123.247 +int SaveLensConfigSizeInBytes ( LensConfig const &config );
 123.248 +// Returns true on success.
 123.249 +bool SaveLensConfig ( uint8_t *pbuffer, int bufferSizeInBytes, LensConfig const &config );
 123.250 +
 123.251 +
 123.252 +//-----------------------------------------------------------------------------------
 123.253 +// ***** DistortionRenderDesc
 123.254 +
 123.255 +// This describes distortion for a single eye in an HMD with a display, not just the lens by itself.
 123.256 +struct DistortionRenderDesc
 123.257 +{
 123.258 +    // The raw lens values.
 123.259 +    LensConfig          Lens;
 123.260 +
 123.261 +    // These map from [-1,1] across the eye being rendered into TanEyeAngle space (but still distorted)
 123.262 +    Vector2f            LensCenter;
 123.263 +    Vector2f            TanEyeAngleScale;
 123.264 +    // Computed from device characteristics, IPD and eye-relief.
 123.265 +    // (not directly used for rendering, but very useful)
 123.266 +    Vector2f            PixelsPerTanAngleAtCenter;
 123.267 +};
 123.268 +
 123.269 +
 123.270 +//-------------------------------------------------------------------------------------
 123.271 +// ***** HMDInfo 
 123.272 +
 123.273 +// This structure describes various aspects of the HMD allowing us to configure rendering.
 123.274 +//
 123.275 +//  Currently included data:
 123.276 +//   - Physical screen dimensions, resolution, and eye distances.
 123.277 +//     (some of these will be configurable with a tool in the future).
 123.278 +//     These arguments allow us to properly setup projection across HMDs.
 123.279 +//   - DisplayDeviceName for identifying HMD screen; system-specific interpretation.
 123.280 +//
 123.281 +// TBD:
 123.282 +//  - Power on/ off?
 123.283 +//  - Sensor rates and capabilities
 123.284 +//  - Distortion radius/variables    
 123.285 +//  - Screen update frequency
 123.286 +//  - Distortion needed flag
 123.287 +//  - Update modes:
 123.288 +//      Set update mode: Stereo (both sides together), mono (same in both eyes),
 123.289 +//                       Alternating, Alternating scan-lines.
 123.290 +
 123.291 +// Win32 Oculus VR Display Driver Shim Information
 123.292 +struct Win32ShimInfo
 123.293 +{
 123.294 +	int DeviceNumber;
 123.295 +	int NativeWidth;
 123.296 +	int NativeHeight;
 123.297 +	int Rotation;
 123.298 +	int UseMirroring;
 123.299 +
 123.300 +	Win32ShimInfo() :
 123.301 +		DeviceNumber(-1),
 123.302 +		NativeWidth(-1),
 123.303 +		NativeHeight(-1),
 123.304 +		Rotation(-1),
 123.305 +		UseMirroring(1)
 123.306 +	{
 123.307 +	}
 123.308 +};
 123.309 +
 123.310 +class HMDInfo
 123.311 +{
 123.312 +public:
 123.313 +	// Name string describing the product: "Oculus Rift DK1", etc.
 123.314 +	String      ProductName;
 123.315 +	String      Manufacturer;
 123.316 +
 123.317 +	unsigned    Version;
 123.318 +
 123.319 +	// Characteristics of the HMD screen and enclosure
 123.320 +	HmdTypeEnum HmdType;
 123.321 +	Size<int>   ResolutionInPixels;
 123.322 +	Size<float> ScreenSizeInMeters;
 123.323 +	float       ScreenGapSizeInMeters;
 123.324 +	float       CenterFromTopInMeters;
 123.325 +	float       LensSeparationInMeters;
 123.326 +    Vector2f    PelOffsetR;                     // Offsets from the green pel in pixels (i.e. usual values are 0.5 or 0.333)
 123.327 +    Vector2f    PelOffsetB;
 123.328 +
 123.329 +
 123.330 +	// Timing & shutter data. All values in seconds.
 123.331 +	struct ShutterInfo
 123.332 +	{
 123.333 +		HmdShutterTypeEnum  Type;
 123.334 +		float   VsyncToNextVsync;                // 1/framerate
 123.335 +		float   VsyncToFirstScanline;            // for global shutter, vsync->shutter open.
 123.336 +		float   FirstScanlineToLastScanline;     // for global shutter, will be zero.
 123.337 +		float   PixelSettleTime;                 // estimated.
 123.338 +		float   PixelPersistence;                // Full persistence = 1/framerate.
 123.339 +	}           Shutter;
 123.340 +
 123.341 +	// Desktop coordinate position of the screen (can be negative; may not be present on all platforms)
 123.342 +	int         DesktopX;
 123.343 +	int         DesktopY;
 123.344 +
 123.345 +	// Windows:
 123.346 +	// "\\\\.\\DISPLAY3", etc. Can be used in EnumDisplaySettings/CreateDC.
 123.347 +	String      DisplayDeviceName;
 123.348 +	Win32ShimInfo ShimInfo;
 123.349 +
 123.350 +	// MacOS:
 123.351 +	int         DisplayId;
 123.352 +
 123.353 +	bool	    InCompatibilityMode;
 123.354 +
 123.355 +	// Printed serial number for the HMD; should match external sticker
 123.356 +    String      PrintedSerial;
 123.357 +
 123.358 +    // Tracker descriptor information:
 123.359 +    int         VendorId;
 123.360 +    int         ProductId;
 123.361 +    int         FirmwareMajor;
 123.362 +    int         FirmwareMinor;
 123.363 +
 123.364 +    float   CameraFrustumHFovInRadians;
 123.365 +    float   CameraFrustumVFovInRadians;
 123.366 +    float   CameraFrustumNearZInMeters;
 123.367 +    float   CameraFrustumFarZInMeters;
 123.368 +
 123.369 +	// Constructor initializes all values to 0s.
 123.370 +	// To create a "virtualized" HMDInfo, use CreateDebugHMDInfo instead.
 123.371 +	HMDInfo() :
 123.372 +		ProductName(),
 123.373 +        Manufacturer(),
 123.374 +        Version(0),
 123.375 +		HmdType(HmdType_None),
 123.376 +		ResolutionInPixels(0),
 123.377 +		ScreenSizeInMeters(0.0f),
 123.378 +		ScreenGapSizeInMeters(0.0f),
 123.379 +		CenterFromTopInMeters(0),
 123.380 +		LensSeparationInMeters(0),
 123.381 +        PelOffsetR(0.0f,0.0f),
 123.382 +        PelOffsetB(0.0f,0.0f),
 123.383 +      //Shutter (initialized below)
 123.384 +		DesktopX(0),
 123.385 +		DesktopY(0),
 123.386 +        DisplayDeviceName(),
 123.387 +        ShimInfo(),
 123.388 +		DisplayId(-1),
 123.389 +		InCompatibilityMode(false),
 123.390 +        PrintedSerial(),
 123.391 +        VendorId(-1),
 123.392 +        ProductId(-1),
 123.393 +        FirmwareMajor(-1),
 123.394 +        FirmwareMinor(-1),
 123.395 +        CameraFrustumHFovInRadians(0.0f),
 123.396 +        CameraFrustumVFovInRadians(0.0f),
 123.397 +        CameraFrustumNearZInMeters(0.0f),
 123.398 +        CameraFrustumFarZInMeters(0.0f)
 123.399 +	{
 123.400 +		Shutter.Type = HmdShutter_LAST;
 123.401 +		Shutter.VsyncToNextVsync = 0.0f;
 123.402 +		Shutter.VsyncToFirstScanline = 0.0f;
 123.403 +		Shutter.FirstScanlineToLastScanline = 0.0f;
 123.404 +		Shutter.PixelSettleTime = 0.0f;
 123.405 +		Shutter.PixelPersistence = 0.0f;
 123.406 +    }
 123.407 +
 123.408 +	// Operator = copies local fields only (base class must be correct already)
 123.409 +	void operator=(const HMDInfo& src)
 123.410 +	{
 123.411 +		ProductName = src.ProductName;
 123.412 +		Manufacturer = src.Manufacturer;
 123.413 +		Version = src.Version;
 123.414 +		HmdType = src.HmdType;
 123.415 +		ResolutionInPixels = src.ResolutionInPixels;
 123.416 +		ScreenSizeInMeters = src.ScreenSizeInMeters;
 123.417 +		ScreenGapSizeInMeters = src.ScreenGapSizeInMeters;
 123.418 +		CenterFromTopInMeters = src.CenterFromTopInMeters;
 123.419 +		LensSeparationInMeters = src.LensSeparationInMeters;
 123.420 +        PelOffsetR = src.PelOffsetR;
 123.421 +        PelOffsetB = src.PelOffsetB;
 123.422 +		DesktopX = src.DesktopX;
 123.423 +		DesktopY = src.DesktopY;
 123.424 +		Shutter = src.Shutter;
 123.425 +		DisplayDeviceName = src.DisplayDeviceName;
 123.426 +		ShimInfo = src.ShimInfo;
 123.427 +		DisplayId = src.DisplayId;
 123.428 +		InCompatibilityMode = src.InCompatibilityMode;
 123.429 +        VendorId = src.VendorId;
 123.430 +        ProductId = src.ProductId;
 123.431 +        FirmwareMajor = src.FirmwareMajor;
 123.432 +        FirmwareMinor = src.FirmwareMinor;
 123.433 +        PrintedSerial = src.PrintedSerial;
 123.434 +        CameraFrustumHFovInRadians = src.CameraFrustumHFovInRadians;
 123.435 +        CameraFrustumVFovInRadians = src.CameraFrustumVFovInRadians;
 123.436 +        CameraFrustumNearZInMeters = src.CameraFrustumNearZInMeters;
 123.437 +        CameraFrustumFarZInMeters = src.CameraFrustumFarZInMeters;
 123.438 +    }
 123.439 +
 123.440 +	void SetScreenParameters(int hres, int vres,
 123.441 +							 float hsize, float vsize,
 123.442 +							 float vCenterFromTopInMeters, float lensSeparationInMeters,
 123.443 +							 bool compatibilityMode)
 123.444 +	{
 123.445 +		ResolutionInPixels = Sizei(hres, vres);
 123.446 +		ScreenSizeInMeters = Sizef(hsize, vsize);
 123.447 +		CenterFromTopInMeters = vCenterFromTopInMeters;
 123.448 +		LensSeparationInMeters = lensSeparationInMeters;
 123.449 +		InCompatibilityMode = compatibilityMode;
 123.450 +	}
 123.451 +
 123.452 +	bool IsSameDisplay(const HMDInfo& o) const
 123.453 +	{
 123.454 +		return DisplayId == o.DisplayId &&
 123.455 +			DisplayDeviceName.CompareNoCase(o.DisplayDeviceName) == 0;
 123.456 +	}
 123.457 +
 123.458 +	static bool CreateFromSensorAndDisplay(SensorDevice* sensor, Display* display, HMDInfo* hmdi);
 123.459 +};
 123.460 +
 123.461 +
 123.462 +//-----------------------------------------------------------------------------------
 123.463 +// ***** HmdRenderInfo
 123.464 +
 123.465 +// All the parts of the HMD info that are needed to set up the rendering system.
 123.466 +
 123.467 +struct HmdRenderInfo
 123.468 +{
 123.469 +    // The start of this structure is intentionally very similar to HMDInfo in OVER_Device.h
 123.470 +    // However to reduce interdependencies, one does not simply #include the other.
 123.471 +
 123.472 +    HmdTypeEnum HmdType;
 123.473 +
 123.474 +    // Size of the entire screen
 123.475 +    Size<int>   ResolutionInPixels;
 123.476 +    Size<float> ScreenSizeInMeters;
 123.477 +    float       ScreenGapSizeInMeters;
 123.478 +    Vector2f    PelOffsetR;                     // Offsets from the green pel in pixels (i.e. usual values are 0.5 or 0.333)
 123.479 +    Vector2f    PelOffsetB;
 123.480 +
 123.481 +    // Characteristics of the lenses.
 123.482 +    float       CenterFromTopInMeters;
 123.483 +    float       LensSeparationInMeters;
 123.484 +    float       LensDiameterInMeters;
 123.485 +    float       LensSurfaceToMidplateInMeters;
 123.486 +    EyeCupType  EyeCups;
 123.487 +
 123.488 +    // Timing & shutter data. All values in seconds.
 123.489 +    struct ShutterInfo
 123.490 +    {
 123.491 +        HmdShutterTypeEnum  Type;
 123.492 +        float               VsyncToNextVsync;                // 1/framerate
 123.493 +        float               VsyncToFirstScanline;            // for global shutter, vsync->shutter open.
 123.494 +        float               FirstScanlineToLastScanline;     // for global shutter, will be zero.
 123.495 +        float               PixelSettleTime;                 // estimated.
 123.496 +        float               PixelPersistence;                // Full persistence = 1/framerate.
 123.497 +    }           Shutter;
 123.498 +
 123.499 +
 123.500 +    // These are all set from the user's profile.
 123.501 +    struct EyeConfig
 123.502 +    {
 123.503 +        // Distance from center of eyeball to front plane of lens.
 123.504 +        float               ReliefInMeters;
 123.505 +        // Distance from nose (technically, center of Rift) to the middle of the eye.
 123.506 +        float               NoseToPupilInMeters;
 123.507 +
 123.508 +        LensConfig          Distortion;
 123.509 +    } EyeLeft, EyeRight;
 123.510 +
 123.511 +
 123.512 +    HmdRenderInfo()
 123.513 +    {
 123.514 +        HmdType = HmdType_None;
 123.515 +        ResolutionInPixels.w = 0;
 123.516 +        ResolutionInPixels.h = 0;
 123.517 +        ScreenSizeInMeters.w = 0.0f;
 123.518 +        ScreenSizeInMeters.h = 0.0f;
 123.519 +        ScreenGapSizeInMeters = 0.0f;
 123.520 +        CenterFromTopInMeters = 0.0f;
 123.521 +        LensSeparationInMeters = 0.0f;
 123.522 +        LensDiameterInMeters = 0.0f;
 123.523 +        LensSurfaceToMidplateInMeters = 0.0f;
 123.524 +        PelOffsetR = Vector2f ( 0.0f, 0.0f );
 123.525 +        PelOffsetB = Vector2f ( 0.0f, 0.0f );
 123.526 +        Shutter.Type = HmdShutter_LAST;
 123.527 +        Shutter.VsyncToNextVsync = 0.0f;
 123.528 +        Shutter.VsyncToFirstScanline = 0.0f;
 123.529 +        Shutter.FirstScanlineToLastScanline = 0.0f;
 123.530 +        Shutter.PixelSettleTime = 0.0f;
 123.531 +        Shutter.PixelPersistence = 0.0f;
 123.532 +        EyeCups = EyeCup_DK1A;
 123.533 +        EyeLeft.ReliefInMeters = 0.0f;
 123.534 +        EyeLeft.NoseToPupilInMeters = 0.0f;
 123.535 +        EyeLeft.Distortion.SetToIdentity();
 123.536 +        EyeRight = EyeLeft;
 123.537 +    }
 123.538 +
 123.539 +    // The "center eye" is the position the HMD tracking returns,
 123.540 +    // and games will also usually use it for audio, aiming reticles, some line-of-sight tests, etc.
 123.541 +    EyeConfig GetEyeCenter() const
 123.542 +    {
 123.543 +        EyeConfig result;
 123.544 +        result.ReliefInMeters = 0.5f * ( EyeLeft.ReliefInMeters + EyeRight.ReliefInMeters );
 123.545 +        result.NoseToPupilInMeters = 0.0f;
 123.546 +        result.Distortion.SetToIdentity();
 123.547 +        return result;
 123.548 +    }
 123.549 +
 123.550 +};
 123.551 +
 123.552 +
 123.553 +//-----------------------------------------------------------------------------------
 123.554 +
 123.555 +// Stateless computation functions, in somewhat recommended execution order.
 123.556 +// For examples on how to use many of them, see the StereoConfig::UpdateComputedState function.
 123.557 +
 123.558 +const float OVR_DEFAULT_EXTRA_EYE_ROTATION = 30.0f * MATH_FLOAT_DEGREETORADFACTOR;
 123.559 +
 123.560 +// Creates a dummy debug HMDInfo matching a particular HMD model.
 123.561 +// Useful for development without an actual HMD attached.
 123.562 +HMDInfo             CreateDebugHMDInfo(HmdTypeEnum hmdType);
 123.563 +
 123.564 +
 123.565 +// profile may be NULL, in which case it uses the hard-coded defaults.
 123.566 +// distortionType should be left at the default unless you require something specific for your distortion shaders.
 123.567 +// eyeCupOverride can be EyeCup_LAST, in which case it uses the one in the profile.
 123.568 +HmdRenderInfo       GenerateHmdRenderInfoFromHmdInfo ( HMDInfo const &hmdInfo,
 123.569 +                                                       Profile const *profile = NULL,
 123.570 +                                                       DistortionEqnType distortionType = Distortion_CatmullRom10,
 123.571 +                                                       EyeCupType eyeCupOverride = EyeCup_LAST );
 123.572 +
 123.573 +LensConfig          GenerateLensConfigFromEyeRelief ( float eyeReliefInMeters, HmdRenderInfo const &hmd,
 123.574 +                                                      DistortionEqnType distortionType = Distortion_CatmullRom10 );
 123.575 +
 123.576 +DistortionRenderDesc CalculateDistortionRenderDesc ( StereoEye eyeType, HmdRenderInfo const &hmd,
 123.577 +                                                     LensConfig const *pLensOverride = NULL );
 123.578 +
 123.579 +FovPort             CalculateFovFromEyePosition ( float eyeReliefInMeters,
 123.580 +                                                  float offsetToRightInMeters,
 123.581 +                                                  float offsetDownwardsInMeters,
 123.582 +                                                  float lensDiameterInMeters,
 123.583 +                                                  float extraEyeRotationInRadians = OVR_DEFAULT_EXTRA_EYE_ROTATION);
 123.584 +
 123.585 +FovPort             CalculateFovFromHmdInfo ( StereoEye eyeType,
 123.586 +                                              DistortionRenderDesc const &distortion,
 123.587 +                                              HmdRenderInfo const &hmd,
 123.588 +                                              float extraEyeRotationInRadians = OVR_DEFAULT_EXTRA_EYE_ROTATION );
 123.589 +
 123.590 +FovPort             GetPhysicalScreenFov ( StereoEye eyeType, DistortionRenderDesc const &distortion );
 123.591 +
 123.592 +FovPort             ClampToPhysicalScreenFov ( StereoEye eyeType, DistortionRenderDesc const &distortion,
 123.593 +                                               FovPort inputFovPort );
 123.594 +
 123.595 +Sizei               CalculateIdealPixelSize ( StereoEye eyeType, DistortionRenderDesc const &distortion,
 123.596 +                                              FovPort fov, float pixelsPerDisplayPixel );
 123.597 +
 123.598 +Recti               GetFramebufferViewport ( StereoEye eyeType, HmdRenderInfo const &hmd );
 123.599 +
 123.600 +Matrix4f            CreateProjection ( bool rightHanded, FovPort fov,
 123.601 +                                       float zNear = 0.01f, float zFar = 10000.0f );
 123.602 +
 123.603 +Matrix4f            CreateOrthoSubProjection ( bool rightHanded, StereoEye eyeType,
 123.604 +                                               float tanHalfFovX, float tanHalfFovY,
 123.605 +                                               float unitsX, float unitsY, float distanceFromCamera,
 123.606 +                                               float interpupillaryDistance, Matrix4f const &projection,
 123.607 +                                               float zNear = 0.0f, float zFar = 0.0f );
 123.608 +
 123.609 +ScaleAndOffset2D    CreateNDCScaleAndOffsetFromFov ( FovPort fov );
 123.610 +
 123.611 +ScaleAndOffset2D    CreateUVScaleAndOffsetfromNDCScaleandOffset ( ScaleAndOffset2D scaleAndOffsetNDC,
 123.612 +                                                                  Recti renderedViewport,
 123.613 +                                                                  Sizei renderTargetSize );
 123.614 +
 123.615 +
 123.616 +//-----------------------------------------------------------------------------------
 123.617 +// ***** StereoEyeParams
 123.618 +
 123.619 +// StereoEyeParams describes RenderDevice configuration needed to render
 123.620 +// the scene for one eye. 
 123.621 +struct StereoEyeParams
 123.622 +{
 123.623 +    StereoEye               Eye;
 123.624 +    Matrix4f                HmdToEyeViewOffset;         // Translation to be applied to view matrix.
 123.625 +
 123.626 +    // Distortion and the VP on the physical display - the thing to run the distortion shader on.
 123.627 +    DistortionRenderDesc    Distortion;
 123.628 +    Recti                   DistortionViewport;
 123.629 +
 123.630 +    // Projection and VP of a particular view (you could have multiple of these).
 123.631 +    Recti                   RenderedViewport;       // Viewport that we render the standard scene to.
 123.632 +    FovPort                 Fov;                    // The FOVs of this scene.
 123.633 +    Matrix4f                RenderedProjection;     // Projection matrix used with this eye.
 123.634 +    ScaleAndOffset2D        EyeToSourceNDC;         // Mapping from TanEyeAngle space to [-1,+1] on the rendered image.
 123.635 +    ScaleAndOffset2D        EyeToSourceUV;          // Mapping from TanEyeAngle space to actual texture UV coords.
 123.636 +};
 123.637 +
 123.638 +
 123.639 +//-----------------------------------------------------------------------------------
 123.640 +// A set of "forward-mapping" functions, mapping from framebuffer space to real-world and/or texture space.
 123.641 +Vector2f TransformScreenNDCToTanFovSpace ( DistortionRenderDesc const &distortion,
 123.642 +                                           const Vector2f &framebufferNDC );
 123.643 +void TransformScreenNDCToTanFovSpaceChroma ( Vector2f *resultR, Vector2f *resultG, Vector2f *resultB, 
 123.644 +                                             DistortionRenderDesc const &distortion,
 123.645 +                                             const Vector2f &framebufferNDC );
 123.646 +Vector2f TransformTanFovSpaceToRendertargetTexUV ( ScaleAndOffset2D const &eyeToSourceUV,
 123.647 +                                                   Vector2f const &tanEyeAngle );
 123.648 +Vector2f TransformTanFovSpaceToRendertargetNDC ( ScaleAndOffset2D const &eyeToSourceNDC,
 123.649 +                                                 Vector2f const &tanEyeAngle );
 123.650 +Vector2f TransformScreenPixelToScreenNDC( Recti const &distortionViewport,
 123.651 +                                          Vector2f const &pixel );
 123.652 +Vector2f TransformScreenPixelToTanFovSpace ( Recti const &distortionViewport,
 123.653 +                                             DistortionRenderDesc const &distortion,
 123.654 +                                             Vector2f const &pixel );
 123.655 +Vector2f TransformScreenNDCToRendertargetTexUV( DistortionRenderDesc const &distortion,
 123.656 +                                                StereoEyeParams const &eyeParams,
 123.657 +                                                Vector2f const &pixel );
 123.658 +Vector2f TransformScreenPixelToRendertargetTexUV( Recti const &distortionViewport,
 123.659 +                                                  DistortionRenderDesc const &distortion,
 123.660 +                                                  StereoEyeParams const &eyeParams,
 123.661 +                                                  Vector2f const &pixel );
 123.662 +
 123.663 +// A set of "reverse-mapping" functions, mapping from real-world and/or texture space back to the framebuffer.
 123.664 +// Be aware that many of these are significantly slower than their forward-mapping counterparts.
 123.665 +Vector2f TransformTanFovSpaceToScreenNDC( DistortionRenderDesc const &distortion,
 123.666 +                                          const Vector2f &tanEyeAngle, bool usePolyApprox = false );
 123.667 +Vector2f TransformRendertargetNDCToTanFovSpace( const ScaleAndOffset2D &eyeToSourceNDC,
 123.668 +                                                const Vector2f &textureNDC );
 123.669 +
 123.670 +// Handy wrappers.
 123.671 +inline Vector2f TransformTanFovSpaceToRendertargetTexUV ( StereoEyeParams const &eyeParams,
 123.672 +                                                          Vector2f const &tanEyeAngle )
 123.673 +{
 123.674 +    return TransformTanFovSpaceToRendertargetTexUV ( eyeParams.EyeToSourceUV, tanEyeAngle );
 123.675 +}
 123.676 +inline Vector2f TransformTanFovSpaceToRendertargetNDC ( StereoEyeParams const &eyeParams,
 123.677 +                                                        Vector2f const &tanEyeAngle )
 123.678 +{
 123.679 +    return TransformTanFovSpaceToRendertargetNDC ( eyeParams.EyeToSourceNDC, tanEyeAngle );
 123.680 +}
 123.681 +
 123.682 +} //namespace OVR
 123.683 +
 123.684 +#endif // OVR_Stereo_h
   124.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   124.2 +++ b/LibOVR/Src/Sensors/OVR_DeviceConstants.h	Wed Jan 14 06:51:16 2015 +0200
   124.3 @@ -0,0 +1,184 @@
   124.4 +/************************************************************************************
   124.5 +
   124.6 +Filename    :   OVR_DeviceConstants.h
   124.7 +Content     :   Device constants
   124.8 +Created     :   February 5, 2013
   124.9 +Authors     :   Lee Cooper
  124.10 +
  124.11 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
  124.12 +
  124.13 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
  124.14 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
  124.15 +which is provided at the time of installation or download, or which 
  124.16 +otherwise accompanies this software in either electronic or hard copy form.
  124.17 +
  124.18 +You may obtain a copy of the License at
  124.19 +
  124.20 +http://www.oculusvr.com/licenses/LICENSE-3.2 
  124.21 +
  124.22 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
  124.23 +distributed under the License is distributed on an "AS IS" BASIS,
  124.24 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  124.25 +See the License for the specific language governing permissions and
  124.26 +limitations under the License.
  124.27 +
  124.28 +*************************************************************************************/
  124.29 +
  124.30 +#ifndef OVR_DeviceConstants_h
  124.31 +#define OVR_DeviceConstants_h
  124.32 +
  124.33 +#include "../Kernel/OVR_Math.h"
  124.34 +
  124.35 +// CAPI forward declarations.
  124.36 +struct ovrSensorData_;
  124.37 +typedef struct ovrSensorData_ ovrSensorData;
  124.38 +
  124.39 +namespace OVR {
  124.40 +
  124.41 +
  124.42 +//-------------------------------------------------------------------------------------
  124.43 +// Different device types supported by OVR; this type is reported by DeviceBase::GetType.
  124.44 +// 
  124.45 +enum DeviceType
  124.46 +{
  124.47 +    Device_None,
  124.48 +    Device_Manager,
  124.49 +    Device_Sensor,
  124.50 +    Device_LatencyTester,
  124.51 +    Device_BootLoader,
  124.52 +    Device_All              = 0xFF // Set for enumeration only, to enumerate all device types.
  124.53 +};
  124.54 +
  124.55 +
  124.56 +
  124.57 +//-------------------------------------------------------------------------------------
  124.58 +// Different lens distortion types supported by devices.
  124.59 +// 
  124.60 +enum DistortionEqnType
  124.61 +{
  124.62 +    Distortion_No_Override  = -1,    
  124.63 +	// These two are leagcy and deprecated.
  124.64 +    Distortion_Poly4        = 0,    // scale = (K0 + K1*r^2 + K2*r^4 + K3*r^6)
  124.65 +    Distortion_RecipPoly4   = 1,    // scale = 1/(K0 + K1*r^2 + K2*r^4 + K3*r^6)
  124.66 +
  124.67 +    // CatmullRom10 is the preferred distortion format.
  124.68 +    Distortion_CatmullRom10 = 2,    // scale = Catmull-Rom spline through points (1.0, K[1]...K[9])
  124.69 +
  124.70 +    Distortion_LAST                 // For ease of enumeration.
  124.71 +};
  124.72 +
  124.73 +
  124.74 +//-------------------------------------------------------------------------------------
  124.75 +// HMD types.
  124.76 +//
  124.77 +enum HmdTypeEnum
  124.78 +{
  124.79 +    HmdType_None,
  124.80 +
  124.81 +    HmdType_DKProto,            // First duct-tape model, never sold.
  124.82 +    HmdType_DK1,                // DevKit1 - on sale to developers.
  124.83 +    HmdType_DKHDProto,          // DKHD - shown at various shows, never sold.
  124.84 +    HmdType_DKHD2Proto,         // DKHD2, 5.85-inch panel, never sold.
  124.85 +    HmdType_DKHDProto566Mi,     // DKHD, 5.66-inch panel, never sold.
  124.86 +    HmdType_CrystalCoveProto,   // Crystal Cove, 5.66-inch panel, shown at shows but never sold.
  124.87 +    HmdType_DK2,
  124.88 +
  124.89 +    // Reminder - this header file is public - codenames only!
  124.90 +
  124.91 +    HmdType_Unknown,            // Used for unnamed HW lab experiments.
  124.92 +
  124.93 +    HmdType_LAST
  124.94 +};
  124.95 +
  124.96 +
  124.97 +//-------------------------------------------------------------------------------------
  124.98 +// HMD shutter types.
  124.99 +//
 124.100 +enum HmdShutterTypeEnum
 124.101 +{
 124.102 +    HmdShutter_Global,
 124.103 +    HmdShutter_RollingTopToBottom,
 124.104 +    HmdShutter_RollingLeftToRight,
 124.105 +    HmdShutter_RollingRightToLeft,
 124.106 +    // TODO:
 124.107 +    // color-sequential e.g. LCOS?
 124.108 +    // alternate eyes?
 124.109 +    // alternate columns?
 124.110 +    // outside-in?
 124.111 +
 124.112 +    HmdShutter_LAST
 124.113 +};
 124.114 +
 124.115 +
 124.116 +
 124.117 +//-------------------------------------------------------------------------------------
 124.118 +// For headsets that use eye cups
 124.119 +//
 124.120 +enum EyeCupType
 124.121 +{
 124.122 +    // Public lenses
 124.123 +    EyeCup_DK1A = 0,
 124.124 +    EyeCup_DK1B = 1,
 124.125 +    EyeCup_DK1C = 2,
 124.126 +
 124.127 +    EyeCup_DK2A = 3,
 124.128 +
 124.129 +    // Internal R&D codenames.
 124.130 +    // Reminder - this header file is public - codenames only!
 124.131 +    EyeCup_DKHD2A,
 124.132 +    EyeCup_OrangeA,
 124.133 +    EyeCup_RedA,
 124.134 +    EyeCup_PinkA,
 124.135 +    EyeCup_BlueA,
 124.136 +    EyeCup_Delilah1A,
 124.137 +    EyeCup_Delilah2A,
 124.138 +    EyeCup_JamesA,
 124.139 +    EyeCup_SunMandalaA,
 124.140 +
 124.141 +    EyeCup_LAST
 124.142 +};
 124.143 +
 124.144 +
 124.145 +//-----------------------------------------------------------------------------
 124.146 +// BodyFrameState
 124.147 +//
 124.148 +#pragma pack(push, 8)
 124.149 +
 124.150 +class SensorDataType
 124.151 +{
 124.152 +public:
 124.153 +
 124.154 +    SensorDataType() : Temperature(0.0f), AbsoluteTimeSeconds(0.0) { }
 124.155 +
 124.156 +    // C-interop support
 124.157 +    SensorDataType(const ovrSensorData& s);
 124.158 +    operator ovrSensorData () const;
 124.159 +
 124.160 +    Vector3f Acceleration;     // in m/s^2
 124.161 +    Vector3f RotationRate;     // in rad/s
 124.162 +    Vector3f MagneticField;    // in Gauss
 124.163 +
 124.164 +    float    Temperature;      // in degrees Celsius
 124.165 +
 124.166 +    // The absolute time from the host computers perspective that the message should be
 124.167 +    // interpreted as. This is based on incoming timestamp and processed by a filter
 124.168 +    // that syncs the clocks while attempting to keep the distance between messages
 124.169 +    // device clock matching.
 124.170 +    //
 124.171 +    // Integration should use TimeDelta, but prediction into the future should derive
 124.172 +    // the delta time from PredictToSeconds - AbsoluteTimeSeconds.
 124.173 +    //
 124.174 +    // This value will generally be <= the return from a call to ovr_GetTimeInSeconds(),
 124.175 +    // but could be greater by under 1 ms due to system time update interrupt delays.
 124.176 +    //
 124.177 +    double   AbsoluteTimeSeconds;
 124.178 +};
 124.179 +
 124.180 +static_assert((sizeof(SensorDataType) == 3*sizeof(Vector3f) + sizeof(float) + sizeof(double)), "sizeof(SensorDataType) failure");
 124.181 +
 124.182 +#pragma pack(pop)
 124.183 +
 124.184 +
 124.185 +} // namespace OVR
 124.186 +
 124.187 +#endif
   125.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   125.2 +++ b/LibOVR/Src/Service/Service_NetClient.cpp	Wed Jan 14 06:51:16 2015 +0200
   125.3 @@ -0,0 +1,882 @@
   125.4 +/************************************************************************************
   125.5 +
   125.6 +Filename    :   Service_NetClient.cpp
   125.7 +Content     :   Client for service interface
   125.8 +Created     :   June 12, 2014
   125.9 +Authors     :   Michael Antonov, Kevin Jenkins, Chris Taylor
  125.10 +
  125.11 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
  125.12 +
  125.13 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
  125.14 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
  125.15 +which is provided at the time of installation or download, or which 
  125.16 +otherwise accompanies this software in either electronic or hard copy form.
  125.17 +
  125.18 +You may obtain a copy of the License at
  125.19 +
  125.20 +http://www.oculusvr.com/licenses/LICENSE-3.2 
  125.21 +
  125.22 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
  125.23 +distributed under the License is distributed on an "AS IS" BASIS,
  125.24 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  125.25 +See the License for the specific language governing permissions and
  125.26 +limitations under the License.
  125.27 +
  125.28 +************************************************************************************/
  125.29 +
  125.30 +#include "Service_NetClient.h"
  125.31 +#include "../Net/OVR_MessageIDTypes.h"
  125.32 +
  125.33 +#if defined (OVR_OS_MAC) || defined(OVR_OS_LINUX)
  125.34 +#define GetCurrentProcessId getpid
  125.35 +#endif
  125.36 +OVR_DEFINE_SINGLETON(OVR::Service::NetClient);
  125.37 +
  125.38 +namespace OVR { namespace Service {
  125.39 +
  125.40 +using namespace OVR::Net;
  125.41 +
  125.42 +
  125.43 +//// NetClient
  125.44 +
  125.45 +NetClient::NetClient() :
  125.46 +    LatencyTesterAvailable(false),
  125.47 +    HMDCount(0),
  125.48 +    EdgeTriggeredHMDCount(false)
  125.49 +{
  125.50 +    GetSession()->AddSessionListener(this);
  125.51 +
  125.52 +    // Register RPC functions
  125.53 +    registerRPC();
  125.54 +
  125.55 +    Start();
  125.56 +
  125.57 +	// Must be at end of function
  125.58 +    PushDestroyCallbacks();
  125.59 +}
  125.60 +
  125.61 +NetClient::~NetClient()
  125.62 +{
  125.63 +}
  125.64 +
  125.65 +void NetClient::OnSystemDestroy()
  125.66 +{
  125.67 +    onSystemDestroy();
  125.68 +}
  125.69 +
  125.70 +void NetClient::OnThreadDestroy()
  125.71 +{
  125.72 +    onThreadDestroy();
  125.73 +}
  125.74 +
  125.75 +int NetClient::Run()
  125.76 +{
  125.77 +    SetThreadName("NetClient");
  125.78 +
  125.79 +    while (!Terminated)
  125.80 +    {
  125.81 +        // Note: There is no watchdog here because the watchdog is part of the private code
  125.82 +
  125.83 +        GetSession()->Poll(false);
  125.84 +
  125.85 +        if (GetSession()->GetActiveSocketsCount() == 0)
  125.86 +        {
  125.87 +            Thread::MSleep(10);
  125.88 +        }
  125.89 +    }
  125.90 +
  125.91 +    return 0;
  125.92 +}
  125.93 +
  125.94 +void NetClient::OnReceive(ReceivePayload* pPayload, ListenerReceiveResult* lrrOut)
  125.95 +{
  125.96 +    OVR_UNUSED(lrrOut);
  125.97 +    OVR_UNUSED(pPayload);
  125.98 +}
  125.99 +
 125.100 +void NetClient::OnDisconnected(Connection* conn)
 125.101 +{
 125.102 +    OVR_UNUSED(conn);
 125.103 +
 125.104 +    OVR_DEBUG_LOG(("[NetClient] Disconnected"));
 125.105 +
 125.106 +    EdgeTriggeredHMDCount = false;
 125.107 +}
 125.108 +
 125.109 +void NetClient::OnConnected(Connection* conn)
 125.110 +{
 125.111 +    OVR_UNUSED(conn);
 125.112 +
 125.113 +    OVR_DEBUG_LOG(("[NetClient] Connected to a server running version %d.%d.%d (my version=%d.%d.%d)",
 125.114 +        conn->RemoteMajorVersion, conn->RemoteMinorVersion, conn->RemotePatchVersion,
 125.115 +        RPCVersion_Major, RPCVersion_Minor, RPCVersion_Patch));
 125.116 +
 125.117 +    EdgeTriggeredHMDCount = false;
 125.118 +}
 125.119 +
 125.120 +bool NetClient::Connect(bool blocking)
 125.121 +{
 125.122 +    // Set up bind parameters
 125.123 +	OVR::Net::BerkleyBindParameters bbp;
 125.124 +	bbp.Address = "::1"; // Bind to localhost only!
 125.125 +    bbp.blockingTimeout = 5000;
 125.126 +	OVR::Net::SockAddr sa;
 125.127 +	sa.Set("::1", VRServicePort, SOCK_STREAM);
 125.128 +
 125.129 +    // Attempt to connect
 125.130 +    OVR::Net::SessionResult result = GetSession()->ConnectPTCP(&bbp, &sa, blocking);
 125.131 +
 125.132 +    // Already connected counts as success too
 125.133 +    return result == Net::SessionResult_OK ||
 125.134 +           result == Net::SessionResult_AlreadyConnected ||
 125.135 +           result == Net::SessionResult_ConnectInProgress;
 125.136 +}
 125.137 +
 125.138 +void NetClient::Disconnect()
 125.139 +{
 125.140 +    GetSession()->Shutdown();
 125.141 +}
 125.142 +
 125.143 +bool NetClient::IsConnected(bool attemptReconnect, bool blockOnReconnect)
 125.144 +{
 125.145 +    // If it was able to connect,
 125.146 +    if (GetSession()->GetConnectionCount() > 0)
 125.147 +    {
 125.148 +        return true;
 125.149 +    }
 125.150 +    else if (attemptReconnect)
 125.151 +    {
 125.152 +        // Attempt to connect here
 125.153 +        Connect(blockOnReconnect);
 125.154 +
 125.155 +        // If it connected,
 125.156 +        if (GetSession()->GetConnectionCount() > 0)
 125.157 +        {
 125.158 +            return true;
 125.159 +        }
 125.160 +    }
 125.161 +
 125.162 +    // No connections
 125.163 +    return false;
 125.164 +}
 125.165 +
 125.166 +void NetClient::GetLocalProtocolVersion(int& major, int& minor, int& patch)
 125.167 +{
 125.168 +    major = RPCVersion_Major;
 125.169 +    minor = RPCVersion_Minor;
 125.170 +    patch = RPCVersion_Patch;
 125.171 +}
 125.172 +
 125.173 +bool NetClient::GetRemoteProtocolVersion(int& major, int& minor, int& patch)
 125.174 +{
 125.175 +    Ptr<Connection> conn = GetSession()->GetConnectionAtIndex(0);
 125.176 +
 125.177 +    if (conn)
 125.178 +    {
 125.179 +        major = conn->RemoteMajorVersion;
 125.180 +        minor = conn->RemoteMinorVersion;
 125.181 +        patch = conn->RemotePatchVersion;
 125.182 +        return true;
 125.183 +    }
 125.184 +
 125.185 +    return false;
 125.186 +}
 125.187 +
 125.188 +
 125.189 +//// NetClient API
 125.190 +
 125.191 +const char* NetClient::GetStringValue(VirtualHmdId hmd, const char* key, const char* default_val)
 125.192 +{
 125.193 +    if (!IsConnected(true, true))
 125.194 +    {
 125.195 +        return "";
 125.196 +    }
 125.197 +
 125.198 +	// If a null value is provided,
 125.199 +	if (!default_val)
 125.200 +	{
 125.201 +		default_val = "";
 125.202 +	}
 125.203 +
 125.204 +    ProfileGetValue1_Str = default_val;
 125.205 +
 125.206 +    OVR::Net::BitStream bsOut, returnData;
 125.207 +    bsOut.Write(hmd);
 125.208 +    bsOut.Write(key);
 125.209 +    bsOut.Write(default_val);
 125.210 +    if (!GetRPC1()->CallBlocking("GetStringValue_1", &bsOut, GetSession()->GetConnectionAtIndex(0), &returnData))
 125.211 +    {
 125.212 +		return "";
 125.213 +    }
 125.214 +    if (!returnData.Read(ProfileGetValue1_Str))
 125.215 +    {
 125.216 +        OVR_ASSERT(false);
 125.217 +    }
 125.218 +    return ProfileGetValue1_Str.ToCStr();
 125.219 +}
 125.220 +bool NetClient::GetBoolValue(VirtualHmdId hmd, const char* key, bool default_val)
 125.221 +{
 125.222 +    if (!IsConnected(true, true))
 125.223 +    {
 125.224 +        return default_val;
 125.225 +    }
 125.226 +
 125.227 +    OVR::Net::BitStream bsOut, returnData;
 125.228 +    bsOut.Write(hmd);
 125.229 +    bsOut.Write(key);
 125.230 +    bsOut.Write(default_val);
 125.231 +    if (!GetRPC1()->CallBlocking("GetBoolValue_1", &bsOut, GetSession()->GetConnectionAtIndex(0), &returnData))
 125.232 +    {
 125.233 +		return default_val;
 125.234 +    }
 125.235 +    uint8_t out = 0;
 125.236 +    if (!returnData.Read(out))
 125.237 +    {
 125.238 +        OVR_ASSERT(false);
 125.239 +    }
 125.240 +    return out != 0;
 125.241 +}
 125.242 +int NetClient::GetIntValue(VirtualHmdId hmd, const char* key, int default_val)
 125.243 +{
 125.244 +    if (!IsConnected(true, true))
 125.245 +    {
 125.246 +        return default_val;
 125.247 +    }
 125.248 +
 125.249 +    OVR::Net::BitStream bsOut, returnData;
 125.250 +    bsOut.Write(hmd);
 125.251 +    bsOut.Write(key);
 125.252 +    bsOut.Write(default_val);
 125.253 +    if (!GetRPC1()->CallBlocking("GetIntValue_1", &bsOut, GetSession()->GetConnectionAtIndex(0), &returnData))
 125.254 +    {
 125.255 +		return default_val;
 125.256 +    }
 125.257 +    int32_t out = (int32_t)default_val;
 125.258 +    if (!returnData.Read(out))
 125.259 +    {
 125.260 +        OVR_ASSERT(false);
 125.261 +    }
 125.262 +    return out;
 125.263 +}
 125.264 +double NetClient::GetNumberValue(VirtualHmdId hmd, const char* key, double default_val)
 125.265 +{
 125.266 +    if (!IsConnected(true, true))
 125.267 +    {
 125.268 +        return default_val;
 125.269 +    }
 125.270 +
 125.271 +    OVR::Net::BitStream bsOut, returnData;
 125.272 +    bsOut.Write(hmd);
 125.273 +    bsOut.Write(key);
 125.274 +    bsOut.Write(default_val);
 125.275 +    if (!GetRPC1()->CallBlocking("GetNumberValue_1", &bsOut, GetSession()->GetConnectionAtIndex(0), &returnData))
 125.276 +    {
 125.277 +		return default_val;
 125.278 +    }
 125.279 +    double out = 0.;
 125.280 +    returnData.Read(out);
 125.281 +    return out;
 125.282 +}
 125.283 +int NetClient::GetNumberValues(VirtualHmdId hmd, const char* key, double* values, int num_vals)
 125.284 +{
 125.285 +    if (!IsConnected(true, true))
 125.286 +    {
 125.287 +        return 0;
 125.288 +    }
 125.289 +
 125.290 +    OVR::Net::BitStream bsOut, returnData;
 125.291 +    bsOut.Write(hmd);
 125.292 +    bsOut.Write(key);
 125.293 +
 125.294 +    int32_t w = (int32_t)num_vals;
 125.295 +    bsOut.Write(w);
 125.296 +
 125.297 +    if (!GetRPC1()->CallBlocking("GetNumberValues_1", &bsOut, GetSession()->GetConnectionAtIndex(0), &returnData))
 125.298 +    {
 125.299 +		return 0;
 125.300 +    }
 125.301 +
 125.302 +    int32_t out = 0;
 125.303 +    if (!returnData.Read(out))
 125.304 +    {
 125.305 +        OVR_ASSERT(false);
 125.306 +    }
 125.307 +    OVR_ASSERT(out >= 0 && out <= num_vals);
 125.308 +    if (out < 0)
 125.309 +    {
 125.310 +        out = 0;
 125.311 +    }
 125.312 +    else if (out > num_vals)
 125.313 +    {
 125.314 +        out = num_vals;
 125.315 +    }
 125.316 +
 125.317 +    for (int i = 0; i < out && i < num_vals; i++)
 125.318 +    {
 125.319 +        if (!returnData.Read(values[i]))
 125.320 +        {
 125.321 +            return i;
 125.322 +        }
 125.323 +    }
 125.324 +
 125.325 +    return out;
 125.326 +}
 125.327 +
 125.328 +bool NetClient::SetStringValue(VirtualHmdId hmd, const char* key, const char* val)
 125.329 +{
 125.330 +    if (!IsConnected(true, true))
 125.331 +    {
 125.332 +        return false;
 125.333 +    }
 125.334 +
 125.335 +    OVR::Net::BitStream bsOut;
 125.336 +    bsOut.Write(hmd);
 125.337 +    bsOut.Write(key);
 125.338 +
 125.339 +    bsOut.Write(val);
 125.340 +
 125.341 +    if (!GetRPC1()->Signal("SetStringValue_1", &bsOut, GetSession()->GetConnectionAtIndex(0)))
 125.342 +    {
 125.343 +        return false;
 125.344 +    }
 125.345 +
 125.346 +    return true;
 125.347 +}
 125.348 +
 125.349 +bool NetClient::SetBoolValue(VirtualHmdId hmd, const char* key, bool val)
 125.350 +{
 125.351 +    if (!IsConnected(true, true))
 125.352 +    {
 125.353 +        return false;
 125.354 +    }
 125.355 +
 125.356 +    OVR::Net::BitStream bsOut;
 125.357 +    bsOut.Write(hmd);
 125.358 +    bsOut.Write(key);
 125.359 +
 125.360 +    uint8_t b = val ? 1 : 0;
 125.361 +    bsOut.Write(b);
 125.362 +
 125.363 +    if (!GetRPC1()->Signal("SetBoolValue_1", &bsOut, GetSession()->GetConnectionAtIndex(0)))
 125.364 +    {
 125.365 +        return false;
 125.366 +    }
 125.367 +
 125.368 +    return true;
 125.369 +}
 125.370 +
 125.371 +bool NetClient::SetIntValue(VirtualHmdId hmd, const char* key, int val)
 125.372 +{
 125.373 +    if (!IsConnected(true, true))
 125.374 +    {
 125.375 +        return false;
 125.376 +    }
 125.377 +
 125.378 +    OVR::Net::BitStream bsOut;
 125.379 +    bsOut.Write(hmd);
 125.380 +    bsOut.Write(key);
 125.381 +
 125.382 +    int32_t w = (int32_t)val;
 125.383 +    bsOut.Write(w);
 125.384 +
 125.385 +    if (!GetRPC1()->Signal("SetIntValue_1", &bsOut, GetSession()->GetConnectionAtIndex(0)))
 125.386 +    {
 125.387 +        return false;
 125.388 +    }
 125.389 +
 125.390 +    return true;
 125.391 +}
 125.392 +
 125.393 +bool NetClient::SetNumberValue(VirtualHmdId hmd, const char* key, double val)
 125.394 +{
 125.395 +    if (!IsConnected(true, true))
 125.396 +    {
 125.397 +        return false;
 125.398 +    }
 125.399 +
 125.400 +    OVR::Net::BitStream bsOut;
 125.401 +    bsOut.Write(hmd);
 125.402 +    bsOut.Write(key);
 125.403 +
 125.404 +    bsOut.Write(val);
 125.405 +
 125.406 +    if (!GetRPC1()->Signal("SetNumberValue_1", &bsOut, GetSession()->GetConnectionAtIndex(0)))
 125.407 +    {
 125.408 +        return false;
 125.409 +    }
 125.410 +
 125.411 +    return true;
 125.412 +}
 125.413 +
 125.414 +bool NetClient::SetNumberValues(VirtualHmdId hmd, const char* key, const double* vals, int num_vals)
 125.415 +{
 125.416 +    if (!IsConnected(true, true))
 125.417 +    {
 125.418 +        return false;
 125.419 +    }
 125.420 +
 125.421 +    OVR::Net::BitStream bsOut;
 125.422 +    bsOut.Write(hmd);
 125.423 +    bsOut.Write(key);
 125.424 +
 125.425 +    int32_t w_count = (int32_t)num_vals;
 125.426 +    bsOut.Write(w_count);
 125.427 +
 125.428 +    for (int i = 0; i < num_vals; i++)
 125.429 +    {
 125.430 +        bsOut.Write(vals[i]);
 125.431 +    }
 125.432 +
 125.433 +    if (!GetRPC1()->Signal("SetNumberValues_1", &bsOut, GetSession()->GetConnectionAtIndex(0)))
 125.434 +    {
 125.435 +        return false;
 125.436 +    }
 125.437 +
 125.438 +    return true;
 125.439 +}
 125.440 +
 125.441 +int NetClient::Hmd_Detect()
 125.442 +{
 125.443 +    if (!IsConnected(true, false))
 125.444 +    {
 125.445 +        return 0;
 125.446 +    }
 125.447 +
 125.448 +    // If using edge-triggered HMD counting,
 125.449 +    if (EdgeTriggeredHMDCount)
 125.450 +    {
 125.451 +        // Return the last update from the server
 125.452 +        return HMDCount;
 125.453 +    }
 125.454 +
 125.455 +    // Otherwise: We need to ask the first time
 125.456 +
 125.457 +	OVR::Net::BitStream bsOut, returnData;
 125.458 +
 125.459 +	if (!GetRPC1()->CallBlocking("Hmd_Detect_1", &bsOut, GetSession()->GetConnectionAtIndex(0), &returnData))
 125.460 +	{
 125.461 +		return 0;
 125.462 +	}
 125.463 +
 125.464 +    int32_t out = 0;
 125.465 +    if (!returnData.Read(out))
 125.466 +    {
 125.467 +        OVR_ASSERT(false);
 125.468 +    }
 125.469 +    HMDCount = out;
 125.470 +    EdgeTriggeredHMDCount = true;
 125.471 +	return out;
 125.472 +}
 125.473 +
 125.474 +bool NetClient::Hmd_Create(int index, HMDNetworkInfo* netInfo)
 125.475 +{
 125.476 +    if (!IsConnected(true, true))
 125.477 +    {
 125.478 +        return false;
 125.479 +    }
 125.480 +
 125.481 +	OVR::Net::BitStream bsOut, returnData;
 125.482 +
 125.483 +    int32_t w = (int32_t)index;
 125.484 +	bsOut.Write(w);
 125.485 +
 125.486 +    // Need the Pid for driver mode
 125.487 +    pid_t pid = GetCurrentProcessId();
 125.488 +    bsOut.Write(pid);
 125.489 +
 125.490 +	if (!GetRPC1()->CallBlocking("Hmd_Create_1", &bsOut, GetSession()->GetConnectionAtIndex(0), &returnData))
 125.491 +	{
 125.492 +		return false;
 125.493 +	}
 125.494 +
 125.495 +	return netInfo->Deserialize(&returnData);
 125.496 +}
 125.497 +
 125.498 +bool NetClient::GetDriverMode(bool& driverInstalled, bool& compatMode, bool& hideDK1Mode)
 125.499 +{
 125.500 +    if (!IsConnected(true, true))
 125.501 +    {
 125.502 +        return false;
 125.503 +    }
 125.504 +
 125.505 +    OVR::Net::BitStream bsOut, returnData;
 125.506 +
 125.507 +    bsOut.Write(InvalidVirtualHmdId);
 125.508 +
 125.509 +    if (!GetRPC1()->CallBlocking("GetDriverMode_1", &bsOut, GetSession()->GetConnectionAtIndex(0), &returnData))
 125.510 +    {
 125.511 +        return false;
 125.512 +    }
 125.513 +
 125.514 +    int32_t w_driverInstalled = 0;
 125.515 +    int32_t w_compatMode = 0;
 125.516 +    int32_t w_hideDK1Mode = 0;
 125.517 +    returnData.Read(w_driverInstalled);
 125.518 +    returnData.Read(w_compatMode);
 125.519 +    if (!returnData.Read(w_hideDK1Mode))
 125.520 +    {
 125.521 +        return false;
 125.522 +    }
 125.523 +
 125.524 +    driverInstalled = w_driverInstalled != 0;
 125.525 +    compatMode = w_compatMode != 0;
 125.526 +    hideDK1Mode = w_hideDK1Mode != 0;
 125.527 +    return true;
 125.528 +}
 125.529 +
 125.530 +bool NetClient::SetDriverMode(bool compatMode, bool hideDK1Mode)
 125.531 +{
 125.532 +    if (!IsConnected(true, true))
 125.533 +    {
 125.534 +        return false;
 125.535 +    }
 125.536 +
 125.537 +    OVR::Net::BitStream bsOut, returnData;
 125.538 +
 125.539 +    bsOut.Write(InvalidVirtualHmdId);
 125.540 +
 125.541 +    int32_t w_compatMode, w_hideDK1Mode;
 125.542 +    w_compatMode = compatMode ? 1 : 0;
 125.543 +    w_hideDK1Mode = hideDK1Mode ? 1 : 0;
 125.544 +    bsOut.Write(w_compatMode);
 125.545 +    bsOut.Write(w_hideDK1Mode);
 125.546 +
 125.547 +    if (!GetRPC1()->CallBlocking("SetDriverMode_1", &bsOut, GetSession()->GetConnectionAtIndex(0), &returnData))
 125.548 +    {
 125.549 +        return false;
 125.550 +    }
 125.551 +
 125.552 +    int32_t out = 0;
 125.553 +    if (!returnData.Read(out))
 125.554 +    {
 125.555 +        OVR_ASSERT(false);
 125.556 +        return false;
 125.557 +    }
 125.558 +
 125.559 +    return out != 0;
 125.560 +}
 125.561 +
 125.562 +bool NetClient::Hmd_AttachToWindow(VirtualHmdId hmd, void* hWindow)
 125.563 +{
 125.564 +    if (!IsConnected(false, false))
 125.565 +    {
 125.566 +        return false;
 125.567 +    }
 125.568 +
 125.569 +    OVR::Net::BitStream bsOut;
 125.570 +    bsOut.Write(hmd);
 125.571 +
 125.572 +    #ifdef OVR_OS_LINUX
 125.573 +    if (hWindow == NULL)
 125.574 +    {
 125.575 +        return false;
 125.576 +    }
 125.577 +    unsigned long hWinWord = *(unsigned long *)hWindow;
 125.578 +    #else
 125.579 +    UInt64 hWinWord = (UPInt)hWindow;
 125.580 +    #endif
 125.581 +    bsOut.Write(hWinWord);
 125.582 +
 125.583 +    if (!GetRPC1()->CallBlocking("Hmd_AttachToWindow_1", &bsOut, GetSession()->GetConnectionAtIndex(0)))
 125.584 +    {
 125.585 +        return false;
 125.586 +    }
 125.587 +
 125.588 +    return true;
 125.589 +}
 125.590 +
 125.591 +void NetClient::Hmd_Release(VirtualHmdId hmd)
 125.592 +{
 125.593 +    if (!IsConnected(false, false))
 125.594 +    {
 125.595 +        return;
 125.596 +    }
 125.597 +
 125.598 +	OVR::Net::BitStream bsOut;
 125.599 +	bsOut.Write(hmd);
 125.600 +	bool result = GetRPC1()->CallBlocking("Hmd_Release_1", &bsOut, GetSession()->GetConnectionAtIndex(0));
 125.601 +    OVR_ASSERT_AND_UNUSED(result, result);
 125.602 +}
 125.603 +
 125.604 +void NetClient::SetLastError(String str)
 125.605 +{
 125.606 +    Hmd_GetLastError_Str = str;
 125.607 +}
 125.608 +
 125.609 +// Last string is cached locally.
 125.610 +const char* NetClient::Hmd_GetLastError(VirtualHmdId hmd)
 125.611 +{
 125.612 +    if (hmd == InvalidVirtualHmdId || !IsConnected(false, false))
 125.613 +    {
 125.614 +        return Hmd_GetLastError_Str.ToCStr();
 125.615 +    }
 125.616 +
 125.617 +    OVR::Net::BitStream bsOut, returnData;
 125.618 +	bsOut.Write(hmd);
 125.619 +    if (!GetRPC1()->CallBlocking("Hmd_GetLastError_1", &bsOut, GetSession()->GetConnectionAtIndex(0), &returnData))
 125.620 +	{
 125.621 +		return Hmd_GetLastError_Str.ToCStr();
 125.622 +	}
 125.623 +    if (!returnData.Read(Hmd_GetLastError_Str))
 125.624 +    {
 125.625 +        OVR_ASSERT(false);
 125.626 +    }
 125.627 +	return Hmd_GetLastError_Str.ToCStr();
 125.628 +}
 125.629 +
 125.630 +
 125.631 +// Fills in description about HMD; this is the same as filled in by ovrHmd_Create.
 125.632 +// The actual descriptor is a par
 125.633 +bool NetClient::Hmd_GetHmdInfo(VirtualHmdId hmd, HMDInfo* hmdInfo)
 125.634 +{
 125.635 +    if (!IsConnected(false, false))
 125.636 +    {
 125.637 +        return false;
 125.638 +    }
 125.639 +
 125.640 +	OVR::Net::BitStream bsOut, returnData;
 125.641 +	bsOut.Write(hmd);
 125.642 +	if (!GetRPC1()->CallBlocking("Hmd_GetHmdInfo_1", &bsOut, GetSession()->GetConnectionAtIndex(0), &returnData))
 125.643 +	{
 125.644 +		return false;
 125.645 +	}
 125.646 +
 125.647 +    return NetSessionCommon::DeserializeHMDInfo(&returnData, hmdInfo);
 125.648 +}
 125.649 +
 125.650 +
 125.651 +//-------------------------------------------------------------------------------------
 125.652 +unsigned int NetClient::Hmd_GetEnabledCaps(VirtualHmdId hmd)
 125.653 +{
 125.654 +    if (!IsConnected(false, false))
 125.655 +    {
 125.656 +        return 0;
 125.657 +    }
 125.658 +
 125.659 +	OVR::Net::BitStream bsOut, returnData;
 125.660 +	bsOut.Write(hmd);
 125.661 +	if (!GetRPC1()->CallBlocking("Hmd_GetEnabledCaps_1", &bsOut, GetSession()->GetConnectionAtIndex(0), &returnData))
 125.662 +	{
 125.663 +		return 0;
 125.664 +	}
 125.665 +
 125.666 +    uint32_t c = 0;
 125.667 +    if (!returnData.Read(c))
 125.668 +    {
 125.669 +        OVR_ASSERT(false);
 125.670 +    }
 125.671 +	return c;
 125.672 +}
 125.673 +
 125.674 +// Returns new caps after modification
 125.675 +unsigned int NetClient::Hmd_SetEnabledCaps(VirtualHmdId hmd, unsigned int hmdCaps)
 125.676 +{
 125.677 +    if (!IsConnected(false, false))
 125.678 +    {
 125.679 +        return 0;
 125.680 +    }
 125.681 +
 125.682 +	OVR::Net::BitStream bsOut, returnData;
 125.683 +	bsOut.Write(hmd);
 125.684 +
 125.685 +    uint32_t c = (uint32_t)hmdCaps;
 125.686 +	bsOut.Write(c);
 125.687 +
 125.688 +	if (!GetRPC1()->CallBlocking("Hmd_SetEnabledCaps_1", &bsOut, GetSession()->GetConnectionAtIndex(0), &returnData))
 125.689 +	{
 125.690 +		return 0;
 125.691 +	}
 125.692 +
 125.693 +    c = 0;
 125.694 +    if (!returnData.Read(c))
 125.695 +    {
 125.696 +        OVR_ASSERT(false);
 125.697 +    }
 125.698 +    return c;
 125.699 +}
 125.700 +
 125.701 +
 125.702 +//-------------------------------------------------------------------------------------
 125.703 +// *** Tracking Setup
 125.704 +
 125.705 +bool NetClient::Hmd_ConfigureTracking(VirtualHmdId hmd, unsigned supportedCaps, unsigned requiredCaps)
 125.706 +{
 125.707 +    if (!IsConnected(false, false))
 125.708 +    {
 125.709 +        return false;
 125.710 +    }
 125.711 +
 125.712 +	OVR::Net::BitStream bsOut, returnData;
 125.713 +	bsOut.Write(hmd);
 125.714 +
 125.715 +    uint32_t w_sc = supportedCaps;
 125.716 +    bsOut.Write(w_sc);
 125.717 +    uint32_t w_rc = requiredCaps;
 125.718 +    bsOut.Write(w_rc);
 125.719 +
 125.720 +	if (!GetRPC1()->CallBlocking("Hmd_ConfigureTracking_1", &bsOut, GetSession()->GetConnectionAtIndex(0), &returnData))
 125.721 +	{
 125.722 +		return false;
 125.723 +	}
 125.724 +
 125.725 +    uint8_t b;
 125.726 +    if (!returnData.Read(b))
 125.727 +    {
 125.728 +        OVR_ASSERT(false);
 125.729 +    }
 125.730 +
 125.731 +	return b != 0;
 125.732 +}
 125.733 +
 125.734 +
 125.735 +void NetClient::Hmd_ResetTracking(VirtualHmdId hmd)
 125.736 +{
 125.737 +    if (!IsConnected(false, false))
 125.738 +    {
 125.739 +        return;
 125.740 +    }
 125.741 +
 125.742 +	OVR::Net::BitStream bsOut;
 125.743 +	bsOut.Write(hmd);
 125.744 +	if (!GetRPC1()->CallBlocking("Hmd_ResetTracking_1", &bsOut, GetSession()->GetConnectionAtIndex(0)))
 125.745 +	{
 125.746 +		return;
 125.747 +	}
 125.748 +}
 125.749 +
 125.750 +bool NetClient::LatencyUtil_ProcessInputs(double startTestSeconds, unsigned char rgbColorOut[3])
 125.751 +{
 125.752 +    if (!IsConnected(false, false))
 125.753 +    {
 125.754 +        return false;
 125.755 +    }
 125.756 +
 125.757 +    if (!LatencyTesterAvailable)
 125.758 +    {
 125.759 +        return false;
 125.760 +    }
 125.761 +
 125.762 +    OVR::Net::BitStream bsOut, returnData;
 125.763 +    bsOut.Write(startTestSeconds);
 125.764 +    if (!GetRPC1()->CallBlocking("LatencyUtil_ProcessInputs_1", &bsOut, GetSession()->GetConnectionAtIndex(0), &returnData))
 125.765 +    {
 125.766 +        return false;
 125.767 +    }
 125.768 +
 125.769 +    uint8_t u;
 125.770 +    returnData.Read(u);
 125.771 +    rgbColorOut[0] = u;
 125.772 +    returnData.Read(u);
 125.773 +    rgbColorOut[1] = u;
 125.774 +    if (!returnData.Read(u))
 125.775 +    {
 125.776 +        return false;
 125.777 +    }
 125.778 +    rgbColorOut[2] = u;
 125.779 +
 125.780 +    return true;
 125.781 +}
 125.782 +
 125.783 +const char* NetClient::LatencyUtil_GetResultsString()
 125.784 +{
 125.785 +    if (!IsConnected(false, false))
 125.786 +    {
 125.787 +        return NULL;
 125.788 +    }
 125.789 +
 125.790 +    OVR::Net::BitStream bsOut, returnData;
 125.791 +    if (!GetRPC1()->CallBlocking("LatencyUtil_GetResultsString_1", &bsOut, GetSession()->GetConnectionAtIndex(0), &returnData))
 125.792 +    {
 125.793 +        return NULL;
 125.794 +    }
 125.795 +
 125.796 +    if (!returnData.Read(LatencyUtil_GetResultsString_Str))
 125.797 +    {
 125.798 +        OVR_ASSERT(false);
 125.799 +    }
 125.800 +
 125.801 +    return LatencyUtil_GetResultsString_Str.ToCStr();
 125.802 +}
 125.803 +
 125.804 +bool NetClient::ShutdownServer()
 125.805 +{
 125.806 +    if (!IsConnected(false, false))
 125.807 +    {
 125.808 +        return false;
 125.809 +    }
 125.810 +
 125.811 +    OVR::Net::BitStream bsOut;
 125.812 +    GetRPC1()->BroadcastSignal("Shutdown_1", &bsOut);
 125.813 +
 125.814 +    return true;
 125.815 +}
 125.816 +
 125.817 +
 125.818 +//// Push Notifications:
 125.819 +
 125.820 +void NetClient::registerRPC()
 125.821 +{
 125.822 +#define RPC_REGISTER_SLOT(observerScope, functionName) \
 125.823 +    observerScope.SetHandler(OVR::Net::Plugins::RPCSlot::FromMember<NetClient, &NetClient::functionName>(this)); pRPC->RegisterSlot(OVR_STRINGIZE(functionName), observerScope);
 125.824 +
 125.825 +    // Register RPC functions:
 125.826 +    RPC_REGISTER_SLOT(InitialServerStateScope, InitialServerState_1);
 125.827 +    RPC_REGISTER_SLOT(LatencyTesterAvailableScope, LatencyTesterAvailable_1);
 125.828 +    RPC_REGISTER_SLOT(DefaultLogOutputScope, DefaultLogOutput_1);
 125.829 +    RPC_REGISTER_SLOT(HMDCountUpdateScope, HMDCountUpdate_1);
 125.830 +}
 125.831 +
 125.832 +void NetClient::InitialServerState_1(BitStream* userData, ReceivePayload* pPayload)
 125.833 +{
 125.834 +    LatencyTesterAvailable_1(userData, pPayload);
 125.835 +}
 125.836 +
 125.837 +void NetClient::LatencyTesterAvailable_1(BitStream* userData, ReceivePayload* pPayload)
 125.838 +{
 125.839 +    OVR_UNUSED(pPayload);
 125.840 +
 125.841 +    uint8_t b = 0;
 125.842 +    if (!userData->Read(b))
 125.843 +    {
 125.844 +        OVR_ASSERT(false);
 125.845 +        return;
 125.846 +    }
 125.847 +
 125.848 +    LatencyTesterAvailable = (b != 0);
 125.849 +}
 125.850 +
 125.851 +void NetClient::DefaultLogOutput_1(BitStream* userData, ReceivePayload* pPayload)
 125.852 +{
 125.853 +    OVR_UNUSED(pPayload);
 125.854 +
 125.855 +    String formattedText;
 125.856 +    LogMessageType messageType = Log_Text; // Will normally be overwritten below.
 125.857 +    userData->Read(messageType);
 125.858 +    if (userData->Read(formattedText))
 125.859 +    {
 125.860 +        if (OVR::Log::GetGlobalLog())
 125.861 +        {
 125.862 +            OVR::String logStr = "[From Service] ";
 125.863 +            logStr.AppendString(formattedText);
 125.864 +            OVR::Log::GetGlobalLog()->LogMessage(messageType, "%s", logStr.ToCStr());
 125.865 +        }
 125.866 +    }
 125.867 +}
 125.868 +
 125.869 +void NetClient::HMDCountUpdate_1(BitStream* userData, ReceivePayload* pPayload)
 125.870 +{
 125.871 +    OVR_UNUSED(pPayload);
 125.872 +
 125.873 +    int32_t hmdCount = 0;
 125.874 +    if (!userData->Read(hmdCount))
 125.875 +    {
 125.876 +        OVR_ASSERT(false);
 125.877 +        return;
 125.878 +    }
 125.879 +
 125.880 +    HMDCount = hmdCount;
 125.881 +    EdgeTriggeredHMDCount = true;
 125.882 +}
 125.883 +
 125.884 +
 125.885 +}} // namespace OVR::Service
   126.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   126.2 +++ b/LibOVR/Src/Service/Service_NetClient.h	Wed Jan 14 06:51:16 2015 +0200
   126.3 @@ -0,0 +1,149 @@
   126.4 +/************************************************************************************
   126.5 +
   126.6 +Filename    :   Service_NetClient.h
   126.7 +Content     :   Client for service interface
   126.8 +Created     :   June 12, 2014
   126.9 +Authors     :   Michael Antonov, Kevin Jenkins, Chris Taylor
  126.10 +
  126.11 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
  126.12 +
  126.13 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
  126.14 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
  126.15 +which is provided at the time of installation or download, or which 
  126.16 +otherwise accompanies this software in either electronic or hard copy form.
  126.17 +
  126.18 +You may obtain a copy of the License at
  126.19 +
  126.20 +http://www.oculusvr.com/licenses/LICENSE-3.2 
  126.21 +
  126.22 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
  126.23 +distributed under the License is distributed on an "AS IS" BASIS,
  126.24 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  126.25 +See the License for the specific language governing permissions and
  126.26 +limitations under the License.
  126.27 +
  126.28 +************************************************************************************/
  126.29 +
  126.30 +#ifndef OVR_Service_NetClient_h
  126.31 +#define OVR_Service_NetClient_h
  126.32 +
  126.33 +#include "../Net/OVR_NetworkTypes.h"
  126.34 +#include "Service_NetSessionCommon.h"
  126.35 +#include "../Kernel/OVR_System.h"
  126.36 +#include "../OVR_CAPI.h"
  126.37 +#include "../Util/Util_Render_Stereo.h"
  126.38 +
  126.39 +namespace OVR { namespace Service {
  126.40 +
  126.41 +using namespace OVR::Net;
  126.42 +
  126.43 +
  126.44 +//-------------------------------------------------------------------------------------
  126.45 +// NetClient
  126.46 +
  126.47 +class NetClient : public NetSessionCommon,
  126.48 +                  public Net::Plugins::NetworkPlugin,
  126.49 +                  public SystemSingletonBase<NetClient>
  126.50 +{
  126.51 +    OVR_DECLARE_SINGLETON(NetClient);
  126.52 +    virtual void OnThreadDestroy();
  126.53 +
  126.54 +    // Status
  126.55 +    bool          LatencyTesterAvailable;
  126.56 +    int           HMDCount;
  126.57 +    bool          EdgeTriggeredHMDCount;
  126.58 +
  126.59 +    virtual void OnReceive(Net::ReceivePayload* pPayload, Net::ListenerReceiveResult* lrrOut);
  126.60 +    virtual void OnDisconnected(Net::Connection* conn);
  126.61 +    virtual void OnConnected(Net::Connection* conn);
  126.62 +
  126.63 +    virtual int  Run();
  126.64 +
  126.65 +public:
  126.66 +    bool         Connect(bool blocking);
  126.67 +    bool         IsConnected(bool attemptReconnect, bool blockOnReconnect);
  126.68 +    void         Disconnect();
  126.69 +
  126.70 +    void         GetLocalProtocolVersion(int& major, int& minor, int& patch);
  126.71 +    // This function may fail if it is not connected
  126.72 +    bool         GetRemoteProtocolVersion(int& major, int& minor, int& patch);
  126.73 +
  126.74 +    void         SetLastError(String str);
  126.75 +
  126.76 +public:
  126.77 +    // Persistent key-value storage
  126.78 +    const char*  GetStringValue(VirtualHmdId hmd, const char* key, const char* default_val);
  126.79 +    bool         GetBoolValue(VirtualHmdId hmd, const char* key, bool default_val);
  126.80 +    int          GetIntValue(VirtualHmdId hmd, const char* key, int default_val);
  126.81 +    double       GetNumberValue(VirtualHmdId hmd, const char* key, double default_val);
  126.82 +    int          GetNumberValues(VirtualHmdId hmd, const char* key, double* values, int num_vals);
  126.83 +
  126.84 +    bool         SetStringValue(VirtualHmdId hmd, const char* key, const char* val);
  126.85 +    bool         SetBoolValue(VirtualHmdId hmd, const char* key, bool val);
  126.86 +    bool         SetIntValue(VirtualHmdId hmd, const char* key, int val);
  126.87 +    bool         SetNumberValue(VirtualHmdId hmd, const char* key, double val);
  126.88 +    bool         SetNumberValues(VirtualHmdId hmd, const char* key, const double* vals, int num_vals);
  126.89 +
  126.90 +    bool         GetDriverMode(bool& driverInstalled, bool& compatMode, bool& hideDK1Mode);
  126.91 +    bool         SetDriverMode(bool compatMode, bool hideDK1Mode);
  126.92 +
  126.93 +	int          Hmd_Detect();
  126.94 +	bool         Hmd_Create(int index, HMDNetworkInfo* netInfo);
  126.95 +	void         Hmd_Release(VirtualHmdId hmd);
  126.96 +
  126.97 +	// Last string is cached locally.
  126.98 +	const char*  Hmd_GetLastError(VirtualHmdId hmd);
  126.99 +
 126.100 +	// TBD: Replace with a function to return internal, original HMDInfo?
 126.101 +
 126.102 +	// Fills in description about HMD; this is the same as filled in by ovrHmd_Create.
 126.103 +	// The actual descriptor is a par
 126.104 +	bool         Hmd_GetHmdInfo(VirtualHmdId hmd, HMDInfo* hmdInfo);
 126.105 +
 126.106 +	//-------------------------------------------------------------------------------------
 126.107 +	unsigned int Hmd_GetEnabledCaps(VirtualHmdId hmd);
 126.108 +	// Returns new caps after modification
 126.109 +	unsigned int Hmd_SetEnabledCaps(VirtualHmdId hmd, unsigned int hmdCaps);
 126.110 +
 126.111 +    // Updates driver render target
 126.112 +    bool         Hmd_AttachToWindow(VirtualHmdId hmd, void* hWindow);
 126.113 +
 126.114 +	//-------------------------------------------------------------------------------------
 126.115 +	// *** Tracking Setup
 126.116 +
 126.117 +	bool         Hmd_ConfigureTracking(VirtualHmdId hmd, unsigned supportedCaps, unsigned requiredCaps);	
 126.118 +	void         Hmd_ResetTracking(VirtualHmdId hmd);
 126.119 +
 126.120 +	// TBD: Camera frames
 126.121 +    bool         LatencyUtil_ProcessInputs(double startTestSeconds, unsigned char rgbColorOut[3]);
 126.122 +    const char*  LatencyUtil_GetResultsString();
 126.123 +
 126.124 +    bool         ShutdownServer();
 126.125 +
 126.126 +protected:
 126.127 +    String       Hmd_GetLastError_Str;
 126.128 +    String       LatencyUtil_GetResultsString_Str;
 126.129 +    String       ProfileGetValue1_Str, ProfileGetValue3_Str;
 126.130 +
 126.131 +protected:
 126.132 +    //// Push Notifications:
 126.133 +
 126.134 +    void registerRPC();
 126.135 +
 126.136 +    ObserverScope<Net::Plugins::RPCSlot> InitialServerStateScope;
 126.137 +    void InitialServerState_1(BitStream* userData, ReceivePayload* pPayload);
 126.138 +
 126.139 +    ObserverScope<Net::Plugins::RPCSlot> LatencyTesterAvailableScope;
 126.140 +    void LatencyTesterAvailable_1(BitStream* userData, ReceivePayload* pPayload);
 126.141 +
 126.142 +    ObserverScope<Net::Plugins::RPCSlot> DefaultLogOutputScope;
 126.143 +    void DefaultLogOutput_1(BitStream* userData, ReceivePayload* pPayload);
 126.144 +
 126.145 +    ObserverScope<Net::Plugins::RPCSlot> HMDCountUpdateScope;
 126.146 +    void HMDCountUpdate_1(BitStream* userData, ReceivePayload* pPayload);
 126.147 +};
 126.148 +
 126.149 +
 126.150 +}} // namespace OVR::Service
 126.151 +
 126.152 +#endif // OVR_Service_NetClient_h
   127.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   127.2 +++ b/LibOVR/Src/Service/Service_NetSessionCommon.cpp	Wed Jan 14 06:51:16 2015 +0200
   127.3 @@ -0,0 +1,343 @@
   127.4 +/************************************************************************************
   127.5 +
   127.6 +Filename    :   Service_NetSessionCommon.cpp
   127.7 +Content     :   Server for service interface
   127.8 +Created     :   June 12, 2014
   127.9 +Authors     :   Kevin Jenkins, Chris Taylor
  127.10 +
  127.11 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
  127.12 +
  127.13 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
  127.14 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
  127.15 +which is provided at the time of installation or download, or which 
  127.16 +otherwise accompanies this software in either electronic or hard copy form.
  127.17 +
  127.18 +You may obtain a copy of the License at
  127.19 +
  127.20 +http://www.oculusvr.com/licenses/LICENSE-3.2 
  127.21 +
  127.22 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
  127.23 +distributed under the License is distributed on an "AS IS" BASIS,
  127.24 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  127.25 +See the License for the specific language governing permissions and
  127.26 +limitations under the License.
  127.27 +
  127.28 +************************************************************************************/
  127.29 +
  127.30 +#include "Service_NetSessionCommon.h"
  127.31 +#include "../OVR_Stereo.h"
  127.32 +
  127.33 +namespace OVR { namespace Service {
  127.34 +
  127.35 +
  127.36 +//// NetSessionCommon
  127.37 +
  127.38 +NetSessionCommon::NetSessionCommon() :
  127.39 +    Terminated(false)
  127.40 +{
  127.41 +    pSession = new Net::Session;
  127.42 +    OVR_ASSERT(pSession != NULL);
  127.43 +
  127.44 +    pRPC = new Net::Plugins::RPC1;
  127.45 +    OVR_ASSERT(pRPC != NULL);
  127.46 +
  127.47 +    pSession->AddSessionListener(pRPC);
  127.48 +}
  127.49 +
  127.50 +NetSessionCommon::~NetSessionCommon()
  127.51 +{
  127.52 +    if (pSession)
  127.53 +    {
  127.54 +        delete pSession;
  127.55 +        pSession = NULL;
  127.56 +    }
  127.57 +    if (pRPC)
  127.58 +    {
  127.59 +        delete pRPC;
  127.60 +        pRPC = NULL;
  127.61 +    }
  127.62 +
  127.63 +    Terminated = true;
  127.64 +
  127.65 +    OVR_ASSERT(IsFinished());
  127.66 +}
  127.67 +
  127.68 +void NetSessionCommon::onSystemDestroy()
  127.69 +{
  127.70 +    Terminated = true;
  127.71 +
  127.72 +    Join();
  127.73 +
  127.74 +    Release();
  127.75 +}
  127.76 +
  127.77 +void NetSessionCommon::onThreadDestroy()
  127.78 +{
  127.79 +    Terminated = true;
  127.80 +    if (pSession)
  127.81 +    {
  127.82 +        pSession->Shutdown();
  127.83 +    }
  127.84 +}
  127.85 +
  127.86 +void NetSessionCommon::SerializeHMDInfo(Net::BitStream *bitStream, HMDInfo* hmdInfo)
  127.87 +{
  127.88 +    bitStream->Write(hmdInfo->ProductName);
  127.89 +    bitStream->Write(hmdInfo->Manufacturer);
  127.90 +
  127.91 +    int32_t w = hmdInfo->Version;
  127.92 +    bitStream->Write(w);
  127.93 +
  127.94 +    w = hmdInfo->HmdType;
  127.95 +    bitStream->Write(w);
  127.96 +
  127.97 +    w = hmdInfo->ResolutionInPixels.w;
  127.98 +    bitStream->Write(w);
  127.99 +
 127.100 +    w = hmdInfo->ResolutionInPixels.h;
 127.101 +    bitStream->Write(w);
 127.102 +
 127.103 +    w = hmdInfo->ShimInfo.DeviceNumber;
 127.104 +    bitStream->Write(w);
 127.105 +
 127.106 +    w = hmdInfo->ShimInfo.NativeWidth;
 127.107 +    bitStream->Write(w);
 127.108 +
 127.109 +    w = hmdInfo->ShimInfo.NativeHeight;
 127.110 +    bitStream->Write(w);
 127.111 +
 127.112 +    w = hmdInfo->ShimInfo.Rotation;
 127.113 +    bitStream->Write(w);
 127.114 +
 127.115 +    bitStream->Write(hmdInfo->ScreenSizeInMeters.w);
 127.116 +    bitStream->Write(hmdInfo->ScreenSizeInMeters.h);
 127.117 +    bitStream->Write(hmdInfo->ScreenGapSizeInMeters);
 127.118 +    bitStream->Write(hmdInfo->CenterFromTopInMeters);
 127.119 +    bitStream->Write(hmdInfo->LensSeparationInMeters);
 127.120 +
 127.121 +    w = hmdInfo->DesktopX;
 127.122 +    bitStream->Write(w);
 127.123 +
 127.124 +    w = hmdInfo->DesktopY;
 127.125 +    bitStream->Write(w);
 127.126 +
 127.127 +    w = hmdInfo->Shutter.Type;
 127.128 +    bitStream->Write(w);
 127.129 +
 127.130 +    bitStream->Write(hmdInfo->Shutter.VsyncToNextVsync);
 127.131 +    bitStream->Write(hmdInfo->Shutter.VsyncToFirstScanline);
 127.132 +    bitStream->Write(hmdInfo->Shutter.FirstScanlineToLastScanline);
 127.133 +    bitStream->Write(hmdInfo->Shutter.PixelSettleTime);
 127.134 +    bitStream->Write(hmdInfo->Shutter.PixelPersistence);
 127.135 +    bitStream->Write(hmdInfo->DisplayDeviceName);
 127.136 +
 127.137 +    w = hmdInfo->DisplayId;
 127.138 +    bitStream->Write(w);
 127.139 +
 127.140 +    bitStream->Write(hmdInfo->PrintedSerial);
 127.141 +
 127.142 +    uint8_t b = hmdInfo->InCompatibilityMode ? 1 : 0;
 127.143 +    bitStream->Write(b);
 127.144 +
 127.145 +    w = hmdInfo->VendorId;
 127.146 +    bitStream->Write(w);
 127.147 +
 127.148 +    w = hmdInfo->ProductId;
 127.149 +    bitStream->Write(w);
 127.150 +
 127.151 +    bitStream->Write(hmdInfo->CameraFrustumFarZInMeters);
 127.152 +    bitStream->Write(hmdInfo->CameraFrustumHFovInRadians);
 127.153 +    bitStream->Write(hmdInfo->CameraFrustumNearZInMeters);
 127.154 +    bitStream->Write(hmdInfo->CameraFrustumVFovInRadians);
 127.155 +
 127.156 +    w = hmdInfo->FirmwareMajor;
 127.157 +    bitStream->Write(w);
 127.158 +
 127.159 +    w = hmdInfo->FirmwareMinor;
 127.160 +    bitStream->Write(w);
 127.161 +
 127.162 +    bitStream->Write(hmdInfo->PelOffsetR.x);
 127.163 +    bitStream->Write(hmdInfo->PelOffsetR.y);
 127.164 +    bitStream->Write(hmdInfo->PelOffsetB.x);
 127.165 +    bitStream->Write(hmdInfo->PelOffsetB.y);
 127.166 +
 127.167 +    // Important please read before modifying!
 127.168 +    // ----------------------------------------------------
 127.169 +    // Please add new serialized data to the end, here.
 127.170 +    // Otherwise we will break backwards compatibility
 127.171 +    // and e.g. 0.4.4 runtime will not work with 0.4.3 SDK.
 127.172 +
 127.173 +    // Please also update the DeserializeHMDInfo() function
 127.174 +    // below also and make sure that the members you added
 127.175 +    // are initialized properly in the HMDInfo constructor.
 127.176 +
 127.177 +    // Note that whenever new fields are added here you
 127.178 +    // should also update the minor version of the RPC
 127.179 +    // protocol in OVR_Session.h so that clients fail at
 127.180 +    // a version check instead of when this data is
 127.181 +    // found to be truncated from the server.
 127.182 +}
 127.183 +
 127.184 +bool NetSessionCommon::DeserializeHMDInfo(Net::BitStream *bitStream, HMDInfo* hmdInfo)
 127.185 +{
 127.186 +    bitStream->Read(hmdInfo->ProductName);
 127.187 +    bitStream->Read(hmdInfo->Manufacturer);
 127.188 +
 127.189 +    int32_t w = 0;
 127.190 +    if (!bitStream->Read(w))
 127.191 +    {
 127.192 +        // This indicates that no HMD could be found
 127.193 +        return false;
 127.194 +    }
 127.195 +    hmdInfo->Version = w;
 127.196 +
 127.197 +    bitStream->Read(w);
 127.198 +    hmdInfo->HmdType = (HmdTypeEnum)w;
 127.199 +
 127.200 +    bitStream->Read(w);
 127.201 +    hmdInfo->ResolutionInPixels.w = w;
 127.202 +
 127.203 +    bitStream->Read(w);
 127.204 +    hmdInfo->ResolutionInPixels.h = w;
 127.205 +
 127.206 +    bitStream->Read(w);
 127.207 +    hmdInfo->ShimInfo.DeviceNumber = w;
 127.208 +
 127.209 +    bitStream->Read(w);
 127.210 +    hmdInfo->ShimInfo.NativeWidth = w;
 127.211 +
 127.212 +    bitStream->Read(w);
 127.213 +    hmdInfo->ShimInfo.NativeHeight = w;
 127.214 +
 127.215 +    bitStream->Read(w);
 127.216 +    hmdInfo->ShimInfo.Rotation = w;
 127.217 +
 127.218 +    bitStream->Read(hmdInfo->ScreenSizeInMeters.w);
 127.219 +    bitStream->Read(hmdInfo->ScreenSizeInMeters.h);
 127.220 +    bitStream->Read(hmdInfo->ScreenGapSizeInMeters);
 127.221 +    bitStream->Read(hmdInfo->CenterFromTopInMeters);
 127.222 +    bitStream->Read(hmdInfo->LensSeparationInMeters);
 127.223 +
 127.224 +    bitStream->Read(w);
 127.225 +    hmdInfo->DesktopX = w;
 127.226 +
 127.227 +    bitStream->Read(w);
 127.228 +    hmdInfo->DesktopY = w;
 127.229 +
 127.230 +    bitStream->Read(w);
 127.231 +    hmdInfo->Shutter.Type = (HmdShutterTypeEnum)w;
 127.232 +
 127.233 +    bitStream->Read(hmdInfo->Shutter.VsyncToNextVsync);
 127.234 +    bitStream->Read(hmdInfo->Shutter.VsyncToFirstScanline);
 127.235 +    bitStream->Read(hmdInfo->Shutter.FirstScanlineToLastScanline);
 127.236 +    bitStream->Read(hmdInfo->Shutter.PixelSettleTime);
 127.237 +    bitStream->Read(hmdInfo->Shutter.PixelPersistence);
 127.238 +    bitStream->Read(hmdInfo->DisplayDeviceName);
 127.239 +
 127.240 +    bitStream->Read(w);
 127.241 +    hmdInfo->DisplayId = w;
 127.242 +
 127.243 +    bitStream->Read(hmdInfo->PrintedSerial);
 127.244 +
 127.245 +    uint8_t b = 0;
 127.246 +    bitStream->Read(b);
 127.247 +    hmdInfo->InCompatibilityMode = (b != 0);
 127.248 +
 127.249 +    bitStream->Read(w);
 127.250 +    hmdInfo->VendorId = w;
 127.251 +
 127.252 +    bitStream->Read(w);
 127.253 +    hmdInfo->ProductId = w;
 127.254 +
 127.255 +    bitStream->Read(hmdInfo->CameraFrustumFarZInMeters);
 127.256 +    bitStream->Read(hmdInfo->CameraFrustumHFovInRadians);
 127.257 +    bitStream->Read(hmdInfo->CameraFrustumNearZInMeters);
 127.258 +    bitStream->Read(hmdInfo->CameraFrustumVFovInRadians);
 127.259 +
 127.260 +    bitStream->Read(w);
 127.261 +    hmdInfo->FirmwareMajor = w;
 127.262 +
 127.263 +    if (!bitStream->Read(w))
 127.264 +    {
 127.265 +        OVR_ASSERT(false);
 127.266 +        return false;
 127.267 +    }
 127.268 +    hmdInfo->FirmwareMinor = w;
 127.269 +
 127.270 +    bitStream->Read(hmdInfo->PelOffsetR.x);
 127.271 +    bitStream->Read(hmdInfo->PelOffsetR.y);
 127.272 +    bitStream->Read(hmdInfo->PelOffsetB.x);
 127.273 +    if (!bitStream->Read(hmdInfo->PelOffsetB.y))
 127.274 +    {
 127.275 +        OVR_ASSERT(false);
 127.276 +        return false;
 127.277 +    }
 127.278 +
 127.279 +    // Important please read before modifying!
 127.280 +    // ----------------------------------------------------
 127.281 +    // Please add new serialized data to the end, here.
 127.282 +    // Otherwise we will break backwards compatibility
 127.283 +    // and e.g. 0.4.4 runtime will not work with 0.4.3 SDK.
 127.284 +
 127.285 +    // Be sure to check that the very last one read properly
 127.286 +    // since HMD Info truncation should be caught here.
 127.287 +
 127.288 +    return true;
 127.289 +}
 127.290 +
 127.291 +// Prefix key names with this to pass through to server
 127.292 +static const char* BypassPrefix = "server:";
 127.293 +
 127.294 +static const char* KeyNames[][NetSessionCommon::ENumTypes] = {
 127.295 +    /* EGetStringValue */ { "CameraSerial", "CameraUUID", 0 },
 127.296 +    /* EGetBoolValue */ { "ReleaseDK2Sensors", "ReleaseLegacySensors", 0 },
 127.297 +    /* EGetIntValue */ { 0 },
 127.298 +    /* EGetNumberValue */{ "CenterPupilDepth", "LoggingMask", 0 },
 127.299 +    /* EGetNumberValues */{ "NeckModelVector3f", 0 },
 127.300 +    /* ESetStringValue */ { 0 },
 127.301 +    /* ESetBoolValue */ { "ReleaseDK2Sensors", "ReleaseLegacySensors", 0 },
 127.302 +    /* ESetIntValue */ { 0 },
 127.303 +    /* ESetNumberValue */{ "CenterPupilDepth", "LoggingMask", 0 },
 127.304 +    /* ESetNumberValues */{ "NeckModelVector3f", 0 },
 127.305 +};
 127.306 +
 127.307 +bool IsInStringArray(const char* a[], const char* key)
 127.308 +{
 127.309 +    for (int i = 0; a[i]; ++i)
 127.310 +    {
 127.311 +        if (OVR_strcmp(a[i], key) == 0)
 127.312 +            return true;
 127.313 +    }
 127.314 +
 127.315 +    return false;
 127.316 +}
 127.317 +
 127.318 +const char *NetSessionCommon::FilterKeyPrefix(const char* key)
 127.319 +{
 127.320 +    // If key starts with BypassPrefix,
 127.321 +    if (strstr(key, BypassPrefix) == key)
 127.322 +    {
 127.323 +        key += strlen(BypassPrefix);
 127.324 +    }
 127.325 +
 127.326 +    return key;
 127.327 +}
 127.328 +
 127.329 +bool NetSessionCommon::IsServiceProperty(EGetterSetters e, const char* key)
 127.330 +{
 127.331 +    if ((e >= 0 && e < ENumTypes) && IsInStringArray(KeyNames[e], key))
 127.332 +    {
 127.333 +        return true;
 127.334 +    }
 127.335 +
 127.336 +    // If key starts with BypassPrefix,
 127.337 +    if (strstr(key, BypassPrefix) == key)
 127.338 +    {
 127.339 +        return true;
 127.340 +    }
 127.341 +
 127.342 +    return false;
 127.343 +}
 127.344 +
 127.345 +
 127.346 +}} // namespace OVR::Service
   128.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   128.2 +++ b/LibOVR/Src/Service/Service_NetSessionCommon.h	Wed Jan 14 06:51:16 2015 +0200
   128.3 @@ -0,0 +1,142 @@
   128.4 +/************************************************************************************
   128.5 +
   128.6 +Filename    :   Service_NetSessionCommon.h
   128.7 +Content     :   Shared networking for service
   128.8 +Created     :   June 12, 2014
   128.9 +Authors     :   Kevin Jenkins, Chris Taylor
  128.10 +
  128.11 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
  128.12 +
  128.13 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
  128.14 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
  128.15 +which is provided at the time of installation or download, or which 
  128.16 +otherwise accompanies this software in either electronic or hard copy form.
  128.17 +
  128.18 +You may obtain a copy of the License at
  128.19 +
  128.20 +http://www.oculusvr.com/licenses/LICENSE-3.2 
  128.21 +
  128.22 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
  128.23 +distributed under the License is distributed on an "AS IS" BASIS,
  128.24 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  128.25 +See the License for the specific language governing permissions and
  128.26 +limitations under the License.
  128.27 +
  128.28 +************************************************************************************/
  128.29 +
  128.30 +#ifndef OVR_Service_NetSessionCommon_h
  128.31 +#define OVR_Service_NetSessionCommon_h
  128.32 +
  128.33 +#include "../OVR_CAPI.h"
  128.34 +#include "../Net/OVR_RPC1.h"
  128.35 +#include "../Kernel/OVR_Threads.h"
  128.36 +#include "../Net/OVR_BitStream.h"
  128.37 +#include "../Kernel/OVR_System.h"
  128.38 +
  128.39 +namespace OVR {
  128.40 +
  128.41 +class HMDInfo;
  128.42 +
  128.43 +namespace Service {
  128.44 +
  128.45 +
  128.46 +//-----------------------------------------------------------------------------
  128.47 +// VirtualHmdId
  128.48 +
  128.49 +// This is an identifier that is unique to each VirtualHmd object on the server
  128.50 +// side.  The client side uses this to opaquely reference those objects.
  128.51 +
  128.52 +typedef int32_t VirtualHmdId;
  128.53 +static const int32_t InvalidVirtualHmdId = -1;
  128.54 +
  128.55 +// Localhost-bound TCP port that the service listens on for VR apps
  128.56 +static const int VRServicePort = 30322; // 0x7672 = "vr" little-endian
  128.57 +
  128.58 +// HMDInfo section related to networking
  128.59 +struct HMDNetworkInfo
  128.60 +{
  128.61 +	HMDNetworkInfo() :
  128.62 +		NetId(InvalidVirtualHmdId)
  128.63 +	{
  128.64 +	}
  128.65 +
  128.66 +	// Network identifier for HMD
  128.67 +	VirtualHmdId NetId;
  128.68 +
  128.69 +	// Name of the shared memory object
  128.70 +	String       SharedMemoryName;
  128.71 +
  128.72 +	void Serialize(Net::BitStream* bs)
  128.73 +	{
  128.74 +		bs->Write(NetId);
  128.75 +		bs->Write(SharedMemoryName);
  128.76 +	}
  128.77 +	bool Deserialize(Net::BitStream* bs)
  128.78 +	{
  128.79 +		bs->Read(NetId);
  128.80 +		return bs->Read(SharedMemoryName);
  128.81 +	}
  128.82 +};
  128.83 +
  128.84 +
  128.85 +//-------------------------------------------------------------------------------------
  128.86 +// ***** NetSessionCommon
  128.87 +
  128.88 +// Common part networking session/RPC implementation shared between client and server.
  128.89 +
  128.90 +class NetSessionCommon : public Thread
  128.91 +{
  128.92 +protected:
  128.93 +    virtual void onSystemDestroy();
  128.94 +    virtual void onThreadDestroy();
  128.95 +
  128.96 +public:
  128.97 +    NetSessionCommon();
  128.98 +    virtual ~NetSessionCommon();
  128.99 +
 128.100 +	Net::Plugins::RPC1* GetRPC1() const
 128.101 +    {
 128.102 +        return pRPC;
 128.103 +    }
 128.104 +	Net::Session* GetSession() const
 128.105 +    {
 128.106 +        return pSession;
 128.107 +    }
 128.108 +
 128.109 +	static void SerializeHMDInfo(Net::BitStream* bitStream, HMDInfo* hmdInfo);
 128.110 +	static bool DeserializeHMDInfo(Net::BitStream* bitStream, HMDInfo* hmdInfo);
 128.111 +
 128.112 +public:
 128.113 +    // Getter/setter tools
 128.114 +    enum EGetterSetters
 128.115 +    {
 128.116 +        // Note: If this enumeration changes, then the Servce_NetSessionCommon.cpp
 128.117 +        // IsServiceProperty() function should be updated.
 128.118 +
 128.119 +        EGetStringValue,
 128.120 +        EGetBoolValue,
 128.121 +        EGetIntValue,
 128.122 +        EGetNumberValue,
 128.123 +        EGetNumberValues,
 128.124 +        ESetStringValue,
 128.125 +        ESetBoolValue,
 128.126 +        ESetIntValue,
 128.127 +        ESetNumberValue,
 128.128 +        ESetNumberValues,
 128.129 +
 128.130 +        ENumTypes
 128.131 +    };
 128.132 +
 128.133 +    static const char* FilterKeyPrefix(const char* key);
 128.134 +    static bool IsServiceProperty(EGetterSetters e, const char* key);
 128.135 +
 128.136 +protected:
 128.137 +    bool                Terminated; // Thread termination flag
 128.138 +    Net::Session*       pSession;   // Networking session
 128.139 +	Net::Plugins::RPC1* pRPC;       // Remote procedure calls object
 128.140 +};
 128.141 +
 128.142 +
 128.143 +}} // namespace OVR::Service
 128.144 +
 128.145 +#endif // OVR_Service_NetSessionCommon_h
   129.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   129.2 +++ b/LibOVR/Src/Tracking/Tracking_PoseState.h	Wed Jan 14 06:51:16 2015 +0200
   129.3 @@ -0,0 +1,133 @@
   129.4 +/************************************************************************************
   129.5 +
   129.6 +Filename    :   Tracking_PoseState.h
   129.7 +Content     :   Describes the complete pose at a point in time, including derivatives
   129.8 +Created     :   May 13, 2014
   129.9 +Authors     :   Dov Katz
  129.10 +
  129.11 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
  129.12 +
  129.13 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License");
  129.14 +you may not use the Oculus VR Rift SDK except in compliance with the License,
  129.15 +which is provided at the time of installation or download, or which
  129.16 +otherwise accompanies this software in either electronic or hard copy form.
  129.17 +
  129.18 +You may obtain a copy of the License at
  129.19 +
  129.20 +http://www.oculusvr.com/licenses/LICENSE-3.2
  129.21 +
  129.22 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK
  129.23 +distributed under the License is distributed on an "AS IS" BASIS,
  129.24 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  129.25 +See the License for the specific language governing permissions and
  129.26 +limitations under the License.
  129.27 +
  129.28 +*************************************************************************************/
  129.29 +
  129.30 +#ifndef Tracking_PoseState_h
  129.31 +#define Tracking_PoseState_h
  129.32 +
  129.33 +#include "../Kernel/OVR_Math.h"
  129.34 +
  129.35 +namespace OVR {
  129.36 +
  129.37 +// PoseState describes the complete pose, or a rigid body configuration, at a
  129.38 +// point in time, including first and second derivatives. It is used to specify
  129.39 +// instantaneous location and movement of the headset.
  129.40 +// SensorState is returned as a part of the sensor state.
  129.41 +
  129.42 +template<class T>
  129.43 +class PoseState
  129.44 +{
  129.45 +public:
  129.46 +	typedef typename CompatibleTypes<Pose<T> >::Type CompatibleType;
  129.47 +
  129.48 +	PoseState() : TimeInSeconds(0.0) { }
  129.49 +    PoseState(Pose<T> pose, double time) : ThePose(pose), TimeInSeconds(time) { }
  129.50 +
  129.51 +	// float <-> double conversion constructor.
  129.52 +	explicit PoseState(const PoseState<typename Math<T>::OtherFloatType> &src)
  129.53 +		: ThePose(src.ThePose),
  129.54 +		AngularVelocity(src.AngularVelocity), LinearVelocity(src.LinearVelocity),
  129.55 +		AngularAcceleration(src.AngularAcceleration), LinearAcceleration(src.LinearAcceleration),
  129.56 +		TimeInSeconds(src.TimeInSeconds)
  129.57 +	{ }
  129.58 +
  129.59 +	// C-interop support: PoseStatef <-> ovrPoseStatef
  129.60 +	PoseState(const typename CompatibleTypes<PoseState<T> >::Type& src)
  129.61 +		: ThePose(src.ThePose),
  129.62 +		AngularVelocity(src.AngularVelocity), LinearVelocity(src.LinearVelocity),
  129.63 +		AngularAcceleration(src.AngularAcceleration), LinearAcceleration(src.LinearAcceleration),
  129.64 +		TimeInSeconds(src.TimeInSeconds)
  129.65 +	{ }
  129.66 +
  129.67 +	operator typename CompatibleTypes<PoseState<T> >::Type() const
  129.68 +	{
  129.69 +		typename CompatibleTypes<PoseState<T> >::Type result;
  129.70 +		result.ThePose = ThePose;
  129.71 +		result.AngularVelocity = AngularVelocity;
  129.72 +		result.LinearVelocity = LinearVelocity;
  129.73 +		result.AngularAcceleration = AngularAcceleration;
  129.74 +		result.LinearAcceleration = LinearAcceleration;
  129.75 +		result.TimeInSeconds = TimeInSeconds;
  129.76 +		return result;
  129.77 +	}
  129.78 +
  129.79 +	Pose<T> ThePose;
  129.80 +	Vector3<T>  AngularVelocity;
  129.81 +	Vector3<T>  LinearVelocity;
  129.82 +	Vector3<T>  AngularAcceleration;
  129.83 +	Vector3<T>  LinearAcceleration;
  129.84 +	// Absolute time of this state sample; always a double measured in seconds.
  129.85 +	double      TimeInSeconds;
  129.86 +
  129.87 +	// ***** Helpers for Pose integration
  129.88 +
  129.89 +	// Stores and integrates gyro angular velocity reading for a given time step.
  129.90 +	void StoreAndIntegrateGyro(Vector3d angVel, double dt);
  129.91 +	// Stores and integrates position/velocity from accelerometer reading for a given time step.
  129.92 +	void StoreAndIntegrateAccelerometer(Vector3d linearAccel, double dt);
  129.93 +
  129.94 +	// Performs integration of state by adding next state delta to it
  129.95 +	// to produce a combined state change
  129.96 +	void AdvanceByDelta(const PoseState<T>& delta);
  129.97 +};
  129.98 +
  129.99 +
 129.100 +template<class T>
 129.101 +PoseState<T> operator*(const OVR::Pose<T>& trans, const PoseState<T>& poseState)
 129.102 +{
 129.103 +	PoseState<T> result;
 129.104 +	result.ThePose = trans * poseState.ThePose;
 129.105 +	result.LinearVelocity = trans.Rotate(poseState.LinearVelocity);
 129.106 +	result.LinearAcceleration = trans.Rotate(poseState.LinearAcceleration);
 129.107 +	result.AngularVelocity = trans.Rotate(poseState.AngularVelocity);
 129.108 +	result.AngularAcceleration = trans.Rotate(poseState.AngularAcceleration);
 129.109 +	return result;
 129.110 +}
 129.111 +
 129.112 +
 129.113 +// External API returns pose as float, but uses doubles internally for quaternion precision.
 129.114 +typedef PoseState<float>  PoseStatef;
 129.115 +typedef PoseState<double> PoseStated;
 129.116 +
 129.117 +
 129.118 +} // namespace OVR::Vision
 129.119 +
 129.120 +
 129.121 +namespace OVR {
 129.122 +
 129.123 +	template<> struct CompatibleTypes<OVR::PoseState<float> > { typedef ovrPoseStatef Type; };
 129.124 +	template<> struct CompatibleTypes<OVR::PoseState<double> > { typedef ovrPoseStated Type; };
 129.125 +
 129.126 +    static_assert((sizeof(PoseState<double>) == sizeof(Pose<double>) + 4*sizeof(Vector3<double>) + sizeof(double)), "sizeof(PoseState<double>) failure");
 129.127 +#ifdef OVR_CPU_X86_64
 129.128 +    static_assert((sizeof(PoseState<float>) == sizeof(Pose<float>) + 4*sizeof(Vector3<float>) + sizeof(uint32_t) + sizeof(double)), "sizeof(PoseState<float>) failure"); //TODO: Manually pad template.
 129.129 +#elif defined(OVR_OS_WIN32) // The Windows 32 bit ABI aligns 64 bit values on 64 bit boundaries
 129.130 +    static_assert((sizeof(PoseState<float>) == sizeof(Pose<float>) + 4*sizeof(Vector3<float>) + sizeof(uint32_t) + sizeof(double)), "sizeof(PoseState<float>) failure");
 129.131 +#else // Else Unix/Apple 32 bit ABI, which aligns 64 bit values on 32 bit boundaries.
 129.132 +    static_assert((sizeof(PoseState<float>) == sizeof(Pose<float>) + 4*sizeof(Vector3<float>) +                    sizeof(double)), "sizeof(PoseState<float>) failure");
 129.133 +#endif
 129.134 +}
 129.135 +
 129.136 +#endif // Tracking_PoseState_h
   130.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   130.2 +++ b/LibOVR/Src/Tracking/Tracking_SensorState.h	Wed Jan 14 06:51:16 2015 +0200
   130.3 @@ -0,0 +1,212 @@
   130.4 +/************************************************************************************
   130.5 +
   130.6 +Filename    :   Tracking_SensorState.h
   130.7 +Content     :   Sensor state information shared by tracking system with games
   130.8 +Created     :   May 13, 2014
   130.9 +Authors     :   Dov Katz, Chris Taylor
  130.10 +
  130.11 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
  130.12 +
  130.13 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License");
  130.14 +you may not use the Oculus VR Rift SDK except in compliance with the License,
  130.15 +which is provided at the time of installation or download, or which
  130.16 +otherwise accompanies this software in either electronic or hard copy form.
  130.17 +
  130.18 +You may obtain a copy of the License at
  130.19 +
  130.20 +http://www.oculusvr.com/licenses/LICENSE-3.2
  130.21 +
  130.22 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK
  130.23 +distributed under the License is distributed on an "AS IS" BASIS,
  130.24 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  130.25 +See the License for the specific language governing permissions and
  130.26 +limitations under the License.
  130.27 +
  130.28 +*************************************************************************************/
  130.29 +
  130.30 +#ifndef Tracking_SensorState_h
  130.31 +#define Tracking_SensorState_h
  130.32 +
  130.33 +#include "Tracking_PoseState.h"
  130.34 +#include "../Kernel/OVR_SharedMemory.h"
  130.35 +#include "../Kernel/OVR_Lockless.h"
  130.36 +#include "../Kernel/OVR_String.h"
  130.37 +#include "../Util/Util_LatencyTest2State.h"
  130.38 +#include "../Sensors/OVR_DeviceConstants.h"
  130.39 +
  130.40 +// CAPI forward declarations.
  130.41 +struct ovrTrackingState_;
  130.42 +typedef struct ovrTrackingState_ ovrTrackingState;
  130.43 +struct ovrPoseStatef_;
  130.44 +typedef struct ovrPoseStatef_ ovrPoseStatef;
  130.45 +
  130.46 +namespace OVR { namespace Tracking {
  130.47 +
  130.48 +
  130.49 +//-------------------------------------------------------------------------------------
  130.50 +// ***** Sensor State
  130.51 +// These values are reported as compatible with C API.
  130.52 +
  130.53 +// Bit flags describing the current status of sensor tracking.
  130.54 +enum StatusBits
  130.55 +{
  130.56 +    // Tracked bits: Toggled by SensorFusion
  130.57 +	Status_OrientationTracked = 0x0001, // Orientation is currently tracked (connected and in use)
  130.58 +	Status_PositionTracked    = 0x0002, // Position is currently tracked (false if out of range)
  130.59 +    Status_CameraPoseTracked  = 0x0004, // Camera pose is currently tracked
  130.60 +
  130.61 +    // Connected bits: Toggled by TrackingManager
  130.62 +    Status_PositionConnected  = 0x0020, // Position tracking HW is connected
  130.63 +	Status_HMDConnected       = 0x0080, // HMD is available & connected
  130.64 +
  130.65 +    // Masks
  130.66 +    Status_AllMask = 0xffff,
  130.67 +    Status_TrackingMask = Status_PositionTracked | Status_OrientationTracked | Status_CameraPoseTracked,
  130.68 +    Status_ConnectedMask = Status_PositionConnected | Status_HMDConnected,
  130.69 +};
  130.70 +
  130.71 +
  130.72 +// Full state of of the sensor reported by GetSensorState() at a given absolute time.
  130.73 +class TrackingState
  130.74 +{
  130.75 +public:
  130.76 +	TrackingState() : HeadPose(), CameraPose(), LeveledCameraPose(), RawSensorData(), StatusFlags(0), LastVisionProcessingTime(0.0) { }
  130.77 +
  130.78 +	// C-interop support
  130.79 +	TrackingState(const ovrTrackingState& s);
  130.80 +	operator ovrTrackingState () const;
  130.81 +
  130.82 +	// HMD pose information for the requested time.
  130.83 +	PoseStatef   HeadPose;
  130.84 +
  130.85 +    // Orientation and position of the external camera, if present.
  130.86 +    Posef        CameraPose;
  130.87 +    // Orientation and position of the camera after alignment with gravity 
  130.88 +    Posef        LeveledCameraPose;
  130.89 +
  130.90 +    // Most recent sensor data received from the HMD
  130.91 +    SensorDataType RawSensorData;
  130.92 +
  130.93 +    // Sensor status described by ovrStatusBits.
  130.94 +	uint32_t     StatusFlags;
  130.95 +
  130.96 +    //// 0.4.1
  130.97 +
  130.98 +    // Measures the time from receiving the camera frame until vision CPU processing completes.
  130.99 +    double LastVisionProcessingTime;
 130.100 +
 130.101 +    //// 0.4.3
 130.102 +
 130.103 +    // Measures the time from exposure until the pose is available for the frame, including processing time.
 130.104 +    double LastVisionFrameLatency;
 130.105 +
 130.106 +    // Tag the vision processing results to a certain frame counter number.
 130.107 +    uint32_t LastCameraFrameCounter;
 130.108 +};
 130.109 +
 130.110 +
 130.111 +// -----------------------------------------------
 130.112 +
 130.113 +#pragma pack(push, 8)
 130.114 +
 130.115 +struct LocklessSensorStatePadding;
 130.116 +
 130.117 +// State version stored in lockless updater "queue" and used for 
 130.118 +// prediction by GetPoseAtTime/GetSensorStateAtTime
 130.119 +struct LocklessSensorState
 130.120 +{
 130.121 +	PoseState<double> WorldFromImu;
 130.122 +    SensorDataType    RawSensorData;
 130.123 +    Pose<double>      WorldFromCamera;
 130.124 +	uint32_t          StatusFlags;
 130.125 +    uint32_t          _PAD_0_;
 130.126 +
 130.127 +	// ImuFromCpf for HMD pose tracking
 130.128 +	Posed             ImuFromCpf;
 130.129 +
 130.130 +    // Performance logging
 130.131 +    double            LastVisionProcessingTime;
 130.132 +    double            LastVisionFrameLatency;
 130.133 +    uint32_t          LastCameraFrameCounter;
 130.134 +    uint32_t          _PAD_1_;
 130.135 +
 130.136 +	// Initialized to invalid state
 130.137 +	LocklessSensorState() :
 130.138 +       WorldFromImu()
 130.139 +     , RawSensorData()
 130.140 +     , WorldFromCamera()
 130.141 +	 , StatusFlags(0)
 130.142 +     , _PAD_0_(0) // This assignment should be irrelevant, but it quells static/runtime analysis complaints.
 130.143 +     , ImuFromCpf()
 130.144 +     , LastVisionProcessingTime(0.0)
 130.145 +     , LastVisionFrameLatency(0.0)
 130.146 +     , LastCameraFrameCounter(0)
 130.147 +     , _PAD_1_(0) // "
 130.148 +	{
 130.149 +	}
 130.150 +
 130.151 +    LocklessSensorState& operator = (const LocklessSensorStatePadding& rhs);
 130.152 +};
 130.153 +    
 130.154 +static_assert((sizeof(LocklessSensorState) == sizeof(PoseState<double>) + sizeof(SensorDataType) + sizeof(Pose<double>) + 2*sizeof(uint32_t) + sizeof(Posed) + sizeof(double)*2 + sizeof(uint32_t)*2), "sizeof(LocklessSensorState) failure");
 130.155 +
 130.156 +// Padded out version stored in the updater slots
 130.157 +// Designed to be a larger fixed size to allow the data to grow in the future
 130.158 +// without breaking older compiled code.
 130.159 +struct LocklessSensorStatePadding
 130.160 +{
 130.161 +    uint64_t words[64];
 130.162 +
 130.163 +    static const int DataWords = (sizeof(LocklessSensorState) + sizeof(uint64_t) - 1) / sizeof(uint64_t);
 130.164 +
 130.165 +    // Just copy the low data words
 130.166 +    inline LocklessSensorStatePadding& operator=(const LocklessSensorState& rhs)
 130.167 +    {
 130.168 +        const uint64_t* src = (const uint64_t*)&rhs;
 130.169 +
 130.170 +        // if this fires off, then increase words' array size
 130.171 +        OVR_ASSERT(sizeof(words) > sizeof(LocklessSensorState));
 130.172 +
 130.173 +        for (int i = 0; i < DataWords; ++i)
 130.174 +        {
 130.175 +            words[i] = src[i];
 130.176 +        }
 130.177 +
 130.178 +        return *this;
 130.179 +    }
 130.180 +};
 130.181 +
 130.182 +// Just copy the low data words
 130.183 +inline LocklessSensorState& LocklessSensorState::operator = (const LocklessSensorStatePadding& rhs)
 130.184 +{
 130.185 +    uint64_t* dest = (uint64_t*)this;
 130.186 +
 130.187 +    for (int i = 0; i < LocklessSensorStatePadding::DataWords; ++i)
 130.188 +    {
 130.189 +        dest[i] = rhs.words[i];
 130.190 +    }
 130.191 +
 130.192 +    return *this;
 130.193 +}
 130.194 +
 130.195 +#pragma pack(pop)
 130.196 +
 130.197 +// A lockless updater for sensor state
 130.198 +typedef LocklessUpdater<LocklessSensorState, LocklessSensorStatePadding> SensorStateUpdater;
 130.199 +
 130.200 +
 130.201 +//// Combined state
 130.202 +
 130.203 +struct CombinedSharedStateUpdater
 130.204 +{
 130.205 +    SensorStateUpdater         SharedSensorState;
 130.206 +    Util::LockessRecordUpdater SharedLatencyTestState;
 130.207 +};
 130.208 +
 130.209 +typedef SharedObjectWriter< CombinedSharedStateUpdater > CombinedSharedStateWriter;
 130.210 +typedef SharedObjectReader< CombinedSharedStateUpdater > CombinedSharedStateReader;
 130.211 +
 130.212 +
 130.213 +}} // namespace OVR::Tracking
 130.214 +
 130.215 +#endif
   131.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   131.2 +++ b/LibOVR/Src/Tracking/Tracking_SensorStateReader.cpp	Wed Jan 14 06:51:16 2015 +0200
   131.3 @@ -0,0 +1,207 @@
   131.4 +/************************************************************************************
   131.5 +
   131.6 +Filename    :   Tracking_SensorStateReader.cpp
   131.7 +Content     :   Separate reader component that is able to recover sensor pose
   131.8 +Created     :   June 4, 2014
   131.9 +Authors     :   Chris Taylor
  131.10 +
  131.11 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
  131.12 +
  131.13 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
  131.14 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
  131.15 +which is provided at the time of installation or download, or which 
  131.16 +otherwise accompanies this software in either electronic or hard copy form.
  131.17 +
  131.18 +You may obtain a copy of the License at
  131.19 +
  131.20 +http://www.oculusvr.com/licenses/LICENSE-3.2 
  131.21 +
  131.22 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
  131.23 +distributed under the License is distributed on an "AS IS" BASIS,
  131.24 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  131.25 +See the License for the specific language governing permissions and
  131.26 +limitations under the License.
  131.27 +
  131.28 +*************************************************************************************/
  131.29 +
  131.30 +#include "Tracking_SensorStateReader.h"
  131.31 +#include "Tracking_PoseState.h"
  131.32 +
  131.33 +namespace OVR { namespace Tracking {
  131.34 +
  131.35 +
  131.36 +//-------------------------------------------------------------------------------------
  131.37 +
  131.38 +// This is a "perceptually tuned predictive filter", which means that it is optimized
  131.39 +// for improvements in the VR experience, rather than pure error.  In particular,
  131.40 +// jitter is more perceptible at lower speeds whereas latency is more perceptible
  131.41 +// after a high-speed motion.  Therefore, the prediction interval is dynamically
  131.42 +// adjusted based on speed.  Significant more research is needed to further improve
  131.43 +// this family of filters.
  131.44 +static Pose<double> calcPredictedPose(const PoseState<double>& poseState, double predictionDt)
  131.45 +{
  131.46 +	Pose<double> pose = poseState.ThePose;
  131.47 +	const double linearCoef = 1.0;
  131.48 +	Vector3d angularVelocity = poseState.AngularVelocity;
  131.49 +	double angularSpeed = angularVelocity.Length();
  131.50 +
  131.51 +	// This could be tuned so that linear and angular are combined with different coefficients
  131.52 +	double speed = angularSpeed + linearCoef * poseState.LinearVelocity.Length();
  131.53 +
  131.54 +	const double slope = 0.2; // The rate at which the dynamic prediction interval varies
  131.55 +	double candidateDt = slope * speed; // TODO: Replace with smoothstep function
  131.56 +
  131.57 +	double dynamicDt = predictionDt;
  131.58 +
  131.59 +	// Choose the candidate if it is shorter, to improve stability
  131.60 +	if (candidateDt < predictionDt)
  131.61 +	{
  131.62 +		dynamicDt = candidateDt;
  131.63 +	}
  131.64 +
  131.65 +	if (angularSpeed > 0.001)
  131.66 +	{
  131.67 +		pose.Rotation = pose.Rotation * Quatd(angularVelocity, angularSpeed * dynamicDt);
  131.68 +	}
  131.69 +
  131.70 +	pose.Translation += poseState.LinearVelocity * dynamicDt;
  131.71 +
  131.72 +	return pose;
  131.73 +}
  131.74 +
  131.75 +
  131.76 +//// SensorStateReader
  131.77 +
  131.78 +SensorStateReader::SensorStateReader() :
  131.79 +	Updater(NULL),
  131.80 +    LastLatWarnTime(0.)
  131.81 +{
  131.82 +}
  131.83 +
  131.84 +void SensorStateReader::SetUpdater(const CombinedSharedStateUpdater* updater)
  131.85 +{
  131.86 +	Updater = updater;
  131.87 +}
  131.88 +
  131.89 +void SensorStateReader::RecenterPose()
  131.90 +{
  131.91 +	if (!Updater)
  131.92 +	{
  131.93 +		return;
  131.94 +	}
  131.95 +
  131.96 +	/*
  131.97 +		This resets position to center in x, y, z, and resets yaw to center.
  131.98 +		Other rotation components are not affected.
  131.99 +	*/
 131.100 +
 131.101 +	const LocklessSensorState lstate = Updater->SharedSensorState.GetState();
 131.102 +
 131.103 +	Posed worldFromCpf = lstate.WorldFromImu.ThePose * lstate.ImuFromCpf;
 131.104 +	double hmdYaw, hmdPitch, hmdRoll;
 131.105 +	worldFromCpf.Rotation.GetEulerAngles<Axis_Y, Axis_X, Axis_Z>(&hmdYaw, &hmdPitch, &hmdRoll);
 131.106 +
 131.107 +	Posed worldFromCentered(Quatd(Axis_Y, hmdYaw), worldFromCpf.Translation);
 131.108 +
 131.109 +	CenteredFromWorld = worldFromCentered.Inverted();
 131.110 +}
 131.111 +
 131.112 +bool SensorStateReader::GetSensorStateAtTime(double absoluteTime, TrackingState& ss) const
 131.113 +{
 131.114 +	if (!Updater)
 131.115 +	{
 131.116 +        ss.StatusFlags = 0;
 131.117 +        return false;
 131.118 +	}
 131.119 +
 131.120 +	const LocklessSensorState lstate = Updater->SharedSensorState.GetState();
 131.121 +
 131.122 +    // Update time
 131.123 +	ss.HeadPose.TimeInSeconds = absoluteTime;
 131.124 +
 131.125 +	// Update the status flags
 131.126 +	ss.StatusFlags = lstate.StatusFlags;
 131.127 +	// If no hardware is connected, override the tracking flags
 131.128 +	if (0 == (ss.StatusFlags & Status_HMDConnected))
 131.129 +	{
 131.130 +		ss.StatusFlags &= ~Status_TrackingMask;
 131.131 +	}
 131.132 +	if (0 == (ss.StatusFlags & Status_PositionConnected))
 131.133 +	{
 131.134 +		ss.StatusFlags &= ~(Status_PositionTracked | Status_CameraPoseTracked);
 131.135 +	}
 131.136 +
 131.137 +	// If tracking info is invalid,
 131.138 +    if (0 == (ss.StatusFlags & Status_TrackingMask))
 131.139 +	{
 131.140 +        return false;
 131.141 +	}
 131.142 +    
 131.143 +    // Delta time from the last available data
 131.144 +	double pdt = absoluteTime - lstate.WorldFromImu.TimeInSeconds;
 131.145 +	static const double maxPdt = 0.1;
 131.146 +
 131.147 +	// If delta went negative due to synchronization problems between processes or just a lag spike,
 131.148 +	if (pdt < 0.)
 131.149 +	{
 131.150 +		pdt = 0.;
 131.151 +	}
 131.152 +	else if (pdt > maxPdt)
 131.153 +	{
 131.154 +        if (LastLatWarnTime != lstate.WorldFromImu.TimeInSeconds)
 131.155 +        {
 131.156 +            LastLatWarnTime = lstate.WorldFromImu.TimeInSeconds;
 131.157 +            LogText("[SensorStateReader] Prediction interval too high: %f s, clamping at %f s\n", pdt, maxPdt);
 131.158 +        }
 131.159 +		pdt = maxPdt;
 131.160 +	}
 131.161 +
 131.162 +	ss.HeadPose = PoseStatef(lstate.WorldFromImu);
 131.163 +	// Do prediction logic and ImuFromCpf transformation
 131.164 +	ss.HeadPose.ThePose = Posef(CenteredFromWorld * calcPredictedPose(lstate.WorldFromImu, pdt) * lstate.ImuFromCpf);
 131.165 +
 131.166 +    ss.CameraPose = Posef(CenteredFromWorld * lstate.WorldFromCamera);
 131.167 +
 131.168 +    Posed worldFromLeveledCamera = Posed(Quatd(), lstate.WorldFromCamera.Translation);
 131.169 +    ss.LeveledCameraPose = Posef(CenteredFromWorld * worldFromLeveledCamera);
 131.170 +
 131.171 +    ss.RawSensorData = lstate.RawSensorData;
 131.172 +    ss.LastVisionProcessingTime = lstate.LastVisionProcessingTime;
 131.173 +    ss.LastVisionFrameLatency = lstate.LastVisionFrameLatency;
 131.174 +
 131.175 +	return true;
 131.176 +}
 131.177 +
 131.178 +bool SensorStateReader::GetPoseAtTime(double absoluteTime, Posef& transform) const
 131.179 +{
 131.180 +	TrackingState ss;
 131.181 +	if (!GetSensorStateAtTime(absoluteTime, ss))
 131.182 +	{
 131.183 +		return false;
 131.184 +	}
 131.185 +
 131.186 +	transform = ss.HeadPose.ThePose;
 131.187 +
 131.188 +	return true;
 131.189 +}
 131.190 +
 131.191 +uint32_t SensorStateReader::GetStatus() const
 131.192 +{
 131.193 +	if (!Updater)
 131.194 +	{
 131.195 +		return 0;
 131.196 +	}
 131.197 +
 131.198 +	const LocklessSensorState lstate = Updater->SharedSensorState.GetState();
 131.199 +
 131.200 +	// If invalid,
 131.201 +	if (0 == (lstate.StatusFlags & Status_TrackingMask))
 131.202 +	{
 131.203 +		// Return 0 indicating no orientation nor position tracking
 131.204 +		return 0;
 131.205 +	}
 131.206 +
 131.207 +	return lstate.StatusFlags;
 131.208 +}
 131.209 +
 131.210 +}} // namespace OVR::Tracking
   132.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   132.2 +++ b/LibOVR/Src/Tracking/Tracking_SensorStateReader.h	Wed Jan 14 06:51:16 2015 +0200
   132.3 @@ -0,0 +1,87 @@
   132.4 +/************************************************************************************
   132.5 +
   132.6 +Filename    :   Tracking_SensorStateReader.h
   132.7 +Content     :   Separate reader component that is able to recover sensor pose
   132.8 +Created     :   June 4, 2014
   132.9 +Authors     :   Chris Taylor
  132.10 +
  132.11 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
  132.12 +
  132.13 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
  132.14 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
  132.15 +which is provided at the time of installation or download, or which 
  132.16 +otherwise accompanies this software in either electronic or hard copy form.
  132.17 +
  132.18 +You may obtain a copy of the License at
  132.19 +
  132.20 +http://www.oculusvr.com/licenses/LICENSE-3.2 
  132.21 +
  132.22 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
  132.23 +distributed under the License is distributed on an "AS IS" BASIS,
  132.24 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  132.25 +See the License for the specific language governing permissions and
  132.26 +limitations under the License.
  132.27 +
  132.28 +*************************************************************************************/
  132.29 +
  132.30 +#ifndef Tracking_SensorStateReader_h
  132.31 +#define Tracking_SensorStateReader_h
  132.32 +
  132.33 +#include "../Kernel/OVR_Lockless.h"
  132.34 +#include "Tracking_SensorState.h"
  132.35 +
  132.36 +#include "../OVR_Profile.h"
  132.37 +
  132.38 +namespace OVR { namespace Tracking {
  132.39 +
  132.40 +
  132.41 +//-----------------------------------------------------------------------------
  132.42 +// SensorStateReader
  132.43 +
  132.44 +// User interface to retrieve pose from the sensor fusion subsystem
  132.45 +class SensorStateReader : public NewOverrideBase
  132.46 +{
  132.47 +protected:
  132.48 +	const CombinedSharedStateUpdater *Updater;
  132.49 +
  132.50 +
  132.51 +    // Last latency warning time
  132.52 +    mutable double LastLatWarnTime;
  132.53 +
  132.54 +    // Transform from real-world coordinates to centered coordinates
  132.55 +    Posed CenteredFromWorld; 
  132.56 +
  132.57 +public:
  132.58 +	SensorStateReader();
  132.59 +
  132.60 +	// Initialize the updater
  132.61 +    void         SetUpdater(const CombinedSharedStateUpdater *updater);
  132.62 +
  132.63 +	// Re-centers on the current yaw (optionally pitch) and translation
  132.64 +	void		 RecenterPose();
  132.65 +
  132.66 +	// Get the full dynamical system state of the CPF, which includes velocities and accelerations,
  132.67 +	// predicted at a specified absolute point in time.
  132.68 +	bool		 GetSensorStateAtTime(double absoluteTime, Tracking::TrackingState& state) const;
  132.69 +
  132.70 +	// Get the predicted pose (orientation, position) of the center pupil frame (CPF) at a specific point in time.
  132.71 +	bool		 GetPoseAtTime(double absoluteTime, Posef& transform) const;
  132.72 +
  132.73 +	// Get the sensor status (same as GetSensorStateAtTime(...).Status)
  132.74 +	uint32_t     GetStatus() const;
  132.75 +
  132.76 +    const Posed getCenteredFromWorld()
  132.77 +    {
  132.78 +        return CenteredFromWorld;
  132.79 +    }
  132.80 +
  132.81 +    void setCenteredFromWorld(const Posed _CenteredFromWorld)
  132.82 +    {
  132.83 +        CenteredFromWorld = _CenteredFromWorld;
  132.84 +    }
  132.85 +};
  132.86 +
  132.87 +
  132.88 +}} // namespace OVR::Tracking
  132.89 +
  132.90 +#endif // Tracking_SensorStateReader_h
   133.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   133.2 +++ b/LibOVR/Src/Util/GUIConsole.h	Wed Jan 14 06:51:16 2015 +0200
   133.3 @@ -0,0 +1,51 @@
   133.4 +/************************************************************************************
   133.5 +
   133.6 +Filename    :   GUIConsole.h
   133.7 +Content     :   A stdout console window that runs alongside Windows GUI applications
   133.8 +Created     :   Feb 4, 2013
   133.9 +Authors     :   Brant Lewis
  133.10 +
  133.11 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
  133.12 +
  133.13 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
  133.14 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
  133.15 +which is provided at the time of installation or download, or which 
  133.16 +otherwise accompanies this software in either electronic or hard copy form.
  133.17 +
  133.18 +You may obtain a copy of the License at
  133.19 +
  133.20 +http://www.oculusvr.com/licenses/LICENSE-3.2 
  133.21 +
  133.22 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
  133.23 +distributed under the License is distributed on an "AS IS" BASIS,
  133.24 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  133.25 +See the License for the specific language governing permissions and
  133.26 +limitations under the License.
  133.27 +
  133.28 +*************************************************************************************/
  133.29 +
  133.30 +#ifndef GUICONSOLE_H
  133.31 +#define GUICONSOLE_H
  133.32 +
  133.33 +#include "../../Include/OVR_Kernel.h"
  133.34 +
  133.35 +#ifdef OVR_INTERNAL_USE
  133.36 +
  133.37 +#include <WinSock2.h>
  133.38 +#include <WS2tcpip.h>
  133.39 +#define WIN32_LEAN_AND_MEAN
  133.40 +#include <Windows.h>
  133.41 +
  133.42 +class GUIConsole
  133.43 +{
  133.44 +public:
  133.45 +  // constructors
  133.46 +  GUIConsole();
  133.47 +  ~GUIConsole();
  133.48 +
  133.49 +  // member variables
  133.50 +  HANDLE hStdIn, hStdOut, hStdError;
  133.51 +};
  133.52 +#endif // #ifdef OVR_INTERNAL_USE
  133.53 +
  133.54 +#endif
   134.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   134.2 +++ b/LibOVR/Src/Util/Util_ImageWindow.h	Wed Jan 14 06:51:16 2015 +0200
   134.3 @@ -0,0 +1,204 @@
   134.4 +/************************************************************************************
   134.5 +
   134.6 +Filename    :   Util_ImageWindow.h
   134.7 +Content     :   An output object for windows that can display raw images for testing
   134.8 +Created     :   March 13, 2014
   134.9 +Authors     :   Dean Beeler
  134.10 +
  134.11 +Copyright   :   Copyright 2014 Oculus, Inc. All Rights reserved.
  134.12 +
  134.13 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
  134.14 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
  134.15 +which is provided at the time of installation or download, or which 
  134.16 +otherwise accompanies this software in either electronic or hard copy form.
  134.17 +
  134.18 +You may obtain a copy of the License at
  134.19 +
  134.20 +http://www.oculusvr.com/licenses/LICENSE-3.2 
  134.21 +
  134.22 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
  134.23 +distributed under the License is distributed on an "AS IS" BASIS,
  134.24 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  134.25 +See the License for the specific language governing permissions and
  134.26 +limitations under the License.
  134.27 +
  134.28 +*************************************************************************************/
  134.29 +
  134.30 +#ifndef UTIL_IMAGEWINDOW_H
  134.31 +#define UTIL_IMAGEWINDOW_H
  134.32 +
  134.33 +#if defined(OVR_OS_WIN32)
  134.34 +#include <WinSock2.h>
  134.35 +#include <WS2tcpip.h>
  134.36 +#define WIN32_LEAN_AND_MEAN
  134.37 +#include <Windows.h>
  134.38 +#include <d2d1.h>
  134.39 +#include <dwrite.h>
  134.40 +#endif
  134.41 +
  134.42 +#include "../Kernel/OVR_Hash.h"
  134.43 +#include "../Kernel/OVR_Array.h"
  134.44 +#include "../Kernel/OVR_Threads.h"
  134.45 +#include "../Kernel/OVR_Deque.h"
  134.46 +
  134.47 +#include <stdint.h>
  134.48 +
  134.49 +namespace OVR { namespace Util {
  134.50 +
  134.51 +	typedef struct 
  134.52 +	{
  134.53 +		float x;
  134.54 +		float y;
  134.55 +		float radius;
  134.56 +		float r;
  134.57 +		float g;
  134.58 +		float b;
  134.59 +		bool  fill;
  134.60 +	} CirclePlot;
  134.61 +
  134.62 +	typedef struct  
  134.63 +	{
  134.64 +		float x;
  134.65 +		float y;
  134.66 +		float r;
  134.67 +		float g;
  134.68 +		float b;
  134.69 +	OVR::String text;
  134.70 +	} TextPlot;
  134.71 +
  134.72 +class Frame : virtual public RefCountBaseV<Frame>
  134.73 +	{
  134.74 +public:
  134.75 +
  134.76 +	Frame( int frame ) :
  134.77 +		frameNumber( frame ),
  134.78 +		imageData( NULL ),
  134.79 +		colorImageData( NULL ),
  134.80 +		plots(),
  134.81 +		textLines(),
  134.82 +		width( 0 ),
  134.83 +		height( 0 ),
  134.84 +		colorPitch( 0 ),
  134.85 +		ready( false )
  134.86 +	{
  134.87 +
  134.88 +	}
  134.89 +
  134.90 +	~Frame()
  134.91 +	{
  134.92 +		if( imageData )
  134.93 +			free( imageData );
  134.94 +		if( colorImageData )
  134.95 +			free( colorImageData );
  134.96 +
  134.97 +		plots.ClearAndRelease();
  134.98 +		textLines.ClearAndRelease();
  134.99 +	}
 134.100 +
 134.101 +	int						frameNumber;
 134.102 +
 134.103 +		Array<CirclePlot> plots;
 134.104 +	Array<TextPlot>			textLines;
 134.105 +		void*			  imageData;
 134.106 +		void*			  colorImageData;
 134.107 +		int				  width;
 134.108 +		int				  height;
 134.109 +		int				  colorPitch;
 134.110 +		bool			  ready;
 134.111 +};
 134.112 +
 134.113 +#if defined(OVR_OS_WIN32)
 134.114 +class ImageWindow
 134.115 +{
 134.116 +	HWND hWindow;
 134.117 +	ID2D1RenderTarget* pRT;
 134.118 +	D2D1_SIZE_U resolution;
 134.119 +
 134.120 +	Mutex*						frontBufferMutex;
 134.121 +
 134.122 +	InPlaceMutableDeque< Ptr<Frame> >	frames;
 134.123 +
 134.124 +	ID2D1Bitmap*				greyBitmap;
 134.125 +	ID2D1Bitmap*				colorBitmap;
 134.126 +    
 134.127 +public:
 134.128 +	// constructors
 134.129 +	ImageWindow();
 134.130 +	ImageWindow( uint32_t width, uint32_t height );
 134.131 +	virtual ~ImageWindow();
 134.132 +
 134.133 +	void GetResolution( size_t& width, size_t& height ) { width = resolution.width; height = resolution.height; }
 134.134 +
 134.135 +	void OnPaint(); // Called by Windows when it receives a WM_PAINT message
 134.136 +
 134.137 +	void UpdateImage( const uint8_t* imageData, uint32_t width, uint32_t height ) { UpdateImageBW( imageData, width, height ); }
 134.138 +	void UpdateImageBW( const uint8_t* imageData, uint32_t width, uint32_t height );
 134.139 +	void UpdateImageRGBA( const uint8_t* imageData, uint32_t width, uint32_t height, uint32_t pitch );
 134.140 +	void Complete(); // Called by drawing thread to submit a frame
 134.141 +
 134.142 +	void Process(); // Called by rendering thread to do window processing
 134.143 +
 134.144 +	void AssociateSurface( void* surface );
 134.145 +
 134.146 +	void addCircle( float x , float y, float radius, float r, float g, float b, bool fill );
 134.147 +	void addText( float x, float y, float r, float g, float b, OVR::String text );
 134.148 +
 134.149 +	static ImageWindow*			GlobalWindow( int window ) { return globalWindow[window]; }
 134.150 +	static int					WindowCount() { return windowCount; }
 134.151 +
 134.152 +private:
 134.153 +
 134.154 +	Ptr<Frame>					lastUnreadyFrame();
 134.155 +
 134.156 +	static const int			MaxWindows = 4;
 134.157 +	static ImageWindow*			globalWindow[MaxWindows];
 134.158 +	static int					windowCount;
 134.159 +	static ID2D1Factory*		pD2DFactory;
 134.160 +	static IDWriteFactory*		pDWriteFactory;
 134.161 +	static HINSTANCE            hInstD2d1;
 134.162 +	static HINSTANCE            hInstDwrite;
 134.163 +
 134.164 +};
 134.165 +
 134.166 +#else
 134.167 +
 134.168 +class ImageWindow
 134.169 +{
 134.170 +public:
 134.171 +	// constructors
 134.172 +	ImageWindow() {}
 134.173 +	ImageWindow( uint32_t width, uint32_t height ) { OVR_UNUSED( width ); OVR_UNUSED( height ); }
 134.174 +	virtual ~ImageWindow() { }
 134.175 +
 134.176 +	void GetResolution( size_t& width, size_t& height ) { width = 0; height = 0; }
 134.177 +
 134.178 +	void OnPaint() { }
 134.179 +
 134.180 +	void UpdateImage( const uint8_t* imageData, uint32_t width, uint32_t height ) { UpdateImageBW( imageData, width, height ); }
 134.181 +	void UpdateImageBW( const uint8_t* imageData, uint32_t width, uint32_t height ) { OVR_UNUSED( imageData ); OVR_UNUSED( width ); OVR_UNUSED( height ); }
 134.182 +	void UpdateImageRGBA( const uint8_t* imageData, uint32_t width, uint32_t height, uint32_t pitch ) { OVR_UNUSED( imageData ); OVR_UNUSED( width ); OVR_UNUSED( height ); OVR_UNUSED( pitch ); }
 134.183 +	void Complete() { }
 134.184 +
 134.185 +	void Process() { }
 134.186 +
 134.187 +	void AssociateSurface( void* surface ) { OVR_UNUSED(surface); }
 134.188 +
 134.189 +	void addCircle( float x , float y, float radius, float r, float g, float b, bool fill ) { OVR_UNUSED( x ); OVR_UNUSED( y ); OVR_UNUSED( radius ); OVR_UNUSED( r ); OVR_UNUSED( g ); OVR_UNUSED( b ); OVR_UNUSED( fill ); }
 134.190 +	void addText( float x, float y, float r, float g, float b, OVR::String text ) { OVR_UNUSED( x ); OVR_UNUSED( y ); OVR_UNUSED( r ); OVR_UNUSED( g ); OVR_UNUSED( b ); OVR_UNUSED( text ); }
 134.191 +
 134.192 +	static ImageWindow*			GlobalWindow( int window ) { return globalWindow[window]; }
 134.193 +	static int					WindowCount() { return windowCount; }
 134.194 +
 134.195 +private:
 134.196 +
 134.197 +	static const int			MaxWindows = 4;
 134.198 +	static ImageWindow*			globalWindow[4];
 134.199 +	static int					windowCount;
 134.200 +};
 134.201 +
 134.202 +#endif
 134.203 +
 134.204 +}} // namespace OVR::Util
 134.205 +
 134.206 +
 134.207 +#endif
   135.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   135.2 +++ b/LibOVR/Src/Util/Util_Interface.cpp	Wed Jan 14 06:51:16 2015 +0200
   135.3 @@ -0,0 +1,34 @@
   135.4 +/************************************************************************************
   135.5 +
   135.6 +Filename    :   Util_Interface.cpp
   135.7 +Content     :   Simple interface, utilised by internal demos,
   135.8 +				with access to wider SDK as needed. 
   135.9 +				Located in the body of the SDK to ensure updated
  135.10 +				when new SDK features are added.
  135.11 +Created     :   February 20, 2014
  135.12 +Authors     :   Tom Heath
  135.13 +
  135.14 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
  135.15 +
  135.16 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
  135.17 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
  135.18 +which is provided at the time of installation or download, or which 
  135.19 +otherwise accompanies this software in either electronic or hard copy form.
  135.20 +
  135.21 +You may obtain a copy of the License at
  135.22 +
  135.23 +http://www.oculusvr.com/licenses/LICENSE-3.2 
  135.24 +
  135.25 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
  135.26 +distributed under the License is distributed on an "AS IS" BASIS,
  135.27 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  135.28 +See the License for the specific language governing permissions and
  135.29 +limitations under the License.
  135.30 +
  135.31 +*************************************************************************************/
  135.32 +
  135.33 +#include "Util_Interface.h"
  135.34 +
  135.35 +
  135.36 +
  135.37 +//Files left in to ease its possible return......
   136.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   136.2 +++ b/LibOVR/Src/Util/Util_Interface.h	Wed Jan 14 06:51:16 2015 +0200
   136.3 @@ -0,0 +1,36 @@
   136.4 +/************************************************************************************
   136.5 +
   136.6 +Filename    :   Util_Interface.h
   136.7 +Content     :   Simple interface, utilised by internal demos,
   136.8 +				with access to wider SDK as needed. 
   136.9 +				Located in the body of the SDK to ensure updated
  136.10 +				when new SDK features are added.
  136.11 +Created     :   February 20, 2014
  136.12 +Authors     :   Tom Heath
  136.13 +
  136.14 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
  136.15 +
  136.16 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
  136.17 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
  136.18 +which is provided at the time of installation or download, or which 
  136.19 +otherwise accompanies this software in either electronic or hard copy form.
  136.20 +
  136.21 +You may obtain a copy of the License at
  136.22 +
  136.23 +http://www.oculusvr.com/licenses/LICENSE-3.2 
  136.24 +
  136.25 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
  136.26 +distributed under the License is distributed on an "AS IS" BASIS,
  136.27 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  136.28 +See the License for the specific language governing permissions and
  136.29 +limitations under the License.
  136.30 +
  136.31 +*************************************************************************************/
  136.32 +
  136.33 +#ifndef OVR_Util_Interface_h
  136.34 +#define OVR_Util_Interface_h
  136.35 +#include "../OVR_CAPI.h"
  136.36 +
  136.37 +//Files left in to ease its possible return......
  136.38 +
  136.39 +#endif
   137.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   137.2 +++ b/LibOVR/Src/Util/Util_LatencyTest2Reader.cpp	Wed Jan 14 06:51:16 2015 +0200
   137.3 @@ -0,0 +1,118 @@
   137.4 +/************************************************************************************
   137.5 +
   137.6 +Filename    :   Util_LatencyTest2Reader.cpp
   137.7 +Content     :   Shared functionality for the DK2 latency tester
   137.8 +Created     :   July 8, 2014
   137.9 +Authors     :   Volga Aksoy, Chris Taylor
  137.10 +
  137.11 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
  137.12 +
  137.13 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
  137.14 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
  137.15 +which is provided at the time of installation or download, or which 
  137.16 +otherwise accompanies this software in either electronic or hard copy form.
  137.17 +
  137.18 +You may obtain a copy of the License at
  137.19 +
  137.20 +http://www.oculusvr.com/licenses/LICENSE-3.2 
  137.21 +
  137.22 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
  137.23 +distributed under the License is distributed on an "AS IS" BASIS,
  137.24 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  137.25 +See the License for the specific language governing permissions and
  137.26 +limitations under the License.
  137.27 +
  137.28 +*************************************************************************************/
  137.29 +
  137.30 +#include "Util_LatencyTest2Reader.h"
  137.31 +
  137.32 +namespace OVR { namespace Util {
  137.33 +
  137.34 +
  137.35 +//// FrameTimeRecord
  137.36 +
  137.37 +bool FrameTimeRecord::ColorToReadbackIndex(int *readbackIndex, unsigned char color)
  137.38 +{
  137.39 +    int compareColor = color - LT2_ColorIncrement/2;
  137.40 +    int index        = color / LT2_ColorIncrement;  // Use color without subtraction due to rounding.
  137.41 +    int delta        = compareColor - index * LT2_ColorIncrement;
  137.42 +
  137.43 +    if ((delta < LT2_PixelTestThreshold) && (delta > -LT2_PixelTestThreshold))
  137.44 +    {
  137.45 +        *readbackIndex = index;
  137.46 +        return true;
  137.47 +    }
  137.48 +    return false;
  137.49 +}
  137.50 +
  137.51 +unsigned char FrameTimeRecord::ReadbackIndexToColor(int readbackIndex)
  137.52 +{
  137.53 +    OVR_ASSERT(readbackIndex < LT2_IncrementCount);
  137.54 +    return (unsigned char)(readbackIndex * LT2_ColorIncrement + LT2_ColorIncrement/2);
  137.55 +}
  137.56 +
  137.57 +
  137.58 +//// FrameTimeRecordSet
  137.59 +
  137.60 +FrameTimeRecordSet::FrameTimeRecordSet()
  137.61 +{
  137.62 +    NextWriteIndex = 0;
  137.63 +    memset(this, 0, sizeof(FrameTimeRecordSet));
  137.64 +}
  137.65 +
  137.66 +void FrameTimeRecordSet::AddValue(int readValue, double timeSeconds)
  137.67 +{
  137.68 +    Records[NextWriteIndex].ReadbackIndex = readValue;
  137.69 +    Records[NextWriteIndex].TimeSeconds = timeSeconds;
  137.70 +    NextWriteIndex++;
  137.71 +    if (NextWriteIndex == RecordCount)
  137.72 +        NextWriteIndex = 0;
  137.73 +}
  137.74 +// Matching should be done starting from NextWrite index 
  137.75 +// until wrap-around
  137.76 +
  137.77 +const FrameTimeRecord& FrameTimeRecordSet::operator [] (int i) const
  137.78 +{
  137.79 +    return Records[(NextWriteIndex + i) & RecordMask];
  137.80 +}
  137.81 +
  137.82 +const FrameTimeRecord& FrameTimeRecordSet::GetMostRecentFrame()
  137.83 +{
  137.84 +    return Records[(NextWriteIndex - 1) & RecordMask];
  137.85 +}
  137.86 +
  137.87 +// Advances I to  absolute color index
  137.88 +bool FrameTimeRecordSet::FindReadbackIndex(int* i, int readbackIndex) const
  137.89 +{
  137.90 +    for (; *i < RecordCount; (*i)++)
  137.91 +    {
  137.92 +        if ((*this)[*i].ReadbackIndex == readbackIndex)
  137.93 +            return true;
  137.94 +    }
  137.95 +    return false;
  137.96 +}
  137.97 +
  137.98 +bool FrameTimeRecordSet::IsAllZeroes() const
  137.99 +{
 137.100 +    for (int i = 0; i < RecordCount; i++)
 137.101 +        if (Records[i].ReadbackIndex != 0)
 137.102 +            return false;
 137.103 +    return true;
 137.104 +}
 137.105 +
 137.106 +
 137.107 +//// RecordStateReader
 137.108 +
 137.109 +void RecordStateReader::GetRecordSet(FrameTimeRecordSet& recordset)
 137.110 +{
 137.111 +    if(!Updater)
 137.112 +    {
 137.113 +        return;
 137.114 +    }
 137.115 +        
 137.116 +    recordset = Updater->SharedLatencyTestState.GetState();
 137.117 +    return;
 137.118 +}
 137.119 +
 137.120 +
 137.121 +}} // namespace OVR::Util
   138.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   138.2 +++ b/LibOVR/Src/Util/Util_LatencyTest2Reader.h	Wed Jan 14 06:51:16 2015 +0200
   138.3 @@ -0,0 +1,63 @@
   138.4 +/************************************************************************************
   138.5 +
   138.6 +Filename    :   Util_LatencyTest2Reader.h
   138.7 +Content     :   Shared functionality for the DK2 latency tester
   138.8 +Created     :   July 8, 2014
   138.9 +Authors     :   Volga Aksoy, Chris Taylor
  138.10 +
  138.11 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
  138.12 +
  138.13 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
  138.14 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
  138.15 +which is provided at the time of installation or download, or which 
  138.16 +otherwise accompanies this software in either electronic or hard copy form.
  138.17 +
  138.18 +You may obtain a copy of the License at
  138.19 +
  138.20 +http://www.oculusvr.com/licenses/LICENSE-3.2 
  138.21 +
  138.22 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
  138.23 +distributed under the License is distributed on an "AS IS" BASIS,
  138.24 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  138.25 +See the License for the specific language governing permissions and
  138.26 +limitations under the License.
  138.27 +
  138.28 +*************************************************************************************/
  138.29 +
  138.30 +#ifndef OVR_Util_LatencyTest2Reader_h
  138.31 +#define OVR_Util_LatencyTest2Reader_h
  138.32 +
  138.33 +#include "../Tracking/Tracking_SensorState.h"
  138.34 +#include "Util_LatencyTest2State.h"
  138.35 +
  138.36 +namespace OVR { namespace Util {
  138.37 +
  138.38 +
  138.39 +//-----------------------------------------------------------------------------
  138.40 +// RecordStateReader
  138.41 +
  138.42 +// User interface to retrieve pose from the sensor fusion subsystem
  138.43 +class RecordStateReader : public NewOverrideBase
  138.44 +{
  138.45 +protected:
  138.46 +    const Tracking::CombinedSharedStateUpdater* Updater;
  138.47 +
  138.48 +public:
  138.49 +    RecordStateReader()
  138.50 +        : Updater(NULL)
  138.51 +    {
  138.52 +    }
  138.53 +
  138.54 +    // Initialize the updater
  138.55 +    void SetUpdater(const Tracking::CombinedSharedStateUpdater *updater)
  138.56 +    {
  138.57 +        Updater = updater;
  138.58 +    }
  138.59 +
  138.60 +    void GetRecordSet(FrameTimeRecordSet& recordset);
  138.61 +};
  138.62 +
  138.63 +
  138.64 +}} // namespace OVR::Util
  138.65 +
  138.66 +#endif // OVR_Util_LatencyTest2Reader_h
   139.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   139.2 +++ b/LibOVR/Src/Util/Util_LatencyTest2State.h	Wed Jan 14 06:51:16 2015 +0200
   139.3 @@ -0,0 +1,96 @@
   139.4 +/************************************************************************************
   139.5 +
   139.6 +Filename    :   Util_LatencyTest2Reader.h
   139.7 +Content     :   Shared functionality for the DK2 latency tester
   139.8 +Created     :   July 8, 2014
   139.9 +Authors     :   Volga Aksoy, Chris Taylor
  139.10 +
  139.11 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
  139.12 +
  139.13 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
  139.14 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
  139.15 +which is provided at the time of installation or download, or which 
  139.16 +otherwise accompanies this software in either electronic or hard copy form.
  139.17 +
  139.18 +You may obtain a copy of the License at
  139.19 +
  139.20 +http://www.oculusvr.com/licenses/LICENSE-3.2 
  139.21 +
  139.22 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
  139.23 +distributed under the License is distributed on an "AS IS" BASIS,
  139.24 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  139.25 +See the License for the specific language governing permissions and
  139.26 +limitations under the License.
  139.27 +
  139.28 +*************************************************************************************/
  139.29 +
  139.30 +#ifndef OVR_Util_LatencyTest2_State_h
  139.31 +#define OVR_Util_LatencyTest2_State_h
  139.32 +
  139.33 +#include "../Kernel/OVR_Lockless.h"
  139.34 +
  139.35 +namespace OVR { namespace Util {
  139.36 +
  139.37 +
  139.38 +enum LatencyTester2Constants
  139.39 +{
  139.40 +    LT2_ColorIncrement                  = 32,
  139.41 +    LT2_PixelTestThreshold              = LT2_ColorIncrement / 3,
  139.42 +    LT2_IncrementCount                  = 256 / LT2_ColorIncrement,
  139.43 +    LT2_TimeoutWaitingForColorDetected  = 1000  // 1 second
  139.44 +};
  139.45 +
  139.46 +
  139.47 +//-------------------------------------------------------------------------------------
  139.48 +// FrameTimeRecord
  139.49 +
  139.50 +// Describes frame scan-out time used for latency testing.
  139.51 +struct FrameTimeRecord
  139.52 +{
  139.53 +    int    ReadbackIndex;
  139.54 +    double TimeSeconds;
  139.55 +
  139.56 +    // Utility functions to convert color to readBack indices and back.
  139.57 +    // The purpose of ReadbackIndex is to allow direct comparison by value.
  139.58 +
  139.59 +    static bool ColorToReadbackIndex(int *readbackIndex, unsigned char color);
  139.60 +    static unsigned char ReadbackIndexToColor(int readbackIndex);
  139.61 +};
  139.62 +
  139.63 +
  139.64 +//-----------------------------------------------------------------------------
  139.65 +// FrameTimeRecordSet
  139.66 +
  139.67 +// FrameTimeRecordSet is a container holding multiple consecutive frame timing records
  139.68 +// returned from the lock-less state. Used by FrameTimeManager. 
  139.69 +struct FrameTimeRecordSet
  139.70 +{
  139.71 +    enum {
  139.72 +        RecordCount = 4,
  139.73 +        RecordMask  = RecordCount - 1
  139.74 +    };
  139.75 +    FrameTimeRecord Records[RecordCount];    
  139.76 +    int             NextWriteIndex;
  139.77 +
  139.78 +    FrameTimeRecordSet();
  139.79 +
  139.80 +    void AddValue(int readValue, double timeSeconds);
  139.81 +    // Matching should be done starting from NextWrite index 
  139.82 +    // until wrap-around
  139.83 +
  139.84 +    const FrameTimeRecord& operator [] (int i) const;
  139.85 +
  139.86 +    const FrameTimeRecord& GetMostRecentFrame();
  139.87 +
  139.88 +    // Advances I to  absolute color index
  139.89 +    bool FindReadbackIndex(int* i, int readbackIndex) const;
  139.90 +
  139.91 +    bool IsAllZeroes() const;
  139.92 +};
  139.93 +
  139.94 +typedef LocklessUpdater<FrameTimeRecordSet, FrameTimeRecordSet> LockessRecordUpdater;
  139.95 +
  139.96 +
  139.97 +}} // namespace OVR::Util
  139.98 +
  139.99 +#endif // OVR_Util_LatencyTest2_State_h
   140.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   140.2 +++ b/LibOVR/Src/Util/Util_Render_Stereo.cpp	Wed Jan 14 06:51:16 2015 +0200
   140.3 @@ -0,0 +1,1554 @@
   140.4 +/************************************************************************************
   140.5 +
   140.6 +Filename    :   Util_Render_Stereo.cpp
   140.7 +Content     :   Stereo rendering configuration implementation
   140.8 +Created     :   October 22, 2012
   140.9 +Authors     :   Michael Antonov, Andrew Reisse, Tom Forsyth
  140.10 +
  140.11 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
  140.12 +
  140.13 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License");
  140.14 +you may not use the Oculus VR Rift SDK except in compliance with the License,
  140.15 +which is provided at the time of installation or download, or which
  140.16 +otherwise accompanies this software in either electronic or hard copy form.
  140.17 +
  140.18 +You may obtain a copy of the License at
  140.19 +
  140.20 +http://www.oculusvr.com/licenses/LICENSE-3.2
  140.21 +
  140.22 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK
  140.23 +distributed under the License is distributed on an "AS IS" BASIS,
  140.24 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  140.25 +See the License for the specific language governing permissions and
  140.26 +limitations under the License.
  140.27 +
  140.28 +*************************************************************************************/
  140.29 +
  140.30 +#include "Util_Render_Stereo.h"
  140.31 +
  140.32 +namespace OVR { namespace Util { namespace Render {
  140.33 +
  140.34 +using namespace OVR::Tracking;
  140.35 +
  140.36 +
  140.37 +//-----------------------------------------------------------------------------------
  140.38 +// **** Useful debug functions.
  140.39 +
  140.40 +char const* GetDebugNameEyeCupType ( EyeCupType eyeCupType )
  140.41 +{
  140.42 +    switch ( eyeCupType )
  140.43 +    {
  140.44 +    case EyeCup_DK1A:           return "DK1 A";
  140.45 +    case EyeCup_DK1B:           return "DK1 B";
  140.46 +    case EyeCup_DK1C:           return "DK1 C";
  140.47 +    case EyeCup_DKHD2A:         return "DKHD2 A";
  140.48 +    case EyeCup_OrangeA:        return "Orange A";
  140.49 +    case EyeCup_RedA:           return "Red A";
  140.50 +    case EyeCup_PinkA:          return "Pink A";
  140.51 +    case EyeCup_BlueA:          return "Blue A";
  140.52 +    case EyeCup_Delilah1A:      return "Delilah 1 A";
  140.53 +    case EyeCup_Delilah2A:      return "Delilah 2 A";
  140.54 +    case EyeCup_JamesA:         return "James A";
  140.55 +    case EyeCup_SunMandalaA:    return "Sun Mandala A";
  140.56 +    case EyeCup_DK2A:           return "DK2 A";
  140.57 +    case EyeCup_LAST:           return "LAST";
  140.58 +    default: OVR_ASSERT ( false ); return "Error";
  140.59 +    }
  140.60 +}
  140.61 +
  140.62 +char const* GetDebugNameHmdType ( HmdTypeEnum hmdType )
  140.63 +{
  140.64 +    switch ( hmdType )
  140.65 +    {
  140.66 +    case HmdType_None:              return "None";
  140.67 +    case HmdType_DK1:               return "DK1";
  140.68 +    case HmdType_DKProto:           return "DK1 prototype";
  140.69 +    case HmdType_DKHDProto:         return "DK HD prototype 1";
  140.70 +    case HmdType_DKHDProto566Mi:    return "DK HD prototype 566 Mi";
  140.71 +    case HmdType_DKHD2Proto:        return "DK HD prototype 585";
  140.72 +    case HmdType_CrystalCoveProto:  return "Crystal Cove";
  140.73 +    case HmdType_DK2:               return "DK2";
  140.74 +    case HmdType_Unknown:           return "Unknown";
  140.75 +    case HmdType_LAST:              return "LAST";
  140.76 +    default: OVR_ASSERT ( false ); return "Error";
  140.77 +    }
  140.78 +}
  140.79 +
  140.80 +
  140.81 +//-----------------------------------------------------------------------------------
  140.82 +// **** Internal pipeline functions.
  140.83 +
  140.84 +struct DistortionAndFov
  140.85 +{
  140.86 +    DistortionRenderDesc    Distortion;
  140.87 +    FovPort                 Fov;
  140.88 +};
  140.89 +
  140.90 +static DistortionAndFov CalculateDistortionAndFovInternal ( StereoEye eyeType, HmdRenderInfo const &hmd,
  140.91 +                                                            LensConfig const *pLensOverride = NULL,
  140.92 +                                                            FovPort const *pTanHalfFovOverride = NULL,
  140.93 +                                                            float extraEyeRotationInRadians = OVR_DEFAULT_EXTRA_EYE_ROTATION )
  140.94 +{
  140.95 +    // pLensOverride can be NULL, which means no override.
  140.96 +
  140.97 +    DistortionRenderDesc localDistortion  = CalculateDistortionRenderDesc ( eyeType, hmd, pLensOverride );
  140.98 +    FovPort              fov              = CalculateFovFromHmdInfo ( eyeType, localDistortion, hmd, extraEyeRotationInRadians );
  140.99 +    // Here the app or the user would optionally clamp this visible fov to a smaller number if
 140.100 +    // they want more perf or resolution and are willing to give up FOV.
 140.101 +    // They may also choose to clamp UDLR differently e.g. to get cinemascope-style views.
 140.102 +    if ( pTanHalfFovOverride != NULL )
 140.103 +    {
 140.104 +        fov = *pTanHalfFovOverride;
 140.105 +    }
 140.106 +
 140.107 +    // Here we could call ClampToPhysicalScreenFov(), but we do want people
 140.108 +    // to be able to play with larger-than-screen views.
 140.109 +    // The calling app can always do the clamping itself.
 140.110 +    DistortionAndFov result;
 140.111 +    result.Distortion = localDistortion;
 140.112 +    result.Fov        = fov;
 140.113 +
 140.114 +    return result;
 140.115 +}
 140.116 +
 140.117 +
 140.118 +static Recti CalculateViewportInternal ( StereoEye eyeType,
 140.119 +                                            Sizei const actualRendertargetSurfaceSize,
 140.120 +                                            Sizei const requestedRenderedPixelSize,
 140.121 +                                            bool bRendertargetSharedByBothEyes,
 140.122 +                                            bool bMonoRenderingMode = false )
 140.123 +{
 140.124 +    Recti renderedViewport;
 140.125 +    if ( bMonoRenderingMode || !bRendertargetSharedByBothEyes || (eyeType == StereoEye_Center) )
 140.126 +    {
 140.127 +        // One eye per RT.
 140.128 +        renderedViewport.x = 0;
 140.129 +        renderedViewport.y = 0;
 140.130 +        renderedViewport.w = Alg::Min ( actualRendertargetSurfaceSize.w, requestedRenderedPixelSize.w );
 140.131 +        renderedViewport.h = Alg::Min ( actualRendertargetSurfaceSize.h, requestedRenderedPixelSize.h );
 140.132 +    }
 140.133 +    else
 140.134 +    {
 140.135 +        // Both eyes share the RT.
 140.136 +        renderedViewport.x = 0;
 140.137 +        renderedViewport.y = 0;
 140.138 +        renderedViewport.w = Alg::Min ( actualRendertargetSurfaceSize.w/2, requestedRenderedPixelSize.w );
 140.139 +        renderedViewport.h = Alg::Min ( actualRendertargetSurfaceSize.h,  requestedRenderedPixelSize.h );
 140.140 +        if ( eyeType == StereoEye_Right )
 140.141 +        {
 140.142 +            renderedViewport.x = (actualRendertargetSurfaceSize.w+1)/2;      // Round up, not down.
 140.143 +        }
 140.144 +    }
 140.145 +    return renderedViewport;
 140.146 +}
 140.147 +
 140.148 +static Recti CalculateViewportDensityInternal ( StereoEye eyeType,
 140.149 +                                                   DistortionRenderDesc const &distortion,
 140.150 +                                                   FovPort const &fov,
 140.151 +                                                   Sizei const &actualRendertargetSurfaceSize,
 140.152 +                                                   bool bRendertargetSharedByBothEyes,
 140.153 +                                                   float desiredPixelDensity = 1.0f,
 140.154 +                                                   bool bMonoRenderingMode = false )
 140.155 +{
 140.156 +    OVR_ASSERT ( actualRendertargetSurfaceSize.w > 0 );
 140.157 +    OVR_ASSERT ( actualRendertargetSurfaceSize.h > 0 );
 140.158 +
 140.159 +    // What size RT do we need to get 1:1 mapping?
 140.160 +    Sizei idealPixelSize = CalculateIdealPixelSize ( eyeType, distortion, fov, desiredPixelDensity );
 140.161 +    // ...but we might not actually get that size.
 140.162 +    return CalculateViewportInternal ( eyeType,
 140.163 +                                       actualRendertargetSurfaceSize,
 140.164 +                                       idealPixelSize,
 140.165 +                                       bRendertargetSharedByBothEyes, bMonoRenderingMode );
 140.166 +}
 140.167 +
 140.168 +static ViewportScaleAndOffset CalculateViewportScaleAndOffsetInternal (
 140.169 +                                                          ScaleAndOffset2D const &eyeToSourceNDC,
 140.170 +                                                          Recti const &renderedViewport,
 140.171 +                                                          Sizei const &actualRendertargetSurfaceSize )
 140.172 +{
 140.173 +    ViewportScaleAndOffset result;
 140.174 +    result.RenderedViewport = renderedViewport;
 140.175 +    result.EyeToSourceUV = CreateUVScaleAndOffsetfromNDCScaleandOffset(
 140.176 +                                            eyeToSourceNDC, renderedViewport, actualRendertargetSurfaceSize );
 140.177 +    return result;
 140.178 +}
 140.179 +
 140.180 +
 140.181 +static StereoEyeParams CalculateStereoEyeParamsInternal ( StereoEye eyeType, HmdRenderInfo const &hmd,
 140.182 +                                                          DistortionRenderDesc const &distortion,
 140.183 +                                                          FovPort const &fov,
 140.184 +                                                          Sizei const &actualRendertargetSurfaceSize,
 140.185 +                                                          Recti const &renderedViewport,
 140.186 +                                                          bool bRightHanded = true, float zNear = 0.01f, float zFar = 10000.0f,
 140.187 +                                                          bool bMonoRenderingMode = false,
 140.188 +                                                          float zoomFactor = 1.0f )
 140.189 +{
 140.190 +    // Generate the projection matrix for intermediate rendertarget.
 140.191 +    // Z range can also be inserted later by the app (though not in this particular case)
 140.192 +    float fovScale = 1.0f / zoomFactor;
 140.193 +    FovPort zoomedFov = fov;
 140.194 +    zoomedFov.LeftTan  *= fovScale;
 140.195 +    zoomedFov.RightTan *= fovScale;
 140.196 +    zoomedFov.UpTan    *= fovScale;
 140.197 +    zoomedFov.DownTan  *= fovScale;
 140.198 +    Matrix4f projection = CreateProjection ( bRightHanded, zoomedFov, zNear, zFar );
 140.199 +
 140.200 +    // Find the mapping from TanAngle space to target NDC space.
 140.201 +    // Note this does NOT take the zoom factor into account because
 140.202 +    // this is the mapping of actual physical eye FOV (and our eyes do not zoom!)
 140.203 +    // to screen space.
 140.204 +    ScaleAndOffset2D eyeToSourceNDC = CreateNDCScaleAndOffsetFromFov ( fov );
 140.205 +
 140.206 +    // The size of the final FB, which is fixed and determined by the physical size of the device display.
 140.207 +    Recti distortedViewport   = GetFramebufferViewport ( eyeType, hmd );
 140.208 +    Vector3f virtualCameraOffset = CalculateEyeVirtualCameraOffset(hmd, eyeType, bMonoRenderingMode);
 140.209 +
 140.210 +    StereoEyeParams result;
 140.211 +    result.Eye                  = eyeType;
 140.212 +    result.HmdToEyeViewOffset   = Matrix4f::Translation(virtualCameraOffset);
 140.213 +    result.Distortion           = distortion;
 140.214 +    result.DistortionViewport   = distortedViewport;
 140.215 +    result.Fov                  = fov;
 140.216 +    result.RenderedProjection   = projection;
 140.217 +    result.EyeToSourceNDC       = eyeToSourceNDC;
 140.218 +    ViewportScaleAndOffset vsao = CalculateViewportScaleAndOffsetInternal ( eyeToSourceNDC, renderedViewport, actualRendertargetSurfaceSize );
 140.219 +    result.RenderedViewport     = vsao.RenderedViewport;
 140.220 +    result.EyeToSourceUV        = vsao.EyeToSourceUV;
 140.221 +
 140.222 +    return result;
 140.223 +}
 140.224 +
 140.225 +
 140.226 +Vector3f CalculateEyeVirtualCameraOffset(HmdRenderInfo const &hmd,
 140.227 +                                         StereoEye eyeType, bool bmonoRenderingMode)
 140.228 +{
 140.229 +    Vector3f virtualCameraOffset(0);
 140.230 +
 140.231 +    if (!bmonoRenderingMode)
 140.232 +    {
 140.233 +        float eyeCenterRelief = hmd.GetEyeCenter().ReliefInMeters;
 140.234 +
 140.235 +        if (eyeType == StereoEye_Left)
 140.236 +        {
 140.237 +            virtualCameraOffset.x = hmd.EyeLeft.NoseToPupilInMeters;
 140.238 +            virtualCameraOffset.z = eyeCenterRelief - hmd.EyeLeft.ReliefInMeters;
 140.239 +        }
 140.240 +        else if (eyeType == StereoEye_Right)
 140.241 +        {
 140.242 +            virtualCameraOffset.x = -hmd.EyeRight.NoseToPupilInMeters;
 140.243 +            virtualCameraOffset.z = eyeCenterRelief - hmd.EyeRight.ReliefInMeters;
 140.244 +        }
 140.245 +    }
 140.246 +
 140.247 +    return virtualCameraOffset;
 140.248 +}
 140.249 +
 140.250 +
 140.251 +//-----------------------------------------------------------------------------------
 140.252 +// **** Higher-level utility functions.
 140.253 +
 140.254 +Sizei CalculateRecommendedTextureSize ( HmdRenderInfo const &hmd,
 140.255 +                                        bool bRendertargetSharedByBothEyes,
 140.256 +                                        float pixelDensityInCenter /*= 1.0f*/ )
 140.257 +{
 140.258 +    Sizei idealPixelSize[2];
 140.259 +    for ( int eyeNum = 0; eyeNum < 2; eyeNum++ )
 140.260 +    {
 140.261 +        StereoEye eyeType = ( eyeNum == 0 ) ? StereoEye_Left : StereoEye_Right;
 140.262 +
 140.263 +        DistortionAndFov distortionAndFov = CalculateDistortionAndFovInternal ( eyeType, hmd, NULL, NULL, OVR_DEFAULT_EXTRA_EYE_ROTATION );
 140.264 +
 140.265 +        idealPixelSize[eyeNum] = CalculateIdealPixelSize ( eyeType,
 140.266 +                                        distortionAndFov.Distortion,
 140.267 +                                        distortionAndFov.Fov,
 140.268 +                                        pixelDensityInCenter );
 140.269 +    }
 140.270 +
 140.271 +    Sizei result;
 140.272 +    result.w = Alg::Max ( idealPixelSize[0].w, idealPixelSize[1].w );
 140.273 +    result.h = Alg::Max ( idealPixelSize[0].h, idealPixelSize[1].h );
 140.274 +    if ( bRendertargetSharedByBothEyes )
 140.275 +    {
 140.276 +        result.w *= 2;
 140.277 +    }
 140.278 +    return result;
 140.279 +}
 140.280 +
 140.281 +StereoEyeParams CalculateStereoEyeParams ( HmdRenderInfo const &hmd,
 140.282 +                                           StereoEye eyeType,
 140.283 +                                           Sizei const &actualRendertargetSurfaceSize,
 140.284 +                                           bool bRendertargetSharedByBothEyes,
 140.285 +                                           bool bRightHanded /*= true*/,
 140.286 +                                           float zNear /*= 0.01f*/, float zFar /*= 10000.0f*/,
 140.287 +										   Sizei const *pOverrideRenderedPixelSize /* = NULL*/,
 140.288 +                                           FovPort const *pOverrideFovport /*= NULL*/,
 140.289 +                                           float zoomFactor /*= 1.0f*/ )
 140.290 +{
 140.291 +    DistortionAndFov distortionAndFov = CalculateDistortionAndFovInternal ( eyeType, hmd, NULL, NULL, OVR_DEFAULT_EXTRA_EYE_ROTATION );
 140.292 +    if ( pOverrideFovport != NULL )
 140.293 +    {
 140.294 +        distortionAndFov.Fov = *pOverrideFovport;
 140.295 +    }
 140.296 +
 140.297 +    Recti viewport;
 140.298 +    if ( pOverrideRenderedPixelSize != NULL )
 140.299 +    {
 140.300 +        viewport = CalculateViewportInternal ( eyeType, actualRendertargetSurfaceSize, *pOverrideRenderedPixelSize, bRendertargetSharedByBothEyes, false );
 140.301 +    }
 140.302 +    else
 140.303 +    {
 140.304 +        viewport = CalculateViewportDensityInternal ( eyeType,
 140.305 +                                                      distortionAndFov.Distortion,
 140.306 +                                                      distortionAndFov.Fov,
 140.307 +                                                      actualRendertargetSurfaceSize, bRendertargetSharedByBothEyes, 1.0f, false );
 140.308 +    }
 140.309 +
 140.310 +    return CalculateStereoEyeParamsInternal (
 140.311 +                                eyeType, hmd,
 140.312 +                                distortionAndFov.Distortion,
 140.313 +                                distortionAndFov.Fov,
 140.314 +                                actualRendertargetSurfaceSize, viewport,
 140.315 +                                bRightHanded, zNear, zFar, false, zoomFactor );
 140.316 +}
 140.317 +
 140.318 +
 140.319 +FovPort CalculateRecommendedFov ( HmdRenderInfo const &hmd,
 140.320 +                                  StereoEye eyeType,
 140.321 +                                  bool bMakeFovSymmetrical /* = false */ )
 140.322 +{
 140.323 +    DistortionAndFov distortionAndFov = CalculateDistortionAndFovInternal ( eyeType, hmd, NULL, NULL, OVR_DEFAULT_EXTRA_EYE_ROTATION );
 140.324 +    FovPort fov = distortionAndFov.Fov;
 140.325 +    if ( bMakeFovSymmetrical )
 140.326 +    {
 140.327 +        // Deal with engines that cannot support an off-center projection.
 140.328 +        // Unfortunately this means they will be rendering pixels that the user can't actually see.
 140.329 +        float fovTanH = Alg::Max ( fov.LeftTan, fov.RightTan );
 140.330 +        float fovTanV = Alg::Max ( fov.UpTan, fov.DownTan );
 140.331 +        fov.LeftTan = fovTanH;
 140.332 +        fov.RightTan = fovTanH;
 140.333 +        fov.UpTan = fovTanV;
 140.334 +        fov.DownTan = fovTanV;
 140.335 +    }
 140.336 +    return fov;
 140.337 +}
 140.338 +
 140.339 +ViewportScaleAndOffset ModifyRenderViewport ( StereoEyeParams const &params,
 140.340 +                                              Sizei const &actualRendertargetSurfaceSize,
 140.341 +                                              Recti const &renderViewport )
 140.342 +{
 140.343 +    return CalculateViewportScaleAndOffsetInternal ( params.EyeToSourceNDC, renderViewport, actualRendertargetSurfaceSize );
 140.344 +}
 140.345 +
 140.346 +ViewportScaleAndOffset ModifyRenderSize ( StereoEyeParams const &params,
 140.347 +                                          Sizei const &actualRendertargetSurfaceSize,
 140.348 +                                          Sizei const &requestedRenderSize,
 140.349 +                                          bool bRendertargetSharedByBothEyes /*= false*/ )
 140.350 +{
 140.351 +    Recti renderViewport = CalculateViewportInternal ( params.Eye, actualRendertargetSurfaceSize, requestedRenderSize, bRendertargetSharedByBothEyes, false );
 140.352 +    return CalculateViewportScaleAndOffsetInternal ( params.EyeToSourceNDC, renderViewport, actualRendertargetSurfaceSize );
 140.353 +}
 140.354 +
 140.355 +ViewportScaleAndOffset ModifyRenderDensity ( StereoEyeParams const &params,
 140.356 +                                             Sizei const &actualRendertargetSurfaceSize,
 140.357 +                                             float pixelDensity /*= 1.0f*/,
 140.358 +                                             bool bRendertargetSharedByBothEyes /*= false*/ )
 140.359 +{
 140.360 +    Recti renderViewport = CalculateViewportDensityInternal ( params.Eye, params.Distortion, params.Fov, actualRendertargetSurfaceSize, bRendertargetSharedByBothEyes, pixelDensity, false );
 140.361 +    return CalculateViewportScaleAndOffsetInternal ( params.EyeToSourceNDC, renderViewport, actualRendertargetSurfaceSize );
 140.362 +}
 140.363 +
 140.364 +
 140.365 +//-----------------------------------------------------------------------------------
 140.366 +// **** StereoConfig Implementation
 140.367 +
 140.368 +StereoConfig::StereoConfig(StereoMode mode)
 140.369 +    : Mode(mode),
 140.370 +      DirtyFlag(true)
 140.371 +{
 140.372 +    // Initialize "fake" default HMD values for testing without HMD plugged in.
 140.373 +    // These default values match those returned by DK1
 140.374 +    // (at least they did at time of writing - certainly good enough for debugging)
 140.375 +    Hmd.HmdType                                         = HmdType_None;
 140.376 +    Hmd.ResolutionInPixels                              = Sizei(1280, 800);
 140.377 +    Hmd.ScreenSizeInMeters                              = Sizef(0.1498f, 0.0936f);
 140.378 +    Hmd.ScreenGapSizeInMeters                           = 0.0f;
 140.379 +    Hmd.PelOffsetR                                      = Vector2f ( 0.0f, 0.0f );
 140.380 +    Hmd.PelOffsetB                                      = Vector2f ( 0.0f, 0.0f );
 140.381 +    Hmd.CenterFromTopInMeters                           = 0.0468f;
 140.382 +    Hmd.LensSeparationInMeters                          = 0.0635f;
 140.383 +    Hmd.LensDiameterInMeters                            = 0.035f;
 140.384 +    Hmd.LensSurfaceToMidplateInMeters                   = 0.025f;
 140.385 +    Hmd.EyeCups                                         = EyeCup_DK1A;
 140.386 +    Hmd.Shutter.Type                                    = HmdShutter_RollingTopToBottom;
 140.387 +    Hmd.Shutter.VsyncToNextVsync                        = ( 1.0f / 60.0f );
 140.388 +    Hmd.Shutter.VsyncToFirstScanline                    = 0.000052f;
 140.389 +    Hmd.Shutter.FirstScanlineToLastScanline             = 0.016580f;
 140.390 +    Hmd.Shutter.PixelSettleTime                         = 0.015f;
 140.391 +    Hmd.Shutter.PixelPersistence                        = ( 1.0f / 60.0f );
 140.392 +    Hmd.EyeLeft.Distortion.SetToIdentity();
 140.393 +    Hmd.EyeLeft.Distortion.MetersPerTanAngleAtCenter    = 0.043875f;
 140.394 +    Hmd.EyeLeft.Distortion.Eqn                          = Distortion_RecipPoly4;
 140.395 +    Hmd.EyeLeft.Distortion.K[0]                         = 1.0f;
 140.396 +    Hmd.EyeLeft.Distortion.K[1]                         = -0.3999f;
 140.397 +    Hmd.EyeLeft.Distortion.K[2]                         = 0.2408f;
 140.398 +    Hmd.EyeLeft.Distortion.K[3]                         = -0.4589f;
 140.399 +    Hmd.EyeLeft.Distortion.MaxR                         = 1.0f;
 140.400 +	Hmd.EyeLeft.Distortion.ChromaticAberration[0]		= 0.006f;
 140.401 +	Hmd.EyeLeft.Distortion.ChromaticAberration[1]		= 0.0f;
 140.402 +	Hmd.EyeLeft.Distortion.ChromaticAberration[2]		= -0.014f;
 140.403 +	Hmd.EyeLeft.Distortion.ChromaticAberration[3]		= 0.0f;
 140.404 +    Hmd.EyeLeft.NoseToPupilInMeters                     = 0.62f;
 140.405 +    Hmd.EyeLeft.ReliefInMeters                          = 0.013f;
 140.406 +    Hmd.EyeRight = Hmd.EyeLeft;
 140.407 +
 140.408 +    SetViewportMode = SVPM_Density;
 140.409 +    SetViewportPixelsPerDisplayPixel = 1.0f;
 140.410 +    // Not used in this mode, but init them anyway.
 140.411 +    SetViewportSize[0] = Sizei(0,0);
 140.412 +    SetViewportSize[1] = Sizei(0,0);
 140.413 +    SetViewport[0] = Recti(0,0,0,0);
 140.414 +    SetViewport[1] = Recti(0,0,0,0);
 140.415 +
 140.416 +    OverrideLens = false;
 140.417 +    OverrideTanHalfFov = false;
 140.418 +    OverrideZeroIpd = false;
 140.419 +    ExtraEyeRotationInRadians = OVR_DEFAULT_EXTRA_EYE_ROTATION;
 140.420 +    IsRendertargetSharedByBothEyes = true;
 140.421 +    RightHandedProjection = true;
 140.422 +
 140.423 +    // This should cause an assert if the app does not call SetRendertargetSize()
 140.424 +    RendertargetSize = Sizei ( 0, 0 );
 140.425 +
 140.426 +    ZNear = 0.01f;
 140.427 +    ZFar = 10000.0f;
 140.428 +
 140.429 +    Set2DAreaFov(DegreeToRad(85.0f));
 140.430 +}
 140.431 +
 140.432 +void StereoConfig::SetHmdRenderInfo(const HmdRenderInfo& hmd)
 140.433 +{
 140.434 +    Hmd = hmd;
 140.435 +    DirtyFlag = true;
 140.436 +}
 140.437 +
 140.438 +void StereoConfig::Set2DAreaFov(float fovRadians)
 140.439 +{
 140.440 +    Area2DFov = fovRadians;
 140.441 +    DirtyFlag = true;
 140.442 +}
 140.443 +
 140.444 +const StereoEyeParamsWithOrtho& StereoConfig::GetEyeRenderParams(StereoEye eye)
 140.445 +{
 140.446 +    if ( DirtyFlag )
 140.447 +    {
 140.448 +        UpdateComputedState();
 140.449 +    }
 140.450 +
 140.451 +    static const uint8_t eyeParamIndices[3] = { 0, 0, 1 };
 140.452 +
 140.453 +    OVR_ASSERT(eye < sizeof(eyeParamIndices));
 140.454 +    return EyeRenderParams[eyeParamIndices[eye]];
 140.455 +}
 140.456 +
 140.457 +void StereoConfig::SetLensOverride ( LensConfig const *pLensOverrideLeft  /*= NULL*/,
 140.458 +                                     LensConfig const *pLensOverrideRight /*= NULL*/ )
 140.459 +{
 140.460 +    if ( pLensOverrideLeft == NULL )
 140.461 +    {
 140.462 +        OverrideLens = false;
 140.463 +    }
 140.464 +    else
 140.465 +    {
 140.466 +        OverrideLens = true;
 140.467 +        LensOverrideLeft = *pLensOverrideLeft;
 140.468 +        LensOverrideRight = *pLensOverrideLeft;
 140.469 +        if ( pLensOverrideRight != NULL )
 140.470 +        {
 140.471 +            LensOverrideRight = *pLensOverrideRight;
 140.472 +        }
 140.473 +    }
 140.474 +    DirtyFlag = true;
 140.475 +}
 140.476 +
 140.477 +void StereoConfig::SetRendertargetSize (Size<int> const rendertargetSize,
 140.478 +                                        bool rendertargetIsSharedByBothEyes )
 140.479 +{
 140.480 +    RendertargetSize = rendertargetSize;
 140.481 +    IsRendertargetSharedByBothEyes = rendertargetIsSharedByBothEyes;
 140.482 +    DirtyFlag = true;
 140.483 +}
 140.484 +
 140.485 +void StereoConfig::SetFov ( FovPort const *pfovLeft  /*= NULL*/,
 140.486 +                            FovPort const *pfovRight /*= NULL*/ )
 140.487 +{
 140.488 +    DirtyFlag = true;
 140.489 +    if ( pfovLeft == NULL )
 140.490 +    {
 140.491 +        OverrideTanHalfFov = false;
 140.492 +    }
 140.493 +    else
 140.494 +    {
 140.495 +        OverrideTanHalfFov = true;
 140.496 +        FovOverrideLeft  = *pfovLeft;
 140.497 +        FovOverrideRight = *pfovLeft;
 140.498 +        if ( pfovRight != NULL )
 140.499 +        {
 140.500 +            FovOverrideRight = *pfovRight;
 140.501 +        }
 140.502 +    }
 140.503 +}
 140.504 +
 140.505 +
 140.506 +void StereoConfig::SetZeroVirtualIpdOverride ( bool enableOverride )
 140.507 +{
 140.508 +    DirtyFlag = true;
 140.509 +    OverrideZeroIpd = enableOverride;
 140.510 +}
 140.511 +
 140.512 +
 140.513 +void StereoConfig::SetZClipPlanesAndHandedness ( float zNear /*= 0.01f*/, float zFar /*= 10000.0f*/, bool rightHandedProjection /*= true*/ )
 140.514 +{
 140.515 +    DirtyFlag = true;
 140.516 +    ZNear = zNear;
 140.517 +    ZFar = zFar;
 140.518 +    RightHandedProjection = rightHandedProjection;
 140.519 +}
 140.520 +
 140.521 +void StereoConfig::SetExtraEyeRotation ( float extraEyeRotationInRadians )
 140.522 +{
 140.523 +    DirtyFlag = true;
 140.524 +    ExtraEyeRotationInRadians = extraEyeRotationInRadians;
 140.525 +}
 140.526 +
 140.527 +Sizei StereoConfig::CalculateRecommendedTextureSize ( bool rendertargetSharedByBothEyes,
 140.528 +                                                      float pixelDensityInCenter /*= 1.0f*/ )
 140.529 +{
 140.530 +    return Render::CalculateRecommendedTextureSize ( Hmd, rendertargetSharedByBothEyes, pixelDensityInCenter );
 140.531 +}
 140.532 +
 140.533 +
 140.534 +
 140.535 +void StereoConfig::UpdateComputedState()
 140.536 +{
 140.537 +    int numEyes = 2;
 140.538 +    StereoEye eyeTypes[2];
 140.539 +
 140.540 +    switch ( Mode )
 140.541 +    {
 140.542 +    case Stereo_None:
 140.543 +        numEyes         = 1;
 140.544 +        eyeTypes[0]     = StereoEye_Center;
 140.545 +        break;
 140.546 +
 140.547 +    case Stereo_LeftRight_Multipass:
 140.548 +        numEyes         = 2;
 140.549 +        eyeTypes[0]     = StereoEye_Left;
 140.550 +        eyeTypes[1]     = StereoEye_Right;
 140.551 +        break;
 140.552 +
 140.553 +    default:
 140.554 +        numEyes = 0;
 140.555 +        OVR_ASSERT( false );
 140.556 +        break;
 140.557 +    }
 140.558 +
 140.559 +    // If either of these fire, you've probably forgotten to call SetRendertargetSize()
 140.560 +    OVR_ASSERT ( RendertargetSize.w > 0 );
 140.561 +    OVR_ASSERT ( RendertargetSize.h > 0 );
 140.562 +
 140.563 +    for ( int eyeNum = 0; eyeNum < numEyes; eyeNum++ )
 140.564 +    {
 140.565 +        StereoEye eyeType = eyeTypes[eyeNum];
 140.566 +        LensConfig *pLensOverride = NULL;
 140.567 +        if ( OverrideLens )
 140.568 +        {
 140.569 +            if ( eyeType == StereoEye_Right )
 140.570 +            {
 140.571 +                pLensOverride = &LensOverrideRight;
 140.572 +            }
 140.573 +            else
 140.574 +            {
 140.575 +                pLensOverride = &LensOverrideLeft;
 140.576 +            }
 140.577 +        }
 140.578 +
 140.579 +        FovPort *pTanHalfFovOverride = NULL;
 140.580 +        if ( OverrideTanHalfFov )
 140.581 +        {
 140.582 +            if ( eyeType == StereoEye_Right )
 140.583 +            {
 140.584 +                pTanHalfFovOverride = &FovOverrideRight;
 140.585 +            }
 140.586 +            else
 140.587 +            {
 140.588 +                pTanHalfFovOverride = &FovOverrideLeft;
 140.589 +            }
 140.590 +        }
 140.591 +
 140.592 +        DistortionAndFov distortionAndFov =
 140.593 +            CalculateDistortionAndFovInternal ( eyeType, Hmd,
 140.594 +                                                pLensOverride, pTanHalfFovOverride,
 140.595 +                                                ExtraEyeRotationInRadians );
 140.596 +
 140.597 +        EyeRenderParams[eyeNum].StereoEye.Distortion = distortionAndFov.Distortion;
 140.598 +        EyeRenderParams[eyeNum].StereoEye.Fov        = distortionAndFov.Fov;
 140.599 +    }
 140.600 +
 140.601 +    if ( OverrideZeroIpd )
 140.602 +    {
 140.603 +        // Take the union of the calculated eye FOVs.
 140.604 +        FovPort fov;
 140.605 +        fov.UpTan    = Alg::Max ( EyeRenderParams[0].StereoEye.Fov.UpTan   , EyeRenderParams[1].StereoEye.Fov.UpTan    );
 140.606 +        fov.DownTan  = Alg::Max ( EyeRenderParams[0].StereoEye.Fov.DownTan , EyeRenderParams[1].StereoEye.Fov.DownTan  );
 140.607 +        fov.LeftTan  = Alg::Max ( EyeRenderParams[0].StereoEye.Fov.LeftTan , EyeRenderParams[1].StereoEye.Fov.LeftTan  );
 140.608 +        fov.RightTan = Alg::Max ( EyeRenderParams[0].StereoEye.Fov.RightTan, EyeRenderParams[1].StereoEye.Fov.RightTan );
 140.609 +        EyeRenderParams[0].StereoEye.Fov = fov;
 140.610 +        EyeRenderParams[1].StereoEye.Fov = fov;
 140.611 +    }
 140.612 +
 140.613 +    for ( int eyeNum = 0; eyeNum < numEyes; eyeNum++ )
 140.614 +    {
 140.615 +        StereoEye eyeType = eyeTypes[eyeNum];
 140.616 +
 140.617 +        DistortionRenderDesc localDistortion = EyeRenderParams[eyeNum].StereoEye.Distortion;
 140.618 +        FovPort              fov             = EyeRenderParams[eyeNum].StereoEye.Fov;
 140.619 +
 140.620 +        // Use a placeholder - will be overridden later.
 140.621 +        Recti tempViewport = Recti ( 0, 0, 1, 1 );
 140.622 +
 140.623 +        EyeRenderParams[eyeNum].StereoEye = CalculateStereoEyeParamsInternal (
 140.624 +                                        eyeType, Hmd, localDistortion, fov,
 140.625 +                                        RendertargetSize, tempViewport,
 140.626 +                                        RightHandedProjection, ZNear, ZFar,
 140.627 +                                        OverrideZeroIpd );
 140.628 +
 140.629 +        // We want to create a virtual 2D surface we can draw debug text messages to.
 140.630 +        // We'd like it to be a fixed distance (OrthoDistance) away,
 140.631 +        // and to cover a specific FOV (Area2DFov). We need to find the projection matrix for this,
 140.632 +        // and also to know how large it is in pixels to achieve a 1:1 mapping at the center of the screen.
 140.633 +        float orthoDistance = 0.8f;
 140.634 +        float orthoHalfFov = tanf ( Area2DFov * 0.5f );
 140.635 +        Vector2f unityOrthoPixelSize = localDistortion.PixelsPerTanAngleAtCenter * ( orthoHalfFov * 2.0f );
 140.636 +        float localInterpupillaryDistance = Hmd.EyeLeft.NoseToPupilInMeters + Hmd.EyeRight.NoseToPupilInMeters;
 140.637 +        if ( OverrideZeroIpd )
 140.638 +        {
 140.639 +            localInterpupillaryDistance = 0.0f;
 140.640 +        }
 140.641 +        Matrix4f ortho = CreateOrthoSubProjection ( true, eyeType,
 140.642 +                                                    orthoHalfFov, orthoHalfFov,
 140.643 +                                                    unityOrthoPixelSize.x, unityOrthoPixelSize.y,
 140.644 +                                                    orthoDistance, localInterpupillaryDistance,
 140.645 +                                                    EyeRenderParams[eyeNum].StereoEye.RenderedProjection );
 140.646 +        EyeRenderParams[eyeNum].OrthoProjection = ortho;
 140.647 +    }
 140.648 +
 140.649 +    // ...and now set up the viewport, scale & offset the way the app wanted.
 140.650 +    setupViewportScaleAndOffsets();
 140.651 +
 140.652 +    if ( OverrideZeroIpd )
 140.653 +    {
 140.654 +        // Monocular rendering has some fragile parts... don't break any by accident.
 140.655 +        OVR_ASSERT ( EyeRenderParams[0].StereoEye.Fov.UpTan                   == EyeRenderParams[1].StereoEye.Fov.UpTan    );
 140.656 +        OVR_ASSERT ( EyeRenderParams[0].StereoEye.Fov.DownTan                 == EyeRenderParams[1].StereoEye.Fov.DownTan  );
 140.657 +        OVR_ASSERT ( EyeRenderParams[0].StereoEye.Fov.LeftTan                 == EyeRenderParams[1].StereoEye.Fov.LeftTan  );
 140.658 +        OVR_ASSERT ( EyeRenderParams[0].StereoEye.Fov.RightTan                == EyeRenderParams[1].StereoEye.Fov.RightTan );
 140.659 +        OVR_ASSERT ( EyeRenderParams[0].StereoEye.RenderedProjection.M[0][0]  == EyeRenderParams[1].StereoEye.RenderedProjection.M[0][0] );
 140.660 +        OVR_ASSERT ( EyeRenderParams[0].StereoEye.RenderedProjection.M[1][1]  == EyeRenderParams[1].StereoEye.RenderedProjection.M[1][1] );
 140.661 +        OVR_ASSERT ( EyeRenderParams[0].StereoEye.RenderedProjection.M[0][2]  == EyeRenderParams[1].StereoEye.RenderedProjection.M[0][2] );
 140.662 +        OVR_ASSERT ( EyeRenderParams[0].StereoEye.RenderedProjection.M[1][2]  == EyeRenderParams[1].StereoEye.RenderedProjection.M[1][2] );
 140.663 +        OVR_ASSERT ( EyeRenderParams[0].StereoEye.RenderedViewport            == EyeRenderParams[1].StereoEye.RenderedViewport      );
 140.664 +        OVR_ASSERT ( EyeRenderParams[0].StereoEye.EyeToSourceUV.Offset        == EyeRenderParams[1].StereoEye.EyeToSourceUV.Offset  );
 140.665 +        OVR_ASSERT ( EyeRenderParams[0].StereoEye.EyeToSourceUV.Scale         == EyeRenderParams[1].StereoEye.EyeToSourceUV.Scale   );
 140.666 +        OVR_ASSERT ( EyeRenderParams[0].StereoEye.EyeToSourceNDC.Offset       == EyeRenderParams[1].StereoEye.EyeToSourceNDC.Offset );
 140.667 +        OVR_ASSERT ( EyeRenderParams[0].StereoEye.EyeToSourceNDC.Scale        == EyeRenderParams[1].StereoEye.EyeToSourceNDC.Scale  );
 140.668 +        OVR_ASSERT ( EyeRenderParams[0].OrthoProjection.M[0][0]               == EyeRenderParams[1].OrthoProjection.M[0][0] );
 140.669 +        OVR_ASSERT ( EyeRenderParams[0].OrthoProjection.M[1][1]               == EyeRenderParams[1].OrthoProjection.M[1][1] );
 140.670 +        OVR_ASSERT ( EyeRenderParams[0].OrthoProjection.M[0][2]               == EyeRenderParams[1].OrthoProjection.M[0][2] );
 140.671 +        OVR_ASSERT ( EyeRenderParams[0].OrthoProjection.M[1][2]               == EyeRenderParams[1].OrthoProjection.M[1][2] );
 140.672 +    }
 140.673 +
 140.674 +    DirtyFlag = false;
 140.675 +}
 140.676 +
 140.677 +
 140.678 +
 140.679 +ViewportScaleAndOffsetBothEyes StereoConfig::setupViewportScaleAndOffsets()
 140.680 +{
 140.681 +    for ( int eyeNum = 0; eyeNum < 2; eyeNum++ )
 140.682 +    {
 140.683 +        StereoEye eyeType = ( eyeNum == 0 ) ? StereoEye_Left : StereoEye_Right;
 140.684 +
 140.685 +        DistortionRenderDesc localDistortion = EyeRenderParams[eyeNum].StereoEye.Distortion;
 140.686 +        FovPort              fov             = EyeRenderParams[eyeNum].StereoEye.Fov;
 140.687 +
 140.688 +        Recti renderedViewport;
 140.689 +        switch ( SetViewportMode )
 140.690 +        {
 140.691 +        case SVPM_Density:
 140.692 +            renderedViewport = CalculateViewportDensityInternal (
 140.693 +                                    eyeType, localDistortion, fov,
 140.694 +                                    RendertargetSize, IsRendertargetSharedByBothEyes,
 140.695 +                                    SetViewportPixelsPerDisplayPixel, OverrideZeroIpd );
 140.696 +            break;
 140.697 +        case SVPM_Size:
 140.698 +            if ( ( eyeType == StereoEye_Right ) && !OverrideZeroIpd )
 140.699 +            {
 140.700 +                renderedViewport = CalculateViewportInternal (
 140.701 +                                        eyeType, RendertargetSize,
 140.702 +                                        SetViewportSize[1],
 140.703 +                                        IsRendertargetSharedByBothEyes, OverrideZeroIpd );
 140.704 +            }
 140.705 +            else
 140.706 +            {
 140.707 +                renderedViewport = CalculateViewportInternal (
 140.708 +                                        eyeType, RendertargetSize,
 140.709 +                                        SetViewportSize[0],
 140.710 +                                        IsRendertargetSharedByBothEyes, OverrideZeroIpd );
 140.711 +            }
 140.712 +            break;
 140.713 +        case SVPM_Viewport:
 140.714 +            if ( ( eyeType == StereoEye_Right ) && !OverrideZeroIpd )
 140.715 +            {
 140.716 +                renderedViewport = SetViewport[1];
 140.717 +            }
 140.718 +            else
 140.719 +            {
 140.720 +                renderedViewport = SetViewport[0];
 140.721 +            }
 140.722 +            break;
 140.723 +        default: OVR_ASSERT ( false ); break;
 140.724 +        }
 140.725 +
 140.726 +        ViewportScaleAndOffset vpsao = CalculateViewportScaleAndOffsetInternal (
 140.727 +                                                EyeRenderParams[eyeNum].StereoEye.EyeToSourceNDC,
 140.728 +                                                renderedViewport,
 140.729 +                                                RendertargetSize );
 140.730 +        EyeRenderParams[eyeNum].StereoEye.RenderedViewport = vpsao.RenderedViewport;
 140.731 +        EyeRenderParams[eyeNum].StereoEye.EyeToSourceUV    = vpsao.EyeToSourceUV;
 140.732 +    }
 140.733 +
 140.734 +    ViewportScaleAndOffsetBothEyes result;
 140.735 +    result.Left.EyeToSourceUV     = EyeRenderParams[0].StereoEye.EyeToSourceUV;
 140.736 +    result.Left.RenderedViewport  = EyeRenderParams[0].StereoEye.RenderedViewport;
 140.737 +    result.Right.EyeToSourceUV    = EyeRenderParams[1].StereoEye.EyeToSourceUV;
 140.738 +    result.Right.RenderedViewport = EyeRenderParams[1].StereoEye.RenderedViewport;
 140.739 +    return result;
 140.740 +}
 140.741 +
 140.742 +// Specify a pixel density - how many rendered pixels per pixel in the physical display.
 140.743 +ViewportScaleAndOffsetBothEyes StereoConfig::SetRenderDensity ( float pixelsPerDisplayPixel )
 140.744 +{
 140.745 +    SetViewportMode  = SVPM_Density;
 140.746 +    SetViewportPixelsPerDisplayPixel = pixelsPerDisplayPixel;
 140.747 +    return setupViewportScaleAndOffsets();
 140.748 +}
 140.749 +
 140.750 +// Supply the size directly. Will be clamped to the physical rendertarget size.
 140.751 +ViewportScaleAndOffsetBothEyes StereoConfig::SetRenderSize ( Sizei const &renderSizeLeft, Sizei const &renderSizeRight )
 140.752 +{
 140.753 +    SetViewportMode  = SVPM_Size;
 140.754 +    SetViewportSize[0] = renderSizeLeft;
 140.755 +    SetViewportSize[1] = renderSizeRight;
 140.756 +    return setupViewportScaleAndOffsets();
 140.757 +}
 140.758 +
 140.759 +// Supply the viewport directly. This is not clamped to the physical rendertarget - careful now!
 140.760 +ViewportScaleAndOffsetBothEyes StereoConfig::SetRenderViewport ( Recti const &renderViewportLeft, Recti const &renderViewportRight )
 140.761 +{
 140.762 +    SetViewportMode  = SVPM_Viewport;
 140.763 +    SetViewport[0] = renderViewportLeft;
 140.764 +    SetViewport[1] = renderViewportRight;
 140.765 +    return setupViewportScaleAndOffsets();
 140.766 +}
 140.767 +
 140.768 +Matrix4f StereoConfig::GetProjectionWithZoom ( StereoEye eye, float fovZoom ) const
 140.769 +{
 140.770 +    int eyeNum = ( eye == StereoEye_Right ) ? 1 : 0;
 140.771 +    float fovScale = 1.0f / fovZoom;
 140.772 +    FovPort fovPort = EyeRenderParams[eyeNum].StereoEye.Fov;
 140.773 +    fovPort.LeftTan  *= fovScale;
 140.774 +    fovPort.RightTan *= fovScale;
 140.775 +    fovPort.UpTan    *= fovScale;
 140.776 +    fovPort.DownTan  *= fovScale;
 140.777 +    return CreateProjection ( RightHandedProjection, fovPort, ZNear, ZFar );
 140.778 +}
 140.779 +
 140.780 +
 140.781 +
 140.782 +
 140.783 +//-----------------------------------------------------------------------------------
 140.784 +// *****  Distortion Mesh Rendering
 140.785 +
 140.786 +
 140.787 +// Pow2 for the Morton order to work!
 140.788 +// 4 is too low - it is easy to see the "wobbles" in the HMD.
 140.789 +// 5 is realllly close but you can see pixel differences with even/odd frame checking.
 140.790 +// 6 is indistinguishable on a monitor on even/odd frames.
 140.791 +static const int DMA_GridSizeLog2   = 6;
 140.792 +static const int DMA_GridSize       = 1<<DMA_GridSizeLog2;
 140.793 +static const int DMA_NumVertsPerEye = (DMA_GridSize+1)*(DMA_GridSize+1);
 140.794 +static const int DMA_NumTrisPerEye  = (DMA_GridSize)*(DMA_GridSize)*2;
 140.795 +
 140.796 +
 140.797 +
 140.798 +DistortionMeshVertexData DistortionMeshMakeVertex ( Vector2f screenNDC,
 140.799 +                                                    bool rightEye,
 140.800 +                                                    const HmdRenderInfo &hmdRenderInfo,
 140.801 +                                                    const DistortionRenderDesc &distortion, const ScaleAndOffset2D &eyeToSourceNDC )
 140.802 +{
 140.803 +    DistortionMeshVertexData result;
 140.804 +
 140.805 +    float xOffset = 0.0f;
 140.806 +    if (rightEye)
 140.807 +    {
 140.808 +        xOffset = 1.0f;
 140.809 +    }
 140.810 +
 140.811 +    Vector2f tanEyeAnglesR, tanEyeAnglesG, tanEyeAnglesB;
 140.812 +    TransformScreenNDCToTanFovSpaceChroma ( &tanEyeAnglesR, &tanEyeAnglesG, &tanEyeAnglesB,
 140.813 +                                            distortion, screenNDC );
 140.814 +
 140.815 +	result.TanEyeAnglesR = tanEyeAnglesR;
 140.816 +	result.TanEyeAnglesG = tanEyeAnglesG;
 140.817 +	result.TanEyeAnglesB = tanEyeAnglesB;
 140.818 +
 140.819 +    HmdShutterTypeEnum shutterType = hmdRenderInfo.Shutter.Type;
 140.820 +    switch ( shutterType )
 140.821 +    {
 140.822 +    case HmdShutter_Global:
 140.823 +        result.TimewarpLerp = 0.0f;
 140.824 +        break;
 140.825 +    case HmdShutter_RollingLeftToRight:
 140.826 +        // Retrace is left to right - left eye goes 0.0 -> 0.5, then right goes 0.5 -> 1.0
 140.827 +        result.TimewarpLerp = screenNDC.x * 0.25f + 0.25f;
 140.828 +        if (rightEye)
 140.829 +        {
 140.830 +            result.TimewarpLerp += 0.5f;
 140.831 +        }
 140.832 +        break;
 140.833 +    case HmdShutter_RollingRightToLeft:
 140.834 +        // Retrace is right to left - right eye goes 0.0 -> 0.5, then left goes 0.5 -> 1.0
 140.835 +        result.TimewarpLerp = 0.75f - screenNDC.x * 0.25f;
 140.836 +        if (rightEye)
 140.837 +        {
 140.838 +            result.TimewarpLerp -= 0.5f;
 140.839 +        }
 140.840 +        break;
 140.841 +    case HmdShutter_RollingTopToBottom:
 140.842 +        // Retrace is top to bottom on both eyes at the same time.
 140.843 +        result.TimewarpLerp = screenNDC.y * 0.5f + 0.5f;
 140.844 +        break;
 140.845 +    default: OVR_ASSERT ( false ); break;
 140.846 +    }
 140.847 +
 140.848 +    // When does the fade-to-black edge start? Chosen heuristically.
 140.849 +    float fadeOutBorderFractionTexture = 0.1f;
 140.850 +    float fadeOutBorderFractionTextureInnerEdge = 0.1f;
 140.851 +    float fadeOutBorderFractionScreen = 0.1f;
 140.852 +    float fadeOutFloor = 0.6f;        // the floor controls how much black is in the fade region
 140.853 +
 140.854 +    if (hmdRenderInfo.HmdType == HmdType_DK1)
 140.855 +    {
 140.856 +        fadeOutBorderFractionTexture = 0.3f;
 140.857 +        fadeOutBorderFractionTextureInnerEdge = 0.075f;
 140.858 +        fadeOutBorderFractionScreen = 0.075f;
 140.859 +        fadeOutFloor = 0.25f;
 140.860 +    }
 140.861 +
 140.862 +    // Fade out at texture edges.
 140.863 +    // The furthest out will be the blue channel, because of chromatic aberration (true of any standard lens)
 140.864 +    Vector2f sourceTexCoordBlueNDC = TransformTanFovSpaceToRendertargetNDC ( eyeToSourceNDC, tanEyeAnglesB );
 140.865 +	if (rightEye)
 140.866 +	{
 140.867 +		// The inner edge of the eye texture is usually much more magnified, because it's right against the middle of the screen, not the FOV edge.
 140.868 +		// So we want a different scaling factor for that. This code flips the texture NDC so that +1.0 is the inner edge
 140.869 +		sourceTexCoordBlueNDC.x = -sourceTexCoordBlueNDC.x;
 140.870 +	}
 140.871 +    float edgeFadeIn               = ( 1.0f / fadeOutBorderFractionTextureInnerEdge ) * ( 1.0f - sourceTexCoordBlueNDC.x )  ;   // Inner
 140.872 +    edgeFadeIn       = Alg::Min ( edgeFadeIn, ( 1.0f / fadeOutBorderFractionTexture ) * ( 1.0f + sourceTexCoordBlueNDC.x ) );   // Outer
 140.873 +    edgeFadeIn       = Alg::Min ( edgeFadeIn, ( 1.0f / fadeOutBorderFractionTexture ) * ( 1.0f - sourceTexCoordBlueNDC.y ) );   // Upper
 140.874 +    edgeFadeIn       = Alg::Min ( edgeFadeIn, ( 1.0f / fadeOutBorderFractionTexture ) * ( 1.0f + sourceTexCoordBlueNDC.y ) );   // Lower
 140.875 +
 140.876 +    // Also fade out at screen edges. Since this is in pixel space, no need to do inner specially.
 140.877 +    float edgeFadeInScreen = ( 1.0f / fadeOutBorderFractionScreen ) *
 140.878 +                             ( 1.0f - Alg::Max ( Alg::Abs ( screenNDC.x ), Alg::Abs ( screenNDC.y ) ) );
 140.879 +    edgeFadeIn = Alg::Min ( edgeFadeInScreen, edgeFadeIn ) + fadeOutFloor;
 140.880 +
 140.881 +	// Note - this is NOT clamped negatively.
 140.882 +	// For rendering methods that interpolate over a coarse grid, we need the values to go negative for correct intersection with zero.
 140.883 +    result.Shade = Alg::Min ( edgeFadeIn, 1.0f );
 140.884 +    result.ScreenPosNDC.x = 0.5f * screenNDC.x - 0.5f + xOffset;
 140.885 +    result.ScreenPosNDC.y = -screenNDC.y;
 140.886 +
 140.887 +    return result;
 140.888 +}
 140.889 +
 140.890 +
 140.891 +void DistortionMeshDestroy ( DistortionMeshVertexData *pVertices, uint16_t *pTriangleMeshIndices )
 140.892 +{
 140.893 +    OVR_FREE ( pVertices );
 140.894 +    OVR_FREE ( pTriangleMeshIndices );
 140.895 +}
 140.896 +
 140.897 +void DistortionMeshCreate ( DistortionMeshVertexData **ppVertices, uint16_t **ppTriangleListIndices,
 140.898 +                            int *pNumVertices, int *pNumTriangles,
 140.899 +                            const StereoEyeParams &stereoParams, const HmdRenderInfo &hmdRenderInfo )
 140.900 +{
 140.901 +    bool    rightEye      = ( stereoParams.Eye == StereoEye_Right );
 140.902 +    int     vertexCount   = 0;
 140.903 +    int     triangleCount = 0;
 140.904 +
 140.905 +    // Generate mesh into allocated data and return result.
 140.906 +    DistortionMeshCreate(ppVertices, ppTriangleListIndices, &vertexCount, &triangleCount,
 140.907 +                         rightEye, hmdRenderInfo, stereoParams.Distortion, stereoParams.EyeToSourceNDC);
 140.908 +
 140.909 +    *pNumVertices  = vertexCount;
 140.910 +    *pNumTriangles = triangleCount;
 140.911 +}
 140.912 +
 140.913 +
 140.914 +// Generate distortion mesh for a eye.
 140.915 +void DistortionMeshCreate( DistortionMeshVertexData **ppVertices, uint16_t **ppTriangleListIndices,
 140.916 +                           int *pNumVertices, int *pNumTriangles,
 140.917 +                           bool rightEye,
 140.918 +                           const HmdRenderInfo &hmdRenderInfo,
 140.919 +                           const DistortionRenderDesc &distortion, const ScaleAndOffset2D &eyeToSourceNDC )
 140.920 +{
 140.921 +    *pNumVertices  = DMA_NumVertsPerEye;
 140.922 +    *pNumTriangles = DMA_NumTrisPerEye;
 140.923 +
 140.924 +    *ppVertices = (DistortionMeshVertexData*)
 140.925 +                      OVR_ALLOC( sizeof(DistortionMeshVertexData) * (*pNumVertices) );
 140.926 +    *ppTriangleListIndices  = (uint16_t*) OVR_ALLOC( sizeof(uint16_t) * (*pNumTriangles) * 3 );
 140.927 +
 140.928 +    if (!*ppVertices || !*ppTriangleListIndices)
 140.929 +    {
 140.930 +        if (*ppVertices)
 140.931 +        {
 140.932 +            OVR_FREE(*ppVertices);
 140.933 +        }
 140.934 +        if (*ppTriangleListIndices)
 140.935 +        {
 140.936 +            OVR_FREE(*ppTriangleListIndices);
 140.937 +        }
 140.938 +        *ppVertices             = NULL;
 140.939 +        *ppTriangleListIndices  = NULL;
 140.940 +        *pNumTriangles          = 0;
 140.941 +        *pNumVertices           = 0;
 140.942 +        return;
 140.943 +    }
 140.944 +
 140.945 +
 140.946 +
 140.947 +    // Populate vertex buffer info
 140.948 +
 140.949 +    // First pass - build up raw vertex data.
 140.950 +    DistortionMeshVertexData* pcurVert = *ppVertices;
 140.951 +
 140.952 +    for ( int y = 0; y <= DMA_GridSize; y++ )
 140.953 +    {
 140.954 +        for ( int x = 0; x <= DMA_GridSize; x++ )
 140.955 +        {
 140.956 +
 140.957 +            Vector2f sourceCoordNDC;
 140.958 +            // NDC texture coords [-1,+1]
 140.959 +            sourceCoordNDC.x = 2.0f * ( (float)x / (float)DMA_GridSize ) - 1.0f;
 140.960 +            sourceCoordNDC.y = 2.0f * ( (float)y / (float)DMA_GridSize ) - 1.0f;
 140.961 +            Vector2f tanEyeAngle = TransformRendertargetNDCToTanFovSpace ( eyeToSourceNDC, sourceCoordNDC );
 140.962 +
 140.963 +            // Find a corresponding screen position.
 140.964 +            // Note - this function does not have to be precise - we're just trying to match the mesh tessellation
 140.965 +            // with the shape of the distortion to minimise the number of trianlges needed.
 140.966 +            Vector2f screenNDC = TransformTanFovSpaceToScreenNDC ( distortion, tanEyeAngle, false );
 140.967 +            // ...but don't let verts overlap to the other eye.
 140.968 +            screenNDC.x = Alg::Max ( -1.0f, Alg::Min ( screenNDC.x, 1.0f ) );
 140.969 +            screenNDC.y = Alg::Max ( -1.0f, Alg::Min ( screenNDC.y, 1.0f ) );
 140.970 +
 140.971 +            // From those screen positions, generate the vertex.
 140.972 +            *pcurVert = DistortionMeshMakeVertex ( screenNDC, rightEye, hmdRenderInfo, distortion, eyeToSourceNDC );
 140.973 +            pcurVert++;
 140.974 +        }
 140.975 +    }
 140.976 +
 140.977 +
 140.978 +    // Populate index buffer info
 140.979 +    uint16_t *pcurIndex = *ppTriangleListIndices;
 140.980 +
 140.981 +    for ( int triNum = 0; triNum < DMA_GridSize * DMA_GridSize; triNum++ )
 140.982 +    {
 140.983 +        // Use a Morton order to help locality of FB, texture and vertex cache.
 140.984 +        // (0.325ms raster order -> 0.257ms Morton order)
 140.985 +        OVR_ASSERT ( DMA_GridSize <= 256 );
 140.986 +        int x = ( ( triNum & 0x0001 ) >> 0 ) |
 140.987 +                ( ( triNum & 0x0004 ) >> 1 ) |
 140.988 +                ( ( triNum & 0x0010 ) >> 2 ) |
 140.989 +                ( ( triNum & 0x0040 ) >> 3 ) |
 140.990 +                ( ( triNum & 0x0100 ) >> 4 ) |
 140.991 +                ( ( triNum & 0x0400 ) >> 5 ) |
 140.992 +                ( ( triNum & 0x1000 ) >> 6 ) |
 140.993 +                ( ( triNum & 0x4000 ) >> 7 );
 140.994 +        int y = ( ( triNum & 0x0002 ) >> 1 ) |
 140.995 +                ( ( triNum & 0x0008 ) >> 2 ) |
 140.996 +                ( ( triNum & 0x0020 ) >> 3 ) |
 140.997 +                ( ( triNum & 0x0080 ) >> 4 ) |
 140.998 +                ( ( triNum & 0x0200 ) >> 5 ) |
 140.999 +                ( ( triNum & 0x0800 ) >> 6 ) |
140.1000 +                ( ( triNum & 0x2000 ) >> 7 ) |
140.1001 +                ( ( triNum & 0x8000 ) >> 8 );
140.1002 +        int FirstVertex = x * (DMA_GridSize+1) + y;
140.1003 +        // Another twist - we want the top-left and bottom-right quadrants to
140.1004 +        // have the triangles split one way, the other two split the other.
140.1005 +        // +---+---+---+---+
140.1006 +        // |  /|  /|\  |\  |
140.1007 +        // | / | / | \ | \ |
140.1008 +        // |/  |/  |  \|  \|
140.1009 +        // +---+---+---+---+
140.1010 +        // |  /|  /|\  |\  |
140.1011 +        // | / | / | \ | \ |
140.1012 +        // |/  |/  |  \|  \|
140.1013 +        // +---+---+---+---+
140.1014 +        // |\  |\  |  /|  /|
140.1015 +        // | \ | \ | / | / |
140.1016 +        // |  \|  \|/  |/  |
140.1017 +        // +---+---+---+---+
140.1018 +        // |\  |\  |  /|  /|
140.1019 +        // | \ | \ | / | / |
140.1020 +        // |  \|  \|/  |/  |
140.1021 +        // +---+---+---+---+
140.1022 +        // This way triangle edges don't span long distances over the distortion function,
140.1023 +        // so linear interpolation works better & we can use fewer tris.
140.1024 +        if ( ( x < DMA_GridSize/2 ) != ( y < DMA_GridSize/2 ) )       // != is logical XOR
140.1025 +        {
140.1026 +            *pcurIndex++ = (uint16_t)FirstVertex;
140.1027 +            *pcurIndex++ = (uint16_t)FirstVertex+1;
140.1028 +            *pcurIndex++ = (uint16_t)FirstVertex+(DMA_GridSize+1)+1;
140.1029 +
140.1030 +            *pcurIndex++ = (uint16_t)FirstVertex+(DMA_GridSize+1)+1;
140.1031 +            *pcurIndex++ = (uint16_t)FirstVertex+(DMA_GridSize+1);
140.1032 +            *pcurIndex++ = (uint16_t)FirstVertex;
140.1033 +        }
140.1034 +        else
140.1035 +        {
140.1036 +            *pcurIndex++ = (uint16_t)FirstVertex;
140.1037 +            *pcurIndex++ = (uint16_t)FirstVertex+1;
140.1038 +            *pcurIndex++ = (uint16_t)FirstVertex+(DMA_GridSize+1);
140.1039 +
140.1040 +            *pcurIndex++ = (uint16_t)FirstVertex+1;
140.1041 +            *pcurIndex++ = (uint16_t)FirstVertex+(DMA_GridSize+1)+1;
140.1042 +            *pcurIndex++ = (uint16_t)FirstVertex+(DMA_GridSize+1);
140.1043 +        }
140.1044 +    }
140.1045 +}
140.1046 +
140.1047 +//-----------------------------------------------------------------------------------
140.1048 +// *****  Heightmap Mesh Rendering
140.1049 +
140.1050 +
140.1051 +static const int HMA_GridSizeLog2   = 7;
140.1052 +static const int HMA_GridSize       = 1<<HMA_GridSizeLog2;
140.1053 +static const int HMA_NumVertsPerEye = (HMA_GridSize+1)*(HMA_GridSize+1);
140.1054 +static const int HMA_NumTrisPerEye  = (HMA_GridSize)*(HMA_GridSize)*2;
140.1055 +
140.1056 +
140.1057 +void HeightmapMeshDestroy ( HeightmapMeshVertexData *pVertices, uint16_t *pTriangleMeshIndices )
140.1058 +{
140.1059 +    OVR_FREE ( pVertices );
140.1060 +    OVR_FREE ( pTriangleMeshIndices );
140.1061 +}
140.1062 +
140.1063 +void HeightmapMeshCreate ( HeightmapMeshVertexData **ppVertices, uint16_t **ppTriangleListIndices,
140.1064 +    int *pNumVertices, int *pNumTriangles,
140.1065 +    const StereoEyeParams &stereoParams, const HmdRenderInfo &hmdRenderInfo )
140.1066 +{
140.1067 +    bool    rightEye      = ( stereoParams.Eye == StereoEye_Right );
140.1068 +    int     vertexCount   = 0;
140.1069 +    int     triangleCount = 0;
140.1070 +
140.1071 +    // Generate mesh into allocated data and return result.
140.1072 +    HeightmapMeshCreate(ppVertices, ppTriangleListIndices, &vertexCount, &triangleCount,
140.1073 +        rightEye, hmdRenderInfo, stereoParams.EyeToSourceNDC);
140.1074 +
140.1075 +    *pNumVertices  = vertexCount;
140.1076 +    *pNumTriangles = triangleCount;
140.1077 +}
140.1078 +
140.1079 +
140.1080 +// Generate heightmap mesh for one eye.
140.1081 +void HeightmapMeshCreate( HeightmapMeshVertexData **ppVertices, uint16_t **ppTriangleListIndices,
140.1082 +    int *pNumVertices, int *pNumTriangles, bool rightEye,
140.1083 +    const HmdRenderInfo &hmdRenderInfo,
140.1084 +    const ScaleAndOffset2D &eyeToSourceNDC )
140.1085 +{
140.1086 +    *pNumVertices  = HMA_NumVertsPerEye;
140.1087 +    *pNumTriangles = HMA_NumTrisPerEye;
140.1088 +
140.1089 +    *ppVertices = (HeightmapMeshVertexData*) OVR_ALLOC( sizeof(HeightmapMeshVertexData) * (*pNumVertices) );
140.1090 +    *ppTriangleListIndices  = (uint16_t*) OVR_ALLOC( sizeof(uint16_t) * (*pNumTriangles) * 3 );
140.1091 +
140.1092 +    if (!*ppVertices || !*ppTriangleListIndices)
140.1093 +    {
140.1094 +        if (*ppVertices)
140.1095 +        {
140.1096 +            OVR_FREE(*ppVertices);
140.1097 +        }
140.1098 +        if (*ppTriangleListIndices)
140.1099 +        {
140.1100 +            OVR_FREE(*ppTriangleListIndices);
140.1101 +        }
140.1102 +        *ppVertices             = NULL;
140.1103 +        *ppTriangleListIndices  = NULL;
140.1104 +        *pNumTriangles          = 0;
140.1105 +        *pNumVertices           = 0;
140.1106 +        return;
140.1107 +    }
140.1108 +
140.1109 +    // Populate vertex buffer info
140.1110 +    // float xOffset = (rightEye ? 1.0f : 0.0f);  Currently disabled because its usage is disabled below.
140.1111 +
140.1112 +    // First pass - build up raw vertex data.
140.1113 +    HeightmapMeshVertexData* pcurVert = *ppVertices;
140.1114 +
140.1115 +    for ( int y = 0; y <= HMA_GridSize; y++ )
140.1116 +    {
140.1117 +        for ( int x = 0; x <= HMA_GridSize; x++ )
140.1118 +        {
140.1119 +            Vector2f sourceCoordNDC;
140.1120 +            // NDC texture coords [-1,+1]
140.1121 +            sourceCoordNDC.x = 2.0f * ( (float)x / (float)HMA_GridSize ) - 1.0f;
140.1122 +            sourceCoordNDC.y = 2.0f * ( (float)y / (float)HMA_GridSize ) - 1.0f;
140.1123 +            Vector2f tanEyeAngle = TransformRendertargetNDCToTanFovSpace ( eyeToSourceNDC, sourceCoordNDC );
140.1124 +
140.1125 +            pcurVert->TanEyeAngles = tanEyeAngle;
140.1126 +
140.1127 +            HmdShutterTypeEnum shutterType = hmdRenderInfo.Shutter.Type;
140.1128 +            switch ( shutterType )
140.1129 +            {
140.1130 +            case HmdShutter_Global:
140.1131 +                pcurVert->TimewarpLerp = 0.0f;
140.1132 +                break;
140.1133 +            case HmdShutter_RollingLeftToRight:
140.1134 +                // Retrace is left to right - left eye goes 0.0 -> 0.5, then right goes 0.5 -> 1.0
140.1135 +                pcurVert->TimewarpLerp = sourceCoordNDC.x * 0.25f + 0.25f;
140.1136 +                if (rightEye)
140.1137 +                {
140.1138 +                    pcurVert->TimewarpLerp += 0.5f;
140.1139 +                }
140.1140 +                break;
140.1141 +            case HmdShutter_RollingRightToLeft:
140.1142 +                // Retrace is right to left - right eye goes 0.0 -> 0.5, then left goes 0.5 -> 1.0
140.1143 +                pcurVert->TimewarpLerp = 0.75f - sourceCoordNDC.x * 0.25f;
140.1144 +                if (rightEye)
140.1145 +                {
140.1146 +                    pcurVert->TimewarpLerp -= 0.5f;
140.1147 +                }
140.1148 +                break;
140.1149 +            case HmdShutter_RollingTopToBottom:
140.1150 +                // Retrace is top to bottom on both eyes at the same time.
140.1151 +                pcurVert->TimewarpLerp = sourceCoordNDC.y * 0.5f + 0.5f;
140.1152 +                break;
140.1153 +            default: OVR_ASSERT ( false ); break;
140.1154 +            }
140.1155 +
140.1156 +            // Don't let verts overlap to the other eye.
140.1157 +            //sourceCoordNDC.x = Alg::Max ( -1.0f, Alg::Min ( sourceCoordNDC.x, 1.0f ) );
140.1158 +            //sourceCoordNDC.y = Alg::Max ( -1.0f, Alg::Min ( sourceCoordNDC.y, 1.0f ) );
140.1159 +
140.1160 +            //pcurVert->ScreenPosNDC.x = 0.5f * sourceCoordNDC.x - 0.5f + xOffset;
140.1161 +            pcurVert->ScreenPosNDC.x = sourceCoordNDC.x;
140.1162 +            pcurVert->ScreenPosNDC.y = -sourceCoordNDC.y;
140.1163 +
140.1164 +            pcurVert++;
140.1165 +        }
140.1166 +    }
140.1167 +
140.1168 +
140.1169 +    // Populate index buffer info
140.1170 +    uint16_t *pcurIndex = *ppTriangleListIndices;
140.1171 +
140.1172 +    for ( int triNum = 0; triNum < HMA_GridSize * HMA_GridSize; triNum++ )
140.1173 +    {
140.1174 +        // Use a Morton order to help locality of FB, texture and vertex cache.
140.1175 +        // (0.325ms raster order -> 0.257ms Morton order)
140.1176 +        OVR_ASSERT ( HMA_GridSize < 256 );
140.1177 +        int x = ( ( triNum & 0x0001 ) >> 0 ) |
140.1178 +                ( ( triNum & 0x0004 ) >> 1 ) |
140.1179 +                ( ( triNum & 0x0010 ) >> 2 ) |
140.1180 +                ( ( triNum & 0x0040 ) >> 3 ) |
140.1181 +                ( ( triNum & 0x0100 ) >> 4 ) |
140.1182 +                ( ( triNum & 0x0400 ) >> 5 ) |
140.1183 +                ( ( triNum & 0x1000 ) >> 6 ) |
140.1184 +                ( ( triNum & 0x4000 ) >> 7 );
140.1185 +        int y = ( ( triNum & 0x0002 ) >> 1 ) |
140.1186 +                ( ( triNum & 0x0008 ) >> 2 ) |
140.1187 +                ( ( triNum & 0x0020 ) >> 3 ) |
140.1188 +                ( ( triNum & 0x0080 ) >> 4 ) |
140.1189 +                ( ( triNum & 0x0200 ) >> 5 ) |
140.1190 +                ( ( triNum & 0x0800 ) >> 6 ) |
140.1191 +                ( ( triNum & 0x2000 ) >> 7 ) |
140.1192 +                ( ( triNum & 0x8000 ) >> 8 );
140.1193 +        int FirstVertex = x * (HMA_GridSize+1) + y;
140.1194 +        // Another twist - we want the top-left and bottom-right quadrants to
140.1195 +        // have the triangles split one way, the other two split the other.
140.1196 +        // +---+---+---+---+
140.1197 +        // |  /|  /|\  |\  |
140.1198 +        // | / | / | \ | \ |
140.1199 +        // |/  |/  |  \|  \|
140.1200 +        // +---+---+---+---+
140.1201 +        // |  /|  /|\  |\  |
140.1202 +        // | / | / | \ | \ |
140.1203 +        // |/  |/  |  \|  \|
140.1204 +        // +---+---+---+---+
140.1205 +        // |\  |\  |  /|  /|
140.1206 +        // | \ | \ | / | / |
140.1207 +        // |  \|  \|/  |/  |
140.1208 +        // +---+---+---+---+
140.1209 +        // |\  |\  |  /|  /|
140.1210 +        // | \ | \ | / | / |
140.1211 +        // |  \|  \|/  |/  |
140.1212 +        // +---+---+---+---+
140.1213 +        // This way triangle edges don't span long distances over the distortion function,
140.1214 +        // so linear interpolation works better & we can use fewer tris.
140.1215 +        if ( ( x < HMA_GridSize/2 ) != ( y < HMA_GridSize/2 ) )       // != is logical XOR
140.1216 +        {
140.1217 +            *pcurIndex++ = (uint16_t)FirstVertex;
140.1218 +            *pcurIndex++ = (uint16_t)FirstVertex+1;
140.1219 +            *pcurIndex++ = (uint16_t)FirstVertex+(HMA_GridSize+1)+1;
140.1220 +
140.1221 +            *pcurIndex++ = (uint16_t)FirstVertex+(HMA_GridSize+1)+1;
140.1222 +            *pcurIndex++ = (uint16_t)FirstVertex+(HMA_GridSize+1);
140.1223 +            *pcurIndex++ = (uint16_t)FirstVertex;
140.1224 +        }
140.1225 +        else
140.1226 +        {
140.1227 +            *pcurIndex++ = (uint16_t)FirstVertex;
140.1228 +            *pcurIndex++ = (uint16_t)FirstVertex+1;
140.1229 +            *pcurIndex++ = (uint16_t)FirstVertex+(HMA_GridSize+1);
140.1230 +
140.1231 +            *pcurIndex++ = (uint16_t)FirstVertex+1;
140.1232 +            *pcurIndex++ = (uint16_t)FirstVertex+(HMA_GridSize+1)+1;
140.1233 +            *pcurIndex++ = (uint16_t)FirstVertex+(HMA_GridSize+1);
140.1234 +        }
140.1235 +    }
140.1236 +}
140.1237 +
140.1238 +//-----------------------------------------------------------------------------------
140.1239 +// ***** Prediction and timewarp.
140.1240 +//
140.1241 +
140.1242 +// Calculates the values from the HMD info.
140.1243 +PredictionValues PredictionGetDeviceValues ( const HmdRenderInfo &hmdRenderInfo,
140.1244 +                                             bool withTimewarp /*= true*/,
140.1245 +                                             bool withVsync /*= true*/ )
140.1246 +{
140.1247 +    PredictionValues result;
140.1248 +
140.1249 +    result.WithTimewarp = withTimewarp;
140.1250 +    result.WithVsync = withVsync;
140.1251 +
140.1252 +    // For unclear reasons, most graphics systems add an extra frame of latency
140.1253 +    // somewhere along the way. In time we'll debug this and figure it out, but
140.1254 +    // for now this gets prediction a little bit better.
140.1255 +    const float extraFramesOfBufferingKludge = 1.0f;
140.1256 +
140.1257 +    if ( withVsync )
140.1258 +    {
140.1259 +        // These are the times from the Present+Flush to when the middle of the scene is "averagely visible" (without timewarp)
140.1260 +        // So if you had no timewarp, this, plus the time until the next vsync, is how much to predict by.
140.1261 +        result.PresentFlushToRenderedScene  = extraFramesOfBufferingKludge * hmdRenderInfo.Shutter.FirstScanlineToLastScanline;
140.1262 +        // Predict to the middle of the screen being scanned out.
140.1263 +        result.PresentFlushToRenderedScene += hmdRenderInfo.Shutter.VsyncToFirstScanline + 0.5f * hmdRenderInfo.Shutter.FirstScanlineToLastScanline;
140.1264 +        // Time for pixels to get half-way to settling.
140.1265 +        result.PresentFlushToRenderedScene += hmdRenderInfo.Shutter.PixelSettleTime * 0.5f;
140.1266 +        // Predict to half-way through persistence
140.1267 +        result.PresentFlushToRenderedScene += hmdRenderInfo.Shutter.PixelPersistence * 0.5f;
140.1268 +
140.1269 +        // The time from the Present+Flush to when the first scanline is "averagely visible".
140.1270 +        result.PresentFlushToTimewarpStart  = extraFramesOfBufferingKludge * hmdRenderInfo.Shutter.FirstScanlineToLastScanline;
140.1271 +        // Predict to the first line being scanned out.
140.1272 +        result.PresentFlushToTimewarpStart += hmdRenderInfo.Shutter.VsyncToFirstScanline;
140.1273 +        // Time for pixels to get half-way to settling.
140.1274 +        result.PresentFlushToTimewarpStart += hmdRenderInfo.Shutter.PixelSettleTime * 0.5f;
140.1275 +        // Predict to half-way through persistence
140.1276 +        result.PresentFlushToTimewarpStart += hmdRenderInfo.Shutter.PixelPersistence * 0.5f;
140.1277 +
140.1278 +        // Time to the the last scanline.
140.1279 +        result.PresentFlushToTimewarpEnd    = result.PresentFlushToTimewarpStart + hmdRenderInfo.Shutter.FirstScanlineToLastScanline;
140.1280 +
140.1281 +        // Ideal framerate.
140.1282 +        result.PresentFlushToPresentFlush   = hmdRenderInfo.Shutter.VsyncToNextVsync;
140.1283 +    }
140.1284 +    else
140.1285 +    {
140.1286 +        // Timewarp without vsync is a little odd.
140.1287 +        // Currently, we assume that without vsync, we have no idea which scanline
140.1288 +        // is currently being sent to the display. So we can't do lerping timewarp,
140.1289 +        // we can just do a full-screen late-stage fixup.
140.1290 +
140.1291 +        // "PresentFlushToRenderedScene" means the time from the Present+Flush to when the middle of the scene is "averagely visible" (without timewarp)
140.1292 +        // So if you had no timewarp, this, plus the time until the next flush (which is usually the time to render the frame), is how much to predict by.
140.1293 +        // Time for pixels to get half-way to settling.
140.1294 +        result.PresentFlushToRenderedScene  = hmdRenderInfo.Shutter.PixelSettleTime * 0.5f;
140.1295 +        // Predict to half-way through persistence
140.1296 +        result.PresentFlushToRenderedScene += hmdRenderInfo.Shutter.PixelPersistence * 0.5f;
140.1297 +
140.1298 +        // Without vsync, you don't know timings, and so can't do anything useful with lerped warping.
140.1299 +        result.PresentFlushToTimewarpStart  = result.PresentFlushToRenderedScene;
140.1300 +        result.PresentFlushToTimewarpEnd    = result.PresentFlushToRenderedScene;
140.1301 +
140.1302 +        // There's no concept of "ideal" when vsync is off.
140.1303 +        result.PresentFlushToPresentFlush   = 0.0f;
140.1304 +    }
140.1305 +
140.1306 +    return result;
140.1307 +}
140.1308 +
140.1309 +Matrix4f TimewarpComputePoseDelta ( Matrix4f const &renderedViewFromWorld, Matrix4f const &predictedViewFromWorld, Matrix4f const&hmdToEyeViewOffset )
140.1310 +{
140.1311 +    Matrix4f worldFromPredictedView = (hmdToEyeViewOffset * predictedViewFromWorld).InvertedHomogeneousTransform();
140.1312 +    Matrix4f matRenderFromNowStart = (hmdToEyeViewOffset * renderedViewFromWorld) * worldFromPredictedView;
140.1313 +
140.1314 +    // The sensor-predicted orientations have:                           X=right, Y=up,   Z=backwards.
140.1315 +    // The vectors inside the mesh are in NDC to keep the shader simple: X=right, Y=down, Z=forwards.
140.1316 +    // So we need to perform a similarity transform on this delta matrix.
140.1317 +    // The verbose code would look like this:
140.1318 +    /*
140.1319 +    Matrix4f matBasisChange;
140.1320 +    matBasisChange.SetIdentity();
140.1321 +    matBasisChange.M[0][0] =  1.0f;
140.1322 +    matBasisChange.M[1][1] = -1.0f;
140.1323 +    matBasisChange.M[2][2] = -1.0f;
140.1324 +    Matrix4f matBasisChangeInv = matBasisChange.Inverted();
140.1325 +    matRenderFromNow = matBasisChangeInv * matRenderFromNow * matBasisChange;
140.1326 +    */
140.1327 +    // ...but of course all the above is a constant transform and much more easily done.
140.1328 +    // We flip the signs of the Y&Z row, then flip the signs of the Y&Z column,
140.1329 +    // and of course most of the flips cancel:
140.1330 +    // +++                        +--                     +--
140.1331 +    // +++ -> flip Y&Z columns -> +-- -> flip Y&Z rows -> -++
140.1332 +    // +++                        +--                     -++
140.1333 +    matRenderFromNowStart.M[0][1] = -matRenderFromNowStart.M[0][1];
140.1334 +    matRenderFromNowStart.M[0][2] = -matRenderFromNowStart.M[0][2];
140.1335 +    matRenderFromNowStart.M[1][0] = -matRenderFromNowStart.M[1][0];
140.1336 +    matRenderFromNowStart.M[2][0] = -matRenderFromNowStart.M[2][0];
140.1337 +    matRenderFromNowStart.M[1][3] = -matRenderFromNowStart.M[1][3];
140.1338 +    matRenderFromNowStart.M[2][3] = -matRenderFromNowStart.M[2][3];
140.1339 +
140.1340 +    return matRenderFromNowStart;
140.1341 +}
140.1342 +
140.1343 +Matrix4f TimewarpComputePoseDeltaPosition ( Matrix4f const &renderedViewFromWorld, Matrix4f const &predictedViewFromWorld, Matrix4f const&hmdToEyeViewOffset )
140.1344 +{
140.1345 +    Matrix4f worldFromPredictedView = (hmdToEyeViewOffset * predictedViewFromWorld).InvertedHomogeneousTransform();
140.1346 +    Matrix4f matRenderXform = (hmdToEyeViewOffset * renderedViewFromWorld) * worldFromPredictedView;
140.1347 +
140.1348 +    return matRenderXform.Inverted();
140.1349 +}
140.1350 +
140.1351 +TimewarpMachine::TimewarpMachine()
140.1352 +  : VsyncEnabled(false),
140.1353 +    RenderInfo(),
140.1354 +    CurrentPredictionValues(),
140.1355 +    DistortionTimeCount(0),
140.1356 +    DistortionTimeCurrentStart(0.0),
140.1357 +  //DistortionTimes[],
140.1358 +    DistortionTimeAverage(0.f),
140.1359 +  //EyeRenderPoses[],
140.1360 +    LastFramePresentFlushTime(0.0),
140.1361 +    PresentFlushToPresentFlushSeconds(0.f),
140.1362 +    NextFramePresentFlushTime(0.0)
140.1363 +{
140.1364 +    #if defined(OVR_BUILD_DEBUG)
140.1365 +        memset(DistortionTimes, 0, sizeof(DistortionTimes));
140.1366 +    #endif
140.1367 +
140.1368 +    for ( int i = 0; i < 2; i++ )
140.1369 +    {
140.1370 +        EyeRenderPoses[i] = Posef();
140.1371 +    }
140.1372 +}
140.1373 +
140.1374 +void TimewarpMachine::Reset(HmdRenderInfo& renderInfo, bool vsyncEnabled, double timeNow)
140.1375 +{
140.1376 +    RenderInfo = renderInfo;
140.1377 +    VsyncEnabled = vsyncEnabled;
140.1378 +    CurrentPredictionValues = PredictionGetDeviceValues ( renderInfo, true, VsyncEnabled );
140.1379 +    PresentFlushToPresentFlushSeconds = 0.0f;
140.1380 +    DistortionTimeCount = 0;
140.1381 +    DistortionTimeAverage = 0.0f;
140.1382 +    LastFramePresentFlushTime = timeNow;
140.1383 +    AfterPresentAndFlush(timeNow);
140.1384 +}
140.1385 +
140.1386 +void TimewarpMachine::AfterPresentAndFlush(double timeNow)
140.1387 +{
140.1388 +    AfterPresentWithoutFlush();
140.1389 +    AfterPresentFinishes ( timeNow );
140.1390 +}
140.1391 +
140.1392 +void TimewarpMachine::AfterPresentWithoutFlush()
140.1393 +{
140.1394 +    // We've only issued the Present - it hasn't actually finished (i.e. appeared)
140.1395 +    // But we need to estimate when the next Present will appear, so extrapolate from previous data.
140.1396 +    NextFramePresentFlushTime = LastFramePresentFlushTime + 2.0 * (double)PresentFlushToPresentFlushSeconds;
140.1397 +}
140.1398 +
140.1399 +void TimewarpMachine::AfterPresentFinishes(double timeNow)
140.1400 +{
140.1401 +    // The present has now actually happened.
140.1402 +    PresentFlushToPresentFlushSeconds = (float)(timeNow - LastFramePresentFlushTime);
140.1403 +    LastFramePresentFlushTime = timeNow;
140.1404 +    NextFramePresentFlushTime = timeNow + (double)PresentFlushToPresentFlushSeconds;
140.1405 +}
140.1406 +
140.1407 +
140.1408 +
140.1409 +double TimewarpMachine::GetViewRenderPredictionTime()
140.1410 +{
140.1411 +    // Note that PredictionGetDeviceValues() did all the vsync-dependent thinking for us.
140.1412 +    return NextFramePresentFlushTime + CurrentPredictionValues.PresentFlushToRenderedScene;
140.1413 +}
140.1414 +
140.1415 +bool TimewarpMachine::GetViewRenderPredictionPose(SensorStateReader* reader, Posef& pose)
140.1416 +{
140.1417 +	return reader->GetPoseAtTime(GetViewRenderPredictionTime(), pose);
140.1418 +}
140.1419 +
140.1420 +double TimewarpMachine::GetVisiblePixelTimeStart()
140.1421 +{
140.1422 +    // Note that PredictionGetDeviceValues() did all the vsync-dependent thinking for us.
140.1423 +    return NextFramePresentFlushTime + CurrentPredictionValues.PresentFlushToTimewarpStart;
140.1424 +}
140.1425 +double TimewarpMachine::GetVisiblePixelTimeEnd()
140.1426 +{
140.1427 +    // Note that PredictionGetDeviceValues() did all the vsync-dependent thinking for us.
140.1428 +    return NextFramePresentFlushTime + CurrentPredictionValues.PresentFlushToTimewarpEnd;
140.1429 +}
140.1430 +bool TimewarpMachine::GetPredictedVisiblePixelPoseStart(SensorStateReader* reader, Posef& pose)
140.1431 +{
140.1432 +	return reader->GetPoseAtTime(GetVisiblePixelTimeStart(), pose);
140.1433 +}
140.1434 +bool TimewarpMachine::GetPredictedVisiblePixelPoseEnd(SensorStateReader* reader, Posef& pose)
140.1435 +{
140.1436 +	return reader->GetPoseAtTime(GetVisiblePixelTimeEnd(), pose);
140.1437 +}
140.1438 +bool TimewarpMachine::GetTimewarpDeltaStart(SensorStateReader* reader, Posef const &renderedPose, Matrix4f& transform)
140.1439 +{
140.1440 +	Posef visiblePose;
140.1441 +	if (!GetPredictedVisiblePixelPoseStart(reader, visiblePose))
140.1442 +	{
140.1443 +		return false;
140.1444 +	}
140.1445 +
140.1446 +    Matrix4f visibleMatrix(visiblePose);
140.1447 +    Matrix4f renderedMatrix(renderedPose);
140.1448 +    Matrix4f identity;  // doesn't matter for orientation-only timewarp
140.1449 +    transform = TimewarpComputePoseDelta ( renderedMatrix, visibleMatrix, identity );
140.1450 +
140.1451 +	return true;
140.1452 +}
140.1453 +bool TimewarpMachine::GetTimewarpDeltaEnd(SensorStateReader* reader, Posef const &renderedPose, Matrix4f& transform)
140.1454 +{
140.1455 +	Posef visiblePose;
140.1456 +	if (!GetPredictedVisiblePixelPoseEnd(reader, visiblePose))
140.1457 +	{
140.1458 +		return false;
140.1459 +	}
140.1460 +
140.1461 +    Matrix4f visibleMatrix(visiblePose);
140.1462 +    Matrix4f renderedMatrix(renderedPose);
140.1463 +    Matrix4f identity;  // doesn't matter for orientation-only timewarp
140.1464 +    transform = TimewarpComputePoseDelta ( renderedMatrix, visibleMatrix, identity );
140.1465 +
140.1466 +	return true;
140.1467 +}
140.1468 +
140.1469 +
140.1470 +// What time should the app wait until before starting distortion?
140.1471 +double  TimewarpMachine::JustInTime_GetDistortionWaitUntilTime()
140.1472 +{
140.1473 +    if ( !VsyncEnabled || ( DistortionTimeCount < NumDistortionTimes ) )
140.1474 +    {
140.1475 +        // Don't wait.
140.1476 +        return LastFramePresentFlushTime;
140.1477 +    }
140.1478 +
140.1479 +    // Note - 1-2ms fudge factor (because Windows timer granularity etc) is NOT added here,
140.1480 +    // because otherwise you end up adding multiple fudge factors!
140.1481 +    // So it's left for the calling app to add just one fudge factor.
140.1482 +
140.1483 +    float howLongBeforePresent = DistortionTimeAverage;
140.1484 +    // Subtlety here. Technically, the correct time is NextFramePresentFlushTime - howLongBeforePresent.
140.1485 +    // However, if the app drops a frame, this then perpetuates it,
140.1486 +    // i.e. if the display is running at 60fps, but the last frame was slow,
140.1487 +    // (e.g. because of swapping or whatever), then NextFramePresentFlushTime is
140.1488 +    // 33ms in the future, not 16ms. Since this function supplies the
140.1489 +    // time to wait until, the app will indeed wait until 32ms, so the framerate
140.1490 +    // drops to 30fps and never comes back up!
140.1491 +    // So we return the *ideal* framerate, not the *actual* framerate.
140.1492 +    return LastFramePresentFlushTime + (float)( CurrentPredictionValues.PresentFlushToPresentFlush - howLongBeforePresent );
140.1493 +}
140.1494 +
140.1495 +double TimewarpMachine::JustInTime_AverageDistortionTime()
140.1496 +{
140.1497 +    if ( JustInTime_NeedDistortionTimeMeasurement() )
140.1498 +    {
140.1499 +        return 0.0;
140.1500 +    }
140.1501 +    return DistortionTimeAverage;
140.1502 +}
140.1503 +
140.1504 +bool    TimewarpMachine::JustInTime_NeedDistortionTimeMeasurement() const
140.1505 +{
140.1506 +    if (!VsyncEnabled)
140.1507 +    {
140.1508 +        return false;
140.1509 +    }
140.1510 +    return ( DistortionTimeCount < NumDistortionTimes );
140.1511 +}
140.1512 +
140.1513 +void    TimewarpMachine::JustInTime_BeforeDistortionTimeMeasurement(double timeNow)
140.1514 +{
140.1515 +    DistortionTimeCurrentStart = timeNow;
140.1516 +}
140.1517 +
140.1518 +void    TimewarpMachine::JustInTime_AfterDistortionTimeMeasurement(double timeNow)
140.1519 +{
140.1520 +    float timeDelta = (float)( timeNow - DistortionTimeCurrentStart );
140.1521 +    if ( DistortionTimeCount < NumDistortionTimes )
140.1522 +    {
140.1523 +        DistortionTimes[DistortionTimeCount] = timeDelta;
140.1524 +        DistortionTimeCount++;
140.1525 +        if ( DistortionTimeCount == NumDistortionTimes )
140.1526 +        {
140.1527 +            // Median.
140.1528 +            float distortionTimeMedian = 0.0f;
140.1529 +            for ( int i = 0; i < NumDistortionTimes/2; i++ )
140.1530 +            {
140.1531 +                // Find the maximum time of those remaining.
140.1532 +                float maxTime = DistortionTimes[0];
140.1533 +                int maxIndex = 0;
140.1534 +                for ( int j = 1; j < NumDistortionTimes; j++ )
140.1535 +                {
140.1536 +                    if ( maxTime < DistortionTimes[j] )
140.1537 +                    {
140.1538 +                        maxTime = DistortionTimes[j];
140.1539 +                        maxIndex = j;
140.1540 +                    }
140.1541 +                }
140.1542 +                // Zero that max time, so we'll find the next-highest time.
140.1543 +                DistortionTimes[maxIndex] = 0.0f;
140.1544 +                distortionTimeMedian = maxTime;
140.1545 +            }
140.1546 +            DistortionTimeAverage = distortionTimeMedian;
140.1547 +        }
140.1548 +    }
140.1549 +    else
140.1550 +    {
140.1551 +        OVR_ASSERT ( !"Really didn't need more measurements, thanks" );
140.1552 +    }
140.1553 +}
140.1554 +
140.1555 +
140.1556 +}}}  // OVR::Util::Render
140.1557 +
   141.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   141.2 +++ b/LibOVR/Src/Util/Util_Render_Stereo.h	Wed Jan 14 06:51:16 2015 +0200
   141.3 @@ -0,0 +1,500 @@
   141.4 +/************************************************************************************
   141.5 +
   141.6 +Filename    :   Util_Render_Stereo.h
   141.7 +Content     :   Sample stereo rendering configuration classes.
   141.8 +Created     :   October 22, 2012
   141.9 +Authors     :   Michael Antonov, Tom Forsyth
  141.10 +
  141.11 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
  141.12 +
  141.13 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
  141.14 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
  141.15 +which is provided at the time of installation or download, or which 
  141.16 +otherwise accompanies this software in either electronic or hard copy form.
  141.17 +
  141.18 +You may obtain a copy of the License at
  141.19 +
  141.20 +http://www.oculusvr.com/licenses/LICENSE-3.2 
  141.21 +
  141.22 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
  141.23 +distributed under the License is distributed on an "AS IS" BASIS,
  141.24 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  141.25 +See the License for the specific language governing permissions and
  141.26 +limitations under the License.
  141.27 +
  141.28 +*************************************************************************************/
  141.29 +
  141.30 +#ifndef OVR_Util_Render_Stereo_h
  141.31 +#define OVR_Util_Render_Stereo_h
  141.32 +
  141.33 +#include "../OVR_Stereo.h"
  141.34 +#include "../Tracking/Tracking_SensorStateReader.h"
  141.35 +
  141.36 +namespace OVR { namespace Util { namespace Render {
  141.37 +
  141.38 +
  141.39 +
  141.40 +//-----------------------------------------------------------------------------------
  141.41 +// **** Useful debug functions.
  141.42 +//
  141.43 +// Purely for debugging - the results are not very end-user-friendly.
  141.44 +char const* GetDebugNameEyeCupType ( EyeCupType eyeCupType );
  141.45 +char const* GetDebugNameHmdType ( HmdTypeEnum hmdType );
  141.46 +
  141.47 +
  141.48 +
  141.49 +//-----------------------------------------------------------------------------------
  141.50 +// **** Higher-level utility functions.
  141.51 +
  141.52 +Sizei CalculateRecommendedTextureSize    ( HmdRenderInfo const &hmd,
  141.53 +                                           bool bRendertargetSharedByBothEyes,
  141.54 +                                           float pixelDensityInCenter = 1.0f );
  141.55 +
  141.56 +FovPort CalculateRecommendedFov          ( HmdRenderInfo const &hmd,
  141.57 +                                           StereoEye eyeType,
  141.58 +                                           bool bMakeFovSymmetrical = false);
  141.59 +
  141.60 +StereoEyeParams CalculateStereoEyeParams ( HmdRenderInfo const &hmd,
  141.61 +                                           StereoEye eyeType,
  141.62 +                                           Sizei const &actualRendertargetSurfaceSize,
  141.63 +                                           bool bRendertargetSharedByBothEyes,
  141.64 +                                           bool bRightHanded = true,
  141.65 +                                           float zNear = 0.01f, float zFar = 10000.0f,
  141.66 +										   Sizei const *pOverrideRenderedPixelSize = NULL,
  141.67 +                                           FovPort const *pOverrideFovport = NULL,
  141.68 +                                           float zoomFactor = 1.0f );
  141.69 +
  141.70 +Vector3f CalculateEyeVirtualCameraOffset(HmdRenderInfo const &hmd,
  141.71 +                                         StereoEye eyeType, bool bMonoRenderingMode );
  141.72 +
  141.73 +
  141.74 +// These are two components from StereoEyeParams that can be changed
  141.75 +// very easily without full recomputation of everything.
  141.76 +struct ViewportScaleAndOffset
  141.77 +{
  141.78 +    Recti               RenderedViewport;
  141.79 +    ScaleAndOffset2D    EyeToSourceUV;
  141.80 +};
  141.81 +
  141.82 +// Three ways to override the size of the render view dynamically.
  141.83 +// None of these require changing the distortion parameters or the regenerating the distortion mesh,
  141.84 +// and can be called every frame if desired.
  141.85 +ViewportScaleAndOffset ModifyRenderViewport ( StereoEyeParams const &params,
  141.86 +                                              Sizei const &actualRendertargetSurfaceSize,
  141.87 +                                              Recti const &renderViewport );
  141.88 +
  141.89 +ViewportScaleAndOffset ModifyRenderSize ( StereoEyeParams const &params,
  141.90 +                                          Sizei const &actualRendertargetSurfaceSize,
  141.91 +                                          Sizei const &requestedRenderSize,
  141.92 +                                          bool bRendertargetSharedByBothEyes = false );
  141.93 +
  141.94 +ViewportScaleAndOffset ModifyRenderDensity ( StereoEyeParams const &params,
  141.95 +                                             Sizei const &actualRendertargetSurfaceSize,
  141.96 +                                             float pixelDensity = 1.0f,
  141.97 +                                             bool bRendertargetSharedByBothEyes = false );
  141.98 +
  141.99 +
 141.100 +//-----------------------------------------------------------------------------------
 141.101 +// *****  StereoConfig
 141.102 +
 141.103 +// StereoConfig maintains a scene stereo state and allow switching between different
 141.104 +// stereo rendering modes. To support rendering, StereoConfig keeps track of HMD
 141.105 +// variables such as screen size, eye-to-screen distance and distortion, and computes
 141.106 +// extra data such as FOV and distortion center offsets based on it. Rendering
 141.107 +// parameters are returned though StereoEyeParams for each eye.
 141.108 +//
 141.109 +// Beyond regular 3D projection, this class supports rendering a 2D orthographic
 141.110 +// surface for UI and text. The 2D surface will be defined by CreateOrthoSubProjection().
 141.111 +// The (0,0) coordinate corresponds to eye center location.
 141.112 +// 
 141.113 +// Applications are not required to use this class, but they should be doing very
 141.114 +// similar sequences of operations, and it may be useful to start with this class
 141.115 +// and modify it.
 141.116 +
 141.117 +struct StereoEyeParamsWithOrtho
 141.118 +{
 141.119 +    StereoEyeParams         StereoEye;
 141.120 +    Matrix4f                OrthoProjection;
 141.121 +};
 141.122 +
 141.123 +struct ViewportScaleAndOffsetBothEyes
 141.124 +{
 141.125 +    ViewportScaleAndOffset  Left;
 141.126 +    ViewportScaleAndOffset  Right;
 141.127 +};
 141.128 +
 141.129 +class StereoConfig
 141.130 +{
 141.131 +public:
 141.132 +
 141.133 +    // StereoMode describes rendering modes that can be used by StereoConfig.
 141.134 +    // These modes control whether stereo rendering is used or not (Stereo_None),
 141.135 +    // and how it is implemented.
 141.136 +    enum StereoMode
 141.137 +    {
 141.138 +        Stereo_None                     = 0,        // Single eye
 141.139 +        Stereo_LeftRight_Multipass      = 1,        // One frustum per eye
 141.140 +    };
 141.141 +
 141.142 +
 141.143 +    StereoConfig(StereoMode mode = Stereo_LeftRight_Multipass);
 141.144 + 
 141.145 +    //---------------------------------------------------------------------------------------------
 141.146 +    // *** Core functions - every app MUST call these functions at least once.
 141.147 +
 141.148 +    // Sets HMD parameters; also initializes distortion coefficients.
 141.149 +    void        SetHmdRenderInfo(const HmdRenderInfo& hmd);
 141.150 +
 141.151 +    // Set the physical size of the rendertarget surface the app created,
 141.152 +    // and whether one RT is shared by both eyes, or each eye has its own RT:
 141.153 +    // true: both eyes are rendered to the same RT. Left eye starts at top-left, right eye starts at top-middle.
 141.154 +    // false: each eye is rendered to its own RT. Some GPU architectures prefer this arrangement.
 141.155 +    // Typically, the app would call CalculateRecommendedTextureSize() to suggest the choice of RT size.
 141.156 +    // This setting must be exactly the size of the actual RT created, or the UVs produced will be incorrect.
 141.157 +    // If the app wants to render to a subsection of the RT, it should use SetRenderSize()
 141.158 +    void        SetRendertargetSize (Size<int> const rendertargetSize,
 141.159 +                                     bool rendertargetIsSharedByBothEyes );
 141.160 +
 141.161 +    // Returns full set of Stereo rendering parameters for the specified eye.
 141.162 +    const StereoEyeParamsWithOrtho& GetEyeRenderParams(StereoEye eye);
 141.163 +
 141.164 +
 141.165 +
 141.166 +    //---------------------------------------------------------------------------------------------
 141.167 +    // *** Optional functions - an app may call these to override default behaviours.
 141.168 +
 141.169 +    const HmdRenderInfo& GetHmdRenderInfo() const { return Hmd; }
 141.170 +
 141.171 +    // Returns the recommended size of rendertargets.
 141.172 +    // If rendertargetIsSharedByBothEyes is true, this is the size of the combined buffer.
 141.173 +    // If rendertargetIsSharedByBothEyes is false, this is the size of each individual buffer.
 141.174 +    // pixelDensityInCenter may be set to any number - by default it will match the HMD resolution in the center of the image.
 141.175 +    // After creating the rendertargets, the application MUST call SetRendertargetSize() with the actual size created
 141.176 +    // (which can be larger or smaller as the app wishes, but StereoConfig needs to know either way)
 141.177 +    Sizei       CalculateRecommendedTextureSize ( bool rendertargetSharedByBothEyes,
 141.178 +                                                  float pixelDensityInCenter = 1.0f );
 141.179 +
 141.180 +    // Sets a stereo rendering mode and updates internal cached
 141.181 +    // state (matrices, per-eye view) based on it.
 141.182 +    void        SetStereoMode(StereoMode mode)  { Mode = mode; DirtyFlag = true; }
 141.183 +    StereoMode  GetStereoMode() const           { return Mode; }
 141.184 +
 141.185 +    // Sets the fieldOfView that the 2D coordinate area stretches to.
 141.186 +    void        Set2DAreaFov(float fovRadians);
 141.187 +
 141.188 +    // Really only for science experiments - no normal app should ever need to override
 141.189 +    // the HMD's lens descriptors. Passing NULL removes the override.
 141.190 +    // Supply both = set left and right.
 141.191 +    // Supply just left = set both to the same.
 141.192 +    // Supply neither = remove override.
 141.193 +    void        SetLensOverride ( LensConfig const *pLensOverrideLeft  = NULL,
 141.194 +                                  LensConfig const *pLensOverrideRight = NULL );
 141.195 + 
 141.196 +    // Override the rendered FOV in various ways. All angles in tangent units.
 141.197 +    // This is not clamped to the physical FOV of the display - you'll need to do that yourself!
 141.198 +    // Supply both = set left and right.
 141.199 +    // Supply just left = set both to the same.
 141.200 +    // Supply neither = remove override.
 141.201 +    void        SetFov ( FovPort const *pfovLeft  = NULL,
 141.202 +					     FovPort const *pfovRight = NULL );
 141.203 +    
 141.204 +    void        SetFovPortRadians ( float horizontal, float vertical )
 141.205 +    {
 141.206 +        FovPort fov = FovPort::CreateFromRadians(horizontal, vertical);
 141.207 +        SetFov( &fov, &fov );
 141.208 +    }
 141.209 +
 141.210 +
 141.211 +    // This forces a "zero IPD" mode where there is just a single render with an FOV that
 141.212 +    //   is the union of the two calculated FOVs.
 141.213 +    // The calculated render is for the left eye. Any size & FOV overrides for the right
 141.214 +    //   eye will be ignored.
 141.215 +    // If you query the right eye's size, you will get the same render
 141.216 +    //   size & position as the left eye - you should not actually do the render of course!
 141.217 +    //   The distortion values will be different, because it goes to a different place on the framebuffer.
 141.218 +    // Note that if you do this, the rendertarget does not need to be twice the width of
 141.219 +    //   the render size any more.
 141.220 +    void        SetZeroVirtualIpdOverride ( bool enableOverride );
 141.221 +
 141.222 +    // Allows the app to specify near and far clip planes and the right/left-handedness of the projection matrix.
 141.223 +    void        SetZClipPlanesAndHandedness ( float zNear = 0.01f, float zFar = 10000.0f,
 141.224 +                                              bool rightHandedProjection = true );
 141.225 +
 141.226 +    // Allows the app to specify how much extra eye rotation to allow when determining the visible FOV.
 141.227 +    void        SetExtraEyeRotation ( float extraEyeRotationInRadians = 0.0f );
 141.228 +
 141.229 +    // The dirty flag is set by any of the above calls. Just handy for the app to know
 141.230 +    // if e.g. the distortion mesh needs regeneration.
 141.231 +    void        SetDirty() { DirtyFlag = true; }
 141.232 +    bool        IsDirty() { return DirtyFlag; }
 141.233 +
 141.234 +    // An app never needs to call this - GetEyeRenderParams will call it internally if
 141.235 +    // the state is dirty. However apps can call this explicitly to control when and where
 141.236 +    // computation is performed (e.g. not inside critical loops)
 141.237 +    void        UpdateComputedState();
 141.238 +
 141.239 +    // This returns the projection matrix with a "zoom". Does not modify any internal state.
 141.240 +    Matrix4f    GetProjectionWithZoom ( StereoEye eye, float fovZoom ) const;
 141.241 +
 141.242 +
 141.243 +    //---------------------------------------------------------------------------------------------
 141.244 +    // The SetRender* functions are special.
 141.245 +    //
 141.246 +    // They do not require a full recalculation of state, and they do not change anything but the
 141.247 +    // ViewportScaleAndOffset data for the eyes (which they return), and do not set the dirty flag!
 141.248 +    // This means they can be called without regenerating the distortion mesh, and thus 
 141.249 +    // can happily be called every frame without causing performance problems. Dynamic rescaling 
 141.250 +    // of the rendertarget can help keep framerate up in demanding VR applications.
 141.251 +    // See the documentation for more details on their use.
 141.252 +
 141.253 +    // Specify a pixel density - how many rendered pixels per pixel in the physical display.
 141.254 +    ViewportScaleAndOffsetBothEyes SetRenderDensity ( float pixelsPerDisplayPixel );
 141.255 +
 141.256 +    // Supply the size directly. Will be clamped to the physical rendertarget size.
 141.257 +    ViewportScaleAndOffsetBothEyes SetRenderSize ( Sizei const &renderSizeLeft, Sizei const &renderSizeRight );
 141.258 +
 141.259 +    // Supply the viewport directly. This is not clamped to the physical rendertarget - careful now!
 141.260 +    ViewportScaleAndOffsetBothEyes SetRenderViewport ( Recti const &renderViewportLeft, Recti const &renderViewportRight );
 141.261 +
 141.262 +private:
 141.263 +
 141.264 +    // *** Modifiable State
 141.265 +
 141.266 +    StereoMode         Mode;
 141.267 +    HmdRenderInfo      Hmd;
 141.268 +
 141.269 +    float              Area2DFov;           // FOV range mapping to the 2D area.
 141.270 +
 141.271 +    // Only one of these three overrides can be true!
 141.272 +    enum SetViewportModeEnum
 141.273 +    {
 141.274 +        SVPM_Density,
 141.275 +        SVPM_Size,
 141.276 +        SVPM_Viewport,
 141.277 +    }                  SetViewportMode;
 141.278 +    // ...and depending which it is, one of the following are used.
 141.279 +    float              SetViewportPixelsPerDisplayPixel;
 141.280 +    Sizei              SetViewportSize[2];
 141.281 +    Recti           SetViewport[2];
 141.282 +
 141.283 +    // Other overrides.
 141.284 +    bool               OverrideLens;
 141.285 +    LensConfig         LensOverrideLeft;
 141.286 +    LensConfig         LensOverrideRight;
 141.287 +    Sizei              RendertargetSize;
 141.288 +    bool               OverrideTanHalfFov;
 141.289 +    FovPort            FovOverrideLeft;
 141.290 +    FovPort            FovOverrideRight;
 141.291 +    bool               OverrideZeroIpd;
 141.292 +    float              ZNear;
 141.293 +    float              ZFar;
 141.294 +    float              ExtraEyeRotationInRadians;
 141.295 +    bool               IsRendertargetSharedByBothEyes;
 141.296 +    bool               RightHandedProjection;
 141.297 +
 141.298 +    bool               DirtyFlag;   // Set when any if the modifiable state changed. Does NOT get set by SetRender*()
 141.299 +
 141.300 +    // Utility function.
 141.301 +    ViewportScaleAndOffsetBothEyes setupViewportScaleAndOffsets();
 141.302 +
 141.303 +    // *** Computed State
 141.304 +
 141.305 +public:     // Small hack for the config tool. Normal code should never read EyeRenderParams directly - use GetEyeRenderParams() instead.
 141.306 +    // 0/1 = left/right main views.
 141.307 +    StereoEyeParamsWithOrtho    EyeRenderParams[2];
 141.308 +};
 141.309 +
 141.310 +
 141.311 +//-----------------------------------------------------------------------------------
 141.312 +// *****  Distortion Mesh Rendering
 141.313 +//
 141.314 +
 141.315 +// Stores both texture UV coords, or tan(angle) values.
 141.316 +// Use whichever set of data the specific distortion algorithm requires.
 141.317 +// This struct *must* be binary compatible with CAPI ovrDistortionVertex.
 141.318 +struct DistortionMeshVertexData
 141.319 +{
 141.320 +    // [-1,+1],[-1,+1] over the entire framebuffer.
 141.321 +    Vector2f    ScreenPosNDC;
 141.322 +    // [0.0-1.0] interpolation value for timewarping - see documentation for details.
 141.323 +    float       TimewarpLerp;
 141.324 +    // [0.0-1.0] fade-to-black at the edges to reduce peripheral vision noise.
 141.325 +    float       Shade;        
 141.326 +    // The red, green, and blue vectors in tan(angle) space.
 141.327 +    // Scale and offset by the values in StereoEyeParams.EyeToSourceUV.Scale
 141.328 +    // and StereoParams.EyeToSourceUV.Offset to get to real texture UV coords.
 141.329 +    Vector2f    TanEyeAnglesR;
 141.330 +    Vector2f    TanEyeAnglesG;
 141.331 +    Vector2f    TanEyeAnglesB;    
 141.332 +};
 141.333 +
 141.334 +// If you just want a single point on the screen transformed.
 141.335 +DistortionMeshVertexData DistortionMeshMakeVertex ( Vector2f screenNDC,
 141.336 +                                                    bool rightEye,
 141.337 +                                                    const HmdRenderInfo &hmdRenderInfo, 
 141.338 +                                                    const DistortionRenderDesc &distortion, const ScaleAndOffset2D &eyeToSourceNDC );
 141.339 +
 141.340 +void DistortionMeshCreate ( DistortionMeshVertexData **ppVertices, uint16_t **ppTriangleListIndices,
 141.341 +                            int *pNumVertices, int *pNumTriangles,
 141.342 +                            const StereoEyeParams &stereoParams, const HmdRenderInfo &hmdRenderInfo );
 141.343 +
 141.344 +// Generate distortion mesh for a eye.
 141.345 +// This version requires less data then stereoParms, supporting dynamic change in render target viewport.
 141.346 +void DistortionMeshCreate( DistortionMeshVertexData **ppVertices, uint16_t **ppTriangleListIndices,
 141.347 +                           int *pNumVertices, int *pNumTriangles,
 141.348 +                           bool rightEye,
 141.349 +                           const HmdRenderInfo &hmdRenderInfo, 
 141.350 +                           const DistortionRenderDesc &distortion, const ScaleAndOffset2D &eyeToSourceNDC );
 141.351 +
 141.352 +void DistortionMeshDestroy ( DistortionMeshVertexData *pVertices, uint16_t *pTriangleMeshIndices );
 141.353 +
 141.354 +
 141.355 +//-----------------------------------------------------------------------------------
 141.356 +// *****  Heightmap Mesh Rendering
 141.357 +//
 141.358 +
 141.359 +// Stores both texture UV coords, or tan(angle) values.
 141.360 +// This struct *must* be binary compatible with CAPI ovrHeightmapVertex.
 141.361 +struct HeightmapMeshVertexData
 141.362 +{
 141.363 +    // [-1,+1],[-1,+1] over the entire framebuffer.
 141.364 +    Vector2f    ScreenPosNDC;
 141.365 +    // [0.0-1.0] interpolation value for timewarping - see documentation for details.
 141.366 +    float       TimewarpLerp;
 141.367 +    // The vectors in tan(angle) space.
 141.368 +    // Scale and offset by the values in StereoEyeParams.EyeToSourceUV.Scale
 141.369 +    // and StereoParams.EyeToSourceUV.Offset to get to real texture UV coords.
 141.370 +    Vector2f    TanEyeAngles;    
 141.371 +};
 141.372 +
 141.373 +
 141.374 +void HeightmapMeshCreate ( HeightmapMeshVertexData **ppVertices, uint16_t **ppTriangleListIndices,
 141.375 +    int *pNumVertices, int *pNumTriangles,
 141.376 +    const StereoEyeParams &stereoParams, const HmdRenderInfo &hmdRenderInfo );
 141.377 +
 141.378 +// Generate heightmap mesh for a eye. This version requires less data then stereoParms, supporting
 141.379 +// dynamic change in render target viewport.
 141.380 +void HeightmapMeshCreate( HeightmapMeshVertexData **ppVertices, uint16_t **ppTriangleListIndices,
 141.381 +    int *pNumVertices, int *pNumTriangles, bool rightEye,
 141.382 +    const HmdRenderInfo &hmdRenderInfo, const ScaleAndOffset2D &eyeToSourceNDC );
 141.383 +
 141.384 +void HeightmapMeshDestroy ( HeightmapMeshVertexData *pVertices, uint16_t *pTriangleMeshIndices );
 141.385 +
 141.386 +
 141.387 +
 141.388 +//-----------------------------------------------------------------------------------
 141.389 +// ***** Prediction and timewarp.
 141.390 +//
 141.391 +
 141.392 +struct PredictionValues
 141.393 +{
 141.394 +    // All values in seconds.
 141.395 +    // These are the times in seconds from a present+flush to the relevant display element.
 141.396 +    // The time is measured to the middle of that element's visibility window,
 141.397 +    // e.g. if the device is a full-persistence display, the element will be visible for
 141.398 +    // an entire frame, so the time measures to the middle of that period, i.e. half the frame time.
 141.399 +    float PresentFlushToRenderedScene;        // To the overall rendered 3D scene being visible.
 141.400 +    float PresentFlushToTimewarpStart;        // To when the first timewarped scanline will be visible.
 141.401 +    float PresentFlushToTimewarpEnd;          // To when the last timewarped scanline will be visible.
 141.402 +    float PresentFlushToPresentFlush;         // To the next present+flush, i.e. the ideal framerate.
 141.403 +
 141.404 +    bool  WithTimewarp;
 141.405 +    bool  WithVsync;
 141.406 +};
 141.407 +
 141.408 +// Calculates the values from the HMD info.
 141.409 +PredictionValues PredictionGetDeviceValues ( const HmdRenderInfo &hmdRenderInfo,
 141.410 +                                             bool withTimewarp = true,
 141.411 +                                             bool withVsync = true );
 141.412 +
 141.413 +// Pass in an orientation used to render the scene, and then the predicted orientation
 141.414 +// (which may have been computed later on, and thus is more accurate), and this
 141.415 +// will return the matrix to pass to the timewarp distortion shader.
 141.416 +// TODO: deal with different handedness?
 141.417 +Matrix4f TimewarpComputePoseDelta ( Matrix4f const &renderedViewFromWorld, Matrix4f const &predictedViewFromWorld, Matrix4f const&hmdToEyeViewOffset );
 141.418 +Matrix4f TimewarpComputePoseDeltaPosition ( Matrix4f const &renderedViewFromWorld, Matrix4f const &predictedViewFromWorld, Matrix4f const&hmdToEyeViewOffset );
 141.419 +
 141.420 +
 141.421 +
 141.422 +// TimewarpMachine helps keep track of rendered frame timing and
 141.423 +// handles predictions for time-warp rendering.
 141.424 +class TimewarpMachine
 141.425 +{
 141.426 +public:
 141.427 +    TimewarpMachine();
 141.428 +   
 141.429 +    // Call this on and every time something about the setup changes.
 141.430 +    void        Reset ( HmdRenderInfo& renderInfo, bool vsyncEnabled, double timeNow );
 141.431 +
 141.432 +    // The only reliable time in most engines is directly after the frame-present and GPU flush-and-wait.
 141.433 +    // This call should be done right after that to give this system the timing info it needs.
 141.434 +    void        AfterPresentAndFlush(double timeNow);
 141.435 +    // But some engines queue up the frame-present and only later find out when it actually happened.
 141.436 +    // They should call these two at those times.
 141.437 +    void        AfterPresentWithoutFlush();
 141.438 +    void        AfterPresentFinishes(double timeNow);
 141.439 +
 141.440 +    // The "average" time the rendered frame will show up,
 141.441 +    // and the predicted pose of the HMD at that time.
 141.442 +    // You usually only need to call one of these functions.
 141.443 +    double      GetViewRenderPredictionTime();
 141.444 +    bool        GetViewRenderPredictionPose(Tracking::SensorStateReader* reader, Posef& transform);
 141.445 +
 141.446 +
 141.447 +    // Timewarp prediction functions. You usually only need to call one of these three sets of functions.
 141.448 +
 141.449 +    // The predicted times that the first and last pixel will be visible on-screen.
 141.450 +    double      GetVisiblePixelTimeStart();
 141.451 +    double      GetVisiblePixelTimeEnd();
 141.452 +    // Predicted poses of the HMD at those first and last pixels.
 141.453 +	bool        GetPredictedVisiblePixelPoseStart(Tracking::SensorStateReader* reader, Posef& transform);
 141.454 +	bool        GetPredictedVisiblePixelPoseEnd(Tracking::SensorStateReader* reader, Posef& transform);
 141.455 +    // The delta matrices to feed to the timewarp distortion code,
 141.456 +    // given the pose that was used for rendering.
 141.457 +    // (usually the one returned by GetViewRenderPredictionPose() earlier)
 141.458 +	bool        GetTimewarpDeltaStart(Tracking::SensorStateReader* reader, Posef const &renderedPose, Matrix4f& transform);
 141.459 +	bool        GetTimewarpDeltaEnd(Tracking::SensorStateReader* reader, Posef const &renderedPose, Matrix4f& transform);
 141.460 +
 141.461 +    // Just-In-Time distortion aims to delay the second sensor reading & distortion
 141.462 +    // until the very last moment to improve prediction. However, it is a little scary,
 141.463 +    // since the delay might wait too long and miss the vsync completely!
 141.464 +    // Use of the JustInTime_* functions is entirely optional, and we advise allowing
 141.465 +    // users to turn it off in their video options to cope with odd machine configurations.
 141.466 +
 141.467 +    // What time should the app wait until before starting distortion?
 141.468 +    double      JustInTime_GetDistortionWaitUntilTime();
 141.469 +
 141.470 +    // Used to time the distortion rendering
 141.471 +    bool        JustInTime_NeedDistortionTimeMeasurement() const;
 141.472 +    void        JustInTime_BeforeDistortionTimeMeasurement(double timeNow);
 141.473 +    void        JustInTime_AfterDistortionTimeMeasurement(double timeNow);
 141.474 +    double      JustInTime_AverageDistortionTime();     // Just for profiling - use JustInTime_GetDistortionWaitUntilTime() for functionality.
 141.475 +
 141.476 +private:
 141.477 +    bool                VsyncEnabled;
 141.478 +    HmdRenderInfo       RenderInfo;
 141.479 +    PredictionValues    CurrentPredictionValues;
 141.480 +
 141.481 +    enum { NumDistortionTimes = 100 };
 141.482 +    int                 DistortionTimeCount;
 141.483 +    double              DistortionTimeCurrentStart;
 141.484 +    float               DistortionTimes[NumDistortionTimes];
 141.485 +    float               DistortionTimeAverage;
 141.486 +
 141.487 +    // Pose at which last time the eye was rendered.
 141.488 +    Posef               EyeRenderPoses[2];
 141.489 +
 141.490 +    // Absolute time of the last present+flush
 141.491 +    double              LastFramePresentFlushTime;
 141.492 +    // Seconds between present+flushes
 141.493 +    float               PresentFlushToPresentFlushSeconds;
 141.494 +    // Predicted absolute time of the next present+flush
 141.495 +    double              NextFramePresentFlushTime;
 141.496 +
 141.497 +};
 141.498 +
 141.499 +
 141.500 +
 141.501 +}}}  // OVR::Util::Render
 141.502 +
 141.503 +#endif
   142.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   142.2 +++ b/LibOVR/Src/Util/Util_SystemGUI.cpp	Wed Jan 14 06:51:16 2015 +0200
   142.3 @@ -0,0 +1,190 @@
   142.4 +/************************************************************************************
   142.5 +
   142.6 +Filename    :   Util_SystemGUI.cpp
   142.7 +Content     :   OS GUI access, usually for diagnostics.
   142.8 +Created     :   October 20, 2014
   142.9 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
  142.10 +
  142.11 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
  142.12 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
  142.13 +which is provided at the time of installation or download, or which 
  142.14 +otherwise accompanies this software in either electronic or hard copy form.
  142.15 +
  142.16 +You may obtain a copy of the License at
  142.17 +
  142.18 +http://www.oculusvr.com/licenses/LICENSE-3.2 
  142.19 +
  142.20 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
  142.21 +distributed under the License is distributed on an "AS IS" BASIS,
  142.22 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  142.23 +See the License for the specific language governing permissions and
  142.24 +limitations under the License.
  142.25 +
  142.26 +*************************************************************************************/
  142.27 +
  142.28 +#include "Util_SystemGUI.h"
  142.29 +#include "../Kernel/OVR_UTF8Util.h"
  142.30 +#include <stdio.h>
  142.31 +
  142.32 +#if defined(OVR_OS_MS)
  142.33 +    #include <Windows.h>
  142.34 +#endif
  142.35 +
  142.36 +
  142.37 +namespace OVR { namespace Util {
  142.38 +
  142.39 +
  142.40 +#if defined(OVR_OS_MS)
  142.41 +
  142.42 +    // On Windows we implement a manual dialog message box. The reason for this is that there's no way to 
  142.43 +    // have a message box like this without either using MFC or WinForms or relying on Windows Vista+.
  142.44 +
  142.45 +    bool DisplayMessageBox(const char* pTitle, const char* pText)
  142.46 +    {
  142.47 +        #define ID_EDIT 100
  142.48 +
  142.49 +        struct Dialog
  142.50 +        {
  142.51 +            static size_t LineCount(const char* pText)
  142.52 +            {
  142.53 +                size_t count = 0;
  142.54 +                while(*pText)
  142.55 +                {
  142.56 +                    if(*pText++ == '\n')
  142.57 +                        count++;
  142.58 +                }
  142.59 +                return count;
  142.60 +            }
  142.61 +
  142.62 +            static WORD* WordUp(WORD* pIn){ return (WORD*)((((uintptr_t)pIn + 3) >> 2) << 2); }
  142.63 +
  142.64 +            static BOOL CALLBACK Proc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam)
  142.65 +            {
  142.66 +                switch (iMsg)
  142.67 +	            {
  142.68 +                    case WM_INITDIALOG:
  142.69 +                    {
  142.70 +                        HWND hWndEdit = GetDlgItem(hDlg, ID_EDIT);
  142.71 +
  142.72 +                        const char* pText = (const char*)lParam;
  142.73 +                        SetWindowTextA(hWndEdit, pText);
  142.74 +
  142.75 +                        HFONT hFont = CreateFontW(-11, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, L"Courier New");
  142.76 +                        if(hFont)
  142.77 +                            SendMessage(hWndEdit, WM_SETFONT, WPARAM(hFont), TRUE);
  142.78 +
  142.79 +                        SendMessage(hWndEdit, EM_SETSEL, (WPARAM)0, (LPARAM)0);
  142.80 +
  142.81 +                        return TRUE;
  142.82 +                    }
  142.83 +
  142.84 +                    case WM_COMMAND:
  142.85 +                        switch (LOWORD(wParam))
  142.86 +                        {
  142.87 +				            case ID_EDIT:
  142.88 +                            {
  142.89 +                                // Handle messages from the edit control here.
  142.90 +                                HWND hWndEdit = GetDlgItem(hDlg, ID_EDIT);
  142.91 +                                SendMessage(hWndEdit, EM_SETSEL, (WPARAM)0, (LPARAM)0);
  142.92 +					            return TRUE;
  142.93 +                            }
  142.94 +
  142.95 +		                    case IDOK:
  142.96 +                                EndDialog(hDlg, 0);
  142.97 +			                    return TRUE;
  142.98 +		                }
  142.99 +                        break;
 142.100 +                }
 142.101 +
 142.102 +                return FALSE;
 142.103 +            }
 142.104 +        };
 142.105 +
 142.106 +
 142.107 +        char dialogTemplateMemory[1024];
 142.108 +        memset(dialogTemplateMemory, 0, sizeof(dialogTemplateMemory));
 142.109 +        DLGTEMPLATE* pDlg = (LPDLGTEMPLATE)dialogTemplateMemory;
 142.110 +
 142.111 +        const size_t textLineCount = Dialog::LineCount(pText);
 142.112 +
 142.113 +        // Sizes are in Windows dialog units, which are relative to a character size. Depends on the font and environment settings. Often the pixel size will be ~3x the dialog unit x size. Often the pixel size will be ~3x the dialog unit y size.
 142.114 +        const int    kGutterSize   =  6; // Empty border space around controls within the dialog
 142.115 +        const int    kButtonWidth  = 24;
 142.116 +        const int    kButtonHeight = 10;
 142.117 +        const int    kDialogWidth  = 600; // To do: Clip this against screen bounds.
 142.118 +        const int    kDialogHeight = ((textLineCount > 100) ? 400 : ((textLineCount > 25) ? 300 : 200));
 142.119 +
 142.120 +        // Define a dialog box.
 142.121 +        pDlg->style = WS_POPUP | WS_BORDER | WS_SYSMENU | DS_MODALFRAME | WS_CAPTION;
 142.122 +        pDlg->cdit  = 2;    // Control count
 142.123 +        pDlg->x     = 10;   // X position To do: Center the dialog.
 142.124 +        pDlg->y     = 10;
 142.125 +        pDlg->cx    = (short)kDialogWidth;
 142.126 +        pDlg->cy    = (short)kDialogHeight;
 142.127 +        WORD* pWord = (WORD*)(pDlg + 1);
 142.128 +        *pWord++ = 0;   // No menu
 142.129 +        *pWord++ = 0;   // Default dialog box class
 142.130 +
 142.131 +        WCHAR* pWchar = (WCHAR*)pWord;
 142.132 +        const size_t titleLength = strlen(pTitle);
 142.133 +        size_t wcharCount = OVR::UTF8Util::DecodeString(pWchar, pTitle, (titleLength > 128) ? 128 : titleLength);
 142.134 +        pWord += wcharCount + 1;
 142.135 +
 142.136 +        // Define an OK button.
 142.137 +        pWord = Dialog::WordUp(pWord);
 142.138 +
 142.139 +        DLGITEMTEMPLATE* pDlgItem = (DLGITEMTEMPLATE*)pWord;
 142.140 +        pDlgItem->x     = pDlg->cx - (kGutterSize + kButtonWidth);
 142.141 +        pDlgItem->y     = pDlg->cy - (kGutterSize + kButtonHeight);
 142.142 +        pDlgItem->cx    = kButtonWidth;
 142.143 +        pDlgItem->cy    = kButtonHeight;
 142.144 +        pDlgItem->id    = IDOK;
 142.145 +        pDlgItem->style = WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON;
 142.146 +
 142.147 +        pWord   = (WORD*)(pDlgItem + 1);
 142.148 +        *pWord++ = 0xFFFF;
 142.149 +        *pWord++ = 0x0080; // button class
 142.150 +
 142.151 +        pWchar     = (WCHAR*)pWord;
 142.152 +        pWchar[0] = 'O'; pWchar[1] = 'K'; pWchar[2] = '\0'; // Not currently localized.
 142.153 +        pWord     += 3; // OK\0
 142.154 +        *pWord++   = 0; // no creation data
 142.155 +
 142.156 +        // Define an EDIT contol.
 142.157 +        pWord = Dialog::WordUp(pWord);
 142.158 +
 142.159 +        pDlgItem = (DLGITEMTEMPLATE*)pWord;
 142.160 +        pDlgItem->x  = kGutterSize;
 142.161 +        pDlgItem->y  = kGutterSize;
 142.162 +        pDlgItem->cx = pDlg->cx - (kGutterSize + kGutterSize);
 142.163 +        pDlgItem->cy = pDlg->cy - (kGutterSize + kButtonHeight + kGutterSize + (kGutterSize / 2));
 142.164 +        pDlgItem->id = ID_EDIT;
 142.165 +        pDlgItem->style = ES_LEFT | ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_WANTRETURN | ES_READONLY | WS_VSCROLL | WS_BORDER | WS_TABSTOP | WS_CHILD | WS_VISIBLE;
 142.166 +
 142.167 +        pWord = (WORD*)(pDlgItem + 1);
 142.168 +        *pWord++ = 0xFFFF;
 142.169 +        *pWord++ = 0x0081;  // edit class atom
 142.170 +        *pWord++ = 0;       // no creation data
 142.171 +
 142.172 +        LRESULT ret = DialogBoxIndirectParam(NULL, (LPDLGTEMPLATE)pDlg, NULL, (DLGPROC)Dialog::Proc, (LPARAM)pText);
 142.173 +
 142.174 +        return (ret != 0);
 142.175 +    }
 142.176 +#elif defined(OVR_OS_MAC)
 142.177 +    // For Apple we use the Objective C implementation in Util_GUI.mm
 142.178 +#else
 142.179 +    // To do.
 142.180 +    bool DisplayMessageBox(const char* pTitle, const char* pText)
 142.181 +    {
 142.182 +        printf("\n\nMessageBox\n%s\n", pTitle);
 142.183 +        printf("%s\n\n", pText);
 142.184 +        return false;
 142.185 +    }
 142.186 +#endif
 142.187 +
 142.188 +
 142.189 +} } // namespace OVR::Util
 142.190 +
 142.191 +
 142.192 +
 142.193 +
   143.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   143.2 +++ b/LibOVR/Src/Util/Util_SystemGUI.h	Wed Jan 14 06:51:16 2015 +0200
   143.3 @@ -0,0 +1,39 @@
   143.4 +/************************************************************************************
   143.5 +
   143.6 +Filename    :   Util_SystemGUI.h
   143.7 +Content     :   OS GUI access, usually for diagnostics.
   143.8 +Created     :   October 20, 2014
   143.9 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
  143.10 +
  143.11 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
  143.12 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
  143.13 +which is provided at the time of installation or download, or which 
  143.14 +otherwise accompanies this software in either electronic or hard copy form.
  143.15 +
  143.16 +You may obtain a copy of the License at
  143.17 +
  143.18 +http://www.oculusvr.com/licenses/LICENSE-3.2 
  143.19 +
  143.20 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
  143.21 +distributed under the License is distributed on an "AS IS" BASIS,
  143.22 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  143.23 +See the License for the specific language governing permissions and
  143.24 +limitations under the License.
  143.25 +
  143.26 +*************************************************************************************/
  143.27 +
  143.28 +#ifndef OVR_Util_GUI_h
  143.29 +#define OVR_Util_GUI_h
  143.30 +
  143.31 +
  143.32 +namespace OVR { namespace Util {
  143.33 +
  143.34 +    // Displays a modal message box on the default GUI display (not on a VR device). 
  143.35 +    // The message box interface (e.g. OK button) is not localized.
  143.36 +    bool DisplayMessageBox(const char* pTitle, const char* pText);
  143.37 +
  143.38 +
  143.39 +} } // namespace OVR::Util
  143.40 +
  143.41 +
  143.42 +#endif
   144.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   144.2 +++ b/LibOVR/Src/Util/Util_SystemInfo.cpp	Wed Jan 14 06:51:16 2015 +0200
   144.3 @@ -0,0 +1,289 @@
   144.4 +/************************************************************************************
   144.5 +
   144.6 +Filename    :   Util_SystemInfo.cpp
   144.7 +Content     :   Various operations to get information about the system
   144.8 +Created     :   September 26, 2014
   144.9 +Author      :   Kevin Jenkins
  144.10 +
  144.11 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
  144.12 +
  144.13 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 
  144.14 +you may not use the Oculus VR Rift SDK except in compliance with the License, 
  144.15 +which is provided at the time of installation or download, or which 
  144.16 +otherwise accompanies this software in either electronic or hard copy form.
  144.17 +
  144.18 +You may obtain a copy of the License at
  144.19 +
  144.20 +http://www.oculusvr.com/licenses/LICENSE-3.2 
  144.21 +
  144.22 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
  144.23 +distributed under the License is distributed on an "AS IS" BASIS,
  144.24 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  144.25 +See the License for the specific language governing permissions and
  144.26 +limitations under the License.
  144.27 +
  144.28 +************************************************************************************/
  144.29 +
  144.30 +#include "Util_SystemInfo.h"
  144.31 +#include "../Kernel/OVR_Timer.h"
  144.32 +#include "../Kernel/OVR_Threads.h"
  144.33 +#include "../Kernel/OVR_Log.h"
  144.34 +#include "../Kernel/OVR_Array.h"
  144.35 +
  144.36 +/*
  144.37 +// Disabled, can't link RiftConfigUtil
  144.38 +#ifdef OVR_OS_WIN32
  144.39 +#define _WIN32_DCOM
  144.40 +#include <comdef.h>
  144.41 +#include <Wbemidl.h>
  144.42 +
  144.43 +# pragma comment(lib, "wbemuuid.lib")
  144.44 +#endif
  144.45 +*/
  144.46 +
  144.47 +
  144.48 +namespace OVR { namespace Util {
  144.49 +
  144.50 +// From http://blogs.msdn.com/b/oldnewthing/archive/2005/02/01/364563.aspx
  144.51 +#if defined (OVR_OS_WIN64) || defined (OVR_OS_WIN32)
  144.52 +
  144.53 +#pragma comment(lib, "version.lib")
  144.54 +
  144.55 +typedef BOOL(WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
  144.56 +BOOL Is64BitWindows()
  144.57 +{
  144.58 +#if defined(_WIN64)
  144.59 +    return TRUE;  // 64-bit programs run only on Win64
  144.60 +#elif defined(_WIN32)
  144.61 +    // 32-bit programs run on both 32-bit and 64-bit Windows
  144.62 +    // so must sniff
  144.63 +    BOOL f64 = FALSE;
  144.64 +    LPFN_ISWOW64PROCESS fnIsWow64Process;
  144.65 +
  144.66 +    fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(GetModuleHandle(L"kernel32"), "IsWow64Process");
  144.67 +    if (NULL != fnIsWow64Process)
  144.68 +    {
  144.69 +        return fnIsWow64Process(GetCurrentProcess(), &f64) && f64;
  144.70 +    }
  144.71 +    return FALSE;
  144.72 +#else
  144.73 +    return FALSE; // Win64 does not support Win16
  144.74 +#endif
  144.75 +}
  144.76 +#endif
  144.77 +
  144.78 +const char * OSAsString()
  144.79 +{
  144.80 +#if defined (OVR_OS_IPHONE)
  144.81 +    return "IPhone";
  144.82 +#elif defined (OVR_OS_DARWIN)
  144.83 +    return "Darwin";
  144.84 +#elif defined (OVR_OS_MAC)
  144.85 +    return "Mac";
  144.86 +#elif defined (OVR_OS_BSD)
  144.87 +    return "BSD";
  144.88 +#elif defined (OVR_OS_WIN64) || defined (OVR_OS_WIN32)
  144.89 +    if (Is64BitWindows())
  144.90 +        return "Win64";
  144.91 +    else
  144.92 +        return "Win32";
  144.93 +#elif defined (OVR_OS_ANDROID)
  144.94 +    return "Android";
  144.95 +#elif defined (OVR_OS_LINUX)
  144.96 +    return "Linux";
  144.97 +#elif defined (OVR_OS_BSD)
  144.98 +    return "BSD";
  144.99 +#else
 144.100 +    return "Other";
 144.101 +#endif
 144.102 +}
 144.103 +
 144.104 +uint64_t GetGuidInt()
 144.105 +{
 144.106 +    uint64_t g = Timer::GetTicksNanos();
 144.107 +
 144.108 +    uint64_t lastTime, thisTime;
 144.109 +    int j;
 144.110 +    // Sleep a small random time, then use the last 4 bits as a source of randomness
 144.111 +    for (j = 0; j < 8; j++)
 144.112 +    {
 144.113 +        lastTime = Timer::GetTicksNanos();
 144.114 +        Thread::MSleep(1);
 144.115 +        Thread::MSleep(0);
 144.116 +        thisTime = Timer::GetTicksNanos();
 144.117 +        uint64_t diff = thisTime - lastTime;
 144.118 +        unsigned int diff4Bits = (unsigned int)(diff & 15);
 144.119 +        diff4Bits <<= 32 - 4;
 144.120 +        diff4Bits >>= j * 4;
 144.121 +        ((char*)&g)[j] ^= diff4Bits;
 144.122 +    }
 144.123 +
 144.124 +    return g;
 144.125 +}
 144.126 +String GetGuidString()
 144.127 +{
 144.128 +    uint64_t guid = GetGuidInt();
 144.129 +
 144.130 +    char buff[64];
 144.131 +#if defined(OVR_CC_MSVC)
 144.132 +    OVR_sprintf(buff, sizeof(buff), "%I64u", guid);
 144.133 +#else
 144.134 +    OVR_sprintf(buff, sizeof(buff), "%llu", (unsigned long long) guid);
 144.135 +#endif
 144.136 +    return String(buff);
 144.137 +}
 144.138 +
 144.139 +const char * GetProcessInfo()
 144.140 +{
 144.141 +	#if defined (OVR_CPU_X86_64	)
 144.142 +    return "64 bit";
 144.143 +#elif defined (OVR_CPU_X86)
 144.144 +    return "32 bit";
 144.145 +#else
 144.146 +    return "TODO";
 144.147 +#endif
 144.148 +}
 144.149 +#ifdef OVR_OS_WIN32
 144.150 +
 144.151 +
 144.152 +String OSVersionAsString()
 144.153 +{
 144.154 +    return GetSystemFileVersionString("\\kernel32.dll");
 144.155 +}
 144.156 +String GetSystemFileVersionString(String filePath)
 144.157 +{
 144.158 +    char strFilePath[MAX_PATH]; // Local variable
 144.159 +    UINT sysDirLen = GetSystemDirectoryA(strFilePath, ARRAYSIZE(strFilePath));
 144.160 +    if (sysDirLen != 0)
 144.161 +    {
 144.162 +        OVR_strcat(strFilePath, MAX_PATH, filePath.ToCStr());
 144.163 +        return GetFileVersionString(strFilePath);
 144.164 +    }
 144.165 +    else
 144.166 +    {
 144.167 +        return "GetSystemDirectoryA failed";
 144.168 +    }
 144.169 +}
 144.170 +// See http://stackoverflow.com/questions/940707/how-do-i-programatically-get-the-version-of-a-dll-or-exe-file
 144.171 +String GetFileVersionString(String filePath)
 144.172 +{
 144.173 +    String result;
 144.174 +
 144.175 +    DWORD dwSize = GetFileVersionInfoSizeA(filePath.ToCStr(), NULL);
 144.176 +    if (dwSize == 0)
 144.177 +    {
 144.178 +        OVR_DEBUG_LOG(("Error in GetFileVersionInfoSizeA: %d (for %s)", GetLastError(), filePath.ToCStr()));
 144.179 +        result = filePath + " not found";
 144.180 +    }
 144.181 +    else
 144.182 +    {
 144.183 +        BYTE* pVersionInfo = new BYTE[dwSize];
 144.184 +        if (!pVersionInfo)
 144.185 +        {
 144.186 +            OVR_DEBUG_LOG(("Out of memory allocating %d bytes (for %s)", dwSize, filePath.ToCStr()));
 144.187 +            result = "Out of memory";
 144.188 +        }
 144.189 +        else
 144.190 +        {
 144.191 +            if (!GetFileVersionInfoA(filePath.ToCStr(), 0, dwSize, pVersionInfo))
 144.192 +            {
 144.193 +                OVR_DEBUG_LOG(("Error in GetFileVersionInfo: %d (for %s)", GetLastError(), filePath.ToCStr()));
 144.194 +                result = "Cannot get version info";
 144.195 +            }
 144.196 +            else
 144.197 +            {
 144.198 +                VS_FIXEDFILEINFO* pFileInfo = NULL;
 144.199 +                UINT              pLenFileInfo = 0;
 144.200 +                if (!VerQueryValue(pVersionInfo, TEXT("\\"), (LPVOID*)&pFileInfo, &pLenFileInfo))
 144.201 +                {
 144.202 +                    OVR_DEBUG_LOG(("Error in VerQueryValue: %d (for %s)", GetLastError(), filePath.ToCStr()));
 144.203 +                    result = "File has no version info";
 144.204 +                }
 144.205 +                else
 144.206 +                {
 144.207 +                    int major = (pFileInfo->dwFileVersionMS >> 16) & 0xffff;
 144.208 +                    int minor = (pFileInfo->dwFileVersionMS) & 0xffff;
 144.209 +                    int hotfix = (pFileInfo->dwFileVersionLS >> 16) & 0xffff;
 144.210 +                    int other = (pFileInfo->dwFileVersionLS) & 0xffff;
 144.211 +
 144.212 +                    char str[128];
 144.213 +                    OVR::OVR_sprintf(str, 128, "%d.%d.%d.%d", major, minor, hotfix, other);
 144.214 +
 144.215 +                    result = str;
 144.216 +                }
 144.217 +            }
 144.218 +
 144.219 +            delete[] pVersionInfo;
 144.220 +        }
 144.221 +    }
 144.222 +
 144.223 +    return result;
 144.224 +}
 144.225 +
 144.226 +
 144.227 +String GetDisplayDriverVersion()
 144.228 +{
 144.229 +    return GetSystemFileVersionString("\\OVRDisplay32.dll");
 144.230 +}
 144.231 +String GetCameraDriverVersion()
 144.232 +{
 144.233 +    return GetSystemFileVersionString("\\drivers\\OCUSBVID.sys");
 144.234 +}
 144.235 +
 144.236 +// From http://stackoverflow.com/questions/9524309/enumdisplaydevices-function-not-working-for-me
 144.237 +void GetGraphicsCardList( Array< String > &gpus)
 144.238 +{
 144.239 +	gpus.Clear();
 144.240 +
 144.241 +	DISPLAY_DEVICEA dd;
 144.242 +
 144.243 +	dd.cb = sizeof(dd);
 144.244 +
 144.245 +	DWORD deviceNum = 0;
 144.246 +	while( EnumDisplayDevicesA(NULL, deviceNum, &dd, 0) ){
 144.247 +        if (dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)
 144.248 +		    gpus.PushBack(dd.DeviceString);
 144.249 +		deviceNum++;
 144.250 +	}
 144.251 +}
 144.252 +#else
 144.253 +
 144.254 +// used for driver files
 144.255 +
 144.256 +String GetFileVersionString(String /*filePath*/)
 144.257 +{
 144.258 +	return String();
 144.259 +}
 144.260 +
 144.261 +String GetSystemFileVersionString(String /*filePath*/)
 144.262 +{
 144.263 +	return String();
 144.264 +}
 144.265 +
 144.266 +String GetDisplayDriverVersion()
 144.267 +{
 144.268 +	return String();
 144.269 +}
 144.270 +
 144.271 +String GetCameraDriverVersion()
 144.272 +{
 144.273 +	return String();
 144.274 +}
 144.275 +
 144.276 +#ifdef OVR_OS_MAC
 144.277 +    //use objective c source
 144.278 +#else
 144.279 +    
 144.280 +//todo linux, this requires searching /var/ files
 144.281 +void GetGraphicsCardList(OVR::Array< OVR::String > &gpus)
 144.282 +{
 144.283 +	gpus.Clear();
 144.284 +}
 144.285 +String OSVersionAsString()
 144.286 +{
 144.287 +    return String();
 144.288 +}
 144.289 +#endif //OVR_OS_MAC
 144.290 +#endif // WIN32
 144.291 +
 144.292 +} } // namespace OVR { namespace Util {
   145.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   145.2 +++ b/LibOVR/Src/Util/Util_SystemInfo.h	Wed Jan 14 06:51:16 2015 +0200
   145.3 @@ -0,0 +1,51 @@
   145.4 +/************************************************************************************
   145.5 +
   145.6 +Filename    :   Util_SystemInfo.h
   145.7 +Content     :   Various operations to get information about the system
   145.8 +Created     :   September 26, 2014
   145.9 +Author      :   Kevin Jenkins
  145.10 +
  145.11 +Copyright   :   Copyright 2014 Oculus VR, LLC All Rights reserved.
  145.12 +
  145.13 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License");
  145.14 +you may not use the Oculus VR Rift SDK except in compliance with the License,
  145.15 +which is provided at the time of installation or download, or which
  145.16 +otherwise accompanies this software in either electronic or hard copy form.
  145.17 +
  145.18 +You may obtain a copy of the License at
  145.19 +
  145.20 +http://www.oculusvr.com/licenses/LICENSE-3.2
  145.21 +
  145.22 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK
  145.23 +distributed under the License is distributed on an "AS IS" BASIS,
  145.24 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  145.25 +See the License for the specific language governing permissions and
  145.26 +limitations under the License.
  145.27 +
  145.28 +************************************************************************************/
  145.29 +
  145.30 +
  145.31 +#ifndef OVR_Util_SystemInfo_h
  145.32 +#define OVR_Util_SystemInfo_h
  145.33 +
  145.34 +#include "../Kernel/OVR_String.h"
  145.35 +#include "../Kernel/OVR_Types.h"
  145.36 +#include "../Kernel/OVR_Array.h"
  145.37 +
  145.38 +namespace OVR { namespace Util {
  145.39 +
  145.40 +const char * OSAsString();
  145.41 +String OSVersionAsString();
  145.42 +uint64_t GetGuidInt();
  145.43 +String GetGuidString();
  145.44 +const char * GetProcessInfo();
  145.45 +String GetFileVersionString(String filePath);
  145.46 +String GetSystemFileVersionString(String filePath);
  145.47 +String GetDisplayDriverVersion();
  145.48 +String GetCameraDriverVersion();
  145.49 +void GetGraphicsCardList(OVR::Array< OVR::String > &gpus);
  145.50 +String GetProcessorInfo(int* numcores = NULL);
  145.51 +
  145.52 +} } // namespace OVR { namespace Util {
  145.53 +
  145.54 +#endif // OVR_Util_SystemInfo_h
   146.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   146.2 +++ b/Makefile	Wed Jan 14 06:51:16 2015 +0200
   146.3 @@ -0,0 +1,104 @@
   146.4 +#############################################################################
   146.5 +#
   146.6 +# Filename    : Makefile
   146.7 +# Content     : Makefile for building linux libovr and OculusWorldDemo
   146.8 +# Created     : 2013
   146.9 +# Authors     : Simon Hallam and Peter Giokaris
  146.10 +# Copyright   : Copyright 2013 OculusVR, Inc. All Rights Reserved
  146.11 +# Instruction : See 'make help'
  146.12 +#
  146.13 +#               make                builds the release versions for the 
  146.14 +#                                   current architechture
  146.15 +#               make clean          delete intermediate release object files 
  146.16 +#                                   and library and executable
  146.17 +#               make DEBUG=1        builds the debug version for the current
  146.18 +#                                   architechture
  146.19 +#               make clean DEBUG=1  deletes intermediate debug object files 
  146.20 +#                                   and the library and executable
  146.21 +#
  146.22 +# Output      : Relative to the directory this Makefile lives in, libraries
  146.23 +#               and executables are built at the following locations 
  146.24 +#               depending upon the architechture of the system you are 
  146.25 +#               running:
  146.26 +#
  146.27 +#           ./LibOVR/Lib/Linux/Debug/i386/libovr.a
  146.28 +#           ./LibOVR/Lib/Linux/Debug/x86_64/libovr.a
  146.29 +#           ./LibOVR/Lib/Linux/Release/i386/libovr.a
  146.30 +#           ./LibOVR/Lib/Linux/Release/x86_64/libovr.a
  146.31 +#           ./Samples/OculusWorldDemo/Release/OculusWorldDemo_i386_Release
  146.32 +#           ./Samples/OculusWorldDemo/Release/OculusWorldDemo_x86_64_Release
  146.33 +#           ./Samples/OculusWorldDemo/Release/OculusWorldDemo_i386_Debug
  146.34 +#           ./Samples/OculusWorldDemo/Release/OculusWorldDemo_x86_64_Debug
  146.35 +#
  146.36 +#############################################################################
  146.37 +
  146.38 +####### Include makefiles in current directory
  146.39 +RELEASESUFFIX =
  146.40 +-include Makefile.*[^~]
  146.41 +
  146.42 +####### Detect system architecture
  146.43 +
  146.44 +SYSARCH       = i386
  146.45 +ifeq ($(shell uname -m),x86_64)
  146.46 +SYSARCH       = x86_64
  146.47 +endif
  146.48 +
  146.49 +####### Compiler, tools and options
  146.50 +
  146.51 +CXX           = g++
  146.52 +LINK          = ar rvs
  146.53 +DELETEFILE    = rm -f
  146.54 +
  146.55 +####### Detect debug or release
  146.56 +
  146.57 +DEBUG         = 0
  146.58 +ifeq ($(DEBUG), 1)
  146.59 +	RELEASETYPE   = Debug$(RELEASESUFFIX)
  146.60 +else
  146.61 +	RELEASETYPE   = Release$(RELEASESUFFIX)
  146.62 +endif
  146.63 +
  146.64 +# Override release types and DEBUG settings in child makefiles.
  146.65 +export RELEASETYPE
  146.66 +export DEBUG
  146.67 +
  146.68 +####### Target settings
  146.69 +LIBOVRPATH    = ./LibOVR
  146.70 +OWDPATH       = ./Samples/OculusWorldDemo
  146.71 +
  146.72 +LIBOVRTARGET  = $(LIBOVRPATH)/Lib/Linux/$(RELEASETYPE)/$(SYSARCH)/libovr.a
  146.73 +OWDTARGET     = $(OWDPATH)/Release/OculusWorldDemo_$(SYSARCH)_$(RELEASETYPE)
  146.74 +
  146.75 +####### Targets
  146.76 +
  146.77 +all:    $(LIBOVRTARGET) $(OWDTARGET)
  146.78 +
  146.79 +$(OWDTARGET): force_look $(LIBOVRTARGET)
  146.80 +	$(MAKE) -C $(OWDPATH)
  146.81 +
  146.82 +$(LIBOVRTARGET): force_look
  146.83 +	$(MAKE) -C $(LIBOVRPATH)
  146.84 +
  146.85 +run: $(OWDTARGET)
  146.86 +	$(MAKE) -C $(OWDPATH) run
  146.87 +
  146.88 +clean:
  146.89 +	$(MAKE) -C $(LIBOVRPATH) clean
  146.90 +	$(MAKE) -C $(OWDPATH) clean
  146.91 +
  146.92 +force_look:
  146.93 +	true
  146.94 +
  146.95 +# Generate help based on descriptions of targets given in this Makefile.
  146.96 +help: 		##- Show this help
  146.97 +	@echo "Targets:"
  146.98 +	@echo "  all      : Build LibOVR and Oculus World Demo"
  146.99 +	@echo "  run      : Run Oculus World Demo"
 146.100 +	@echo "  clean    : Clean selected release (DEBUG=[0,1])"
 146.101 +	@echo "  cleanall : Clean all possible release targets"
 146.102 +	@echo ""
 146.103 +	@echo "Options:"
 146.104 +	@echo "  DEBUG    : 'make DEBUG=1' will build the current target in DEBUG mode"
 146.105 +
 146.106 +# Experimental method of automatically generating help from target names.
 146.107 +#@grep -h "##-" $(MAKEFILE_LIST) | grep -v grep | sed -e 's/^/ /' | sed -e 's/\:\s*##-/:/' | awk '{printf "%+6s\n", $$0}'