summaryrefslogtreecommitdiff
path: root/platform
diff options
context:
space:
mode:
Diffstat (limited to 'platform')
-rw-r--r--platform/android/AndroidManifest.xml.template5
-rw-r--r--platform/android/SCsub4
-rw-r--r--platform/android/cpu-features.c1089
-rw-r--r--platform/android/cpu-features.h214
-rw-r--r--platform/android/detect.py7
-rw-r--r--platform/android/export/export.cpp6
-rw-r--r--platform/android/java/res/layout/downloading_expansion.xml166
-rw-r--r--platform/android/java/res/values/strings.xml12
-rw-r--r--platform/android/java/src/com/android/godot/Godot.java378
-rw-r--r--platform/android/java/src/com/android/godot/GodotDownloaderAlarmReceiver.java3
-rw-r--r--platform/android/java/src/com/android/godot/GodotDownloaderService.java13
-rw-r--r--platform/android/java/src/com/android/godot/GodotPaymentV3.java32
-rw-r--r--platform/android/java/src/com/android/godot/payments/GenericConsumeTask.java53
-rw-r--r--platform/android/java/src/com/android/godot/payments/HandlePurchaseTask.java14
-rw-r--r--platform/android/java/src/com/android/godot/payments/PaymentsCache.java4
-rw-r--r--platform/android/java/src/com/android/godot/payments/PaymentsManager.java41
-rw-r--r--platform/android/java/src/com/android/godot/payments/PurchaseTask.java26
-rw-r--r--platform/android/java/src/com/android/godot/payments/ReleaseAllConsumablesTask.java87
-rw-r--r--platform/android/java_class_wrapper.cpp1332
-rw-r--r--platform/android/java_class_wrapper.h168
-rw-r--r--platform/android/java_glue.cpp20
-rw-r--r--platform/android/libs/downloader_library/.classpath9
-rw-r--r--platform/android/libs/downloader_library/.settings/org.eclipse.jdt.core.prefs4
-rw-r--r--platform/android/libs/downloader_library/AndroidManifest.xml9
-rw-r--r--platform/android/libs/downloader_library/build.xml92
-rw-r--r--platform/android/libs/downloader_library/gen/com/android/vending/expansion/downloader/BuildConfig.java6
-rw-r--r--platform/android/libs/downloader_library/gen/com/android/vending/expansion/downloader/R.java73
-rw-r--r--platform/android/libs/downloader_library/proguard-project.txt20
-rw-r--r--platform/android/libs/downloader_library/project.properties13
-rw-r--r--platform/android/libs/downloader_library/res/drawable-hdpi/notify_panel_notification_icon_bg.pngbin0 -> 1027 bytes
-rw-r--r--platform/android/libs/downloader_library/res/drawable-mdpi/notify_panel_notification_icon_bg.pngbin0 -> 1125 bytes
-rw-r--r--platform/android/libs/downloader_library/res/layout/status_bar_ongoing_event_progress_bar.xml104
-rw-r--r--platform/android/libs/downloader_library/res/values-v11/styles.xml6
-rw-r--r--platform/android/libs/downloader_library/res/values-v9/styles.xml5
-rw-r--r--platform/android/libs/downloader_library/res/values/strings.xml41
-rw-r--r--platform/android/libs/downloader_library/res/values/styles.xml25
-rw-r--r--platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/Constants.java236
-rw-r--r--platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/DownloadProgressInfo.java80
-rw-r--r--platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/DownloaderClientMarshaller.java277
-rw-r--r--platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/DownloaderServiceMarshaller.java181
-rw-r--r--platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/Helpers.java306
-rw-r--r--platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/IDownloaderClient.java126
-rw-r--r--platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/IDownloaderService.java83
-rw-r--r--platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/IStub.java41
-rw-r--r--platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/SystemFacade.java123
-rw-r--r--platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/AndroidHttpClient.java536
-rwxr-xr-xplatform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/CustomIntentService.java112
-rw-r--r--platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/CustomNotificationFactory.java30
-rw-r--r--platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/DownloadInfo.java92
-rw-r--r--platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/DownloadNotification.java231
-rw-r--r--platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/DownloadThread.java963
-rw-r--r--platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/DownloaderService.java1341
-rwxr-xr-xplatform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/DownloadsDB.java510
-rw-r--r--platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/HttpDateTime.java200
-rw-r--r--platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/V14CustomNotification.java101
-rw-r--r--platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/V3CustomNotification.java116
-rw-r--r--platform/android/libs/google_play_services/.classpath1
-rw-r--r--platform/android/libs/play_licensing/src/com/google/android/vending/licensing/LicenseChecker.java2
-rw-r--r--platform/bb10/detect.py2
-rw-r--r--platform/bb10/export/export.cpp2
-rw-r--r--platform/iphone/SCsub2
-rw-r--r--platform/iphone/app_delegate.mm4
-rw-r--r--platform/iphone/audio_driver_iphone.cpp39
-rw-r--r--platform/iphone/audio_driver_iphone.h4
-rw-r--r--platform/iphone/detect.py13
-rwxr-xr-xplatform/iphone/gl_view.mm6
-rw-r--r--platform/iphone/globals/global_defaults.cpp1
-rw-r--r--platform/iphone/in_app_store.h2
-rw-r--r--platform/iphone/in_app_store.mm31
-rw-r--r--platform/javascript/export/export.cpp4
-rw-r--r--platform/osx/export/export.cpp4
-rw-r--r--platform/server/detect.py1
-rw-r--r--platform/windows/detect.py5
-rw-r--r--platform/windows/os_windows.cpp151
-rw-r--r--platform/windows/os_windows.h8
-rw-r--r--platform/winrt/SCsub8
-rw-r--r--platform/winrt/detect.py83
-rw-r--r--platform/winrt/include/EGL/egl.h298
-rw-r--r--platform/winrt/include/EGL/eglext.h759
-rw-r--r--platform/winrt/include/EGL/eglplatform.h131
-rw-r--r--platform/winrt/include/FunctionDiscoveryKeys_devpkey.h213
-rw-r--r--platform/winrt/include/GLES2/gl2.h620
-rw-r--r--platform/winrt/include/GLES2/gl2ext.h2013
-rw-r--r--platform/winrt/include/GLES2/gl2platform.h30
-rw-r--r--platform/winrt/include/GLES3/gl3.h1061
-rw-r--r--platform/winrt/include/GLES3/gl3ext.h24
-rw-r--r--platform/winrt/include/GLES3/gl3platform.h30
-rw-r--r--platform/winrt/include/GLSLANG/ShaderLang.h513
-rw-r--r--platform/winrt/include/GLSLANG/ShaderVars.h128
-rw-r--r--platform/winrt/include/KHR/khrplatform.h282
-rw-r--r--platform/winrt/include/angle_gl.h23
-rw-r--r--platform/winrt/logo.pngbin0 -> 1434 bytes
-rw-r--r--platform/winrt/os_winrt.cpp756
-rw-r--r--platform/winrt/os_winrt.h242
-rw-r--r--platform/winrt/platform_config.h2
-rw-r--r--platform/winrt/thread_winrt.cpp42
-rw-r--r--platform/winrt/thread_winrt.h35
-rw-r--r--platform/x11/context_gl_x11.cpp11
-rw-r--r--platform/x11/os_x11.cpp96
-rw-r--r--platform/x11/os_x11.h10
100 files changed, 17264 insertions, 194 deletions
diff --git a/platform/android/AndroidManifest.xml.template b/platform/android/AndroidManifest.xml.template
index e723b693d8..60861db603 100644
--- a/platform/android/AndroidManifest.xml.template
+++ b/platform/android/AndroidManifest.xml.template
@@ -10,12 +10,12 @@
android:largeScreens="true"
android:xlargeScreens="true"/>
- <application android:label="@string/godot_project_name_string" android:icon="@drawable/icon">
+ <application android:label="@string/godot_project_name_string" android:icon="@drawable/icon" android:allowBackup="false">
<activity android:name="com.android.godot.Godot"
android:label="@string/godot_project_name_string"
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
android:launchMode="singleTask"
- android:screenOrientation="landscape"
+ android:screenOrientation="portrait"
android:configChanges="orientation|keyboardHidden|screenSize|smallestScreenSize">
<intent-filter>
@@ -23,6 +23,7 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
+ <service android:name="com.android.godot.GodotDownloaderService" />
diff --git a/platform/android/SCsub b/platform/android/SCsub
index 8e61b7d8e0..699db30cad 100644
--- a/platform/android/SCsub
+++ b/platform/android/SCsub
@@ -15,7 +15,9 @@ android_files = [
'audio_driver_jandroid.cpp',
'ifaddrs_android.cpp',
'android_native_app_glue.c',
- 'java_glue.cpp'
+ 'java_glue.cpp',
+ 'cpu-features.c',
+ 'java_class_wrapper.cpp'
]
#env.Depends('#core/math/vector3.h', 'vector3_psp.h')
diff --git a/platform/android/cpu-features.c b/platform/android/cpu-features.c
new file mode 100644
index 0000000000..156d464729
--- /dev/null
+++ b/platform/android/cpu-features.c
@@ -0,0 +1,1089 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* ChangeLog for this library:
+ *
+ * NDK r8d: Add android_setCpu().
+ *
+ * NDK r8c: Add new ARM CPU features: VFPv2, VFP_D32, VFP_FP16,
+ * VFP_FMA, NEON_FMA, IDIV_ARM, IDIV_THUMB2 and iWMMXt.
+ *
+ * Rewrite the code to parse /proc/self/auxv instead of
+ * the "Features" field in /proc/cpuinfo.
+ *
+ * Dynamically allocate the buffer that hold the content
+ * of /proc/cpuinfo to deal with newer hardware.
+ *
+ * NDK r7c: Fix CPU count computation. The old method only reported the
+ * number of _active_ CPUs when the library was initialized,
+ * which could be less than the real total.
+ *
+ * NDK r5: Handle buggy kernels which report a CPU Architecture number of 7
+ * for an ARMv6 CPU (see below).
+ *
+ * Handle kernels that only report 'neon', and not 'vfpv3'
+ * (VFPv3 is mandated by the ARM architecture is Neon is implemented)
+ *
+ * Handle kernels that only report 'vfpv3d16', and not 'vfpv3'
+ *
+ * Fix x86 compilation. Report ANDROID_CPU_FAMILY_X86 in
+ * android_getCpuFamily().
+ *
+ * NDK r4: Initial release
+ */
+
+#if defined(__le32__)
+
+// When users enter this, we should only provide interface and
+// libportable will give the implementations.
+
+#else // !__le32__
+
+#include <sys/system_properties.h>
+#include <pthread.h>
+#include "cpu-features.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <errno.h>
+
+static pthread_once_t g_once;
+static int g_inited;
+static AndroidCpuFamily g_cpuFamily;
+static uint64_t g_cpuFeatures;
+static int g_cpuCount;
+
+#ifdef __arm__
+static uint32_t g_cpuIdArm;
+#endif
+
+static const int android_cpufeatures_debug = 0;
+
+#ifdef __arm__
+# define DEFAULT_CPU_FAMILY ANDROID_CPU_FAMILY_ARM
+#elif defined __i386__
+# define DEFAULT_CPU_FAMILY ANDROID_CPU_FAMILY_X86
+#else
+# define DEFAULT_CPU_FAMILY ANDROID_CPU_FAMILY_UNKNOWN
+#endif
+
+#define D(...) \
+ do { \
+ if (android_cpufeatures_debug) { \
+ printf(__VA_ARGS__); fflush(stdout); \
+ } \
+ } while (0)
+
+#ifdef __i386__
+static __inline__ void x86_cpuid(int func, int values[4])
+{
+ int a, b, c, d;
+ /* We need to preserve ebx since we're compiling PIC code */
+ /* this means we can't use "=b" for the second output register */
+ __asm__ __volatile__ ( \
+ "push %%ebx\n"
+ "cpuid\n" \
+ "mov %%ebx, %1\n"
+ "pop %%ebx\n"
+ : "=a" (a), "=r" (b), "=c" (c), "=d" (d) \
+ : "a" (func) \
+ );
+ values[0] = a;
+ values[1] = b;
+ values[2] = c;
+ values[3] = d;
+}
+#endif
+
+/* Get the size of a file by reading it until the end. This is needed
+ * because files under /proc do not always return a valid size when
+ * using fseek(0, SEEK_END) + ftell(). Nor can they be mmap()-ed.
+ */
+static int
+get_file_size(const char* pathname)
+{
+ int fd, ret, result = 0;
+ char buffer[256];
+
+ fd = open(pathname, O_RDONLY);
+ if (fd < 0) {
+ D("Can't open %s: %s\n", pathname, strerror(errno));
+ return -1;
+ }
+
+ for (;;) {
+ int ret = read(fd, buffer, sizeof buffer);
+ if (ret < 0) {
+ if (errno == EINTR)
+ continue;
+ D("Error while reading %s: %s\n", pathname, strerror(errno));
+ break;
+ }
+ if (ret == 0)
+ break;
+
+ result += ret;
+ }
+ close(fd);
+ return result;
+}
+
+/* Read the content of /proc/cpuinfo into a user-provided buffer.
+ * Return the length of the data, or -1 on error. Does *not*
+ * zero-terminate the content. Will not read more
+ * than 'buffsize' bytes.
+ */
+static int
+read_file(const char* pathname, char* buffer, size_t buffsize)
+{
+ int fd, count;
+
+ fd = open(pathname, O_RDONLY);
+ if (fd < 0) {
+ D("Could not open %s: %s\n", pathname, strerror(errno));
+ return -1;
+ }
+ count = 0;
+ while (count < (int)buffsize) {
+ int ret = read(fd, buffer + count, buffsize - count);
+ if (ret < 0) {
+ if (errno == EINTR)
+ continue;
+ D("Error while reading from %s: %s\n", pathname, strerror(errno));
+ if (count == 0)
+ count = -1;
+ break;
+ }
+ if (ret == 0)
+ break;
+ count += ret;
+ }
+ close(fd);
+ return count;
+}
+
+/* Extract the content of a the first occurence of a given field in
+ * the content of /proc/cpuinfo and return it as a heap-allocated
+ * string that must be freed by the caller.
+ *
+ * Return NULL if not found
+ */
+static char*
+extract_cpuinfo_field(const char* buffer, int buflen, const char* field)
+{
+ int fieldlen = strlen(field);
+ const char* bufend = buffer + buflen;
+ char* result = NULL;
+ int len, ignore;
+ const char *p, *q;
+
+ /* Look for first field occurence, and ensures it starts the line. */
+ p = buffer;
+ for (;;) {
+ p = memmem(p, bufend-p, field, fieldlen);
+ if (p == NULL)
+ goto EXIT;
+
+ if (p == buffer || p[-1] == '\n')
+ break;
+
+ p += fieldlen;
+ }
+
+ /* Skip to the first column followed by a space */
+ p += fieldlen;
+ p = memchr(p, ':', bufend-p);
+ if (p == NULL || p[1] != ' ')
+ goto EXIT;
+
+ /* Find the end of the line */
+ p += 2;
+ q = memchr(p, '\n', bufend-p);
+ if (q == NULL)
+ q = bufend;
+
+ /* Copy the line into a heap-allocated buffer */
+ len = q-p;
+ result = malloc(len+1);
+ if (result == NULL)
+ goto EXIT;
+
+ memcpy(result, p, len);
+ result[len] = '\0';
+
+EXIT:
+ return result;
+}
+
+/* Checks that a space-separated list of items contains one given 'item'.
+ * Returns 1 if found, 0 otherwise.
+ */
+static int
+has_list_item(const char* list, const char* item)
+{
+ const char* p = list;
+ int itemlen = strlen(item);
+
+ if (list == NULL)
+ return 0;
+
+ while (*p) {
+ const char* q;
+
+ /* skip spaces */
+ while (*p == ' ' || *p == '\t')
+ p++;
+
+ /* find end of current list item */
+ q = p;
+ while (*q && *q != ' ' && *q != '\t')
+ q++;
+
+ if (itemlen == q-p && !memcmp(p, item, itemlen))
+ return 1;
+
+ /* skip to next item */
+ p = q;
+ }
+ return 0;
+}
+
+/* Parse a number starting from 'input', but not going further
+ * than 'limit'. Return the value into '*result'.
+ *
+ * NOTE: Does not skip over leading spaces, or deal with sign characters.
+ * NOTE: Ignores overflows.
+ *
+ * The function returns NULL in case of error (bad format), or the new
+ * position after the decimal number in case of success (which will always
+ * be <= 'limit').
+ */
+static const char*
+parse_number(const char* input, const char* limit, int base, int* result)
+{
+ const char* p = input;
+ int val = 0;
+ while (p < limit) {
+ int d = (*p - '0');
+ if ((unsigned)d >= 10U) {
+ d = (*p - 'a');
+ if ((unsigned)d >= 6U)
+ d = (*p - 'A');
+ if ((unsigned)d >= 6U)
+ break;
+ d += 10;
+ }
+ if (d >= base)
+ break;
+ val = val*base + d;
+ p++;
+ }
+ if (p == input)
+ return NULL;
+
+ *result = val;
+ return p;
+}
+
+static const char*
+parse_decimal(const char* input, const char* limit, int* result)
+{
+ return parse_number(input, limit, 10, result);
+}
+
+static const char*
+parse_hexadecimal(const char* input, const char* limit, int* result)
+{
+ return parse_number(input, limit, 16, result);
+}
+
+/* This small data type is used to represent a CPU list / mask, as read
+ * from sysfs on Linux. See http://www.kernel.org/doc/Documentation/cputopology.txt
+ *
+ * For now, we don't expect more than 32 cores on mobile devices, so keep
+ * everything simple.
+ */
+typedef struct {
+ uint32_t mask;
+} CpuList;
+
+static __inline__ void
+cpulist_init(CpuList* list) {
+ list->mask = 0;
+}
+
+static __inline__ void
+cpulist_and(CpuList* list1, CpuList* list2) {
+ list1->mask &= list2->mask;
+}
+
+static __inline__ void
+cpulist_set(CpuList* list, int index) {
+ if ((unsigned)index < 32) {
+ list->mask |= (uint32_t)(1U << index);
+ }
+}
+
+static __inline__ int
+cpulist_count(CpuList* list) {
+ return __builtin_popcount(list->mask);
+}
+
+/* Parse a textual list of cpus and store the result inside a CpuList object.
+ * Input format is the following:
+ * - comma-separated list of items (no spaces)
+ * - each item is either a single decimal number (cpu index), or a range made
+ * of two numbers separated by a single dash (-). Ranges are inclusive.
+ *
+ * Examples: 0
+ * 2,4-127,128-143
+ * 0-1
+ */
+static void
+cpulist_parse(CpuList* list, const char* line, int line_len)
+{
+ const char* p = line;
+ const char* end = p + line_len;
+ const char* q;
+
+ /* NOTE: the input line coming from sysfs typically contains a
+ * trailing newline, so take care of it in the code below
+ */
+ while (p < end && *p != '\n')
+ {
+ int val, start_value, end_value;
+
+ /* Find the end of current item, and put it into 'q' */
+ q = memchr(p, ',', end-p);
+ if (q == NULL) {
+ q = end;
+ }
+
+ /* Get first value */
+ p = parse_decimal(p, q, &start_value);
+ if (p == NULL)
+ goto BAD_FORMAT;
+
+ end_value = start_value;
+
+ /* If we're not at the end of the item, expect a dash and
+ * and integer; extract end value.
+ */
+ if (p < q && *p == '-') {
+ p = parse_decimal(p+1, q, &end_value);
+ if (p == NULL)
+ goto BAD_FORMAT;
+ }
+
+ /* Set bits CPU list bits */
+ for (val = start_value; val <= end_value; val++) {
+ cpulist_set(list, val);
+ }
+
+ /* Jump to next item */
+ p = q;
+ if (p < end)
+ p++;
+ }
+
+BAD_FORMAT:
+ ;
+}
+
+/* Read a CPU list from one sysfs file */
+static void
+cpulist_read_from(CpuList* list, const char* filename)
+{
+ char file[64];
+ int filelen;
+
+ cpulist_init(list);
+
+ filelen = read_file(filename, file, sizeof file);
+ if (filelen < 0) {
+ D("Could not read %s: %s\n", filename, strerror(errno));
+ return;
+ }
+
+ cpulist_parse(list, file, filelen);
+}
+
+// See <asm/hwcap.h> kernel header.
+#define HWCAP_VFP (1 << 6)
+#define HWCAP_IWMMXT (1 << 9)
+#define HWCAP_NEON (1 << 12)
+#define HWCAP_VFPv3 (1 << 13)
+#define HWCAP_VFPv3D16 (1 << 14)
+#define HWCAP_VFPv4 (1 << 16)
+#define HWCAP_IDIVA (1 << 17)
+#define HWCAP_IDIVT (1 << 18)
+
+#define AT_HWCAP 16
+
+#if defined(__arm__)
+/* Compute the ELF HWCAP flags.
+ */
+static uint32_t
+get_elf_hwcap(const char* cpuinfo, int cpuinfo_len)
+{
+ /* IMPORTANT:
+ * Accessing /proc/self/auxv doesn't work anymore on all
+ * platform versions. More specifically, when running inside
+ * a regular application process, most of /proc/self/ will be
+ * non-readable, including /proc/self/auxv. This doesn't
+ * happen however if the application is debuggable, or when
+ * running under the "shell" UID, which is why this was not
+ * detected appropriately.
+ */
+#if 0
+ uint32_t result = 0;
+ const char filepath[] = "/proc/self/auxv";
+ int fd = open(filepath, O_RDONLY);
+ if (fd < 0) {
+ D("Could not open %s: %s\n", filepath, strerror(errno));
+ return 0;
+ }
+
+ struct { uint32_t tag; uint32_t value; } entry;
+
+ for (;;) {
+ int ret = read(fd, (char*)&entry, sizeof entry);
+ if (ret < 0) {
+ if (errno == EINTR)
+ continue;
+ D("Error while reading %s: %s\n", filepath, strerror(errno));
+ break;
+ }
+ // Detect end of list.
+ if (ret == 0 || (entry.tag == 0 && entry.value == 0))
+ break;
+ if (entry.tag == AT_HWCAP) {
+ result = entry.value;
+ break;
+ }
+ }
+ close(fd);
+ return result;
+#else
+ // Recreate ELF hwcaps by parsing /proc/cpuinfo Features tag.
+ uint32_t hwcaps = 0;
+
+ char* cpuFeatures = extract_cpuinfo_field(cpuinfo, cpuinfo_len, "Features");
+
+ if (cpuFeatures != NULL) {
+ D("Found cpuFeatures = '%s'\n", cpuFeatures);
+
+ if (has_list_item(cpuFeatures, "vfp"))
+ hwcaps |= HWCAP_VFP;
+ if (has_list_item(cpuFeatures, "vfpv3"))
+ hwcaps |= HWCAP_VFPv3;
+ if (has_list_item(cpuFeatures, "vfpv3d16"))
+ hwcaps |= HWCAP_VFPv3D16;
+ if (has_list_item(cpuFeatures, "vfpv4"))
+ hwcaps |= HWCAP_VFPv4;
+ if (has_list_item(cpuFeatures, "neon"))
+ hwcaps |= HWCAP_NEON;
+ if (has_list_item(cpuFeatures, "idiva"))
+ hwcaps |= HWCAP_IDIVA;
+ if (has_list_item(cpuFeatures, "idivt"))
+ hwcaps |= HWCAP_IDIVT;
+ if (has_list_item(cpuFeatures, "idiv"))
+ hwcaps |= HWCAP_IDIVA | HWCAP_IDIVT;
+ if (has_list_item(cpuFeatures, "iwmmxt"))
+ hwcaps |= HWCAP_IWMMXT;
+
+ free(cpuFeatures);
+ }
+ return hwcaps;
+#endif
+}
+#endif /* __arm__ */
+
+/* Return the number of cpus present on a given device.
+ *
+ * To handle all weird kernel configurations, we need to compute the
+ * intersection of the 'present' and 'possible' CPU lists and count
+ * the result.
+ */
+static int
+get_cpu_count(void)
+{
+ CpuList cpus_present[1];
+ CpuList cpus_possible[1];
+
+ cpulist_read_from(cpus_present, "/sys/devices/system/cpu/present");
+ cpulist_read_from(cpus_possible, "/sys/devices/system/cpu/possible");
+
+ /* Compute the intersection of both sets to get the actual number of
+ * CPU cores that can be used on this device by the kernel.
+ */
+ cpulist_and(cpus_present, cpus_possible);
+
+ return cpulist_count(cpus_present);
+}
+
+static void
+android_cpuInitFamily(void)
+{
+#if defined(__arm__)
+ g_cpuFamily = ANDROID_CPU_FAMILY_ARM;
+#elif defined(__i386__)
+ g_cpuFamily = ANDROID_CPU_FAMILY_X86;
+#elif defined(__mips64)
+/* Needs to be before __mips__ since the compiler defines both */
+ g_cpuFamily = ANDROID_CPU_FAMILY_MIPS64;
+#elif defined(__mips__)
+ g_cpuFamily = ANDROID_CPU_FAMILY_MIPS;
+#elif defined(__aarch64__)
+ g_cpuFamily = ANDROID_CPU_FAMILY_ARM64;
+#elif defined(__x86_64__)
+ g_cpuFamily = ANDROID_CPU_FAMILY_X86_64;
+#else
+ g_cpuFamily = ANDROID_CPU_FAMILY_UNKNOWN;
+#endif
+}
+
+static void
+android_cpuInit(void)
+{
+ char* cpuinfo = NULL;
+ int cpuinfo_len;
+
+ android_cpuInitFamily();
+
+ g_cpuFeatures = 0;
+ g_cpuCount = 1;
+ g_inited = 1;
+
+ cpuinfo_len = get_file_size("/proc/cpuinfo");
+ if (cpuinfo_len < 0) {
+ D("cpuinfo_len cannot be computed!");
+ return;
+ }
+ cpuinfo = malloc(cpuinfo_len);
+ if (cpuinfo == NULL) {
+ D("cpuinfo buffer could not be allocated");
+ return;
+ }
+ cpuinfo_len = read_file("/proc/cpuinfo", cpuinfo, cpuinfo_len);
+ D("cpuinfo_len is (%d):\n%.*s\n", cpuinfo_len,
+ cpuinfo_len >= 0 ? cpuinfo_len : 0, cpuinfo);
+
+ if (cpuinfo_len < 0) /* should not happen */ {
+ free(cpuinfo);
+ return;
+ }
+
+ /* Count the CPU cores, the value may be 0 for single-core CPUs */
+ g_cpuCount = get_cpu_count();
+ if (g_cpuCount == 0) {
+ g_cpuCount = 1;
+ }
+
+ D("found cpuCount = %d\n", g_cpuCount);
+
+#ifdef __arm__
+ {
+ char* features = NULL;
+ char* architecture = NULL;
+
+ /* Extract architecture from the "CPU Architecture" field.
+ * The list is well-known, unlike the the output of
+ * the 'Processor' field which can vary greatly.
+ *
+ * See the definition of the 'proc_arch' array in
+ * $KERNEL/arch/arm/kernel/setup.c and the 'c_show' function in
+ * same file.
+ */
+ char* cpuArch = extract_cpuinfo_field(cpuinfo, cpuinfo_len, "CPU architecture");
+
+ if (cpuArch != NULL) {
+ char* end;
+ long archNumber;
+ int hasARMv7 = 0;
+
+ D("found cpuArch = '%s'\n", cpuArch);
+
+ /* read the initial decimal number, ignore the rest */
+ archNumber = strtol(cpuArch, &end, 10);
+
+ /* Here we assume that ARMv8 will be upwards compatible with v7
+ * in the future. Unfortunately, there is no 'Features' field to
+ * indicate that Thumb-2 is supported.
+ */
+ if (end > cpuArch && archNumber >= 7) {
+ hasARMv7 = 1;
+ }
+
+ /* Unfortunately, it seems that certain ARMv6-based CPUs
+ * report an incorrect architecture number of 7!
+ *
+ * See http://code.google.com/p/android/issues/detail?id=10812
+ *
+ * We try to correct this by looking at the 'elf_format'
+ * field reported by the 'Processor' field, which is of the
+ * form of "(v7l)" for an ARMv7-based CPU, and "(v6l)" for
+ * an ARMv6-one.
+ */
+ if (hasARMv7) {
+ char* cpuProc = extract_cpuinfo_field(cpuinfo, cpuinfo_len,
+ "Processor");
+ if (cpuProc != NULL) {
+ D("found cpuProc = '%s'\n", cpuProc);
+ if (has_list_item(cpuProc, "(v6l)")) {
+ D("CPU processor and architecture mismatch!!\n");
+ hasARMv7 = 0;
+ }
+ free(cpuProc);
+ }
+ }
+
+ if (hasARMv7) {
+ g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_ARMv7;
+ }
+
+ /* The LDREX / STREX instructions are available from ARMv6 */
+ if (archNumber >= 6) {
+ g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_LDREX_STREX;
+ }
+
+ free(cpuArch);
+ }
+
+ /* Extract the list of CPU features from ELF hwcaps */
+ uint32_t hwcaps = get_elf_hwcap(cpuinfo, cpuinfo_len);
+
+ if (hwcaps != 0) {
+ int has_vfp = (hwcaps & HWCAP_VFP);
+ int has_vfpv3 = (hwcaps & HWCAP_VFPv3);
+ int has_vfpv3d16 = (hwcaps & HWCAP_VFPv3D16);
+ int has_vfpv4 = (hwcaps & HWCAP_VFPv4);
+ int has_neon = (hwcaps & HWCAP_NEON);
+ int has_idiva = (hwcaps & HWCAP_IDIVA);
+ int has_idivt = (hwcaps & HWCAP_IDIVT);
+ int has_iwmmxt = (hwcaps & HWCAP_IWMMXT);
+
+ // The kernel does a poor job at ensuring consistency when
+ // describing CPU features. So lots of guessing is needed.
+
+ // 'vfpv4' implies VFPv3|VFP_FMA|FP16
+ if (has_vfpv4)
+ g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv3 |
+ ANDROID_CPU_ARM_FEATURE_VFP_FP16 |
+ ANDROID_CPU_ARM_FEATURE_VFP_FMA;
+
+ // 'vfpv3' or 'vfpv3d16' imply VFPv3. Note that unlike GCC,
+ // a value of 'vfpv3' doesn't necessarily mean that the D32
+ // feature is present, so be conservative. All CPUs in the
+ // field that support D32 also support NEON, so this should
+ // not be a problem in practice.
+ if (has_vfpv3 || has_vfpv3d16)
+ g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv3;
+
+ // 'vfp' is super ambiguous. Depending on the kernel, it can
+ // either mean VFPv2 or VFPv3. Make it depend on ARMv7.
+ if (has_vfp) {
+ if (g_cpuFeatures & ANDROID_CPU_ARM_FEATURE_ARMv7)
+ g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv3;
+ else
+ g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv2;
+ }
+
+ // Neon implies VFPv3|D32, and if vfpv4 is detected, NEON_FMA
+ if (has_neon) {
+ g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv3 |
+ ANDROID_CPU_ARM_FEATURE_NEON |
+ ANDROID_CPU_ARM_FEATURE_VFP_D32;
+ if (has_vfpv4)
+ g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_NEON_FMA;
+ }
+
+ // VFPv3 implies VFPv2 and ARMv7
+ if (g_cpuFeatures & ANDROID_CPU_ARM_FEATURE_VFPv3)
+ g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv2 |
+ ANDROID_CPU_ARM_FEATURE_ARMv7;
+
+ if (has_idiva)
+ g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_IDIV_ARM;
+ if (has_idivt)
+ g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_IDIV_THUMB2;
+
+ if (has_iwmmxt)
+ g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_iWMMXt;
+ }
+
+ /* Extract the cpuid value from various fields */
+ // The CPUID value is broken up in several entries in /proc/cpuinfo.
+ // This table is used to rebuild it from the entries.
+ static const struct CpuIdEntry {
+ const char* field;
+ char format;
+ char bit_lshift;
+ char bit_length;
+ } cpu_id_entries[] = {
+ { "CPU implementer", 'x', 24, 8 },
+ { "CPU variant", 'x', 20, 4 },
+ { "CPU part", 'x', 4, 12 },
+ { "CPU revision", 'd', 0, 4 },
+ };
+ size_t i;
+ D("Parsing /proc/cpuinfo to recover CPUID\n");
+ for (i = 0;
+ i < sizeof(cpu_id_entries)/sizeof(cpu_id_entries[0]);
+ ++i) {
+ const struct CpuIdEntry* entry = &cpu_id_entries[i];
+ char* value = extract_cpuinfo_field(cpuinfo,
+ cpuinfo_len,
+ entry->field);
+ if (value == NULL)
+ continue;
+
+ D("field=%s value='%s'\n", entry->field, value);
+ char* value_end = value + strlen(value);
+ int val = 0;
+ const char* start = value;
+ const char* p;
+ if (value[0] == '0' && (value[1] == 'x' || value[1] == 'X')) {
+ start += 2;
+ p = parse_hexadecimal(start, value_end, &val);
+ } else if (entry->format == 'x')
+ p = parse_hexadecimal(value, value_end, &val);
+ else
+ p = parse_decimal(value, value_end, &val);
+
+ if (p > (const char*)start) {
+ val &= ((1 << entry->bit_length)-1);
+ val <<= entry->bit_lshift;
+ g_cpuIdArm |= (uint32_t) val;
+ }
+
+ free(value);
+ }
+
+ // Handle kernel configuration bugs that prevent the correct
+ // reporting of CPU features.
+ static const struct CpuFix {
+ uint32_t cpuid;
+ uint64_t or_flags;
+ } cpu_fixes[] = {
+ /* The Nexus 4 (Qualcomm Krait) kernel configuration
+ * forgets to report IDIV support. */
+ { 0x510006f2, ANDROID_CPU_ARM_FEATURE_IDIV_ARM |
+ ANDROID_CPU_ARM_FEATURE_IDIV_THUMB2 },
+ { 0x510006f3, ANDROID_CPU_ARM_FEATURE_IDIV_ARM |
+ ANDROID_CPU_ARM_FEATURE_IDIV_THUMB2 },
+ };
+ size_t n;
+ for (n = 0; n < sizeof(cpu_fixes)/sizeof(cpu_fixes[0]); ++n) {
+ const struct CpuFix* entry = &cpu_fixes[n];
+
+ if (g_cpuIdArm == entry->cpuid)
+ g_cpuFeatures |= entry->or_flags;
+ }
+
+ }
+#endif /* __arm__ */
+
+#ifdef __i386__
+ int regs[4];
+
+/* According to http://en.wikipedia.org/wiki/CPUID */
+#define VENDOR_INTEL_b 0x756e6547
+#define VENDOR_INTEL_c 0x6c65746e
+#define VENDOR_INTEL_d 0x49656e69
+
+ x86_cpuid(0, regs);
+ int vendorIsIntel = (regs[1] == VENDOR_INTEL_b &&
+ regs[2] == VENDOR_INTEL_c &&
+ regs[3] == VENDOR_INTEL_d);
+
+ x86_cpuid(1, regs);
+ if ((regs[2] & (1 << 9)) != 0) {
+ g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_SSSE3;
+ }
+ if ((regs[2] & (1 << 23)) != 0) {
+ g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_POPCNT;
+ }
+ if (vendorIsIntel && (regs[2] & (1 << 22)) != 0) {
+ g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_MOVBE;
+ }
+#endif
+
+ free(cpuinfo);
+}
+
+
+AndroidCpuFamily
+android_getCpuFamily(void)
+{
+ pthread_once(&g_once, android_cpuInit);
+ return g_cpuFamily;
+}
+
+
+uint64_t
+android_getCpuFeatures(void)
+{
+ pthread_once(&g_once, android_cpuInit);
+ return g_cpuFeatures;
+}
+
+
+int
+android_getCpuCount(void)
+{
+ pthread_once(&g_once, android_cpuInit);
+ return g_cpuCount;
+}
+
+static void
+android_cpuInitDummy(void)
+{
+ g_inited = 1;
+}
+
+int
+android_setCpu(int cpu_count, uint64_t cpu_features)
+{
+ /* Fail if the library was already initialized. */
+ if (g_inited)
+ return 0;
+
+ android_cpuInitFamily();
+ g_cpuCount = (cpu_count <= 0 ? 1 : cpu_count);
+ g_cpuFeatures = cpu_features;
+ pthread_once(&g_once, android_cpuInitDummy);
+
+ return 1;
+}
+
+#ifdef __arm__
+uint32_t
+android_getCpuIdArm(void)
+{
+ pthread_once(&g_once, android_cpuInit);
+ return g_cpuIdArm;
+}
+
+int
+android_setCpuArm(int cpu_count, uint64_t cpu_features, uint32_t cpu_id)
+{
+ if (!android_setCpu(cpu_count, cpu_features))
+ return 0;
+
+ g_cpuIdArm = cpu_id;
+ return 1;
+}
+#endif /* __arm__ */
+
+/*
+ * Technical note: Making sense of ARM's FPU architecture versions.
+ *
+ * FPA was ARM's first attempt at an FPU architecture. There is no Android
+ * device that actually uses it since this technology was already obsolete
+ * when the project started. If you see references to FPA instructions
+ * somewhere, you can be sure that this doesn't apply to Android at all.
+ *
+ * FPA was followed by "VFP", soon renamed "VFPv1" due to the emergence of
+ * new versions / additions to it. ARM considers this obsolete right now,
+ * and no known Android device implements it either.
+ *
+ * VFPv2 added a few instructions to VFPv1, and is an *optional* extension
+ * supported by some ARMv5TE, ARMv6 and ARMv6T2 CPUs. Note that a device
+ * supporting the 'armeabi' ABI doesn't necessarily support these.
+ *
+ * VFPv3-D16 adds a few instructions on top of VFPv2 and is typically used
+ * on ARMv7-A CPUs which implement a FPU. Note that it is also mandated
+ * by the Android 'armeabi-v7a' ABI. The -D16 suffix in its name means
+ * that it provides 16 double-precision FPU registers (d0-d15) and 32
+ * single-precision ones (s0-s31) which happen to be mapped to the same
+ * register banks.
+ *
+ * VFPv3-D32 is the name of an extension to VFPv3-D16 that provides 16
+ * additional double precision registers (d16-d31). Note that there are
+ * still only 32 single precision registers.
+ *
+ * VFPv3xD is a *subset* of VFPv3-D16 that only provides single-precision
+ * registers. It is only used on ARMv7-M (i.e. on micro-controllers) which
+ * are not supported by Android. Note that it is not compatible with VFPv2.
+ *
+ * NOTE: The term 'VFPv3' usually designate either VFPv3-D16 or VFPv3-D32
+ * depending on context. For example GCC uses it for VFPv3-D32, but
+ * the Linux kernel code uses it for VFPv3-D16 (especially in
+ * /proc/cpuinfo). Always try to use the full designation when
+ * possible.
+ *
+ * NEON, a.k.a. "ARM Advanced SIMD" is an extension that provides
+ * instructions to perform parallel computations on vectors of 8, 16,
+ * 32, 64 and 128 bit quantities. NEON requires VFPv32-D32 since all
+ * NEON registers are also mapped to the same register banks.
+ *
+ * VFPv4-D16, adds a few instructions on top of VFPv3-D16 in order to
+ * perform fused multiply-accumulate on VFP registers, as well as
+ * half-precision (16-bit) conversion operations.
+ *
+ * VFPv4-D32 is VFPv4-D16 with 32, instead of 16, FPU double precision
+ * registers.
+ *
+ * VPFv4-NEON is VFPv4-D32 with NEON instructions. It also adds fused
+ * multiply-accumulate instructions that work on the NEON registers.
+ *
+ * NOTE: Similarly, "VFPv4" might either reference VFPv4-D16 or VFPv4-D32
+ * depending on context.
+ *
+ * The following information was determined by scanning the binutils-2.22
+ * sources:
+ *
+ * Basic VFP instruction subsets:
+ *
+ * #define FPU_VFP_EXT_V1xD 0x08000000 // Base VFP instruction set.
+ * #define FPU_VFP_EXT_V1 0x04000000 // Double-precision insns.
+ * #define FPU_VFP_EXT_V2 0x02000000 // ARM10E VFPr1.
+ * #define FPU_VFP_EXT_V3xD 0x01000000 // VFPv3 single-precision.
+ * #define FPU_VFP_EXT_V3 0x00800000 // VFPv3 double-precision.
+ * #define FPU_NEON_EXT_V1 0x00400000 // Neon (SIMD) insns.
+ * #define FPU_VFP_EXT_D32 0x00200000 // Registers D16-D31.
+ * #define FPU_VFP_EXT_FP16 0x00100000 // Half-precision extensions.
+ * #define FPU_NEON_EXT_FMA 0x00080000 // Neon fused multiply-add
+ * #define FPU_VFP_EXT_FMA 0x00040000 // VFP fused multiply-add
+ *
+ * FPU types (excluding NEON)
+ *
+ * FPU_VFP_V1xD (EXT_V1xD)
+ * |
+ * +--------------------------+
+ * | |
+ * FPU_VFP_V1 (+EXT_V1) FPU_VFP_V3xD (+EXT_V2+EXT_V3xD)
+ * | |
+ * | |
+ * FPU_VFP_V2 (+EXT_V2) FPU_VFP_V4_SP_D16 (+EXT_FP16+EXT_FMA)
+ * |
+ * FPU_VFP_V3D16 (+EXT_Vx3D+EXT_V3)
+ * |
+ * +--------------------------+
+ * | |
+ * FPU_VFP_V3 (+EXT_D32) FPU_VFP_V4D16 (+EXT_FP16+EXT_FMA)
+ * | |
+ * | FPU_VFP_V4 (+EXT_D32)
+ * |
+ * FPU_VFP_HARD (+EXT_FMA+NEON_EXT_FMA)
+ *
+ * VFP architectures:
+ *
+ * ARCH_VFP_V1xD (EXT_V1xD)
+ * |
+ * +------------------+
+ * | |
+ * | ARCH_VFP_V3xD (+EXT_V2+EXT_V3xD)
+ * | |
+ * | ARCH_VFP_V3xD_FP16 (+EXT_FP16)
+ * | |
+ * | ARCH_VFP_V4_SP_D16 (+EXT_FMA)
+ * |
+ * ARCH_VFP_V1 (+EXT_V1)
+ * |
+ * ARCH_VFP_V2 (+EXT_V2)
+ * |
+ * ARCH_VFP_V3D16 (+EXT_V3xD+EXT_V3)
+ * |
+ * +-------------------+
+ * | |
+ * | ARCH_VFP_V3D16_FP16 (+EXT_FP16)
+ * |
+ * +-------------------+
+ * | |
+ * | ARCH_VFP_V4_D16 (+EXT_FP16+EXT_FMA)
+ * | |
+ * | ARCH_VFP_V4 (+EXT_D32)
+ * | |
+ * | ARCH_NEON_VFP_V4 (+EXT_NEON+EXT_NEON_FMA)
+ * |
+ * ARCH_VFP_V3 (+EXT_D32)
+ * |
+ * +-------------------+
+ * | |
+ * | ARCH_VFP_V3_FP16 (+EXT_FP16)
+ * |
+ * ARCH_VFP_V3_PLUS_NEON_V1 (+EXT_NEON)
+ * |
+ * ARCH_NEON_FP16 (+EXT_FP16)
+ *
+ * -fpu=<name> values and their correspondance with FPU architectures above:
+ *
+ * {"vfp", FPU_ARCH_VFP_V2},
+ * {"vfp9", FPU_ARCH_VFP_V2},
+ * {"vfp3", FPU_ARCH_VFP_V3}, // For backwards compatbility.
+ * {"vfp10", FPU_ARCH_VFP_V2},
+ * {"vfp10-r0", FPU_ARCH_VFP_V1},
+ * {"vfpxd", FPU_ARCH_VFP_V1xD},
+ * {"vfpv2", FPU_ARCH_VFP_V2},
+ * {"vfpv3", FPU_ARCH_VFP_V3},
+ * {"vfpv3-fp16", FPU_ARCH_VFP_V3_FP16},
+ * {"vfpv3-d16", FPU_ARCH_VFP_V3D16},
+ * {"vfpv3-d16-fp16", FPU_ARCH_VFP_V3D16_FP16},
+ * {"vfpv3xd", FPU_ARCH_VFP_V3xD},
+ * {"vfpv3xd-fp16", FPU_ARCH_VFP_V3xD_FP16},
+ * {"neon", FPU_ARCH_VFP_V3_PLUS_NEON_V1},
+ * {"neon-fp16", FPU_ARCH_NEON_FP16},
+ * {"vfpv4", FPU_ARCH_VFP_V4},
+ * {"vfpv4-d16", FPU_ARCH_VFP_V4D16},
+ * {"fpv4-sp-d16", FPU_ARCH_VFP_V4_SP_D16},
+ * {"neon-vfpv4", FPU_ARCH_NEON_VFP_V4},
+ *
+ *
+ * Simplified diagram that only includes FPUs supported by Android:
+ * Only ARCH_VFP_V3D16 is actually mandated by the armeabi-v7a ABI,
+ * all others are optional and must be probed at runtime.
+ *
+ * ARCH_VFP_V3D16 (EXT_V1xD+EXT_V1+EXT_V2+EXT_V3xD+EXT_V3)
+ * |
+ * +-------------------+
+ * | |
+ * | ARCH_VFP_V3D16_FP16 (+EXT_FP16)
+ * |
+ * +-------------------+
+ * | |
+ * | ARCH_VFP_V4_D16 (+EXT_FP16+EXT_FMA)
+ * | |
+ * | ARCH_VFP_V4 (+EXT_D32)
+ * | |
+ * | ARCH_NEON_VFP_V4 (+EXT_NEON+EXT_NEON_FMA)
+ * |
+ * ARCH_VFP_V3 (+EXT_D32)
+ * |
+ * +-------------------+
+ * | |
+ * | ARCH_VFP_V3_FP16 (+EXT_FP16)
+ * |
+ * ARCH_VFP_V3_PLUS_NEON_V1 (+EXT_NEON)
+ * |
+ * ARCH_NEON_FP16 (+EXT_FP16)
+ *
+ */
+
+#endif // defined(__le32__)
diff --git a/platform/android/cpu-features.h b/platform/android/cpu-features.h
new file mode 100644
index 0000000000..01b7fe207c
--- /dev/null
+++ b/platform/android/cpu-features.h
@@ -0,0 +1,214 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#ifndef CPU_FEATURES_H
+#define CPU_FEATURES_H
+
+#include <sys/cdefs.h>
+#include <stdint.h>
+
+__BEGIN_DECLS
+
+typedef enum {
+ ANDROID_CPU_FAMILY_UNKNOWN = 0,
+ ANDROID_CPU_FAMILY_ARM,
+ ANDROID_CPU_FAMILY_X86,
+ ANDROID_CPU_FAMILY_MIPS,
+ ANDROID_CPU_FAMILY_ARM64,
+ ANDROID_CPU_FAMILY_X86_64,
+ ANDROID_CPU_FAMILY_MIPS64,
+
+ ANDROID_CPU_FAMILY_MAX /* do not remove */
+
+} AndroidCpuFamily;
+
+/* Return family of the device's CPU */
+extern AndroidCpuFamily android_getCpuFamily(void);
+
+/* The list of feature flags for ARM CPUs that can be recognized by the
+ * library. Value details are:
+ *
+ * VFPv2:
+ * CPU supports the VFPv2 instruction set. Many, but not all, ARMv6 CPUs
+ * support these instructions. VFPv2 is a subset of VFPv3 so this will
+ * be set whenever VFPv3 is set too.
+ *
+ * ARMv7:
+ * CPU supports the ARMv7-A basic instruction set.
+ * This feature is mandated by the 'armeabi-v7a' ABI.
+ *
+ * VFPv3:
+ * CPU supports the VFPv3-D16 instruction set, providing hardware FPU
+ * support for single and double precision floating point registers.
+ * Note that only 16 FPU registers are available by default, unless
+ * the D32 bit is set too. This feature is also mandated by the
+ * 'armeabi-v7a' ABI.
+ *
+ * VFP_D32:
+ * CPU VFP optional extension that provides 32 FPU registers,
+ * instead of 16. Note that ARM mandates this feature is the 'NEON'
+ * feature is implemented by the CPU.
+ *
+ * NEON:
+ * CPU FPU supports "ARM Advanced SIMD" instructions, also known as
+ * NEON. Note that this mandates the VFP_D32 feature as well, per the
+ * ARM Architecture specification.
+ *
+ * VFP_FP16:
+ * Half-width floating precision VFP extension. If set, the CPU
+ * supports instructions to perform floating-point operations on
+ * 16-bit registers. This is part of the VFPv4 specification, but
+ * not mandated by any Android ABI.
+ *
+ * VFP_FMA:
+ * Fused multiply-accumulate VFP instructions extension. Also part of
+ * the VFPv4 specification, but not mandated by any Android ABI.
+ *
+ * NEON_FMA:
+ * Fused multiply-accumulate NEON instructions extension. Optional
+ * extension from the VFPv4 specification, but not mandated by any
+ * Android ABI.
+ *
+ * IDIV_ARM:
+ * Integer division available in ARM mode. Only available
+ * on recent CPUs (e.g. Cortex-A15).
+ *
+ * IDIV_THUMB2:
+ * Integer division available in Thumb-2 mode. Only available
+ * on recent CPUs (e.g. Cortex-A15).
+ *
+ * iWMMXt:
+ * Optional extension that adds MMX registers and operations to an
+ * ARM CPU. This is only available on a few XScale-based CPU designs
+ * sold by Marvell. Pretty rare in practice.
+ *
+ * If you want to tell the compiler to generate code that targets one of
+ * the feature set above, you should probably use one of the following
+ * flags (for more details, see technical note at the end of this file):
+ *
+ * -mfpu=vfp
+ * -mfpu=vfpv2
+ * These are equivalent and tell GCC to use VFPv2 instructions for
+ * floating-point operations. Use this if you want your code to
+ * run on *some* ARMv6 devices, and any ARMv7-A device supported
+ * by Android.
+ *
+ * Generated code requires VFPv2 feature.
+ *
+ * -mfpu=vfpv3-d16
+ * Tell GCC to use VFPv3 instructions (using only 16 FPU registers).
+ * This should be generic code that runs on any CPU that supports the
+ * 'armeabi-v7a' Android ABI. Note that no ARMv6 CPU supports this.
+ *
+ * Generated code requires VFPv3 feature.
+ *
+ * -mfpu=vfpv3
+ * Tell GCC to use VFPv3 instructions with 32 FPU registers.
+ * Generated code requires VFPv3|VFP_D32 features.
+ *
+ * -mfpu=neon
+ * Tell GCC to use VFPv3 instructions with 32 FPU registers, and
+ * also support NEON intrinsics (see <arm_neon.h>).
+ * Generated code requires VFPv3|VFP_D32|NEON features.
+ *
+ * -mfpu=vfpv4-d16
+ * Generated code requires VFPv3|VFP_FP16|VFP_FMA features.
+ *
+ * -mfpu=vfpv4
+ * Generated code requires VFPv3|VFP_FP16|VFP_FMA|VFP_D32 features.
+ *
+ * -mfpu=neon-vfpv4
+ * Generated code requires VFPv3|VFP_FP16|VFP_FMA|VFP_D32|NEON|NEON_FMA
+ * features.
+ *
+ * -mcpu=cortex-a7
+ * -mcpu=cortex-a15
+ * Generated code requires VFPv3|VFP_FP16|VFP_FMA|VFP_D32|
+ * NEON|NEON_FMA|IDIV_ARM|IDIV_THUMB2
+ * This flag implies -mfpu=neon-vfpv4.
+ *
+ * -mcpu=iwmmxt
+ * Allows the use of iWMMXt instrinsics with GCC.
+ */
+enum {
+ ANDROID_CPU_ARM_FEATURE_ARMv7 = (1 << 0),
+ ANDROID_CPU_ARM_FEATURE_VFPv3 = (1 << 1),
+ ANDROID_CPU_ARM_FEATURE_NEON = (1 << 2),
+ ANDROID_CPU_ARM_FEATURE_LDREX_STREX = (1 << 3),
+ ANDROID_CPU_ARM_FEATURE_VFPv2 = (1 << 4),
+ ANDROID_CPU_ARM_FEATURE_VFP_D32 = (1 << 5),
+ ANDROID_CPU_ARM_FEATURE_VFP_FP16 = (1 << 6),
+ ANDROID_CPU_ARM_FEATURE_VFP_FMA = (1 << 7),
+ ANDROID_CPU_ARM_FEATURE_NEON_FMA = (1 << 8),
+ ANDROID_CPU_ARM_FEATURE_IDIV_ARM = (1 << 9),
+ ANDROID_CPU_ARM_FEATURE_IDIV_THUMB2 = (1 << 10),
+ ANDROID_CPU_ARM_FEATURE_iWMMXt = (1 << 11),
+};
+
+enum {
+ ANDROID_CPU_X86_FEATURE_SSSE3 = (1 << 0),
+ ANDROID_CPU_X86_FEATURE_POPCNT = (1 << 1),
+ ANDROID_CPU_X86_FEATURE_MOVBE = (1 << 2),
+};
+
+extern uint64_t android_getCpuFeatures(void);
+#define android_getCpuFeaturesExt android_getCpuFeatures
+
+/* Return the number of CPU cores detected on this device. */
+extern int android_getCpuCount(void);
+
+/* The following is used to force the CPU count and features
+ * mask in sandboxed processes. Under 4.1 and higher, these processes
+ * cannot access /proc, which is the only way to get information from
+ * the kernel about the current hardware (at least on ARM).
+ *
+ * It _must_ be called only once, and before any android_getCpuXXX
+ * function, any other case will fail.
+ *
+ * This function return 1 on success, and 0 on failure.
+ */
+extern int android_setCpu(int cpu_count,
+ uint64_t cpu_features);
+
+#ifdef __arm__
+/* Retrieve the ARM 32-bit CPUID value from the kernel.
+ * Note that this cannot work on sandboxed processes under 4.1 and
+ * higher, unless you called android_setCpuArm() before.
+ */
+extern uint32_t android_getCpuIdArm(void);
+
+/* An ARM-specific variant of android_setCpu() that also allows you
+ * to set the ARM CPUID field.
+ */
+extern int android_setCpuArm(int cpu_count,
+ uint64_t cpu_features,
+ uint32_t cpu_id);
+#endif
+
+__END_DECLS
+
+#endif /* CPU_FEATURES_H */
diff --git a/platform/android/detect.py b/platform/android/detect.py
index c9b21626c3..0c860c23b1 100644
--- a/platform/android/detect.py
+++ b/platform/android/detect.py
@@ -39,6 +39,8 @@ def get_flags():
('nedmalloc', 'no'),
('builtin_zlib', 'no'),
('openssl','builtin'), #use builtin openssl
+ ('theora','no'), #use builtin openssl
+
]
@@ -61,8 +63,11 @@ def configure(env):
env.Tool('gcc')
env['SPAWN'] = methods.win32_spawn
- env.android_source_modules.append("../libs/apk_expansion")
+# env.android_source_modules.append("../libs/apk_expansion")
env.android_source_modules.append("../libs/google_play_services")
+ env.android_source_modules.append("../libs/downloader_library")
+ env.android_source_modules.append("../libs/play_licensing")
+
ndk_platform=""
ndk_platform="android-15"
diff --git a/platform/android/export/export.cpp b/platform/android/export/export.cpp
index f47ff4ed50..aef223470a 100644
--- a/platform/android/export/export.cpp
+++ b/platform/android/export/export.cpp
@@ -378,8 +378,8 @@ bool EditorExportPlatformAndroid::_get(const StringName& p_name,Variant &r_ret)
void EditorExportPlatformAndroid::_get_property_list( List<PropertyInfo> *p_list) const{
- p_list->push_back( PropertyInfo( Variant::STRING, "custom_package/debug", PROPERTY_HINT_FILE,"apk"));
- p_list->push_back( PropertyInfo( Variant::STRING, "custom_package/release", PROPERTY_HINT_FILE,"apk"));
+ p_list->push_back( PropertyInfo( Variant::STRING, "custom_package/debug", PROPERTY_HINT_GLOBAL_FILE,"apk"));
+ p_list->push_back( PropertyInfo( Variant::STRING, "custom_package/release", PROPERTY_HINT_GLOBAL_FILE,"apk"));
p_list->push_back( PropertyInfo( Variant::STRING, "command_line/extra_args"));
p_list->push_back( PropertyInfo( Variant::INT, "version/code", PROPERTY_HINT_RANGE,"1,65535,1"));
p_list->push_back( PropertyInfo( Variant::STRING, "version/name") );
@@ -426,7 +426,7 @@ static String _parse_string(const uint8_t *p_bytes,bool p_utf8) {
}
offset+=2;
- printf("len %i, unicode: %i\n",len,int(p_utf8));
+ //printf("len %i, unicode: %i\n",len,int(p_utf8));
if (p_utf8) {
diff --git a/platform/android/java/res/layout/downloading_expansion.xml b/platform/android/java/res/layout/downloading_expansion.xml
new file mode 100644
index 0000000000..553155dcd3
--- /dev/null
+++ b/platform/android/java/res/layout/downloading_expansion.xml
@@ -0,0 +1,166 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical" >
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="0"
+ android:orientation="vertical" >
+
+ <TextView
+ android:id="@+id/statusText"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="10dp"
+ android:layout_marginLeft="5dp"
+ android:layout_marginTop="10dp"
+ android:textStyle="bold" />
+
+ <LinearLayout
+ android:id="@+id/downloaderDashboard"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/statusText"
+ android:orientation="vertical" >
+
+ <RelativeLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1" >
+
+ <TextView
+ android:id="@+id/progressAsFraction"
+ style="@android:style/TextAppearance.Small"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentLeft="true"
+ android:layout_marginLeft="5dp"
+ android:text="0MB / 0MB" >
+ </TextView>
+
+ <TextView
+ android:id="@+id/progressAsPercentage"
+ style="@android:style/TextAppearance.Small"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignRight="@+id/progressBar"
+ android:text="0%" />
+
+ <ProgressBar
+ android:id="@+id/progressBar"
+ style="?android:attr/progressBarStyleHorizontal"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@+id/progressAsFraction"
+ android:layout_marginBottom="10dp"
+ android:layout_marginLeft="10dp"
+ android:layout_marginRight="10dp"
+ android:layout_marginTop="10dp"
+ android:layout_weight="1" />
+
+ <TextView
+ android:id="@+id/progressAverageSpeed"
+ style="@android:style/TextAppearance.Small"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentLeft="true"
+ android:layout_below="@+id/progressBar"
+ android:layout_marginLeft="5dp" />
+
+ <TextView
+ android:id="@+id/progressTimeRemaining"
+ style="@android:style/TextAppearance.Small"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignRight="@+id/progressBar"
+ android:layout_below="@+id/progressBar" />
+ </RelativeLayout>
+
+ <LinearLayout
+ android:id="@+id/downloaderDashboard"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal" >
+
+ <Button
+ android:id="@+id/pauseButton"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:layout_marginBottom="10dp"
+ android:layout_marginLeft="10dp"
+ android:layout_marginRight="5dp"
+ android:layout_marginTop="10dp"
+ android:layout_weight="0"
+ android:minHeight="40dp"
+ android:minWidth="94dp"
+ android:text="@string/text_button_pause" />
+
+ <Button
+ android:id="@+id/cancelButton"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:layout_marginBottom="10dp"
+ android:layout_marginLeft="5dp"
+ android:layout_marginRight="5dp"
+ android:layout_marginTop="10dp"
+ android:layout_weight="0"
+ android:minHeight="40dp"
+ android:minWidth="94dp"
+ android:text="@string/text_button_cancel"
+ android:visibility="gone" />
+ </LinearLayout>
+ </LinearLayout>
+ </LinearLayout>
+
+ <LinearLayout
+ android:id="@+id/approveCellular"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:orientation="vertical"
+ android:visibility="gone" >
+
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_margin="10dp"
+ android:id="@+id/textPausedParagraph1"
+ android:text="@string/text_paused_cellular" />
+
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_margin="10dp"
+ android:id="@+id/textPausedParagraph2"
+ android:text="@string/text_paused_cellular_2" />
+
+ <LinearLayout
+ android:id="@+id/buttonRow"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal" >
+
+ <Button
+ android:id="@+id/resumeOverCellular"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:layout_margin="10dp"
+ android:text="@string/text_button_resume_cellular" />
+
+ <Button
+ android:id="@+id/wifiSettingsButton"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:layout_margin="10dp"
+ android:text="@string/text_button_wifi_settings" />
+ </LinearLayout>
+ </LinearLayout>
+
+</LinearLayout> \ No newline at end of file
diff --git a/platform/android/java/res/values/strings.xml b/platform/android/java/res/values/strings.xml
index 3a38d40599..49ebcc06f9 100644
--- a/platform/android/java/res/values/strings.xml
+++ b/platform/android/java/res/values/strings.xml
@@ -3,5 +3,15 @@
<string name="godot_project_name_string">godot-project-name</string>
<string name="testuf8">元気です</string>
<string name="testuf2">元気です元気です元気です</string>
-
+ <string name="text_paused_cellular">Would you like to enable downloading over cellular connections? Depending on your data plan, this may cost you money.</string>
+ <string name="text_paused_cellular_2">If you choose not to enable downloading over cellular connections, the download will automatically resume when wi-fi is available.</string>
+ <string name="text_button_resume_cellular">Resume download</string>
+ <string name="text_button_wifi_settings">Wi-Fi settings</string>
+ <string name="text_verifying_download">Verifying Download</string>
+ <string name="text_validation_complete">XAPK File Validation Complete. Select OK to exit.</string>
+ <string name="text_validation_failed">XAPK File Validation Failed.</string>
+ <string name="text_button_pause">Pause Download</string>
+ <string name="text_button_resume">Resume Download</string>
+ <string name="text_button_cancel">Cancel</string>
+ <string name="text_button_cancel_verify">Cancel Verification</string>
</resources>
diff --git a/platform/android/java/src/com/android/godot/Godot.java b/platform/android/java/src/com/android/godot/Godot.java
index 658c272321..f6cd57f4f3 100644
--- a/platform/android/java/src/com/android/godot/Godot.java
+++ b/platform/android/java/src/com/android/godot/Godot.java
@@ -28,16 +28,20 @@
/*************************************************************************/
package com.android.godot;
+import android.R;
import android.app.Activity;
import android.os.Bundle;
import android.view.MotionEvent;
+import android.view.View;
+import android.widget.Button;
+import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.LinearLayout;
+import android.widget.TextView;
import android.view.ViewGroup.LayoutParams;
-
-
import android.app.*;
import android.content.*;
+import android.content.SharedPreferences.Editor;
import android.view.*;
import android.view.inputmethod.InputMethodManager;
import android.os.*;
@@ -48,33 +52,82 @@ import android.text.*;
import android.media.*;
import android.hardware.*;
import android.content.*;
-
+import android.content.pm.PackageManager.NameNotFoundException;
import android.net.Uri;
import android.media.MediaPlayer;
import java.lang.reflect.Method;
import java.util.List;
import java.util.ArrayList;
+
import com.android.godot.payments.PaymentsManager;
+
import java.io.IOException;
+
import android.provider.Settings.Secure;
import android.widget.FrameLayout;
+
import com.android.godot.input.*;
-import java.io.InputStream;
+import java.io.InputStream;
import javax.microedition.khronos.opengles.GL10;
import java.security.MessageDigest;
import java.io.File;
import java.io.FileInputStream;
import java.util.LinkedList;
-public class Godot extends Activity implements SensorEventListener
+import com.google.android.vending.expansion.downloader.Constants;
+import com.google.android.vending.expansion.downloader.DownloadProgressInfo;
+import com.google.android.vending.expansion.downloader.DownloaderClientMarshaller;
+import com.google.android.vending.expansion.downloader.DownloaderServiceMarshaller;
+import com.google.android.vending.expansion.downloader.Helpers;
+import com.google.android.vending.expansion.downloader.IDownloaderClient;
+import com.google.android.vending.expansion.downloader.IDownloaderService;
+import com.google.android.vending.expansion.downloader.IStub;
+
+import android.os.Bundle;
+import android.os.Messenger;
+import android.os.SystemClock;
+
+
+public class Godot extends Activity implements SensorEventListener, IDownloaderClient
{
static final int MAX_SINGLETONS = 64;
-
+ private IStub mDownloaderClientStub;
+ private IDownloaderService mRemoteService;
+ private TextView mStatusText;
+ private TextView mProgressFraction;
+ private TextView mProgressPercent;
+ private TextView mAverageSpeed;
+ private TextView mTimeRemaining;
+ private ProgressBar mPB;
+
+ private View mDashboard;
+ private View mCellMessage;
+
+ private Button mPauseButton;
+ private Button mWiFiSettingsButton;
+
+ private boolean mStatePaused;
+ private int mState;
+
+ private void setState(int newState) {
+ if (mState != newState) {
+ mState = newState;
+ mStatusText.setText(Helpers.getDownloaderStringResourceIDFromState(newState));
+ }
+ }
+
+ private void setButtonPausedState(boolean paused) {
+ mStatePaused = paused;
+ int stringResourceID = paused ? com.godot.game.R.string.text_button_resume :
+ com.godot.game.R.string.text_button_pause;
+ mPauseButton.setText(stringResourceID);
+ }
+
static public class SingletonBase {
-
+
protected void registerClass(String p_name, String[] p_methods) {
GodotLib.singleton(p_name,this);
@@ -83,20 +136,20 @@ public class Godot extends Activity implements SensorEventListener
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
boolean found=false;
- System.out.printf("METHOD: %s\n",method.getName());
+ Log.d("XXX","METHOD: %s\n" + method.getName());
for (String s : p_methods) {
- System.out.printf("METHOD CMP WITH: %s\n",s);
+ Log.d("XXX", "METHOD CMP WITH: %s\n" + s);
if (s.equals(method.getName())) {
found=true;
- System.out.printf("METHOD CMP VALID");
+ Log.d("XXX","METHOD CMP VALID");
break;
}
}
if (!found)
continue;
- System.out.printf("METHOD FOUND: %s\n",method.getName());
+ Log.d("XXX","METHOD FOUND: %s\n" + method.getName());
List<String> ptr = new ArrayList<String>();
@@ -230,7 +283,7 @@ public class Godot extends Activity implements SensorEventListener
byte[] len = new byte[4];
int r = is.read(len);
if (r<4) {
- System.out.printf("**ERROR** Wrong cmdline length.\n");
+ Log.d("XXX","**ERROR** Wrong cmdline length.\n");
Log.d("GODOT", "**ERROR** Wrong cmdline length.\n");
return new String[0];
}
@@ -258,7 +311,6 @@ public class Godot extends Activity implements SensorEventListener
return cmdline;
} catch (Exception e) {
e.printStackTrace();
- System.out.printf("**ERROR** No commandline.\n");
Log.d("GODOT", "**ERROR** Exception " + e.getClass().getName() + ":" + e.getMessage());
return new String[0];
}
@@ -277,12 +329,14 @@ public class Godot extends Activity implements SensorEventListener
String[] new_cmdline;
int cll=0;
if (command_line!=null) {
+ Log.d("GODOT", "initializeGodot: command_line: is not null" );
new_cmdline = new String[ command_line.length + 2 ];
cll=command_line.length;
for(int i=0;i<command_line.length;i++) {
new_cmdline[i]=command_line[i];
}
} else {
+ Log.d("GODOT", "initializeGodot: command_line: is null" );
new_cmdline = new String[ 2 ];
}
@@ -294,6 +348,13 @@ public class Godot extends Activity implements SensorEventListener
io = new GodotIO(this);
io.unique_id = Secure.getString(getContentResolver(), Secure.ANDROID_ID);
GodotLib.io=io;
+ Log.d("GODOT", "command_line is null? " + ((command_line == null)?"yes":"no"));
+ /*if(command_line != null){
+ Log.d("GODOT", "Command Line:");
+ for(int w=0;w <command_line.length;w++){
+ Log.d("GODOT"," " + command_line[w]);
+ }
+ }*/
GodotLib.initialize(this,io.needsReloadHooks(),command_line);
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
@@ -306,10 +367,16 @@ public class Godot extends Activity implements SensorEventListener
}
+ @Override
+ public void onServiceConnected(Messenger m) {
+ mRemoteService = DownloaderServiceMarshaller.CreateProxy(m);
+ mRemoteService.onClientUpdated(mDownloaderClientStub.getMessenger());
+ }
- @Override protected void onCreate(Bundle icicle) {
+ @Override
+ protected void onCreate(Bundle icicle) {
- System.out.printf("** GODOT ACTIVITY CREATED HERE ***\n");
+ Log.d("GODOT", "** GODOT ACTIVITY CREATED HERE ***\n");
super.onCreate(icicle);
_self = this;
@@ -319,7 +386,8 @@ public class Godot extends Activity implements SensorEventListener
//check for apk expansion API
- if (!true) {
+ if (true) {
+ boolean md5mismatch = false;
command_line = getCommandLine();
boolean use_apk_expansion=false;
String main_pack_md5=null;
@@ -338,17 +406,23 @@ public class Godot extends Activity implements SensorEventListener
i++;
} else if (has_extra && command_line[i].equals("-apk_expansion_key")) {
main_pack_key=command_line[i+1];
+ SharedPreferences prefs = getSharedPreferences("app_data_keys", MODE_PRIVATE);
+ Editor editor = prefs.edit();
+ editor.putString("store_public_key", main_pack_key);
+
+ editor.commit();
i++;
} else if (command_line[i].trim().length()!=0){
new_args.add(command_line[i]);
}
}
- if (new_args.isEmpty())
+ if (new_args.isEmpty()){
command_line=null;
- else
- command_line = new_args.toArray(new String[new_args.size()]);
+ }else{
+ command_line = new_args.toArray(new String[new_args.size()]);
+ }
if (use_apk_expansion && main_pack_md5!=null && main_pack_key!=null) {
//check that environment is ok!
if (!Environment.getExternalStorageState().equals( Environment.MEDIA_MOUNTED )) {
@@ -374,49 +448,62 @@ public class Godot extends Activity implements SensorEventListener
pack_valid=false;
Log.d("GODOT","**PACK** - File does not exist");
- } else {
- try {
-
- InputStream fis = new FileInputStream(expansion_pack_path);
-
- // Create MD5 Hash
- byte[] buffer = new byte[16384];
-
- MessageDigest complete = MessageDigest.getInstance("MD5");
- int numRead;
- do {
- numRead = fis.read(buffer);
- if (numRead > 0) {
- complete.update(buffer, 0, numRead);
- }
- } while (numRead != -1);
-
-
- fis.close();
- byte[] messageDigest = complete.digest();
-
- // Create Hex String
- StringBuffer hexString = new StringBuffer();
- for (int i=0; i<messageDigest.length; i++)
- hexString.append(Integer.toHexString(0xFF & messageDigest[i]));
- String md5str = hexString.toString();
-
- Log.d("GODOT","**PACK** - My MD5: "+hexString+" - APK md5: "+main_pack_md5);
- if (!hexString.equals(main_pack_md5)) {
- pack_valid=false;
- }
- } catch (Exception e) {
- e.printStackTrace();
- Log.d("GODOT","**PACK FAIL**");
- pack_valid=false;
+ } else if( obbIsCorrupted(expansion_pack_path, main_pack_md5)){
+ Log.d("GODOT", "**PACK** - Expansion pack (obb) is corrupted");
+ pack_valid = false;
+ try{
+ f.delete();
+ }catch(Exception e){
+ Log.d("GODOT", "**PACK** - Error deleting corrupted expansion pack (obb)");
}
-
-
}
if (!pack_valid) {
-
-
+ Log.d("GODOT", "Pack Invalid, try re-downloading.");
+
+ Intent notifierIntent = new Intent(this, this.getClass());
+ notifierIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
+ Intent.FLAG_ACTIVITY_CLEAR_TOP);
+
+ PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
+ notifierIntent, PendingIntent.FLAG_UPDATE_CURRENT);
+
+ int startResult;
+ try {
+ Log.d("GODOT", "INITIALIZING DOWNLOAD");
+ startResult = DownloaderClientMarshaller.startDownloadServiceIfRequired(
+ getApplicationContext(),
+ pendingIntent,
+ GodotDownloaderService.class);
+ Log.d("GODOT", "DOWNLOAD SERVICE FINISHED:" + startResult);
+
+ if (startResult != DownloaderClientMarshaller.NO_DOWNLOAD_REQUIRED) {
+ Log.d("GODOT", "DOWNLOAD REQUIRED");
+ // This is where you do set up to display the download
+ // progress (next step)
+ mDownloaderClientStub = DownloaderClientMarshaller.CreateStub(this,
+ GodotDownloaderService.class);
+
+ setContentView(com.godot.game.R.layout.downloading_expansion);
+ mPB = (ProgressBar) findViewById(com.godot.game.R.id.progressBar);
+ mStatusText = (TextView) findViewById(com.godot.game.R.id.statusText);
+ mProgressFraction = (TextView) findViewById(com.godot.game.R.id.progressAsFraction);
+ mProgressPercent = (TextView) findViewById(com.godot.game.R.id.progressAsPercentage);
+ mAverageSpeed = (TextView) findViewById(com.godot.game.R.id.progressAverageSpeed);
+ mTimeRemaining = (TextView) findViewById(com.godot.game.R.id.progressTimeRemaining);
+ mDashboard = findViewById(com.godot.game.R.id.downloaderDashboard);
+ mCellMessage = findViewById(com.godot.game.R.id.approveCellular);
+ mPauseButton = (Button) findViewById(com.godot.game.R.id.pauseButton);
+ mWiFiSettingsButton = (Button) findViewById(com.godot.game.R.id.wifiSettingsButton);
+
+ return;
+ } else{
+ Log.d("GODOT", "NO DOWNLOAD REQUIRED");
+ }
+ } catch (NameNotFoundException e) {
+ // TODO Auto-generated catch block
+ Log.d("GODOT", "Error downloading expansion package:" + e.getMessage());
+ }
}
@@ -431,6 +518,7 @@ public class Godot extends Activity implements SensorEventListener
}
+
@Override protected void onDestroy(){
if(mPaymentsManager != null ) mPaymentsManager.destroy();
@@ -442,8 +530,12 @@ public class Godot extends Activity implements SensorEventListener
@Override protected void onPause() {
super.onPause();
- if (!godot_initialized)
+ if (!godot_initialized){
+ if (null != mDownloaderClientStub) {
+ mDownloaderClientStub.disconnect(this);
+ }
return;
+ }
mView.onPause();
mSensorManager.unregisterListener(this);
GodotLib.focusout();
@@ -455,8 +547,12 @@ public class Godot extends Activity implements SensorEventListener
@Override protected void onResume() {
super.onResume();
- if (!godot_initialized)
+ if (!godot_initialized){
+ if (null != mDownloaderClientStub) {
+ mDownloaderClientStub.connect(this);
+ }
return;
+ }
mView.onResume();
mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
@@ -466,6 +562,8 @@ public class Godot extends Activity implements SensorEventListener
singletons[i].onMainResume();
}
+
+
}
@@ -508,6 +606,54 @@ public class Godot extends Activity implements SensorEventListener
}
+
+ private boolean obbIsCorrupted(String f, String main_pack_md5){
+
+ try {
+
+ InputStream fis = new FileInputStream(f);
+
+ // Create MD5 Hash
+ byte[] buffer = new byte[16384];
+
+ MessageDigest complete = MessageDigest.getInstance("MD5");
+ int numRead;
+ do {
+ numRead = fis.read(buffer);
+ if (numRead > 0) {
+ complete.update(buffer, 0, numRead);
+ }
+ } while (numRead != -1);
+
+
+ fis.close();
+ byte[] messageDigest = complete.digest();
+
+ // Create Hex String
+ StringBuffer hexString = new StringBuffer();
+ for (int i=0; i<messageDigest.length; i++) {
+ String s = Integer.toHexString(0xFF & messageDigest[i]);
+
+ if (s.length()==1) {
+ s="0"+s;
+ }
+ hexString.append(s);
+ }
+ String md5str = hexString.toString();
+
+ //Log.d("GODOT","**PACK** - My MD5: "+hexString+" - APK md5: "+main_pack_md5);
+ if (!md5str.equals(main_pack_md5)) {
+ Log.d("GODOT","**PACK MD5 MISMATCH???** - MD5 Found: "+md5str+" "+Integer.toString(md5str.length())+" - MD5 Expected: "+main_pack_md5+" "+Integer.toString(main_pack_md5.length()));
+ return true;
+ }
+ return false;
+ } catch (Exception e) {
+ e.printStackTrace();
+ Log.d("GODOT","**PACK FAIL**");
+ return true;
+ }
+ }
+
//@Override public boolean dispatchTouchEvent (MotionEvent event) {
public boolean gotTouchEvent(MotionEvent event) {
@@ -602,5 +748,115 @@ public class Godot extends Activity implements SensorEventListener
// Audio
-
+ /**
+ * The download state should trigger changes in the UI --- it may be useful
+ * to show the state as being indeterminate at times. This sample can be
+ * considered a guideline.
+ */
+ @Override
+ public void onDownloadStateChanged(int newState) {
+ Log.d("GODOT", "onDownloadStateChanged:" + newState);
+ setState(newState);
+ boolean showDashboard = true;
+ boolean showCellMessage = false;
+ boolean paused;
+ boolean indeterminate;
+ switch (newState) {
+ case IDownloaderClient.STATE_IDLE:
+ Log.d("GODOT", "STATE IDLE");
+ // STATE_IDLE means the service is listening, so it's
+ // safe to start making calls via mRemoteService.
+ paused = false;
+ indeterminate = true;
+ break;
+ case IDownloaderClient.STATE_CONNECTING:
+ case IDownloaderClient.STATE_FETCHING_URL:
+ Log.d("GODOT", "STATE CONNECTION / FETCHING URL");
+ showDashboard = true;
+ paused = false;
+ indeterminate = true;
+ break;
+ case IDownloaderClient.STATE_DOWNLOADING:
+ Log.d("GODOT", "STATE DOWNLOADING");
+ paused = false;
+ showDashboard = true;
+ indeterminate = false;
+ break;
+
+ case IDownloaderClient.STATE_FAILED_CANCELED:
+ case IDownloaderClient.STATE_FAILED:
+ case IDownloaderClient.STATE_FAILED_FETCHING_URL:
+ case IDownloaderClient.STATE_FAILED_UNLICENSED:
+ Log.d("GODOT", "MANY TYPES OF FAILING");
+ paused = true;
+ showDashboard = false;
+ indeterminate = false;
+ break;
+ case IDownloaderClient.STATE_PAUSED_NEED_CELLULAR_PERMISSION:
+ case IDownloaderClient.STATE_PAUSED_WIFI_DISABLED_NEED_CELLULAR_PERMISSION:
+ Log.d("GODOT", "PAUSED FOR SOME STUPID REASON");
+ showDashboard = false;
+ paused = true;
+ indeterminate = false;
+ showCellMessage = true;
+ break;
+
+ case IDownloaderClient.STATE_PAUSED_BY_REQUEST:
+ Log.d("GODOT", "PAUSED BY STUPID USER");
+ paused = true;
+ indeterminate = false;
+ break;
+ case IDownloaderClient.STATE_PAUSED_ROAMING:
+ case IDownloaderClient.STATE_PAUSED_SDCARD_UNAVAILABLE:
+ Log.d("GODOT", "PAUSED BY ROAMING WTF!?");
+ paused = true;
+ indeterminate = false;
+ break;
+ case IDownloaderClient.STATE_COMPLETED:
+ Log.d("GODOT", "COMPLETED");
+ showDashboard = false;
+ paused = false;
+ indeterminate = false;
+// validateXAPKZipFiles();
+ initializeGodot();
+ return;
+ default:
+ Log.d("GODOT", "DEFAULT ????");
+ paused = true;
+ indeterminate = true;
+ showDashboard = true;
+ }
+ int newDashboardVisibility = showDashboard ? View.VISIBLE : View.GONE;
+ if (mDashboard.getVisibility() != newDashboardVisibility) {
+ mDashboard.setVisibility(newDashboardVisibility);
+ }
+ int cellMessageVisibility = showCellMessage ? View.VISIBLE : View.GONE;
+ if (mCellMessage.getVisibility() != cellMessageVisibility) {
+ mCellMessage.setVisibility(cellMessageVisibility);
+ }
+
+ mPB.setIndeterminate(indeterminate);
+ setButtonPausedState(paused);
+ }
+
+
+ @Override
+ public void onDownloadProgress(DownloadProgressInfo progress) {
+ mAverageSpeed.setText(getString(com.godot.game.R.string.kilobytes_per_second,
+ Helpers.getSpeedString(progress.mCurrentSpeed)));
+ mTimeRemaining.setText(getString(com.godot.game.R.string.time_remaining,
+ Helpers.getTimeRemaining(progress.mTimeRemaining)));
+
+ progress.mOverallTotal = progress.mOverallTotal;
+ mPB.setMax((int) (progress.mOverallTotal >> 8));
+ mPB.setProgress((int) (progress.mOverallProgress >> 8));
+ mProgressPercent.setText(Long.toString(progress.mOverallProgress
+ * 100 /
+ progress.mOverallTotal) + "%");
+ mProgressFraction.setText(Helpers.getDownloadProgressString
+ (progress.mOverallProgress,
+ progress.mOverallTotal));
+
+ }
+
}
diff --git a/platform/android/java/src/com/android/godot/GodotDownloaderAlarmReceiver.java b/platform/android/java/src/com/android/godot/GodotDownloaderAlarmReceiver.java
index d945a8b192..e82c3eb0fe 100644
--- a/platform/android/java/src/com/android/godot/GodotDownloaderAlarmReceiver.java
+++ b/platform/android/java/src/com/android/godot/GodotDownloaderAlarmReceiver.java
@@ -6,6 +6,7 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager.NameNotFoundException;
+import android.util.Log;
/**
* You should start your derived downloader class when this receiver gets the message
@@ -18,10 +19,12 @@ public class GodotDownloaderAlarmReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
+ Log.d("GODOT", "Alarma recivida");
try {
DownloaderClientMarshaller.startDownloadServiceIfRequired(context, intent, GodotDownloaderService.class);
} catch (NameNotFoundException e) {
e.printStackTrace();
+ Log.d("GODOT", "Exception: " + e.getClass().getName() + ":" + e.getMessage());
}
}
}
diff --git a/platform/android/java/src/com/android/godot/GodotDownloaderService.java b/platform/android/java/src/com/android/godot/GodotDownloaderService.java
index e0fe95ad96..2657edc1d2 100644
--- a/platform/android/java/src/com/android/godot/GodotDownloaderService.java
+++ b/platform/android/java/src/com/android/godot/GodotDownloaderService.java
@@ -1,5 +1,9 @@
package com.android.godot;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.util.Log;
+
import com.google.android.vending.expansion.downloader.impl.DownloaderService;
/**
@@ -21,7 +25,11 @@ public class GodotDownloaderService extends DownloaderService {
*/
@Override
public String getPublicKey() {
- return BASE64_PUBLIC_KEY;
+ SharedPreferences prefs = getApplicationContext().getSharedPreferences("app_data_keys", Context.MODE_PRIVATE);
+ Log.d("GODOT", "getting public key:" + prefs.getString("store_public_key", null));
+ return prefs.getString("store_public_key", null);
+
+// return BASE64_PUBLIC_KEY;
}
/**
@@ -41,7 +49,8 @@ public class GodotDownloaderService extends DownloaderService {
*/
@Override
public String getAlarmReceiverClassName() {
- return GodotDownloaderAlarmReceiver.class.getName();
+ Log.d("GODOT", "getAlarmReceiverClassName()");
+ return GodotDownloaderAlarmReceiver.class.getName();
}
}
diff --git a/platform/android/java/src/com/android/godot/GodotPaymentV3.java b/platform/android/java/src/com/android/godot/GodotPaymentV3.java
index dba4a9a774..0fd102ac55 100644
--- a/platform/android/java/src/com/android/godot/GodotPaymentV3.java
+++ b/platform/android/java/src/com/android/godot/GodotPaymentV3.java
@@ -1,8 +1,6 @@
package com.android.godot;
-
-import org.json.JSONObject;
-
+import com.android.godot.Dictionary;
import android.app.Activity;
import android.util.Log;
@@ -44,10 +42,20 @@ public class GodotPaymentV3 extends Godot.SingletonBase {
public GodotPaymentV3(Activity p_activity) {
- registerClass("GodotPayments", new String[] {"purchase", "setPurchaseCallbackId", "setPurchaseValidationUrlPrefix", "setTransactionId", "getSignature"});
+ registerClass("GodotPayments", new String[] {"purchase", "setPurchaseCallbackId", "setPurchaseValidationUrlPrefix", "setTransactionId", "getSignature", "consumeUnconsumedPurchases"});
activity=(Godot) p_activity;
}
+ public void consumeUnconsumedPurchases(){
+ activity.getPaymentsManager().setBaseSingleton(this);
+ activity.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ activity.getPaymentsManager().consumeUnconsumedPurchases();
+ }
+ });
+
+ }
private String signature;
public String getSignature(){
@@ -56,9 +64,19 @@ public class GodotPaymentV3 extends Godot.SingletonBase {
public void callbackSuccess(String ticket, String signature){
- Log.d(this.getClass().getName(), "PRE-Send callback to purchase success");
- GodotLib.calldeferred(purchaseCallbackId, "purchase_success", new Object[]{ticket, signature});
- Log.d(this.getClass().getName(), "POST-Send callback to purchase success");
+// Log.d(this.getClass().getName(), "PRE-Send callback to purchase success");
+ GodotLib.callobject(purchaseCallbackId, "purchase_success", new Object[]{ticket, signature});
+// Log.d(this.getClass().getName(), "POST-Send callback to purchase success");
+}
+
+ public void callbackSuccessProductMassConsumed(String ticket, String signature, String sku){
+// Log.d(this.getClass().getName(), "PRE-Send callback to consume success");
+ GodotLib.calldeferred(purchaseCallbackId, "consume_success", new Object[]{ticket, signature, sku});
+// Log.d(this.getClass().getName(), "POST-Send callback to consume success");
+ }
+
+ public void callbackSuccessNoUnconsumedPurchases(){
+ GodotLib.calldeferred(purchaseCallbackId, "no_validation_required", new Object[]{});
}
public void callbackFail(){
diff --git a/platform/android/java/src/com/android/godot/payments/GenericConsumeTask.java b/platform/android/java/src/com/android/godot/payments/GenericConsumeTask.java
new file mode 100644
index 0000000000..d68f029246
--- /dev/null
+++ b/platform/android/java/src/com/android/godot/payments/GenericConsumeTask.java
@@ -0,0 +1,53 @@
+package com.android.godot.payments;
+
+import com.android.vending.billing.IInAppBillingService;
+
+import android.content.Context;
+import android.os.AsyncTask;
+import android.os.RemoteException;
+import android.util.Log;
+
+abstract public class GenericConsumeTask extends AsyncTask<String, String, String>{
+
+ private Context context;
+ private IInAppBillingService mService;
+
+
+
+
+ public GenericConsumeTask(Context context, IInAppBillingService mService, String sku, String receipt, String signature, String token){
+ this.context = context;
+ this.mService = mService;
+ this.sku = sku;
+ this.receipt = receipt;
+ this.signature = signature;
+ this.token = token;
+ }
+
+ private String sku;
+ private String receipt;
+ private String signature;
+ private String token;
+
+ @Override
+ protected String doInBackground(String... params) {
+ try {
+// Log.d("godot", "Requesting to consume an item with token ." + token);
+ int response = mService.consumePurchase(3, context.getPackageName(), token);
+// Log.d("godot", "consumePurchase response: " + response);
+ if(response == 0 || response == 8){
+ return null;
+ }
+ } catch (Exception e) {
+ Log.d("godot", "Error " + e.getClass().getName() + ":" + e.getMessage());
+ }
+ return null;
+ }
+
+ protected void onPostExecute(String sarasa){
+ onSuccess(sku, receipt, signature, token);
+ }
+
+ abstract public void onSuccess(String sku, String receipt, String signature, String token);
+
+}
diff --git a/platform/android/java/src/com/android/godot/payments/HandlePurchaseTask.java b/platform/android/java/src/com/android/godot/payments/HandlePurchaseTask.java
index a810ac40ae..4c31704cc8 100644
--- a/platform/android/java/src/com/android/godot/payments/HandlePurchaseTask.java
+++ b/platform/android/java/src/com/android/godot/payments/HandlePurchaseTask.java
@@ -28,19 +28,19 @@ abstract public class HandlePurchaseTask {
public void handlePurchaseRequest(int resultCode, Intent data){
- Log.d("XXX", "Handling purchase response");
+// Log.d("XXX", "Handling purchase response");
// int responseCode = data.getIntExtra("RESPONSE_CODE", 0);
PaymentsCache pc = new PaymentsCache(context);
String purchaseData = data.getStringExtra("INAPP_PURCHASE_DATA");
- Log.d("XXX", "Purchase data:" + purchaseData);
+// Log.d("XXX", "Purchase data:" + purchaseData);
String dataSignature = data.getStringExtra("INAPP_DATA_SIGNATURE");
- Log.d("XXX", "Purchase signature:" + dataSignature);
+ //Log.d("XXX", "Purchase signature:" + dataSignature);
if (resultCode == Activity.RESULT_OK) {
try {
- Log.d("SARLANGA", purchaseData);
+// Log.d("SARLANGA", purchaseData);
JSONObject jo = new JSONObject(purchaseData);
@@ -58,13 +58,13 @@ abstract public class HandlePurchaseTask {
error("Untrusted callback");
return;
}
- Log.d("XXX", "Este es el product ID:" + productId);
+// Log.d("XXX", "Este es el product ID:" + productId);
pc.setConsumableValue("ticket_signautre", productId, dataSignature);
pc.setConsumableValue("ticket", productId, purchaseData);
pc.setConsumableFlag("block", productId, true);
pc.setConsumableValue("token", productId, purchaseToken);
- success(productId, dataSignature);
+ success(productId, dataSignature, purchaseData);
return;
} catch (JSONException e) {
error(e.getMessage());
@@ -74,7 +74,7 @@ abstract public class HandlePurchaseTask {
}
}
- abstract protected void success(String ticket, String signature);
+ abstract protected void success(String sku, String signature, String ticket);
abstract protected void error(String message);
abstract protected void canceled();
diff --git a/platform/android/java/src/com/android/godot/payments/PaymentsCache.java b/platform/android/java/src/com/android/godot/payments/PaymentsCache.java
index 7337acc0b8..1de772bf28 100644
--- a/platform/android/java/src/com/android/godot/payments/PaymentsCache.java
+++ b/platform/android/java/src/com/android/godot/payments/PaymentsCache.java
@@ -31,14 +31,14 @@ public class PaymentsCache {
SharedPreferences sharedPref = context.getSharedPreferences("consumables_" + set, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPref.edit();
editor.putString(sku, value);
- Log.d("XXX", "Setting asset: consumables_" + set + ":" + sku);
+// Log.d("XXX", "Setting asset: consumables_" + set + ":" + sku);
editor.commit();
}
public String getConsumableValue(String set, String sku){
SharedPreferences sharedPref = context.getSharedPreferences(
"consumables_" + set, Context.MODE_PRIVATE);
- Log.d("XXX", "Getting asset: consumables_" + set + ":" + sku);
+// Log.d("XXX", "Getting asset: consumables_" + set + ":" + sku);
return sharedPref.getString(sku, null);
}
diff --git a/platform/android/java/src/com/android/godot/payments/PaymentsManager.java b/platform/android/java/src/com/android/godot/payments/PaymentsManager.java
index d85a8ea8ea..fd1a62738a 100644
--- a/platform/android/java/src/com/android/godot/payments/PaymentsManager.java
+++ b/platform/android/java/src/com/android/godot/payments/PaymentsManager.java
@@ -1,5 +1,9 @@
package com.android.godot.payments;
+import java.util.ArrayList;
+import java.util.List;
+
+import android.os.RemoteException;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
@@ -7,7 +11,13 @@ import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.util.Log;
+import android.os.Bundle;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.json.JSONStringer;
+import com.android.godot.Dictionary;
import com.android.godot.Godot;
import com.android.godot.GodotPaymentV3;
import com.android.vending.billing.IInAppBillingService;
@@ -23,7 +33,6 @@ public class PaymentsManager {
private Activity activity;
IInAppBillingService mService;
-
public void setActivity(Activity activity){
this.activity = activity;
}
@@ -81,18 +90,39 @@ public class PaymentsManager {
}
+ public void consumeUnconsumedPurchases(){
+ new ReleaseAllConsumablesTask(mService, activity) {
+
+ @Override
+ protected void success(String sku, String receipt, String signature, String token) {
+ godotPaymentV3.callbackSuccessProductMassConsumed(receipt, signature, sku);
+ }
+
+ @Override
+ protected void error(String message) {
+ godotPaymentV3.callbackFail();
+
+ }
+
+ @Override
+ protected void notRequired() {
+ godotPaymentV3.callbackSuccessNoUnconsumedPurchases();
+
+ }
+ }.consumeItAll();
+ }
+
public void processPurchaseResponse(int resultCode, Intent data) {
new HandlePurchaseTask(activity){
@Override
- protected void success(final String sku, final String signature) {
+ protected void success(final String sku, final String signature, final String ticket) {
+ godotPaymentV3.callbackSuccess(ticket, signature);
new ConsumeTask(mService, activity) {
@Override
protected void success(String ticket) {
// godotPaymentV3.callbackSuccess("");
- Log.d("XXX", "calling success:" + signature);
- godotPaymentV3.callbackSuccess(ticket, signature);
}
@Override
@@ -103,7 +133,7 @@ public class PaymentsManager {
}.consume(sku);
-
+// godotPaymentV3.callbackSuccess(new PaymentsCache(activity).getConsumableValue("ticket", sku),signature);
// godotPaymentV3.callbackSuccess(ticket);
//validatePurchase(purchaseToken, sku);
}
@@ -166,5 +196,6 @@ public class PaymentsManager {
this.godotPaymentV3 = godotPaymentV3;
}
+
}
diff --git a/platform/android/java/src/com/android/godot/payments/PurchaseTask.java b/platform/android/java/src/com/android/godot/payments/PurchaseTask.java
index 0856b4e900..75662a442e 100644
--- a/platform/android/java/src/com/android/godot/payments/PurchaseTask.java
+++ b/platform/android/java/src/com/android/godot/payments/PurchaseTask.java
@@ -64,31 +64,7 @@ abstract public class PurchaseTask {
canceled();
return ;
}
- if(responseCode == 7){
- new ConsumeTask(mService, context) {
-
- @Override
- protected void success(String ticket) {
-// Log.d("XXX", "Product was erroniously purchased!");
- if(isLooping){
-// Log.d("XXX", "It is looping");
- error("Error while purchasing product");
- return;
- }
- isLooping=true;
- PurchaseTask.this.purchase(sku, transactionId);
-
- }
-
- @Override
- protected void error(String message) {
- PurchaseTask.this.error(message);
-
- }
- }.consume(sku);
- return;
- }
-
+
PendingIntent pendingIntent = buyIntentBundle.getParcelable("BUY_INTENT");
pc.setConsumableValue("validation_hash", sku, hash);
diff --git a/platform/android/java/src/com/android/godot/payments/ReleaseAllConsumablesTask.java b/platform/android/java/src/com/android/godot/payments/ReleaseAllConsumablesTask.java
new file mode 100644
index 0000000000..c1a9c5d421
--- /dev/null
+++ b/platform/android/java/src/com/android/godot/payments/ReleaseAllConsumablesTask.java
@@ -0,0 +1,87 @@
+package com.android.godot.payments;
+
+import java.util.ArrayList;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import com.android.godot.Dictionary;
+import com.android.godot.Godot;
+import com.android.vending.billing.IInAppBillingService;
+
+import android.content.Context;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.os.RemoteException;
+import android.util.Log;
+
+abstract public class ReleaseAllConsumablesTask {
+
+ private Context context;
+ private IInAppBillingService mService;
+
+ public ReleaseAllConsumablesTask(IInAppBillingService mService, Context context ){
+ this.context = context;
+ this.mService = mService;
+ }
+
+
+ public void consumeItAll(){
+ try{
+// Log.d("godot", "consumeItall for " + context.getPackageName());
+ Bundle bundle = mService.getPurchases(3, context.getPackageName(), "inapp",null);
+
+ for (String key : bundle.keySet()) {
+ Object value = bundle.get(key);
+// Log.d("godot", String.format("%s %s (%s)", key,
+// value.toString(), value.getClass().getName()));
+ }
+
+
+ if (bundle.getInt("RESPONSE_CODE") == 0){
+
+ final ArrayList<String> myPurchases = bundle.getStringArrayList("INAPP_PURCHASE_DATA_LIST");
+ final ArrayList<String> mySignatures = bundle.getStringArrayList("INAPP_DATA_SIGNATURE_LIST");
+
+
+ if (myPurchases == null || myPurchases.size() == 0){
+// Log.d("godot", "No purchases!");
+ notRequired();
+ return;
+ }
+
+
+// Log.d("godot", "# products to be consumed:" + myPurchases.size());
+ for (int i=0;i<myPurchases.size();i++)
+ {
+
+ try{
+ String receipt = myPurchases.get(i);
+ JSONObject inappPurchaseData = new JSONObject(receipt);
+ String sku = inappPurchaseData.getString("productId");
+ String token = inappPurchaseData.getString("purchaseToken");
+ String signature = mySignatures.get(i);
+// Log.d("godot", "A punto de consumir un item con token:" + token + "\n" + receipt);
+ new GenericConsumeTask(context, mService, sku, receipt,signature, token) {
+
+ @Override
+ public void onSuccess(String sku, String receipt, String signature, String token) {
+ ReleaseAllConsumablesTask.this.success(sku, receipt, signature, token);
+ }
+ }.execute();
+
+ } catch (JSONException e) {
+ }
+ }
+
+ }
+ }catch(Exception e){
+ Log.d("godot", "Error releasing products:" + e.getClass().getName() + ":" + e.getMessage());
+ }
+ }
+
+ abstract protected void success(String sku, String receipt, String signature, String token);
+ abstract protected void error(String message);
+ abstract protected void notRequired();
+
+}
diff --git a/platform/android/java_class_wrapper.cpp b/platform/android/java_class_wrapper.cpp
new file mode 100644
index 0000000000..d4cf848484
--- /dev/null
+++ b/platform/android/java_class_wrapper.cpp
@@ -0,0 +1,1332 @@
+#include "java_class_wrapper.h"
+#include "thread_jandroid.h"
+
+
+bool JavaClass::_call_method(JavaObject* p_instance,const StringName& p_method,const Variant** p_args,int p_argcount,Variant::CallError &r_error,Variant& ret) {
+
+ Map<StringName,List<MethodInfo> >::Element *M=methods.find(p_method);
+ if (!M)
+ return false;
+
+ JNIEnv *env = ThreadAndroid::get_env();
+
+ MethodInfo *method=NULL;
+ for (List<MethodInfo>::Element *E=M->get().front();E;E=E->next()) {
+
+ if (!p_instance && !E->get()._static) {
+ r_error.error=Variant::CallError::CALL_ERROR_INSTANCE_IS_NULL;
+ continue;
+ }
+
+ int pc = E->get().param_types.size();
+ if (pc>p_argcount) {
+
+ r_error.error=Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
+ r_error.argument=pc;
+ continue;
+ }
+ if (pc<p_argcount) {
+
+ r_error.error=Variant::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS;
+ r_error.argument=pc;
+ continue;
+ }
+ uint32_t *ptypes=E->get().param_types.ptr();
+ bool valid=true;
+
+ for(int i=0;i<pc;i++) {
+
+ Variant::Type arg_expected=Variant::NIL;
+ switch(ptypes[i]) {
+
+ case ARG_TYPE_VOID: {
+ //bug?
+ } break;
+ case ARG_TYPE_BOOLEAN: {
+ if (p_args[i]->get_type()!=Variant::BOOL)
+ arg_expected=Variant::BOOL;
+ } break;
+ case ARG_NUMBER_CLASS_BIT|ARG_TYPE_BYTE:
+ case ARG_NUMBER_CLASS_BIT|ARG_TYPE_CHAR:
+ case ARG_NUMBER_CLASS_BIT|ARG_TYPE_SHORT:
+ case ARG_NUMBER_CLASS_BIT|ARG_TYPE_INT:
+ case ARG_NUMBER_CLASS_BIT|ARG_TYPE_LONG:
+ case ARG_TYPE_BYTE:
+ case ARG_TYPE_CHAR:
+ case ARG_TYPE_SHORT:
+ case ARG_TYPE_INT:
+ case ARG_TYPE_LONG: {
+
+ if (!p_args[i]->is_num())
+ arg_expected=Variant::INT;
+
+ } break;
+ case ARG_NUMBER_CLASS_BIT|ARG_TYPE_FLOAT:
+ case ARG_NUMBER_CLASS_BIT|ARG_TYPE_DOUBLE:
+ case ARG_TYPE_FLOAT:
+ case ARG_TYPE_DOUBLE: {
+
+ if (!p_args[i]->is_num())
+ arg_expected=Variant::REAL;
+
+ } break;
+ case ARG_TYPE_STRING: {
+
+ if (p_args[i]->get_type()!=Variant::STRING)
+ arg_expected=Variant::STRING;
+
+ } break;
+ case ARG_TYPE_CLASS: {
+
+ if (p_args[i]->get_type()!=Variant::OBJECT)
+ arg_expected=Variant::OBJECT;
+ else {
+
+ Ref<Reference> ref = *p_args[i];
+ if (!ref.is_null()) {
+ if (ref->cast_to<JavaObject>() ) {
+
+ Ref<JavaObject> jo=ref;
+ //could be faster
+ jclass c = env->FindClass(E->get().param_sigs[i].operator String().utf8().get_data());
+ if (!c || !env->IsInstanceOf(jo->instance,c)) {
+
+ arg_expected=Variant::OBJECT;
+ } else {
+ //ok
+ }
+ } else {
+ arg_expected=Variant::OBJECT;
+ }
+
+ }
+ }
+
+ } break;
+ default: {
+
+ if (p_args[i]->get_type()!=Variant::ARRAY)
+ arg_expected=Variant::ARRAY;
+
+ } break;
+
+ }
+
+ if (arg_expected!=Variant::NIL) {
+ r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.argument=i;
+ r_error.expected=arg_expected;
+ valid=false;
+ break;
+
+ }
+
+ }
+ if (!valid)
+ continue;
+
+
+ method=&E->get();
+ break;
+
+ }
+
+ if (!method)
+ return true; //no version convinces
+
+
+
+ r_error.error=Variant::CallError::CALL_OK;
+
+ jvalue *argv=NULL;
+
+ if (method->param_types.size()) {
+
+ argv=(jvalue*)alloca( sizeof(jvalue)*method->param_types.size() );
+ }
+
+ List<jobject> to_free;
+ for(int i=0;i<method->param_types.size();i++) {
+
+ switch(method->param_types[i]) {
+ case ARG_TYPE_VOID: {
+ //can't happen
+ argv[i].l=NULL; //I hope this works
+ } break;
+
+ case ARG_TYPE_BOOLEAN: {
+ argv[i].z=*p_args[i];
+ } break;
+ case ARG_TYPE_BYTE: {
+ argv[i].b=*p_args[i];
+ } break;
+ case ARG_TYPE_CHAR: {
+ argv[i].c=*p_args[i];
+ } break;
+ case ARG_TYPE_SHORT: {
+ argv[i].s=*p_args[i];
+ } break;
+ case ARG_TYPE_INT: {
+ argv[i].i=*p_args[i];
+ } break;
+ case ARG_TYPE_LONG: {
+ argv[i].j=*p_args[i];
+ } break;
+ case ARG_TYPE_FLOAT: {
+ argv[i].f=*p_args[i];
+ } break;
+ case ARG_TYPE_DOUBLE: {
+ argv[i].d=*p_args[i];
+ } break;
+ case ARG_NUMBER_CLASS_BIT|ARG_TYPE_BOOLEAN: {
+ jclass bclass = env->FindClass("java/lang/Boolean");
+ jmethodID ctor = env->GetMethodID(bclass, "<init>", "(Z)V");
+ jvalue val;
+ val.z = (bool)(*p_args[i]);
+ jobject obj = env->NewObjectA(bclass, ctor, &val);
+ argv[i].l = obj;
+ to_free.push_back(obj);
+ } break;
+ case ARG_NUMBER_CLASS_BIT|ARG_TYPE_BYTE: {
+ jclass bclass = env->FindClass("java/lang/Byte");
+ jmethodID ctor = env->GetMethodID(bclass, "<init>", "(B)V");
+ jvalue val;
+ val.b = (int)(*p_args[i]);
+ jobject obj = env->NewObjectA(bclass, ctor, &val);
+ argv[i].l = obj;
+ to_free.push_back(obj);
+ } break;
+ case ARG_NUMBER_CLASS_BIT|ARG_TYPE_CHAR: {
+ jclass bclass = env->FindClass("java/lang/Character");
+ jmethodID ctor = env->GetMethodID(bclass, "<init>", "(C)V");
+ jvalue val;
+ val.c = (int)(*p_args[i]);
+ jobject obj = env->NewObjectA(bclass, ctor, &val);
+ argv[i].l = obj;
+ to_free.push_back(obj);
+ } break;
+ case ARG_NUMBER_CLASS_BIT|ARG_TYPE_SHORT: {
+ jclass bclass = env->FindClass("java/lang/Short");
+ jmethodID ctor = env->GetMethodID(bclass, "<init>", "(S)V");
+ jvalue val;
+ val.s = (int)(*p_args[i]);
+ jobject obj = env->NewObjectA(bclass, ctor, &val);
+ argv[i].l = obj;
+ to_free.push_back(obj);
+ } break;
+ case ARG_NUMBER_CLASS_BIT|ARG_TYPE_INT: {
+ jclass bclass = env->FindClass("java/lang/Integer");
+ jmethodID ctor = env->GetMethodID(bclass, "<init>", "(I)V");
+ jvalue val;
+ val.i = (int)(*p_args[i]);
+ jobject obj = env->NewObjectA(bclass, ctor, &val);
+ argv[i].l = obj;
+ to_free.push_back(obj);
+ } break;
+ case ARG_NUMBER_CLASS_BIT|ARG_TYPE_LONG: {
+ jclass bclass = env->FindClass("java/lang/Long");
+ jmethodID ctor = env->GetMethodID(bclass, "<init>", "(J)V");
+ jvalue val;
+ val.j = (int64_t)(*p_args[i]);
+ jobject obj = env->NewObjectA(bclass, ctor, &val);
+ argv[i].l = obj;
+ to_free.push_back(obj);
+ } break;
+ case ARG_NUMBER_CLASS_BIT|ARG_TYPE_FLOAT: {
+ jclass bclass = env->FindClass("java/lang/Float");
+ jmethodID ctor = env->GetMethodID(bclass, "<init>", "(F)V");
+ jvalue val;
+ val.f = (float)(*p_args[i]);
+ jobject obj = env->NewObjectA(bclass, ctor, &val);
+ argv[i].l = obj;
+ to_free.push_back(obj);
+ } break;
+ case ARG_NUMBER_CLASS_BIT|ARG_TYPE_DOUBLE: {
+ jclass bclass = env->FindClass("java/lang/Double");
+ jmethodID ctor = env->GetMethodID(bclass, "<init>", "(D)V");
+ jvalue val;
+ val.d = (double)(*p_args[i]);
+ jobject obj = env->NewObjectA(bclass, ctor, &val);
+ argv[i].l = obj;
+ to_free.push_back(obj);
+ } break;
+ case ARG_TYPE_STRING: {
+ String s = *p_args[i];
+ jstring jStr = env->NewStringUTF(s.utf8().get_data());
+ argv[i].l=jStr;
+ to_free.push_back(jStr);
+ } break;
+ case ARG_TYPE_CLASS: {
+
+ Ref<JavaObject> jo=*p_args[i];
+ if (jo.is_valid()) {
+
+ argv[i].l=jo->instance;
+ } else {
+ argv[i].l=NULL; //I hope this works
+ }
+
+ } break;
+ case ARG_ARRAY_BIT|ARG_TYPE_BOOLEAN: {
+
+ Array arr = *p_args[i];
+ jbooleanArray a = env->NewBooleanArray(arr.size());
+ for(int j=0;j<arr.size();j++) {
+ jboolean val = arr[j];
+ env->SetBooleanArrayRegion(a,j,1,&val);
+ }
+ argv[i].l=a;
+ to_free.push_back(a);
+
+ } break;
+ case ARG_ARRAY_BIT|ARG_TYPE_BYTE: {
+
+ Array arr = *p_args[i];
+ jbyteArray a = env->NewByteArray(arr.size());
+ for(int j=0;j<arr.size();j++) {
+ jbyte val = arr[j];
+ env->SetByteArrayRegion(a,j,1,&val);
+ }
+ argv[i].l=a;
+ to_free.push_back(a);
+
+
+ } break;
+ case ARG_ARRAY_BIT|ARG_TYPE_CHAR: {
+
+ Array arr = *p_args[i];
+ jcharArray a = env->NewCharArray(arr.size());
+ for(int j=0;j<arr.size();j++) {
+ jchar val = arr[j];
+ env->SetCharArrayRegion(a,j,1,&val);
+ }
+ argv[i].l=a;
+ to_free.push_back(a);
+
+ } break;
+ case ARG_ARRAY_BIT|ARG_TYPE_SHORT: {
+
+ Array arr = *p_args[i];
+ jshortArray a = env->NewShortArray(arr.size());
+ for(int j=0;j<arr.size();j++) {
+ jshort val = arr[j];
+ env->SetShortArrayRegion(a,j,1,&val);
+ }
+ argv[i].l=a;
+ to_free.push_back(a);
+
+ } break;
+ case ARG_ARRAY_BIT|ARG_TYPE_INT: {
+
+ Array arr = *p_args[i];
+ jintArray a = env->NewIntArray(arr.size());
+ for(int j=0;j<arr.size();j++) {
+ jint val = arr[j];
+ env->SetIntArrayRegion(a,j,1,&val);
+ }
+ argv[i].l=a;
+ to_free.push_back(a);
+ } break;
+ case ARG_ARRAY_BIT|ARG_TYPE_LONG: {
+ Array arr = *p_args[i];
+ jlongArray a = env->NewLongArray(arr.size());
+ for(int j=0;j<arr.size();j++) {
+ jlong val = arr[j];
+ env->SetLongArrayRegion(a,j,1,&val);
+ }
+ argv[i].l=a;
+ to_free.push_back(a);
+
+ } break;
+ case ARG_ARRAY_BIT|ARG_TYPE_FLOAT: {
+
+ Array arr = *p_args[i];
+ jfloatArray a = env->NewFloatArray(arr.size());
+ for(int j=0;j<arr.size();j++) {
+ jfloat val = arr[j];
+ env->SetFloatArrayRegion(a,j,1,&val);
+ }
+ argv[i].l=a;
+ to_free.push_back(a);
+
+
+ } break;
+ case ARG_ARRAY_BIT|ARG_TYPE_DOUBLE: {
+
+ Array arr = *p_args[i];
+ jdoubleArray a = env->NewDoubleArray(arr.size());
+ for(int j=0;j<arr.size();j++) {
+ jdouble val = arr[j];
+ env->SetDoubleArrayRegion(a,j,1,&val);
+ }
+ argv[i].l=a;
+ to_free.push_back(a);
+
+ } break;
+ case ARG_ARRAY_BIT|ARG_TYPE_STRING: {
+
+ Array arr = *p_args[i];
+ jobjectArray a = env->NewObjectArray(arr.size(),env->FindClass("java/lang/String"),NULL);
+ for(int j=0;j<arr.size();j++) {
+
+ String s = arr[j];
+ jstring jStr = env->NewStringUTF(s.utf8().get_data());
+ env->SetObjectArrayElement(a,j,jStr);
+ to_free.push_back(jStr);
+ }
+
+ argv[i].l=a;
+ to_free.push_back(a);
+ } break;
+ case ARG_ARRAY_BIT|ARG_TYPE_CLASS: {
+
+ argv[i].l=NULL;
+ } break;
+ }
+ }
+
+ r_error.error=Variant::CallError::CALL_OK;
+ bool success=true;
+
+ switch(method->return_type) {
+
+
+ case ARG_TYPE_VOID: {
+ if (method->_static) {
+ env->CallStaticVoidMethodA(_class,method->method,argv);
+ } else {
+ env->CallVoidMethodA(p_instance->instance,method->method,argv);
+ }
+ ret=Variant();
+
+ } break;
+ case ARG_TYPE_BOOLEAN: {
+ if (method->_static) {
+ ret=env->CallStaticBooleanMethodA(_class,method->method,argv);
+ } else {
+ ret=env->CallBooleanMethodA(p_instance->instance,method->method,argv);
+ }
+ } break;
+ case ARG_TYPE_BYTE: {
+ if (method->_static) {
+ ret=env->CallStaticByteMethodA(_class,method->method,argv);
+ } else {
+ ret=env->CallByteMethodA(p_instance->instance,method->method,argv);
+ }
+ } break;
+ case ARG_TYPE_CHAR: {
+
+ if (method->_static) {
+ ret=env->CallStaticCharMethodA(_class,method->method,argv);
+ } else {
+ ret=env->CallCharMethodA(p_instance->instance,method->method,argv);
+ }
+ } break;
+ case ARG_TYPE_SHORT: {
+
+ if (method->_static) {
+ ret=env->CallStaticShortMethodA(_class,method->method,argv);
+ } else {
+ ret=env->CallShortMethodA(p_instance->instance,method->method,argv);
+ }
+
+ } break;
+ case ARG_TYPE_INT: {
+
+ if (method->_static) {
+ ret=env->CallStaticIntMethodA(_class,method->method,argv);
+ } else {
+ ret=env->CallIntMethodA(p_instance->instance,method->method,argv);
+ }
+
+ } break;
+ case ARG_TYPE_LONG: {
+
+ if (method->_static) {
+ ret=env->CallStaticLongMethodA(_class,method->method,argv);
+ } else {
+ ret=env->CallLongMethodA(p_instance->instance,method->method,argv);
+ }
+
+ } break;
+ case ARG_TYPE_FLOAT: {
+
+ if (method->_static) {
+ ret=env->CallStaticFloatMethodA(_class,method->method,argv);
+ } else {
+ ret=env->CallFloatMethodA(p_instance->instance,method->method,argv);
+ }
+
+ } break;
+ case ARG_TYPE_DOUBLE: {
+
+ if (method->_static) {
+ ret=env->CallStaticDoubleMethodA(_class,method->method,argv);
+ } else {
+ ret=env->CallDoubleMethodA(p_instance->instance,method->method,argv);
+ }
+
+ } break;
+ default: {
+
+ jobject obj;
+ if (method->_static) {
+ obj=env->CallStaticObjectMethodA(_class,method->method,argv);
+ } else {
+ obj=env->CallObjectMethodA(p_instance->instance,method->method,argv);
+ }
+
+ if (!obj) {
+ ret=Variant();
+ } else {
+
+ if (!_convert_object_to_variant(env, obj, ret,method->return_type)) {
+ ret=Variant();
+ r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD;
+ success=false;
+ }
+ env->DeleteLocalRef(obj);
+ }
+
+ } break;
+
+ }
+
+ for(List<jobject>::Element *E=to_free.front();E;E=E->next()) {
+ env->DeleteLocalRef(E->get());
+ }
+
+ return success;
+}
+
+Variant JavaClass::call(const StringName& p_method,const Variant** p_args,int p_argcount,Variant::CallError &r_error) {
+
+ Variant ret;
+ bool found = _call_method(NULL,p_method,p_args,p_argcount,r_error,ret);
+ if (found) {
+ return ret;
+ }
+
+ return Reference::call(p_method,p_args,p_argcount,r_error);
+}
+
+JavaClass::JavaClass() {
+
+
+}
+
+/////////////////////
+
+Variant JavaObject::call(const StringName& p_method,const Variant** p_args,int p_argcount,Variant::CallError &r_error){
+
+
+ return Variant();
+}
+
+JavaObject::JavaObject(const Ref<JavaClass>& p_base,jobject *p_instance) {
+
+
+}
+
+JavaObject::~JavaObject(){
+
+
+}
+
+
+////////////////////
+
+void JavaClassWrapper::_bind_methods() {
+
+ ObjectTypeDB::bind_method(_MD("wrap:JavaClass","name"),&JavaClassWrapper::wrap);
+}
+
+
+bool JavaClassWrapper::_get_type_sig(JNIEnv *env,jobject obj,uint32_t& sig,String&strsig) {
+
+ jstring name2 = (jstring)env->CallObjectMethod(obj, Class_getName);
+ String str_type = env->GetStringUTFChars( name2, NULL );
+ print_line("name: "+str_type);
+ env->DeleteLocalRef(name2);
+ uint32_t t=0;
+
+ if (str_type.begins_with("[")) {
+
+ t=JavaClass::ARG_ARRAY_BIT;
+ strsig="[";
+ str_type=str_type.substr(1,str_type.length()-1);
+ if (str_type.begins_with("[")) {
+ print_line("Nested arrays not supported for type: "+str_type);
+ return false;
+ }
+ if (str_type.begins_with("L")) {
+ str_type=str_type.substr(1,str_type.length()-2); //ok it's a class
+ }
+ }
+
+ if (str_type=="void" || str_type=="V") {
+ t|=JavaClass::ARG_TYPE_VOID;
+ strsig+="V";
+ } else if (str_type=="boolean" || str_type=="Z") {
+ t|=JavaClass::ARG_TYPE_BOOLEAN;
+ strsig+="Z";
+ } else if (str_type=="byte" || str_type=="B") {
+ t|=JavaClass::ARG_TYPE_BYTE;
+ strsig+="B";
+ } else if (str_type=="char" || str_type=="C") {
+ t|=JavaClass::ARG_TYPE_CHAR;
+ strsig+="C";
+ } else if (str_type=="short" || str_type=="S") {
+ t|=JavaClass::ARG_TYPE_SHORT;
+ strsig+="S";
+ } else if (str_type=="int" || str_type=="I") {
+ t|=JavaClass::ARG_TYPE_INT;
+ strsig+="I";
+ } else if (str_type=="long" || str_type=="J") {
+ t|=JavaClass::ARG_TYPE_LONG;
+ strsig+="J";
+ } else if (str_type=="float" || str_type=="F") {
+ t|=JavaClass::ARG_TYPE_FLOAT;
+ strsig+="F";
+ } else if (str_type=="double" || str_type=="D") {
+ t|=JavaClass::ARG_TYPE_DOUBLE;
+ strsig+="D";
+ } else if (str_type=="java.lang.String") {
+ t|=JavaClass::ARG_TYPE_STRING;
+ strsig+="Ljava/lang/String;";
+ } else if (str_type=="java.lang.Boolean") {
+ t|=JavaClass::ARG_TYPE_BOOLEAN|JavaClass::ARG_NUMBER_CLASS_BIT;
+ strsig+="Ljava/lang/Boolean;";
+ } else if (str_type=="java.lang.Byte") {
+ t|=JavaClass::ARG_TYPE_BYTE|JavaClass::ARG_NUMBER_CLASS_BIT;
+ strsig+="Ljava/lang/Byte;";
+ } else if (str_type=="java.lang.Character") {
+ t|=JavaClass::ARG_TYPE_CHAR|JavaClass::ARG_NUMBER_CLASS_BIT;
+ strsig+="Ljava/lang/Character;";
+ } else if (str_type=="java.lang.Short") {
+ t|=JavaClass::ARG_TYPE_SHORT|JavaClass::ARG_NUMBER_CLASS_BIT;
+ strsig+="Ljava/lang/Short;";
+ } else if (str_type=="java.lang.Integer") {
+ t|=JavaClass::ARG_TYPE_INT|JavaClass::ARG_NUMBER_CLASS_BIT;
+ strsig+="Ljava/lang/Integer;";
+ } else if (str_type=="java.lang.Long") {
+ t|=JavaClass::ARG_TYPE_LONG|JavaClass::ARG_NUMBER_CLASS_BIT;
+ strsig+="Ljava/lang/Long;";
+ } else if (str_type=="java.lang.Float") {
+ t|=JavaClass::ARG_TYPE_FLOAT|JavaClass::ARG_NUMBER_CLASS_BIT;
+ strsig+="Ljava/lang/Float;";
+ } else if (str_type=="java.lang.Double") {
+ t|=JavaClass::ARG_TYPE_DOUBLE|JavaClass::ARG_NUMBER_CLASS_BIT;
+ strsig+="Ljava/lang/Double;";
+ } else {
+ //a class likely
+ strsig+="L"+str_type.replace(".","/")+";";
+ t|=JavaClass::ARG_TYPE_CLASS;
+ }
+
+ sig=t;
+
+
+ return true;
+
+}
+
+bool JavaClass::_convert_object_to_variant(JNIEnv * env, jobject obj, Variant& var,uint32_t p_sig) {
+
+ if (!obj) {
+ var=Variant(); //seems null is just null...
+ return true;
+ }
+
+
+ switch(p_sig) {
+
+ case ARG_TYPE_VOID: {
+
+ return Variant();
+ } break;
+ case ARG_TYPE_BOOLEAN|ARG_NUMBER_CLASS_BIT: {
+
+ var = env->CallBooleanMethod(obj, JavaClassWrapper::singleton->Boolean_booleanValue);
+ return true;
+ } break;
+ case ARG_TYPE_BYTE|ARG_NUMBER_CLASS_BIT: {
+
+ var = env->CallByteMethod(obj, JavaClassWrapper::singleton->Byte_byteValue);
+ return true;
+
+ } break;
+ case ARG_TYPE_CHAR|ARG_NUMBER_CLASS_BIT: {
+
+ var = env->CallCharMethod(obj, JavaClassWrapper::singleton->Character_characterValue);
+ return true;
+
+ } break;
+ case ARG_TYPE_SHORT|ARG_NUMBER_CLASS_BIT: {
+
+ var = env->CallShortMethod(obj, JavaClassWrapper::singleton->Short_shortValue);
+ return true;
+
+ } break;
+ case ARG_TYPE_INT|ARG_NUMBER_CLASS_BIT: {
+
+ var = env->CallIntMethod(obj, JavaClassWrapper::singleton->Integer_integerValue);
+ return true;
+
+ } break;
+ case ARG_TYPE_LONG|ARG_NUMBER_CLASS_BIT: {
+
+ var = env->CallLongMethod(obj, JavaClassWrapper::singleton->Long_longValue);
+ return true;
+
+ } break;
+ case ARG_TYPE_FLOAT|ARG_NUMBER_CLASS_BIT: {
+
+ var = env->CallFloatMethod(obj, JavaClassWrapper::singleton->Float_floatValue);
+ return true;
+
+ } break;
+ case ARG_TYPE_DOUBLE|ARG_NUMBER_CLASS_BIT: {
+
+ var = env->CallDoubleMethod(obj, JavaClassWrapper::singleton->Double_doubleValue);
+ return true;
+ } break;
+ case ARG_TYPE_STRING: {
+
+ var = String::utf8(env->GetStringUTFChars( (jstring)obj, NULL ));
+ return true;
+ } break;
+ case ARG_TYPE_CLASS: {
+
+ return false;
+ } break;
+ case ARG_ARRAY_BIT|ARG_TYPE_VOID: {
+
+ var = Array(); // ?
+ return true;
+ } break;
+ case ARG_ARRAY_BIT|ARG_TYPE_BOOLEAN: {
+
+ Array ret;
+ jobjectArray arr = (jobjectArray)obj;
+
+ int count = env->GetArrayLength(arr);
+
+ for (int i=0; i<count; i++) {
+
+ jboolean val;
+ env->GetBooleanArrayRegion((jbooleanArray)arr,0,1,&val);
+ ret.push_back(val);
+ }
+
+ var=ret;
+ return true;
+
+ } break;
+ case ARG_ARRAY_BIT|ARG_TYPE_BYTE: {
+
+ Array ret;
+ jobjectArray arr = (jobjectArray)obj;
+
+ int count = env->GetArrayLength(arr);
+
+ for (int i=0; i<count; i++) {
+
+ jbyte val;
+ env->GetByteArrayRegion((jbyteArray)arr,0,1,&val);
+ ret.push_back(val);
+ }
+
+ var=ret;
+ return true;
+ } break;
+ case ARG_ARRAY_BIT|ARG_TYPE_CHAR: {
+ Array ret;
+ jobjectArray arr = (jobjectArray)obj;
+
+ int count = env->GetArrayLength(arr);
+
+ for (int i=0; i<count; i++) {
+
+ jchar val;
+ env->GetCharArrayRegion((jcharArray)arr,0,1,&val);
+ ret.push_back(val);
+ }
+
+ var=ret;
+ return true;
+ } break;
+ case ARG_ARRAY_BIT|ARG_TYPE_SHORT: {
+ Array ret;
+ jobjectArray arr = (jobjectArray)obj;
+
+ int count = env->GetArrayLength(arr);
+
+ for (int i=0; i<count; i++) {
+
+ jshort val;
+ env->GetShortArrayRegion((jshortArray)arr,0,1,&val);
+ ret.push_back(val);
+ }
+
+ var=ret;
+ return true;
+ } break;
+ case ARG_ARRAY_BIT|ARG_TYPE_INT: {
+ Array ret;
+ jobjectArray arr = (jobjectArray)obj;
+
+ int count = env->GetArrayLength(arr);
+
+ for (int i=0; i<count; i++) {
+
+ jint val;
+ env->GetIntArrayRegion((jintArray)arr,0,1,&val);
+ ret.push_back(val);
+ }
+
+ var=ret;
+ return true;
+ } break;
+ case ARG_ARRAY_BIT|ARG_TYPE_LONG: {
+ Array ret;
+ jobjectArray arr = (jobjectArray)obj;
+
+ int count = env->GetArrayLength(arr);
+
+ for (int i=0; i<count; i++) {
+
+ jlong val;
+ env->GetLongArrayRegion((jlongArray)arr,0,1,&val);
+ ret.push_back(val);
+ }
+
+ var=ret;
+ return true;
+ } break;
+ case ARG_ARRAY_BIT|ARG_TYPE_FLOAT: {
+ Array ret;
+ jobjectArray arr = (jobjectArray)obj;
+
+ int count = env->GetArrayLength(arr);
+
+ for (int i=0; i<count; i++) {
+
+ jfloat val;
+ env->GetFloatArrayRegion((jfloatArray)arr,0,1,&val);
+ ret.push_back(val);
+ }
+
+ var=ret;
+ return true;
+ } break;
+ case ARG_ARRAY_BIT|ARG_TYPE_DOUBLE: {
+ Array ret;
+ jobjectArray arr = (jobjectArray)obj;
+
+ int count = env->GetArrayLength(arr);
+
+ for (int i=0; i<count; i++) {
+
+ jdouble val;
+ env->GetDoubleArrayRegion((jdoubleArray)arr,0,1,&val);
+ ret.push_back(val);
+ }
+
+ var=ret;
+ return true;
+ } break;
+ case ARG_NUMBER_CLASS_BIT|ARG_ARRAY_BIT|ARG_TYPE_BOOLEAN: {
+
+ Array ret;
+ jobjectArray arr = (jobjectArray)obj;
+
+ int count = env->GetArrayLength(arr);
+
+ for (int i=0; i<count; i++) {
+
+ jobject o = env->GetObjectArrayElement(arr, i);
+ if (!o)
+ ret.push_back(Variant());
+ else {
+ bool val = env->CallBooleanMethod(o, JavaClassWrapper::singleton->Boolean_booleanValue);
+ ret.push_back(val);
+
+ }
+ env->DeleteLocalRef(o);
+ }
+
+ var=ret;
+ return true;
+
+ } break;
+ case ARG_NUMBER_CLASS_BIT|ARG_ARRAY_BIT|ARG_TYPE_BYTE: {
+
+ Array ret;
+ jobjectArray arr = (jobjectArray)obj;
+
+ int count = env->GetArrayLength(arr);
+
+ for (int i=0; i<count; i++) {
+
+ jobject o = env->GetObjectArrayElement(arr, i);
+ if (!o)
+ ret.push_back(Variant());
+ else {
+ int val = env->CallByteMethod(o, JavaClassWrapper::singleton->Byte_byteValue);
+ ret.push_back(val);
+
+ }
+ env->DeleteLocalRef(o);
+ }
+
+ var=ret;
+ return true;
+ } break;
+ case ARG_NUMBER_CLASS_BIT|ARG_ARRAY_BIT|ARG_TYPE_CHAR: {
+
+ Array ret;
+ jobjectArray arr = (jobjectArray)obj;
+
+ int count = env->GetArrayLength(arr);
+
+ for (int i=0; i<count; i++) {
+
+ jobject o = env->GetObjectArrayElement(arr, i);
+ if (!o)
+ ret.push_back(Variant());
+ else {
+ int val = env->CallCharMethod(o, JavaClassWrapper::singleton->Character_characterValue);
+ ret.push_back(val);
+
+ }
+ env->DeleteLocalRef(o);
+ }
+
+ var=ret;
+ return true;
+ } break;
+ case ARG_NUMBER_CLASS_BIT|ARG_ARRAY_BIT|ARG_TYPE_SHORT: {
+
+ Array ret;
+ jobjectArray arr = (jobjectArray)obj;
+
+ int count = env->GetArrayLength(arr);
+
+ for (int i=0; i<count; i++) {
+
+ jobject o = env->GetObjectArrayElement(arr, i);
+ if (!o)
+ ret.push_back(Variant());
+ else {
+ int val = env->CallShortMethod(o, JavaClassWrapper::singleton->Short_shortValue);
+ ret.push_back(val);
+
+ }
+ env->DeleteLocalRef(o);
+ }
+
+ var=ret;
+ return true;
+ } break;
+ case ARG_NUMBER_CLASS_BIT|ARG_ARRAY_BIT|ARG_TYPE_INT: {
+
+ Array ret;
+ jobjectArray arr = (jobjectArray)obj;
+
+ int count = env->GetArrayLength(arr);
+
+ for (int i=0; i<count; i++) {
+
+ jobject o = env->GetObjectArrayElement(arr, i);
+ if (!o)
+ ret.push_back(Variant());
+ else {
+ int val = env->CallIntMethod(o, JavaClassWrapper::singleton->Integer_integerValue);
+ ret.push_back(val);
+
+ }
+ env->DeleteLocalRef(o);
+ }
+
+ var=ret;
+ return true;
+ } break;
+ case ARG_NUMBER_CLASS_BIT|ARG_ARRAY_BIT|ARG_TYPE_LONG: {
+
+ Array ret;
+ jobjectArray arr = (jobjectArray)obj;
+
+ int count = env->GetArrayLength(arr);
+
+ for (int i=0; i<count; i++) {
+
+ jobject o = env->GetObjectArrayElement(arr, i);
+ if (!o)
+ ret.push_back(Variant());
+ else {
+ int64_t val = env->CallLongMethod(o, JavaClassWrapper::singleton->Long_longValue);
+ ret.push_back(val);
+
+ }
+ env->DeleteLocalRef(o);
+ }
+
+ var=ret;
+ return true;
+ } break;
+ case ARG_NUMBER_CLASS_BIT|ARG_ARRAY_BIT|ARG_TYPE_FLOAT: {
+
+ Array ret;
+ jobjectArray arr = (jobjectArray)obj;
+
+ int count = env->GetArrayLength(arr);
+
+ for (int i=0; i<count; i++) {
+
+ jobject o = env->GetObjectArrayElement(arr, i);
+ if (!o)
+ ret.push_back(Variant());
+ else {
+ float val = env->CallFloatMethod(o, JavaClassWrapper::singleton->Float_floatValue);
+ ret.push_back(val);
+
+ }
+ env->DeleteLocalRef(o);
+ }
+
+ var=ret;
+ return true;
+ } break;
+ case ARG_NUMBER_CLASS_BIT|ARG_ARRAY_BIT|ARG_TYPE_DOUBLE: {
+ Array ret;
+ jobjectArray arr = (jobjectArray)obj;
+
+ int count = env->GetArrayLength(arr);
+
+ for (int i=0; i<count; i++) {
+
+ jobject o = env->GetObjectArrayElement(arr, i);
+ if (!o)
+ ret.push_back(Variant());
+ else {
+ double val = env->CallDoubleMethod(o, JavaClassWrapper::singleton->Double_doubleValue);
+ ret.push_back(val);
+
+ }
+ env->DeleteLocalRef(o);
+ }
+
+ var=ret;
+ return true;
+ } break;
+
+ case ARG_ARRAY_BIT|ARG_TYPE_STRING: {
+
+ Array ret;
+ jobjectArray arr = (jobjectArray)obj;
+
+ int count = env->GetArrayLength(arr);
+
+ for (int i=0; i<count; i++) {
+
+ jobject o = env->GetObjectArrayElement(arr, i);
+ if (!o)
+ ret.push_back(Variant());
+ else {
+ String val = String::utf8(env->GetStringUTFChars( (jstring)o, NULL ));
+ ret.push_back(val);
+
+ }
+ env->DeleteLocalRef(o);
+ }
+
+ var=ret;
+ return true;
+ } break;
+ case ARG_ARRAY_BIT|ARG_TYPE_CLASS: {
+
+ } break;
+ }
+
+ return false;
+
+}
+
+
+Ref<JavaClass> JavaClassWrapper::wrap(const String& p_class) {
+
+ if (class_cache.has(p_class))
+ return class_cache[p_class];
+
+
+ JNIEnv *env = ThreadAndroid::get_env();
+
+ jclass bclass = env->FindClass(p_class.utf8().get_data());
+ ERR_FAIL_COND_V(!bclass,Ref<JavaClass>());
+
+ //jmethodID getDeclaredMethods = env->GetMethodID(bclass,"getDeclaredMethods", "()[Ljava/lang/reflect/Method;");
+
+ //ERR_FAIL_COND_V(!getDeclaredMethods,Ref<JavaClass>());
+
+ jobjectArray methods = (jobjectArray)env->CallObjectMethod(bclass, getDeclaredMethods);
+
+ ERR_FAIL_COND_V(!methods,Ref<JavaClass>());
+
+
+ Ref<JavaClass> java_class = memnew( JavaClass );
+
+ int count = env->GetArrayLength(methods);
+
+ for (int i=0; i<count; i++) {
+
+ jobject obj = env->GetObjectArrayElement(methods, i);
+ ERR_CONTINUE(!obj);
+
+
+ jstring name = (jstring)env->CallObjectMethod(obj, getName);
+ String str_method = env->GetStringUTFChars( name, NULL );
+ env->DeleteLocalRef(name);
+
+ Vector<String> params;
+
+ jint mods = env->CallIntMethod(obj,getModifiers);
+
+ if (!(mods&0x0001)) {
+ env->DeleteLocalRef(obj);
+ continue; //not public bye
+ }
+
+
+
+ jobjectArray param_types = (jobjectArray)env->CallObjectMethod(obj, getParameterTypes);
+ int count2=env->GetArrayLength(param_types);
+
+ if (!java_class->methods.has(str_method)) {
+ java_class->methods[str_method]=List<JavaClass::MethodInfo>();
+ }
+
+ JavaClass::MethodInfo mi;
+ mi._static = (mods&0x8)!=0;
+ bool valid=true;
+ String signature="(";
+
+ for(int j=0;j<count2;j++) {
+
+ jobject obj2 = env->GetObjectArrayElement(param_types, j);
+ String strsig;
+ uint32_t sig=0;
+ if (!_get_type_sig(env,obj2,sig,strsig)) {
+ valid=false;
+ env->DeleteLocalRef(obj2);
+ break;
+ }
+ signature+=strsig;
+ mi.param_types.push_back(sig);
+ mi.param_sigs.push_back(strsig);
+ env->DeleteLocalRef(obj2);
+
+ }
+
+ if (!valid) {
+ print_line("Method Can't be bound (unsupported arguments): "+p_class+"::"+str_method);
+ env->DeleteLocalRef(obj);
+ env->DeleteLocalRef(param_types);
+ continue;
+ }
+
+ signature+=")";
+
+ jobject return_type = (jobject)env->CallObjectMethod(obj, getReturnType);
+
+
+ String strsig;
+ uint32_t sig=0;
+ if (!_get_type_sig(env,return_type,sig,strsig)) {
+ print_line("Method Can't be bound (unsupported return type): "+p_class+"::"+str_method);
+ env->DeleteLocalRef(obj);
+ env->DeleteLocalRef(param_types);
+ env->DeleteLocalRef(return_type);
+ continue;
+ }
+
+ signature+=strsig;
+ mi.return_type=sig;
+
+ print_line("METHOD: "+str_method+" SIG: "+signature+" static: "+itos(mi._static));
+
+ bool discard=false;
+
+ for(List<JavaClass::MethodInfo>::Element *E=java_class->methods[str_method].front();E;E=E->next()) {
+
+ float new_likeliness=0;
+ float existing_likeliness=0;
+
+ if (E->get().param_types.size()!=mi.param_types.size())
+ continue;
+ bool valid=true;
+ for(int j=0;j<E->get().param_types.size();j++) {
+
+ Variant::Type _new;
+ float new_l;
+ Variant::Type existing;
+ float existing_l;
+ JavaClass::_convert_to_variant_type(E->get().param_types[j],existing,existing_l);
+ JavaClass::_convert_to_variant_type(mi.param_types[j],_new,new_l);
+ if (_new!=existing) {
+ valid=false;
+ break;
+ }
+ new_likeliness+=new_l;
+ existing_likeliness=existing_l;
+
+ }
+
+ if (!valid)
+ continue;
+
+ if (new_likeliness>existing_likeliness) {
+ java_class->methods[str_method].erase(E);
+ print_line("replace old");
+ break;
+ } else {
+ discard=true;
+ print_line("old is better");
+ }
+
+
+ }
+
+ if (!discard) {
+ if (mi._static)
+ mi.method = env->GetStaticMethodID(bclass, str_method.utf8().get_data(), signature.utf8().get_data());
+ else
+ mi.method = env->GetMethodID(bclass, str_method.utf8().get_data(), signature.utf8().get_data());
+
+ ERR_CONTINUE(!mi.method);
+
+ java_class->methods[str_method].push_back(mi);
+ }
+
+ env->DeleteLocalRef(obj);
+ env->DeleteLocalRef(param_types);
+ env->DeleteLocalRef(return_type);
+
+
+
+
+ //args[i] = _jobject_to_variant(env, obj);
+// print_line("\targ"+itos(i)+": "+Variant::get_type_name(args[i].get_type()));
+
+ };
+
+ env->DeleteLocalRef(methods);
+
+ jobjectArray fields = (jobjectArray)env->CallObjectMethod(bclass, getFields);
+
+ count = env->GetArrayLength(fields);
+
+ for (int i=0; i<count; i++) {
+
+ jobject obj = env->GetObjectArrayElement(fields, i);
+ ERR_CONTINUE(!obj);
+
+ jstring name = (jstring)env->CallObjectMethod(obj, Field_getName);
+ String str_field = env->GetStringUTFChars( name, NULL );
+ env->DeleteLocalRef(name);
+ print_line("FIELD: "+str_field);
+ int mods = env->CallIntMethod(obj,Field_getModifiers);
+ if ((mods&0x8) && (mods&0x10) && (mods&0x1)) { //static final public!
+
+ jobject objc = env->CallObjectMethod(obj, Field_get,NULL);
+ if (objc) {
+
+
+ uint32_t sig;
+ String strsig;
+ jclass cl = env->GetObjectClass(objc);
+ if (JavaClassWrapper::_get_type_sig(env,cl,sig,strsig)) {
+
+ if ((sig&JavaClass::ARG_TYPE_MASK)<=JavaClass::ARG_TYPE_STRING) {
+
+ Variant value;
+ if (JavaClass::_convert_object_to_variant(env,objc,value,sig)) {
+
+ java_class->constant_map[str_field]=value;
+ }
+ }
+ }
+
+ env->DeleteLocalRef(cl);
+ }
+
+
+ env->DeleteLocalRef(objc);
+
+ }
+ env->DeleteLocalRef(obj);
+ }
+
+ env->DeleteLocalRef(fields);
+
+
+ return Ref<JavaClass>();
+}
+
+JavaClassWrapper *JavaClassWrapper::singleton=NULL;
+
+JavaClassWrapper::JavaClassWrapper(jobject p_activity) {
+
+ singleton=this;
+
+ JNIEnv *env = ThreadAndroid::get_env();
+
+ jclass activityClass = env->FindClass("com/android/godot/Godot");
+ jmethodID getClassLoader = env->GetMethodID(activityClass,"getClassLoader", "()Ljava/lang/ClassLoader;");
+ classLoader = env->CallObjectMethod(p_activity, getClassLoader);
+ classLoader=(jclass)env->NewGlobalRef(classLoader);
+ jclass classLoaderClass = env->FindClass("java/lang/ClassLoader");
+ findClass = env->GetMethodID(classLoaderClass, "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;");
+
+ jclass bclass = env->FindClass("java/lang/Class");
+ getDeclaredMethods = env->GetMethodID(bclass,"getDeclaredMethods", "()[Ljava/lang/reflect/Method;");
+ getFields = env->GetMethodID(bclass,"getFields", "()[Ljava/lang/reflect/Field;");
+ Class_getName = env->GetMethodID(bclass,"getName", "()Ljava/lang/String;");
+ //
+ bclass = env->FindClass("java/lang/reflect/Method");
+ getParameterTypes = env->GetMethodID(bclass,"getParameterTypes", "()[Ljava/lang/Class;");
+ getReturnType = env->GetMethodID(bclass,"getReturnType", "()Ljava/lang/Class;");
+ getName = env->GetMethodID(bclass,"getName", "()Ljava/lang/String;");
+ getModifiers = env->GetMethodID(bclass,"getModifiers", "()I");
+ ///
+ bclass = env->FindClass("java/lang/reflect/Field");
+ Field_getName = env->GetMethodID(bclass,"getName", "()Ljava/lang/String;");
+ Field_getModifiers = env->GetMethodID(bclass,"getModifiers", "()I");
+ Field_get = env->GetMethodID(bclass,"get", "(Ljava/lang/Object;)Ljava/lang/Object;");
+ // each
+ bclass = env->FindClass("java/lang/Boolean");
+ Boolean_booleanValue = env->GetMethodID(bclass, "booleanValue", "()Z");
+
+ bclass = env->FindClass("java/lang/Byte");
+ Byte_byteValue = env->GetMethodID(bclass, "byteValue", "()B");
+
+ bclass = env->FindClass("java/lang/Character");
+ Character_characterValue = env->GetMethodID(bclass, "charValue", "()C");
+
+ bclass = env->FindClass("java/lang/Short");
+ Short_shortValue = env->GetMethodID(bclass, "shortValue", "()S");
+
+ bclass = env->FindClass("java/lang/Integer");
+ Integer_integerValue = env->GetMethodID(bclass, "intValue", "()I");
+
+ bclass = env->FindClass("java/lang/Long");
+ Long_longValue = env->GetMethodID(bclass, "longValue", "()J");
+
+ bclass = env->FindClass("java/lang/Float");
+ Float_floatValue = env->GetMethodID(bclass, "floatValue", "()F");
+
+ bclass = env->FindClass("java/lang/Double");
+ Double_doubleValue = env->GetMethodID(bclass, "doubleValue", "()D");
+
+
+}
diff --git a/platform/android/java_class_wrapper.h b/platform/android/java_class_wrapper.h
new file mode 100644
index 0000000000..d5d8bd5be8
--- /dev/null
+++ b/platform/android/java_class_wrapper.h
@@ -0,0 +1,168 @@
+#ifndef JAVA_CLASS_WRAPPER_H
+#define JAVA_CLASS_WRAPPER_H
+
+#include "reference.h"
+#include <jni.h>
+#include <android/log.h>
+
+class JavaObject;
+
+class JavaClass : public Reference {
+
+ OBJ_TYPE(JavaClass,Reference);
+
+ enum ArgumentType {
+
+ ARG_TYPE_VOID,
+ ARG_TYPE_BOOLEAN,
+ ARG_TYPE_BYTE,
+ ARG_TYPE_CHAR,
+ ARG_TYPE_SHORT,
+ ARG_TYPE_INT,
+ ARG_TYPE_LONG,
+ ARG_TYPE_FLOAT,
+ ARG_TYPE_DOUBLE,
+ ARG_TYPE_STRING, //special case
+ ARG_TYPE_CLASS,
+ ARG_ARRAY_BIT=1<<16,
+ ARG_NUMBER_CLASS_BIT=1<<17,
+ ARG_TYPE_MASK=(1<<16)-1
+ };
+
+
+ Map<StringName,Variant> constant_map;
+
+ struct MethodInfo {
+
+ bool _static;
+ Vector<uint32_t> param_types;
+ Vector<StringName> param_sigs;
+ uint32_t return_type;
+ jmethodID method;
+
+ };
+
+ _FORCE_INLINE_ static void _convert_to_variant_type(int p_sig, Variant::Type& r_type, float& likelyhood) {
+
+ likelyhood=1.0;
+ r_type=Variant::NIL;
+
+ switch(p_sig) {
+
+ case ARG_TYPE_VOID: r_type=Variant::NIL; break;
+ case ARG_TYPE_BOOLEAN|ARG_NUMBER_CLASS_BIT:
+ case ARG_TYPE_BOOLEAN: r_type=Variant::BOOL; break;
+ case ARG_TYPE_BYTE|ARG_NUMBER_CLASS_BIT:
+ case ARG_TYPE_BYTE: r_type=Variant::INT; likelyhood=0.1; break;
+ case ARG_TYPE_CHAR|ARG_NUMBER_CLASS_BIT:
+ case ARG_TYPE_CHAR: r_type=Variant::INT; likelyhood=0.2; break;
+ case ARG_TYPE_SHORT|ARG_NUMBER_CLASS_BIT:
+ case ARG_TYPE_SHORT: r_type=Variant::INT; likelyhood=0.3; break;
+ case ARG_TYPE_INT|ARG_NUMBER_CLASS_BIT:
+ case ARG_TYPE_INT: r_type=Variant::INT; likelyhood=1.0; break;
+ case ARG_TYPE_LONG|ARG_NUMBER_CLASS_BIT:
+ case ARG_TYPE_LONG: r_type=Variant::INT; likelyhood=0.5; break;
+ case ARG_TYPE_FLOAT|ARG_NUMBER_CLASS_BIT:
+ case ARG_TYPE_FLOAT: r_type=Variant::REAL; likelyhood=1.0; break;
+ case ARG_TYPE_DOUBLE|ARG_NUMBER_CLASS_BIT:
+ case ARG_TYPE_DOUBLE: r_type=Variant::REAL; likelyhood=0.5; break;
+ case ARG_TYPE_STRING: r_type=Variant::STRING; break;
+ case ARG_TYPE_CLASS: r_type=Variant::OBJECT; break;
+ case ARG_ARRAY_BIT|ARG_TYPE_VOID: r_type=Variant::NIL; break;
+ case ARG_ARRAY_BIT|ARG_TYPE_BOOLEAN: r_type=Variant::ARRAY; break;
+ case ARG_ARRAY_BIT|ARG_TYPE_BYTE: r_type=Variant::RAW_ARRAY; likelyhood=1.0; break;
+ case ARG_ARRAY_BIT|ARG_TYPE_CHAR: r_type=Variant::RAW_ARRAY; likelyhood=0.5; break;
+ case ARG_ARRAY_BIT|ARG_TYPE_SHORT: r_type=Variant::INT_ARRAY; likelyhood=0.3; break;
+ case ARG_ARRAY_BIT|ARG_TYPE_INT: r_type=Variant::INT_ARRAY; likelyhood=1.0; break;
+ case ARG_ARRAY_BIT|ARG_TYPE_LONG: r_type=Variant::INT_ARRAY; likelyhood=0.5; break;
+ case ARG_ARRAY_BIT|ARG_TYPE_FLOAT: r_type=Variant::REAL_ARRAY; likelyhood=1.0; break;
+ case ARG_ARRAY_BIT|ARG_TYPE_DOUBLE: r_type=Variant::REAL_ARRAY; likelyhood=0.5; break;
+ case ARG_ARRAY_BIT|ARG_TYPE_STRING: r_type=Variant::STRING_ARRAY; break;
+ case ARG_ARRAY_BIT|ARG_TYPE_CLASS: r_type=Variant::ARRAY; break;
+ }
+ }
+
+ _FORCE_INLINE_ static bool _convert_object_to_variant(JNIEnv * env, jobject obj, Variant& var,uint32_t p_sig);
+
+
+
+ bool _call_method(JavaObject* p_instance,const StringName& p_method,const Variant** p_args,int p_argcount,Variant::CallError &r_error,Variant& ret);
+
+friend class JavaClassWrapper;
+ Map<StringName,List<MethodInfo> > methods;
+ jclass _class;
+
+public:
+
+ virtual Variant call(const StringName& p_method,const Variant** p_args,int p_argcount,Variant::CallError &r_error);
+
+ JavaClass();
+
+};
+
+
+class JavaObject : public Reference {
+
+ OBJ_TYPE(JavaObject,Reference);
+
+ Ref<JavaClass> base_class;
+friend class JavaClass;
+
+ jobject instance;
+
+public:
+
+ virtual Variant call(const StringName& p_method,const Variant** p_args,int p_argcount,Variant::CallError &r_error);
+
+ JavaObject(const Ref<JavaClass>& p_base,jobject *p_instance);
+ ~JavaObject();
+
+};
+
+
+class JavaClassWrapper : public Object {
+
+ OBJ_TYPE(JavaClassWrapper,Object);
+
+
+ Map<String,Ref<JavaClass> > class_cache;
+friend class JavaClass;
+ jclass activityClass;
+ jmethodID findClass;
+ jmethodID getDeclaredMethods;
+ jmethodID getFields;
+ jmethodID getParameterTypes;
+ jmethodID getReturnType;
+ jmethodID getModifiers;
+ jmethodID getName;
+ jmethodID Class_getName;
+ jmethodID Field_getName;
+ jmethodID Field_getModifiers;
+ jmethodID Field_get;
+ jmethodID Boolean_booleanValue;
+ jmethodID Byte_byteValue;
+ jmethodID Character_characterValue;
+ jmethodID Short_shortValue;
+ jmethodID Integer_integerValue;
+ jmethodID Long_longValue;
+ jmethodID Float_floatValue;
+ jmethodID Double_doubleValue;
+ jobject classLoader;
+
+ bool _get_type_sig(JNIEnv *env, jobject obj, uint32_t& sig, String&strsig);
+
+ static JavaClassWrapper *singleton;
+
+protected:
+
+ static void _bind_methods();
+public:
+
+ static JavaClassWrapper *get_singleton() { return singleton; }
+
+ Ref<JavaClass> wrap(const String& p_class);
+
+ JavaClassWrapper(jobject p_activity=NULL);
+};
+
+#endif // JAVA_CLASS_WRAPPER_H
diff --git a/platform/android/java_glue.cpp b/platform/android/java_glue.cpp
index e67388b6f5..fdc6f1207d 100644
--- a/platform/android/java_glue.cpp
+++ b/platform/android/java_glue.cpp
@@ -38,7 +38,10 @@
#include "globals.h"
#include "thread_jandroid.h"
#include "core/os/keyboard.h"
+#include "java_class_wrapper.h"
+
+static JavaClassWrapper *java_class_wrapper=NULL;
static OS_Android *os_android=NULL;
@@ -753,7 +756,7 @@ JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_initialize(JNIEnv * env,
int cmdlen=0;
bool use_apk_expansion=false;
if (p_cmdline) {
- int cmdlen = env->GetArrayLength(p_cmdline);
+ cmdlen = env->GetArrayLength(p_cmdline);
if (cmdlen) {
cmdline = (const char**)malloc((env->GetArrayLength(p_cmdline)+1)*sizeof(const char*));
cmdline[cmdlen]=NULL;
@@ -776,6 +779,8 @@ JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_initialize(JNIEnv * env,
}
}
+ __android_log_print(ANDROID_LOG_INFO,"godot","CMDLINE LEN %i - APK EXPANSION %I\n",cmdlen,int(use_apk_expansion));
+
os_android = new OS_Android(_gfx_init_func,env,_open_uri,_get_data_dir,_get_locale, _get_model,_show_vk, _hide_vk,_set_screen_orient,_get_unique_id, _play_video, _is_video_playing, _pause_video, _stop_video,use_apk_expansion);
os_android->set_need_reload_hooks(p_need_reload_hook);
@@ -932,6 +937,8 @@ JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_step(JNIEnv * env, jobjec
// ugly hack to initialize the rest of the engine
// because of the way android forces you to do everything with threads
+ java_class_wrapper = memnew( JavaClassWrapper(_godot_instance ));
+ Globals::get_singleton()->add_singleton(Globals::Singleton("JavaClassWrapper",java_class_wrapper));
_initialize_java_modules();
Main::setup2();
@@ -1552,7 +1559,9 @@ JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_callobject(JNIEnv * env,
for (int i=0; i<count; i++) {
jobject obj = env->GetObjectArrayElement(params, i);
- Variant v = _jobject_to_variant(env, obj);
+ Variant v;
+ if (obj)
+ v=_jobject_to_variant(env, obj);
memnew_placement(&vlist[i], Variant);
vlist[i] = v;
vptr[i] = &vlist[i];
@@ -1573,13 +1582,14 @@ JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_calldeferred(JNIEnv * env
int count = env->GetArrayLength(params);
Variant args[VARIANT_ARG_MAX];
- print_line("Java->GD call: "+obj->get_type()+"::"+str_method+" argc "+itos(count));
+// print_line("Java->GD call: "+obj->get_type()+"::"+str_method+" argc "+itos(count));
for (int i=0; i<MIN(count,VARIANT_ARG_MAX); i++) {
jobject obj = env->GetObjectArrayElement(params, i);
- args[i] = _jobject_to_variant(env, obj);
- print_line("\targ"+itos(i)+": "+Variant::get_type_name(args[i].get_type()));
+ if (obj)
+ args[i] = _jobject_to_variant(env, obj);
+// print_line("\targ"+itos(i)+": "+Variant::get_type_name(args[i].get_type()));
};
diff --git a/platform/android/libs/downloader_library/.classpath b/platform/android/libs/downloader_library/.classpath
new file mode 100644
index 0000000000..7bc01d9a9c
--- /dev/null
+++ b/platform/android/libs/downloader_library/.classpath
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="src" path="gen"/>
+ <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
+ <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
+ <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
+ <classpathentry kind="output" path="bin/classes"/>
+</classpath>
diff --git a/platform/android/libs/downloader_library/.settings/org.eclipse.jdt.core.prefs b/platform/android/libs/downloader_library/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000000..b080d2ddc8
--- /dev/null
+++ b/platform/android/libs/downloader_library/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,4 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.source=1.6
diff --git a/platform/android/libs/downloader_library/AndroidManifest.xml b/platform/android/libs/downloader_library/AndroidManifest.xml
new file mode 100644
index 0000000000..20b74a2988
--- /dev/null
+++ b/platform/android/libs/downloader_library/AndroidManifest.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.vending.expansion.downloader"
+ android:versionCode="2"
+ android:versionName="1.1" >
+
+ <uses-sdk android:minSdkVersion="4" android:targetSdkVersion="15"/>
+
+</manifest> \ No newline at end of file
diff --git a/platform/android/libs/downloader_library/build.xml b/platform/android/libs/downloader_library/build.xml
new file mode 100644
index 0000000000..d65c145148
--- /dev/null
+++ b/platform/android/libs/downloader_library/build.xml
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project name="downloader_library" default="help">
+
+ <!-- The local.properties file is created and updated by the 'android' tool.
+ It contains the path to the SDK. It should *NOT* be checked into
+ Version Control Systems. -->
+ <property file="local.properties" />
+
+ <!-- The ant.properties file can be created by you. It is only edited by the
+ 'android' tool to add properties to it.
+ This is the place to change some Ant specific build properties.
+ Here are some properties you may want to change/update:
+
+ source.dir
+ The name of the source directory. Default is 'src'.
+ out.dir
+ The name of the output directory. Default is 'bin'.
+
+ For other overridable properties, look at the beginning of the rules
+ files in the SDK, at tools/ant/build.xml
+
+ Properties related to the SDK location or the project target should
+ be updated using the 'android' tool with the 'update' action.
+
+ This file is an integral part of the build system for your
+ application and should be checked into Version Control Systems.
+
+ -->
+ <property file="ant.properties" />
+
+ <!-- if sdk.dir was not set from one of the property file, then
+ get it from the ANDROID_HOME env var.
+ This must be done before we load project.properties since
+ the proguard config can use sdk.dir -->
+ <property environment="env" />
+ <condition property="sdk.dir" value="${env.ANDROID_HOME}">
+ <isset property="env.ANDROID_HOME" />
+ </condition>
+
+ <!-- The project.properties file is created and updated by the 'android'
+ tool, as well as ADT.
+
+ This contains project specific properties such as project target, and library
+ dependencies. Lower level build properties are stored in ant.properties
+ (or in .classpath for Eclipse projects).
+
+ This file is an integral part of the build system for your
+ application and should be checked into Version Control Systems. -->
+ <loadproperties srcFile="project.properties" />
+
+ <!-- quick check on sdk.dir -->
+ <fail
+ message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through the ANDROID_HOME environment variable."
+ unless="sdk.dir"
+ />
+
+ <!--
+ Import per project custom build rules if present at the root of the project.
+ This is the place to put custom intermediary targets such as:
+ -pre-build
+ -pre-compile
+ -post-compile (This is typically used for code obfuscation.
+ Compiled code location: ${out.classes.absolute.dir}
+ If this is not done in place, override ${out.dex.input.absolute.dir})
+ -post-package
+ -post-build
+ -pre-clean
+ -->
+ <import file="custom_rules.xml" optional="true" />
+
+ <!-- Import the actual build file.
+
+ To customize existing targets, there are two options:
+ - Customize only one target:
+ - copy/paste the target into this file, *before* the
+ <import> task.
+ - customize it to your needs.
+ - Customize the whole content of build.xml
+ - copy/paste the content of the rules files (minus the top node)
+ into this file, replacing the <import> task.
+ - customize to your needs.
+
+ ***********************
+ ****** IMPORTANT ******
+ ***********************
+ In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
+ in order to avoid having your file be overridden by tools such as "android update project"
+ -->
+ <!-- version-tag: 1 -->
+ <import file="${sdk.dir}/tools/ant/build.xml" />
+
+</project>
diff --git a/platform/android/libs/downloader_library/gen/com/android/vending/expansion/downloader/BuildConfig.java b/platform/android/libs/downloader_library/gen/com/android/vending/expansion/downloader/BuildConfig.java
new file mode 100644
index 0000000000..da9d06e63c
--- /dev/null
+++ b/platform/android/libs/downloader_library/gen/com/android/vending/expansion/downloader/BuildConfig.java
@@ -0,0 +1,6 @@
+/** Automatically generated file. DO NOT MODIFY */
+package com.android.vending.expansion.downloader;
+
+public final class BuildConfig {
+ public final static boolean DEBUG = false;
+} \ No newline at end of file
diff --git a/platform/android/libs/downloader_library/gen/com/android/vending/expansion/downloader/R.java b/platform/android/libs/downloader_library/gen/com/android/vending/expansion/downloader/R.java
new file mode 100644
index 0000000000..330aed1856
--- /dev/null
+++ b/platform/android/libs/downloader_library/gen/com/android/vending/expansion/downloader/R.java
@@ -0,0 +1,73 @@
+/* AUTO-GENERATED FILE. DO NOT MODIFY.
+ *
+ * This class was automatically generated by the
+ * aapt tool from the resource data it found. It
+ * should not be modified by hand.
+ */
+
+package com.android.vending.expansion.downloader;
+
+public final class R {
+ public static final class attr {
+ }
+ public static final class drawable {
+ public static int notify_panel_notification_icon_bg=0x7f020000;
+ }
+ public static final class id {
+ public static int appIcon=0x7f060001;
+ public static int description=0x7f060007;
+ public static int notificationLayout=0x7f060000;
+ public static int progress_bar=0x7f060006;
+ public static int progress_bar_frame=0x7f060005;
+ public static int progress_text=0x7f060002;
+ public static int time_remaining=0x7f060004;
+ public static int title=0x7f060003;
+ }
+ public static final class layout {
+ public static int status_bar_ongoing_event_progress_bar=0x7f030000;
+ }
+ public static final class string {
+ public static int kilobytes_per_second=0x7f040014;
+ /** When a download completes, a notification is displayed, and this
+ string is used to indicate that the download successfully completed.
+ Note that such a download could have been initiated by a variety of
+ applications, including (but not limited to) the browser, an email
+ application, a content marketplace.
+ */
+ public static int notification_download_complete=0x7f040000;
+ /** When a download completes, a notification is displayed, and this
+ string is used to indicate that the download failed.
+ Note that such a download could have been initiated by a variety of
+ applications, including (but not limited to) the browser, an email
+ application, a content marketplace.
+ */
+ public static int notification_download_failed=0x7f040001;
+ public static int state_completed=0x7f040007;
+ public static int state_connecting=0x7f040005;
+ public static int state_downloading=0x7f040006;
+ public static int state_failed=0x7f040013;
+ public static int state_failed_cancelled=0x7f040012;
+ public static int state_failed_fetching_url=0x7f040010;
+ public static int state_failed_sdcard_full=0x7f040011;
+ public static int state_failed_unlicensed=0x7f04000f;
+ public static int state_fetching_url=0x7f040004;
+ public static int state_idle=0x7f040003;
+ public static int state_paused_by_request=0x7f04000a;
+ public static int state_paused_network_setup_failure=0x7f040009;
+ public static int state_paused_network_unavailable=0x7f040008;
+ public static int state_paused_roaming=0x7f04000d;
+ public static int state_paused_sdcard_unavailable=0x7f04000e;
+ public static int state_paused_wifi_disabled=0x7f04000c;
+ public static int state_paused_wifi_unavailable=0x7f04000b;
+ public static int state_unknown=0x7f040002;
+ public static int time_remaining=0x7f040015;
+ public static int time_remaining_notification=0x7f040016;
+ }
+ public static final class style {
+ public static int ButtonBackground=0x7f050003;
+ public static int NotificationText=0x7f050000;
+ public static int NotificationTextSecondary=0x7f050004;
+ public static int NotificationTextShadow=0x7f050001;
+ public static int NotificationTitle=0x7f050002;
+ }
+}
diff --git a/platform/android/libs/downloader_library/proguard-project.txt b/platform/android/libs/downloader_library/proguard-project.txt
new file mode 100644
index 0000000000..f2fe1559a2
--- /dev/null
+++ b/platform/android/libs/downloader_library/proguard-project.txt
@@ -0,0 +1,20 @@
+# To enable ProGuard in your project, edit project.properties
+# to define the proguard.config property as described in that file.
+#
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in ${sdk.dir}/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the ProGuard
+# include property in project.properties.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
diff --git a/platform/android/libs/downloader_library/project.properties b/platform/android/libs/downloader_library/project.properties
new file mode 100644
index 0000000000..eda83430bf
--- /dev/null
+++ b/platform/android/libs/downloader_library/project.properties
@@ -0,0 +1,13 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system use,
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+
+# Project target.
+target=android-15
+android.library=true
+android.library.reference.1=../play_licensing
diff --git a/platform/android/libs/downloader_library/res/drawable-hdpi/notify_panel_notification_icon_bg.png b/platform/android/libs/downloader_library/res/drawable-hdpi/notify_panel_notification_icon_bg.png
new file mode 100644
index 0000000000..f5b762ecf3
--- /dev/null
+++ b/platform/android/libs/downloader_library/res/drawable-hdpi/notify_panel_notification_icon_bg.png
Binary files differ
diff --git a/platform/android/libs/downloader_library/res/drawable-mdpi/notify_panel_notification_icon_bg.png b/platform/android/libs/downloader_library/res/drawable-mdpi/notify_panel_notification_icon_bg.png
new file mode 100644
index 0000000000..9ecb8af06c
--- /dev/null
+++ b/platform/android/libs/downloader_library/res/drawable-mdpi/notify_panel_notification_icon_bg.png
Binary files differ
diff --git a/platform/android/libs/downloader_library/res/layout/status_bar_ongoing_event_progress_bar.xml b/platform/android/libs/downloader_library/res/layout/status_bar_ongoing_event_progress_bar.xml
new file mode 100644
index 0000000000..23bac02294
--- /dev/null
+++ b/platform/android/libs/downloader_library/res/layout/status_bar_ongoing_event_progress_bar.xml
@@ -0,0 +1,104 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2008, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<LinearLayout android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:baselineAligned="false"
+ android:orientation="horizontal" android:id="@+id/notificationLayout" xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <RelativeLayout
+ android:layout_width="35dp"
+ android:layout_height="fill_parent"
+ android:paddingTop="10dp"
+ android:paddingBottom="8dp" >
+
+ <ImageView
+ android:id="@+id/appIcon"
+ android:layout_width="fill_parent"
+ android:layout_height="25dp"
+ android:scaleType="centerInside"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentTop="true"
+ android:src="@android:drawable/stat_sys_download" />
+
+ <TextView
+ android:id="@+id/progress_text"
+ style="@style/NotificationText"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentBottom="true"
+ android:layout_gravity="center_horizontal"
+ android:singleLine="true"
+ android:gravity="center" />
+ </RelativeLayout>
+
+ <RelativeLayout
+ android:layout_width="0dip"
+ android:layout_height="match_parent"
+ android:layout_weight="1.0"
+ android:clickable="true"
+ android:focusable="true"
+ android:paddingTop="10dp"
+ android:paddingRight="8dp"
+ android:paddingBottom="8dp" >
+
+ <TextView
+ android:id="@+id/title"
+ style="@style/NotificationTitle"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentLeft="true"
+ android:singleLine="true"/>
+
+ <TextView
+ android:id="@+id/time_remaining"
+ style="@style/NotificationText"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentRight="true"
+ android:singleLine="true"/>
+ <!-- Only one of progress_bar and paused_text will be visible. -->
+
+ <FrameLayout
+ android:id="@+id/progress_bar_frame"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_alignParentBottom="true" >
+
+ <ProgressBar
+ android:id="@+id/progress_bar"
+ style="?android:attr/progressBarStyleHorizontal"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:paddingRight="25dp" />
+
+ <TextView
+ android:id="@+id/description"
+ style="@style/NotificationTextShadow"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:paddingRight="25dp"
+ android:singleLine="true" />
+ </FrameLayout>
+
+ </RelativeLayout>
+
+</LinearLayout> \ No newline at end of file
diff --git a/platform/android/libs/downloader_library/res/values-v11/styles.xml b/platform/android/libs/downloader_library/res/values-v11/styles.xml
new file mode 100644
index 0000000000..f2013bc0bf
--- /dev/null
+++ b/platform/android/libs/downloader_library/res/values-v11/styles.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <style name="NotificationTextSecondary" parent="NotificationText">
+ <item name="android:textSize">12sp</item>
+ </style>
+</resources> \ No newline at end of file
diff --git a/platform/android/libs/downloader_library/res/values-v9/styles.xml b/platform/android/libs/downloader_library/res/values-v9/styles.xml
new file mode 100644
index 0000000000..736e77a5d6
--- /dev/null
+++ b/platform/android/libs/downloader_library/res/values-v9/styles.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <style name="NotificationText" parent="android:TextAppearance.StatusBar.EventContent" />
+ <style name="NotificationTitle" parent="android:TextAppearance.StatusBar.EventContent.Title" />
+</resources> \ No newline at end of file
diff --git a/platform/android/libs/downloader_library/res/values/strings.xml b/platform/android/libs/downloader_library/res/values/strings.xml
new file mode 100644
index 0000000000..b84749faf2
--- /dev/null
+++ b/platform/android/libs/downloader_library/res/values/strings.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+ <!-- When a download completes, a notification is displayed, and this
+ string is used to indicate that the download successfully completed.
+ Note that such a download could have been initiated by a variety of
+ applications, including (but not limited to) the browser, an email
+ application, a content marketplace. -->
+ <string name="notification_download_complete">Download complete</string>
+
+ <!-- When a download completes, a notification is displayed, and this
+ string is used to indicate that the download failed.
+ Note that such a download could have been initiated by a variety of
+ applications, including (but not limited to) the browser, an email
+ application, a content marketplace. -->
+ <string name="notification_download_failed">Download unsuccessful</string>
+
+
+ <string name="state_unknown">Starting..."</string>
+ <string name="state_idle">Waiting for download to start</string>
+ <string name="state_fetching_url">Looking for resources to download</string>
+ <string name="state_connecting">Connecting to the download server</string>
+ <string name="state_downloading">Downloading resources</string>
+ <string name="state_completed">Download finished</string>
+ <string name="state_paused_network_unavailable">Download paused because no network is available</string>
+ <string name="state_paused_network_setup_failure">Download paused. Test a website in browser</string>
+ <string name="state_paused_by_request">Download paused</string>
+ <string name="state_paused_wifi_unavailable">Download paused because wifi is unavailable</string>
+ <string name="state_paused_wifi_disabled">Download paused because wifi is disabled</string>
+ <string name="state_paused_roaming">Download paused because you are roaming</string>
+ <string name="state_paused_sdcard_unavailable">Download paused because the external storage is unavailable</string>
+ <string name="state_failed_unlicensed">Download failed because you may not have purchased this app</string>
+ <string name="state_failed_fetching_url">Download failed because the resources could not be found</string>
+ <string name="state_failed_sdcard_full">Download failed because the external storage is full</string>
+ <string name="state_failed_cancelled">Download cancelled</string>
+ <string name="state_failed">Download failed</string>
+
+ <string name="kilobytes_per_second">%1$s KB/s</string>
+ <string name="time_remaining">Time remaining: %1$s</string>
+ <string name="time_remaining_notification">%1$s left</string>
+</resources> \ No newline at end of file
diff --git a/platform/android/libs/downloader_library/res/values/styles.xml b/platform/android/libs/downloader_library/res/values/styles.xml
new file mode 100644
index 0000000000..a442f61e7e
--- /dev/null
+++ b/platform/android/libs/downloader_library/res/values/styles.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+ <style name="NotificationText">
+ <item name="android:textColor">?android:attr/textColorPrimary</item>
+ </style>
+
+ <style name="NotificationTextShadow" parent="NotificationText">
+ <item name="android:textColor">?android:attr/textColorPrimary</item>
+ <item name="android:shadowColor">@android:color/background_dark</item>
+ <item name="android:shadowDx">1.0</item>
+ <item name="android:shadowDy">1.0</item>
+ <item name="android:shadowRadius">1</item>
+ </style>
+
+ <style name="NotificationTitle">
+ <item name="android:textColor">?android:attr/textColorPrimary</item>
+ <item name="android:textStyle">bold</item>
+ </style>
+
+ <style name="ButtonBackground">
+ <item name="android:background">@android:color/background_dark</item>
+ </style>
+
+</resources> \ No newline at end of file
diff --git a/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/Constants.java b/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/Constants.java
new file mode 100644
index 0000000000..ff2c6f535a
--- /dev/null
+++ b/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/Constants.java
@@ -0,0 +1,236 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.android.vending.expansion.downloader;
+
+import java.io.File;
+
+
+/**
+ * Contains the internal constants that are used in the download manager.
+ * As a general rule, modifying these constants should be done with care.
+ */
+public class Constants {
+ /** Tag used for debugging/logging */
+ public static final String TAG = "LVLDL";
+
+ /**
+ * Expansion path where we store obb files
+ */
+ public static final String EXP_PATH = File.separator + "Android"
+ + File.separator + "obb" + File.separator;
+
+ /** The intent that gets sent when the service must wake up for a retry */
+ public static final String ACTION_RETRY = "android.intent.action.DOWNLOAD_WAKEUP";
+
+ /** the intent that gets sent when clicking a successful download */
+ public static final String ACTION_OPEN = "android.intent.action.DOWNLOAD_OPEN";
+
+ /** the intent that gets sent when clicking an incomplete/failed download */
+ public static final String ACTION_LIST = "android.intent.action.DOWNLOAD_LIST";
+
+ /** the intent that gets sent when deleting the notification of a completed download */
+ public static final String ACTION_HIDE = "android.intent.action.DOWNLOAD_HIDE";
+
+ /**
+ * When a number has to be appended to the filename, this string is used to separate the
+ * base filename from the sequence number
+ */
+ public static final String FILENAME_SEQUENCE_SEPARATOR = "-";
+
+ /** The default user agent used for downloads */
+ public static final String DEFAULT_USER_AGENT = "Android.LVLDM";
+
+ /** The buffer size used to stream the data */
+ public static final int BUFFER_SIZE = 4096;
+
+ /** The minimum amount of progress that has to be done before the progress bar gets updated */
+ public static final int MIN_PROGRESS_STEP = 4096;
+
+ /** The minimum amount of time that has to elapse before the progress bar gets updated, in ms */
+ public static final long MIN_PROGRESS_TIME = 1000;
+
+ /** The maximum number of rows in the database (FIFO) */
+ public static final int MAX_DOWNLOADS = 1000;
+
+ /**
+ * The number of times that the download manager will retry its network
+ * operations when no progress is happening before it gives up.
+ */
+ public static final int MAX_RETRIES = 5;
+
+ /**
+ * The minimum amount of time that the download manager accepts for
+ * a Retry-After response header with a parameter in delta-seconds.
+ */
+ public static final int MIN_RETRY_AFTER = 30; // 30s
+
+ /**
+ * The maximum amount of time that the download manager accepts for
+ * a Retry-After response header with a parameter in delta-seconds.
+ */
+ public static final int MAX_RETRY_AFTER = 24 * 60 * 60; // 24h
+
+ /**
+ * The maximum number of redirects.
+ */
+ public static final int MAX_REDIRECTS = 5; // can't be more than 7.
+
+ /**
+ * The time between a failure and the first retry after an IOException.
+ * Each subsequent retry grows exponentially, doubling each time.
+ * The time is in seconds.
+ */
+ public static final int RETRY_FIRST_DELAY = 30;
+
+ /** Enable separate connectivity logging */
+ public static final boolean LOGX = true;
+
+ /** Enable verbose logging */
+ public static final boolean LOGV = false;
+
+ /** Enable super-verbose logging */
+ private static final boolean LOCAL_LOGVV = false;
+ public static final boolean LOGVV = LOCAL_LOGVV && LOGV;
+
+ /**
+ * This download has successfully completed.
+ * Warning: there might be other status values that indicate success
+ * in the future.
+ * Use isSucccess() to capture the entire category.
+ */
+ public static final int STATUS_SUCCESS = 200;
+
+ /**
+ * This request couldn't be parsed. This is also used when processing
+ * requests with unknown/unsupported URI schemes.
+ */
+ public static final int STATUS_BAD_REQUEST = 400;
+
+ /**
+ * This download can't be performed because the content type cannot be
+ * handled.
+ */
+ public static final int STATUS_NOT_ACCEPTABLE = 406;
+
+ /**
+ * This download cannot be performed because the length cannot be
+ * determined accurately. This is the code for the HTTP error "Length
+ * Required", which is typically used when making requests that require
+ * a content length but don't have one, and it is also used in the
+ * client when a response is received whose length cannot be determined
+ * accurately (therefore making it impossible to know when a download
+ * completes).
+ */
+ public static final int STATUS_LENGTH_REQUIRED = 411;
+
+ /**
+ * This download was interrupted and cannot be resumed.
+ * This is the code for the HTTP error "Precondition Failed", and it is
+ * also used in situations where the client doesn't have an ETag at all.
+ */
+ public static final int STATUS_PRECONDITION_FAILED = 412;
+
+ /**
+ * The lowest-valued error status that is not an actual HTTP status code.
+ */
+ public static final int MIN_ARTIFICIAL_ERROR_STATUS = 488;
+
+ /**
+ * The requested destination file already exists.
+ */
+ public static final int STATUS_FILE_ALREADY_EXISTS_ERROR = 488;
+
+ /**
+ * Some possibly transient error occurred, but we can't resume the download.
+ */
+ public static final int STATUS_CANNOT_RESUME = 489;
+
+ /**
+ * This download was canceled
+ */
+ public static final int STATUS_CANCELED = 490;
+
+ /**
+ * This download has completed with an error.
+ * Warning: there will be other status values that indicate errors in
+ * the future. Use isStatusError() to capture the entire category.
+ */
+ public static final int STATUS_UNKNOWN_ERROR = 491;
+
+ /**
+ * This download couldn't be completed because of a storage issue.
+ * Typically, that's because the filesystem is missing or full.
+ * Use the more specific {@link #STATUS_INSUFFICIENT_SPACE_ERROR}
+ * and {@link #STATUS_DEVICE_NOT_FOUND_ERROR} when appropriate.
+ */
+ public static final int STATUS_FILE_ERROR = 492;
+
+ /**
+ * This download couldn't be completed because of an HTTP
+ * redirect response that the download manager couldn't
+ * handle.
+ */
+ public static final int STATUS_UNHANDLED_REDIRECT = 493;
+
+ /**
+ * This download couldn't be completed because of an
+ * unspecified unhandled HTTP code.
+ */
+ public static final int STATUS_UNHANDLED_HTTP_CODE = 494;
+
+ /**
+ * This download couldn't be completed because of an
+ * error receiving or processing data at the HTTP level.
+ */
+ public static final int STATUS_HTTP_DATA_ERROR = 495;
+
+ /**
+ * This download couldn't be completed because of an
+ * HttpException while setting up the request.
+ */
+ public static final int STATUS_HTTP_EXCEPTION = 496;
+
+ /**
+ * This download couldn't be completed because there were
+ * too many redirects.
+ */
+ public static final int STATUS_TOO_MANY_REDIRECTS = 497;
+
+ /**
+ * This download couldn't be completed due to insufficient storage
+ * space. Typically, this is because the SD card is full.
+ */
+ public static final int STATUS_INSUFFICIENT_SPACE_ERROR = 498;
+
+ /**
+ * This download couldn't be completed because no external storage
+ * device was found. Typically, this is because the SD card is not
+ * mounted.
+ */
+ public static final int STATUS_DEVICE_NOT_FOUND_ERROR = 499;
+
+ /**
+ * The wake duration to check to see if a download is possible.
+ */
+ public static final long WATCHDOG_WAKE_TIMER = 60*1000;
+
+ /**
+ * The wake duration to check to see if the process was killed.
+ */
+ public static final long ACTIVE_THREAD_WATCHDOG = 5*1000;
+
+} \ No newline at end of file
diff --git a/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/DownloadProgressInfo.java b/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/DownloadProgressInfo.java
new file mode 100644
index 0000000000..9cb294d721
--- /dev/null
+++ b/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/DownloadProgressInfo.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.android.vending.expansion.downloader;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+
+/**
+ * This class contains progress information about the active download(s).
+ *
+ * When you build the Activity that initiates a download and tracks the
+ * progress by implementing the {@link IDownloaderClient} interface, you'll
+ * receive a DownloadProgressInfo object in each call to the {@link
+ * IDownloaderClient#onDownloadProgress} method. This allows you to update
+ * your activity's UI with information about the download progress, such
+ * as the progress so far, time remaining and current speed.
+ */
+public class DownloadProgressInfo implements Parcelable {
+ public long mOverallTotal;
+ public long mOverallProgress;
+ public long mTimeRemaining; // time remaining
+ public float mCurrentSpeed; // speed in KB/S
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel p, int i) {
+ p.writeLong(mOverallTotal);
+ p.writeLong(mOverallProgress);
+ p.writeLong(mTimeRemaining);
+ p.writeFloat(mCurrentSpeed);
+ }
+
+ public DownloadProgressInfo(Parcel p) {
+ mOverallTotal = p.readLong();
+ mOverallProgress = p.readLong();
+ mTimeRemaining = p.readLong();
+ mCurrentSpeed = p.readFloat();
+ }
+
+ public DownloadProgressInfo(long overallTotal, long overallProgress,
+ long timeRemaining,
+ float currentSpeed) {
+ this.mOverallTotal = overallTotal;
+ this.mOverallProgress = overallProgress;
+ this.mTimeRemaining = timeRemaining;
+ this.mCurrentSpeed = currentSpeed;
+ }
+
+ public static final Creator<DownloadProgressInfo> CREATOR = new Creator<DownloadProgressInfo>() {
+ @Override
+ public DownloadProgressInfo createFromParcel(Parcel parcel) {
+ return new DownloadProgressInfo(parcel);
+ }
+
+ @Override
+ public DownloadProgressInfo[] newArray(int i) {
+ return new DownloadProgressInfo[i];
+ }
+ };
+
+}
diff --git a/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/DownloaderClientMarshaller.java b/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/DownloaderClientMarshaller.java
new file mode 100644
index 0000000000..2201751254
--- /dev/null
+++ b/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/DownloaderClientMarshaller.java
@@ -0,0 +1,277 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.android.vending.expansion.downloader;
+
+import com.google.android.vending.expansion.downloader.impl.DownloaderService;
+
+import android.app.PendingIntent;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.Messenger;
+import android.os.RemoteException;
+import android.util.Log;
+
+
+
+/**
+ * This class binds the service API to your application client. It contains the IDownloaderClient proxy,
+ * which is used to call functions in your client as well as the Stub, which is used to call functions
+ * in the client implementation of IDownloaderClient.
+ *
+ * <p>The IPC is implemented using an Android Messenger and a service Binder. The connect method
+ * should be called whenever the client wants to bind to the service. It opens up a service connection
+ * that ends up calling the onServiceConnected client API that passes the service messenger
+ * in. If the client wants to be notified by the service, it is responsible for then passing its
+ * messenger to the service in a separate call.
+ *
+ * <p>Critical methods are {@link #startDownloadServiceIfRequired} and {@link #CreateStub}.
+ *
+ * <p>When your application first starts, you should first check whether your app's expansion files are
+ * already on the device. If not, you should then call {@link #startDownloadServiceIfRequired}, which
+ * starts your {@link impl.DownloaderService} to download the expansion files if necessary. The method
+ * returns a value indicating whether download is required or not.
+ *
+ * <p>If a download is required, {@link #startDownloadServiceIfRequired} begins the download through
+ * the specified service and you should then call {@link #CreateStub} to instantiate a member {@link
+ * IStub} object that you need in order to receive calls through your {@link IDownloaderClient}
+ * interface.
+ */
+public class DownloaderClientMarshaller {
+ public static final int MSG_ONDOWNLOADSTATE_CHANGED = 10;
+ public static final int MSG_ONDOWNLOADPROGRESS = 11;
+ public static final int MSG_ONSERVICECONNECTED = 12;
+
+ public static final String PARAM_NEW_STATE = "newState";
+ public static final String PARAM_PROGRESS = "progress";
+ public static final String PARAM_MESSENGER = DownloaderService.EXTRA_MESSAGE_HANDLER;
+
+ public static final int NO_DOWNLOAD_REQUIRED = DownloaderService.NO_DOWNLOAD_REQUIRED;
+ public static final int LVL_CHECK_REQUIRED = DownloaderService.LVL_CHECK_REQUIRED;
+ public static final int DOWNLOAD_REQUIRED = DownloaderService.DOWNLOAD_REQUIRED;
+
+ private static class Proxy implements IDownloaderClient {
+ private Messenger mServiceMessenger;
+
+ @Override
+ public void onDownloadStateChanged(int newState) {
+ Bundle params = new Bundle(1);
+ params.putInt(PARAM_NEW_STATE, newState);
+ send(MSG_ONDOWNLOADSTATE_CHANGED, params);
+ }
+
+ @Override
+ public void onDownloadProgress(DownloadProgressInfo progress) {
+ Bundle params = new Bundle(1);
+ params.putParcelable(PARAM_PROGRESS, progress);
+ send(MSG_ONDOWNLOADPROGRESS, params);
+ }
+
+ private void send(int method, Bundle params) {
+ Message m = Message.obtain(null, method);
+ m.setData(params);
+ try {
+ mServiceMessenger.send(m);
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public Proxy(Messenger msg) {
+ mServiceMessenger = msg;
+ }
+
+ @Override
+ public void onServiceConnected(Messenger m) {
+ /**
+ * This is never called through the proxy.
+ */
+ }
+ }
+
+ private static class Stub implements IStub {
+ private IDownloaderClient mItf = null;
+ private Class<?> mDownloaderServiceClass;
+ private boolean mBound;
+ private Messenger mServiceMessenger;
+ private Context mContext;
+ /**
+ * Target we publish for clients to send messages to IncomingHandler.
+ */
+ final Messenger mMessenger = new Messenger(new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_ONDOWNLOADPROGRESS:
+ Bundle bun = msg.getData();
+ if ( null != mContext ) {
+ bun.setClassLoader(mContext.getClassLoader());
+ DownloadProgressInfo dpi = (DownloadProgressInfo) msg.getData()
+ .getParcelable(PARAM_PROGRESS);
+ mItf.onDownloadProgress(dpi);
+ }
+ break;
+ case MSG_ONDOWNLOADSTATE_CHANGED:
+ mItf.onDownloadStateChanged(msg.getData().getInt(PARAM_NEW_STATE));
+ break;
+ case MSG_ONSERVICECONNECTED:
+ mItf.onServiceConnected(
+ (Messenger) msg.getData().getParcelable(PARAM_MESSENGER));
+ break;
+ }
+ }
+ });
+
+ public Stub(IDownloaderClient itf, Class<?> downloaderService) {
+ mItf = itf;
+ mDownloaderServiceClass = downloaderService;
+ }
+
+ /**
+ * Class for interacting with the main interface of the service.
+ */
+ private ServiceConnection mConnection = new ServiceConnection() {
+ public void onServiceConnected(ComponentName className, IBinder service) {
+ // This is called when the connection with the service has been
+ // established, giving us the object we can use to
+ // interact with the service. We are communicating with the
+ // service using a Messenger, so here we get a client-side
+ // representation of that from the raw IBinder object.
+ mServiceMessenger = new Messenger(service);
+ mItf.onServiceConnected(
+ mServiceMessenger);
+ }
+
+ public void onServiceDisconnected(ComponentName className) {
+ // This is called when the connection with the service has been
+ // unexpectedly disconnected -- that is, its process crashed.
+ mServiceMessenger = null;
+ }
+ };
+
+ @Override
+ public void connect(Context c) {
+ mContext = c;
+ Intent bindIntent = new Intent(c, mDownloaderServiceClass);
+ bindIntent.putExtra(PARAM_MESSENGER, mMessenger);
+ if ( !c.bindService(bindIntent, mConnection, Context.BIND_DEBUG_UNBIND) ) {
+ if ( Constants.LOGVV ) {
+ Log.d(Constants.TAG, "Service Unbound");
+ }
+ } else {
+ mBound = true;
+ }
+
+ }
+
+ @Override
+ public void disconnect(Context c) {
+ if (mBound) {
+ c.unbindService(mConnection);
+ mBound = false;
+ }
+ mContext = null;
+ }
+
+ @Override
+ public Messenger getMessenger() {
+ return mMessenger;
+ }
+ }
+
+ /**
+ * Returns a proxy that will marshal calls to IDownloaderClient methods
+ *
+ * @param msg
+ * @return
+ */
+ public static IDownloaderClient CreateProxy(Messenger msg) {
+ return new Proxy(msg);
+ }
+
+ /**
+ * Returns a stub object that, when connected, will listen for marshaled
+ * {@link IDownloaderClient} methods and translate them into calls to the supplied
+ * interface.
+ *
+ * @param itf An implementation of IDownloaderClient that will be called
+ * when remote method calls are unmarshaled.
+ * @param downloaderService The class for your implementation of {@link
+ * impl.DownloaderService}.
+ * @return The {@link IStub} that allows you to connect to the service such that
+ * your {@link IDownloaderClient} receives status updates.
+ */
+ public static IStub CreateStub(IDownloaderClient itf, Class<?> downloaderService) {
+ return new Stub(itf, downloaderService);
+ }
+
+ /**
+ * Starts the download if necessary. This function starts a flow that does `
+ * many things. 1) Checks to see if the APK version has been checked and
+ * the metadata database updated 2) If the APK version does not match,
+ * checks the new LVL status to see if a new download is required 3) If the
+ * APK version does match, then checks to see if the download(s) have been
+ * completed 4) If the downloads have been completed, returns
+ * NO_DOWNLOAD_REQUIRED The idea is that this can be called during the
+ * startup of an application to quickly ascertain if the application needs
+ * to wait to hear about any updated APK expansion files. Note that this does
+ * mean that the application MUST be run for the first time with a network
+ * connection, even if Market delivers all of the files.
+ *
+ * @param context Your application Context.
+ * @param notificationClient A PendingIntent to start the Activity in your application
+ * that shows the download progress and which will also start the application when download
+ * completes.
+ * @param serviceClass the class of your {@link imp.DownloaderService} implementation
+ * @return whether the service was started and the reason for starting the service.
+ * Either {@link #NO_DOWNLOAD_REQUIRED}, {@link #LVL_CHECK_REQUIRED}, or {@link
+ * #DOWNLOAD_REQUIRED}.
+ * @throws NameNotFoundException
+ */
+ public static int startDownloadServiceIfRequired(Context context, PendingIntent notificationClient,
+ Class<?> serviceClass)
+ throws NameNotFoundException {
+ return DownloaderService.startDownloadServiceIfRequired(context, notificationClient,
+ serviceClass);
+ }
+
+ /**
+ * This version assumes that the intent contains the pending intent as a parameter. This
+ * is used for responding to alarms.
+ * <p>The pending intent must be in an extra with the key {@link
+ * impl.DownloaderService#EXTRA_PENDING_INTENT}.
+ *
+ * @param context
+ * @param notificationClient
+ * @param serviceClass the class of the service to start
+ * @return
+ * @throws NameNotFoundException
+ */
+ public static int startDownloadServiceIfRequired(Context context, Intent notificationClient,
+ Class<?> serviceClass)
+ throws NameNotFoundException {
+ return DownloaderService.startDownloadServiceIfRequired(context, notificationClient,
+ serviceClass);
+ }
+
+}
diff --git a/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/DownloaderServiceMarshaller.java b/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/DownloaderServiceMarshaller.java
new file mode 100644
index 0000000000..054eaa9895
--- /dev/null
+++ b/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/DownloaderServiceMarshaller.java
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.android.vending.expansion.downloader;
+
+import com.google.android.vending.expansion.downloader.impl.DownloaderService;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.os.Messenger;
+import android.os.RemoteException;
+
+
+
+/**
+ * This class is used by the client activity to proxy requests to the Downloader
+ * Service.
+ *
+ * Most importantly, you must call {@link #CreateProxy} during the {@link
+ * IDownloaderClient#onServiceConnected} callback in your activity in order to instantiate
+ * an {@link IDownloaderService} object that you can then use to issue commands to the {@link
+ * DownloaderService} (such as to pause and resume downloads).
+ */
+public class DownloaderServiceMarshaller {
+
+ public static final int MSG_REQUEST_ABORT_DOWNLOAD =
+ 1;
+ public static final int MSG_REQUEST_PAUSE_DOWNLOAD =
+ 2;
+ public static final int MSG_SET_DOWNLOAD_FLAGS =
+ 3;
+ public static final int MSG_REQUEST_CONTINUE_DOWNLOAD =
+ 4;
+ public static final int MSG_REQUEST_DOWNLOAD_STATE =
+ 5;
+ public static final int MSG_REQUEST_CLIENT_UPDATE =
+ 6;
+
+ public static final String PARAMS_FLAGS = "flags";
+ public static final String PARAM_MESSENGER = DownloaderService.EXTRA_MESSAGE_HANDLER;
+
+ private static class Proxy implements IDownloaderService {
+ private Messenger mMsg;
+
+ private void send(int method, Bundle params) {
+ Message m = Message.obtain(null, method);
+ m.setData(params);
+ try {
+ mMsg.send(m);
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public Proxy(Messenger msg) {
+ mMsg = msg;
+ }
+
+ @Override
+ public void requestAbortDownload() {
+ send(MSG_REQUEST_ABORT_DOWNLOAD, new Bundle());
+ }
+
+ @Override
+ public void requestPauseDownload() {
+ send(MSG_REQUEST_PAUSE_DOWNLOAD, new Bundle());
+ }
+
+ @Override
+ public void setDownloadFlags(int flags) {
+ Bundle params = new Bundle();
+ params.putInt(PARAMS_FLAGS, flags);
+ send(MSG_SET_DOWNLOAD_FLAGS, params);
+ }
+
+ @Override
+ public void requestContinueDownload() {
+ send(MSG_REQUEST_CONTINUE_DOWNLOAD, new Bundle());
+ }
+
+ @Override
+ public void requestDownloadStatus() {
+ send(MSG_REQUEST_DOWNLOAD_STATE, new Bundle());
+ }
+
+ @Override
+ public void onClientUpdated(Messenger clientMessenger) {
+ Bundle bundle = new Bundle(1);
+ bundle.putParcelable(PARAM_MESSENGER, clientMessenger);
+ send(MSG_REQUEST_CLIENT_UPDATE, bundle);
+ }
+ }
+
+ private static class Stub implements IStub {
+ private IDownloaderService mItf = null;
+ final Messenger mMessenger = new Messenger(new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_REQUEST_ABORT_DOWNLOAD:
+ mItf.requestAbortDownload();
+ break;
+ case MSG_REQUEST_CONTINUE_DOWNLOAD:
+ mItf.requestContinueDownload();
+ break;
+ case MSG_REQUEST_PAUSE_DOWNLOAD:
+ mItf.requestPauseDownload();
+ break;
+ case MSG_SET_DOWNLOAD_FLAGS:
+ mItf.setDownloadFlags(msg.getData().getInt(PARAMS_FLAGS));
+ break;
+ case MSG_REQUEST_DOWNLOAD_STATE:
+ mItf.requestDownloadStatus();
+ break;
+ case MSG_REQUEST_CLIENT_UPDATE:
+ mItf.onClientUpdated((Messenger) msg.getData().getParcelable(
+ PARAM_MESSENGER));
+ break;
+ }
+ }
+ });
+
+ public Stub(IDownloaderService itf) {
+ mItf = itf;
+ }
+
+ @Override
+ public Messenger getMessenger() {
+ return mMessenger;
+ }
+
+ @Override
+ public void connect(Context c) {
+
+ }
+
+ @Override
+ public void disconnect(Context c) {
+
+ }
+ }
+
+ /**
+ * Returns a proxy that will marshall calls to IDownloaderService methods
+ *
+ * @param ctx
+ * @return
+ */
+ public static IDownloaderService CreateProxy(Messenger msg) {
+ return new Proxy(msg);
+ }
+
+ /**
+ * Returns a stub object that, when connected, will listen for marshalled
+ * IDownloaderService methods and translate them into calls to the supplied
+ * interface.
+ *
+ * @param itf An implementation of IDownloaderService that will be called
+ * when remote method calls are unmarshalled.
+ * @return
+ */
+ public static IStub CreateStub(IDownloaderService itf) {
+ return new Stub(itf);
+ }
+
+}
diff --git a/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/Helpers.java b/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/Helpers.java
new file mode 100644
index 0000000000..1e84e54a0f
--- /dev/null
+++ b/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/Helpers.java
@@ -0,0 +1,306 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.android.vending.expansion.downloader;
+
+import com.android.vending.expansion.downloader.R;
+
+import android.content.Context;
+import android.os.Environment;
+import android.os.StatFs;
+import android.os.SystemClock;
+import android.util.Log;
+
+import java.io.File;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Locale;
+import java.util.Random;
+import java.util.TimeZone;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Some helper functions for the download manager
+ */
+public class Helpers {
+
+ public static Random sRandom = new Random(SystemClock.uptimeMillis());
+
+ /** Regex used to parse content-disposition headers */
+ private static final Pattern CONTENT_DISPOSITION_PATTERN = Pattern
+ .compile("attachment;\\s*filename\\s*=\\s*\"([^\"]*)\"");
+
+ private Helpers() {
+ }
+
+ /*
+ * Parse the Content-Disposition HTTP Header. The format of the header is
+ * defined here: http://www.w3.org/Protocols/rfc2616/rfc2616-sec19.html This
+ * header provides a filename for content that is going to be downloaded to
+ * the file system. We only support the attachment type.
+ */
+ static String parseContentDisposition(String contentDisposition) {
+ try {
+ Matcher m = CONTENT_DISPOSITION_PATTERN.matcher(contentDisposition);
+ if (m.find()) {
+ return m.group(1);
+ }
+ } catch (IllegalStateException ex) {
+ // This function is defined as returning null when it can't parse
+ // the header
+ }
+ return null;
+ }
+
+ /**
+ * @return the root of the filesystem containing the given path
+ */
+ public static File getFilesystemRoot(String path) {
+ File cache = Environment.getDownloadCacheDirectory();
+ if (path.startsWith(cache.getPath())) {
+ return cache;
+ }
+ File external = Environment.getExternalStorageDirectory();
+ if (path.startsWith(external.getPath())) {
+ return external;
+ }
+ throw new IllegalArgumentException(
+ "Cannot determine filesystem root for " + path);
+ }
+
+ public static boolean isExternalMediaMounted() {
+ if (!Environment.getExternalStorageState().equals(
+ Environment.MEDIA_MOUNTED)) {
+ // No SD card found.
+ if ( Constants.LOGVV ) {
+ Log.d(Constants.TAG, "no external storage");
+ }
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * @return the number of bytes available on the filesystem rooted at the
+ * given File
+ */
+ public static long getAvailableBytes(File root) {
+ StatFs stat = new StatFs(root.getPath());
+ // put a bit of margin (in case creating the file grows the system by a
+ // few blocks)
+ long availableBlocks = (long) stat.getAvailableBlocks() - 4;
+ return stat.getBlockSize() * availableBlocks;
+ }
+
+ /**
+ * Checks whether the filename looks legitimate
+ */
+ public static boolean isFilenameValid(String filename) {
+ filename = filename.replaceFirst("/+", "/"); // normalize leading
+ // slashes
+ return filename.startsWith(Environment.getDownloadCacheDirectory().toString())
+ || filename.startsWith(Environment.getExternalStorageDirectory().toString());
+ }
+
+ /*
+ * Delete the given file from device
+ */
+ /* package */static void deleteFile(String path) {
+ try {
+ File file = new File(path);
+ file.delete();
+ } catch (Exception e) {
+ Log.w(Constants.TAG, "file: '" + path + "' couldn't be deleted", e);
+ }
+ }
+
+ /**
+ * Showing progress in MB here. It would be nice to choose the unit (KB, MB,
+ * GB) based on total file size, but given what we know about the expected
+ * ranges of file sizes for APK expansion files, it's probably not necessary.
+ *
+ * @param overallProgress
+ * @param overallTotal
+ * @return
+ */
+
+ static public String getDownloadProgressString(long overallProgress, long overallTotal) {
+ if (overallTotal == 0) {
+ if ( Constants.LOGVV ) {
+ Log.e(Constants.TAG, "Notification called when total is zero");
+ }
+ return "";
+ }
+ return String.format("%.2f",
+ (float) overallProgress / (1024.0f * 1024.0f))
+ + "MB /" +
+ String.format("%.2f", (float) overallTotal /
+ (1024.0f * 1024.0f)) + "MB";
+ }
+
+ /**
+ * Adds a percentile to getDownloadProgressString.
+ *
+ * @param overallProgress
+ * @param overallTotal
+ * @return
+ */
+ static public String getDownloadProgressStringNotification(long overallProgress,
+ long overallTotal) {
+ if (overallTotal == 0) {
+ if ( Constants.LOGVV ) {
+ Log.e(Constants.TAG, "Notification called when total is zero");
+ }
+ return "";
+ }
+ return getDownloadProgressString(overallProgress, overallTotal) + " (" +
+ getDownloadProgressPercent(overallProgress, overallTotal) + ")";
+ }
+
+ public static String getDownloadProgressPercent(long overallProgress, long overallTotal) {
+ if (overallTotal == 0) {
+ if ( Constants.LOGVV ) {
+ Log.e(Constants.TAG, "Notification called when total is zero");
+ }
+ return "";
+ }
+ return Long.toString(overallProgress * 100 / overallTotal) + "%";
+ }
+
+ public static String getSpeedString(float bytesPerMillisecond) {
+ return String.format("%.2f", bytesPerMillisecond * 1000 / 1024);
+ }
+
+ public static String getTimeRemaining(long durationInMilliseconds) {
+ SimpleDateFormat sdf;
+ if (durationInMilliseconds > 1000 * 60 * 60) {
+ sdf = new SimpleDateFormat("HH:mm", Locale.getDefault());
+ } else {
+ sdf = new SimpleDateFormat("mm:ss", Locale.getDefault());
+ }
+ return sdf.format(new Date(durationInMilliseconds - TimeZone.getDefault().getRawOffset()));
+ }
+
+ /**
+ * Returns the file name (without full path) for an Expansion APK file from
+ * the given context.
+ *
+ * @param c the context
+ * @param mainFile true for main file, false for patch file
+ * @param versionCode the version of the file
+ * @return String the file name of the expansion file
+ */
+ public static String getExpansionAPKFileName(Context c, boolean mainFile, int versionCode) {
+ return (mainFile ? "main." : "patch.") + versionCode + "." + c.getPackageName() + ".obb";
+ }
+
+ /**
+ * Returns the filename (where the file should be saved) from info about a
+ * download
+ */
+ static public String generateSaveFileName(Context c, String fileName) {
+ String path = getSaveFilePath(c)
+ + File.separator + fileName;
+ return path;
+ }
+
+ static public String getSaveFilePath(Context c) {
+ File root = Environment.getExternalStorageDirectory();
+ String path = root.toString() + Constants.EXP_PATH + c.getPackageName();
+ return path;
+ }
+
+ /**
+ * Helper function to ascertain the existence of a file and return
+ * true/false appropriately
+ *
+ * @param c the app/activity/service context
+ * @param fileName the name (sans path) of the file to query
+ * @param fileSize the size that the file must match
+ * @param deleteFileOnMismatch if the file sizes do not match, delete the
+ * file
+ * @return true if it does exist, false otherwise
+ */
+ static public boolean doesFileExist(Context c, String fileName, long fileSize,
+ boolean deleteFileOnMismatch) {
+ // the file may have been delivered by Market --- let's make sure
+ // it's the size we expect
+ File fileForNewFile = new File(Helpers.generateSaveFileName(c, fileName));
+ if (fileForNewFile.exists()) {
+ if (fileForNewFile.length() == fileSize) {
+ return true;
+ }
+ if (deleteFileOnMismatch) {
+ // delete the file --- we won't be able to resume
+ // because we cannot confirm the integrity of the file
+ fileForNewFile.delete();
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Converts download states that are returned by the {@link
+ * IDownloaderClient#onDownloadStateChanged} callback into usable strings.
+ * This is useful if using the state strings built into the library to display user messages.
+ * @param state One of the STATE_* constants from {@link IDownloaderClient}.
+ * @return string resource ID for the corresponding string.
+ */
+ static public int getDownloaderStringResourceIDFromState(int state) {
+ switch (state) {
+ case IDownloaderClient.STATE_IDLE:
+ return R.string.state_idle;
+ case IDownloaderClient.STATE_FETCHING_URL:
+ return R.string.state_fetching_url;
+ case IDownloaderClient.STATE_CONNECTING:
+ return R.string.state_connecting;
+ case IDownloaderClient.STATE_DOWNLOADING:
+ return R.string.state_downloading;
+ case IDownloaderClient.STATE_COMPLETED:
+ return R.string.state_completed;
+ case IDownloaderClient.STATE_PAUSED_NETWORK_UNAVAILABLE:
+ return R.string.state_paused_network_unavailable;
+ case IDownloaderClient.STATE_PAUSED_BY_REQUEST:
+ return R.string.state_paused_by_request;
+ case IDownloaderClient.STATE_PAUSED_WIFI_DISABLED_NEED_CELLULAR_PERMISSION:
+ return R.string.state_paused_wifi_disabled;
+ case IDownloaderClient.STATE_PAUSED_NEED_CELLULAR_PERMISSION:
+ return R.string.state_paused_wifi_unavailable;
+ case IDownloaderClient.STATE_PAUSED_WIFI_DISABLED:
+ return R.string.state_paused_wifi_disabled;
+ case IDownloaderClient.STATE_PAUSED_NEED_WIFI:
+ return R.string.state_paused_wifi_unavailable;
+ case IDownloaderClient.STATE_PAUSED_ROAMING:
+ return R.string.state_paused_roaming;
+ case IDownloaderClient.STATE_PAUSED_NETWORK_SETUP_FAILURE:
+ return R.string.state_paused_network_setup_failure;
+ case IDownloaderClient.STATE_PAUSED_SDCARD_UNAVAILABLE:
+ return R.string.state_paused_sdcard_unavailable;
+ case IDownloaderClient.STATE_FAILED_UNLICENSED:
+ return R.string.state_failed_unlicensed;
+ case IDownloaderClient.STATE_FAILED_FETCHING_URL:
+ return R.string.state_failed_fetching_url;
+ case IDownloaderClient.STATE_FAILED_SDCARD_FULL:
+ return R.string.state_failed_sdcard_full;
+ case IDownloaderClient.STATE_FAILED_CANCELED:
+ return R.string.state_failed_cancelled;
+ default:
+ return R.string.state_unknown;
+ }
+ }
+
+}
diff --git a/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/IDownloaderClient.java b/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/IDownloaderClient.java
new file mode 100644
index 0000000000..b8511a62a0
--- /dev/null
+++ b/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/IDownloaderClient.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.android.vending.expansion.downloader;
+
+import android.os.Messenger;
+
+/**
+ * This interface should be implemented by the client activity for the
+ * downloader. It is used to pass status from the service to the client.
+ */
+public interface IDownloaderClient {
+ static final int STATE_IDLE = 1;
+ static final int STATE_FETCHING_URL = 2;
+ static final int STATE_CONNECTING = 3;
+ static final int STATE_DOWNLOADING = 4;
+ static final int STATE_COMPLETED = 5;
+
+ static final int STATE_PAUSED_NETWORK_UNAVAILABLE = 6;
+ static final int STATE_PAUSED_BY_REQUEST = 7;
+
+ /**
+ * Both STATE_PAUSED_WIFI_DISABLED_NEED_CELLULAR_PERMISSION and
+ * STATE_PAUSED_NEED_CELLULAR_PERMISSION imply that Wi-Fi is unavailable and
+ * cellular permission will restart the service. Wi-Fi disabled means that
+ * the Wi-Fi manager is returning that Wi-Fi is not enabled, while in the
+ * other case Wi-Fi is enabled but not available.
+ */
+ static final int STATE_PAUSED_WIFI_DISABLED_NEED_CELLULAR_PERMISSION = 8;
+ static final int STATE_PAUSED_NEED_CELLULAR_PERMISSION = 9;
+
+ /**
+ * Both STATE_PAUSED_WIFI_DISABLED and STATE_PAUSED_NEED_WIFI imply that
+ * Wi-Fi is unavailable and cellular permission will NOT restart the
+ * service. Wi-Fi disabled means that the Wi-Fi manager is returning that
+ * Wi-Fi is not enabled, while in the other case Wi-Fi is enabled but not
+ * available.
+ * <p>
+ * The service does not return these values. We recommend that app
+ * developers with very large payloads do not allow these payloads to be
+ * downloaded over cellular connections.
+ */
+ static final int STATE_PAUSED_WIFI_DISABLED = 10;
+ static final int STATE_PAUSED_NEED_WIFI = 11;
+
+ static final int STATE_PAUSED_ROAMING = 12;
+
+ /**
+ * Scary case. We were on a network that redirected us to another website
+ * that delivered us the wrong file.
+ */
+ static final int STATE_PAUSED_NETWORK_SETUP_FAILURE = 13;
+
+ static final int STATE_PAUSED_SDCARD_UNAVAILABLE = 14;
+
+ static final int STATE_FAILED_UNLICENSED = 15;
+ static final int STATE_FAILED_FETCHING_URL = 16;
+ static final int STATE_FAILED_SDCARD_FULL = 17;
+ static final int STATE_FAILED_CANCELED = 18;
+
+ static final int STATE_FAILED = 19;
+
+ /**
+ * Called internally by the stub when the service is bound to the client.
+ * <p>
+ * Critical implementation detail. In onServiceConnected we create the
+ * remote service and marshaler. This is how we pass the client information
+ * back to the service so the client can be properly notified of changes. We
+ * must do this every time we reconnect to the service.
+ * <p>
+ * That is, when you receive this callback, you should call
+ * {@link DownloaderServiceMarshaller#CreateProxy} to instantiate a member
+ * instance of {@link IDownloaderService}, then call
+ * {@link IDownloaderService#onClientUpdated} with the Messenger retrieved
+ * from your {@link IStub} proxy object.
+ *
+ * @param m the service Messenger. This Messenger is used to call the
+ * service API from the client.
+ */
+ void onServiceConnected(Messenger m);
+
+ /**
+ * Called when the download state changes. Depending on the state, there may
+ * be user requests. The service is free to change the download state in the
+ * middle of a user request, so the client should be able to handle this.
+ * <p>
+ * The Downloader Library includes a collection of string resources that
+ * correspond to each of the states, which you can use to provide users a
+ * useful message based on the state provided in this callback. To fetch the
+ * appropriate string for a state, call
+ * {@link Helpers#getDownloaderStringResourceIDFromState}.
+ * <p>
+ * What this means to the developer: The application has gotten a message
+ * that the download has paused due to lack of WiFi. The developer should
+ * then show UI asking the user if they want to enable downloading over
+ * cellular connections with appropriate warnings. If the application
+ * suddenly starts downloading, the application should revert to showing the
+ * progress again, rather than leaving up the download over cellular UI up.
+ *
+ * @param newState one of the STATE_* values defined in IDownloaderClient
+ */
+ void onDownloadStateChanged(int newState);
+
+ /**
+ * Shows the download progress. This is intended to be used to fill out a
+ * client UI. This progress should only be shown in a few states such as
+ * STATE_DOWNLOADING.
+ *
+ * @param progress the DownloadProgressInfo object containing the current
+ * progress of all downloads.
+ */
+ void onDownloadProgress(DownloadProgressInfo progress);
+}
diff --git a/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/IDownloaderService.java b/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/IDownloaderService.java
new file mode 100644
index 0000000000..4789afe19c
--- /dev/null
+++ b/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/IDownloaderService.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.android.vending.expansion.downloader;
+
+import com.google.android.vending.expansion.downloader.impl.DownloaderService;
+import android.os.Messenger;
+
+/**
+ * This interface is implemented by the DownloaderService and by the
+ * DownloaderServiceMarshaller. It contains functions to control the service.
+ * When a client binds to the service, it must call the onClientUpdated
+ * function.
+ * <p>
+ * You can acquire a proxy that implements this interface for your service by
+ * calling {@link DownloaderServiceMarshaller#CreateProxy} during the
+ * {@link IDownloaderClient#onServiceConnected} callback. At which point, you
+ * should immediately call {@link #onClientUpdated}.
+ */
+public interface IDownloaderService {
+ /**
+ * Set this flag in response to the
+ * IDownloaderClient.STATE_PAUSED_NEED_CELLULAR_PERMISSION state and then
+ * call RequestContinueDownload to resume a download
+ */
+ public static final int FLAGS_DOWNLOAD_OVER_CELLULAR = 1;
+
+ /**
+ * Request that the service abort the current download. The service should
+ * respond by changing the state to {@link IDownloaderClient.STATE_ABORTED}.
+ */
+ void requestAbortDownload();
+
+ /**
+ * Request that the service pause the current download. The service should
+ * respond by changing the state to
+ * {@link IDownloaderClient.STATE_PAUSED_BY_REQUEST}.
+ */
+ void requestPauseDownload();
+
+ /**
+ * Request that the service continue a paused download, when in any paused
+ * or failed state, including
+ * {@link IDownloaderClient.STATE_PAUSED_BY_REQUEST}.
+ */
+ void requestContinueDownload();
+
+ /**
+ * Set the flags for this download (e.g.
+ * {@link DownloaderService.FLAGS_DOWNLOAD_OVER_CELLULAR}).
+ *
+ * @param flags
+ */
+ void setDownloadFlags(int flags);
+
+ /**
+ * Requests that the download status be sent to the client.
+ */
+ void requestDownloadStatus();
+
+ /**
+ * Call this when you get {@link
+ * IDownloaderClient.onServiceConnected(Messenger m)} from the
+ * DownloaderClient to register the client with the service. It will
+ * automatically send the current status to the client.
+ *
+ * @param clientMessenger
+ */
+ void onClientUpdated(Messenger clientMessenger);
+}
diff --git a/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/IStub.java b/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/IStub.java
new file mode 100644
index 0000000000..d5bc3a843e
--- /dev/null
+++ b/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/IStub.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.android.vending.expansion.downloader;
+
+import android.content.Context;
+import android.os.Messenger;
+
+/**
+ * This is the interface that is used to connect/disconnect from the downloader
+ * service.
+ * <p>
+ * You should get a proxy object that implements this interface by calling
+ * {@link DownloaderClientMarshaller#CreateStub} in your activity when the
+ * downloader service starts. Then, call {@link #connect} during your activity's
+ * onResume() and call {@link #disconnect} during onStop().
+ * <p>
+ * Then during the {@link IDownloaderClient#onServiceConnected} callback, you
+ * should call {@link #getMessenger} to pass the stub's Messenger object to
+ * {@link IDownloaderService#onClientUpdated}.
+ */
+public interface IStub {
+ Messenger getMessenger();
+
+ void connect(Context c);
+
+ void disconnect(Context c);
+}
diff --git a/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/SystemFacade.java b/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/SystemFacade.java
new file mode 100644
index 0000000000..12edd97ab2
--- /dev/null
+++ b/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/SystemFacade.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.android.vending.expansion.downloader;
+
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.telephony.TelephonyManager;
+import android.util.Log;
+
+/**
+ * Contains useful helper functions, typically tied to the application context.
+ */
+class SystemFacade {
+ private Context mContext;
+ private NotificationManager mNotificationManager;
+
+ public SystemFacade(Context context) {
+ mContext = context;
+ mNotificationManager = (NotificationManager)
+ mContext.getSystemService(Context.NOTIFICATION_SERVICE);
+ }
+
+ public long currentTimeMillis() {
+ return System.currentTimeMillis();
+ }
+
+ public Integer getActiveNetworkType() {
+ ConnectivityManager connectivity =
+ (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
+ if (connectivity == null) {
+ Log.w(Constants.TAG, "couldn't get connectivity manager");
+ return null;
+ }
+
+ NetworkInfo activeInfo = connectivity.getActiveNetworkInfo();
+ if (activeInfo == null) {
+ if (Constants.LOGVV) {
+ Log.v(Constants.TAG, "network is not available");
+ }
+ return null;
+ }
+ return activeInfo.getType();
+ }
+
+ public boolean isNetworkRoaming() {
+ ConnectivityManager connectivity =
+ (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
+ if (connectivity == null) {
+ Log.w(Constants.TAG, "couldn't get connectivity manager");
+ return false;
+ }
+
+ NetworkInfo info = connectivity.getActiveNetworkInfo();
+ boolean isMobile = (info != null && info.getType() == ConnectivityManager.TYPE_MOBILE);
+ TelephonyManager tm = (TelephonyManager) mContext
+ .getSystemService(Context.TELEPHONY_SERVICE);
+ if (null == tm) {
+ Log.w(Constants.TAG, "couldn't get telephony manager");
+ return false;
+ }
+ boolean isRoaming = isMobile && tm.isNetworkRoaming();
+ if (Constants.LOGVV && isRoaming) {
+ Log.v(Constants.TAG, "network is roaming");
+ }
+ return isRoaming;
+ }
+
+ public Long getMaxBytesOverMobile() {
+ return (long) Integer.MAX_VALUE;
+ }
+
+ public Long getRecommendedMaxBytesOverMobile() {
+ return 2097152L;
+ }
+
+ public void sendBroadcast(Intent intent) {
+ mContext.sendBroadcast(intent);
+ }
+
+ public boolean userOwnsPackage(int uid, String packageName) throws NameNotFoundException {
+ return mContext.getPackageManager().getApplicationInfo(packageName, 0).uid == uid;
+ }
+
+ public void postNotification(long id, Notification notification) {
+ /**
+ * TODO: The system notification manager takes ints, not longs, as IDs,
+ * but the download manager uses IDs take straight from the database,
+ * which are longs. This will have to be dealt with at some point.
+ */
+ mNotificationManager.notify((int) id, notification);
+ }
+
+ public void cancelNotification(long id) {
+ mNotificationManager.cancel((int) id);
+ }
+
+ public void cancelAllNotifications() {
+ mNotificationManager.cancelAll();
+ }
+
+ public void startThread(Thread thread) {
+ thread.start();
+ }
+}
diff --git a/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/AndroidHttpClient.java b/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/AndroidHttpClient.java
new file mode 100644
index 0000000000..4667acce67
--- /dev/null
+++ b/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/AndroidHttpClient.java
@@ -0,0 +1,536 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * This is a port of AndroidHttpClient to pre-Froyo devices, that takes advantage of
+ * the SSLSessionCache added Froyo devices using reflection.
+ */
+
+package com.google.android.vending.expansion.downloader.impl;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.net.URI;
+import java.util.zip.GZIPInputStream;
+import java.util.zip.GZIPOutputStream;
+
+import org.apache.http.Header;
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpEntityEnclosingRequest;
+import org.apache.http.HttpException;
+import org.apache.http.HttpHost;
+import org.apache.http.HttpRequest;
+import org.apache.http.HttpRequestInterceptor;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.ClientProtocolException;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.ResponseHandler;
+import org.apache.http.client.methods.HttpUriRequest;
+import org.apache.http.client.params.HttpClientParams;
+import org.apache.http.client.protocol.ClientContext;
+import org.apache.http.conn.ClientConnectionManager;
+import org.apache.http.conn.scheme.PlainSocketFactory;
+import org.apache.http.conn.scheme.Scheme;
+import org.apache.http.conn.scheme.SchemeRegistry;
+import org.apache.http.conn.scheme.SocketFactory;
+import org.apache.http.conn.ssl.SSLSocketFactory;
+import org.apache.http.entity.AbstractHttpEntity;
+import org.apache.http.entity.ByteArrayEntity;
+import org.apache.http.impl.client.DefaultHttpClient;
+import org.apache.http.impl.client.RequestWrapper;
+import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
+import org.apache.http.params.BasicHttpParams;
+import org.apache.http.params.HttpConnectionParams;
+import org.apache.http.params.HttpParams;
+import org.apache.http.params.HttpProtocolParams;
+import org.apache.http.protocol.BasicHttpContext;
+import org.apache.http.protocol.BasicHttpProcessor;
+import org.apache.http.protocol.HttpContext;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.net.SSLCertificateSocketFactory;
+import android.os.Looper;
+import android.util.Log;
+
+/**
+ * Subclass of the Apache {@link DefaultHttpClient} that is configured with
+ * reasonable default settings and registered schemes for Android, and
+ * also lets the user add {@link HttpRequestInterceptor} classes.
+ * Don't create this directly, use the {@link #newInstance} factory method.
+ *
+ * <p>This client processes cookies but does not retain them by default.
+ * To retain cookies, simply add a cookie store to the HttpContext:</p>
+ *
+ * <pre>context.setAttribute(ClientContext.COOKIE_STORE, cookieStore);</pre>
+ */
+public final class AndroidHttpClient implements HttpClient {
+
+ static Class<?> sSslSessionCacheClass;
+ static {
+ // if we are on Froyo+ devices, we can take advantage of the SSLSessionCache
+ try {
+ sSslSessionCacheClass = Class.forName("android.net.SSLSessionCache");
+ } catch (Exception e) {
+
+ }
+ }
+
+ // Gzip of data shorter than this probably won't be worthwhile
+ public static long DEFAULT_SYNC_MIN_GZIP_BYTES = 256;
+
+ // Default connection and socket timeout of 60 seconds. Tweak to taste.
+ private static final int SOCKET_OPERATION_TIMEOUT = 60 * 1000;
+
+ private static final String TAG = "AndroidHttpClient";
+
+
+ /** Interceptor throws an exception if the executing thread is blocked */
+ private static final HttpRequestInterceptor sThreadCheckInterceptor =
+ new HttpRequestInterceptor() {
+ public void process(HttpRequest request, HttpContext context) {
+ // Prevent the HttpRequest from being sent on the main thread
+ if (Looper.myLooper() != null && Looper.myLooper() == Looper.getMainLooper() ) {
+ throw new RuntimeException("This thread forbids HTTP requests");
+ }
+ }
+ };
+
+ /**
+ * Create a new HttpClient with reasonable defaults (which you can update).
+ *
+ * @param userAgent to report in your HTTP requests
+ * @param context to use for caching SSL sessions (may be null for no caching)
+ * @return AndroidHttpClient for you to use for all your requests.
+ */
+ public static AndroidHttpClient newInstance(String userAgent, Context context) {
+ HttpParams params = new BasicHttpParams();
+
+ // Turn off stale checking. Our connections break all the time anyway,
+ // and it's not worth it to pay the penalty of checking every time.
+ HttpConnectionParams.setStaleCheckingEnabled(params, false);
+
+ HttpConnectionParams.setConnectionTimeout(params, SOCKET_OPERATION_TIMEOUT);
+ HttpConnectionParams.setSoTimeout(params, SOCKET_OPERATION_TIMEOUT);
+ HttpConnectionParams.setSocketBufferSize(params, 8192);
+
+ // Don't handle redirects -- return them to the caller. Our code
+ // often wants to re-POST after a redirect, which we must do ourselves.
+ HttpClientParams.setRedirecting(params, false);
+
+ Object sessionCache = null;
+ // Use a session cache for SSL sockets -- Froyo only
+ if ( null != context && null != sSslSessionCacheClass ) {
+ Constructor<?> ct;
+ try {
+ ct = sSslSessionCacheClass.getConstructor(Context.class);
+ sessionCache = ct.newInstance(context);
+ } catch (SecurityException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (NoSuchMethodException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (IllegalArgumentException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (InstantiationException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (IllegalAccessException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (InvocationTargetException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+ // Set the specified user agent and register standard protocols.
+ HttpProtocolParams.setUserAgent(params, userAgent);
+ SchemeRegistry schemeRegistry = new SchemeRegistry();
+ schemeRegistry.register(new Scheme("http",
+ PlainSocketFactory.getSocketFactory(), 80));
+ SocketFactory sslCertificateSocketFactory = null;
+ if ( null != sessionCache ) {
+ Method getHttpSocketFactoryMethod;
+ try {
+ getHttpSocketFactoryMethod = SSLCertificateSocketFactory.class.getDeclaredMethod("getHttpSocketFactory",Integer.TYPE, sSslSessionCacheClass);
+ sslCertificateSocketFactory = (SocketFactory)getHttpSocketFactoryMethod.invoke(null, SOCKET_OPERATION_TIMEOUT, sessionCache);
+ } catch (SecurityException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (NoSuchMethodException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (IllegalArgumentException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (IllegalAccessException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (InvocationTargetException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+ if ( null == sslCertificateSocketFactory ) {
+ sslCertificateSocketFactory = SSLSocketFactory.getSocketFactory();
+ }
+ schemeRegistry.register(new Scheme("https",
+ sslCertificateSocketFactory, 443));
+
+ ClientConnectionManager manager =
+ new ThreadSafeClientConnManager(params, schemeRegistry);
+
+ // We use a factory method to modify superclass initialization
+ // parameters without the funny call-a-static-method dance.
+ return new AndroidHttpClient(manager, params);
+ }
+
+ /**
+ * Create a new HttpClient with reasonable defaults (which you can update).
+ * @param userAgent to report in your HTTP requests.
+ * @return AndroidHttpClient for you to use for all your requests.
+ */
+ public static AndroidHttpClient newInstance(String userAgent) {
+ return newInstance(userAgent, null /* session cache */);
+ }
+
+ private final HttpClient delegate;
+
+ private RuntimeException mLeakedException = new IllegalStateException(
+ "AndroidHttpClient created and never closed");
+
+ private AndroidHttpClient(ClientConnectionManager ccm, HttpParams params) {
+ this.delegate = new DefaultHttpClient(ccm, params) {
+ @Override
+ protected BasicHttpProcessor createHttpProcessor() {
+ // Add interceptor to prevent making requests from main thread.
+ BasicHttpProcessor processor = super.createHttpProcessor();
+ processor.addRequestInterceptor(sThreadCheckInterceptor);
+ processor.addRequestInterceptor(new CurlLogger());
+
+ return processor;
+ }
+
+ @Override
+ protected HttpContext createHttpContext() {
+ // Same as DefaultHttpClient.createHttpContext() minus the
+ // cookie store.
+ HttpContext context = new BasicHttpContext();
+ context.setAttribute(
+ ClientContext.AUTHSCHEME_REGISTRY,
+ getAuthSchemes());
+ context.setAttribute(
+ ClientContext.COOKIESPEC_REGISTRY,
+ getCookieSpecs());
+ context.setAttribute(
+ ClientContext.CREDS_PROVIDER,
+ getCredentialsProvider());
+ return context;
+ }
+ };
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ super.finalize();
+ if (mLeakedException != null) {
+ Log.e(TAG, "Leak found", mLeakedException);
+ mLeakedException = null;
+ }
+ }
+
+ /**
+ * Modifies a request to indicate to the server that we would like a
+ * gzipped response. (Uses the "Accept-Encoding" HTTP header.)
+ * @param request the request to modify
+ * @see #getUngzippedContent
+ */
+ public static void modifyRequestToAcceptGzipResponse(HttpRequest request) {
+ request.addHeader("Accept-Encoding", "gzip");
+ }
+
+ /**
+ * Gets the input stream from a response entity. If the entity is gzipped
+ * then this will get a stream over the uncompressed data.
+ *
+ * @param entity the entity whose content should be read
+ * @return the input stream to read from
+ * @throws IOException
+ */
+ public static InputStream getUngzippedContent(HttpEntity entity)
+ throws IOException {
+ InputStream responseStream = entity.getContent();
+ if (responseStream == null) return responseStream;
+ Header header = entity.getContentEncoding();
+ if (header == null) return responseStream;
+ String contentEncoding = header.getValue();
+ if (contentEncoding == null) return responseStream;
+ if (contentEncoding.contains("gzip")) responseStream
+ = new GZIPInputStream(responseStream);
+ return responseStream;
+ }
+
+ /**
+ * Release resources associated with this client. You must call this,
+ * or significant resources (sockets and memory) may be leaked.
+ */
+ public void close() {
+ if (mLeakedException != null) {
+ getConnectionManager().shutdown();
+ mLeakedException = null;
+ }
+ }
+
+ public HttpParams getParams() {
+ return delegate.getParams();
+ }
+
+ public ClientConnectionManager getConnectionManager() {
+ return delegate.getConnectionManager();
+ }
+
+ public HttpResponse execute(HttpUriRequest request) throws IOException {
+ return delegate.execute(request);
+ }
+
+ public HttpResponse execute(HttpUriRequest request, HttpContext context)
+ throws IOException {
+ return delegate.execute(request, context);
+ }
+
+ public HttpResponse execute(HttpHost target, HttpRequest request)
+ throws IOException {
+ return delegate.execute(target, request);
+ }
+
+ public HttpResponse execute(HttpHost target, HttpRequest request,
+ HttpContext context) throws IOException {
+ return delegate.execute(target, request, context);
+ }
+
+ public <T> T execute(HttpUriRequest request,
+ ResponseHandler<? extends T> responseHandler)
+ throws IOException, ClientProtocolException {
+ return delegate.execute(request, responseHandler);
+ }
+
+ public <T> T execute(HttpUriRequest request,
+ ResponseHandler<? extends T> responseHandler, HttpContext context)
+ throws IOException, ClientProtocolException {
+ return delegate.execute(request, responseHandler, context);
+ }
+
+ public <T> T execute(HttpHost target, HttpRequest request,
+ ResponseHandler<? extends T> responseHandler) throws IOException,
+ ClientProtocolException {
+ return delegate.execute(target, request, responseHandler);
+ }
+
+ public <T> T execute(HttpHost target, HttpRequest request,
+ ResponseHandler<? extends T> responseHandler, HttpContext context)
+ throws IOException, ClientProtocolException {
+ return delegate.execute(target, request, responseHandler, context);
+ }
+
+ /**
+ * Compress data to send to server.
+ * Creates a Http Entity holding the gzipped data.
+ * The data will not be compressed if it is too short.
+ * @param data The bytes to compress
+ * @return Entity holding the data
+ */
+ public static AbstractHttpEntity getCompressedEntity(byte data[], ContentResolver resolver)
+ throws IOException {
+ AbstractHttpEntity entity;
+ if (data.length < getMinGzipSize(resolver)) {
+ entity = new ByteArrayEntity(data);
+ } else {
+ ByteArrayOutputStream arr = new ByteArrayOutputStream();
+ OutputStream zipper = new GZIPOutputStream(arr);
+ zipper.write(data);
+ zipper.close();
+ entity = new ByteArrayEntity(arr.toByteArray());
+ entity.setContentEncoding("gzip");
+ }
+ return entity;
+ }
+
+ /**
+ * Retrieves the minimum size for compressing data.
+ * Shorter data will not be compressed.
+ */
+ public static long getMinGzipSize(ContentResolver resolver) {
+ return DEFAULT_SYNC_MIN_GZIP_BYTES; // For now, this is just a constant.
+ }
+
+ /* cURL logging support. */
+
+ /**
+ * Logging tag and level.
+ */
+ private static class LoggingConfiguration {
+
+ private final String tag;
+ private final int level;
+
+ private LoggingConfiguration(String tag, int level) {
+ this.tag = tag;
+ this.level = level;
+ }
+
+ /**
+ * Returns true if logging is turned on for this configuration.
+ */
+ private boolean isLoggable() {
+ return Log.isLoggable(tag, level);
+ }
+
+ /**
+ * Prints a message using this configuration.
+ */
+ private void println(String message) {
+ Log.println(level, tag, message);
+ }
+ }
+
+ /** cURL logging configuration. */
+ private volatile LoggingConfiguration curlConfiguration;
+
+ /**
+ * Enables cURL request logging for this client.
+ *
+ * @param name to log messages with
+ * @param level at which to log messages (see {@link android.util.Log})
+ */
+ public void enableCurlLogging(String name, int level) {
+ if (name == null) {
+ throw new NullPointerException("name");
+ }
+ if (level < Log.VERBOSE || level > Log.ASSERT) {
+ throw new IllegalArgumentException("Level is out of range ["
+ + Log.VERBOSE + ".." + Log.ASSERT + "]");
+ }
+
+ curlConfiguration = new LoggingConfiguration(name, level);
+ }
+
+ /**
+ * Disables cURL logging for this client.
+ */
+ public void disableCurlLogging() {
+ curlConfiguration = null;
+ }
+
+ /**
+ * Logs cURL commands equivalent to requests.
+ */
+ private class CurlLogger implements HttpRequestInterceptor {
+ public void process(HttpRequest request, HttpContext context)
+ throws HttpException, IOException {
+ LoggingConfiguration configuration = curlConfiguration;
+ if (configuration != null
+ && configuration.isLoggable()
+ && request instanceof HttpUriRequest) {
+ // Never print auth token -- we used to check ro.secure=0 to
+ // enable that, but can't do that in unbundled code.
+ configuration.println(toCurl((HttpUriRequest) request, false));
+ }
+ }
+ }
+
+ /**
+ * Generates a cURL command equivalent to the given request.
+ */
+ private static String toCurl(HttpUriRequest request, boolean logAuthToken) throws IOException {
+ StringBuilder builder = new StringBuilder();
+
+ builder.append("curl ");
+
+ for (Header header: request.getAllHeaders()) {
+ if (!logAuthToken
+ && (header.getName().equals("Authorization") ||
+ header.getName().equals("Cookie"))) {
+ continue;
+ }
+ builder.append("--header \"");
+ builder.append(header.toString().trim());
+ builder.append("\" ");
+ }
+
+ URI uri = request.getURI();
+
+ // If this is a wrapped request, use the URI from the original
+ // request instead. getURI() on the wrapper seems to return a
+ // relative URI. We want an absolute URI.
+ if (request instanceof RequestWrapper) {
+ HttpRequest original = ((RequestWrapper) request).getOriginal();
+ if (original instanceof HttpUriRequest) {
+ uri = ((HttpUriRequest) original).getURI();
+ }
+ }
+
+ builder.append("\"");
+ builder.append(uri);
+ builder.append("\"");
+
+ if (request instanceof HttpEntityEnclosingRequest) {
+ HttpEntityEnclosingRequest entityRequest =
+ (HttpEntityEnclosingRequest) request;
+ HttpEntity entity = entityRequest.getEntity();
+ if (entity != null && entity.isRepeatable()) {
+ if (entity.getContentLength() < 1024) {
+ ByteArrayOutputStream stream = new ByteArrayOutputStream();
+ entity.writeTo(stream);
+ String entityString = stream.toString();
+
+ // TODO: Check the content type, too.
+ builder.append(" --data-ascii \"")
+ .append(entityString)
+ .append("\"");
+ } else {
+ builder.append(" [TOO MUCH DATA TO INCLUDE]");
+ }
+ }
+ }
+
+ return builder.toString();
+ }
+
+ /**
+ * Returns the date of the given HTTP date string. This method can identify
+ * and parse the date formats emitted by common HTTP servers, such as
+ * <a href="http://www.ietf.org/rfc/rfc0822.txt">RFC 822</a>,
+ * <a href="http://www.ietf.org/rfc/rfc0850.txt">RFC 850</a>,
+ * <a href="http://www.ietf.org/rfc/rfc1036.txt">RFC 1036</a>,
+ * <a href="http://www.ietf.org/rfc/rfc1123.txt">RFC 1123</a> and
+ * <a href="http://www.opengroup.org/onlinepubs/007908799/xsh/asctime.html">ANSI
+ * C's asctime()</a>.
+ *
+ * @return the number of milliseconds since Jan. 1, 1970, midnight GMT.
+ * @throws IllegalArgumentException if {@code dateString} is not a date or
+ * of an unsupported format.
+ */
+ public static long parseDate(String dateString) {
+ return HttpDateTime.parse(dateString);
+ }
+} \ No newline at end of file
diff --git a/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/CustomIntentService.java b/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/CustomIntentService.java
new file mode 100755
index 0000000000..b77af7e085
--- /dev/null
+++ b/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/CustomIntentService.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.android.vending.expansion.downloader.impl;
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.util.Log;
+
+/**
+ * This service differs from IntentService in a few minor ways/ It will not
+ * auto-stop itself after the intent is handled unless the target returns "true"
+ * in should stop. Since the goal of this service is to handle a single kind of
+ * intent, it does not queue up batches of intents of the same type.
+ */
+public abstract class CustomIntentService extends Service {
+ private String mName;
+ private boolean mRedelivery;
+ private volatile ServiceHandler mServiceHandler;
+ private volatile Looper mServiceLooper;
+ private static final String LOG_TAG = "CancellableIntentService";
+ private static final int WHAT_MESSAGE = -10;
+
+ public CustomIntentService(String paramString) {
+ this.mName = paramString;
+ }
+
+ @Override
+ public IBinder onBind(Intent paramIntent) {
+ return null;
+ }
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ HandlerThread localHandlerThread = new HandlerThread("IntentService["
+ + this.mName + "]");
+ localHandlerThread.start();
+ this.mServiceLooper = localHandlerThread.getLooper();
+ this.mServiceHandler = new ServiceHandler(this.mServiceLooper);
+ }
+
+ @Override
+ public void onDestroy() {
+ Thread localThread = this.mServiceLooper.getThread();
+ if ((localThread != null) && (localThread.isAlive())) {
+ localThread.interrupt();
+ }
+ this.mServiceLooper.quit();
+ Log.d(LOG_TAG, "onDestroy");
+ }
+
+ protected abstract void onHandleIntent(Intent paramIntent);
+
+ protected abstract boolean shouldStop();
+
+ @Override
+ public void onStart(Intent paramIntent, int startId) {
+ if (!this.mServiceHandler.hasMessages(WHAT_MESSAGE)) {
+ Message localMessage = this.mServiceHandler.obtainMessage();
+ localMessage.arg1 = startId;
+ localMessage.obj = paramIntent;
+ localMessage.what = WHAT_MESSAGE;
+ this.mServiceHandler.sendMessage(localMessage);
+ }
+ }
+
+ @Override
+ public int onStartCommand(Intent paramIntent, int flags, int startId) {
+ onStart(paramIntent, startId);
+ return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
+ }
+
+ public void setIntentRedelivery(boolean enabled) {
+ this.mRedelivery = enabled;
+ }
+
+ private final class ServiceHandler extends Handler {
+ public ServiceHandler(Looper looper) {
+ super(looper);
+ }
+
+ @Override
+ public void handleMessage(Message paramMessage) {
+ CustomIntentService.this
+ .onHandleIntent((Intent) paramMessage.obj);
+ if (shouldStop()) {
+ Log.d(LOG_TAG, "stopSelf");
+ CustomIntentService.this.stopSelf(paramMessage.arg1);
+ Log.d(LOG_TAG, "afterStopSelf");
+ }
+ }
+ }
+}
diff --git a/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/CustomNotificationFactory.java b/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/CustomNotificationFactory.java
new file mode 100644
index 0000000000..9a0ca02122
--- /dev/null
+++ b/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/CustomNotificationFactory.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.android.vending.expansion.downloader.impl;
+
+/**
+ * Uses the class-loader model to utilize the updated notification builders in
+ * Honeycomb while maintaining a compatible version for older devices.
+ */
+public class CustomNotificationFactory {
+ static public DownloadNotification.ICustomNotification createCustomNotification() {
+ if (android.os.Build.VERSION.SDK_INT > 13)
+ return new V14CustomNotification();
+ else
+ return new V3CustomNotification();
+ }
+}
diff --git a/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/DownloadInfo.java b/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/DownloadInfo.java
new file mode 100644
index 0000000000..45111b16a3
--- /dev/null
+++ b/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/DownloadInfo.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.android.vending.expansion.downloader.impl;
+
+import com.google.android.vending.expansion.downloader.Constants;
+import com.google.android.vending.expansion.downloader.Helpers;
+
+import android.util.Log;
+
+/**
+ * Representation of information about an individual download from the database.
+ */
+public class DownloadInfo {
+ public String mUri;
+ public final int mIndex;
+ public final String mFileName;
+ public String mETag;
+ public long mTotalBytes;
+ public long mCurrentBytes;
+ public long mLastMod;
+ public int mStatus;
+ public int mControl;
+ public int mNumFailed;
+ public int mRetryAfter;
+ public int mRedirectCount;
+
+ boolean mInitialized;
+
+ public int mFuzz;
+
+ public DownloadInfo(int index, String fileName, String pkg) {
+ mFuzz = Helpers.sRandom.nextInt(1001);
+ mFileName = fileName;
+ mIndex = index;
+ }
+
+ public void resetDownload() {
+ mCurrentBytes = 0;
+ mETag = "";
+ mLastMod = 0;
+ mStatus = 0;
+ mControl = 0;
+ mNumFailed = 0;
+ mRetryAfter = 0;
+ mRedirectCount = 0;
+ }
+
+ /**
+ * Returns the time when a download should be restarted.
+ */
+ public long restartTime(long now) {
+ if (mNumFailed == 0) {
+ return now;
+ }
+ if (mRetryAfter > 0) {
+ return mLastMod + mRetryAfter;
+ }
+ return mLastMod +
+ Constants.RETRY_FIRST_DELAY *
+ (1000 + mFuzz) * (1 << (mNumFailed - 1));
+ }
+
+ public void logVerboseInfo() {
+ Log.v(Constants.TAG, "Service adding new entry");
+ Log.v(Constants.TAG, "FILENAME: " + mFileName);
+ Log.v(Constants.TAG, "URI : " + mUri);
+ Log.v(Constants.TAG, "FILENAME: " + mFileName);
+ Log.v(Constants.TAG, "CONTROL : " + mControl);
+ Log.v(Constants.TAG, "STATUS : " + mStatus);
+ Log.v(Constants.TAG, "FAILED_C: " + mNumFailed);
+ Log.v(Constants.TAG, "RETRY_AF: " + mRetryAfter);
+ Log.v(Constants.TAG, "REDIRECT: " + mRedirectCount);
+ Log.v(Constants.TAG, "LAST_MOD: " + mLastMod);
+ Log.v(Constants.TAG, "TOTAL : " + mTotalBytes);
+ Log.v(Constants.TAG, "CURRENT : " + mCurrentBytes);
+ Log.v(Constants.TAG, "ETAG : " + mETag);
+ }
+}
diff --git a/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/DownloadNotification.java b/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/DownloadNotification.java
new file mode 100644
index 0000000000..eef205d7b7
--- /dev/null
+++ b/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/DownloadNotification.java
@@ -0,0 +1,231 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.android.vending.expansion.downloader.impl;
+
+import com.android.vending.expansion.downloader.R;
+import com.google.android.vending.expansion.downloader.DownloadProgressInfo;
+import com.google.android.vending.expansion.downloader.DownloaderClientMarshaller;
+import com.google.android.vending.expansion.downloader.Helpers;
+import com.google.android.vending.expansion.downloader.IDownloaderClient;
+
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.os.Messenger;
+
+/**
+ * This class handles displaying the notification associated with the download
+ * queue going on in the download manager. It handles multiple status types;
+ * Some require user interaction and some do not. Some of the user interactions
+ * may be transient. (for example: the user is queried to continue the download
+ * on 3G when it started on WiFi, but then the phone locks onto WiFi again so
+ * the prompt automatically goes away)
+ * <p/>
+ * The application interface for the downloader also needs to understand and
+ * handle these transient states.
+ */
+public class DownloadNotification implements IDownloaderClient {
+
+ private int mState;
+ private final Context mContext;
+ private final NotificationManager mNotificationManager;
+ private String mCurrentTitle;
+
+ private IDownloaderClient mClientProxy;
+ final ICustomNotification mCustomNotification;
+ private Notification mNotification;
+ private Notification mCurrentNotification;
+ private CharSequence mLabel;
+ private String mCurrentText;
+ private PendingIntent mContentIntent;
+ private DownloadProgressInfo mProgressInfo;
+
+ static final String LOGTAG = "DownloadNotification";
+ static final int NOTIFICATION_ID = LOGTAG.hashCode();
+
+ public PendingIntent getClientIntent() {
+ return mContentIntent;
+ }
+
+ public void setClientIntent(PendingIntent mClientIntent) {
+ this.mContentIntent = mClientIntent;
+ }
+
+ public void resendState() {
+ if (null != mClientProxy) {
+ mClientProxy.onDownloadStateChanged(mState);
+ }
+ }
+
+ @Override
+ public void onDownloadStateChanged(int newState) {
+ if (null != mClientProxy) {
+ mClientProxy.onDownloadStateChanged(newState);
+ }
+ if (newState != mState) {
+ mState = newState;
+ if (newState == IDownloaderClient.STATE_IDLE || null == mContentIntent) {
+ return;
+ }
+ int stringDownloadID;
+ int iconResource;
+ boolean ongoingEvent;
+
+ // get the new title string and paused text
+ switch (newState) {
+ case 0:
+ iconResource = android.R.drawable.stat_sys_warning;
+ stringDownloadID = R.string.state_unknown;
+ ongoingEvent = false;
+ break;
+
+ case IDownloaderClient.STATE_DOWNLOADING:
+ iconResource = android.R.drawable.stat_sys_download;
+ stringDownloadID = Helpers.getDownloaderStringResourceIDFromState(newState);
+ ongoingEvent = true;
+ break;
+
+ case IDownloaderClient.STATE_FETCHING_URL:
+ case IDownloaderClient.STATE_CONNECTING:
+ iconResource = android.R.drawable.stat_sys_download_done;
+ stringDownloadID = Helpers.getDownloaderStringResourceIDFromState(newState);
+ ongoingEvent = true;
+ break;
+
+ case IDownloaderClient.STATE_COMPLETED:
+ case IDownloaderClient.STATE_PAUSED_BY_REQUEST:
+ iconResource = android.R.drawable.stat_sys_download_done;
+ stringDownloadID = Helpers.getDownloaderStringResourceIDFromState(newState);
+ ongoingEvent = false;
+ break;
+
+ case IDownloaderClient.STATE_FAILED:
+ case IDownloaderClient.STATE_FAILED_CANCELED:
+ case IDownloaderClient.STATE_FAILED_FETCHING_URL:
+ case IDownloaderClient.STATE_FAILED_SDCARD_FULL:
+ case IDownloaderClient.STATE_FAILED_UNLICENSED:
+ iconResource = android.R.drawable.stat_sys_warning;
+ stringDownloadID = Helpers.getDownloaderStringResourceIDFromState(newState);
+ ongoingEvent = false;
+ break;
+
+ default:
+ iconResource = android.R.drawable.stat_sys_warning;
+ stringDownloadID = Helpers.getDownloaderStringResourceIDFromState(newState);
+ ongoingEvent = true;
+ break;
+ }
+ mCurrentText = mContext.getString(stringDownloadID);
+ mCurrentTitle = mLabel.toString();
+ mCurrentNotification.tickerText = mLabel + ": " + mCurrentText;
+ mCurrentNotification.icon = iconResource;
+ mCurrentNotification.setLatestEventInfo(mContext, mCurrentTitle, mCurrentText,
+ mContentIntent);
+ if (ongoingEvent) {
+ mCurrentNotification.flags |= Notification.FLAG_ONGOING_EVENT;
+ } else {
+ mCurrentNotification.flags &= ~Notification.FLAG_ONGOING_EVENT;
+ mCurrentNotification.flags |= Notification.FLAG_AUTO_CANCEL;
+ }
+ mNotificationManager.notify(NOTIFICATION_ID, mCurrentNotification);
+ }
+ }
+
+ @Override
+ public void onDownloadProgress(DownloadProgressInfo progress) {
+ mProgressInfo = progress;
+ if (null != mClientProxy) {
+ mClientProxy.onDownloadProgress(progress);
+ }
+ if (progress.mOverallTotal <= 0) {
+ // we just show the text
+ mNotification.tickerText = mCurrentTitle;
+ mNotification.icon = android.R.drawable.stat_sys_download;
+ mNotification.setLatestEventInfo(mContext, mLabel, mCurrentText, mContentIntent);
+ mCurrentNotification = mNotification;
+ } else {
+ mCustomNotification.setCurrentBytes(progress.mOverallProgress);
+ mCustomNotification.setTotalBytes(progress.mOverallTotal);
+ mCustomNotification.setIcon(android.R.drawable.stat_sys_download);
+ mCustomNotification.setPendingIntent(mContentIntent);
+ mCustomNotification.setTicker(mLabel + ": " + mCurrentText);
+ mCustomNotification.setTitle(mLabel);
+ mCustomNotification.setTimeRemaining(progress.mTimeRemaining);
+ mCurrentNotification = mCustomNotification.updateNotification(mContext);
+ }
+ mNotificationManager.notify(NOTIFICATION_ID, mCurrentNotification);
+ }
+
+ public interface ICustomNotification {
+ void setTitle(CharSequence title);
+
+ void setTicker(CharSequence ticker);
+
+ void setPendingIntent(PendingIntent mContentIntent);
+
+ void setTotalBytes(long totalBytes);
+
+ void setCurrentBytes(long currentBytes);
+
+ void setIcon(int iconResource);
+
+ void setTimeRemaining(long timeRemaining);
+
+ Notification updateNotification(Context c);
+ }
+
+ /**
+ * Called in response to onClientUpdated. Creates a new proxy and notifies
+ * it of the current state.
+ *
+ * @param msg the client Messenger to notify
+ */
+ public void setMessenger(Messenger msg) {
+ mClientProxy = DownloaderClientMarshaller.CreateProxy(msg);
+ if (null != mProgressInfo) {
+ mClientProxy.onDownloadProgress(mProgressInfo);
+ }
+ if (mState != -1) {
+ mClientProxy.onDownloadStateChanged(mState);
+ }
+ }
+
+ /**
+ * Constructor
+ *
+ * @param ctx The context to use to obtain access to the Notification
+ * Service
+ */
+ DownloadNotification(Context ctx, CharSequence applicationLabel) {
+ mState = -1;
+ mContext = ctx;
+ mLabel = applicationLabel;
+ mNotificationManager = (NotificationManager)
+ mContext.getSystemService(Context.NOTIFICATION_SERVICE);
+ mCustomNotification = CustomNotificationFactory
+ .createCustomNotification();
+ mNotification = new Notification();
+ mCurrentNotification = mNotification;
+
+ }
+
+ @Override
+ public void onServiceConnected(Messenger m) {
+ }
+
+}
diff --git a/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/DownloadThread.java b/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/DownloadThread.java
new file mode 100644
index 0000000000..056d1eca0b
--- /dev/null
+++ b/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/DownloadThread.java
@@ -0,0 +1,963 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.android.vending.expansion.downloader.impl;
+
+import com.google.android.vending.expansion.downloader.Constants;
+import com.google.android.vending.expansion.downloader.Helpers;
+import com.google.android.vending.expansion.downloader.IDownloaderClient;
+
+import org.apache.http.Header;
+import org.apache.http.HttpHost;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.conn.params.ConnRouteParams;
+
+import android.content.Context;
+import android.net.Proxy;
+import android.os.PowerManager;
+import android.os.Process;
+import android.util.Log;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.SyncFailedException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.Locale;
+
+/**
+ * Runs an actual download
+ */
+public class DownloadThread {
+
+ private Context mContext;
+ private DownloadInfo mInfo;
+ private DownloaderService mService;
+ private final DownloadsDB mDB;
+ private final DownloadNotification mNotification;
+ private String mUserAgent;
+
+ public DownloadThread(DownloadInfo info, DownloaderService service,
+ DownloadNotification notification) {
+ mContext = service;
+ mInfo = info;
+ mService = service;
+ mNotification = notification;
+ mDB = DownloadsDB.getDB(service);
+ mUserAgent = "APKXDL (Linux; U; Android " + android.os.Build.VERSION.RELEASE + ";"
+ + Locale.getDefault().toString() + "; " + android.os.Build.DEVICE + "/"
+ + android.os.Build.ID + ")" +
+ service.getPackageName();
+ }
+
+ /**
+ * Returns the default user agent
+ */
+ private String userAgent() {
+ return mUserAgent;
+ }
+
+ /**
+ * State for the entire run() method.
+ */
+ private static class State {
+ public String mFilename;
+ public FileOutputStream mStream;
+ public boolean mCountRetry = false;
+ public int mRetryAfter = 0;
+ public int mRedirectCount = 0;
+ public String mNewUri;
+ public boolean mGotData = false;
+ public String mRequestUri;
+
+ public State(DownloadInfo info, DownloaderService service) {
+ mRedirectCount = info.mRedirectCount;
+ mRequestUri = info.mUri;
+ mFilename = service.generateTempSaveFileName(info.mFileName);
+ }
+ }
+
+ /**
+ * State within executeDownload()
+ */
+ private static class InnerState {
+ public int mBytesSoFar = 0;
+ public int mBytesThisSession = 0;
+ public String mHeaderETag;
+ public boolean mContinuingDownload = false;
+ public String mHeaderContentLength;
+ public String mHeaderContentDisposition;
+ public String mHeaderContentLocation;
+ public int mBytesNotified = 0;
+ public long mTimeLastNotification = 0;
+ }
+
+ /**
+ * Raised from methods called by run() to indicate that the current request
+ * should be stopped immediately. Note the message passed to this exception
+ * will be logged and therefore must be guaranteed not to contain any PII,
+ * meaning it generally can't include any information about the request URI,
+ * headers, or destination filename.
+ */
+ private class StopRequest extends Throwable {
+ /**
+ *
+ */
+ private static final long serialVersionUID = 6338592678988347973L;
+ public int mFinalStatus;
+
+ public StopRequest(int finalStatus, String message) {
+ super(message);
+ mFinalStatus = finalStatus;
+ }
+
+ public StopRequest(int finalStatus, String message, Throwable throwable) {
+ super(message, throwable);
+ mFinalStatus = finalStatus;
+ }
+ }
+
+ /**
+ * Raised from methods called by executeDownload() to indicate that the
+ * download should be retried immediately.
+ */
+ private class RetryDownload extends Throwable {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 6196036036517540229L;
+ }
+
+ /**
+ * Returns the preferred proxy to be used by clients. This is a wrapper
+ * around {@link android.net.Proxy#getHost()}. Currently no proxy will be
+ * returned for localhost or if the active network is Wi-Fi.
+ *
+ * @param context the context which will be passed to
+ * {@link android.net.Proxy#getHost()}
+ * @param url the target URL for the request
+ * @note Calling this method requires permission
+ * android.permission.ACCESS_NETWORK_STATE
+ * @return The preferred proxy to be used by clients, or null if there is no
+ * proxy.
+ */
+ public HttpHost getPreferredHttpHost(Context context,
+ String url) {
+ if (!isLocalHost(url) && !mService.isWiFi()) {
+ final String proxyHost = Proxy.getHost(context);
+ if (proxyHost != null) {
+ return new HttpHost(proxyHost, Proxy.getPort(context), "http");
+ }
+ }
+
+ return null;
+ }
+
+ static final private boolean isLocalHost(String url) {
+ if (url == null) {
+ return false;
+ }
+
+ try {
+ final URI uri = URI.create(url);
+ final String host = uri.getHost();
+ if (host != null) {
+ // TODO: InetAddress.isLoopbackAddress should be used to check
+ // for localhost. However no public factory methods exist which
+ // can be used without triggering DNS lookup if host is not
+ // localhost.
+ if (host.equalsIgnoreCase("localhost") ||
+ host.equals("127.0.0.1") ||
+ host.equals("[::1]")) {
+ return true;
+ }
+ }
+ } catch (IllegalArgumentException iex) {
+ // Ignore (URI.create)
+ }
+
+ return false;
+ }
+
+ /**
+ * Executes the download in a separate thread
+ */
+ public void run() {
+ Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
+
+ State state = new State(mInfo, mService);
+ AndroidHttpClient client = null;
+ PowerManager.WakeLock wakeLock = null;
+ int finalStatus = DownloaderService.STATUS_UNKNOWN_ERROR;
+
+ try {
+ PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
+ wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, Constants.TAG);
+ wakeLock.acquire();
+
+ if (Constants.LOGV) {
+ Log.v(Constants.TAG, "initiating download for " + mInfo.mFileName);
+ Log.v(Constants.TAG, " at " + mInfo.mUri);
+ }
+
+ client = AndroidHttpClient.newInstance(userAgent(), mContext);
+
+ boolean finished = false;
+ while (!finished) {
+ if (Constants.LOGV) {
+ Log.v(Constants.TAG, "initiating download for " + mInfo.mFileName);
+ Log.v(Constants.TAG, " at " + mInfo.mUri);
+ }
+ // Set or unset proxy, which may have changed since last GET
+ // request.
+ // setDefaultProxy() supports null as proxy parameter.
+ ConnRouteParams.setDefaultProxy(client.getParams(),
+ getPreferredHttpHost(mContext, state.mRequestUri));
+ HttpGet request = new HttpGet(state.mRequestUri);
+ try {
+ executeDownload(state, client, request);
+ finished = true;
+ } catch (RetryDownload exc) {
+ // fall through
+ } finally {
+ request.abort();
+ request = null;
+ }
+ }
+
+ if (Constants.LOGV) {
+ Log.v(Constants.TAG, "download completed for " + mInfo.mFileName);
+ Log.v(Constants.TAG, " at " + mInfo.mUri);
+ }
+ finalizeDestinationFile(state);
+ finalStatus = DownloaderService.STATUS_SUCCESS;
+ } catch (StopRequest error) {
+ // remove the cause before printing, in case it contains PII
+ Log.w(Constants.TAG,
+ "Aborting request for download " + mInfo.mFileName + ": " + error.getMessage());
+ error.printStackTrace();
+ finalStatus = error.mFinalStatus;
+ // fall through to finally block
+ } catch (Throwable ex) { // sometimes the socket code throws unchecked
+ // exceptions
+ Log.w(Constants.TAG, "Exception for " + mInfo.mFileName + ": " + ex);
+ finalStatus = DownloaderService.STATUS_UNKNOWN_ERROR;
+ // falls through to the code that reports an error
+ } finally {
+ if (wakeLock != null) {
+ wakeLock.release();
+ wakeLock = null;
+ }
+ if (client != null) {
+ client.close();
+ client = null;
+ }
+ cleanupDestination(state, finalStatus);
+ notifyDownloadCompleted(finalStatus, state.mCountRetry, state.mRetryAfter,
+ state.mRedirectCount, state.mGotData, state.mFilename);
+ }
+ }
+
+ /**
+ * Fully execute a single download request - setup and send the request,
+ * handle the response, and transfer the data to the destination file.
+ */
+ private void executeDownload(State state, AndroidHttpClient client, HttpGet request)
+ throws StopRequest, RetryDownload {
+ InnerState innerState = new InnerState();
+ byte data[] = new byte[Constants.BUFFER_SIZE];
+
+ checkPausedOrCanceled(state);
+
+ setupDestinationFile(state, innerState);
+ addRequestHeaders(innerState, request);
+
+ // check just before sending the request to avoid using an invalid
+ // connection at all
+ checkConnectivity(state);
+
+ mNotification.onDownloadStateChanged(IDownloaderClient.STATE_CONNECTING);
+ HttpResponse response = sendRequest(state, client, request);
+ handleExceptionalStatus(state, innerState, response);
+
+ if (Constants.LOGV) {
+ Log.v(Constants.TAG, "received response for " + mInfo.mUri);
+ }
+
+ processResponseHeaders(state, innerState, response);
+ InputStream entityStream = openResponseEntity(state, response);
+ mNotification.onDownloadStateChanged(IDownloaderClient.STATE_DOWNLOADING);
+ transferData(state, innerState, data, entityStream);
+ }
+
+ /**
+ * Check if current connectivity is valid for this request.
+ */
+ private void checkConnectivity(State state) throws StopRequest {
+ switch (mService.getNetworkAvailabilityState(mDB)) {
+ case DownloaderService.NETWORK_OK:
+ return;
+ case DownloaderService.NETWORK_NO_CONNECTION:
+ throw new StopRequest(DownloaderService.STATUS_WAITING_FOR_NETWORK,
+ "waiting for network to return");
+ case DownloaderService.NETWORK_TYPE_DISALLOWED_BY_REQUESTOR:
+ throw new StopRequest(
+ DownloaderService.STATUS_QUEUED_FOR_WIFI_OR_CELLULAR_PERMISSION,
+ "waiting for wifi or for download over cellular to be authorized");
+ case DownloaderService.NETWORK_CANNOT_USE_ROAMING:
+ throw new StopRequest(DownloaderService.STATUS_WAITING_FOR_NETWORK,
+ "roaming is not allowed");
+ case DownloaderService.NETWORK_UNUSABLE_DUE_TO_SIZE:
+ throw new StopRequest(DownloaderService.STATUS_QUEUED_FOR_WIFI, "waiting for wifi");
+ }
+ }
+
+ /**
+ * Transfer as much data as possible from the HTTP response to the
+ * destination file.
+ *
+ * @param data buffer to use to read data
+ * @param entityStream stream for reading the HTTP response entity
+ */
+ private void transferData(State state, InnerState innerState, byte[] data,
+ InputStream entityStream) throws StopRequest {
+ for (;;) {
+ int bytesRead = readFromResponse(state, innerState, data, entityStream);
+ if (bytesRead == -1) { // success, end of stream already reached
+ handleEndOfStream(state, innerState);
+ return;
+ }
+
+ state.mGotData = true;
+ writeDataToDestination(state, data, bytesRead);
+ innerState.mBytesSoFar += bytesRead;
+ innerState.mBytesThisSession += bytesRead;
+ reportProgress(state, innerState);
+
+ checkPausedOrCanceled(state);
+ }
+ }
+
+ /**
+ * Called after a successful completion to take any necessary action on the
+ * downloaded file.
+ */
+ private void finalizeDestinationFile(State state) throws StopRequest {
+ syncDestination(state);
+ String tempFilename = state.mFilename;
+ String finalFilename = Helpers.generateSaveFileName(mService, mInfo.mFileName);
+ if (!state.mFilename.equals(finalFilename)) {
+ File startFile = new File(tempFilename);
+ File destFile = new File(finalFilename);
+ if (mInfo.mTotalBytes != -1 && mInfo.mCurrentBytes == mInfo.mTotalBytes) {
+ if (!startFile.renameTo(destFile)) {
+ throw new StopRequest(DownloaderService.STATUS_FILE_ERROR,
+ "unable to finalize destination file");
+ }
+ } else {
+ throw new StopRequest(DownloaderService.STATUS_FILE_DELIVERED_INCORRECTLY,
+ "file delivered with incorrect size. probably due to network not browser configured");
+ }
+ }
+ }
+
+ /**
+ * Called just before the thread finishes, regardless of status, to take any
+ * necessary action on the downloaded file.
+ */
+ private void cleanupDestination(State state, int finalStatus) {
+ closeDestination(state);
+ if (state.mFilename != null && DownloaderService.isStatusError(finalStatus)) {
+ new File(state.mFilename).delete();
+ state.mFilename = null;
+ }
+ }
+
+ /**
+ * Sync the destination file to storage.
+ */
+ private void syncDestination(State state) {
+ FileOutputStream downloadedFileStream = null;
+ try {
+ downloadedFileStream = new FileOutputStream(state.mFilename, true);
+ downloadedFileStream.getFD().sync();
+ } catch (FileNotFoundException ex) {
+ Log.w(Constants.TAG, "file " + state.mFilename + " not found: " + ex);
+ } catch (SyncFailedException ex) {
+ Log.w(Constants.TAG, "file " + state.mFilename + " sync failed: " + ex);
+ } catch (IOException ex) {
+ Log.w(Constants.TAG, "IOException trying to sync " + state.mFilename + ": " + ex);
+ } catch (RuntimeException ex) {
+ Log.w(Constants.TAG, "exception while syncing file: ", ex);
+ } finally {
+ if (downloadedFileStream != null) {
+ try {
+ downloadedFileStream.close();
+ } catch (IOException ex) {
+ Log.w(Constants.TAG, "IOException while closing synced file: ", ex);
+ } catch (RuntimeException ex) {
+ Log.w(Constants.TAG, "exception while closing file: ", ex);
+ }
+ }
+ }
+ }
+
+ /**
+ * Close the destination output stream.
+ */
+ private void closeDestination(State state) {
+ try {
+ // close the file
+ if (state.mStream != null) {
+ state.mStream.close();
+ state.mStream = null;
+ }
+ } catch (IOException ex) {
+ if (Constants.LOGV) {
+ Log.v(Constants.TAG, "exception when closing the file after download : " + ex);
+ }
+ // nothing can really be done if the file can't be closed
+ }
+ }
+
+ /**
+ * Check if the download has been paused or canceled, stopping the request
+ * appropriately if it has been.
+ */
+ private void checkPausedOrCanceled(State state) throws StopRequest {
+ if (mService.getControl() == DownloaderService.CONTROL_PAUSED) {
+ int status = mService.getStatus();
+ switch (status) {
+ case DownloaderService.STATUS_PAUSED_BY_APP:
+ throw new StopRequest(mService.getStatus(),
+ "download paused");
+ }
+ }
+ }
+
+ /**
+ * Report download progress through the database if necessary.
+ */
+ private void reportProgress(State state, InnerState innerState) {
+ long now = System.currentTimeMillis();
+ if (innerState.mBytesSoFar - innerState.mBytesNotified
+ > Constants.MIN_PROGRESS_STEP
+ && now - innerState.mTimeLastNotification
+ > Constants.MIN_PROGRESS_TIME) {
+ // we store progress updates to the database here
+ mInfo.mCurrentBytes = innerState.mBytesSoFar;
+ mDB.updateDownloadCurrentBytes(mInfo);
+
+ innerState.mBytesNotified = innerState.mBytesSoFar;
+ innerState.mTimeLastNotification = now;
+
+ long totalBytesSoFar = innerState.mBytesThisSession + mService.mBytesSoFar;
+
+ if (Constants.LOGVV) {
+ Log.v(Constants.TAG, "downloaded " + mInfo.mCurrentBytes + " out of "
+ + mInfo.mTotalBytes);
+ Log.v(Constants.TAG, " total " + totalBytesSoFar + " out of "
+ + mService.mTotalLength);
+ }
+
+ mService.notifyUpdateBytes(totalBytesSoFar);
+ }
+ }
+
+ /**
+ * Write a data buffer to the destination file.
+ *
+ * @param data buffer containing the data to write
+ * @param bytesRead how many bytes to write from the buffer
+ */
+ private void writeDataToDestination(State state, byte[] data, int bytesRead)
+ throws StopRequest {
+ for (;;) {
+ try {
+ if (state.mStream == null) {
+ state.mStream = new FileOutputStream(state.mFilename, true);
+ }
+ state.mStream.write(data, 0, bytesRead);
+ // we close after every write --- this may be too inefficient
+ closeDestination(state);
+ return;
+ } catch (IOException ex) {
+ if (!Helpers.isExternalMediaMounted()) {
+ throw new StopRequest(DownloaderService.STATUS_DEVICE_NOT_FOUND_ERROR,
+ "external media not mounted while writing destination file");
+ }
+
+ long availableBytes =
+ Helpers.getAvailableBytes(Helpers.getFilesystemRoot(state.mFilename));
+ if (availableBytes < bytesRead) {
+ throw new StopRequest(DownloaderService.STATUS_INSUFFICIENT_SPACE_ERROR,
+ "insufficient space while writing destination file", ex);
+ }
+ throw new StopRequest(DownloaderService.STATUS_FILE_ERROR,
+ "while writing destination file: " + ex.toString(), ex);
+ }
+ }
+ }
+
+ /**
+ * Called when we've reached the end of the HTTP response stream, to update
+ * the database and check for consistency.
+ */
+ private void handleEndOfStream(State state, InnerState innerState) throws StopRequest {
+ mInfo.mCurrentBytes = innerState.mBytesSoFar;
+ // this should always be set from the market
+ // if ( innerState.mHeaderContentLength == null ) {
+ // mInfo.mTotalBytes = innerState.mBytesSoFar;
+ // }
+ mDB.updateDownload(mInfo);
+
+ boolean lengthMismatched = (innerState.mHeaderContentLength != null)
+ && (innerState.mBytesSoFar != Integer.parseInt(innerState.mHeaderContentLength));
+ if (lengthMismatched) {
+ if (cannotResume(innerState)) {
+ throw new StopRequest(DownloaderService.STATUS_CANNOT_RESUME,
+ "mismatched content length");
+ } else {
+ throw new StopRequest(getFinalStatusForHttpError(state),
+ "closed socket before end of file");
+ }
+ }
+ }
+
+ private boolean cannotResume(InnerState innerState) {
+ return innerState.mBytesSoFar > 0 && innerState.mHeaderETag == null;
+ }
+
+ /**
+ * Read some data from the HTTP response stream, handling I/O errors.
+ *
+ * @param data buffer to use to read data
+ * @param entityStream stream for reading the HTTP response entity
+ * @return the number of bytes actually read or -1 if the end of the stream
+ * has been reached
+ */
+ private int readFromResponse(State state, InnerState innerState, byte[] data,
+ InputStream entityStream) throws StopRequest {
+ try {
+ return entityStream.read(data);
+ } catch (IOException ex) {
+ logNetworkState();
+ mInfo.mCurrentBytes = innerState.mBytesSoFar;
+ mDB.updateDownload(mInfo);
+ if (cannotResume(innerState)) {
+ String message = "while reading response: " + ex.toString()
+ + ", can't resume interrupted download with no ETag";
+ throw new StopRequest(DownloaderService.STATUS_CANNOT_RESUME,
+ message, ex);
+ } else {
+ throw new StopRequest(getFinalStatusForHttpError(state),
+ "while reading response: " + ex.toString(), ex);
+ }
+ }
+ }
+
+ /**
+ * Open a stream for the HTTP response entity, handling I/O errors.
+ *
+ * @return an InputStream to read the response entity
+ */
+ private InputStream openResponseEntity(State state, HttpResponse response)
+ throws StopRequest {
+ try {
+ return response.getEntity().getContent();
+ } catch (IOException ex) {
+ logNetworkState();
+ throw new StopRequest(getFinalStatusForHttpError(state),
+ "while getting entity: " + ex.toString(), ex);
+ }
+ }
+
+ private void logNetworkState() {
+ if (Constants.LOGX) {
+ Log.i(Constants.TAG,
+ "Net "
+ + (mService.getNetworkAvailabilityState(mDB) == DownloaderService.NETWORK_OK ? "Up"
+ : "Down"));
+ }
+ }
+
+ /**
+ * Read HTTP response headers and take appropriate action, including setting
+ * up the destination file and updating the database.
+ */
+ private void processResponseHeaders(State state, InnerState innerState, HttpResponse response)
+ throws StopRequest {
+ if (innerState.mContinuingDownload) {
+ // ignore response headers on resume requests
+ return;
+ }
+
+ readResponseHeaders(state, innerState, response);
+
+ try {
+ state.mFilename = mService.generateSaveFile(mInfo.mFileName, mInfo.mTotalBytes);
+ } catch (DownloaderService.GenerateSaveFileError exc) {
+ throw new StopRequest(exc.mStatus, exc.mMessage);
+ }
+ try {
+ state.mStream = new FileOutputStream(state.mFilename);
+ } catch (FileNotFoundException exc) {
+ // make sure the directory exists
+ File pathFile = new File(Helpers.getSaveFilePath(mService));
+ try {
+ if (pathFile.mkdirs()) {
+ state.mStream = new FileOutputStream(state.mFilename);
+ }
+ } catch (Exception ex) {
+ throw new StopRequest(DownloaderService.STATUS_FILE_ERROR,
+ "while opening destination file: " + exc.toString(), exc);
+ }
+ }
+ if (Constants.LOGV) {
+ Log.v(Constants.TAG, "writing " + mInfo.mUri + " to " + state.mFilename);
+ }
+
+ updateDatabaseFromHeaders(state, innerState);
+ // check connectivity again now that we know the total size
+ checkConnectivity(state);
+ }
+
+ /**
+ * Update necessary database fields based on values of HTTP response headers
+ * that have been read.
+ */
+ private void updateDatabaseFromHeaders(State state, InnerState innerState) {
+ mInfo.mETag = innerState.mHeaderETag;
+ mDB.updateDownload(mInfo);
+ }
+
+ /**
+ * Read headers from the HTTP response and store them into local state.
+ */
+ private void readResponseHeaders(State state, InnerState innerState, HttpResponse response)
+ throws StopRequest {
+ Header header = response.getFirstHeader("Content-Disposition");
+ if (header != null) {
+ innerState.mHeaderContentDisposition = header.getValue();
+ }
+ header = response.getFirstHeader("Content-Location");
+ if (header != null) {
+ innerState.mHeaderContentLocation = header.getValue();
+ }
+ header = response.getFirstHeader("ETag");
+ if (header != null) {
+ innerState.mHeaderETag = header.getValue();
+ }
+ String headerTransferEncoding = null;
+ header = response.getFirstHeader("Transfer-Encoding");
+ if (header != null) {
+ headerTransferEncoding = header.getValue();
+ }
+ String headerContentType = null;
+ header = response.getFirstHeader("Content-Type");
+ if (header != null) {
+ headerContentType = header.getValue();
+ if (!headerContentType.equals("application/vnd.android.obb")) {
+ throw new StopRequest(DownloaderService.STATUS_FILE_DELIVERED_INCORRECTLY,
+ "file delivered with incorrect Mime type");
+ }
+ }
+
+ if (headerTransferEncoding == null) {
+ header = response.getFirstHeader("Content-Length");
+ if (header != null) {
+ innerState.mHeaderContentLength = header.getValue();
+ // this is always set from Market
+ long contentLength = Long.parseLong(innerState.mHeaderContentLength);
+ if (contentLength != -1 && contentLength != mInfo.mTotalBytes) {
+ // we're most likely on a bad wifi connection -- we should
+ // probably
+ // also look at the mime type --- but the size mismatch is
+ // enough
+ // to tell us that something is wrong here
+ Log.e(Constants.TAG, "Incorrect file size delivered.");
+ }
+ }
+ } else {
+ // Ignore content-length with transfer-encoding - 2616 4.4 3
+ if (Constants.LOGVV) {
+ Log.v(Constants.TAG,
+ "ignoring content-length because of xfer-encoding");
+ }
+ }
+ if (Constants.LOGVV) {
+ Log.v(Constants.TAG, "Content-Disposition: " +
+ innerState.mHeaderContentDisposition);
+ Log.v(Constants.TAG, "Content-Length: " + innerState.mHeaderContentLength);
+ Log.v(Constants.TAG, "Content-Location: " + innerState.mHeaderContentLocation);
+ Log.v(Constants.TAG, "ETag: " + innerState.mHeaderETag);
+ Log.v(Constants.TAG, "Transfer-Encoding: " + headerTransferEncoding);
+ }
+
+ boolean noSizeInfo = innerState.mHeaderContentLength == null
+ && (headerTransferEncoding == null
+ || !headerTransferEncoding.equalsIgnoreCase("chunked"));
+ if (noSizeInfo) {
+ throw new StopRequest(DownloaderService.STATUS_HTTP_DATA_ERROR,
+ "can't know size of download, giving up");
+ }
+ }
+
+ /**
+ * Check the HTTP response status and handle anything unusual (e.g. not
+ * 200/206).
+ */
+ private void handleExceptionalStatus(State state, InnerState innerState, HttpResponse response)
+ throws StopRequest, RetryDownload {
+ int statusCode = response.getStatusLine().getStatusCode();
+ if (statusCode == 503 && mInfo.mNumFailed < Constants.MAX_RETRIES) {
+ handleServiceUnavailable(state, response);
+ }
+ if (statusCode == 301 || statusCode == 302 || statusCode == 303 || statusCode == 307) {
+ handleRedirect(state, response, statusCode);
+ }
+
+ int expectedStatus = innerState.mContinuingDownload ? 206
+ : DownloaderService.STATUS_SUCCESS;
+ if (statusCode != expectedStatus) {
+ handleOtherStatus(state, innerState, statusCode);
+ } else {
+ // no longer redirected
+ state.mRedirectCount = 0;
+ }
+ }
+
+ /**
+ * Handle a status that we don't know how to deal with properly.
+ */
+ private void handleOtherStatus(State state, InnerState innerState, int statusCode)
+ throws StopRequest {
+ int finalStatus;
+ if (DownloaderService.isStatusError(statusCode)) {
+ finalStatus = statusCode;
+ } else if (statusCode >= 300 && statusCode < 400) {
+ finalStatus = DownloaderService.STATUS_UNHANDLED_REDIRECT;
+ } else if (innerState.mContinuingDownload && statusCode == DownloaderService.STATUS_SUCCESS) {
+ finalStatus = DownloaderService.STATUS_CANNOT_RESUME;
+ } else {
+ finalStatus = DownloaderService.STATUS_UNHANDLED_HTTP_CODE;
+ }
+ throw new StopRequest(finalStatus, "http error " + statusCode);
+ }
+
+ /**
+ * Handle a 3xx redirect status.
+ */
+ private void handleRedirect(State state, HttpResponse response, int statusCode)
+ throws StopRequest, RetryDownload {
+ if (Constants.LOGVV) {
+ Log.v(Constants.TAG, "got HTTP redirect " + statusCode);
+ }
+ if (state.mRedirectCount >= Constants.MAX_REDIRECTS) {
+ throw new StopRequest(DownloaderService.STATUS_TOO_MANY_REDIRECTS, "too many redirects");
+ }
+ Header header = response.getFirstHeader("Location");
+ if (header == null) {
+ return;
+ }
+ if (Constants.LOGVV) {
+ Log.v(Constants.TAG, "Location :" + header.getValue());
+ }
+
+ String newUri;
+ try {
+ newUri = new URI(mInfo.mUri).resolve(new URI(header.getValue())).toString();
+ } catch (URISyntaxException ex) {
+ if (Constants.LOGV) {
+ Log.d(Constants.TAG, "Couldn't resolve redirect URI " + header.getValue()
+ + " for " + mInfo.mUri);
+ }
+ throw new StopRequest(DownloaderService.STATUS_HTTP_DATA_ERROR,
+ "Couldn't resolve redirect URI");
+ }
+ ++state.mRedirectCount;
+ state.mRequestUri = newUri;
+ if (statusCode == 301 || statusCode == 303) {
+ // use the new URI for all future requests (should a retry/resume be
+ // necessary)
+ state.mNewUri = newUri;
+ }
+ throw new RetryDownload();
+ }
+
+ /**
+ * Add headers for this download to the HTTP request to allow for resume.
+ */
+ private void addRequestHeaders(InnerState innerState, HttpGet request) {
+ if (innerState.mContinuingDownload) {
+ if (innerState.mHeaderETag != null) {
+ request.addHeader("If-Match", innerState.mHeaderETag);
+ }
+ request.addHeader("Range", "bytes=" + innerState.mBytesSoFar + "-");
+ }
+ }
+
+ /**
+ * Handle a 503 Service Unavailable status by processing the Retry-After
+ * header.
+ */
+ private void handleServiceUnavailable(State state, HttpResponse response) throws StopRequest {
+ if (Constants.LOGVV) {
+ Log.v(Constants.TAG, "got HTTP response code 503");
+ }
+ state.mCountRetry = true;
+ Header header = response.getFirstHeader("Retry-After");
+ if (header != null) {
+ try {
+ if (Constants.LOGVV) {
+ Log.v(Constants.TAG, "Retry-After :" + header.getValue());
+ }
+ state.mRetryAfter = Integer.parseInt(header.getValue());
+ if (state.mRetryAfter < 0) {
+ state.mRetryAfter = 0;
+ } else {
+ if (state.mRetryAfter < Constants.MIN_RETRY_AFTER) {
+ state.mRetryAfter = Constants.MIN_RETRY_AFTER;
+ } else if (state.mRetryAfter > Constants.MAX_RETRY_AFTER) {
+ state.mRetryAfter = Constants.MAX_RETRY_AFTER;
+ }
+ state.mRetryAfter += Helpers.sRandom.nextInt(Constants.MIN_RETRY_AFTER + 1);
+ state.mRetryAfter *= 1000;
+ }
+ } catch (NumberFormatException ex) {
+ // ignored - retryAfter stays 0 in this case.
+ }
+ }
+ throw new StopRequest(DownloaderService.STATUS_WAITING_TO_RETRY,
+ "got 503 Service Unavailable, will retry later");
+ }
+
+ /**
+ * Send the request to the server, handling any I/O exceptions.
+ */
+ private HttpResponse sendRequest(State state, AndroidHttpClient client, HttpGet request)
+ throws StopRequest {
+ try {
+ return client.execute(request);
+ } catch (IllegalArgumentException ex) {
+ throw new StopRequest(DownloaderService.STATUS_HTTP_DATA_ERROR,
+ "while trying to execute request: " + ex.toString(), ex);
+ } catch (IOException ex) {
+ logNetworkState();
+ throw new StopRequest(getFinalStatusForHttpError(state),
+ "while trying to execute request: " + ex.toString(), ex);
+ }
+ }
+
+ private int getFinalStatusForHttpError(State state) {
+ if (mService.getNetworkAvailabilityState(mDB) != DownloaderService.NETWORK_OK) {
+ return DownloaderService.STATUS_WAITING_FOR_NETWORK;
+ } else if (mInfo.mNumFailed < Constants.MAX_RETRIES) {
+ state.mCountRetry = true;
+ return DownloaderService.STATUS_WAITING_TO_RETRY;
+ } else {
+ Log.w(Constants.TAG, "reached max retries for " + mInfo.mNumFailed);
+ return DownloaderService.STATUS_HTTP_DATA_ERROR;
+ }
+ }
+
+ /**
+ * Prepare the destination file to receive data. If the file already exists,
+ * we'll set up appropriately for resumption.
+ */
+ private void setupDestinationFile(State state, InnerState innerState)
+ throws StopRequest {
+ if (state.mFilename != null) { // only true if we've already run a
+ // thread for this download
+ if (!Helpers.isFilenameValid(state.mFilename)) {
+ // this should never happen
+ throw new StopRequest(DownloaderService.STATUS_FILE_ERROR,
+ "found invalid internal destination filename");
+ }
+ // We're resuming a download that got interrupted
+ File f = new File(state.mFilename);
+ if (f.exists()) {
+ long fileLength = f.length();
+ if (fileLength == 0) {
+ // The download hadn't actually started, we can restart from
+ // scratch
+ f.delete();
+ state.mFilename = null;
+ } else if (mInfo.mETag == null) {
+ // This should've been caught upon failure
+ f.delete();
+ throw new StopRequest(DownloaderService.STATUS_CANNOT_RESUME,
+ "Trying to resume a download that can't be resumed");
+ } else {
+ // All right, we'll be able to resume this download
+ try {
+ state.mStream = new FileOutputStream(state.mFilename, true);
+ } catch (FileNotFoundException exc) {
+ throw new StopRequest(DownloaderService.STATUS_FILE_ERROR,
+ "while opening destination for resuming: " + exc.toString(), exc);
+ }
+ innerState.mBytesSoFar = (int) fileLength;
+ if (mInfo.mTotalBytes != -1) {
+ innerState.mHeaderContentLength = Long.toString(mInfo.mTotalBytes);
+ }
+ innerState.mHeaderETag = mInfo.mETag;
+ innerState.mContinuingDownload = true;
+ }
+ }
+ }
+
+ if (state.mStream != null) {
+ closeDestination(state);
+ }
+ }
+
+ /**
+ * Stores information about the completed download, and notifies the
+ * initiating application.
+ */
+ private void notifyDownloadCompleted(
+ int status, boolean countRetry, int retryAfter, int redirectCount, boolean gotData,
+ String filename) {
+ updateDownloadDatabase(
+ status, countRetry, retryAfter, redirectCount, gotData, filename);
+ if (DownloaderService.isStatusCompleted(status)) {
+ // TBD: send status update?
+ }
+ }
+
+ private void updateDownloadDatabase(
+ int status, boolean countRetry, int retryAfter, int redirectCount, boolean gotData,
+ String filename) {
+ mInfo.mStatus = status;
+ mInfo.mRetryAfter = retryAfter;
+ mInfo.mRedirectCount = redirectCount;
+ mInfo.mLastMod = System.currentTimeMillis();
+ if (!countRetry) {
+ mInfo.mNumFailed = 0;
+ } else if (gotData) {
+ mInfo.mNumFailed = 1;
+ } else {
+ mInfo.mNumFailed++;
+ }
+ mDB.updateDownload(mInfo);
+ }
+
+}
diff --git a/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/DownloaderService.java b/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/DownloaderService.java
new file mode 100644
index 0000000000..627bf3eedd
--- /dev/null
+++ b/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/DownloaderService.java
@@ -0,0 +1,1341 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.android.vending.expansion.downloader.impl;
+
+import com.google.android.vending.expansion.downloader.Constants;
+import com.google.android.vending.expansion.downloader.DownloadProgressInfo;
+import com.google.android.vending.expansion.downloader.DownloaderServiceMarshaller;
+import com.google.android.vending.expansion.downloader.Helpers;
+import com.google.android.vending.expansion.downloader.IDownloaderClient;
+import com.google.android.vending.expansion.downloader.IDownloaderService;
+import com.google.android.vending.expansion.downloader.IStub;
+import com.google.android.vending.licensing.AESObfuscator;
+import com.google.android.vending.licensing.APKExpansionPolicy;
+import com.google.android.vending.licensing.LicenseChecker;
+import com.google.android.vending.licensing.LicenseCheckerCallback;
+import com.google.android.vending.licensing.Policy;
+
+import android.app.AlarmManager;
+import android.app.PendingIntent;
+import android.app.Service;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.net.wifi.WifiManager;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Messenger;
+import android.os.SystemClock;
+import android.provider.Settings.Secure;
+import android.telephony.TelephonyManager;
+import android.util.Log;
+
+import java.io.File;
+
+/**
+ * Performs the background downloads requested by applications that use the
+ * Downloads provider. This service does not run as a foreground task, so
+ * Android may kill it off at will, but it will try to restart itself if it can.
+ * Note that Android by default will kill off any process that has an open file
+ * handle on the shared (SD Card) partition if the partition is unmounted.
+ */
+public abstract class DownloaderService extends CustomIntentService implements IDownloaderService {
+
+ public DownloaderService() {
+ super("LVLDownloadService");
+ }
+
+ private static final String LOG_TAG = "LVLDL";
+
+ // the following NETWORK_* constants are used to indicates specific reasons
+ // for disallowing a
+ // download from using a network, since specific causes can require special
+ // handling
+
+ /**
+ * The network is usable for the given download.
+ */
+ public static final int NETWORK_OK = 1;
+
+ /**
+ * There is no network connectivity.
+ */
+ public static final int NETWORK_NO_CONNECTION = 2;
+
+ /**
+ * The download exceeds the maximum size for this network.
+ */
+ public static final int NETWORK_UNUSABLE_DUE_TO_SIZE = 3;
+
+ /**
+ * The download exceeds the recommended maximum size for this network, the
+ * user must confirm for this download to proceed without WiFi.
+ */
+ public static final int NETWORK_RECOMMENDED_UNUSABLE_DUE_TO_SIZE = 4;
+
+ /**
+ * The current connection is roaming, and the download can't proceed over a
+ * roaming connection.
+ */
+ public static final int NETWORK_CANNOT_USE_ROAMING = 5;
+
+ /**
+ * The app requesting the download specific that it can't use the current
+ * network connection.
+ */
+ public static final int NETWORK_TYPE_DISALLOWED_BY_REQUESTOR = 6;
+
+ /**
+ * For intents used to notify the user that a download exceeds a size
+ * threshold, if this extra is true, WiFi is required for this download
+ * size; otherwise, it is only recommended.
+ */
+ public static final String EXTRA_IS_WIFI_REQUIRED = "isWifiRequired";
+ public static final String EXTRA_FILE_NAME = "downloadId";
+
+ /**
+ * Used with DOWNLOAD_STATUS
+ */
+ public static final String EXTRA_STATUS_STATE = "ESS";
+ public static final String EXTRA_STATUS_TOTAL_SIZE = "ETS";
+ public static final String EXTRA_STATUS_CURRENT_FILE_SIZE = "CFS";
+ public static final String EXTRA_STATUS_TOTAL_PROGRESS = "TFP";
+ public static final String EXTRA_STATUS_CURRENT_PROGRESS = "CFP";
+
+ public static final String ACTION_DOWNLOADS_CHANGED = "downloadsChanged";
+
+ /**
+ * Broadcast intent action sent by the download manager when a download
+ * completes.
+ */
+ public final static String ACTION_DOWNLOAD_COMPLETE = "lvldownloader.intent.action.DOWNLOAD_COMPLETE";
+
+ /**
+ * Broadcast intent action sent by the download manager when download status
+ * changes.
+ */
+ public final static String ACTION_DOWNLOAD_STATUS = "lvldownloader.intent.action.DOWNLOAD_STATUS";
+
+ /*
+ * Lists the states that the download manager can set on a download to
+ * notify applications of the download progress. The codes follow the HTTP
+ * families:<br> 1xx: informational<br> 2xx: success<br> 3xx: redirects (not
+ * used by the download manager)<br> 4xx: client errors<br> 5xx: server
+ * errors
+ */
+
+ /**
+ * Returns whether the status is informational (i.e. 1xx).
+ */
+ public static boolean isStatusInformational(int status) {
+ return (status >= 100 && status < 200);
+ }
+
+ /**
+ * Returns whether the status is a success (i.e. 2xx).
+ */
+ public static boolean isStatusSuccess(int status) {
+ return (status >= 200 && status < 300);
+ }
+
+ /**
+ * Returns whether the status is an error (i.e. 4xx or 5xx).
+ */
+ public static boolean isStatusError(int status) {
+ return (status >= 400 && status < 600);
+ }
+
+ /**
+ * Returns whether the status is a client error (i.e. 4xx).
+ */
+ public static boolean isStatusClientError(int status) {
+ return (status >= 400 && status < 500);
+ }
+
+ /**
+ * Returns whether the status is a server error (i.e. 5xx).
+ */
+ public static boolean isStatusServerError(int status) {
+ return (status >= 500 && status < 600);
+ }
+
+ /**
+ * Returns whether the download has completed (either with success or
+ * error).
+ */
+ public static boolean isStatusCompleted(int status) {
+ return (status >= 200 && status < 300)
+ || (status >= 400 && status < 600);
+ }
+
+ /**
+ * This download hasn't stated yet
+ */
+ public static final int STATUS_PENDING = 190;
+
+ /**
+ * This download has started
+ */
+ public static final int STATUS_RUNNING = 192;
+
+ /**
+ * This download has been paused by the owning app.
+ */
+ public static final int STATUS_PAUSED_BY_APP = 193;
+
+ /**
+ * This download encountered some network error and is waiting before
+ * retrying the request.
+ */
+ public static final int STATUS_WAITING_TO_RETRY = 194;
+
+ /**
+ * This download is waiting for network connectivity to proceed.
+ */
+ public static final int STATUS_WAITING_FOR_NETWORK = 195;
+
+ /**
+ * This download is waiting for a Wi-Fi connection to proceed or for
+ * permission to download over cellular.
+ */
+ public static final int STATUS_QUEUED_FOR_WIFI_OR_CELLULAR_PERMISSION = 196;
+
+ /**
+ * This download is waiting for a Wi-Fi connection to proceed.
+ */
+ public static final int STATUS_QUEUED_FOR_WIFI = 197;
+
+ /**
+ * This download has successfully completed. Warning: there might be other
+ * status values that indicate success in the future. Use isSucccess() to
+ * capture the entire category.
+ *
+ * @hide
+ */
+ public static final int STATUS_SUCCESS = 200;
+
+ /**
+ * The requested URL is no longer available
+ */
+ public static final int STATUS_FORBIDDEN = 403;
+
+ /**
+ * The file was delivered incorrectly
+ */
+ public static final int STATUS_FILE_DELIVERED_INCORRECTLY = 487;
+
+ /**
+ * The requested destination file already exists.
+ */
+ public static final int STATUS_FILE_ALREADY_EXISTS_ERROR = 488;
+
+ /**
+ * Some possibly transient error occurred, but we can't resume the download.
+ */
+ public static final int STATUS_CANNOT_RESUME = 489;
+
+ /**
+ * This download was canceled
+ *
+ * @hide
+ */
+ public static final int STATUS_CANCELED = 490;
+
+ /**
+ * This download has completed with an error. Warning: there will be other
+ * status values that indicate errors in the future. Use isStatusError() to
+ * capture the entire category.
+ */
+ public static final int STATUS_UNKNOWN_ERROR = 491;
+
+ /**
+ * This download couldn't be completed because of a storage issue.
+ * Typically, that's because the filesystem is missing or full. Use the more
+ * specific {@link #STATUS_INSUFFICIENT_SPACE_ERROR} and
+ * {@link #STATUS_DEVICE_NOT_FOUND_ERROR} when appropriate.
+ *
+ * @hide
+ */
+ public static final int STATUS_FILE_ERROR = 492;
+
+ /**
+ * This download couldn't be completed because of an HTTP redirect response
+ * that the download manager couldn't handle.
+ *
+ * @hide
+ */
+ public static final int STATUS_UNHANDLED_REDIRECT = 493;
+
+ /**
+ * This download couldn't be completed because of an unspecified unhandled
+ * HTTP code.
+ *
+ * @hide
+ */
+ public static final int STATUS_UNHANDLED_HTTP_CODE = 494;
+
+ /**
+ * This download couldn't be completed because of an error receiving or
+ * processing data at the HTTP level.
+ *
+ * @hide
+ */
+ public static final int STATUS_HTTP_DATA_ERROR = 495;
+
+ /**
+ * This download couldn't be completed because of an HttpException while
+ * setting up the request.
+ *
+ * @hide
+ */
+ public static final int STATUS_HTTP_EXCEPTION = 496;
+
+ /**
+ * This download couldn't be completed because there were too many
+ * redirects.
+ *
+ * @hide
+ */
+ public static final int STATUS_TOO_MANY_REDIRECTS = 497;
+
+ /**
+ * This download couldn't be completed due to insufficient storage space.
+ * Typically, this is because the SD card is full.
+ *
+ * @hide
+ */
+ public static final int STATUS_INSUFFICIENT_SPACE_ERROR = 498;
+
+ /**
+ * This download couldn't be completed because no external storage device
+ * was found. Typically, this is because the SD card is not mounted.
+ *
+ * @hide
+ */
+ public static final int STATUS_DEVICE_NOT_FOUND_ERROR = 499;
+
+ /**
+ * This download is allowed to run.
+ *
+ * @hide
+ */
+ public static final int CONTROL_RUN = 0;
+
+ /**
+ * This download must pause at the first opportunity.
+ *
+ * @hide
+ */
+ public static final int CONTROL_PAUSED = 1;
+
+ /**
+ * This download is visible but only shows in the notifications while it's
+ * in progress.
+ *
+ * @hide
+ */
+ public static final int VISIBILITY_VISIBLE = 0;
+
+ /**
+ * This download is visible and shows in the notifications while in progress
+ * and after completion.
+ *
+ * @hide
+ */
+ public static final int VISIBILITY_VISIBLE_NOTIFY_COMPLETED = 1;
+
+ /**
+ * This download doesn't show in the UI or in the notifications.
+ *
+ * @hide
+ */
+ public static final int VISIBILITY_HIDDEN = 2;
+
+ /**
+ * Bit flag for {@link #setAllowedNetworkTypes} corresponding to
+ * {@link ConnectivityManager#TYPE_MOBILE}.
+ */
+ public static final int NETWORK_MOBILE = 1 << 0;
+
+ /**
+ * Bit flag for {@link #setAllowedNetworkTypes} corresponding to
+ * {@link ConnectivityManager#TYPE_WIFI}.
+ */
+ public static final int NETWORK_WIFI = 1 << 1;
+
+ private final static String TEMP_EXT = ".tmp";
+
+ /**
+ * Service thread status
+ */
+ private static boolean sIsRunning;
+
+ @Override
+ public IBinder onBind(Intent paramIntent) {
+ Log.d(Constants.TAG, "Service Bound");
+ return this.mServiceMessenger.getBinder();
+ }
+
+ /**
+ * Network state.
+ */
+ private boolean mIsConnected;
+ private boolean mIsFailover;
+ private boolean mIsCellularConnection;
+ private boolean mIsRoaming;
+ private boolean mIsAtLeast3G;
+ private boolean mIsAtLeast4G;
+ private boolean mStateChanged;
+
+ /**
+ * Download state
+ */
+ private int mControl;
+ private int mStatus;
+
+ public boolean isWiFi() {
+ return mIsConnected && !mIsCellularConnection;
+ }
+
+ /**
+ * Bindings to important services
+ */
+ private ConnectivityManager mConnectivityManager;
+ private WifiManager mWifiManager;
+
+ /**
+ * Package we are downloading for (defaults to package of application)
+ */
+ private PackageInfo mPackageInfo;
+
+ /**
+ * Byte counts
+ */
+ long mBytesSoFar;
+ long mTotalLength;
+ int mFileCount;
+
+ /**
+ * Used for calculating time remaining and speed
+ */
+ long mBytesAtSample;
+ long mMillisecondsAtSample;
+ float mAverageDownloadSpeed;
+
+ /**
+ * Our binding to the network state broadcasts
+ */
+ private BroadcastReceiver mConnReceiver;
+ final private IStub mServiceStub = DownloaderServiceMarshaller.CreateStub(this);
+ final private Messenger mServiceMessenger = mServiceStub.getMessenger();
+ private Messenger mClientMessenger;
+ private DownloadNotification mNotification;
+ private PendingIntent mPendingIntent;
+ private PendingIntent mAlarmIntent;
+
+ /**
+ * Updates the network type based upon the type and subtype returned from
+ * the connectivity manager. Subtype is only used for cellular signals.
+ *
+ * @param type
+ * @param subType
+ */
+ private void updateNetworkType(int type, int subType) {
+ switch (type) {
+ case ConnectivityManager.TYPE_WIFI:
+ case ConnectivityManager.TYPE_ETHERNET:
+ case ConnectivityManager.TYPE_BLUETOOTH:
+ mIsCellularConnection = false;
+ mIsAtLeast3G = false;
+ mIsAtLeast4G = false;
+ break;
+ case ConnectivityManager.TYPE_WIMAX:
+ mIsCellularConnection = true;
+ mIsAtLeast3G = true;
+ mIsAtLeast4G = true;
+ break;
+ case ConnectivityManager.TYPE_MOBILE:
+ mIsCellularConnection = true;
+ switch (subType) {
+ case TelephonyManager.NETWORK_TYPE_1xRTT:
+ case TelephonyManager.NETWORK_TYPE_CDMA:
+ case TelephonyManager.NETWORK_TYPE_EDGE:
+ case TelephonyManager.NETWORK_TYPE_GPRS:
+ case TelephonyManager.NETWORK_TYPE_IDEN:
+ mIsAtLeast3G = false;
+ mIsAtLeast4G = false;
+ break;
+ case TelephonyManager.NETWORK_TYPE_HSDPA:
+ case TelephonyManager.NETWORK_TYPE_HSUPA:
+ case TelephonyManager.NETWORK_TYPE_HSPA:
+ case TelephonyManager.NETWORK_TYPE_EVDO_0:
+ case TelephonyManager.NETWORK_TYPE_EVDO_A:
+ case TelephonyManager.NETWORK_TYPE_UMTS:
+ mIsAtLeast3G = true;
+ mIsAtLeast4G = false;
+ break;
+ case TelephonyManager.NETWORK_TYPE_LTE: // 4G
+ case TelephonyManager.NETWORK_TYPE_EHRPD: // 3G ++ interop
+ // with 4G
+ case TelephonyManager.NETWORK_TYPE_HSPAP: // 3G ++ but
+ // marketed as
+ // 4G
+ mIsAtLeast3G = true;
+ mIsAtLeast4G = true;
+ break;
+ default:
+ mIsCellularConnection = false;
+ mIsAtLeast3G = false;
+ mIsAtLeast4G = false;
+ }
+ }
+ }
+
+ private void updateNetworkState(NetworkInfo info) {
+ boolean isConnected = mIsConnected;
+ boolean isFailover = mIsFailover;
+ boolean isCellularConnection = mIsCellularConnection;
+ boolean isRoaming = mIsRoaming;
+ boolean isAtLeast3G = mIsAtLeast3G;
+ if (null != info) {
+ mIsRoaming = info.isRoaming();
+ mIsFailover = info.isFailover();
+ mIsConnected = info.isConnected();
+ updateNetworkType(info.getType(), info.getSubtype());
+ } else {
+ mIsRoaming = false;
+ mIsFailover = false;
+ mIsConnected = false;
+ updateNetworkType(-1, -1);
+ }
+ mStateChanged = (mStateChanged || isConnected != mIsConnected
+ || isFailover != mIsFailover
+ || isCellularConnection != mIsCellularConnection
+ || isRoaming != mIsRoaming || isAtLeast3G != mIsAtLeast3G);
+ if (Constants.LOGVV) {
+ if (mStateChanged) {
+ Log.v(LOG_TAG, "Network state changed: ");
+ Log.v(LOG_TAG, "Starting State: " +
+ (isConnected ? "Connected " : "Not Connected ") +
+ (isCellularConnection ? "Cellular " : "WiFi ") +
+ (isRoaming ? "Roaming " : "Local ") +
+ (isAtLeast3G ? "3G+ " : "<3G "));
+ Log.v(LOG_TAG, "Ending State: " +
+ (mIsConnected ? "Connected " : "Not Connected ") +
+ (mIsCellularConnection ? "Cellular " : "WiFi ") +
+ (mIsRoaming ? "Roaming " : "Local ") +
+ (mIsAtLeast3G ? "3G+ " : "<3G "));
+
+ if (isServiceRunning()) {
+ if (mIsRoaming) {
+ mStatus = STATUS_WAITING_FOR_NETWORK;
+ mControl = CONTROL_PAUSED;
+ } else if (mIsCellularConnection) {
+ DownloadsDB db = DownloadsDB.getDB(this);
+ int flags = db.getFlags();
+ if (0 == (flags & FLAGS_DOWNLOAD_OVER_CELLULAR)) {
+ mStatus = STATUS_QUEUED_FOR_WIFI;
+ mControl = CONTROL_PAUSED;
+ }
+ }
+ }
+
+ }
+ }
+ }
+
+ /**
+ * Polls the network state, setting the flags appropriately.
+ */
+ void pollNetworkState() {
+ if (null == mConnectivityManager) {
+ mConnectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
+ }
+ if (null == mWifiManager) {
+ mWifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
+ }
+ if (mConnectivityManager == null) {
+ Log.w(Constants.TAG,
+ "couldn't get connectivity manager to poll network state");
+ } else {
+ NetworkInfo activeInfo = mConnectivityManager
+ .getActiveNetworkInfo();
+ updateNetworkState(activeInfo);
+ }
+ }
+
+ public static final int NO_DOWNLOAD_REQUIRED = 0;
+ public static final int LVL_CHECK_REQUIRED = 1;
+ public static final int DOWNLOAD_REQUIRED = 2;
+
+ public static final String EXTRA_PACKAGE_NAME = "EPN";
+ public static final String EXTRA_PENDING_INTENT = "EPI";
+ public static final String EXTRA_MESSAGE_HANDLER = "EMH";
+
+ /**
+ * Returns true if the LVL check is required
+ *
+ * @param db a downloads DB synchronized with the latest state
+ * @param pi the package info for the project
+ * @return returns true if the filenames need to be returned
+ */
+ private static boolean isLVLCheckRequired(DownloadsDB db, PackageInfo pi) {
+ // we need to update the LVL check and get a successful status to
+ // proceed
+ if (db.mVersionCode != pi.versionCode) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Careful! Only use this internally.
+ *
+ * @return whether we think the service is running
+ */
+ private static synchronized boolean isServiceRunning() {
+ return sIsRunning;
+ }
+
+ private static synchronized void setServiceRunning(boolean isRunning) {
+ sIsRunning = isRunning;
+ }
+
+ public static int startDownloadServiceIfRequired(Context context,
+ Intent intent, Class<?> serviceClass) throws NameNotFoundException {
+ final PendingIntent pendingIntent = (PendingIntent) intent
+ .getParcelableExtra(EXTRA_PENDING_INTENT);
+ return startDownloadServiceIfRequired(context, pendingIntent,
+ serviceClass);
+ }
+
+ public static int startDownloadServiceIfRequired(Context context,
+ PendingIntent pendingIntent, Class<?> serviceClass)
+ throws NameNotFoundException
+ {
+ String packageName = context.getPackageName();
+ String className = serviceClass.getName();
+
+ return startDownloadServiceIfRequired(context, pendingIntent,
+ packageName, className);
+ }
+
+ /**
+ * Starts the download if necessary. This function starts a flow that does `
+ * many things. 1) Checks to see if the APK version has been checked and the
+ * metadata database updated 2) If the APK version does not match, checks
+ * the new LVL status to see if a new download is required 3) If the APK
+ * version does match, then checks to see if the download(s) have been
+ * completed 4) If the downloads have been completed, returns
+ * NO_DOWNLOAD_REQUIRED The idea is that this can be called during the
+ * startup of an application to quickly ascertain if the application needs
+ * to wait to hear about any updated APK expansion files. Note that this
+ * does mean that the application MUST be run for the first time with a
+ * network connection, even if Market delivers all of the files.
+ *
+ * @param context
+ * @param thisIntent
+ * @return true if the app should wait for more guidance from the
+ * downloader, false if the app can continue
+ * @throws NameNotFoundException
+ */
+ public static int startDownloadServiceIfRequired(Context context,
+ PendingIntent pendingIntent, String classPackage, String className)
+ throws NameNotFoundException {
+ // first: do we need to do an LVL update?
+ // we begin by getting our APK version from the package manager
+ final PackageInfo pi = context.getPackageManager().getPackageInfo(
+ context.getPackageName(), 0);
+
+ int status = NO_DOWNLOAD_REQUIRED;
+
+ // the database automatically reads the metadata for version code
+ // and download status when the instance is created
+ DownloadsDB db = DownloadsDB.getDB(context);
+
+ // we need to update the LVL check and get a successful status to
+ // proceed
+ if (isLVLCheckRequired(db, pi)) {
+ status = LVL_CHECK_REQUIRED;
+ }
+ // we don't have to update LVL. do we still have a download to start?
+ if (db.mStatus == 0) {
+ DownloadInfo[] infos = db.getDownloads();
+ if (null != infos) {
+ for (DownloadInfo info : infos) {
+ if (!Helpers.doesFileExist(context, info.mFileName, info.mTotalBytes, true)) {
+ status = DOWNLOAD_REQUIRED;
+ db.updateStatus(-1);
+ break;
+ }
+ }
+ }
+ } else {
+ status = DOWNLOAD_REQUIRED;
+ }
+ switch (status) {
+ case DOWNLOAD_REQUIRED:
+ case LVL_CHECK_REQUIRED:
+ Intent fileIntent = new Intent();
+ fileIntent.setClassName(classPackage, className);
+ fileIntent.putExtra(EXTRA_PENDING_INTENT, pendingIntent);
+ context.startService(fileIntent);
+ break;
+ }
+ return status;
+ }
+
+ @Override
+ public void requestAbortDownload() {
+ mControl = CONTROL_PAUSED;
+ mStatus = STATUS_CANCELED;
+ }
+
+ @Override
+ public void requestPauseDownload() {
+ mControl = CONTROL_PAUSED;
+ mStatus = STATUS_PAUSED_BY_APP;
+ }
+
+ @Override
+ public void setDownloadFlags(int flags) {
+ DownloadsDB.getDB(this).updateFlags(flags);
+ }
+
+ @Override
+ public void requestContinueDownload() {
+ if (mControl == CONTROL_PAUSED) {
+ mControl = CONTROL_RUN;
+ }
+ Intent fileIntent = new Intent(this, this.getClass());
+ fileIntent.putExtra(EXTRA_PENDING_INTENT, mPendingIntent);
+ this.startService(fileIntent);
+ }
+
+ public abstract String getPublicKey();
+
+ public abstract byte[] getSALT();
+
+ public abstract String getAlarmReceiverClassName();
+
+ private class LVLRunnable implements Runnable {
+ LVLRunnable(Context context, PendingIntent intent) {
+ mContext = context;
+ mPendingIntent = intent;
+ }
+
+ final Context mContext;
+
+ @Override
+ public void run() {
+ setServiceRunning(true);
+ mNotification.onDownloadStateChanged(IDownloaderClient.STATE_FETCHING_URL);
+ String deviceId = Secure.getString(mContext.getContentResolver(),
+ Secure.ANDROID_ID);
+
+ final APKExpansionPolicy aep = new APKExpansionPolicy(mContext,
+ new AESObfuscator(getSALT(), mContext.getPackageName(), deviceId));
+
+ // reset our policy back to the start of the world to force a
+ // re-check
+ aep.resetPolicy();
+
+ // let's try and get the OBB file from LVL first
+ // Construct the LicenseChecker with a Policy.
+ final LicenseChecker checker = new LicenseChecker(mContext, aep,
+ getPublicKey() // Your public licensing key.
+ );
+ checker.checkAccess(new LicenseCheckerCallback() {
+
+ @Override
+ public void allow(int reason) {
+ try {
+ int count = aep.getExpansionURLCount();
+ DownloadsDB db = DownloadsDB.getDB(mContext);
+ int status = 0;
+ if (count != 0) {
+ for (int i = 0; i < count; i++) {
+ String currentFileName = aep
+ .getExpansionFileName(i);
+ if (null != currentFileName) {
+ DownloadInfo di = new DownloadInfo(i,
+ currentFileName, mContext.getPackageName());
+
+ long fileSize = aep.getExpansionFileSize(i);
+ if (handleFileUpdated(db, i, currentFileName,
+ fileSize)) {
+ status |= -1;
+ di.resetDownload();
+ di.mUri = aep.getExpansionURL(i);
+ di.mTotalBytes = fileSize;
+ di.mStatus = status;
+ db.updateDownload(di);
+ } else {
+ // we need to read the download
+ // information
+ // from
+ // the database
+ DownloadInfo dbdi = db
+ .getDownloadInfoByFileName(di.mFileName);
+ if (null == dbdi) {
+ // the file exists already and is
+ // the
+ // correct size
+ // was delivered by Market or
+ // through
+ // another mechanism
+ Log.d(LOG_TAG, "file " + di.mFileName
+ + " found. Not downloading.");
+ di.mStatus = STATUS_SUCCESS;
+ di.mTotalBytes = fileSize;
+ di.mCurrentBytes = fileSize;
+ di.mUri = aep.getExpansionURL(i);
+ db.updateDownload(di);
+ } else if (dbdi.mStatus != STATUS_SUCCESS) {
+ // we just update the URL
+ dbdi.mUri = aep.getExpansionURL(i);
+ db.updateDownload(dbdi);
+ status |= -1;
+ }
+ }
+ }
+ }
+ }
+ // first: do we need to do an LVL update?
+ // we begin by getting our APK version from the package
+ // manager
+ PackageInfo pi;
+ try {
+ pi = mContext.getPackageManager().getPackageInfo(
+ mContext.getPackageName(), 0);
+ db.updateMetadata(pi.versionCode, status);
+ Class<?> serviceClass = DownloaderService.this.getClass();
+ switch (startDownloadServiceIfRequired(mContext, mPendingIntent,
+ serviceClass)) {
+ case NO_DOWNLOAD_REQUIRED:
+ mNotification
+ .onDownloadStateChanged(IDownloaderClient.STATE_COMPLETED);
+ break;
+ case LVL_CHECK_REQUIRED:
+ // DANGER WILL ROBINSON!
+ Log.e(LOG_TAG, "In LVL checking loop!");
+ mNotification
+ .onDownloadStateChanged(IDownloaderClient.STATE_FAILED_UNLICENSED);
+ throw new RuntimeException(
+ "Error with LVL checking and database integrity");
+ case DOWNLOAD_REQUIRED:
+ // do nothing. the download will notify the
+ // application
+ // when things are done
+ break;
+ }
+ } catch (NameNotFoundException e1) {
+ e1.printStackTrace();
+ throw new RuntimeException(
+ "Error with getting information from package name");
+ }
+ } finally {
+ setServiceRunning(false);
+ }
+ }
+
+ @Override
+ public void dontAllow(int reason) {
+ try
+ {
+ switch (reason) {
+ case Policy.NOT_LICENSED:
+ mNotification
+ .onDownloadStateChanged(IDownloaderClient.STATE_FAILED_UNLICENSED);
+ break;
+ case Policy.RETRY:
+ mNotification
+ .onDownloadStateChanged(IDownloaderClient.STATE_FAILED_FETCHING_URL);
+ break;
+ }
+ } finally {
+ setServiceRunning(false);
+ }
+
+ }
+
+ @Override
+ public void applicationError(int errorCode) {
+ try {
+ mNotification
+ .onDownloadStateChanged(IDownloaderClient.STATE_FAILED_FETCHING_URL);
+ } finally {
+ setServiceRunning(false);
+ }
+ }
+
+ });
+
+ }
+
+ };
+
+ /**
+ * Updates the LVL information from the server.
+ *
+ * @param context
+ */
+ public void updateLVL(final Context context) {
+ Context c = context.getApplicationContext();
+ Handler h = new Handler(c.getMainLooper());
+ h.post(new LVLRunnable(c, mPendingIntent));
+ }
+
+ /**
+ * The APK has been updated and a filename has been sent down from the
+ * Market call. If the file has the same name as the previous file, we do
+ * nothing as the file is guaranteed to be the same. If the file does not
+ * have the same name, we download it if it hasn't already been delivered by
+ * Market.
+ *
+ * @param index the index of the file from market (0 = main, 1 = patch)
+ * @param filename the name of the new file
+ * @param fileSize the size of the new file
+ * @return
+ */
+ public boolean handleFileUpdated(DownloadsDB db, int index,
+ String filename, long fileSize) {
+ DownloadInfo di = db.getDownloadInfoByFileName(filename);
+ if (null != di) {
+ String oldFile = di.mFileName;
+ // cleanup
+ if (null != oldFile) {
+ if (filename.equals(oldFile)) {
+ return false;
+ }
+
+ // remove partially downloaded file if it is there
+ String deleteFile = Helpers.generateSaveFileName(this, oldFile);
+ File f = new File(deleteFile);
+ if (f.exists())
+ f.delete();
+ }
+ }
+ return !Helpers.doesFileExist(this, filename, fileSize, true);
+ }
+
+ private void scheduleAlarm(long wakeUp) {
+ AlarmManager alarms = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
+ if (alarms == null) {
+ Log.e(Constants.TAG, "couldn't get alarm manager");
+ return;
+ }
+
+ if (Constants.LOGV) {
+ Log.v(Constants.TAG, "scheduling retry in " + wakeUp + "ms");
+ }
+
+ String className = getAlarmReceiverClassName();
+ Intent intent = new Intent(Constants.ACTION_RETRY);
+ intent.putExtra(EXTRA_PENDING_INTENT, mPendingIntent);
+ intent.setClassName(this.getPackageName(),
+ className);
+ mAlarmIntent = PendingIntent.getBroadcast(this, 0, intent,
+ PendingIntent.FLAG_ONE_SHOT);
+ alarms.set(
+ AlarmManager.RTC_WAKEUP,
+ System.currentTimeMillis() + wakeUp, mAlarmIntent
+ );
+ }
+
+ private void cancelAlarms() {
+ if (null != mAlarmIntent) {
+ AlarmManager alarms = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
+ if (alarms == null) {
+ Log.e(Constants.TAG, "couldn't get alarm manager");
+ return;
+ }
+ alarms.cancel(mAlarmIntent);
+ mAlarmIntent = null;
+ }
+ }
+
+ /**
+ * We use this to track network state, such as when WiFi, Cellular, etc. is
+ * enabled when downloads are paused or in progress.
+ */
+ private class InnerBroadcastReceiver extends BroadcastReceiver {
+ final Service mService;
+
+ InnerBroadcastReceiver(Service service) {
+ mService = service;
+ }
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ pollNetworkState();
+ if (mStateChanged
+ && !isServiceRunning()) {
+ Log.d(Constants.TAG, "InnerBroadcastReceiver Called");
+ Intent fileIntent = new Intent(context, mService.getClass());
+ fileIntent.putExtra(EXTRA_PENDING_INTENT, mPendingIntent);
+ // send a new intent to the service
+ context.startService(fileIntent);
+ }
+ }
+ };
+
+ /**
+ * This is the main thread for the Downloader. This thread is responsible
+ * for queuing up downloads and other goodness.
+ */
+ @Override
+ protected void onHandleIntent(Intent intent) {
+ setServiceRunning(true);
+ try {
+ // the database automatically reads the metadata for version code
+ // and download status when the instance is created
+ DownloadsDB db = DownloadsDB.getDB(this);
+ final PendingIntent pendingIntent = (PendingIntent) intent
+ .getParcelableExtra(EXTRA_PENDING_INTENT);
+
+ if (null != pendingIntent)
+ {
+ mNotification.setClientIntent(pendingIntent);
+ mPendingIntent = pendingIntent;
+ } else if (null != mPendingIntent) {
+ mNotification.setClientIntent(mPendingIntent);
+ } else {
+ Log.e(LOG_TAG, "Downloader started in bad state without notification intent.");
+ return;
+ }
+
+ // when the LVL check completes, a successful response will update
+ // the service
+ if (isLVLCheckRequired(db, mPackageInfo)) {
+ updateLVL(this);
+ return;
+ }
+
+ // get each download
+ DownloadInfo[] infos = db.getDownloads();
+ mBytesSoFar = 0;
+ mTotalLength = 0;
+ mFileCount = infos.length;
+ for (DownloadInfo info : infos) {
+ // We do an (simple) integrity check on each file, just to make
+ // sure
+ if (info.mStatus == STATUS_SUCCESS) {
+ // verify that the file matches the state
+ if (!Helpers.doesFileExist(this, info.mFileName, info.mTotalBytes, true)) {
+ info.mStatus = 0;
+ info.mCurrentBytes = 0;
+ }
+ }
+ // get aggregate data
+ mTotalLength += info.mTotalBytes;
+ mBytesSoFar += info.mCurrentBytes;
+ }
+
+ // loop through all downloads and fetch them
+ pollNetworkState();
+ if (null == mConnReceiver) {
+
+ /**
+ * We use this to track network state, such as when WiFi,
+ * Cellular, etc. is enabled when downloads are paused or in
+ * progress.
+ */
+ mConnReceiver = new InnerBroadcastReceiver(this);
+ IntentFilter intentFilter = new IntentFilter(
+ ConnectivityManager.CONNECTIVITY_ACTION);
+ intentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
+ registerReceiver(mConnReceiver, intentFilter);
+ }
+
+ for (DownloadInfo info : infos) {
+ long startingCount = info.mCurrentBytes;
+
+ if (info.mStatus != STATUS_SUCCESS) {
+ DownloadThread dt = new DownloadThread(info, this, mNotification);
+ cancelAlarms();
+ scheduleAlarm(Constants.ACTIVE_THREAD_WATCHDOG);
+ dt.run();
+ cancelAlarms();
+ }
+ db.updateFromDb(info);
+ boolean setWakeWatchdog = false;
+ int notifyStatus;
+ switch (info.mStatus) {
+ case STATUS_FORBIDDEN:
+ // the URL is out of date
+ updateLVL(this);
+ return;
+ case STATUS_SUCCESS:
+ mBytesSoFar += info.mCurrentBytes - startingCount;
+ db.updateMetadata(mPackageInfo.versionCode, 0);
+ continue;
+ case STATUS_FILE_DELIVERED_INCORRECTLY:
+ // we may be on a network that is returning us a web
+ // page on redirect
+ notifyStatus = IDownloaderClient.STATE_PAUSED_NETWORK_SETUP_FAILURE;
+ info.mCurrentBytes = 0;
+ db.updateDownload(info);
+ setWakeWatchdog = true;
+ break;
+ case STATUS_PAUSED_BY_APP:
+ notifyStatus = IDownloaderClient.STATE_PAUSED_BY_REQUEST;
+ break;
+ case STATUS_WAITING_FOR_NETWORK:
+ case STATUS_WAITING_TO_RETRY:
+ notifyStatus = IDownloaderClient.STATE_PAUSED_NETWORK_UNAVAILABLE;
+ setWakeWatchdog = true;
+ break;
+ case STATUS_QUEUED_FOR_WIFI_OR_CELLULAR_PERMISSION:
+ case STATUS_QUEUED_FOR_WIFI:
+ // look for more detail here
+ if (null != mWifiManager) {
+ if (!mWifiManager.isWifiEnabled()) {
+ notifyStatus = IDownloaderClient.STATE_PAUSED_WIFI_DISABLED_NEED_CELLULAR_PERMISSION;
+ setWakeWatchdog = true;
+ break;
+ }
+ }
+ notifyStatus = IDownloaderClient.STATE_PAUSED_NEED_CELLULAR_PERMISSION;
+ setWakeWatchdog = true;
+ break;
+ case STATUS_CANCELED:
+ notifyStatus = IDownloaderClient.STATE_FAILED_CANCELED;
+ setWakeWatchdog = true;
+ break;
+
+ case STATUS_INSUFFICIENT_SPACE_ERROR:
+ notifyStatus = IDownloaderClient.STATE_FAILED_SDCARD_FULL;
+ setWakeWatchdog = true;
+ break;
+
+ case STATUS_DEVICE_NOT_FOUND_ERROR:
+ notifyStatus = IDownloaderClient.STATE_PAUSED_SDCARD_UNAVAILABLE;
+ setWakeWatchdog = true;
+ break;
+
+ default:
+ notifyStatus = IDownloaderClient.STATE_FAILED;
+ break;
+ }
+ if (setWakeWatchdog) {
+ scheduleAlarm(Constants.WATCHDOG_WAKE_TIMER);
+ } else {
+ cancelAlarms();
+ }
+ // failure or pause state
+ mNotification.onDownloadStateChanged(notifyStatus);
+ return;
+ }
+
+ // all downloads complete
+ mNotification.onDownloadStateChanged(IDownloaderClient.STATE_COMPLETED);
+ } finally {
+ setServiceRunning(false);
+ }
+ }
+
+ @Override
+ public void onDestroy() {
+ if (null != mConnReceiver) {
+ unregisterReceiver(mConnReceiver);
+ mConnReceiver = null;
+ }
+ mServiceStub.disconnect(this);
+ super.onDestroy();
+ }
+
+ public int getNetworkAvailabilityState(DownloadsDB db) {
+ if (mIsConnected) {
+ if (!mIsCellularConnection)
+ return NETWORK_OK;
+ int flags = db.mFlags;
+ if (mIsRoaming)
+ return NETWORK_CANNOT_USE_ROAMING;
+ if (0 != (flags & FLAGS_DOWNLOAD_OVER_CELLULAR)) {
+ return NETWORK_OK;
+ } else {
+ return NETWORK_TYPE_DISALLOWED_BY_REQUESTOR;
+ }
+ }
+ return NETWORK_NO_CONNECTION;
+ }
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ try {
+ mPackageInfo = getPackageManager().getPackageInfo(
+ getPackageName(), 0);
+ ApplicationInfo ai = getApplicationInfo();
+ CharSequence applicationLabel = getPackageManager().getApplicationLabel(ai);
+ mNotification = new DownloadNotification(this, applicationLabel);
+
+ } catch (NameNotFoundException e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Exception thrown from methods called by generateSaveFile() for any fatal
+ * error.
+ */
+ public static class GenerateSaveFileError extends Exception {
+ private static final long serialVersionUID = 3465966015408936540L;
+ int mStatus;
+ String mMessage;
+
+ public GenerateSaveFileError(int status, String message) {
+ mStatus = status;
+ mMessage = message;
+ }
+ }
+
+ /**
+ * Returns the filename (where the file should be saved) from info about a
+ * download
+ */
+ public String generateTempSaveFileName(String fileName) {
+ String path = Helpers.getSaveFilePath(this)
+ + File.separator + fileName + TEMP_EXT;
+ return path;
+ }
+
+ /**
+ * Creates a filename (where the file should be saved) from info about a
+ * download.
+ */
+ public String generateSaveFile(String filename, long filesize)
+ throws GenerateSaveFileError {
+ String path = generateTempSaveFileName(filename);
+ File expPath = new File(path);
+ if (!Helpers.isExternalMediaMounted()) {
+ Log.d(Constants.TAG, "External media not mounted: " + path);
+ throw new GenerateSaveFileError(STATUS_DEVICE_NOT_FOUND_ERROR,
+ "external media is not yet mounted");
+
+ }
+ if (expPath.exists()) {
+ Log.d(Constants.TAG, "File already exists: " + path);
+ throw new GenerateSaveFileError(STATUS_FILE_ALREADY_EXISTS_ERROR,
+ "requested destination file already exists");
+ }
+ if (Helpers.getAvailableBytes(Helpers.getFilesystemRoot(path)) < filesize) {
+ throw new GenerateSaveFileError(STATUS_INSUFFICIENT_SPACE_ERROR,
+ "insufficient space on external storage");
+ }
+ return path;
+ }
+
+ /**
+ * @return a non-localized string appropriate for logging corresponding to
+ * one of the NETWORK_* constants.
+ */
+ public String getLogMessageForNetworkError(int networkError) {
+ switch (networkError) {
+ case NETWORK_RECOMMENDED_UNUSABLE_DUE_TO_SIZE:
+ return "download size exceeds recommended limit for mobile network";
+
+ case NETWORK_UNUSABLE_DUE_TO_SIZE:
+ return "download size exceeds limit for mobile network";
+
+ case NETWORK_NO_CONNECTION:
+ return "no network connection available";
+
+ case NETWORK_CANNOT_USE_ROAMING:
+ return "download cannot use the current network connection because it is roaming";
+
+ case NETWORK_TYPE_DISALLOWED_BY_REQUESTOR:
+ return "download was requested to not use the current network type";
+
+ default:
+ return "unknown error with network connectivity";
+ }
+ }
+
+ public int getControl() {
+ return mControl;
+ }
+
+ public int getStatus() {
+ return mStatus;
+ }
+
+ /**
+ * Calculating a moving average for the speed so we don't get jumpy
+ * calculations for time etc.
+ */
+ static private final float SMOOTHING_FACTOR = 0.005f;
+
+ public void notifyUpdateBytes(long totalBytesSoFar) {
+ long timeRemaining;
+ long currentTime = SystemClock.uptimeMillis();
+ if (0 != mMillisecondsAtSample) {
+ // we have a sample.
+ long timePassed = currentTime - mMillisecondsAtSample;
+ long bytesInSample = totalBytesSoFar - mBytesAtSample;
+ float currentSpeedSample = (float) bytesInSample / (float) timePassed;
+ if (0 != mAverageDownloadSpeed) {
+ mAverageDownloadSpeed = SMOOTHING_FACTOR * currentSpeedSample
+ + (1 - SMOOTHING_FACTOR) * mAverageDownloadSpeed;
+ } else {
+ mAverageDownloadSpeed = currentSpeedSample;
+ }
+ timeRemaining = (long) ((mTotalLength - totalBytesSoFar) / mAverageDownloadSpeed);
+ } else {
+ timeRemaining = -1;
+ }
+ mMillisecondsAtSample = currentTime;
+ mBytesAtSample = totalBytesSoFar;
+ mNotification.onDownloadProgress(
+ new DownloadProgressInfo(mTotalLength,
+ totalBytesSoFar,
+ timeRemaining,
+ mAverageDownloadSpeed)
+ );
+
+ }
+
+ @Override
+ protected boolean shouldStop() {
+ // the database automatically reads the metadata for version code
+ // and download status when the instance is created
+ DownloadsDB db = DownloadsDB.getDB(this);
+ if (db.mStatus == 0) {
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public void requestDownloadStatus() {
+ mNotification.resendState();
+ }
+
+ @Override
+ public void onClientUpdated(Messenger clientMessenger) {
+ this.mClientMessenger = clientMessenger;
+ mNotification.setMessenger(mClientMessenger);
+ }
+
+}
diff --git a/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/DownloadsDB.java b/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/DownloadsDB.java
new file mode 100755
index 0000000000..250299c400
--- /dev/null
+++ b/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/DownloadsDB.java
@@ -0,0 +1,510 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.android.vending.expansion.downloader.impl;
+
+import android.content.ContentValues;
+import android.content.Context;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteDoneException;
+import android.database.sqlite.SQLiteOpenHelper;
+import android.database.sqlite.SQLiteStatement;
+import android.provider.BaseColumns;
+import android.util.Log;
+
+public class DownloadsDB {
+ private static final String DATABASE_NAME = "DownloadsDB";
+ private static final int DATABASE_VERSION = 7;
+ public static final String LOG_TAG = DownloadsDB.class.getName();
+ final SQLiteOpenHelper mHelper;
+ SQLiteStatement mGetDownloadByIndex;
+ SQLiteStatement mUpdateCurrentBytes;
+ private static DownloadsDB mDownloadsDB;
+ long mMetadataRowID = -1;
+ int mVersionCode = -1;
+ int mStatus = -1;
+ int mFlags;
+
+ static public synchronized DownloadsDB getDB(Context paramContext) {
+ if (null == mDownloadsDB) {
+ return new DownloadsDB(paramContext);
+ }
+ return mDownloadsDB;
+ }
+
+ private SQLiteStatement getDownloadByIndexStatement() {
+ if (null == mGetDownloadByIndex) {
+ mGetDownloadByIndex = mHelper.getReadableDatabase().compileStatement(
+ "SELECT " + BaseColumns._ID + " FROM "
+ + DownloadColumns.TABLE_NAME + " WHERE "
+ + DownloadColumns.INDEX + " = ?");
+ }
+ return mGetDownloadByIndex;
+ }
+
+ private SQLiteStatement getUpdateCurrentBytesStatement() {
+ if (null == mUpdateCurrentBytes) {
+ mUpdateCurrentBytes = mHelper.getReadableDatabase().compileStatement(
+ "UPDATE " + DownloadColumns.TABLE_NAME + " SET " + DownloadColumns.CURRENTBYTES
+ + " = ?" +
+ " WHERE " + DownloadColumns.INDEX + " = ?");
+ }
+ return mUpdateCurrentBytes;
+ }
+
+ private DownloadsDB(Context paramContext) {
+ this.mHelper = new DownloadsContentDBHelper(paramContext);
+ final SQLiteDatabase sqldb = mHelper.getReadableDatabase();
+ // Query for the version code, the row ID of the metadata (for future
+ // updating) the status and the flags
+ Cursor cur = sqldb.rawQuery("SELECT " +
+ MetadataColumns.APKVERSION + "," +
+ BaseColumns._ID + "," +
+ MetadataColumns.DOWNLOAD_STATUS + "," +
+ MetadataColumns.FLAGS +
+ " FROM "
+ + MetadataColumns.TABLE_NAME + " LIMIT 1", null);
+ if (null != cur && cur.moveToFirst()) {
+ mVersionCode = cur.getInt(0);
+ mMetadataRowID = cur.getLong(1);
+ mStatus = cur.getInt(2);
+ mFlags = cur.getInt(3);
+ cur.close();
+ }
+ mDownloadsDB = this;
+ }
+
+ protected DownloadInfo getDownloadInfoByFileName(String fileName) {
+ final SQLiteDatabase sqldb = mHelper.getReadableDatabase();
+ Cursor itemcur = null;
+ try {
+ itemcur = sqldb.query(DownloadColumns.TABLE_NAME, DC_PROJECTION,
+ DownloadColumns.FILENAME + " = ?",
+ new String[] {
+ fileName
+ }, null, null, null);
+ if (null != itemcur && itemcur.moveToFirst()) {
+ return getDownloadInfoFromCursor(itemcur);
+ }
+ } finally {
+ if (null != itemcur)
+ itemcur.close();
+ }
+ return null;
+ }
+
+ public long getIDForDownloadInfo(final DownloadInfo di) {
+ return getIDByIndex(di.mIndex);
+ }
+
+ public long getIDByIndex(int index) {
+ SQLiteStatement downloadByIndex = getDownloadByIndexStatement();
+ downloadByIndex.clearBindings();
+ downloadByIndex.bindLong(1, index);
+ try {
+ return downloadByIndex.simpleQueryForLong();
+ } catch (SQLiteDoneException e) {
+ return -1;
+ }
+ }
+
+ public void updateDownloadCurrentBytes(final DownloadInfo di) {
+ SQLiteStatement downloadCurrentBytes = getUpdateCurrentBytesStatement();
+ downloadCurrentBytes.clearBindings();
+ downloadCurrentBytes.bindLong(1, di.mCurrentBytes);
+ downloadCurrentBytes.bindLong(2, di.mIndex);
+ downloadCurrentBytes.execute();
+ }
+
+ public void close() {
+ this.mHelper.close();
+ }
+
+ protected static class DownloadsContentDBHelper extends SQLiteOpenHelper {
+ DownloadsContentDBHelper(Context paramContext) {
+ super(paramContext, DATABASE_NAME, null, DATABASE_VERSION);
+ }
+
+ private String createTableQueryFromArray(String paramString,
+ String[][] paramArrayOfString) {
+ StringBuilder localStringBuilder = new StringBuilder();
+ localStringBuilder.append("CREATE TABLE ");
+ localStringBuilder.append(paramString);
+ localStringBuilder.append(" (");
+ int i = paramArrayOfString.length;
+ for (int j = 0;; j++) {
+ if (j >= i) {
+ localStringBuilder
+ .setLength(localStringBuilder.length() - 1);
+ localStringBuilder.append(");");
+ return localStringBuilder.toString();
+ }
+ String[] arrayOfString = paramArrayOfString[j];
+ localStringBuilder.append(' ');
+ localStringBuilder.append(arrayOfString[0]);
+ localStringBuilder.append(' ');
+ localStringBuilder.append(arrayOfString[1]);
+ localStringBuilder.append(',');
+ }
+ }
+
+ /**
+ * These two arrays must match and have the same order. For every Schema
+ * there must be a corresponding table name.
+ */
+ static final private String[][][] sSchemas = {
+ DownloadColumns.SCHEMA, MetadataColumns.SCHEMA
+ };
+
+ static final private String[] sTables = {
+ DownloadColumns.TABLE_NAME, MetadataColumns.TABLE_NAME
+ };
+
+ /**
+ * Goes through all of the tables in sTables and drops each table if it
+ * exists. Altered to no longer make use of reflection.
+ */
+ private void dropTables(SQLiteDatabase paramSQLiteDatabase) {
+ for (String table : sTables) {
+ try {
+ paramSQLiteDatabase.execSQL("DROP TABLE IF EXISTS " + table);
+ } catch (Exception localException) {
+ localException.printStackTrace();
+ }
+ }
+ }
+
+ /**
+ * Goes through all of the tables in sTables and creates a database with
+ * the corresponding schema described in sSchemas. Altered to no longer
+ * make use of reflection.
+ */
+ public void onCreate(SQLiteDatabase paramSQLiteDatabase) {
+ int numSchemas = sSchemas.length;
+ for (int i = 0; i < numSchemas; i++) {
+ try {
+ String[][] schema = (String[][]) sSchemas[i];
+ paramSQLiteDatabase.execSQL(createTableQueryFromArray(
+ sTables[i], schema));
+ } catch (Exception localException) {
+ while (true)
+ localException.printStackTrace();
+ }
+ }
+ }
+
+ public void onUpgrade(SQLiteDatabase paramSQLiteDatabase,
+ int paramInt1, int paramInt2) {
+ Log.w(DownloadsContentDBHelper.class.getName(),
+ "Upgrading database from version " + paramInt1 + " to "
+ + paramInt2 + ", which will destroy all old data");
+ dropTables(paramSQLiteDatabase);
+ onCreate(paramSQLiteDatabase);
+ }
+ }
+
+ public static class MetadataColumns implements BaseColumns {
+ public static final String APKVERSION = "APKVERSION";
+ public static final String DOWNLOAD_STATUS = "DOWNLOADSTATUS";
+ public static final String FLAGS = "DOWNLOADFLAGS";
+
+ public static final String[][] SCHEMA = {
+ {
+ BaseColumns._ID, "INTEGER PRIMARY KEY"
+ },
+ {
+ APKVERSION, "INTEGER"
+ }, {
+ DOWNLOAD_STATUS, "INTEGER"
+ },
+ {
+ FLAGS, "INTEGER"
+ }
+ };
+ public static final String TABLE_NAME = "MetadataColumns";
+ public static final String _ID = "MetadataColumns._id";
+ }
+
+ public static class DownloadColumns implements BaseColumns {
+ public static final String INDEX = "FILEIDX";
+ public static final String URI = "URI";
+ public static final String FILENAME = "FN";
+ public static final String ETAG = "ETAG";
+
+ public static final String TOTALBYTES = "TOTALBYTES";
+ public static final String CURRENTBYTES = "CURRENTBYTES";
+ public static final String LASTMOD = "LASTMOD";
+
+ public static final String STATUS = "STATUS";
+ public static final String CONTROL = "CONTROL";
+ public static final String NUM_FAILED = "FAILCOUNT";
+ public static final String RETRY_AFTER = "RETRYAFTER";
+ public static final String REDIRECT_COUNT = "REDIRECTCOUNT";
+
+ public static final String[][] SCHEMA = {
+ {
+ BaseColumns._ID, "INTEGER PRIMARY KEY"
+ },
+ {
+ INDEX, "INTEGER UNIQUE"
+ }, {
+ URI, "TEXT"
+ },
+ {
+ FILENAME, "TEXT UNIQUE"
+ }, {
+ ETAG, "TEXT"
+ },
+ {
+ TOTALBYTES, "INTEGER"
+ }, {
+ CURRENTBYTES, "INTEGER"
+ },
+ {
+ LASTMOD, "INTEGER"
+ }, {
+ STATUS, "INTEGER"
+ },
+ {
+ CONTROL, "INTEGER"
+ }, {
+ NUM_FAILED, "INTEGER"
+ },
+ {
+ RETRY_AFTER, "INTEGER"
+ }, {
+ REDIRECT_COUNT, "INTEGER"
+ }
+ };
+ public static final String TABLE_NAME = "DownloadColumns";
+ public static final String _ID = "DownloadColumns._id";
+ }
+
+ private static final String[] DC_PROJECTION = {
+ DownloadColumns.FILENAME,
+ DownloadColumns.URI, DownloadColumns.ETAG,
+ DownloadColumns.TOTALBYTES, DownloadColumns.CURRENTBYTES,
+ DownloadColumns.LASTMOD, DownloadColumns.STATUS,
+ DownloadColumns.CONTROL, DownloadColumns.NUM_FAILED,
+ DownloadColumns.RETRY_AFTER, DownloadColumns.REDIRECT_COUNT,
+ DownloadColumns.INDEX
+ };
+
+ private static final int FILENAME_IDX = 0;
+ private static final int URI_IDX = 1;
+ private static final int ETAG_IDX = 2;
+ private static final int TOTALBYTES_IDX = 3;
+ private static final int CURRENTBYTES_IDX = 4;
+ private static final int LASTMOD_IDX = 5;
+ private static final int STATUS_IDX = 6;
+ private static final int CONTROL_IDX = 7;
+ private static final int NUM_FAILED_IDX = 8;
+ private static final int RETRY_AFTER_IDX = 9;
+ private static final int REDIRECT_COUNT_IDX = 10;
+ private static final int INDEX_IDX = 11;
+
+ /**
+ * This function will add a new file to the database if it does not exist.
+ *
+ * @param di DownloadInfo that we wish to store
+ * @return the row id of the record to be updated/inserted, or -1
+ */
+ public boolean updateDownload(DownloadInfo di) {
+ ContentValues cv = new ContentValues();
+ cv.put(DownloadColumns.INDEX, di.mIndex);
+ cv.put(DownloadColumns.FILENAME, di.mFileName);
+ cv.put(DownloadColumns.URI, di.mUri);
+ cv.put(DownloadColumns.ETAG, di.mETag);
+ cv.put(DownloadColumns.TOTALBYTES, di.mTotalBytes);
+ cv.put(DownloadColumns.CURRENTBYTES, di.mCurrentBytes);
+ cv.put(DownloadColumns.LASTMOD, di.mLastMod);
+ cv.put(DownloadColumns.STATUS, di.mStatus);
+ cv.put(DownloadColumns.CONTROL, di.mControl);
+ cv.put(DownloadColumns.NUM_FAILED, di.mNumFailed);
+ cv.put(DownloadColumns.RETRY_AFTER, di.mRetryAfter);
+ cv.put(DownloadColumns.REDIRECT_COUNT, di.mRedirectCount);
+ return updateDownload(di, cv);
+ }
+
+ public boolean updateDownload(DownloadInfo di, ContentValues cv) {
+ long id = di == null ? -1 : getIDForDownloadInfo(di);
+ try {
+ final SQLiteDatabase sqldb = mHelper.getWritableDatabase();
+ if (id != -1) {
+ if (1 != sqldb.update(DownloadColumns.TABLE_NAME,
+ cv, DownloadColumns._ID + " = " + id, null)) {
+ return false;
+ }
+ } else {
+ return -1 != sqldb.insert(DownloadColumns.TABLE_NAME,
+ DownloadColumns.URI, cv);
+ }
+ } catch (android.database.sqlite.SQLiteException ex) {
+ ex.printStackTrace();
+ }
+ return false;
+ }
+
+ public int getLastCheckedVersionCode() {
+ return mVersionCode;
+ }
+
+ public boolean isDownloadRequired() {
+ final SQLiteDatabase sqldb = mHelper.getReadableDatabase();
+ Cursor cur = sqldb.rawQuery("SELECT Count(*) FROM "
+ + DownloadColumns.TABLE_NAME + " WHERE "
+ + DownloadColumns.STATUS + " <> 0", null);
+ try {
+ if (null != cur && cur.moveToFirst()) {
+ return 0 == cur.getInt(0);
+ }
+ } finally {
+ if (null != cur)
+ cur.close();
+ }
+ return true;
+ }
+
+ public int getFlags() {
+ return mFlags;
+ }
+
+ public boolean updateFlags(int flags) {
+ if (mFlags != flags) {
+ ContentValues cv = new ContentValues();
+ cv.put(MetadataColumns.FLAGS, flags);
+ if (updateMetadata(cv)) {
+ mFlags = flags;
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ return true;
+ }
+ };
+
+ public boolean updateStatus(int status) {
+ if (mStatus != status) {
+ ContentValues cv = new ContentValues();
+ cv.put(MetadataColumns.DOWNLOAD_STATUS, status);
+ if (updateMetadata(cv)) {
+ mStatus = status;
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ return true;
+ }
+ };
+
+ public boolean updateMetadata(ContentValues cv) {
+ final SQLiteDatabase sqldb = mHelper.getWritableDatabase();
+ if (-1 == this.mMetadataRowID) {
+ long newID = sqldb.insert(MetadataColumns.TABLE_NAME,
+ MetadataColumns.APKVERSION, cv);
+ if (-1 == newID)
+ return false;
+ mMetadataRowID = newID;
+ } else {
+ if (0 == sqldb.update(MetadataColumns.TABLE_NAME, cv,
+ BaseColumns._ID + " = " + mMetadataRowID, null))
+ return false;
+ }
+ return true;
+ }
+
+ public boolean updateMetadata(int apkVersion, int downloadStatus) {
+ ContentValues cv = new ContentValues();
+ cv.put(MetadataColumns.APKVERSION, apkVersion);
+ cv.put(MetadataColumns.DOWNLOAD_STATUS, downloadStatus);
+ if (updateMetadata(cv)) {
+ mVersionCode = apkVersion;
+ mStatus = downloadStatus;
+ return true;
+ } else {
+ return false;
+ }
+ };
+
+ public boolean updateFromDb(DownloadInfo di) {
+ final SQLiteDatabase sqldb = mHelper.getReadableDatabase();
+ Cursor cur = null;
+ try {
+ cur = sqldb.query(DownloadColumns.TABLE_NAME, DC_PROJECTION,
+ DownloadColumns.FILENAME + "= ?",
+ new String[] {
+ di.mFileName
+ }, null, null, null);
+ if (null != cur && cur.moveToFirst()) {
+ setDownloadInfoFromCursor(di, cur);
+ return true;
+ }
+ return false;
+ } finally {
+ if (null != cur) {
+ cur.close();
+ }
+ }
+ }
+
+ public void setDownloadInfoFromCursor(DownloadInfo di, Cursor cur) {
+ di.mUri = cur.getString(URI_IDX);
+ di.mETag = cur.getString(ETAG_IDX);
+ di.mTotalBytes = cur.getLong(TOTALBYTES_IDX);
+ di.mCurrentBytes = cur.getLong(CURRENTBYTES_IDX);
+ di.mLastMod = cur.getLong(LASTMOD_IDX);
+ di.mStatus = cur.getInt(STATUS_IDX);
+ di.mControl = cur.getInt(CONTROL_IDX);
+ di.mNumFailed = cur.getInt(NUM_FAILED_IDX);
+ di.mRetryAfter = cur.getInt(RETRY_AFTER_IDX);
+ di.mRedirectCount = cur.getInt(REDIRECT_COUNT_IDX);
+ }
+
+ public DownloadInfo getDownloadInfoFromCursor(Cursor cur) {
+ DownloadInfo di = new DownloadInfo(cur.getInt(INDEX_IDX),
+ cur.getString(FILENAME_IDX), this.getClass().getPackage()
+ .getName());
+ setDownloadInfoFromCursor(di, cur);
+ return di;
+ }
+
+ public DownloadInfo[] getDownloads() {
+ final SQLiteDatabase sqldb = mHelper.getReadableDatabase();
+ Cursor cur = null;
+ try {
+ cur = sqldb.query(DownloadColumns.TABLE_NAME, DC_PROJECTION, null,
+ null, null, null, null);
+ if (null != cur && cur.moveToFirst()) {
+ DownloadInfo[] retInfos = new DownloadInfo[cur.getCount()];
+ int idx = 0;
+ do {
+ DownloadInfo di = getDownloadInfoFromCursor(cur);
+ retInfos[idx++] = di;
+ } while (cur.moveToNext());
+ return retInfos;
+ }
+ return null;
+ } finally {
+ if (null != cur) {
+ cur.close();
+ }
+ }
+ }
+
+}
diff --git a/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/HttpDateTime.java b/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/HttpDateTime.java
new file mode 100644
index 0000000000..3f440e9893
--- /dev/null
+++ b/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/HttpDateTime.java
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.android.vending.expansion.downloader.impl;
+
+import android.text.format.Time;
+
+import java.util.Calendar;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Helper for parsing an HTTP date.
+ */
+public final class HttpDateTime {
+
+ /*
+ * Regular expression for parsing HTTP-date. Wdy, DD Mon YYYY HH:MM:SS GMT
+ * RFC 822, updated by RFC 1123 Weekday, DD-Mon-YY HH:MM:SS GMT RFC 850,
+ * obsoleted by RFC 1036 Wdy Mon DD HH:MM:SS YYYY ANSI C's asctime() format
+ * with following variations Wdy, DD-Mon-YYYY HH:MM:SS GMT Wdy, (SP)D Mon
+ * YYYY HH:MM:SS GMT Wdy,DD Mon YYYY HH:MM:SS GMT Wdy, DD-Mon-YY HH:MM:SS
+ * GMT Wdy, DD Mon YYYY HH:MM:SS -HHMM Wdy, DD Mon YYYY HH:MM:SS Wdy Mon
+ * (SP)D HH:MM:SS YYYY Wdy Mon DD HH:MM:SS YYYY GMT HH can be H if the first
+ * digit is zero. Mon can be the full name of the month.
+ */
+ private static final String HTTP_DATE_RFC_REGEXP =
+ "([0-9]{1,2})[- ]([A-Za-z]{3,9})[- ]([0-9]{2,4})[ ]"
+ + "([0-9]{1,2}:[0-9][0-9]:[0-9][0-9])";
+
+ private static final String HTTP_DATE_ANSIC_REGEXP =
+ "[ ]([A-Za-z]{3,9})[ ]+([0-9]{1,2})[ ]"
+ + "([0-9]{1,2}:[0-9][0-9]:[0-9][0-9])[ ]([0-9]{2,4})";
+
+ /**
+ * The compiled version of the HTTP-date regular expressions.
+ */
+ private static final Pattern HTTP_DATE_RFC_PATTERN =
+ Pattern.compile(HTTP_DATE_RFC_REGEXP);
+ private static final Pattern HTTP_DATE_ANSIC_PATTERN =
+ Pattern.compile(HTTP_DATE_ANSIC_REGEXP);
+
+ private static class TimeOfDay {
+ TimeOfDay(int h, int m, int s) {
+ this.hour = h;
+ this.minute = m;
+ this.second = s;
+ }
+
+ int hour;
+ int minute;
+ int second;
+ }
+
+ public static long parse(String timeString)
+ throws IllegalArgumentException {
+
+ int date = 1;
+ int month = Calendar.JANUARY;
+ int year = 1970;
+ TimeOfDay timeOfDay;
+
+ Matcher rfcMatcher = HTTP_DATE_RFC_PATTERN.matcher(timeString);
+ if (rfcMatcher.find()) {
+ date = getDate(rfcMatcher.group(1));
+ month = getMonth(rfcMatcher.group(2));
+ year = getYear(rfcMatcher.group(3));
+ timeOfDay = getTime(rfcMatcher.group(4));
+ } else {
+ Matcher ansicMatcher = HTTP_DATE_ANSIC_PATTERN.matcher(timeString);
+ if (ansicMatcher.find()) {
+ month = getMonth(ansicMatcher.group(1));
+ date = getDate(ansicMatcher.group(2));
+ timeOfDay = getTime(ansicMatcher.group(3));
+ year = getYear(ansicMatcher.group(4));
+ } else {
+ throw new IllegalArgumentException();
+ }
+ }
+
+ // FIXME: Y2038 BUG!
+ if (year >= 2038) {
+ year = 2038;
+ month = Calendar.JANUARY;
+ date = 1;
+ }
+
+ Time time = new Time(Time.TIMEZONE_UTC);
+ time.set(timeOfDay.second, timeOfDay.minute, timeOfDay.hour, date,
+ month, year);
+ return time.toMillis(false /* use isDst */);
+ }
+
+ private static int getDate(String dateString) {
+ if (dateString.length() == 2) {
+ return (dateString.charAt(0) - '0') * 10
+ + (dateString.charAt(1) - '0');
+ } else {
+ return (dateString.charAt(0) - '0');
+ }
+ }
+
+ /*
+ * jan = 9 + 0 + 13 = 22 feb = 5 + 4 + 1 = 10 mar = 12 + 0 + 17 = 29 apr = 0
+ * + 15 + 17 = 32 may = 12 + 0 + 24 = 36 jun = 9 + 20 + 13 = 42 jul = 9 + 20
+ * + 11 = 40 aug = 0 + 20 + 6 = 26 sep = 18 + 4 + 15 = 37 oct = 14 + 2 + 19
+ * = 35 nov = 13 + 14 + 21 = 48 dec = 3 + 4 + 2 = 9
+ */
+ private static int getMonth(String monthString) {
+ int hash = Character.toLowerCase(monthString.charAt(0)) +
+ Character.toLowerCase(monthString.charAt(1)) +
+ Character.toLowerCase(monthString.charAt(2)) - 3 * 'a';
+ switch (hash) {
+ case 22:
+ return Calendar.JANUARY;
+ case 10:
+ return Calendar.FEBRUARY;
+ case 29:
+ return Calendar.MARCH;
+ case 32:
+ return Calendar.APRIL;
+ case 36:
+ return Calendar.MAY;
+ case 42:
+ return Calendar.JUNE;
+ case 40:
+ return Calendar.JULY;
+ case 26:
+ return Calendar.AUGUST;
+ case 37:
+ return Calendar.SEPTEMBER;
+ case 35:
+ return Calendar.OCTOBER;
+ case 48:
+ return Calendar.NOVEMBER;
+ case 9:
+ return Calendar.DECEMBER;
+ default:
+ throw new IllegalArgumentException();
+ }
+ }
+
+ private static int getYear(String yearString) {
+ if (yearString.length() == 2) {
+ int year = (yearString.charAt(0) - '0') * 10
+ + (yearString.charAt(1) - '0');
+ if (year >= 70) {
+ return year + 1900;
+ } else {
+ return year + 2000;
+ }
+ } else if (yearString.length() == 3) {
+ // According to RFC 2822, three digit years should be added to 1900.
+ int year = (yearString.charAt(0) - '0') * 100
+ + (yearString.charAt(1) - '0') * 10
+ + (yearString.charAt(2) - '0');
+ return year + 1900;
+ } else if (yearString.length() == 4) {
+ return (yearString.charAt(0) - '0') * 1000
+ + (yearString.charAt(1) - '0') * 100
+ + (yearString.charAt(2) - '0') * 10
+ + (yearString.charAt(3) - '0');
+ } else {
+ return 1970;
+ }
+ }
+
+ private static TimeOfDay getTime(String timeString) {
+ // HH might be H
+ int i = 0;
+ int hour = timeString.charAt(i++) - '0';
+ if (timeString.charAt(i) != ':')
+ hour = hour * 10 + (timeString.charAt(i++) - '0');
+ // Skip ':'
+ i++;
+
+ int minute = (timeString.charAt(i++) - '0') * 10
+ + (timeString.charAt(i++) - '0');
+ // Skip ':'
+ i++;
+
+ int second = (timeString.charAt(i++) - '0') * 10
+ + (timeString.charAt(i++) - '0');
+
+ return new TimeOfDay(hour, minute, second);
+ }
+}
diff --git a/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/V14CustomNotification.java b/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/V14CustomNotification.java
new file mode 100644
index 0000000000..e736603e2a
--- /dev/null
+++ b/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/V14CustomNotification.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.android.vending.expansion.downloader.impl;
+
+import com.android.vending.expansion.downloader.R;
+import com.google.android.vending.expansion.downloader.Helpers;
+
+import android.app.Notification;
+import android.app.PendingIntent;
+import android.content.Context;
+
+public class V14CustomNotification implements DownloadNotification.ICustomNotification {
+
+ CharSequence mTitle;
+ CharSequence mTicker;
+ int mIcon;
+ long mTotalKB = -1;
+ long mCurrentKB = -1;
+ long mTimeRemaining;
+ PendingIntent mPendingIntent;
+
+ @Override
+ public void setIcon(int icon) {
+ mIcon = icon;
+ }
+
+ @Override
+ public void setTitle(CharSequence title) {
+ mTitle = title;
+ }
+
+ @Override
+ public void setTotalBytes(long totalBytes) {
+ mTotalKB = totalBytes;
+ }
+
+ @Override
+ public void setCurrentBytes(long currentBytes) {
+ mCurrentKB = currentBytes;
+ }
+
+ void setProgress(Notification.Builder builder) {
+
+ }
+
+ @Override
+ public Notification updateNotification(Context c) {
+ Notification.Builder builder = new Notification.Builder(c);
+ builder.setContentTitle(mTitle);
+ if (mTotalKB > 0 && -1 != mCurrentKB) {
+ builder.setProgress((int) (mTotalKB >> 8), (int) (mCurrentKB >> 8), false);
+ } else {
+ builder.setProgress(0, 0, true);
+ }
+ builder.setContentText(Helpers.getDownloadProgressString(mCurrentKB, mTotalKB));
+ builder.setContentInfo(c.getString(R.string.time_remaining_notification,
+ Helpers.getTimeRemaining(mTimeRemaining)));
+ if (mIcon != 0) {
+ builder.setSmallIcon(mIcon);
+ } else {
+ int iconResource = android.R.drawable.stat_sys_download;
+ builder.setSmallIcon(iconResource);
+ }
+ builder.setOngoing(true);
+ builder.setTicker(mTicker);
+ builder.setContentIntent(mPendingIntent);
+ builder.setOnlyAlertOnce(true);
+
+ return builder.getNotification();
+ }
+
+ @Override
+ public void setPendingIntent(PendingIntent contentIntent) {
+ mPendingIntent = contentIntent;
+ }
+
+ @Override
+ public void setTicker(CharSequence ticker) {
+ mTicker = ticker;
+ }
+
+ @Override
+ public void setTimeRemaining(long timeRemaining) {
+ mTimeRemaining = timeRemaining;
+ }
+
+}
diff --git a/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/V3CustomNotification.java b/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/V3CustomNotification.java
new file mode 100644
index 0000000000..e3666e05b9
--- /dev/null
+++ b/platform/android/libs/downloader_library/src/com/google/android/vending/expansion/downloader/impl/V3CustomNotification.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.android.vending.expansion.downloader.impl;
+
+import com.android.vending.expansion.downloader.R;
+import com.google.android.vending.expansion.downloader.Helpers;
+
+import android.app.Notification;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.graphics.BitmapFactory;
+import android.view.View;
+import android.widget.RemoteViews;
+
+public class V3CustomNotification implements DownloadNotification.ICustomNotification {
+
+ CharSequence mTitle;
+ CharSequence mTicker;
+ int mIcon;
+ long mTotalBytes = -1;
+ long mCurrentBytes = -1;
+ long mTimeRemaining;
+ PendingIntent mPendingIntent;
+ Notification mNotification = new Notification();
+
+ @Override
+ public void setIcon(int icon) {
+ mIcon = icon;
+ }
+
+ @Override
+ public void setTitle(CharSequence title) {
+ mTitle = title;
+ }
+
+ @Override
+ public void setTotalBytes(long totalBytes) {
+ mTotalBytes = totalBytes;
+ }
+
+ @Override
+ public void setCurrentBytes(long currentBytes) {
+ mCurrentBytes = currentBytes;
+ }
+
+ @Override
+ public Notification updateNotification(Context c) {
+ Notification n = mNotification;
+
+ n.icon = mIcon;
+
+ n.flags |= Notification.FLAG_ONGOING_EVENT;
+
+ if (android.os.Build.VERSION.SDK_INT > 10) {
+ n.flags |= Notification.FLAG_ONLY_ALERT_ONCE; // only matters for
+ // Honeycomb
+ }
+
+ // Build the RemoteView object
+ RemoteViews expandedView = new RemoteViews(
+ c.getPackageName(),
+ R.layout.status_bar_ongoing_event_progress_bar);
+
+ expandedView.setTextViewText(R.id.title, mTitle);
+ // look at strings
+ expandedView.setViewVisibility(R.id.description, View.VISIBLE);
+ expandedView.setTextViewText(R.id.description,
+ Helpers.getDownloadProgressString(mCurrentBytes, mTotalBytes));
+ expandedView.setViewVisibility(R.id.progress_bar_frame, View.VISIBLE);
+ expandedView.setProgressBar(R.id.progress_bar,
+ (int) (mTotalBytes >> 8),
+ (int) (mCurrentBytes >> 8),
+ mTotalBytes <= 0);
+ expandedView.setViewVisibility(R.id.time_remaining, View.VISIBLE);
+ expandedView.setTextViewText(
+ R.id.time_remaining,
+ c.getString(R.string.time_remaining_notification,
+ Helpers.getTimeRemaining(mTimeRemaining)));
+ expandedView.setTextViewText(R.id.progress_text,
+ Helpers.getDownloadProgressPercent(mCurrentBytes, mTotalBytes));
+ expandedView.setImageViewResource(R.id.appIcon, mIcon);
+ n.contentView = expandedView;
+ n.contentIntent = mPendingIntent;
+ return n;
+ }
+
+ @Override
+ public void setPendingIntent(PendingIntent contentIntent) {
+ mPendingIntent = contentIntent;
+ }
+
+ @Override
+ public void setTicker(CharSequence ticker) {
+ mTicker = ticker;
+ }
+
+ @Override
+ public void setTimeRemaining(long timeRemaining) {
+ mTimeRemaining = timeRemaining;
+ }
+
+}
diff --git a/platform/android/libs/google_play_services/.classpath b/platform/android/libs/google_play_services/.classpath
index 6aed2ebfbe..7bc01d9a9c 100644
--- a/platform/android/libs/google_play_services/.classpath
+++ b/platform/android/libs/google_play_services/.classpath
@@ -4,5 +4,6 @@
<classpathentry kind="src" path="gen"/>
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
+ <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
<classpathentry kind="output" path="bin/classes"/>
</classpath>
diff --git a/platform/android/libs/play_licensing/src/com/google/android/vending/licensing/LicenseChecker.java b/platform/android/libs/play_licensing/src/com/google/android/vending/licensing/LicenseChecker.java
index 0b1c4b6cca..8b53545e61 100644
--- a/platform/android/libs/play_licensing/src/com/google/android/vending/licensing/LicenseChecker.java
+++ b/platform/android/libs/play_licensing/src/com/google/android/vending/licensing/LicenseChecker.java
@@ -63,7 +63,7 @@ public class LicenseChecker implements ServiceConnection {
private static final int TIMEOUT_MS = 10 * 1000;
private static final SecureRandom RANDOM = new SecureRandom();
- private static final boolean DEBUG_LICENSE_ERROR = false;
+ private static final boolean DEBUG_LICENSE_ERROR = true;
private ILicensingService mService;
diff --git a/platform/bb10/detect.py b/platform/bb10/detect.py
index 22940c0f2d..3ddb7a4450 100644
--- a/platform/bb10/detect.py
+++ b/platform/bb10/detect.py
@@ -35,6 +35,8 @@ def get_flags():
('lua', 'no'),
('tools', 'no'),
('nedmalloc', 'no'),
+ ('theora', 'no'),
+
]
def configure(env):
diff --git a/platform/bb10/export/export.cpp b/platform/bb10/export/export.cpp
index 5edcf39396..d40cb82cdf 100644
--- a/platform/bb10/export/export.cpp
+++ b/platform/bb10/export/export.cpp
@@ -147,7 +147,7 @@ void EditorExportPlatformBB10::_get_property_list( List<PropertyInfo> *p_list) c
p_list->push_back( PropertyInfo( Variant::STRING, "package/name") );
p_list->push_back( PropertyInfo( Variant::STRING, "package/description",PROPERTY_HINT_MULTILINE_TEXT) );
p_list->push_back( PropertyInfo( Variant::STRING, "package/icon",PROPERTY_HINT_FILE,"png") );
- p_list->push_back( PropertyInfo( Variant::STRING, "package/custom_template", PROPERTY_HINT_FILE,"zip"));
+ p_list->push_back( PropertyInfo( Variant::STRING, "package/custom_template", PROPERTY_HINT_GLOBAL_FILE,"zip"));
p_list->push_back( PropertyInfo( Variant::STRING, "release/author") );
p_list->push_back( PropertyInfo( Variant::STRING, "release/author_id") );
diff --git a/platform/iphone/SCsub b/platform/iphone/SCsub
index 0113f75697..d30d101e1b 100644
--- a/platform/iphone/SCsub
+++ b/platform/iphone/SCsub
@@ -35,7 +35,7 @@ if env['ios_appirater'] == "yes":
obj = env_ios.Object('godot_iphone.cpp')
prog = None
-if env["target"]=="release":
+if env["target"]=="release" or env["target"] == "release_debug":
prog = env_ios.Program('#bin/godot_opt', [obj] + iphone_lib)
#action = "dsymutil "+File(prog)[0].path+" -o ../build/script_exec/build/Debug-iphoneos/script_exec.app.dSYM"
#env.AddPostAction(prog, action)
diff --git a/platform/iphone/app_delegate.mm b/platform/iphone/app_delegate.mm
index 9ba95ff0c5..9877e09ade 100644
--- a/platform/iphone/app_delegate.mm
+++ b/platform/iphone/app_delegate.mm
@@ -257,18 +257,21 @@ static int frame_count = 0;
- (void)applicationDidEnterBackground:(UIApplication *)application
{
printf("********************* did enter background\n");
+ OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_WM_FOCUS_OUT);
[view_controller.view stopAnimation];
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
printf("********************* did enter foreground\n");
+ //OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_WM_FOCUS_IN);
[view_controller.view startAnimation];
}
- (void) applicationWillResignActive:(UIApplication *)application
{
printf("********************* will resign active\n");
+ //OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_WM_FOCUS_OUT);
[view_controller.view stopAnimation]; // FIXME: pause seems to be recommended elsewhere
}
@@ -279,6 +282,7 @@ static int frame_count = 0;
printf("********************* mobile app tracker found\n");
[MobileAppTracker measureSession];
#endif
+ OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_WM_FOCUS_IN);
[view_controller.view startAnimation]; // FIXME: resume seems to be recommended elsewhere
}
diff --git a/platform/iphone/audio_driver_iphone.cpp b/platform/iphone/audio_driver_iphone.cpp
index d39b8f3c4d..c3ba0e6944 100644
--- a/platform/iphone/audio_driver_iphone.cpp
+++ b/platform/iphone/audio_driver_iphone.cpp
@@ -99,7 +99,16 @@ OSStatus AudioDriverIphone::output_callback(void *inRefCon,
AudioBuffer *abuf;
AudioDriverIphone* ad = (AudioDriverIphone*)inRefCon;
- if (!ad->active) {
+ bool mix = true;
+
+ if (!ad->active)
+ mix = false;
+ else if (ad->mutex) {
+ mix = ad->mutex->try_lock() == OK;
+ };
+
+
+ if (!mix) {
for (unsigned int i = 0; i < ioData->mNumberBuffers; i++) {
abuf = &ioData->mBuffers[i];
zeromem(abuf->mData, abuf->mDataByteSize);
@@ -118,9 +127,9 @@ OSStatus AudioDriverIphone::output_callback(void *inRefCon,
while (frames_left) {
int frames = MIN(frames_left, ad->buffer_frames);
- ad->lock();
+ //ad->lock();
ad->audio_server_process(frames, ad->samples_in);
- ad->unlock();
+ //ad->unlock();
for(int i = 0; i < frames * ad->channels; i++) {
@@ -132,6 +141,9 @@ OSStatus AudioDriverIphone::output_callback(void *inRefCon,
};
};
+ if (ad->mutex)
+ ad->mutex->unlock();
+
return 0;
};
@@ -147,11 +159,28 @@ AudioDriverSW::OutputFormat AudioDriverIphone::get_output_format() const {
return OUTPUT_STEREO;
};
-void AudioDriverIphone::lock() {};
-void AudioDriverIphone::unlock() {};
+void AudioDriverIphone::lock() {
+
+ if (active && mutex)
+ mutex->lock();
+};
+
+void AudioDriverIphone::unlock() {
+ if (active && mutex)
+ mutex->unlock();
+};
void AudioDriverIphone::finish() {
memdelete_arr(samples_in);
};
+
+AudioDriverIphone::AudioDriverIphone() {
+
+ mutex=Mutex::create();//NULL;
+};
+
+AudioDriverIphone::~AudioDriverIphone() {
+
+};
diff --git a/platform/iphone/audio_driver_iphone.h b/platform/iphone/audio_driver_iphone.h
index eec54d9ee3..05fa741282 100644
--- a/platform/iphone/audio_driver_iphone.h
+++ b/platform/iphone/audio_driver_iphone.h
@@ -34,6 +34,7 @@ class AudioDriverIphone : public AudioDriverSW {
AudioComponentInstance audio_unit;
bool active;
+ Mutex *mutex;
int channels;
int32_t* samples_in;
@@ -59,5 +60,8 @@ public:
virtual void lock();
virtual void unlock();
virtual void finish();
+
+ AudioDriverIphone();
+ ~AudioDriverIphone();
};
diff --git a/platform/iphone/detect.py b/platform/iphone/detect.py
index ec6e4c98f1..2065d459cd 100644
--- a/platform/iphone/detect.py
+++ b/platform/iphone/detect.py
@@ -28,14 +28,14 @@ def get_opts():
('ios_gles22_override', 'Force GLES2.0 on iOS', 'yes'),
('ios_GLES1_override', 'Force legacy GLES (1.1) on iOS', 'no'),
('ios_appirater', 'Enable Appirater', 'no'),
- ('ios_exceptions', 'Use exceptions when compiling on playbook', 'no'),
+ ('ios_exceptions', 'Use exceptions when compiling on playbook', 'yes'),
]
def get_flags():
return [
('lua', 'no'),
- ('tools', 'yes'),
+ ('tools', 'no'),
('nedmalloc', 'no'),
('webp', 'yes'),
('openssl','builtin'), #use builtin openssl
@@ -104,10 +104,17 @@ def configure(env):
env['OBJSUFFIX'] = "_opt"+env['OBJSUFFIX']
env['LIBSUFFIX'] = "_opt"+env['LIBSUFFIX']
+ elif env["target"] == "release_debug":
+ env.Append(CCFLAGS=['-Os', '-ffast-math', '-DNS_BLOCK_ASSERTIONS=1','-Wall','-DDEBUG_ENABLED'])
+ env.Append(LINKFLAGS=['-Os', '-ffast-math'])
+ env.Append(CPPFLAGS=['-DDEBUG_MEMORY_ENABLED'])
+ env['OBJSUFFIX'] = "_opt"+env['OBJSUFFIX']
+ env['LIBSUFFIX'] = "_opt"+env['LIBSUFFIX']
+
elif (env["target"]=="debug"):
env.Append(CCFLAGS=['-D_DEBUG', '-DDEBUG=1', '-gdwarf-2', '-Wall', '-O0', '-DDEBUG_ENABLED'])
- env.Append(CPPFLAGS=['-DDEBUG_MEMORY_ALLOC'])
+ env.Append(CPPFLAGS=['-DDEBUG_MEMORY_ENABLED'])
elif (env["target"]=="profile"):
diff --git a/platform/iphone/gl_view.mm b/platform/iphone/gl_view.mm
index 500c7c7174..06b679c305 100755
--- a/platform/iphone/gl_view.mm
+++ b/platform/iphone/gl_view.mm
@@ -70,7 +70,7 @@ bool _play_video(String p_path, float p_volume) {
float player_volume = p_volume * AudioServer::get_singleton()->get_singleton()->get_stream_global_volume_scale();
video_previous_volume = [[MPMusicPlayerController applicationMusicPlayer] volume];
- [[MPMusicPlayerController applicationMusicPlayer] setVolume: player_volume];
+ //[[MPMusicPlayerController applicationMusicPlayer] setVolume: player_volume];
p_path = Globals::get_singleton()->globalize_path(p_path);
@@ -113,7 +113,7 @@ void _pause_video() {
void _stop_video() {
[_instance.moviePlayerController stop];
[_instance.moviePlayerController.view removeFromSuperview];
- [[MPMusicPlayerController applicationMusicPlayer] setVolume: video_previous_volume];
+ //[[MPMusicPlayerController applicationMusicPlayer] setVolume: video_previous_volume];
video_playing = false;
}
@@ -554,7 +554,7 @@ static void clear_touches() {
[_instance.moviePlayerController stop];
[_instance.moviePlayerController.view removeFromSuperview];
- [[MPMusicPlayerController applicationMusicPlayer] setVolume: video_previous_volume];
+ //[[MPMusicPlayerController applicationMusicPlayer] setVolume: video_previous_volume];
video_playing = false;
}
diff --git a/platform/iphone/globals/global_defaults.cpp b/platform/iphone/globals/global_defaults.cpp
index 63463ab366..a4929c57dc 100644
--- a/platform/iphone/globals/global_defaults.cpp
+++ b/platform/iphone/globals/global_defaults.cpp
@@ -6,6 +6,7 @@
void register_iphone_global_defaults() {
GLOBAL_DEF("rasterizer.iOS/use_fragment_lighting",false);
+ GLOBAL_DEF("rasterizer.iOS/fp16_framebuffer",false);
GLOBAL_DEF("display.iOS/driver","GLES2");
Globals::get_singleton()->set_custom_property_info("display.iOS/driver",PropertyInfo(Variant::STRING,"display.iOS/driver",PROPERTY_HINT_ENUM,"GLES1,GLES2"));
}
diff --git a/platform/iphone/in_app_store.h b/platform/iphone/in_app_store.h
index dba1a1a5a1..656d126ead 100644
--- a/platform/iphone/in_app_store.h
+++ b/platform/iphone/in_app_store.h
@@ -49,6 +49,8 @@ public:
int get_pending_event_count();
Variant pop_pending_event();
+ void finish_transaction(String product_id);
+ void set_auto_finish_transaction(bool b);
void _post_event(Variant p_event);
void _record_purchase(String product_id);
diff --git a/platform/iphone/in_app_store.mm b/platform/iphone/in_app_store.mm
index 9b932d147b..f3640c3076 100644
--- a/platform/iphone/in_app_store.mm
+++ b/platform/iphone/in_app_store.mm
@@ -32,8 +32,12 @@
extern "C" {
#import <StoreKit/StoreKit.h>
+#import <Foundation/Foundation.h>
};
+bool auto_finish_transactions = true;
+NSMutableDictionary* pending_transactions = [NSMutableDictionary dictionary];
+
@interface SKProduct (LocalizedPrice)
@property (nonatomic, readonly) NSString *localizedPrice;
@end
@@ -63,6 +67,8 @@ void InAppStore::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_pending_event_count"),&InAppStore::get_pending_event_count);
ObjectTypeDB::bind_method(_MD("pop_pending_event"),&InAppStore::pop_pending_event);
+ ObjectTypeDB::bind_method(_MD("finish_transaction"),&InAppStore::finish_transaction);
+ ObjectTypeDB::bind_method(_MD("set_auto_finish_transaction"),&InAppStore::set_auto_finish_transaction);
};
@interface ProductsDelegate : NSObject<SKProductsRequestDelegate> {
@@ -162,11 +168,13 @@ Error InAppStore::request_product_info(Variant p_params) {
case SKPaymentTransactionStatePurchased: {
printf("status purchased!\n");
String pid = String::utf8([transaction.payment.productIdentifier UTF8String]);
+ String transactionId = String::utf8([transaction.transactionIdentifier UTF8String]);
InAppStore::get_singleton()->_record_purchase(pid);
Dictionary ret;
ret["type"] = "purchase";
ret["result"] = "ok";
ret["product_id"] = pid;
+ ret["transaction_id"] = transactionId;
NSData* receipt = nil;
int sdk_version = 6;
@@ -207,7 +215,13 @@ Error InAppStore::request_product_info(Variant p_params) {
ret["receipt"] = receipt_ret;
InAppStore::get_singleton()->_post_event(ret);
- [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
+
+ if (auto_finish_transactions){
+ [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
+ }
+ else{
+ [pending_transactions setObject:transaction forKey:transaction.payment.productIdentifier];
+ }
} break;
case SKPaymentTransactionStateFailed: {
printf("status transaction failed!\n");
@@ -290,11 +304,26 @@ InAppStore* InAppStore::get_singleton() {
InAppStore::InAppStore() {
ERR_FAIL_COND(instance != NULL);
instance = this;
+ auto_finish_transactions = false;
TransObserver* observer = [[TransObserver alloc] init];
[[SKPaymentQueue defaultQueue] addTransactionObserver:observer];
+ //pending_transactions = [NSMutableDictionary dictionary];
};
+void InAppStore::finish_transaction(String product_id){
+ NSString* prod_id = [NSString stringWithCString:product_id.utf8().get_data() encoding:NSUTF8StringEncoding];
+
+ if ([pending_transactions objectForKey:prod_id]){
+ [[SKPaymentQueue defaultQueue] finishTransaction:[pending_transactions objectForKey:prod_id]];
+ [pending_transactions removeObjectForKey:prod_id];
+ }
+};
+
+void InAppStore::set_auto_finish_transaction(bool b){
+ auto_finish_transactions = b;
+}
+
InAppStore::~InAppStore() {
};
diff --git a/platform/javascript/export/export.cpp b/platform/javascript/export/export.cpp
index 928d128799..8924f38de0 100644
--- a/platform/javascript/export/export.cpp
+++ b/platform/javascript/export/export.cpp
@@ -126,8 +126,8 @@ bool EditorExportPlatformJavaScript::_get(const StringName& p_name,Variant &r_re
}
void EditorExportPlatformJavaScript::_get_property_list( List<PropertyInfo> *p_list) const{
- p_list->push_back( PropertyInfo( Variant::STRING, "custom_package/debug", PROPERTY_HINT_FILE,"zip"));
- p_list->push_back( PropertyInfo( Variant::STRING, "custom_package/release", PROPERTY_HINT_FILE,"zip"));
+ p_list->push_back( PropertyInfo( Variant::STRING, "custom_package/debug", PROPERTY_HINT_GLOBAL_FILE,"zip"));
+ p_list->push_back( PropertyInfo( Variant::STRING, "custom_package/release", PROPERTY_HINT_GLOBAL_FILE,"zip"));
p_list->push_back( PropertyInfo( Variant::INT, "options/memory_size",PROPERTY_HINT_ENUM,"32mb,64mb,128mb,256mb,512mb,1024mb"));
p_list->push_back( PropertyInfo( Variant::BOOL, "browser/enable_run"));
diff --git a/platform/osx/export/export.cpp b/platform/osx/export/export.cpp
index 087a648700..885f234a0a 100644
--- a/platform/osx/export/export.cpp
+++ b/platform/osx/export/export.cpp
@@ -138,8 +138,8 @@ bool EditorExportPlatformOSX::_get(const StringName& p_name,Variant &r_ret) cons
}
void EditorExportPlatformOSX::_get_property_list( List<PropertyInfo> *p_list) const{
- p_list->push_back( PropertyInfo( Variant::STRING, "custom_package/debug", PROPERTY_HINT_FILE,"zip"));
- p_list->push_back( PropertyInfo( Variant::STRING, "custom_package/release", PROPERTY_HINT_FILE,"zip"));
+ p_list->push_back( PropertyInfo( Variant::STRING, "custom_package/debug", PROPERTY_HINT_GLOBAL_FILE,"zip"));
+ p_list->push_back( PropertyInfo( Variant::STRING, "custom_package/release", PROPERTY_HINT_GLOBAL_FILE,"zip"));
p_list->push_back( PropertyInfo( Variant::STRING, "application/name") );
p_list->push_back( PropertyInfo( Variant::STRING, "application/info") );
diff --git a/platform/server/detect.py b/platform/server/detect.py
index 1ce8c23229..682c6d0729 100644
--- a/platform/server/detect.py
+++ b/platform/server/detect.py
@@ -28,6 +28,7 @@ def get_flags():
return [
('builtin_zlib', 'no'),
+ ('theora','no'), #use builtin openssl
]
diff --git a/platform/windows/detect.py b/platform/windows/detect.py
index 0e21540e13..3277884165 100644
--- a/platform/windows/detect.py
+++ b/platform/windows/detect.py
@@ -51,8 +51,8 @@ def get_flags():
return [
('freetype','builtin'), #use builtin freetype
- ('openssl','builtin'), #use builtin openssl
- ]
+ ('openssl','builtin'), #use builtin openssl
+ ]
@@ -166,6 +166,7 @@ def configure(env):
env.Append(CCFLAGS=['-O3','-ffast-math','-fomit-frame-pointer','-msse2'])
env['OBJSUFFIX'] = "_opt"+env['OBJSUFFIX']
env['LIBSUFFIX'] = "_opt"+env['LIBSUFFIX']
+ env.Append(LINKFLAGS=['-Wl,--subsystem,windows'])
elif (env["target"]=="release_debug"):
env.Append(CCFLAGS=['-O2','-DDEBUG_ENABLED'])
diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp
index 64219d6c17..5e57827c68 100644
--- a/platform/windows/os_windows.cpp
+++ b/platform/windows/os_windows.cpp
@@ -206,6 +206,54 @@ bool OS_Windows::can_draw() const {
return !minimized;
};
+#define MI_WP_SIGNATURE 0xFF515700
+#define SIGNATURE_MASK 0xFFFFFF00
+#define IsPenEvent(dw) (((dw) & SIGNATURE_MASK) == MI_WP_SIGNATURE)
+
+
+void OS_Windows::_touch_event(int idx, UINT uMsg, WPARAM wParam, LPARAM lParam) {
+
+ InputEvent event;
+ event.type = InputEvent::SCREEN_TOUCH;
+ event.ID=++last_id;
+ event.screen_touch.index = idx;
+
+ switch (uMsg) {
+ case WM_LBUTTONDOWN:
+ case WM_MBUTTONDOWN:
+ case WM_RBUTTONDOWN: {
+
+ event.screen_touch.pressed = true;
+ } break;
+
+ case WM_LBUTTONUP:
+ case WM_MBUTTONUP:
+ case WM_RBUTTONUP: {
+ event.screen_touch.pressed = false;
+ } break;
+ };
+
+ event.screen_touch.x=GET_X_LPARAM(lParam);
+ event.screen_touch.y=GET_Y_LPARAM(lParam);
+
+ if (main_loop) {
+ input->parse_input_event(event);
+ }
+};
+
+void OS_Windows::_drag_event(int idx,UINT uMsg, WPARAM wParam, LPARAM lParam) {
+
+ InputEvent event;
+ event.type = InputEvent::SCREEN_DRAG;
+ event.ID=++last_id;
+ event.screen_drag.index = idx;
+
+ event.screen_drag.x=GET_X_LPARAM(lParam);
+ event.screen_drag.y=GET_Y_LPARAM(lParam);
+
+ if (main_loop)
+ input->parse_input_event(event);
+};
LRESULT OS_Windows::WndProc(HWND hWnd,UINT uMsg, WPARAM wParam, LPARAM lParam) {
@@ -270,28 +318,41 @@ LRESULT OS_Windows::WndProc(HWND hWnd,UINT uMsg, WPARAM wParam, LPARAM lParam) {
}
case WM_MOUSELEAVE: {
- old_invalid=true;
- outside=true;
+ old_invalid=true;
+ outside=true;
} break;
case WM_MOUSEMOVE: {
- if (outside) {
+ if (outside) {
- CursorShape c=cursor_shape;
- cursor_shape=CURSOR_MAX;
- set_cursor_shape(c);
- outside=false;
+ CursorShape c=cursor_shape;
+ cursor_shape=CURSOR_MAX;
+ set_cursor_shape(c);
+ outside=false;
+
+ //Once-Off notification, must call again....
+ TRACKMOUSEEVENT tme;
+ tme.cbSize=sizeof(TRACKMOUSEEVENT);
+ tme.dwFlags=TME_LEAVE;
+ tme.hwndTrack=hWnd;
+ tme.dwHoverTime=HOVER_DEFAULT;
+ TrackMouseEvent(&tme);
+
+ }
+
+ LPARAM extra = GetMessageExtraInfo();
+ if (IsPenEvent(extra)) {
+
+ int idx = extra & 0x7f;
+ _drag_event(idx, uMsg, wParam, lParam);
+ if (idx != 0) {
+ return 0;
+ };
+ // fallthrough for mouse event
+ };
- //Once-Off notification, must call again....
- TRACKMOUSEEVENT tme;
- tme.cbSize=sizeof(TRACKMOUSEEVENT);
- tme.dwFlags=TME_LEAVE;
- tme.hwndTrack=hWnd;
- tme.dwHoverTime=HOVER_DEFAULT;
- TrackMouseEvent(&tme);
- }
InputEvent event;
event.type=InputEvent::MOUSE_MOTION;
event.ID=++last_id;
@@ -360,6 +421,17 @@ LRESULT OS_Windows::WndProc(HWND hWnd,UINT uMsg, WPARAM wParam, LPARAM lParam) {
/*case WM_XBUTTONDOWN:
case WM_XBUTTONUP: */{
+ LPARAM extra = GetMessageExtraInfo();
+ if (IsPenEvent(extra)) {
+
+ int idx = extra & 0x7f;
+ _touch_event(idx, uMsg, wParam, lParam);
+ if (idx != 0) {
+ return 0;
+ };
+ // fallthrough for mouse event
+ };
+
InputEvent event;
event.type=InputEvent::MOUSE_BUTTON;
event.ID=++last_id;
@@ -574,6 +646,8 @@ LRESULT CALLBACK WndProc(HWND hWnd,UINT uMsg, WPARAM wParam, LPARAM lParam) {
void OS_Windows::probe_joysticks() {
+ static uint32_t last_attached = 0;
+
int device_count = joyGetNumDevs();
JOYINFOEX jinfo;
@@ -582,21 +656,40 @@ void OS_Windows::probe_joysticks() {
for (int i=0; i<JOYSTICKS_MAX; i++) {
- joysticks[i].attached = (device_count > 0) && (joyGetPosEx(JOYSTICKID1 + i, &jinfo) == JOYERR_NOERROR);
-
- if (!joysticks[i].attached) {
+ Joystick joy;
+ joy.id = i;
+ joy.attached = (device_count > 0) && (joyGetPosEx(JOYSTICKID1 + i, &jinfo) == JOYERR_NOERROR);
+ if (joy.attached == (last_attached & (1 << i) != 0)) {
continue;
};
- joysticks[i].last_buttons = jinfo.dwButtons;
+ // there's been a change since last call
+
+ if (joy.attached)
+ last_attached = last_attached | (1 << i);
+ else
+ last_attached &= ~(1 << i);
+
+ if (joy.attached) {
+
+ joy.last_buttons = jinfo.dwButtons;
- joysticks[i].last_axis[0] = jinfo.dwXpos;
- joysticks[i].last_axis[1] = jinfo.dwYpos;
- joysticks[i].last_axis[2] = jinfo.dwZpos;
- joysticks[i].last_axis[3] = jinfo.dwRpos;
- joysticks[i].last_axis[4] = jinfo.dwUpos;
- joysticks[i].last_axis[5] = jinfo.dwVpos;
+ joy.last_axis[0] = jinfo.dwXpos;
+ joy.last_axis[1] = jinfo.dwYpos;
+ joy.last_axis[2] = jinfo.dwZpos;
+ joy.last_axis[3] = jinfo.dwRpos;
+ joy.last_axis[4] = jinfo.dwUpos;
+ joy.last_axis[5] = jinfo.dwVpos;
+
+ JOYCAPS jcaps;
+ MMRESULT res = joyGetDevCaps(JOYSTICKID1 + i, &jcaps, sizeof(jcaps));
+ if (res == JOYERR_NOERROR) {
+ joy.name = jcaps.szPname;
+ };
+ };
+
+ joystick_change_queue.push_back(joy);
};
};
@@ -998,7 +1091,13 @@ void OS_Windows::initialize(const VideoMode& p_desired,int p_video_driver,int p_
spatial_sound_2d_server = memnew( SpatialSound2DServerSW );
spatial_sound_2d_server->init();
- probe_joysticks();
+ probe_joysticks(); // todo: move this to a thread
+ while (joystick_change_queue.size() > 0) {
+ Joystick joy = joystick_change_queue.front()->get();
+ joystick_change_queue.pop_front();
+ joysticks[joy.id] = joy;
+ input->joy_connection_changed(joy.id, joy.attached, joy.name);
+ };
TRACKMOUSEEVENT tme;
tme.cbSize=sizeof(TRACKMOUSEEVENT);
diff --git a/platform/windows/os_windows.h b/platform/windows/os_windows.h
index 365808d175..1a41b9d77d 100644
--- a/platform/windows/os_windows.h
+++ b/platform/windows/os_windows.h
@@ -106,13 +106,16 @@ class OS_Windows : public OS {
struct Joystick {
+ int id;
bool attached;
DWORD last_axis[JOY_AXIS_COUNT];
DWORD last_buttons;
DWORD last_pov;
+ String name;
Joystick() {
+ id = -1;
attached = false;
for (int i=0; i<JOY_AXIS_COUNT; i++) {
@@ -123,6 +126,7 @@ class OS_Windows : public OS {
};
};
+ List<Joystick> joystick_change_queue;
int joystick_count;
Joystick joysticks[JOYSTICKS_MAX];
@@ -156,6 +160,10 @@ class OS_Windows : public OS {
void _post_dpad(DWORD p_dpad, int p_device, bool p_pressed);
+ void _drag_event(int idx,UINT uMsg, WPARAM wParam, LPARAM lParam);
+ void _touch_event(int idx, UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+
// functions used by main to initialize/deintialize the OS
protected:
virtual int get_video_driver_count() const;
diff --git a/platform/winrt/SCsub b/platform/winrt/SCsub
new file mode 100644
index 0000000000..c83f4fab32
--- /dev/null
+++ b/platform/winrt/SCsub
@@ -0,0 +1,8 @@
+Import('env')
+
+files = [
+ 'thread_winrt.cpp',
+# '#platform/windows/stream_peer_winsock.cpp',
+]
+
+env.Program('#bin/godot_rt.exe', files)
diff --git a/platform/winrt/detect.py b/platform/winrt/detect.py
new file mode 100644
index 0000000000..d09688b71c
--- /dev/null
+++ b/platform/winrt/detect.py
@@ -0,0 +1,83 @@
+
+
+import os
+
+import sys
+
+
+def is_active():
+ return True
+
+def get_name():
+ return "WinRT"
+
+def can_build():
+ if (os.name=="nt"):
+ #building natively on windows!
+ if (os.getenv("VSINSTALLDIR")):
+ return True
+ return False
+
+def get_opts():
+ return []
+
+def get_flags():
+
+ return []
+
+
+def configure(env):
+
+ env.Append(CPPPATH=['#platform/winrt', '#platform/winrt/include'])
+
+ env['OBJSUFFIX'] = ".rt" + env['OBJSUFFIX']
+ env['LIBSUFFIX'] = ".rt" + env['LIBSUFFIX']
+
+ env.Append(LIBPATH=['#platform/winrt/x64/lib'])
+
+ if (env["target"]=="release"):
+
+ env.Append(CCFLAGS=['/O2'])
+ env.Append(LINKFLAGS=['/SUBSYSTEM:WINDOWS'])
+ env.Append(LINKFLAGS=['/ENTRY:mainCRTStartup'])
+
+ elif (env["target"]=="test"):
+
+ env.Append(CCFLAGS=['/O2','/DDEBUG_ENABLED','/DD3D_DEBUG_INFO'])
+ env.Append(LINKFLAGS=['/SUBSYSTEM:CONSOLE'])
+
+ elif (env["target"]=="debug"):
+
+ env.Append(CCFLAGS=['/Zi','/DDEBUG_ENABLED','/DD3D_DEBUG_INFO','/O1'])
+ env.Append(LINKFLAGS=['/SUBSYSTEM:CONSOLE'])
+ env.Append(LINKFLAGS=['/DEBUG'])
+
+ elif (env["target"]=="profile"):
+
+ env.Append(CCFLAGS=['-g','-pg'])
+ env.Append(LINKFLAGS=['-pg'])
+
+ env.Append(CCFLAGS=['/Gd','/GR','/nologo', '/ZW', '/EHsc'])
+ env.Append(CXXFLAGS=['/TP'])
+ env.Append(CPPFLAGS=['/DMSVC', '/GR', ])
+ #env.Append(CCFLAGS=['/I'+os.getenv("WindowsSdkDir")+"/Include"])
+ env.Append(CCFLAGS=['/DWINRT_ENABLED'])
+ env.Append(CCFLAGS=['/DWINDOWS_ENABLED'])
+ env.Append(CCFLAGS=['/DWINAPI_FAMILY=WINAPI_FAMILY_APP'])
+ env.Append(CCFLAGS=['/DRTAUDIO_ENABLED'])
+ #env.Append(CCFLAGS=['/DWIN32'])
+ env.Append(CCFLAGS=['/DTYPED_METHOD_BIND'])
+
+ env.Append(CCFLAGS=['/DGLES2_ENABLED'])
+ #env.Append(CCFLAGS=['/DGLES1_ENABLED'])
+ env.Append(LIBS=['winmm','opengl32','dsound','kernel32','ole32','user32','gdi32', 'IPHLPAPI', 'wsock32', 'shell32','advapi32'])
+
+ import methods
+ env.Append( BUILDERS = { 'GLSL120' : env.Builder(action = methods.build_legacygl_headers, suffix = 'glsl.h',src_suffix = '.glsl') } )
+ env.Append( BUILDERS = { 'GLSL' : env.Builder(action = methods.build_glsl_headers, suffix = 'glsl.h',src_suffix = '.glsl') } )
+ env.Append( BUILDERS = { 'HLSL9' : env.Builder(action = methods.build_hlsl_dx9_headers, suffix = 'hlsl.h',src_suffix = '.hlsl') } )
+ env.Append( BUILDERS = { 'GLSL120GLES' : env.Builder(action = methods.build_gles2_headers, suffix = 'glsl.h',src_suffix = '.glsl') } )
+
+ env['ENV'] = os.environ;
+
+
diff --git a/platform/winrt/include/EGL/egl.h b/platform/winrt/include/EGL/egl.h
new file mode 100644
index 0000000000..fb6f9b71e0
--- /dev/null
+++ b/platform/winrt/include/EGL/egl.h
@@ -0,0 +1,298 @@
+#ifndef __egl_h_
+#define __egl_h_ 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** Copyright (c) 2013-2014 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+/*
+** This header is generated from the Khronos OpenGL / OpenGL ES XML
+** API Registry. The current version of the Registry, generator scripts
+** used to make the header, and the header can be found at
+** http://www.opengl.org/registry/
+**
+** Khronos $Revision: 27018 $ on $Date: 2014-06-10 08:06:12 -0700 (Tue, 10 Jun 2014) $
+*/
+
+#include <EGL/eglplatform.h>
+
+/* Generated on date 20140610 */
+
+/* Generated C header for:
+ * API: egl
+ * Versions considered: .*
+ * Versions emitted: .*
+ * Default extensions included: None
+ * Additional extensions included: _nomatch_^
+ * Extensions removed: _nomatch_^
+ */
+
+#ifndef EGL_VERSION_1_0
+#define EGL_VERSION_1_0 1
+typedef unsigned int EGLBoolean;
+typedef void *EGLDisplay;
+#include <KHR/khrplatform.h>
+#include <EGL/eglplatform.h>
+typedef void *EGLConfig;
+typedef void *EGLSurface;
+typedef void *EGLContext;
+typedef void (*__eglMustCastToProperFunctionPointerType)(void);
+#define EGL_ALPHA_SIZE 0x3021
+#define EGL_BAD_ACCESS 0x3002
+#define EGL_BAD_ALLOC 0x3003
+#define EGL_BAD_ATTRIBUTE 0x3004
+#define EGL_BAD_CONFIG 0x3005
+#define EGL_BAD_CONTEXT 0x3006
+#define EGL_BAD_CURRENT_SURFACE 0x3007
+#define EGL_BAD_DISPLAY 0x3008
+#define EGL_BAD_MATCH 0x3009
+#define EGL_BAD_NATIVE_PIXMAP 0x300A
+#define EGL_BAD_NATIVE_WINDOW 0x300B
+#define EGL_BAD_PARAMETER 0x300C
+#define EGL_BAD_SURFACE 0x300D
+#define EGL_BLUE_SIZE 0x3022
+#define EGL_BUFFER_SIZE 0x3020
+#define EGL_CONFIG_CAVEAT 0x3027
+#define EGL_CONFIG_ID 0x3028
+#define EGL_CORE_NATIVE_ENGINE 0x305B
+#define EGL_DEPTH_SIZE 0x3025
+#define EGL_DONT_CARE ((EGLint)-1)
+#define EGL_DRAW 0x3059
+#define EGL_EXTENSIONS 0x3055
+#define EGL_FALSE 0
+#define EGL_GREEN_SIZE 0x3023
+#define EGL_HEIGHT 0x3056
+#define EGL_LARGEST_PBUFFER 0x3058
+#define EGL_LEVEL 0x3029
+#define EGL_MAX_PBUFFER_HEIGHT 0x302A
+#define EGL_MAX_PBUFFER_PIXELS 0x302B
+#define EGL_MAX_PBUFFER_WIDTH 0x302C
+#define EGL_NATIVE_RENDERABLE 0x302D
+#define EGL_NATIVE_VISUAL_ID 0x302E
+#define EGL_NATIVE_VISUAL_TYPE 0x302F
+#define EGL_NONE 0x3038
+#define EGL_NON_CONFORMANT_CONFIG 0x3051
+#define EGL_NOT_INITIALIZED 0x3001
+#define EGL_NO_CONTEXT ((EGLContext)0)
+#define EGL_NO_DISPLAY ((EGLDisplay)0)
+#define EGL_NO_SURFACE ((EGLSurface)0)
+#define EGL_PBUFFER_BIT 0x0001
+#define EGL_PIXMAP_BIT 0x0002
+#define EGL_READ 0x305A
+#define EGL_RED_SIZE 0x3024
+#define EGL_SAMPLES 0x3031
+#define EGL_SAMPLE_BUFFERS 0x3032
+#define EGL_SLOW_CONFIG 0x3050
+#define EGL_STENCIL_SIZE 0x3026
+#define EGL_SUCCESS 0x3000
+#define EGL_SURFACE_TYPE 0x3033
+#define EGL_TRANSPARENT_BLUE_VALUE 0x3035
+#define EGL_TRANSPARENT_GREEN_VALUE 0x3036
+#define EGL_TRANSPARENT_RED_VALUE 0x3037
+#define EGL_TRANSPARENT_RGB 0x3052
+#define EGL_TRANSPARENT_TYPE 0x3034
+#define EGL_TRUE 1
+#define EGL_VENDOR 0x3053
+#define EGL_VERSION 0x3054
+#define EGL_WIDTH 0x3057
+#define EGL_WINDOW_BIT 0x0004
+EGLAPI EGLBoolean EGLAPIENTRY eglChooseConfig (EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config);
+EGLAPI EGLBoolean EGLAPIENTRY eglCopyBuffers (EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target);
+EGLAPI EGLContext EGLAPIENTRY eglCreateContext (EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list);
+EGLAPI EGLSurface EGLAPIENTRY eglCreatePbufferSurface (EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list);
+EGLAPI EGLSurface EGLAPIENTRY eglCreatePixmapSurface (EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list);
+EGLAPI EGLSurface EGLAPIENTRY eglCreateWindowSurface (EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglDestroyContext (EGLDisplay dpy, EGLContext ctx);
+EGLAPI EGLBoolean EGLAPIENTRY eglDestroySurface (EGLDisplay dpy, EGLSurface surface);
+EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigAttrib (EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value);
+EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigs (EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config);
+EGLAPI EGLDisplay EGLAPIENTRY eglGetCurrentDisplay (void);
+EGLAPI EGLSurface EGLAPIENTRY eglGetCurrentSurface (EGLint readdraw);
+EGLAPI EGLDisplay EGLAPIENTRY eglGetDisplay (EGLNativeDisplayType display_id);
+EGLAPI EGLint EGLAPIENTRY eglGetError (void);
+EGLAPI __eglMustCastToProperFunctionPointerType EGLAPIENTRY eglGetProcAddress (const char *procname);
+EGLAPI EGLBoolean EGLAPIENTRY eglInitialize (EGLDisplay dpy, EGLint *major, EGLint *minor);
+EGLAPI EGLBoolean EGLAPIENTRY eglMakeCurrent (EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryContext (EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value);
+EGLAPI const char *EGLAPIENTRY eglQueryString (EGLDisplay dpy, EGLint name);
+EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurface (EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value);
+EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffers (EGLDisplay dpy, EGLSurface surface);
+EGLAPI EGLBoolean EGLAPIENTRY eglTerminate (EGLDisplay dpy);
+EGLAPI EGLBoolean EGLAPIENTRY eglWaitGL (void);
+EGLAPI EGLBoolean EGLAPIENTRY eglWaitNative (EGLint engine);
+#endif /* EGL_VERSION_1_0 */
+
+#ifndef EGL_VERSION_1_1
+#define EGL_VERSION_1_1 1
+#define EGL_BACK_BUFFER 0x3084
+#define EGL_BIND_TO_TEXTURE_RGB 0x3039
+#define EGL_BIND_TO_TEXTURE_RGBA 0x303A
+#define EGL_CONTEXT_LOST 0x300E
+#define EGL_MIN_SWAP_INTERVAL 0x303B
+#define EGL_MAX_SWAP_INTERVAL 0x303C
+#define EGL_MIPMAP_TEXTURE 0x3082
+#define EGL_MIPMAP_LEVEL 0x3083
+#define EGL_NO_TEXTURE 0x305C
+#define EGL_TEXTURE_2D 0x305F
+#define EGL_TEXTURE_FORMAT 0x3080
+#define EGL_TEXTURE_RGB 0x305D
+#define EGL_TEXTURE_RGBA 0x305E
+#define EGL_TEXTURE_TARGET 0x3081
+EGLAPI EGLBoolean EGLAPIENTRY eglBindTexImage (EGLDisplay dpy, EGLSurface surface, EGLint buffer);
+EGLAPI EGLBoolean EGLAPIENTRY eglReleaseTexImage (EGLDisplay dpy, EGLSurface surface, EGLint buffer);
+EGLAPI EGLBoolean EGLAPIENTRY eglSurfaceAttrib (EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value);
+EGLAPI EGLBoolean EGLAPIENTRY eglSwapInterval (EGLDisplay dpy, EGLint interval);
+#endif /* EGL_VERSION_1_1 */
+
+#ifndef EGL_VERSION_1_2
+#define EGL_VERSION_1_2 1
+typedef unsigned int EGLenum;
+typedef void *EGLClientBuffer;
+#define EGL_ALPHA_FORMAT 0x3088
+#define EGL_ALPHA_FORMAT_NONPRE 0x308B
+#define EGL_ALPHA_FORMAT_PRE 0x308C
+#define EGL_ALPHA_MASK_SIZE 0x303E
+#define EGL_BUFFER_PRESERVED 0x3094
+#define EGL_BUFFER_DESTROYED 0x3095
+#define EGL_CLIENT_APIS 0x308D
+#define EGL_COLORSPACE 0x3087
+#define EGL_COLORSPACE_sRGB 0x3089
+#define EGL_COLORSPACE_LINEAR 0x308A
+#define EGL_COLOR_BUFFER_TYPE 0x303F
+#define EGL_CONTEXT_CLIENT_TYPE 0x3097
+#define EGL_DISPLAY_SCALING 10000
+#define EGL_HORIZONTAL_RESOLUTION 0x3090
+#define EGL_LUMINANCE_BUFFER 0x308F
+#define EGL_LUMINANCE_SIZE 0x303D
+#define EGL_OPENGL_ES_BIT 0x0001
+#define EGL_OPENVG_BIT 0x0002
+#define EGL_OPENGL_ES_API 0x30A0
+#define EGL_OPENVG_API 0x30A1
+#define EGL_OPENVG_IMAGE 0x3096
+#define EGL_PIXEL_ASPECT_RATIO 0x3092
+#define EGL_RENDERABLE_TYPE 0x3040
+#define EGL_RENDER_BUFFER 0x3086
+#define EGL_RGB_BUFFER 0x308E
+#define EGL_SINGLE_BUFFER 0x3085
+#define EGL_SWAP_BEHAVIOR 0x3093
+#define EGL_UNKNOWN ((EGLint)-1)
+#define EGL_VERTICAL_RESOLUTION 0x3091
+EGLAPI EGLBoolean EGLAPIENTRY eglBindAPI (EGLenum api);
+EGLAPI EGLenum EGLAPIENTRY eglQueryAPI (void);
+EGLAPI EGLSurface EGLAPIENTRY eglCreatePbufferFromClientBuffer (EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglReleaseThread (void);
+EGLAPI EGLBoolean EGLAPIENTRY eglWaitClient (void);
+#endif /* EGL_VERSION_1_2 */
+
+#ifndef EGL_VERSION_1_3
+#define EGL_VERSION_1_3 1
+#define EGL_CONFORMANT 0x3042
+#define EGL_CONTEXT_CLIENT_VERSION 0x3098
+#define EGL_MATCH_NATIVE_PIXMAP 0x3041
+#define EGL_OPENGL_ES2_BIT 0x0004
+#define EGL_VG_ALPHA_FORMAT 0x3088
+#define EGL_VG_ALPHA_FORMAT_NONPRE 0x308B
+#define EGL_VG_ALPHA_FORMAT_PRE 0x308C
+#define EGL_VG_ALPHA_FORMAT_PRE_BIT 0x0040
+#define EGL_VG_COLORSPACE 0x3087
+#define EGL_VG_COLORSPACE_sRGB 0x3089
+#define EGL_VG_COLORSPACE_LINEAR 0x308A
+#define EGL_VG_COLORSPACE_LINEAR_BIT 0x0020
+#endif /* EGL_VERSION_1_3 */
+
+#ifndef EGL_VERSION_1_4
+#define EGL_VERSION_1_4 1
+#define EGL_DEFAULT_DISPLAY ((EGLNativeDisplayType)0)
+#define EGL_MULTISAMPLE_RESOLVE_BOX_BIT 0x0200
+#define EGL_MULTISAMPLE_RESOLVE 0x3099
+#define EGL_MULTISAMPLE_RESOLVE_DEFAULT 0x309A
+#define EGL_MULTISAMPLE_RESOLVE_BOX 0x309B
+#define EGL_OPENGL_API 0x30A2
+#define EGL_OPENGL_BIT 0x0008
+#define EGL_SWAP_BEHAVIOR_PRESERVED_BIT 0x0400
+EGLAPI EGLContext EGLAPIENTRY eglGetCurrentContext (void);
+#endif /* EGL_VERSION_1_4 */
+
+#ifndef EGL_VERSION_1_5
+#define EGL_VERSION_1_5 1
+typedef void *EGLSync;
+typedef intptr_t EGLAttrib;
+typedef khronos_utime_nanoseconds_t EGLTime;
+#define EGL_CONTEXT_MAJOR_VERSION 0x3098
+#define EGL_CONTEXT_MINOR_VERSION 0x30FB
+#define EGL_CONTEXT_OPENGL_PROFILE_MASK 0x30FD
+#define EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY 0x31BD
+#define EGL_NO_RESET_NOTIFICATION 0x31BE
+#define EGL_LOSE_CONTEXT_ON_RESET 0x31BF
+#define EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT 0x00000001
+#define EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT 0x00000002
+#define EGL_CONTEXT_OPENGL_DEBUG 0x31B0
+#define EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE 0x31B1
+#define EGL_CONTEXT_OPENGL_ROBUST_ACCESS 0x31B2
+#define EGL_OPENGL_ES3_BIT 0x00000040
+#define EGL_CL_EVENT_HANDLE 0x309C
+#define EGL_SYNC_CL_EVENT 0x30FE
+#define EGL_SYNC_CL_EVENT_COMPLETE 0x30FF
+#define EGL_SYNC_PRIOR_COMMANDS_COMPLETE 0x30F0
+#define EGL_SYNC_TYPE 0x30F7
+#define EGL_SYNC_STATUS 0x30F1
+#define EGL_SYNC_CONDITION 0x30F8
+#define EGL_SIGNALED 0x30F2
+#define EGL_UNSIGNALED 0x30F3
+#define EGL_SYNC_FLUSH_COMMANDS_BIT 0x0001
+#define EGL_FOREVER 0xFFFFFFFFFFFFFFFFull
+#define EGL_TIMEOUT_EXPIRED 0x30F5
+#define EGL_CONDITION_SATISFIED 0x30F6
+#define EGL_NO_SYNC ((EGLSync)0)
+#define EGL_SYNC_FENCE 0x30F9
+#define EGL_GL_COLORSPACE 0x309D
+#define EGL_GL_COLORSPACE_SRGB 0x3089
+#define EGL_GL_COLORSPACE_LINEAR 0x308A
+#define EGL_GL_RENDERBUFFER 0x30B9
+#define EGL_GL_TEXTURE_2D 0x30B1
+#define EGL_GL_TEXTURE_LEVEL 0x30BC
+#define EGL_GL_TEXTURE_3D 0x30B2
+#define EGL_GL_TEXTURE_ZOFFSET 0x30BD
+#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x30B3
+#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x30B4
+#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x30B5
+#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x30B6
+#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x30B7
+#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x30B8
+EGLAPI EGLSync EGLAPIENTRY eglCreateSync (EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglDestroySync (EGLDisplay dpy, EGLSync sync);
+EGLAPI EGLint EGLAPIENTRY eglClientWaitSync (EGLDisplay dpy, EGLSync sync, EGLint flags, EGLTime timeout);
+EGLAPI EGLBoolean EGLAPIENTRY eglGetSyncAttrib (EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib *value);
+EGLAPI EGLDisplay EGLAPIENTRY eglGetPlatformDisplay (EGLenum platform, void *native_display, const EGLAttrib *attrib_list);
+EGLAPI EGLSurface EGLAPIENTRY eglCreatePlatformWindowSurface (EGLDisplay dpy, EGLConfig config, void *native_window, const EGLAttrib *attrib_list);
+EGLAPI EGLSurface EGLAPIENTRY eglCreatePlatformPixmapSurface (EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLAttrib *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglWaitSync (EGLDisplay dpy, EGLSync sync, EGLint flags);
+#endif /* EGL_VERSION_1_5 */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/platform/winrt/include/EGL/eglext.h b/platform/winrt/include/EGL/eglext.h
new file mode 100644
index 0000000000..9828628e75
--- /dev/null
+++ b/platform/winrt/include/EGL/eglext.h
@@ -0,0 +1,759 @@
+#ifndef __eglext_h_
+#define __eglext_h_ 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** Copyright (c) 2013-2014 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+/*
+** This header is generated from the Khronos OpenGL / OpenGL ES XML
+** API Registry. The current version of the Registry, generator scripts
+** used to make the header, and the header can be found at
+** http://www.opengl.org/registry/
+**
+** Khronos $Revision: 27018 $ on $Date: 2014-06-10 08:06:12 -0700 (Tue, 10 Jun 2014) $
+*/
+
+#include <EGL/eglplatform.h>
+
+#define EGL_EGLEXT_VERSION 20140610
+
+/* Generated C header for:
+ * API: egl
+ * Versions considered: .*
+ * Versions emitted: _nomatch_^
+ * Default extensions included: egl
+ * Additional extensions included: _nomatch_^
+ * Extensions removed: _nomatch_^
+ */
+
+#ifndef EGL_KHR_cl_event
+#define EGL_KHR_cl_event 1
+#define EGL_CL_EVENT_HANDLE_KHR 0x309C
+#define EGL_SYNC_CL_EVENT_KHR 0x30FE
+#define EGL_SYNC_CL_EVENT_COMPLETE_KHR 0x30FF
+#endif /* EGL_KHR_cl_event */
+
+#ifndef EGL_KHR_cl_event2
+#define EGL_KHR_cl_event2 1
+typedef void *EGLSyncKHR;
+typedef intptr_t EGLAttribKHR;
+typedef EGLSyncKHR (EGLAPIENTRYP PFNEGLCREATESYNC64KHRPROC) (EGLDisplay dpy, EGLenum type, const EGLAttribKHR *attrib_list);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLSyncKHR EGLAPIENTRY eglCreateSync64KHR (EGLDisplay dpy, EGLenum type, const EGLAttribKHR *attrib_list);
+#endif
+#endif /* EGL_KHR_cl_event2 */
+
+#ifndef EGL_KHR_client_get_all_proc_addresses
+#define EGL_KHR_client_get_all_proc_addresses 1
+#endif /* EGL_KHR_client_get_all_proc_addresses */
+
+#ifndef EGL_KHR_config_attribs
+#define EGL_KHR_config_attribs 1
+#define EGL_CONFORMANT_KHR 0x3042
+#define EGL_VG_COLORSPACE_LINEAR_BIT_KHR 0x0020
+#define EGL_VG_ALPHA_FORMAT_PRE_BIT_KHR 0x0040
+#endif /* EGL_KHR_config_attribs */
+
+#ifndef EGL_KHR_create_context
+#define EGL_KHR_create_context 1
+#define EGL_CONTEXT_MAJOR_VERSION_KHR 0x3098
+#define EGL_CONTEXT_MINOR_VERSION_KHR 0x30FB
+#define EGL_CONTEXT_FLAGS_KHR 0x30FC
+#define EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR 0x30FD
+#define EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR 0x31BD
+#define EGL_NO_RESET_NOTIFICATION_KHR 0x31BE
+#define EGL_LOSE_CONTEXT_ON_RESET_KHR 0x31BF
+#define EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR 0x00000001
+#define EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR 0x00000002
+#define EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR 0x00000004
+#define EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR 0x00000001
+#define EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR 0x00000002
+#define EGL_OPENGL_ES3_BIT_KHR 0x00000040
+#endif /* EGL_KHR_create_context */
+
+#ifndef EGL_KHR_fence_sync
+#define EGL_KHR_fence_sync 1
+#ifdef KHRONOS_SUPPORT_INT64
+#define EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR 0x30F0
+#define EGL_SYNC_CONDITION_KHR 0x30F8
+#define EGL_SYNC_FENCE_KHR 0x30F9
+#endif /* KHRONOS_SUPPORT_INT64 */
+#endif /* EGL_KHR_fence_sync */
+
+#ifndef EGL_KHR_get_all_proc_addresses
+#define EGL_KHR_get_all_proc_addresses 1
+#endif /* EGL_KHR_get_all_proc_addresses */
+
+#ifndef EGL_KHR_gl_colorspace
+#define EGL_KHR_gl_colorspace 1
+#define EGL_GL_COLORSPACE_KHR 0x309D
+#define EGL_GL_COLORSPACE_SRGB_KHR 0x3089
+#define EGL_GL_COLORSPACE_LINEAR_KHR 0x308A
+#endif /* EGL_KHR_gl_colorspace */
+
+#ifndef EGL_KHR_gl_renderbuffer_image
+#define EGL_KHR_gl_renderbuffer_image 1
+#define EGL_GL_RENDERBUFFER_KHR 0x30B9
+#endif /* EGL_KHR_gl_renderbuffer_image */
+
+#ifndef EGL_KHR_gl_texture_2D_image
+#define EGL_KHR_gl_texture_2D_image 1
+#define EGL_GL_TEXTURE_2D_KHR 0x30B1
+#define EGL_GL_TEXTURE_LEVEL_KHR 0x30BC
+#endif /* EGL_KHR_gl_texture_2D_image */
+
+#ifndef EGL_KHR_gl_texture_3D_image
+#define EGL_KHR_gl_texture_3D_image 1
+#define EGL_GL_TEXTURE_3D_KHR 0x30B2
+#define EGL_GL_TEXTURE_ZOFFSET_KHR 0x30BD
+#endif /* EGL_KHR_gl_texture_3D_image */
+
+#ifndef EGL_KHR_gl_texture_cubemap_image
+#define EGL_KHR_gl_texture_cubemap_image 1
+#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR 0x30B3
+#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR 0x30B4
+#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR 0x30B5
+#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR 0x30B6
+#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR 0x30B7
+#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR 0x30B8
+#endif /* EGL_KHR_gl_texture_cubemap_image */
+
+#ifndef EGL_KHR_image
+#define EGL_KHR_image 1
+typedef void *EGLImageKHR;
+#define EGL_NATIVE_PIXMAP_KHR 0x30B0
+#define EGL_NO_IMAGE_KHR ((EGLImageKHR)0)
+typedef EGLImageKHR (EGLAPIENTRYP PFNEGLCREATEIMAGEKHRPROC) (EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYIMAGEKHRPROC) (EGLDisplay dpy, EGLImageKHR image);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLImageKHR EGLAPIENTRY eglCreateImageKHR (EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglDestroyImageKHR (EGLDisplay dpy, EGLImageKHR image);
+#endif
+#endif /* EGL_KHR_image */
+
+#ifndef EGL_KHR_image_base
+#define EGL_KHR_image_base 1
+#define EGL_IMAGE_PRESERVED_KHR 0x30D2
+#endif /* EGL_KHR_image_base */
+
+#ifndef EGL_KHR_image_pixmap
+#define EGL_KHR_image_pixmap 1
+#endif /* EGL_KHR_image_pixmap */
+
+#ifndef EGL_KHR_lock_surface
+#define EGL_KHR_lock_surface 1
+#define EGL_READ_SURFACE_BIT_KHR 0x0001
+#define EGL_WRITE_SURFACE_BIT_KHR 0x0002
+#define EGL_LOCK_SURFACE_BIT_KHR 0x0080
+#define EGL_OPTIMAL_FORMAT_BIT_KHR 0x0100
+#define EGL_MATCH_FORMAT_KHR 0x3043
+#define EGL_FORMAT_RGB_565_EXACT_KHR 0x30C0
+#define EGL_FORMAT_RGB_565_KHR 0x30C1
+#define EGL_FORMAT_RGBA_8888_EXACT_KHR 0x30C2
+#define EGL_FORMAT_RGBA_8888_KHR 0x30C3
+#define EGL_MAP_PRESERVE_PIXELS_KHR 0x30C4
+#define EGL_LOCK_USAGE_HINT_KHR 0x30C5
+#define EGL_BITMAP_POINTER_KHR 0x30C6
+#define EGL_BITMAP_PITCH_KHR 0x30C7
+#define EGL_BITMAP_ORIGIN_KHR 0x30C8
+#define EGL_BITMAP_PIXEL_RED_OFFSET_KHR 0x30C9
+#define EGL_BITMAP_PIXEL_GREEN_OFFSET_KHR 0x30CA
+#define EGL_BITMAP_PIXEL_BLUE_OFFSET_KHR 0x30CB
+#define EGL_BITMAP_PIXEL_ALPHA_OFFSET_KHR 0x30CC
+#define EGL_BITMAP_PIXEL_LUMINANCE_OFFSET_KHR 0x30CD
+#define EGL_LOWER_LEFT_KHR 0x30CE
+#define EGL_UPPER_LEFT_KHR 0x30CF
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLLOCKSURFACEKHRPROC) (EGLDisplay dpy, EGLSurface surface, const EGLint *attrib_list);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLUNLOCKSURFACEKHRPROC) (EGLDisplay dpy, EGLSurface surface);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglLockSurfaceKHR (EGLDisplay dpy, EGLSurface surface, const EGLint *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglUnlockSurfaceKHR (EGLDisplay dpy, EGLSurface surface);
+#endif
+#endif /* EGL_KHR_lock_surface */
+
+#ifndef EGL_KHR_lock_surface2
+#define EGL_KHR_lock_surface2 1
+#define EGL_BITMAP_PIXEL_SIZE_KHR 0x3110
+#endif /* EGL_KHR_lock_surface2 */
+
+#ifndef EGL_KHR_lock_surface3
+#define EGL_KHR_lock_surface3 1
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSURFACE64KHRPROC) (EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLAttribKHR *value);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurface64KHR (EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLAttribKHR *value);
+#endif
+#endif /* EGL_KHR_lock_surface3 */
+
+#ifndef EGL_KHR_platform_android
+#define EGL_KHR_platform_android 1
+#define EGL_PLATFORM_ANDROID_KHR 0x3141
+#endif /* EGL_KHR_platform_android */
+
+#ifndef EGL_KHR_platform_gbm
+#define EGL_KHR_platform_gbm 1
+#define EGL_PLATFORM_GBM_KHR 0x31D7
+#endif /* EGL_KHR_platform_gbm */
+
+#ifndef EGL_KHR_platform_wayland
+#define EGL_KHR_platform_wayland 1
+#define EGL_PLATFORM_WAYLAND_KHR 0x31D8
+#endif /* EGL_KHR_platform_wayland */
+
+#ifndef EGL_KHR_platform_x11
+#define EGL_KHR_platform_x11 1
+#define EGL_PLATFORM_X11_KHR 0x31D5
+#define EGL_PLATFORM_X11_SCREEN_KHR 0x31D6
+#endif /* EGL_KHR_platform_x11 */
+
+#ifndef EGL_KHR_reusable_sync
+#define EGL_KHR_reusable_sync 1
+typedef khronos_utime_nanoseconds_t EGLTimeKHR;
+#ifdef KHRONOS_SUPPORT_INT64
+#define EGL_SYNC_STATUS_KHR 0x30F1
+#define EGL_SIGNALED_KHR 0x30F2
+#define EGL_UNSIGNALED_KHR 0x30F3
+#define EGL_TIMEOUT_EXPIRED_KHR 0x30F5
+#define EGL_CONDITION_SATISFIED_KHR 0x30F6
+#define EGL_SYNC_TYPE_KHR 0x30F7
+#define EGL_SYNC_REUSABLE_KHR 0x30FA
+#define EGL_SYNC_FLUSH_COMMANDS_BIT_KHR 0x0001
+#define EGL_FOREVER_KHR 0xFFFFFFFFFFFFFFFFull
+#define EGL_NO_SYNC_KHR ((EGLSyncKHR)0)
+typedef EGLSyncKHR (EGLAPIENTRYP PFNEGLCREATESYNCKHRPROC) (EGLDisplay dpy, EGLenum type, const EGLint *attrib_list);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync);
+typedef EGLint (EGLAPIENTRYP PFNEGLCLIENTWAITSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSIGNALSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETSYNCATTRIBKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLSyncKHR EGLAPIENTRY eglCreateSyncKHR (EGLDisplay dpy, EGLenum type, const EGLint *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglDestroySyncKHR (EGLDisplay dpy, EGLSyncKHR sync);
+EGLAPI EGLint EGLAPIENTRY eglClientWaitSyncKHR (EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout);
+EGLAPI EGLBoolean EGLAPIENTRY eglSignalSyncKHR (EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode);
+EGLAPI EGLBoolean EGLAPIENTRY eglGetSyncAttribKHR (EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value);
+#endif
+#endif /* KHRONOS_SUPPORT_INT64 */
+#endif /* EGL_KHR_reusable_sync */
+
+#ifndef EGL_KHR_stream
+#define EGL_KHR_stream 1
+typedef void *EGLStreamKHR;
+typedef khronos_uint64_t EGLuint64KHR;
+#ifdef KHRONOS_SUPPORT_INT64
+#define EGL_NO_STREAM_KHR ((EGLStreamKHR)0)
+#define EGL_CONSUMER_LATENCY_USEC_KHR 0x3210
+#define EGL_PRODUCER_FRAME_KHR 0x3212
+#define EGL_CONSUMER_FRAME_KHR 0x3213
+#define EGL_STREAM_STATE_KHR 0x3214
+#define EGL_STREAM_STATE_CREATED_KHR 0x3215
+#define EGL_STREAM_STATE_CONNECTING_KHR 0x3216
+#define EGL_STREAM_STATE_EMPTY_KHR 0x3217
+#define EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR 0x3218
+#define EGL_STREAM_STATE_OLD_FRAME_AVAILABLE_KHR 0x3219
+#define EGL_STREAM_STATE_DISCONNECTED_KHR 0x321A
+#define EGL_BAD_STREAM_KHR 0x321B
+#define EGL_BAD_STATE_KHR 0x321C
+typedef EGLStreamKHR (EGLAPIENTRYP PFNEGLCREATESTREAMKHRPROC) (EGLDisplay dpy, const EGLint *attrib_list);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYSTREAMKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMATTRIBKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLint value);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSTREAMKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLint *value);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSTREAMU64KHRPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLuint64KHR *value);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLStreamKHR EGLAPIENTRY eglCreateStreamKHR (EGLDisplay dpy, const EGLint *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglDestroyStreamKHR (EGLDisplay dpy, EGLStreamKHR stream);
+EGLAPI EGLBoolean EGLAPIENTRY eglStreamAttribKHR (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLint value);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryStreamKHR (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLint *value);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryStreamu64KHR (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLuint64KHR *value);
+#endif
+#endif /* KHRONOS_SUPPORT_INT64 */
+#endif /* EGL_KHR_stream */
+
+#ifndef EGL_KHR_stream_consumer_gltexture
+#define EGL_KHR_stream_consumer_gltexture 1
+#ifdef EGL_KHR_stream
+#define EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR 0x321E
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERGLTEXTUREEXTERNALKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERACQUIREKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERRELEASEKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerGLTextureExternalKHR (EGLDisplay dpy, EGLStreamKHR stream);
+EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerAcquireKHR (EGLDisplay dpy, EGLStreamKHR stream);
+EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerReleaseKHR (EGLDisplay dpy, EGLStreamKHR stream);
+#endif
+#endif /* EGL_KHR_stream */
+#endif /* EGL_KHR_stream_consumer_gltexture */
+
+#ifndef EGL_KHR_stream_cross_process_fd
+#define EGL_KHR_stream_cross_process_fd 1
+typedef int EGLNativeFileDescriptorKHR;
+#ifdef EGL_KHR_stream
+#define EGL_NO_FILE_DESCRIPTOR_KHR ((EGLNativeFileDescriptorKHR)(-1))
+typedef EGLNativeFileDescriptorKHR (EGLAPIENTRYP PFNEGLGETSTREAMFILEDESCRIPTORKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream);
+typedef EGLStreamKHR (EGLAPIENTRYP PFNEGLCREATESTREAMFROMFILEDESCRIPTORKHRPROC) (EGLDisplay dpy, EGLNativeFileDescriptorKHR file_descriptor);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLNativeFileDescriptorKHR EGLAPIENTRY eglGetStreamFileDescriptorKHR (EGLDisplay dpy, EGLStreamKHR stream);
+EGLAPI EGLStreamKHR EGLAPIENTRY eglCreateStreamFromFileDescriptorKHR (EGLDisplay dpy, EGLNativeFileDescriptorKHR file_descriptor);
+#endif
+#endif /* EGL_KHR_stream */
+#endif /* EGL_KHR_stream_cross_process_fd */
+
+#ifndef EGL_KHR_stream_fifo
+#define EGL_KHR_stream_fifo 1
+#ifdef EGL_KHR_stream
+#define EGL_STREAM_FIFO_LENGTH_KHR 0x31FC
+#define EGL_STREAM_TIME_NOW_KHR 0x31FD
+#define EGL_STREAM_TIME_CONSUMER_KHR 0x31FE
+#define EGL_STREAM_TIME_PRODUCER_KHR 0x31FF
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSTREAMTIMEKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLTimeKHR *value);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryStreamTimeKHR (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLTimeKHR *value);
+#endif
+#endif /* EGL_KHR_stream */
+#endif /* EGL_KHR_stream_fifo */
+
+#ifndef EGL_KHR_stream_producer_aldatalocator
+#define EGL_KHR_stream_producer_aldatalocator 1
+#ifdef EGL_KHR_stream
+#endif /* EGL_KHR_stream */
+#endif /* EGL_KHR_stream_producer_aldatalocator */
+
+#ifndef EGL_KHR_stream_producer_eglsurface
+#define EGL_KHR_stream_producer_eglsurface 1
+#ifdef EGL_KHR_stream
+#define EGL_STREAM_BIT_KHR 0x0800
+typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATESTREAMPRODUCERSURFACEKHRPROC) (EGLDisplay dpy, EGLConfig config, EGLStreamKHR stream, const EGLint *attrib_list);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLSurface EGLAPIENTRY eglCreateStreamProducerSurfaceKHR (EGLDisplay dpy, EGLConfig config, EGLStreamKHR stream, const EGLint *attrib_list);
+#endif
+#endif /* EGL_KHR_stream */
+#endif /* EGL_KHR_stream_producer_eglsurface */
+
+#ifndef EGL_KHR_surfaceless_context
+#define EGL_KHR_surfaceless_context 1
+#endif /* EGL_KHR_surfaceless_context */
+
+#ifndef EGL_KHR_vg_parent_image
+#define EGL_KHR_vg_parent_image 1
+#define EGL_VG_PARENT_IMAGE_KHR 0x30BA
+#endif /* EGL_KHR_vg_parent_image */
+
+#ifndef EGL_KHR_wait_sync
+#define EGL_KHR_wait_sync 1
+typedef EGLint (EGLAPIENTRYP PFNEGLWAITSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLint flags);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLint EGLAPIENTRY eglWaitSyncKHR (EGLDisplay dpy, EGLSyncKHR sync, EGLint flags);
+#endif
+#endif /* EGL_KHR_wait_sync */
+
+#ifndef EGL_ANDROID_blob_cache
+#define EGL_ANDROID_blob_cache 1
+typedef khronos_ssize_t EGLsizeiANDROID;
+typedef void (*EGLSetBlobFuncANDROID) (const void *key, EGLsizeiANDROID keySize, const void *value, EGLsizeiANDROID valueSize);
+typedef EGLsizeiANDROID (*EGLGetBlobFuncANDROID) (const void *key, EGLsizeiANDROID keySize, void *value, EGLsizeiANDROID valueSize);
+typedef void (EGLAPIENTRYP PFNEGLSETBLOBCACHEFUNCSANDROIDPROC) (EGLDisplay dpy, EGLSetBlobFuncANDROID set, EGLGetBlobFuncANDROID get);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI void EGLAPIENTRY eglSetBlobCacheFuncsANDROID (EGLDisplay dpy, EGLSetBlobFuncANDROID set, EGLGetBlobFuncANDROID get);
+#endif
+#endif /* EGL_ANDROID_blob_cache */
+
+#ifndef EGL_ANDROID_framebuffer_target
+#define EGL_ANDROID_framebuffer_target 1
+#define EGL_FRAMEBUFFER_TARGET_ANDROID 0x3147
+#endif /* EGL_ANDROID_framebuffer_target */
+
+#ifndef EGL_ANDROID_image_native_buffer
+#define EGL_ANDROID_image_native_buffer 1
+#define EGL_NATIVE_BUFFER_ANDROID 0x3140
+#endif /* EGL_ANDROID_image_native_buffer */
+
+#ifndef EGL_ANDROID_native_fence_sync
+#define EGL_ANDROID_native_fence_sync 1
+#define EGL_SYNC_NATIVE_FENCE_ANDROID 0x3144
+#define EGL_SYNC_NATIVE_FENCE_FD_ANDROID 0x3145
+#define EGL_SYNC_NATIVE_FENCE_SIGNALED_ANDROID 0x3146
+#define EGL_NO_NATIVE_FENCE_FD_ANDROID -1
+typedef EGLint (EGLAPIENTRYP PFNEGLDUPNATIVEFENCEFDANDROIDPROC) (EGLDisplay dpy, EGLSyncKHR sync);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLint EGLAPIENTRY eglDupNativeFenceFDANDROID (EGLDisplay dpy, EGLSyncKHR sync);
+#endif
+#endif /* EGL_ANDROID_native_fence_sync */
+
+#ifndef EGL_ANDROID_recordable
+#define EGL_ANDROID_recordable 1
+#define EGL_RECORDABLE_ANDROID 0x3142
+#endif /* EGL_ANDROID_recordable */
+
+#ifndef EGL_ANGLE_d3d_share_handle_client_buffer
+#define EGL_ANGLE_d3d_share_handle_client_buffer 1
+#define EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE 0x3200
+#endif /* EGL_ANGLE_d3d_share_handle_client_buffer */
+
+#ifndef EGL_ANGLE_window_fixed_size
+#define EGL_ANGLE_window_fixed_size 1
+#define EGL_FIXED_SIZE_ANGLE 0x3201
+#endif /* EGL_ANGLE_window_fixed_size */
+
+#ifndef EGL_ANGLE_query_surface_pointer
+#define EGL_ANGLE_query_surface_pointer 1
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSURFACEPOINTERANGLEPROC) (EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurfacePointerANGLE (EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value);
+#endif
+#endif /* EGL_ANGLE_query_surface_pointer */
+
+#ifndef EGL_ANGLE_software_display
+#define EGL_ANGLE_software_display 1
+#define EGL_SOFTWARE_DISPLAY_ANGLE ((EGLNativeDisplayType)-1)
+#endif /* EGL_ANGLE_software_display */
+
+#ifndef EGL_ANGLE_direct3d_display
+#define EGL_ANGLE_direct3d_display 1
+#define EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE ((EGLNativeDisplayType)-2)
+#define EGL_D3D11_ONLY_DISPLAY_ANGLE ((EGLNativeDisplayType)-3)
+#define EGL_D3D11_FL9_3_ONLY_DISPLAY_ANGLE ((EGLNativeDisplayType)-4)
+#endif /* EGL_ANGLE_direct3d_display */
+
+#ifndef EGL_ANGLE_surface_d3d_texture_2d_share_handle
+#define EGL_ANGLE_surface_d3d_texture_2d_share_handle 1
+#endif /* EGL_ANGLE_surface_d3d_texture_2d_share_handle */
+
+#ifndef EGL_ANGLE_platform_angle
+#define EGL_ANGLE_platform_angle 1
+#define EGL_PLATFORM_ANGLE_ANGLE 0x3201
+#define EGL_PLATFORM_ANGLE_TYPE_ANGLE 0x3202
+#define EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE 0x3203
+#endif /* EGL_ANGLE_platform_angle */
+
+#ifndef EGL_ANGLE_platform_angle_d3d
+#define EGL_ANGLE_platform_angle_d3d 1
+#define EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE 0x3204
+#define EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE 0x3205
+#define EGL_PLATFORM_ANGLE_TYPE_D3D11_WARP_ANGLE 0x3206
+#endif /* EGL_ANGLE_platform_angle_d3d */
+
+#ifndef EGL_ANGLE_platform_angle_opengl
+#define EGL_ANGLE_platform_angle_opengl 1
+#define EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE 0x3207
+#define EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE 0x3208
+#endif /* EGL_ANGLE_platform_angle_opengl */
+
+#ifndef EGL_ARM_pixmap_multisample_discard
+#define EGL_ARM_pixmap_multisample_discard 1
+#define EGL_DISCARD_SAMPLES_ARM 0x3286
+#endif /* EGL_ARM_pixmap_multisample_discard */
+
+#ifndef EGL_EXT_buffer_age
+#define EGL_EXT_buffer_age 1
+#define EGL_BUFFER_AGE_EXT 0x313D
+#endif /* EGL_EXT_buffer_age */
+
+#ifndef EGL_EXT_client_extensions
+#define EGL_EXT_client_extensions 1
+#endif /* EGL_EXT_client_extensions */
+
+#ifndef EGL_EXT_create_context_robustness
+#define EGL_EXT_create_context_robustness 1
+#define EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT 0x30BF
+#define EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT 0x3138
+#define EGL_NO_RESET_NOTIFICATION_EXT 0x31BE
+#define EGL_LOSE_CONTEXT_ON_RESET_EXT 0x31BF
+#endif /* EGL_EXT_create_context_robustness */
+
+#ifndef EGL_EXT_device_base
+#define EGL_EXT_device_base 1
+typedef void *EGLDeviceEXT;
+#define EGL_NO_DEVICE_EXT ((EGLDeviceEXT)(0))
+#define EGL_BAD_DEVICE_EXT 0x322B
+#define EGL_DEVICE_EXT 0x322C
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYDEVICEATTRIBEXTPROC) (EGLDeviceEXT device, EGLint attribute, EGLAttrib *value);
+typedef const char *(EGLAPIENTRYP PFNEGLQUERYDEVICESTRINGEXTPROC) (EGLDeviceEXT device, EGLint name);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYDEVICESEXTPROC) (EGLint max_devices, EGLDeviceEXT *devices, EGLint *num_devices);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYDISPLAYATTRIBEXTPROC) (EGLDisplay dpy, EGLint attribute, EGLAttrib *value);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryDeviceAttribEXT (EGLDeviceEXT device, EGLint attribute, EGLAttrib *value);
+EGLAPI const char *EGLAPIENTRY eglQueryDeviceStringEXT (EGLDeviceEXT device, EGLint name);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryDevicesEXT (EGLint max_devices, EGLDeviceEXT *devices, EGLint *num_devices);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryDisplayAttribEXT (EGLDisplay dpy, EGLint attribute, EGLAttrib *value);
+#endif
+#endif /* EGL_EXT_device_base */
+
+#ifndef EGL_EXT_image_dma_buf_import
+#define EGL_EXT_image_dma_buf_import 1
+#define EGL_LINUX_DMA_BUF_EXT 0x3270
+#define EGL_LINUX_DRM_FOURCC_EXT 0x3271
+#define EGL_DMA_BUF_PLANE0_FD_EXT 0x3272
+#define EGL_DMA_BUF_PLANE0_OFFSET_EXT 0x3273
+#define EGL_DMA_BUF_PLANE0_PITCH_EXT 0x3274
+#define EGL_DMA_BUF_PLANE1_FD_EXT 0x3275
+#define EGL_DMA_BUF_PLANE1_OFFSET_EXT 0x3276
+#define EGL_DMA_BUF_PLANE1_PITCH_EXT 0x3277
+#define EGL_DMA_BUF_PLANE2_FD_EXT 0x3278
+#define EGL_DMA_BUF_PLANE2_OFFSET_EXT 0x3279
+#define EGL_DMA_BUF_PLANE2_PITCH_EXT 0x327A
+#define EGL_YUV_COLOR_SPACE_HINT_EXT 0x327B
+#define EGL_SAMPLE_RANGE_HINT_EXT 0x327C
+#define EGL_YUV_CHROMA_HORIZONTAL_SITING_HINT_EXT 0x327D
+#define EGL_YUV_CHROMA_VERTICAL_SITING_HINT_EXT 0x327E
+#define EGL_ITU_REC601_EXT 0x327F
+#define EGL_ITU_REC709_EXT 0x3280
+#define EGL_ITU_REC2020_EXT 0x3281
+#define EGL_YUV_FULL_RANGE_EXT 0x3282
+#define EGL_YUV_NARROW_RANGE_EXT 0x3283
+#define EGL_YUV_CHROMA_SITING_0_EXT 0x3284
+#define EGL_YUV_CHROMA_SITING_0_5_EXT 0x3285
+#endif /* EGL_EXT_image_dma_buf_import */
+
+#ifndef EGL_EXT_multiview_window
+#define EGL_EXT_multiview_window 1
+#define EGL_MULTIVIEW_VIEW_COUNT_EXT 0x3134
+#endif /* EGL_EXT_multiview_window */
+
+#ifndef EGL_EXT_platform_base
+#define EGL_EXT_platform_base 1
+typedef EGLDisplay (EGLAPIENTRYP PFNEGLGETPLATFORMDISPLAYEXTPROC) (EGLenum platform, void *native_display, const EGLint *attrib_list);
+typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC) (EGLDisplay dpy, EGLConfig config, void *native_window, const EGLint *attrib_list);
+typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATEPLATFORMPIXMAPSURFACEEXTPROC) (EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLint *attrib_list);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLDisplay EGLAPIENTRY eglGetPlatformDisplayEXT (EGLenum platform, void *native_display, const EGLint *attrib_list);
+EGLAPI EGLSurface EGLAPIENTRY eglCreatePlatformWindowSurfaceEXT (EGLDisplay dpy, EGLConfig config, void *native_window, const EGLint *attrib_list);
+EGLAPI EGLSurface EGLAPIENTRY eglCreatePlatformPixmapSurfaceEXT (EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLint *attrib_list);
+#endif
+#endif /* EGL_EXT_platform_base */
+
+#ifndef EGL_EXT_platform_device
+#define EGL_EXT_platform_device 1
+#define EGL_PLATFORM_DEVICE_EXT 0x313F
+#endif /* EGL_EXT_platform_device */
+
+#ifndef EGL_EXT_platform_wayland
+#define EGL_EXT_platform_wayland 1
+#define EGL_PLATFORM_WAYLAND_EXT 0x31D8
+#endif /* EGL_EXT_platform_wayland */
+
+#ifndef EGL_EXT_platform_x11
+#define EGL_EXT_platform_x11 1
+#define EGL_PLATFORM_X11_EXT 0x31D5
+#define EGL_PLATFORM_X11_SCREEN_EXT 0x31D6
+#endif /* EGL_EXT_platform_x11 */
+
+#ifndef EGL_EXT_protected_surface
+#define EGL_EXT_protected_surface 1
+#define EGL_PROTECTED_CONTENT_EXT 0x32C0
+#endif /* EGL_EXT_protected_surface */
+
+#ifndef EGL_EXT_swap_buffers_with_damage
+#define EGL_EXT_swap_buffers_with_damage 1
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSWAPBUFFERSWITHDAMAGEEXTPROC) (EGLDisplay dpy, EGLSurface surface, EGLint *rects, EGLint n_rects);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffersWithDamageEXT (EGLDisplay dpy, EGLSurface surface, EGLint *rects, EGLint n_rects);
+#endif
+#endif /* EGL_EXT_swap_buffers_with_damage */
+
+#ifndef EGL_HI_clientpixmap
+#define EGL_HI_clientpixmap 1
+struct EGLClientPixmapHI {
+ void *pData;
+ EGLint iWidth;
+ EGLint iHeight;
+ EGLint iStride;
+};
+#define EGL_CLIENT_PIXMAP_POINTER_HI 0x8F74
+typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATEPIXMAPSURFACEHIPROC) (EGLDisplay dpy, EGLConfig config, struct EGLClientPixmapHI *pixmap);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLSurface EGLAPIENTRY eglCreatePixmapSurfaceHI (EGLDisplay dpy, EGLConfig config, struct EGLClientPixmapHI *pixmap);
+#endif
+#endif /* EGL_HI_clientpixmap */
+
+#ifndef EGL_HI_colorformats
+#define EGL_HI_colorformats 1
+#define EGL_COLOR_FORMAT_HI 0x8F70
+#define EGL_COLOR_RGB_HI 0x8F71
+#define EGL_COLOR_RGBA_HI 0x8F72
+#define EGL_COLOR_ARGB_HI 0x8F73
+#endif /* EGL_HI_colorformats */
+
+#ifndef EGL_IMG_context_priority
+#define EGL_IMG_context_priority 1
+#define EGL_CONTEXT_PRIORITY_LEVEL_IMG 0x3100
+#define EGL_CONTEXT_PRIORITY_HIGH_IMG 0x3101
+#define EGL_CONTEXT_PRIORITY_MEDIUM_IMG 0x3102
+#define EGL_CONTEXT_PRIORITY_LOW_IMG 0x3103
+#endif /* EGL_IMG_context_priority */
+
+#ifndef EGL_MESA_drm_image
+#define EGL_MESA_drm_image 1
+#define EGL_DRM_BUFFER_FORMAT_MESA 0x31D0
+#define EGL_DRM_BUFFER_USE_MESA 0x31D1
+#define EGL_DRM_BUFFER_FORMAT_ARGB32_MESA 0x31D2
+#define EGL_DRM_BUFFER_MESA 0x31D3
+#define EGL_DRM_BUFFER_STRIDE_MESA 0x31D4
+#define EGL_DRM_BUFFER_USE_SCANOUT_MESA 0x00000001
+#define EGL_DRM_BUFFER_USE_SHARE_MESA 0x00000002
+typedef EGLImageKHR (EGLAPIENTRYP PFNEGLCREATEDRMIMAGEMESAPROC) (EGLDisplay dpy, const EGLint *attrib_list);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLEXPORTDRMIMAGEMESAPROC) (EGLDisplay dpy, EGLImageKHR image, EGLint *name, EGLint *handle, EGLint *stride);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLImageKHR EGLAPIENTRY eglCreateDRMImageMESA (EGLDisplay dpy, const EGLint *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglExportDRMImageMESA (EGLDisplay dpy, EGLImageKHR image, EGLint *name, EGLint *handle, EGLint *stride);
+#endif
+#endif /* EGL_MESA_drm_image */
+
+#ifndef EGL_MESA_platform_gbm
+#define EGL_MESA_platform_gbm 1
+#define EGL_PLATFORM_GBM_MESA 0x31D7
+#endif /* EGL_MESA_platform_gbm */
+
+#ifndef EGL_NOK_swap_region
+#define EGL_NOK_swap_region 1
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSWAPBUFFERSREGIONNOKPROC) (EGLDisplay dpy, EGLSurface surface, EGLint numRects, const EGLint *rects);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffersRegionNOK (EGLDisplay dpy, EGLSurface surface, EGLint numRects, const EGLint *rects);
+#endif
+#endif /* EGL_NOK_swap_region */
+
+#ifndef EGL_NOK_swap_region2
+#define EGL_NOK_swap_region2 1
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSWAPBUFFERSREGION2NOKPROC) (EGLDisplay dpy, EGLSurface surface, EGLint numRects, const EGLint *rects);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffersRegion2NOK (EGLDisplay dpy, EGLSurface surface, EGLint numRects, const EGLint *rects);
+#endif
+#endif /* EGL_NOK_swap_region2 */
+
+#ifndef EGL_NOK_texture_from_pixmap
+#define EGL_NOK_texture_from_pixmap 1
+#define EGL_Y_INVERTED_NOK 0x307F
+#endif /* EGL_NOK_texture_from_pixmap */
+
+#ifndef EGL_NV_3dvision_surface
+#define EGL_NV_3dvision_surface 1
+#define EGL_AUTO_STEREO_NV 0x3136
+#endif /* EGL_NV_3dvision_surface */
+
+#ifndef EGL_NV_coverage_sample
+#define EGL_NV_coverage_sample 1
+#define EGL_COVERAGE_BUFFERS_NV 0x30E0
+#define EGL_COVERAGE_SAMPLES_NV 0x30E1
+#endif /* EGL_NV_coverage_sample */
+
+#ifndef EGL_NV_coverage_sample_resolve
+#define EGL_NV_coverage_sample_resolve 1
+#define EGL_COVERAGE_SAMPLE_RESOLVE_NV 0x3131
+#define EGL_COVERAGE_SAMPLE_RESOLVE_DEFAULT_NV 0x3132
+#define EGL_COVERAGE_SAMPLE_RESOLVE_NONE_NV 0x3133
+#endif /* EGL_NV_coverage_sample_resolve */
+
+#ifndef EGL_NV_depth_nonlinear
+#define EGL_NV_depth_nonlinear 1
+#define EGL_DEPTH_ENCODING_NV 0x30E2
+#define EGL_DEPTH_ENCODING_NONE_NV 0
+#define EGL_DEPTH_ENCODING_NONLINEAR_NV 0x30E3
+#endif /* EGL_NV_depth_nonlinear */
+
+#ifndef EGL_NV_native_query
+#define EGL_NV_native_query 1
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYNATIVEDISPLAYNVPROC) (EGLDisplay dpy, EGLNativeDisplayType *display_id);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYNATIVEWINDOWNVPROC) (EGLDisplay dpy, EGLSurface surf, EGLNativeWindowType *window);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYNATIVEPIXMAPNVPROC) (EGLDisplay dpy, EGLSurface surf, EGLNativePixmapType *pixmap);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryNativeDisplayNV (EGLDisplay dpy, EGLNativeDisplayType *display_id);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryNativeWindowNV (EGLDisplay dpy, EGLSurface surf, EGLNativeWindowType *window);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryNativePixmapNV (EGLDisplay dpy, EGLSurface surf, EGLNativePixmapType *pixmap);
+#endif
+#endif /* EGL_NV_native_query */
+
+#ifndef EGL_NV_post_convert_rounding
+#define EGL_NV_post_convert_rounding 1
+#endif /* EGL_NV_post_convert_rounding */
+
+#ifndef EGL_NV_post_sub_buffer
+#define EGL_NV_post_sub_buffer 1
+#define EGL_POST_SUB_BUFFER_SUPPORTED_NV 0x30BE
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLPOSTSUBBUFFERNVPROC) (EGLDisplay dpy, EGLSurface surface, EGLint x, EGLint y, EGLint width, EGLint height);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglPostSubBufferNV (EGLDisplay dpy, EGLSurface surface, EGLint x, EGLint y, EGLint width, EGLint height);
+#endif
+#endif /* EGL_NV_post_sub_buffer */
+
+#ifndef EGL_NV_stream_sync
+#define EGL_NV_stream_sync 1
+#define EGL_SYNC_NEW_FRAME_NV 0x321F
+typedef EGLSyncKHR (EGLAPIENTRYP PFNEGLCREATESTREAMSYNCNVPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum type, const EGLint *attrib_list);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLSyncKHR EGLAPIENTRY eglCreateStreamSyncNV (EGLDisplay dpy, EGLStreamKHR stream, EGLenum type, const EGLint *attrib_list);
+#endif
+#endif /* EGL_NV_stream_sync */
+
+#ifndef EGL_NV_sync
+#define EGL_NV_sync 1
+typedef void *EGLSyncNV;
+typedef khronos_utime_nanoseconds_t EGLTimeNV;
+#ifdef KHRONOS_SUPPORT_INT64
+#define EGL_SYNC_PRIOR_COMMANDS_COMPLETE_NV 0x30E6
+#define EGL_SYNC_STATUS_NV 0x30E7
+#define EGL_SIGNALED_NV 0x30E8
+#define EGL_UNSIGNALED_NV 0x30E9
+#define EGL_SYNC_FLUSH_COMMANDS_BIT_NV 0x0001
+#define EGL_FOREVER_NV 0xFFFFFFFFFFFFFFFFull
+#define EGL_ALREADY_SIGNALED_NV 0x30EA
+#define EGL_TIMEOUT_EXPIRED_NV 0x30EB
+#define EGL_CONDITION_SATISFIED_NV 0x30EC
+#define EGL_SYNC_TYPE_NV 0x30ED
+#define EGL_SYNC_CONDITION_NV 0x30EE
+#define EGL_SYNC_FENCE_NV 0x30EF
+#define EGL_NO_SYNC_NV ((EGLSyncNV)0)
+typedef EGLSyncNV (EGLAPIENTRYP PFNEGLCREATEFENCESYNCNVPROC) (EGLDisplay dpy, EGLenum condition, const EGLint *attrib_list);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYSYNCNVPROC) (EGLSyncNV sync);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLFENCENVPROC) (EGLSyncNV sync);
+typedef EGLint (EGLAPIENTRYP PFNEGLCLIENTWAITSYNCNVPROC) (EGLSyncNV sync, EGLint flags, EGLTimeNV timeout);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSIGNALSYNCNVPROC) (EGLSyncNV sync, EGLenum mode);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETSYNCATTRIBNVPROC) (EGLSyncNV sync, EGLint attribute, EGLint *value);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLSyncNV EGLAPIENTRY eglCreateFenceSyncNV (EGLDisplay dpy, EGLenum condition, const EGLint *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglDestroySyncNV (EGLSyncNV sync);
+EGLAPI EGLBoolean EGLAPIENTRY eglFenceNV (EGLSyncNV sync);
+EGLAPI EGLint EGLAPIENTRY eglClientWaitSyncNV (EGLSyncNV sync, EGLint flags, EGLTimeNV timeout);
+EGLAPI EGLBoolean EGLAPIENTRY eglSignalSyncNV (EGLSyncNV sync, EGLenum mode);
+EGLAPI EGLBoolean EGLAPIENTRY eglGetSyncAttribNV (EGLSyncNV sync, EGLint attribute, EGLint *value);
+#endif
+#endif /* KHRONOS_SUPPORT_INT64 */
+#endif /* EGL_NV_sync */
+
+#ifndef EGL_NV_system_time
+#define EGL_NV_system_time 1
+typedef khronos_utime_nanoseconds_t EGLuint64NV;
+#ifdef KHRONOS_SUPPORT_INT64
+typedef EGLuint64NV (EGLAPIENTRYP PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC) (void);
+typedef EGLuint64NV (EGLAPIENTRYP PFNEGLGETSYSTEMTIMENVPROC) (void);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLuint64NV EGLAPIENTRY eglGetSystemTimeFrequencyNV (void);
+EGLAPI EGLuint64NV EGLAPIENTRY eglGetSystemTimeNV (void);
+#endif
+#endif /* KHRONOS_SUPPORT_INT64 */
+#endif /* EGL_NV_system_time */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/platform/winrt/include/EGL/eglplatform.h b/platform/winrt/include/EGL/eglplatform.h
new file mode 100644
index 0000000000..d2e30bddbe
--- /dev/null
+++ b/platform/winrt/include/EGL/eglplatform.h
@@ -0,0 +1,131 @@
+#ifndef __eglplatform_h_
+#define __eglplatform_h_
+
+/*
+** Copyright (c) 2007-2013 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+/* Platform-specific types and definitions for egl.h
+ * $Revision: 23432 $ on $Date: 2013-10-09 00:57:24 -0700 (Wed, 09 Oct 2013) $
+ *
+ * Adopters may modify khrplatform.h and this file to suit their platform.
+ * You are encouraged to submit all modifications to the Khronos group so that
+ * they can be included in future versions of this file. Please submit changes
+ * by sending them to the public Khronos Bugzilla (http://khronos.org/bugzilla)
+ * by filing a bug against product "EGL" component "Registry".
+ */
+
+#include <KHR/khrplatform.h>
+
+/* Macros used in EGL function prototype declarations.
+ *
+ * EGL functions should be prototyped as:
+ *
+ * EGLAPI return-type EGLAPIENTRY eglFunction(arguments);
+ * typedef return-type (EXPAPIENTRYP PFNEGLFUNCTIONPROC) (arguments);
+ *
+ * KHRONOS_APICALL and KHRONOS_APIENTRY are defined in KHR/khrplatform.h
+ */
+
+#ifndef EGLAPI
+#define EGLAPI KHRONOS_APICALL
+#endif
+
+#ifndef EGLAPIENTRY
+#define EGLAPIENTRY KHRONOS_APIENTRY
+#endif
+#define EGLAPIENTRYP EGLAPIENTRY*
+
+/* The types NativeDisplayType, NativeWindowType, and NativePixmapType
+ * are aliases of window-system-dependent types, such as X Display * or
+ * Windows Device Context. They must be defined in platform-specific
+ * code below. The EGL-prefixed versions of Native*Type are the same
+ * types, renamed in EGL 1.3 so all types in the API start with "EGL".
+ *
+ * Khronos STRONGLY RECOMMENDS that you use the default definitions
+ * provided below, since these changes affect both binary and source
+ * portability of applications using EGL running on different EGL
+ * implementations.
+ */
+
+#if defined(_WIN32) || defined(__VC32__) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) /* Win32 and WinCE */
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN 1
+#endif
+#include <windows.h>
+
+typedef HDC EGLNativeDisplayType;
+typedef HBITMAP EGLNativePixmapType;
+
+#if defined(WINAPI_FAMILY) && !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
+#include <inspectable.h>
+typedef IInspectable* EGLNativeWindowType;
+#else
+typedef HWND EGLNativeWindowType;
+#endif // defined(WINAPI_FAMILY) && !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
+
+#elif defined(__WINSCW__) || defined(__SYMBIAN32__) /* Symbian */
+
+typedef int EGLNativeDisplayType;
+typedef void *EGLNativeWindowType;
+typedef void *EGLNativePixmapType;
+
+#elif defined(__ANDROID__) || defined(ANDROID)
+
+#include <android/native_window.h>
+
+struct egl_native_pixmap_t;
+
+typedef struct ANativeWindow* EGLNativeWindowType;
+typedef struct egl_native_pixmap_t* EGLNativePixmapType;
+typedef void* EGLNativeDisplayType;
+
+#elif defined(__unix__)
+
+/* X11 (tentative) */
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+typedef Display *EGLNativeDisplayType;
+typedef Pixmap EGLNativePixmapType;
+typedef Window EGLNativeWindowType;
+
+#else
+#error "Platform not recognized"
+#endif
+
+/* EGL 1.2 types, renamed for consistency in EGL 1.3 */
+typedef EGLNativeDisplayType NativeDisplayType;
+typedef EGLNativePixmapType NativePixmapType;
+typedef EGLNativeWindowType NativeWindowType;
+
+
+/* Define EGLint. This must be a signed integral type large enough to contain
+ * all legal attribute names and values passed into and out of EGL, whether
+ * their type is boolean, bitmask, enumerant (symbolic constant), integer,
+ * handle, or other. While in general a 32-bit integer will suffice, if
+ * handles are 64 bit types, then EGLint should be defined as a signed 64-bit
+ * integer type.
+ */
+typedef khronos_int32_t EGLint;
+
+#endif /* __eglplatform_h */
diff --git a/platform/winrt/include/FunctionDiscoveryKeys_devpkey.h b/platform/winrt/include/FunctionDiscoveryKeys_devpkey.h
new file mode 100644
index 0000000000..303e70b029
--- /dev/null
+++ b/platform/winrt/include/FunctionDiscoveryKeys_devpkey.h
@@ -0,0 +1,213 @@
+#pragma once
+#if 0
+/*++
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+
+Module Name:
+
+ devpkey.h
+
+Abstract:
+
+ Defines property keys for the Plug and Play Device Property API.
+
+Author:
+
+ Jim Cavalaris (jamesca) 10-14-2003
+
+Environment:
+
+ User-mode only.
+
+Revision History:
+
+ 14-October-2003 jamesca
+
+ Creation and initial implementation.
+
+ 20-June-2006 dougb
+
+ Copied Jim's version replaced "DEFINE_DEVPROPKEY(DEVPKEY_" with "DEFINE_PROPERTYKEY(PKEY_"
+
+--*/
+
+//#include <devpropdef.h>
+
+//
+// _NAME
+//
+
+DEFINE_PROPERTYKEY(PKEY_NAME, 0xb725f130, 0x47ef, 0x101a, 0xa5, 0xf1, 0x02, 0x60, 0x8c, 0x9e, 0xeb, 0xac, 10); // DEVPROP_TYPE_STRING
+
+//
+// Device properties
+// These PKEYs correspond to the old setupapi SPDRP_XXX properties
+//
+DEFINE_PROPERTYKEY(PKEY_Device_DeviceDesc, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 2); // DEVPROP_TYPE_STRING
+DEFINE_PROPERTYKEY(PKEY_Device_HardwareIds, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 3); // DEVPROP_TYPE_STRING_LIST
+DEFINE_PROPERTYKEY(PKEY_Device_CompatibleIds, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 4); // DEVPROP_TYPE_STRING_LIST
+DEFINE_PROPERTYKEY(PKEY_Device_Service, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 6); // DEVPROP_TYPE_STRING
+DEFINE_PROPERTYKEY(PKEY_Device_Class, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 9); // DEVPROP_TYPE_STRING
+DEFINE_PROPERTYKEY(PKEY_Device_ClassGuid, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 10); // DEVPROP_TYPE_GUID
+DEFINE_PROPERTYKEY(PKEY_Device_Driver, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 11); // DEVPROP_TYPE_STRING
+DEFINE_PROPERTYKEY(PKEY_Device_ConfigFlags, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 12); // DEVPROP_TYPE_UINT32
+DEFINE_PROPERTYKEY(PKEY_Device_Manufacturer, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 13); // DEVPROP_TYPE_STRING
+DEFINE_PROPERTYKEY(PKEY_Device_FriendlyName, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 14); // DEVPROP_TYPE_STRING
+DEFINE_PROPERTYKEY(PKEY_Device_LocationInfo, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 15); // DEVPROP_TYPE_STRING
+DEFINE_PROPERTYKEY(PKEY_Device_PDOName, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 16); // DEVPROP_TYPE_STRING
+DEFINE_PROPERTYKEY(PKEY_Device_Capabilities, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 17); // DEVPROP_TYPE_UNINT32
+DEFINE_PROPERTYKEY(PKEY_Device_UINumber, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 18); // DEVPROP_TYPE_STRING
+DEFINE_PROPERTYKEY(PKEY_Device_UpperFilters, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 19); // DEVPROP_TYPE_STRING_LIST
+DEFINE_PROPERTYKEY(PKEY_Device_LowerFilters, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 20); // DEVPROP_TYPE_STRING_LIST
+DEFINE_PROPERTYKEY(PKEY_Device_BusTypeGuid, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 21); // DEVPROP_TYPE_GUID
+DEFINE_PROPERTYKEY(PKEY_Device_LegacyBusType, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 22); // DEVPROP_TYPE_UINT32
+DEFINE_PROPERTYKEY(PKEY_Device_BusNumber, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 23); // DEVPROP_TYPE_UINT32
+DEFINE_PROPERTYKEY(PKEY_Device_EnumeratorName, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 24); // DEVPROP_TYPE_STRING
+DEFINE_PROPERTYKEY(PKEY_Device_Security, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 25); // DEVPROP_TYPE_SECURITY_DESCRIPTOR
+DEFINE_PROPERTYKEY(PKEY_Device_SecuritySDS, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 26); // DEVPROP_TYPE_SECURITY_DESCRIPTOR_STRING
+DEFINE_PROPERTYKEY(PKEY_Device_DevType, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 27); // DEVPROP_TYPE_UINT32
+DEFINE_PROPERTYKEY(PKEY_Device_Exclusive, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 28); // DEVPROP_TYPE_UINT32
+DEFINE_PROPERTYKEY(PKEY_Device_Characteristics, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 29); // DEVPROP_TYPE_UINT32
+DEFINE_PROPERTYKEY(PKEY_Device_Address, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 30); // DEVPROP_TYPE_UINT32
+DEFINE_PROPERTYKEY(PKEY_Device_UINumberDescFormat, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 31); // DEVPROP_TYPE_STRING
+DEFINE_PROPERTYKEY(PKEY_Device_PowerData, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 32); // DEVPROP_TYPE_BINARY
+DEFINE_PROPERTYKEY(PKEY_Device_RemovalPolicy, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 33); // DEVPROP_TYPE_UINT32
+DEFINE_PROPERTYKEY(PKEY_Device_RemovalPolicyDefault, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 34); // DEVPROP_TYPE_UINT32
+DEFINE_PROPERTYKEY(PKEY_Device_RemovalPolicyOverride, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 35); // DEVPROP_TYPE_UINT32
+DEFINE_PROPERTYKEY(PKEY_Device_InstallState, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 36); // DEVPROP_TYPE_UINT32
+DEFINE_PROPERTYKEY(PKEY_Device_LocationPaths, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 37); // DEVPROP_TYPE_STRING_LIST
+DEFINE_PROPERTYKEY(PKEY_Device_BaseContainerId, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 38); // DEVPROP_TYPE_GUID
+
+//
+// Device properties
+// These PKEYs correspond to a device's status and problem code
+//
+DEFINE_PROPERTYKEY(PKEY_Device_DevNodeStatus, 0x4340a6c5, 0x93fa, 0x4706, 0x97, 0x2c, 0x7b, 0x64, 0x80, 0x08, 0xa5, 0xa7, 2); // DEVPROP_TYPE_UINT32
+DEFINE_PROPERTYKEY(PKEY_Device_ProblemCode, 0x4340a6c5, 0x93fa, 0x4706, 0x97, 0x2c, 0x7b, 0x64, 0x80, 0x08, 0xa5, 0xa7, 3); // DEVPROP_TYPE_UINT32
+
+//
+// Device properties
+// These PKEYs correspond to device relations
+//
+DEFINE_PROPERTYKEY(PKEY_Device_EjectionRelations, 0x4340a6c5, 0x93fa, 0x4706, 0x97, 0x2c, 0x7b, 0x64, 0x80, 0x08, 0xa5, 0xa7, 4); // DEVPROP_TYPE_STRING_LIST
+DEFINE_PROPERTYKEY(PKEY_Device_RemovalRelations, 0x4340a6c5, 0x93fa, 0x4706, 0x97, 0x2c, 0x7b, 0x64, 0x80, 0x08, 0xa5, 0xa7, 5); // DEVPROP_TYPE_STRING_LIST
+DEFINE_PROPERTYKEY(PKEY_Device_PowerRelations, 0x4340a6c5, 0x93fa, 0x4706, 0x97, 0x2c, 0x7b, 0x64, 0x80, 0x08, 0xa5, 0xa7, 6); // DEVPROP_TYPE_STRING_LIST
+DEFINE_PROPERTYKEY(PKEY_Device_BusRelations, 0x4340a6c5, 0x93fa, 0x4706, 0x97, 0x2c, 0x7b, 0x64, 0x80, 0x08, 0xa5, 0xa7, 7); // DEVPROP_TYPE_STRING_LIST
+DEFINE_PROPERTYKEY(PKEY_Device_Parent, 0x4340a6c5, 0x93fa, 0x4706, 0x97, 0x2c, 0x7b, 0x64, 0x80, 0x08, 0xa5, 0xa7, 8); // DEVPROP_TYPE_STRING
+DEFINE_PROPERTYKEY(PKEY_Device_Children, 0x4340a6c5, 0x93fa, 0x4706, 0x97, 0x2c, 0x7b, 0x64, 0x80, 0x08, 0xa5, 0xa7, 9); // DEVPROP_TYPE_STRING_LIST
+DEFINE_PROPERTYKEY(PKEY_Device_Siblings, 0x4340a6c5, 0x93fa, 0x4706, 0x97, 0x2c, 0x7b, 0x64, 0x80, 0x08, 0xa5, 0xa7, 10); // DEVPROP_TYPE_STRING_LIST
+DEFINE_PROPERTYKEY(PKEY_Device_TransportRelations, 0x4340a6c5, 0x93fa, 0x4706, 0x97, 0x2c, 0x7b, 0x64, 0x80, 0x08, 0xa5, 0xa7, 11); // DEVPROP_TYPE_STRING_LIST
+
+//
+// Other Device properties
+//
+DEFINE_PROPERTYKEY(PKEY_Device_Reported, 0x80497100, 0x8c73, 0x48b9, 0xaa, 0xd9, 0xce, 0x38, 0x7e, 0x19, 0xc5, 0x6e, 2); // DEVPROP_TYPE_BOOLEAN
+DEFINE_PROPERTYKEY(PKEY_Device_Legacy, 0x80497100, 0x8c73, 0x48b9, 0xaa, 0xd9, 0xce, 0x38, 0x7e, 0x19, 0xc5, 0x6e, 3); // DEVPROP_TYPE_BOOLEAN
+DEFINE_PROPERTYKEY(PKEY_Device_InstanceId, 0x78c34fc8, 0x104a, 0x4aca, 0x9e, 0xa4, 0x52, 0x4d, 0x52, 0x99, 0x6e, 0x57, 256); // DEVPROP_TYPE_STRING
+
+DEFINE_PROPERTYKEY(PKEY_Device_ContainerId, 0x8c7ed206, 0x3f8a, 0x4827, 0xb3, 0xab, 0xae, 0x9e, 0x1f, 0xae, 0xfc, 0x6c, 2); // DEVPROP_TYPE_GUID
+
+DEFINE_PROPERTYKEY(PKEY_Device_ModelId, 0x80d81ea6, 0x7473, 0x4b0c, 0x82, 0x16, 0xef, 0xc1, 0x1a, 0x2c, 0x4c, 0x8b, 2); // DEVPROP_TYPE_GUID
+
+DEFINE_PROPERTYKEY(PKEY_Device_FriendlyNameAttributes, 0x80d81ea6, 0x7473, 0x4b0c, 0x82, 0x16, 0xef, 0xc1, 0x1a, 0x2c, 0x4c, 0x8b, 3); // DEVPROP_TYPE_UINT32
+DEFINE_PROPERTYKEY(PKEY_Device_ManufacturerAttributes, 0x80d81ea6, 0x7473, 0x4b0c, 0x82, 0x16, 0xef, 0xc1, 0x1a, 0x2c, 0x4c, 0x8b, 4); // DEVPROP_TYPE_UINT32
+
+DEFINE_PROPERTYKEY(PKEY_Device_PresenceNotForDevice, 0x80d81ea6, 0x7473, 0x4b0c, 0x82, 0x16, 0xef, 0xc1, 0x1a, 0x2c, 0x4c, 0x8b, 5); // DEVPROP_TYPE_BOOLEAN
+
+
+DEFINE_PROPERTYKEY(PKEY_Numa_Proximity_Domain, 0x540b947e, 0x8b40, 0x45bc, 0xa8, 0xa2, 0x6a, 0x0b, 0x89, 0x4c, 0xbd, 0xa2, 1); // DEVPROP_TYPE_UINT32
+DEFINE_PROPERTYKEY(PKEY_Device_DHP_Rebalance_Policy, 0x540b947e, 0x8b40, 0x45bc, 0xa8, 0xa2, 0x6a, 0x0b, 0x89, 0x4c, 0xbd, 0xa2, 2); // DEVPROP_TYPE_UINT32
+DEFINE_PROPERTYKEY(PKEY_Device_Numa_Node, 0x540b947e, 0x8b40, 0x45bc, 0xa8, 0xa2, 0x6a, 0x0b, 0x89, 0x4c, 0xbd, 0xa2, 3); // DEVPROP_TYPE_UINT32
+DEFINE_PROPERTYKEY(PKEY_Device_BusReportedDeviceDesc, 0x540b947e, 0x8b40, 0x45bc, 0xa8, 0xa2, 0x6a, 0x0b, 0x89, 0x4c, 0xbd, 0xa2, 4); // DEVPROP_TYPE_STRING
+
+DEFINE_PROPERTYKEY(PKEY_Device_InstallInProgress, 0x83da6326, 0x97a6, 0x4088, 0x94, 0x53, 0xa1, 0x92, 0x3f, 0x57, 0x3b, 0x29, 9); // DEVPROP_TYPE_BOOLEAN
+
+//
+// Device driver properties
+//
+DEFINE_PROPERTYKEY(PKEY_Device_DriverDate, 0xa8b865dd, 0x2e3d, 0x4094, 0xad, 0x97, 0xe5, 0x93, 0xa7, 0xc, 0x75, 0xd6, 2); // DEVPROP_TYPE_FILETIME
+DEFINE_PROPERTYKEY(PKEY_Device_DriverVersion, 0xa8b865dd, 0x2e3d, 0x4094, 0xad, 0x97, 0xe5, 0x93, 0xa7, 0xc, 0x75, 0xd6, 3); // DEVPROP_TYPE_STRING
+DEFINE_PROPERTYKEY(PKEY_Device_DriverDesc, 0xa8b865dd, 0x2e3d, 0x4094, 0xad, 0x97, 0xe5, 0x93, 0xa7, 0xc, 0x75, 0xd6, 4); // DEVPROP_TYPE_STRING
+DEFINE_PROPERTYKEY(PKEY_Device_DriverInfPath, 0xa8b865dd, 0x2e3d, 0x4094, 0xad, 0x97, 0xe5, 0x93, 0xa7, 0xc, 0x75, 0xd6, 5); // DEVPROP_TYPE_STRING
+DEFINE_PROPERTYKEY(PKEY_Device_DriverInfSection, 0xa8b865dd, 0x2e3d, 0x4094, 0xad, 0x97, 0xe5, 0x93, 0xa7, 0xc, 0x75, 0xd6, 6); // DEVPROP_TYPE_STRING
+DEFINE_PROPERTYKEY(PKEY_Device_DriverInfSectionExt, 0xa8b865dd, 0x2e3d, 0x4094, 0xad, 0x97, 0xe5, 0x93, 0xa7, 0xc, 0x75, 0xd6, 7); // DEVPROP_TYPE_STRING
+DEFINE_PROPERTYKEY(PKEY_Device_MatchingDeviceId, 0xa8b865dd, 0x2e3d, 0x4094, 0xad, 0x97, 0xe5, 0x93, 0xa7, 0xc, 0x75, 0xd6, 8); // DEVPROP_TYPE_STRING
+DEFINE_PROPERTYKEY(PKEY_Device_DriverProvider, 0xa8b865dd, 0x2e3d, 0x4094, 0xad, 0x97, 0xe5, 0x93, 0xa7, 0xc, 0x75, 0xd6, 9); // DEVPROP_TYPE_STRING
+DEFINE_PROPERTYKEY(PKEY_Device_DriverPropPageProvider, 0xa8b865dd, 0x2e3d, 0x4094, 0xad, 0x97, 0xe5, 0x93, 0xa7, 0xc, 0x75, 0xd6, 10); // DEVPROP_TYPE_STRING
+DEFINE_PROPERTYKEY(PKEY_Device_DriverCoInstallers, 0xa8b865dd, 0x2e3d, 0x4094, 0xad, 0x97, 0xe5, 0x93, 0xa7, 0xc, 0x75, 0xd6, 11); // DEVPROP_TYPE_STRING_LIST
+DEFINE_PROPERTYKEY(PKEY_Device_ResourcePickerTags, 0xa8b865dd, 0x2e3d, 0x4094, 0xad, 0x97, 0xe5, 0x93, 0xa7, 0xc, 0x75, 0xd6, 12); // DEVPROP_TYPE_STRING
+DEFINE_PROPERTYKEY(PKEY_Device_ResourcePickerExceptions, 0xa8b865dd, 0x2e3d, 0x4094, 0xad, 0x97, 0xe5, 0x93, 0xa7, 0xc, 0x75, 0xd6, 13); // DEVPROP_TYPE_STRING
+DEFINE_PROPERTYKEY(PKEY_Device_DriverRank, 0xa8b865dd, 0x2e3d, 0x4094, 0xad, 0x97, 0xe5, 0x93, 0xa7, 0xc, 0x75, 0xd6, 14); // DEVPROP_TYPE_UINT32
+DEFINE_PROPERTYKEY(PKEY_Device_DriverLogoLevel, 0xa8b865dd, 0x2e3d, 0x4094, 0xad, 0x97, 0xe5, 0x93, 0xa7, 0xc, 0x75, 0xd6, 15); // DEVPROP_TYPE_UINT32
+DEFINE_PROPERTYKEY(PKEY_Device_NoConnectSound, 0xa8b865dd, 0x2e3d, 0x4094, 0xad, 0x97, 0xe5, 0x93, 0xa7, 0xc, 0x75, 0xd6, 17); // DEVPROP_TYPE_BOOLEAN
+DEFINE_PROPERTYKEY(PKEY_Device_GenericDriverInstalled, 0xa8b865dd, 0x2e3d, 0x4094, 0xad, 0x97, 0xe5, 0x93, 0xa7, 0xc, 0x75, 0xd6, 18); // DEVPROP_TYPE_BOOLEAN
+DEFINE_PROPERTYKEY(PKEY_Device_AdditionalSoftwareRequested, 0xa8b865dd, 0x2e3d, 0x4094, 0xad, 0x97, 0xe5, 0x93, 0xa7, 0xc, 0x75, 0xd6, 19);// DEVPROP_TYPE_BOOLEAN
+
+//
+// Device safe-removal properties
+//
+DEFINE_PROPERTYKEY(PKEY_Device_SafeRemovalRequired, 0xafd97640, 0x86a3, 0x4210, 0xb6, 0x7c, 0x28, 0x9c, 0x41, 0xaa, 0xbe, 0x55, 2); // DEVPROP_TYPE_BOOLEAN
+DEFINE_PROPERTYKEY(PKEY_Device_SafeRemovalRequiredOverride, 0xafd97640, 0x86a3, 0x4210, 0xb6, 0x7c, 0x28, 0x9c, 0x41, 0xaa, 0xbe, 0x55, 3);// DEVPROP_TYPE_BOOLEAN
+
+
+//
+// Device properties that were set by the driver package that was installed
+// on the device.
+//
+DEFINE_PROPERTYKEY(PKEY_DrvPkg_Model, 0xcf73bb51, 0x3abf, 0x44a2, 0x85, 0xe0, 0x9a, 0x3d, 0xc7, 0xa1, 0x21, 0x32, 2); // DEVPROP_TYPE_STRING
+DEFINE_PROPERTYKEY(PKEY_DrvPkg_VendorWebSite, 0xcf73bb51, 0x3abf, 0x44a2, 0x85, 0xe0, 0x9a, 0x3d, 0xc7, 0xa1, 0x21, 0x32, 3); // DEVPROP_TYPE_STRING
+DEFINE_PROPERTYKEY(PKEY_DrvPkg_DetailedDescription, 0xcf73bb51, 0x3abf, 0x44a2, 0x85, 0xe0, 0x9a, 0x3d, 0xc7, 0xa1, 0x21, 0x32, 4); // DEVPROP_TYPE_STRING
+DEFINE_PROPERTYKEY(PKEY_DrvPkg_DocumentationLink, 0xcf73bb51, 0x3abf, 0x44a2, 0x85, 0xe0, 0x9a, 0x3d, 0xc7, 0xa1, 0x21, 0x32, 5); // DEVPROP_TYPE_STRING
+DEFINE_PROPERTYKEY(PKEY_DrvPkg_Icon, 0xcf73bb51, 0x3abf, 0x44a2, 0x85, 0xe0, 0x9a, 0x3d, 0xc7, 0xa1, 0x21, 0x32, 6); // DEVPROP_TYPE_STRING_LIST
+DEFINE_PROPERTYKEY(PKEY_DrvPkg_BrandingIcon, 0xcf73bb51, 0x3abf, 0x44a2, 0x85, 0xe0, 0x9a, 0x3d, 0xc7, 0xa1, 0x21, 0x32, 7); // DEVPROP_TYPE_STRING_LIST
+
+//
+// Device setup class properties
+// These PKEYs correspond to the old setupapi SPCRP_XXX properties
+//
+DEFINE_PROPERTYKEY(PKEY_DeviceClass_UpperFilters, 0x4321918b, 0xf69e, 0x470d, 0xa5, 0xde, 0x4d, 0x88, 0xc7, 0x5a, 0xd2, 0x4b, 19); // DEVPROP_TYPE_STRING_LIST
+DEFINE_PROPERTYKEY(PKEY_DeviceClass_LowerFilters, 0x4321918b, 0xf69e, 0x470d, 0xa5, 0xde, 0x4d, 0x88, 0xc7, 0x5a, 0xd2, 0x4b, 20); // DEVPROP_TYPE_STRING_LIST
+DEFINE_PROPERTYKEY(PKEY_DeviceClass_Security, 0x4321918b, 0xf69e, 0x470d, 0xa5, 0xde, 0x4d, 0x88, 0xc7, 0x5a, 0xd2, 0x4b, 25); // DEVPROP_TYPE_SECURITY_DESCRIPTOR
+DEFINE_PROPERTYKEY(PKEY_DeviceClass_SecuritySDS, 0x4321918b, 0xf69e, 0x470d, 0xa5, 0xde, 0x4d, 0x88, 0xc7, 0x5a, 0xd2, 0x4b, 26); // DEVPROP_TYPE_SECURITY_DESCRIPTOR_STRING
+DEFINE_PROPERTYKEY(PKEY_DeviceClass_DevType, 0x4321918b, 0xf69e, 0x470d, 0xa5, 0xde, 0x4d, 0x88, 0xc7, 0x5a, 0xd2, 0x4b, 27); // DEVPROP_TYPE_UINT32
+DEFINE_PROPERTYKEY(PKEY_DeviceClass_Exclusive, 0x4321918b, 0xf69e, 0x470d, 0xa5, 0xde, 0x4d, 0x88, 0xc7, 0x5a, 0xd2, 0x4b, 28); // DEVPROP_TYPE_UINT32
+DEFINE_PROPERTYKEY(PKEY_DeviceClass_Characteristics, 0x4321918b, 0xf69e, 0x470d, 0xa5, 0xde, 0x4d, 0x88, 0xc7, 0x5a, 0xd2, 0x4b, 29); // DEVPROP_TYPE_UINT32
+
+//
+// Device setup class properties
+// These PKEYs correspond to registry values under the device class GUID key
+//
+DEFINE_PROPERTYKEY(PKEY_DeviceClass_Name, 0x259abffc, 0x50a7, 0x47ce, 0xaf, 0x8, 0x68, 0xc9, 0xa7, 0xd7, 0x33, 0x66, 2); // DEVPROP_TYPE_STRING
+DEFINE_PROPERTYKEY(PKEY_DeviceClass_ClassName, 0x259abffc, 0x50a7, 0x47ce, 0xaf, 0x8, 0x68, 0xc9, 0xa7, 0xd7, 0x33, 0x66, 3); // DEVPROP_TYPE_STRING
+DEFINE_PROPERTYKEY(PKEY_DeviceClass_Icon, 0x259abffc, 0x50a7, 0x47ce, 0xaf, 0x8, 0x68, 0xc9, 0xa7, 0xd7, 0x33, 0x66, 4); // DEVPROP_TYPE_STRING
+DEFINE_PROPERTYKEY(PKEY_DeviceClass_ClassInstaller, 0x259abffc, 0x50a7, 0x47ce, 0xaf, 0x8, 0x68, 0xc9, 0xa7, 0xd7, 0x33, 0x66, 5); // DEVPROP_TYPE_STRING
+DEFINE_PROPERTYKEY(PKEY_DeviceClass_PropPageProvider, 0x259abffc, 0x50a7, 0x47ce, 0xaf, 0x8, 0x68, 0xc9, 0xa7, 0xd7, 0x33, 0x66, 6); // DEVPROP_TYPE_STRING
+DEFINE_PROPERTYKEY(PKEY_DeviceClass_NoInstallClass, 0x259abffc, 0x50a7, 0x47ce, 0xaf, 0x8, 0x68, 0xc9, 0xa7, 0xd7, 0x33, 0x66, 7); // DEVPROP_TYPE_BOOLEAN
+DEFINE_PROPERTYKEY(PKEY_DeviceClass_NoDisplayClass, 0x259abffc, 0x50a7, 0x47ce, 0xaf, 0x8, 0x68, 0xc9, 0xa7, 0xd7, 0x33, 0x66, 8); // DEVPROP_TYPE_BOOLEAN
+DEFINE_PROPERTYKEY(PKEY_DeviceClass_SilentInstall, 0x259abffc, 0x50a7, 0x47ce, 0xaf, 0x8, 0x68, 0xc9, 0xa7, 0xd7, 0x33, 0x66, 9); // DEVPROP_TYPE_BOOLEAN
+DEFINE_PROPERTYKEY(PKEY_DeviceClass_NoUseClass, 0x259abffc, 0x50a7, 0x47ce, 0xaf, 0x8, 0x68, 0xc9, 0xa7, 0xd7, 0x33, 0x66, 10); // DEVPROP_TYPE_BOOLEAN
+DEFINE_PROPERTYKEY(PKEY_DeviceClass_DefaultService, 0x259abffc, 0x50a7, 0x47ce, 0xaf, 0x8, 0x68, 0xc9, 0xa7, 0xd7, 0x33, 0x66, 11); // DEVPROP_TYPE_STRING
+DEFINE_PROPERTYKEY(PKEY_DeviceClass_IconPath, 0x259abffc, 0x50a7, 0x47ce, 0xaf, 0x8, 0x68, 0xc9, 0xa7, 0xd7, 0x33, 0x66, 12); // DEVPROP_TYPE_STRING_LIST
+
+//
+// Other Device setup class properties
+//
+DEFINE_PROPERTYKEY(PKEY_DeviceClass_ClassCoInstallers, 0x713d1703, 0xa2e2, 0x49f5, 0x92, 0x14, 0x56, 0x47, 0x2e, 0xf3, 0xda, 0x5c, 2); // DEVPROP_TYPE_STRING_LIST
+
+//
+// Device interface properties
+//
+DEFINE_PROPERTYKEY(PKEY_DeviceInterface_FriendlyName, 0x026e516e, 0xb814, 0x414b, 0x83, 0xcd, 0x85, 0x6d, 0x6f, 0xef, 0x48, 0x22, 2); // DEVPROP_TYPE_STRING
+DEFINE_PROPERTYKEY(PKEY_DeviceInterface_Enabled, 0x026e516e, 0xb814, 0x414b, 0x83, 0xcd, 0x85, 0x6d, 0x6f, 0xef, 0x48, 0x22, 3); // DEVPROP_TYPE_BOOLEAN
+DEFINE_PROPERTYKEY(PKEY_DeviceInterface_ClassGuid, 0x026e516e, 0xb814, 0x414b, 0x83, 0xcd, 0x85, 0x6d, 0x6f, 0xef, 0x48, 0x22, 4); // DEVPROP_TYPE_GUID
+
+//
+// Device interface class properties
+//
+DEFINE_PROPERTYKEY(PKEY_DeviceInterfaceClass_DefaultInterface, 0x14c83a99, 0x0b3f, 0x44b7, 0xbe, 0x4c, 0xa1, 0x78, 0xd3, 0x99, 0x05, 0x64, 2); // DEVPROP_TYPE_STRING
+
+
+
+
+#endif
diff --git a/platform/winrt/include/GLES2/gl2.h b/platform/winrt/include/GLES2/gl2.h
new file mode 100644
index 0000000000..5b3fa03c89
--- /dev/null
+++ b/platform/winrt/include/GLES2/gl2.h
@@ -0,0 +1,620 @@
+#ifndef __gl2_h_
+#define __gl2_h_
+
+/* $Revision: 20555 $ on $Date:: 2013-02-12 14:32:47 -0800 #$ */
+
+#include <GLES2/gl2platform.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * This document is licensed under the SGI Free Software B License Version
+ * 2.0. For details, see http://oss.sgi.com/projects/FreeB/ .
+ */
+
+/*-------------------------------------------------------------------------
+ * Data type definitions
+ *-----------------------------------------------------------------------*/
+
+typedef void GLvoid;
+typedef char GLchar;
+typedef unsigned int GLenum;
+typedef unsigned char GLboolean;
+typedef unsigned int GLbitfield;
+typedef khronos_int8_t GLbyte;
+typedef short GLshort;
+typedef int GLint;
+typedef int GLsizei;
+typedef khronos_uint8_t GLubyte;
+typedef unsigned short GLushort;
+typedef unsigned int GLuint;
+typedef khronos_float_t GLfloat;
+typedef khronos_float_t GLclampf;
+typedef khronos_int32_t GLfixed;
+
+/* GL types for handling large vertex buffer objects */
+typedef khronos_intptr_t GLintptr;
+typedef khronos_ssize_t GLsizeiptr;
+
+/* OpenGL ES core versions */
+#define GL_ES_VERSION_2_0 1
+
+/* ClearBufferMask */
+#define GL_DEPTH_BUFFER_BIT 0x00000100
+#define GL_STENCIL_BUFFER_BIT 0x00000400
+#define GL_COLOR_BUFFER_BIT 0x00004000
+
+/* Boolean */
+#define GL_FALSE 0
+#define GL_TRUE 1
+
+/* BeginMode */
+#define GL_POINTS 0x0000
+#define GL_LINES 0x0001
+#define GL_LINE_LOOP 0x0002
+#define GL_LINE_STRIP 0x0003
+#define GL_TRIANGLES 0x0004
+#define GL_TRIANGLE_STRIP 0x0005
+#define GL_TRIANGLE_FAN 0x0006
+
+/* AlphaFunction (not supported in ES20) */
+/* GL_NEVER */
+/* GL_LESS */
+/* GL_EQUAL */
+/* GL_LEQUAL */
+/* GL_GREATER */
+/* GL_NOTEQUAL */
+/* GL_GEQUAL */
+/* GL_ALWAYS */
+
+/* BlendingFactorDest */
+#define GL_ZERO 0
+#define GL_ONE 1
+#define GL_SRC_COLOR 0x0300
+#define GL_ONE_MINUS_SRC_COLOR 0x0301
+#define GL_SRC_ALPHA 0x0302
+#define GL_ONE_MINUS_SRC_ALPHA 0x0303
+#define GL_DST_ALPHA 0x0304
+#define GL_ONE_MINUS_DST_ALPHA 0x0305
+
+/* BlendingFactorSrc */
+/* GL_ZERO */
+/* GL_ONE */
+#define GL_DST_COLOR 0x0306
+#define GL_ONE_MINUS_DST_COLOR 0x0307
+#define GL_SRC_ALPHA_SATURATE 0x0308
+/* GL_SRC_ALPHA */
+/* GL_ONE_MINUS_SRC_ALPHA */
+/* GL_DST_ALPHA */
+/* GL_ONE_MINUS_DST_ALPHA */
+
+/* BlendEquationSeparate */
+#define GL_FUNC_ADD 0x8006
+#define GL_BLEND_EQUATION 0x8009
+#define GL_BLEND_EQUATION_RGB 0x8009 /* same as BLEND_EQUATION */
+#define GL_BLEND_EQUATION_ALPHA 0x883D
+
+/* BlendSubtract */
+#define GL_FUNC_SUBTRACT 0x800A
+#define GL_FUNC_REVERSE_SUBTRACT 0x800B
+
+/* Separate Blend Functions */
+#define GL_BLEND_DST_RGB 0x80C8
+#define GL_BLEND_SRC_RGB 0x80C9
+#define GL_BLEND_DST_ALPHA 0x80CA
+#define GL_BLEND_SRC_ALPHA 0x80CB
+#define GL_CONSTANT_COLOR 0x8001
+#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002
+#define GL_CONSTANT_ALPHA 0x8003
+#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004
+#define GL_BLEND_COLOR 0x8005
+
+/* Buffer Objects */
+#define GL_ARRAY_BUFFER 0x8892
+#define GL_ELEMENT_ARRAY_BUFFER 0x8893
+#define GL_ARRAY_BUFFER_BINDING 0x8894
+#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895
+
+#define GL_STREAM_DRAW 0x88E0
+#define GL_STATIC_DRAW 0x88E4
+#define GL_DYNAMIC_DRAW 0x88E8
+
+#define GL_BUFFER_SIZE 0x8764
+#define GL_BUFFER_USAGE 0x8765
+
+#define GL_CURRENT_VERTEX_ATTRIB 0x8626
+
+/* CullFaceMode */
+#define GL_FRONT 0x0404
+#define GL_BACK 0x0405
+#define GL_FRONT_AND_BACK 0x0408
+
+/* DepthFunction */
+/* GL_NEVER */
+/* GL_LESS */
+/* GL_EQUAL */
+/* GL_LEQUAL */
+/* GL_GREATER */
+/* GL_NOTEQUAL */
+/* GL_GEQUAL */
+/* GL_ALWAYS */
+
+/* EnableCap */
+#define GL_TEXTURE_2D 0x0DE1
+#define GL_CULL_FACE 0x0B44
+#define GL_BLEND 0x0BE2
+#define GL_DITHER 0x0BD0
+#define GL_STENCIL_TEST 0x0B90
+#define GL_DEPTH_TEST 0x0B71
+#define GL_SCISSOR_TEST 0x0C11
+#define GL_POLYGON_OFFSET_FILL 0x8037
+#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E
+#define GL_SAMPLE_COVERAGE 0x80A0
+
+/* ErrorCode */
+#define GL_NO_ERROR 0
+#define GL_INVALID_ENUM 0x0500
+#define GL_INVALID_VALUE 0x0501
+#define GL_INVALID_OPERATION 0x0502
+#define GL_OUT_OF_MEMORY 0x0505
+
+/* FrontFaceDirection */
+#define GL_CW 0x0900
+#define GL_CCW 0x0901
+
+/* GetPName */
+#define GL_LINE_WIDTH 0x0B21
+#define GL_ALIASED_POINT_SIZE_RANGE 0x846D
+#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E
+#define GL_CULL_FACE_MODE 0x0B45
+#define GL_FRONT_FACE 0x0B46
+#define GL_DEPTH_RANGE 0x0B70
+#define GL_DEPTH_WRITEMASK 0x0B72
+#define GL_DEPTH_CLEAR_VALUE 0x0B73
+#define GL_DEPTH_FUNC 0x0B74
+#define GL_STENCIL_CLEAR_VALUE 0x0B91
+#define GL_STENCIL_FUNC 0x0B92
+#define GL_STENCIL_FAIL 0x0B94
+#define GL_STENCIL_PASS_DEPTH_FAIL 0x0B95
+#define GL_STENCIL_PASS_DEPTH_PASS 0x0B96
+#define GL_STENCIL_REF 0x0B97
+#define GL_STENCIL_VALUE_MASK 0x0B93
+#define GL_STENCIL_WRITEMASK 0x0B98
+#define GL_STENCIL_BACK_FUNC 0x8800
+#define GL_STENCIL_BACK_FAIL 0x8801
+#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802
+#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803
+#define GL_STENCIL_BACK_REF 0x8CA3
+#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4
+#define GL_STENCIL_BACK_WRITEMASK 0x8CA5
+#define GL_VIEWPORT 0x0BA2
+#define GL_SCISSOR_BOX 0x0C10
+/* GL_SCISSOR_TEST */
+#define GL_COLOR_CLEAR_VALUE 0x0C22
+#define GL_COLOR_WRITEMASK 0x0C23
+#define GL_UNPACK_ALIGNMENT 0x0CF5
+#define GL_PACK_ALIGNMENT 0x0D05
+#define GL_MAX_TEXTURE_SIZE 0x0D33
+#define GL_MAX_VIEWPORT_DIMS 0x0D3A
+#define GL_SUBPIXEL_BITS 0x0D50
+#define GL_RED_BITS 0x0D52
+#define GL_GREEN_BITS 0x0D53
+#define GL_BLUE_BITS 0x0D54
+#define GL_ALPHA_BITS 0x0D55
+#define GL_DEPTH_BITS 0x0D56
+#define GL_STENCIL_BITS 0x0D57
+#define GL_POLYGON_OFFSET_UNITS 0x2A00
+/* GL_POLYGON_OFFSET_FILL */
+#define GL_POLYGON_OFFSET_FACTOR 0x8038
+#define GL_TEXTURE_BINDING_2D 0x8069
+#define GL_SAMPLE_BUFFERS 0x80A8
+#define GL_SAMPLES 0x80A9
+#define GL_SAMPLE_COVERAGE_VALUE 0x80AA
+#define GL_SAMPLE_COVERAGE_INVERT 0x80AB
+
+/* GetTextureParameter */
+/* GL_TEXTURE_MAG_FILTER */
+/* GL_TEXTURE_MIN_FILTER */
+/* GL_TEXTURE_WRAP_S */
+/* GL_TEXTURE_WRAP_T */
+
+#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2
+#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3
+
+/* HintMode */
+#define GL_DONT_CARE 0x1100
+#define GL_FASTEST 0x1101
+#define GL_NICEST 0x1102
+
+/* HintTarget */
+#define GL_GENERATE_MIPMAP_HINT 0x8192
+
+/* DataType */
+#define GL_BYTE 0x1400
+#define GL_UNSIGNED_BYTE 0x1401
+#define GL_SHORT 0x1402
+#define GL_UNSIGNED_SHORT 0x1403
+#define GL_INT 0x1404
+#define GL_UNSIGNED_INT 0x1405
+#define GL_FLOAT 0x1406
+#define GL_FIXED 0x140C
+
+/* PixelFormat */
+#define GL_DEPTH_COMPONENT 0x1902
+#define GL_ALPHA 0x1906
+#define GL_RGB 0x1907
+#define GL_RGBA 0x1908
+#define GL_LUMINANCE 0x1909
+#define GL_LUMINANCE_ALPHA 0x190A
+
+/* PixelType */
+/* GL_UNSIGNED_BYTE */
+#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033
+#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034
+#define GL_UNSIGNED_SHORT_5_6_5 0x8363
+
+/* Shaders */
+#define GL_FRAGMENT_SHADER 0x8B30
+#define GL_VERTEX_SHADER 0x8B31
+#define GL_MAX_VERTEX_ATTRIBS 0x8869
+#define GL_MAX_VERTEX_UNIFORM_VECTORS 0x8DFB
+#define GL_MAX_VARYING_VECTORS 0x8DFC
+#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D
+#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C
+#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872
+#define GL_MAX_FRAGMENT_UNIFORM_VECTORS 0x8DFD
+#define GL_SHADER_TYPE 0x8B4F
+#define GL_DELETE_STATUS 0x8B80
+#define GL_LINK_STATUS 0x8B82
+#define GL_VALIDATE_STATUS 0x8B83
+#define GL_ATTACHED_SHADERS 0x8B85
+#define GL_ACTIVE_UNIFORMS 0x8B86
+#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87
+#define GL_ACTIVE_ATTRIBUTES 0x8B89
+#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A
+#define GL_SHADING_LANGUAGE_VERSION 0x8B8C
+#define GL_CURRENT_PROGRAM 0x8B8D
+
+/* StencilFunction */
+#define GL_NEVER 0x0200
+#define GL_LESS 0x0201
+#define GL_EQUAL 0x0202
+#define GL_LEQUAL 0x0203
+#define GL_GREATER 0x0204
+#define GL_NOTEQUAL 0x0205
+#define GL_GEQUAL 0x0206
+#define GL_ALWAYS 0x0207
+
+/* StencilOp */
+/* GL_ZERO */
+#define GL_KEEP 0x1E00
+#define GL_REPLACE 0x1E01
+#define GL_INCR 0x1E02
+#define GL_DECR 0x1E03
+#define GL_INVERT 0x150A
+#define GL_INCR_WRAP 0x8507
+#define GL_DECR_WRAP 0x8508
+
+/* StringName */
+#define GL_VENDOR 0x1F00
+#define GL_RENDERER 0x1F01
+#define GL_VERSION 0x1F02
+#define GL_EXTENSIONS 0x1F03
+
+/* TextureMagFilter */
+#define GL_NEAREST 0x2600
+#define GL_LINEAR 0x2601
+
+/* TextureMinFilter */
+/* GL_NEAREST */
+/* GL_LINEAR */
+#define GL_NEAREST_MIPMAP_NEAREST 0x2700
+#define GL_LINEAR_MIPMAP_NEAREST 0x2701
+#define GL_NEAREST_MIPMAP_LINEAR 0x2702
+#define GL_LINEAR_MIPMAP_LINEAR 0x2703
+
+/* TextureParameterName */
+#define GL_TEXTURE_MAG_FILTER 0x2800
+#define GL_TEXTURE_MIN_FILTER 0x2801
+#define GL_TEXTURE_WRAP_S 0x2802
+#define GL_TEXTURE_WRAP_T 0x2803
+
+/* TextureTarget */
+/* GL_TEXTURE_2D */
+#define GL_TEXTURE 0x1702
+
+#define GL_TEXTURE_CUBE_MAP 0x8513
+#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A
+#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C
+
+/* TextureUnit */
+#define GL_TEXTURE0 0x84C0
+#define GL_TEXTURE1 0x84C1
+#define GL_TEXTURE2 0x84C2
+#define GL_TEXTURE3 0x84C3
+#define GL_TEXTURE4 0x84C4
+#define GL_TEXTURE5 0x84C5
+#define GL_TEXTURE6 0x84C6
+#define GL_TEXTURE7 0x84C7
+#define GL_TEXTURE8 0x84C8
+#define GL_TEXTURE9 0x84C9
+#define GL_TEXTURE10 0x84CA
+#define GL_TEXTURE11 0x84CB
+#define GL_TEXTURE12 0x84CC
+#define GL_TEXTURE13 0x84CD
+#define GL_TEXTURE14 0x84CE
+#define GL_TEXTURE15 0x84CF
+#define GL_TEXTURE16 0x84D0
+#define GL_TEXTURE17 0x84D1
+#define GL_TEXTURE18 0x84D2
+#define GL_TEXTURE19 0x84D3
+#define GL_TEXTURE20 0x84D4
+#define GL_TEXTURE21 0x84D5
+#define GL_TEXTURE22 0x84D6
+#define GL_TEXTURE23 0x84D7
+#define GL_TEXTURE24 0x84D8
+#define GL_TEXTURE25 0x84D9
+#define GL_TEXTURE26 0x84DA
+#define GL_TEXTURE27 0x84DB
+#define GL_TEXTURE28 0x84DC
+#define GL_TEXTURE29 0x84DD
+#define GL_TEXTURE30 0x84DE
+#define GL_TEXTURE31 0x84DF
+#define GL_ACTIVE_TEXTURE 0x84E0
+
+/* TextureWrapMode */
+#define GL_REPEAT 0x2901
+#define GL_CLAMP_TO_EDGE 0x812F
+#define GL_MIRRORED_REPEAT 0x8370
+
+/* Uniform Types */
+#define GL_FLOAT_VEC2 0x8B50
+#define GL_FLOAT_VEC3 0x8B51
+#define GL_FLOAT_VEC4 0x8B52
+#define GL_INT_VEC2 0x8B53
+#define GL_INT_VEC3 0x8B54
+#define GL_INT_VEC4 0x8B55
+#define GL_BOOL 0x8B56
+#define GL_BOOL_VEC2 0x8B57
+#define GL_BOOL_VEC3 0x8B58
+#define GL_BOOL_VEC4 0x8B59
+#define GL_FLOAT_MAT2 0x8B5A
+#define GL_FLOAT_MAT3 0x8B5B
+#define GL_FLOAT_MAT4 0x8B5C
+#define GL_SAMPLER_2D 0x8B5E
+#define GL_SAMPLER_CUBE 0x8B60
+
+/* Vertex Arrays */
+#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622
+#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623
+#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624
+#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625
+#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A
+#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645
+#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F
+
+/* Read Format */
+#define GL_IMPLEMENTATION_COLOR_READ_TYPE 0x8B9A
+#define GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B
+
+/* Shader Source */
+#define GL_COMPILE_STATUS 0x8B81
+#define GL_INFO_LOG_LENGTH 0x8B84
+#define GL_SHADER_SOURCE_LENGTH 0x8B88
+#define GL_SHADER_COMPILER 0x8DFA
+
+/* Shader Binary */
+#define GL_SHADER_BINARY_FORMATS 0x8DF8
+#define GL_NUM_SHADER_BINARY_FORMATS 0x8DF9
+
+/* Shader Precision-Specified Types */
+#define GL_LOW_FLOAT 0x8DF0
+#define GL_MEDIUM_FLOAT 0x8DF1
+#define GL_HIGH_FLOAT 0x8DF2
+#define GL_LOW_INT 0x8DF3
+#define GL_MEDIUM_INT 0x8DF4
+#define GL_HIGH_INT 0x8DF5
+
+/* Framebuffer Object. */
+#define GL_FRAMEBUFFER 0x8D40
+#define GL_RENDERBUFFER 0x8D41
+
+#define GL_RGBA4 0x8056
+#define GL_RGB5_A1 0x8057
+#define GL_RGB565 0x8D62
+#define GL_DEPTH_COMPONENT16 0x81A5
+#define GL_STENCIL_INDEX8 0x8D48
+
+#define GL_RENDERBUFFER_WIDTH 0x8D42
+#define GL_RENDERBUFFER_HEIGHT 0x8D43
+#define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44
+#define GL_RENDERBUFFER_RED_SIZE 0x8D50
+#define GL_RENDERBUFFER_GREEN_SIZE 0x8D51
+#define GL_RENDERBUFFER_BLUE_SIZE 0x8D52
+#define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53
+#define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54
+#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55
+
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3
+
+#define GL_COLOR_ATTACHMENT0 0x8CE0
+#define GL_DEPTH_ATTACHMENT 0x8D00
+#define GL_STENCIL_ATTACHMENT 0x8D20
+
+#define GL_NONE 0
+
+#define GL_FRAMEBUFFER_COMPLETE 0x8CD5
+#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6
+#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7
+#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS 0x8CD9
+#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD
+
+#define GL_FRAMEBUFFER_BINDING 0x8CA6
+#define GL_RENDERBUFFER_BINDING 0x8CA7
+#define GL_MAX_RENDERBUFFER_SIZE 0x84E8
+
+#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506
+
+/*-------------------------------------------------------------------------
+ * GL core functions.
+ *-----------------------------------------------------------------------*/
+
+GL_APICALL void GL_APIENTRY glActiveTexture (GLenum texture);
+GL_APICALL void GL_APIENTRY glAttachShader (GLuint program, GLuint shader);
+GL_APICALL void GL_APIENTRY glBindAttribLocation (GLuint program, GLuint index, const GLchar* name);
+GL_APICALL void GL_APIENTRY glBindBuffer (GLenum target, GLuint buffer);
+GL_APICALL void GL_APIENTRY glBindFramebuffer (GLenum target, GLuint framebuffer);
+GL_APICALL void GL_APIENTRY glBindRenderbuffer (GLenum target, GLuint renderbuffer);
+GL_APICALL void GL_APIENTRY glBindTexture (GLenum target, GLuint texture);
+GL_APICALL void GL_APIENTRY glBlendColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+GL_APICALL void GL_APIENTRY glBlendEquation ( GLenum mode );
+GL_APICALL void GL_APIENTRY glBlendEquationSeparate (GLenum modeRGB, GLenum modeAlpha);
+GL_APICALL void GL_APIENTRY glBlendFunc (GLenum sfactor, GLenum dfactor);
+GL_APICALL void GL_APIENTRY glBlendFuncSeparate (GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+GL_APICALL void GL_APIENTRY glBufferData (GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage);
+GL_APICALL void GL_APIENTRY glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data);
+GL_APICALL GLenum GL_APIENTRY glCheckFramebufferStatus (GLenum target);
+GL_APICALL void GL_APIENTRY glClear (GLbitfield mask);
+GL_APICALL void GL_APIENTRY glClearColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+GL_APICALL void GL_APIENTRY glClearDepthf (GLclampf depth);
+GL_APICALL void GL_APIENTRY glClearStencil (GLint s);
+GL_APICALL void GL_APIENTRY glColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+GL_APICALL void GL_APIENTRY glCompileShader (GLuint shader);
+GL_APICALL void GL_APIENTRY glCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* data);
+GL_APICALL void GL_APIENTRY glCompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid* data);
+GL_APICALL void GL_APIENTRY glCopyTexImage2D (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+GL_APICALL void GL_APIENTRY glCopyTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+GL_APICALL GLuint GL_APIENTRY glCreateProgram (void);
+GL_APICALL GLuint GL_APIENTRY glCreateShader (GLenum type);
+GL_APICALL void GL_APIENTRY glCullFace (GLenum mode);
+GL_APICALL void GL_APIENTRY glDeleteBuffers (GLsizei n, const GLuint* buffers);
+GL_APICALL void GL_APIENTRY glDeleteFramebuffers (GLsizei n, const GLuint* framebuffers);
+GL_APICALL void GL_APIENTRY glDeleteProgram (GLuint program);
+GL_APICALL void GL_APIENTRY glDeleteRenderbuffers (GLsizei n, const GLuint* renderbuffers);
+GL_APICALL void GL_APIENTRY glDeleteShader (GLuint shader);
+GL_APICALL void GL_APIENTRY glDeleteTextures (GLsizei n, const GLuint* textures);
+GL_APICALL void GL_APIENTRY glDepthFunc (GLenum func);
+GL_APICALL void GL_APIENTRY glDepthMask (GLboolean flag);
+GL_APICALL void GL_APIENTRY glDepthRangef (GLclampf zNear, GLclampf zFar);
+GL_APICALL void GL_APIENTRY glDetachShader (GLuint program, GLuint shader);
+GL_APICALL void GL_APIENTRY glDisable (GLenum cap);
+GL_APICALL void GL_APIENTRY glDisableVertexAttribArray (GLuint index);
+GL_APICALL void GL_APIENTRY glDrawArrays (GLenum mode, GLint first, GLsizei count);
+GL_APICALL void GL_APIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const GLvoid* indices);
+GL_APICALL void GL_APIENTRY glEnable (GLenum cap);
+GL_APICALL void GL_APIENTRY glEnableVertexAttribArray (GLuint index);
+GL_APICALL void GL_APIENTRY glFinish (void);
+GL_APICALL void GL_APIENTRY glFlush (void);
+GL_APICALL void GL_APIENTRY glFramebufferRenderbuffer (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+GL_APICALL void GL_APIENTRY glFramebufferTexture2D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+GL_APICALL void GL_APIENTRY glFrontFace (GLenum mode);
+GL_APICALL void GL_APIENTRY glGenBuffers (GLsizei n, GLuint* buffers);
+GL_APICALL void GL_APIENTRY glGenerateMipmap (GLenum target);
+GL_APICALL void GL_APIENTRY glGenFramebuffers (GLsizei n, GLuint* framebuffers);
+GL_APICALL void GL_APIENTRY glGenRenderbuffers (GLsizei n, GLuint* renderbuffers);
+GL_APICALL void GL_APIENTRY glGenTextures (GLsizei n, GLuint* textures);
+GL_APICALL void GL_APIENTRY glGetActiveAttrib (GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name);
+GL_APICALL void GL_APIENTRY glGetActiveUniform (GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name);
+GL_APICALL void GL_APIENTRY glGetAttachedShaders (GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders);
+GL_APICALL GLint GL_APIENTRY glGetAttribLocation (GLuint program, const GLchar* name);
+GL_APICALL void GL_APIENTRY glGetBooleanv (GLenum pname, GLboolean* params);
+GL_APICALL void GL_APIENTRY glGetBufferParameteriv (GLenum target, GLenum pname, GLint* params);
+GL_APICALL GLenum GL_APIENTRY glGetError (void);
+GL_APICALL void GL_APIENTRY glGetFloatv (GLenum pname, GLfloat* params);
+GL_APICALL void GL_APIENTRY glGetFramebufferAttachmentParameteriv (GLenum target, GLenum attachment, GLenum pname, GLint* params);
+GL_APICALL void GL_APIENTRY glGetIntegerv (GLenum pname, GLint* params);
+GL_APICALL void GL_APIENTRY glGetProgramiv (GLuint program, GLenum pname, GLint* params);
+GL_APICALL void GL_APIENTRY glGetProgramInfoLog (GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog);
+GL_APICALL void GL_APIENTRY glGetRenderbufferParameteriv (GLenum target, GLenum pname, GLint* params);
+GL_APICALL void GL_APIENTRY glGetShaderiv (GLuint shader, GLenum pname, GLint* params);
+GL_APICALL void GL_APIENTRY glGetShaderInfoLog (GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog);
+GL_APICALL void GL_APIENTRY glGetShaderPrecisionFormat (GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision);
+GL_APICALL void GL_APIENTRY glGetShaderSource (GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source);
+GL_APICALL const GLubyte* GL_APIENTRY glGetString (GLenum name);
+GL_APICALL void GL_APIENTRY glGetTexParameterfv (GLenum target, GLenum pname, GLfloat* params);
+GL_APICALL void GL_APIENTRY glGetTexParameteriv (GLenum target, GLenum pname, GLint* params);
+GL_APICALL void GL_APIENTRY glGetUniformfv (GLuint program, GLint location, GLfloat* params);
+GL_APICALL void GL_APIENTRY glGetUniformiv (GLuint program, GLint location, GLint* params);
+GL_APICALL GLint GL_APIENTRY glGetUniformLocation (GLuint program, const GLchar* name);
+GL_APICALL void GL_APIENTRY glGetVertexAttribfv (GLuint index, GLenum pname, GLfloat* params);
+GL_APICALL void GL_APIENTRY glGetVertexAttribiv (GLuint index, GLenum pname, GLint* params);
+GL_APICALL void GL_APIENTRY glGetVertexAttribPointerv (GLuint index, GLenum pname, GLvoid** pointer);
+GL_APICALL void GL_APIENTRY glHint (GLenum target, GLenum mode);
+GL_APICALL GLboolean GL_APIENTRY glIsBuffer (GLuint buffer);
+GL_APICALL GLboolean GL_APIENTRY glIsEnabled (GLenum cap);
+GL_APICALL GLboolean GL_APIENTRY glIsFramebuffer (GLuint framebuffer);
+GL_APICALL GLboolean GL_APIENTRY glIsProgram (GLuint program);
+GL_APICALL GLboolean GL_APIENTRY glIsRenderbuffer (GLuint renderbuffer);
+GL_APICALL GLboolean GL_APIENTRY glIsShader (GLuint shader);
+GL_APICALL GLboolean GL_APIENTRY glIsTexture (GLuint texture);
+GL_APICALL void GL_APIENTRY glLineWidth (GLfloat width);
+GL_APICALL void GL_APIENTRY glLinkProgram (GLuint program);
+GL_APICALL void GL_APIENTRY glPixelStorei (GLenum pname, GLint param);
+GL_APICALL void GL_APIENTRY glPolygonOffset (GLfloat factor, GLfloat units);
+GL_APICALL void GL_APIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels);
+GL_APICALL void GL_APIENTRY glReleaseShaderCompiler (void);
+GL_APICALL void GL_APIENTRY glRenderbufferStorage (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glSampleCoverage (GLclampf value, GLboolean invert);
+GL_APICALL void GL_APIENTRY glScissor (GLint x, GLint y, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glShaderBinary (GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length);
+GL_APICALL void GL_APIENTRY glShaderSource (GLuint shader, GLsizei count, const GLchar* const* string, const GLint* length);
+GL_APICALL void GL_APIENTRY glStencilFunc (GLenum func, GLint ref, GLuint mask);
+GL_APICALL void GL_APIENTRY glStencilFuncSeparate (GLenum face, GLenum func, GLint ref, GLuint mask);
+GL_APICALL void GL_APIENTRY glStencilMask (GLuint mask);
+GL_APICALL void GL_APIENTRY glStencilMaskSeparate (GLenum face, GLuint mask);
+GL_APICALL void GL_APIENTRY glStencilOp (GLenum fail, GLenum zfail, GLenum zpass);
+GL_APICALL void GL_APIENTRY glStencilOpSeparate (GLenum face, GLenum fail, GLenum zfail, GLenum zpass);
+GL_APICALL void GL_APIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* pixels);
+GL_APICALL void GL_APIENTRY glTexParameterf (GLenum target, GLenum pname, GLfloat param);
+GL_APICALL void GL_APIENTRY glTexParameterfv (GLenum target, GLenum pname, const GLfloat* params);
+GL_APICALL void GL_APIENTRY glTexParameteri (GLenum target, GLenum pname, GLint param);
+GL_APICALL void GL_APIENTRY glTexParameteriv (GLenum target, GLenum pname, const GLint* params);
+GL_APICALL void GL_APIENTRY glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* pixels);
+GL_APICALL void GL_APIENTRY glUniform1f (GLint location, GLfloat x);
+GL_APICALL void GL_APIENTRY glUniform1fv (GLint location, GLsizei count, const GLfloat* v);
+GL_APICALL void GL_APIENTRY glUniform1i (GLint location, GLint x);
+GL_APICALL void GL_APIENTRY glUniform1iv (GLint location, GLsizei count, const GLint* v);
+GL_APICALL void GL_APIENTRY glUniform2f (GLint location, GLfloat x, GLfloat y);
+GL_APICALL void GL_APIENTRY glUniform2fv (GLint location, GLsizei count, const GLfloat* v);
+GL_APICALL void GL_APIENTRY glUniform2i (GLint location, GLint x, GLint y);
+GL_APICALL void GL_APIENTRY glUniform2iv (GLint location, GLsizei count, const GLint* v);
+GL_APICALL void GL_APIENTRY glUniform3f (GLint location, GLfloat x, GLfloat y, GLfloat z);
+GL_APICALL void GL_APIENTRY glUniform3fv (GLint location, GLsizei count, const GLfloat* v);
+GL_APICALL void GL_APIENTRY glUniform3i (GLint location, GLint x, GLint y, GLint z);
+GL_APICALL void GL_APIENTRY glUniform3iv (GLint location, GLsizei count, const GLint* v);
+GL_APICALL void GL_APIENTRY glUniform4f (GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GL_APICALL void GL_APIENTRY glUniform4fv (GLint location, GLsizei count, const GLfloat* v);
+GL_APICALL void GL_APIENTRY glUniform4i (GLint location, GLint x, GLint y, GLint z, GLint w);
+GL_APICALL void GL_APIENTRY glUniform4iv (GLint location, GLsizei count, const GLint* v);
+GL_APICALL void GL_APIENTRY glUniformMatrix2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+GL_APICALL void GL_APIENTRY glUniformMatrix3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+GL_APICALL void GL_APIENTRY glUniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+GL_APICALL void GL_APIENTRY glUseProgram (GLuint program);
+GL_APICALL void GL_APIENTRY glValidateProgram (GLuint program);
+GL_APICALL void GL_APIENTRY glVertexAttrib1f (GLuint indx, GLfloat x);
+GL_APICALL void GL_APIENTRY glVertexAttrib1fv (GLuint indx, const GLfloat* values);
+GL_APICALL void GL_APIENTRY glVertexAttrib2f (GLuint indx, GLfloat x, GLfloat y);
+GL_APICALL void GL_APIENTRY glVertexAttrib2fv (GLuint indx, const GLfloat* values);
+GL_APICALL void GL_APIENTRY glVertexAttrib3f (GLuint indx, GLfloat x, GLfloat y, GLfloat z);
+GL_APICALL void GL_APIENTRY glVertexAttrib3fv (GLuint indx, const GLfloat* values);
+GL_APICALL void GL_APIENTRY glVertexAttrib4f (GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GL_APICALL void GL_APIENTRY glVertexAttrib4fv (GLuint indx, const GLfloat* values);
+GL_APICALL void GL_APIENTRY glVertexAttribPointer (GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr);
+GL_APICALL void GL_APIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gl2_h_ */
diff --git a/platform/winrt/include/GLES2/gl2ext.h b/platform/winrt/include/GLES2/gl2ext.h
new file mode 100644
index 0000000000..cc6997d4b2
--- /dev/null
+++ b/platform/winrt/include/GLES2/gl2ext.h
@@ -0,0 +1,2013 @@
+#ifndef __gl2ext_h_
+#define __gl2ext_h_
+
+/* $Revision: 20795 $ on $Date:: 2013-03-07 01:01:58 -0800 #$ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * This document is licensed under the SGI Free Software B License Version
+ * 2.0. For details, see http://oss.sgi.com/projects/FreeB/ .
+ */
+
+#ifndef GL_APIENTRYP
+# define GL_APIENTRYP GL_APIENTRY*
+#endif
+
+/*------------------------------------------------------------------------*
+ * OES extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_OES_compressed_ETC1_RGB8_texture */
+#ifndef GL_OES_compressed_ETC1_RGB8_texture
+#define GL_ETC1_RGB8_OES 0x8D64
+#endif
+
+/* GL_OES_compressed_paletted_texture */
+#ifndef GL_OES_compressed_paletted_texture
+#define GL_PALETTE4_RGB8_OES 0x8B90
+#define GL_PALETTE4_RGBA8_OES 0x8B91
+#define GL_PALETTE4_R5_G6_B5_OES 0x8B92
+#define GL_PALETTE4_RGBA4_OES 0x8B93
+#define GL_PALETTE4_RGB5_A1_OES 0x8B94
+#define GL_PALETTE8_RGB8_OES 0x8B95
+#define GL_PALETTE8_RGBA8_OES 0x8B96
+#define GL_PALETTE8_R5_G6_B5_OES 0x8B97
+#define GL_PALETTE8_RGBA4_OES 0x8B98
+#define GL_PALETTE8_RGB5_A1_OES 0x8B99
+#endif
+
+/* GL_OES_depth24 */
+#ifndef GL_OES_depth24
+#define GL_DEPTH_COMPONENT24_OES 0x81A6
+#endif
+
+/* GL_OES_depth32 */
+#ifndef GL_OES_depth32
+#define GL_DEPTH_COMPONENT32_OES 0x81A7
+#endif
+
+/* GL_OES_depth_texture */
+/* No new tokens introduced by this extension. */
+
+/* GL_OES_EGL_image */
+#ifndef GL_OES_EGL_image
+typedef void* GLeglImageOES;
+#endif
+
+/* GL_OES_EGL_image_external */
+#ifndef GL_OES_EGL_image_external
+/* GLeglImageOES defined in GL_OES_EGL_image already. */
+#define GL_TEXTURE_EXTERNAL_OES 0x8D65
+#define GL_SAMPLER_EXTERNAL_OES 0x8D66
+#define GL_TEXTURE_BINDING_EXTERNAL_OES 0x8D67
+#define GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES 0x8D68
+#endif
+
+/* GL_OES_element_index_uint */
+#ifndef GL_OES_element_index_uint
+#define GL_UNSIGNED_INT 0x1405
+#endif
+
+/* GL_OES_get_program_binary */
+#ifndef GL_OES_get_program_binary
+#define GL_PROGRAM_BINARY_LENGTH_OES 0x8741
+#define GL_NUM_PROGRAM_BINARY_FORMATS_OES 0x87FE
+#define GL_PROGRAM_BINARY_FORMATS_OES 0x87FF
+#endif
+
+/* GL_OES_mapbuffer */
+#ifndef GL_OES_mapbuffer
+#define GL_WRITE_ONLY_OES 0x88B9
+#define GL_BUFFER_ACCESS_OES 0x88BB
+#define GL_BUFFER_MAPPED_OES 0x88BC
+#define GL_BUFFER_MAP_POINTER_OES 0x88BD
+#endif
+
+/* GL_OES_packed_depth_stencil */
+#ifndef GL_OES_packed_depth_stencil
+#define GL_DEPTH_STENCIL_OES 0x84F9
+#define GL_UNSIGNED_INT_24_8_OES 0x84FA
+#define GL_DEPTH24_STENCIL8_OES 0x88F0
+#endif
+
+/* GL_OES_required_internalformat */
+#ifndef GL_OES_required_internalformat
+#define GL_ALPHA8_OES 0x803C
+#define GL_DEPTH_COMPONENT16_OES 0x81A5
+/* reuse GL_DEPTH_COMPONENT24_OES */
+/* reuse GL_DEPTH24_STENCIL8_OES */
+/* reuse GL_DEPTH_COMPONENT32_OES */
+#define GL_LUMINANCE4_ALPHA4_OES 0x8043
+#define GL_LUMINANCE8_ALPHA8_OES 0x8045
+#define GL_LUMINANCE8_OES 0x8040
+#define GL_RGBA4_OES 0x8056
+#define GL_RGB5_A1_OES 0x8057
+#define GL_RGB565_OES 0x8D62
+/* reuse GL_RGB8_OES */
+/* reuse GL_RGBA8_OES */
+/* reuse GL_RGB10_EXT */
+/* reuse GL_RGB10_A2_EXT */
+#endif
+
+/* GL_OES_rgb8_rgba8 */
+#ifndef GL_OES_rgb8_rgba8
+#define GL_RGB8_OES 0x8051
+#define GL_RGBA8_OES 0x8058
+#endif
+
+/* GL_OES_standard_derivatives */
+#ifndef GL_OES_standard_derivatives
+#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES 0x8B8B
+#endif
+
+/* GL_OES_stencil1 */
+#ifndef GL_OES_stencil1
+#define GL_STENCIL_INDEX1_OES 0x8D46
+#endif
+
+/* GL_OES_stencil4 */
+#ifndef GL_OES_stencil4
+#define GL_STENCIL_INDEX4_OES 0x8D47
+#endif
+
+#ifndef GL_OES_surfaceless_context
+#define GL_FRAMEBUFFER_UNDEFINED_OES 0x8219
+#endif
+
+/* GL_OES_texture_3D */
+#ifndef GL_OES_texture_3D
+#define GL_TEXTURE_WRAP_R_OES 0x8072
+#define GL_TEXTURE_3D_OES 0x806F
+#define GL_TEXTURE_BINDING_3D_OES 0x806A
+#define GL_MAX_3D_TEXTURE_SIZE_OES 0x8073
+#define GL_SAMPLER_3D_OES 0x8B5F
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_OES 0x8CD4
+#endif
+
+/* GL_OES_texture_float */
+/* No new tokens introduced by this extension. */
+
+/* GL_OES_texture_float_linear */
+/* No new tokens introduced by this extension. */
+
+/* GL_OES_texture_half_float */
+#ifndef GL_OES_texture_half_float
+#define GL_HALF_FLOAT_OES 0x8D61
+#endif
+
+/* GL_OES_texture_half_float_linear */
+/* No new tokens introduced by this extension. */
+
+/* GL_OES_texture_npot */
+/* No new tokens introduced by this extension. */
+
+/* GL_OES_vertex_array_object */
+#ifndef GL_OES_vertex_array_object
+#define GL_VERTEX_ARRAY_BINDING_OES 0x85B5
+#endif
+
+/* GL_OES_vertex_half_float */
+/* GL_HALF_FLOAT_OES defined in GL_OES_texture_half_float already. */
+
+/* GL_OES_vertex_type_10_10_10_2 */
+#ifndef GL_OES_vertex_type_10_10_10_2
+#define GL_UNSIGNED_INT_10_10_10_2_OES 0x8DF6
+#define GL_INT_10_10_10_2_OES 0x8DF7
+#endif
+
+/*------------------------------------------------------------------------*
+ * KHR extension tokens
+ *------------------------------------------------------------------------*/
+
+#ifndef GL_KHR_debug
+typedef void (GL_APIENTRYP GLDEBUGPROC)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,GLvoid *userParam);
+#define GL_DEBUG_OUTPUT_SYNCHRONOUS 0x8242
+#define GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH 0x8243
+#define GL_DEBUG_CALLBACK_FUNCTION 0x8244
+#define GL_DEBUG_CALLBACK_USER_PARAM 0x8245
+#define GL_DEBUG_SOURCE_API 0x8246
+#define GL_DEBUG_SOURCE_WINDOW_SYSTEM 0x8247
+#define GL_DEBUG_SOURCE_SHADER_COMPILER 0x8248
+#define GL_DEBUG_SOURCE_THIRD_PARTY 0x8249
+#define GL_DEBUG_SOURCE_APPLICATION 0x824A
+#define GL_DEBUG_SOURCE_OTHER 0x824B
+#define GL_DEBUG_TYPE_ERROR 0x824C
+#define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR 0x824D
+#define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR 0x824E
+#define GL_DEBUG_TYPE_PORTABILITY 0x824F
+#define GL_DEBUG_TYPE_PERFORMANCE 0x8250
+#define GL_DEBUG_TYPE_OTHER 0x8251
+#define GL_DEBUG_TYPE_MARKER 0x8268
+#define GL_DEBUG_TYPE_PUSH_GROUP 0x8269
+#define GL_DEBUG_TYPE_POP_GROUP 0x826A
+#define GL_DEBUG_SEVERITY_NOTIFICATION 0x826B
+#define GL_MAX_DEBUG_GROUP_STACK_DEPTH 0x826C
+#define GL_DEBUG_GROUP_STACK_DEPTH 0x826D
+#define GL_BUFFER 0x82E0
+#define GL_SHADER 0x82E1
+#define GL_PROGRAM 0x82E2
+#define GL_QUERY 0x82E3
+/* PROGRAM_PIPELINE only in GL */
+#define GL_SAMPLER 0x82E6
+/* DISPLAY_LIST only in GL */
+#define GL_MAX_LABEL_LENGTH 0x82E8
+#define GL_MAX_DEBUG_MESSAGE_LENGTH 0x9143
+#define GL_MAX_DEBUG_LOGGED_MESSAGES 0x9144
+#define GL_DEBUG_LOGGED_MESSAGES 0x9145
+#define GL_DEBUG_SEVERITY_HIGH 0x9146
+#define GL_DEBUG_SEVERITY_MEDIUM 0x9147
+#define GL_DEBUG_SEVERITY_LOW 0x9148
+#define GL_DEBUG_OUTPUT 0x92E0
+#define GL_CONTEXT_FLAG_DEBUG_BIT 0x00000002
+#define GL_STACK_OVERFLOW 0x0503
+#define GL_STACK_UNDERFLOW 0x0504
+#endif
+
+#ifndef GL_KHR_texture_compression_astc_ldr
+#define GL_COMPRESSED_RGBA_ASTC_4x4_KHR 0x93B0
+#define GL_COMPRESSED_RGBA_ASTC_5x4_KHR 0x93B1
+#define GL_COMPRESSED_RGBA_ASTC_5x5_KHR 0x93B2
+#define GL_COMPRESSED_RGBA_ASTC_6x5_KHR 0x93B3
+#define GL_COMPRESSED_RGBA_ASTC_6x6_KHR 0x93B4
+#define GL_COMPRESSED_RGBA_ASTC_8x5_KHR 0x93B5
+#define GL_COMPRESSED_RGBA_ASTC_8x6_KHR 0x93B6
+#define GL_COMPRESSED_RGBA_ASTC_8x8_KHR 0x93B7
+#define GL_COMPRESSED_RGBA_ASTC_10x5_KHR 0x93B8
+#define GL_COMPRESSED_RGBA_ASTC_10x6_KHR 0x93B9
+#define GL_COMPRESSED_RGBA_ASTC_10x8_KHR 0x93BA
+#define GL_COMPRESSED_RGBA_ASTC_10x10_KHR 0x93BB
+#define GL_COMPRESSED_RGBA_ASTC_12x10_KHR 0x93BC
+#define GL_COMPRESSED_RGBA_ASTC_12x12_KHR 0x93BD
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR 0x93D0
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR 0x93D1
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR 0x93D2
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR 0x93D3
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR 0x93D4
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR 0x93D5
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR 0x93D6
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR 0x93D7
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR 0x93D8
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR 0x93D9
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR 0x93DA
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR 0x93DB
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR 0x93DC
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR 0x93DD
+#endif
+
+/*------------------------------------------------------------------------*
+ * AMD extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_AMD_compressed_3DC_texture */
+#ifndef GL_AMD_compressed_3DC_texture
+#define GL_3DC_X_AMD 0x87F9
+#define GL_3DC_XY_AMD 0x87FA
+#endif
+
+/* GL_AMD_compressed_ATC_texture */
+#ifndef GL_AMD_compressed_ATC_texture
+#define GL_ATC_RGB_AMD 0x8C92
+#define GL_ATC_RGBA_EXPLICIT_ALPHA_AMD 0x8C93
+#define GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD 0x87EE
+#endif
+
+/* GL_AMD_performance_monitor */
+#ifndef GL_AMD_performance_monitor
+#define GL_COUNTER_TYPE_AMD 0x8BC0
+#define GL_COUNTER_RANGE_AMD 0x8BC1
+#define GL_UNSIGNED_INT64_AMD 0x8BC2
+#define GL_PERCENTAGE_AMD 0x8BC3
+#define GL_PERFMON_RESULT_AVAILABLE_AMD 0x8BC4
+#define GL_PERFMON_RESULT_SIZE_AMD 0x8BC5
+#define GL_PERFMON_RESULT_AMD 0x8BC6
+#endif
+
+/* GL_AMD_program_binary_Z400 */
+#ifndef GL_AMD_program_binary_Z400
+#define GL_Z400_BINARY_AMD 0x8740
+#endif
+
+/*------------------------------------------------------------------------*
+ * ANGLE extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_ANGLE_depth_texture */
+#ifndef GL_ANGLE_depth_texture
+#define GL_DEPTH_COMPONENT 0x1902
+#define GL_DEPTH_STENCIL_OES 0x84F9
+#define GL_UNSIGNED_SHORT 0x1403
+#define GL_UNSIGNED_INT 0x1405
+#define GL_UNSIGNED_INT_24_8_OES 0x84FA
+#define GL_DEPTH_COMPONENT16 0x81A5
+#define GL_DEPTH_COMPONENT32_OES 0x81A7
+#define GL_DEPTH24_STENCIL8_OES 0x88F0
+#endif
+
+/* GL_ANGLE_framebuffer_blit */
+#ifndef GL_ANGLE_framebuffer_blit
+#define GL_READ_FRAMEBUFFER_ANGLE 0x8CA8
+#define GL_DRAW_FRAMEBUFFER_ANGLE 0x8CA9
+#define GL_DRAW_FRAMEBUFFER_BINDING_ANGLE 0x8CA6
+#define GL_READ_FRAMEBUFFER_BINDING_ANGLE 0x8CAA
+#endif
+
+/* GL_ANGLE_framebuffer_multisample */
+#ifndef GL_ANGLE_framebuffer_multisample
+#define GL_RENDERBUFFER_SAMPLES_ANGLE 0x8CAB
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE 0x8D56
+#define GL_MAX_SAMPLES_ANGLE 0x8D57
+#endif
+
+/* GL_ANGLE_instanced_arrays */
+#ifndef GL_ANGLE_instanced_arrays
+#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE 0x88FE
+#endif
+
+/* GL_ANGLE_pack_reverse_row_order */
+#ifndef GL_ANGLE_pack_reverse_row_order
+#define GL_PACK_REVERSE_ROW_ORDER_ANGLE 0x93A4
+#endif
+
+/* GL_ANGLE_program_binary */
+#ifndef GL_ANGLE_program_binary
+#define GL_PROGRAM_BINARY_ANGLE 0x93A6
+#endif
+
+/* GL_ANGLE_texture_compression_dxt3 */
+#ifndef GL_ANGLE_texture_compression_dxt3
+#define GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE 0x83F2
+#endif
+
+/* GL_ANGLE_texture_compression_dxt5 */
+#ifndef GL_ANGLE_texture_compression_dxt5
+#define GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE 0x83F3
+#endif
+
+/* GL_ANGLE_texture_usage */
+#ifndef GL_ANGLE_texture_usage
+#define GL_TEXTURE_USAGE_ANGLE 0x93A2
+#define GL_FRAMEBUFFER_ATTACHMENT_ANGLE 0x93A3
+#endif
+
+/* GL_ANGLE_translated_shader_source */
+#ifndef GL_ANGLE_translated_shader_source
+#define GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE 0x93A0
+#endif
+
+/*------------------------------------------------------------------------*
+ * APPLE extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_APPLE_copy_texture_levels */
+/* No new tokens introduced by this extension. */
+
+/* GL_APPLE_framebuffer_multisample */
+#ifndef GL_APPLE_framebuffer_multisample
+#define GL_RENDERBUFFER_SAMPLES_APPLE 0x8CAB
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_APPLE 0x8D56
+#define GL_MAX_SAMPLES_APPLE 0x8D57
+#define GL_READ_FRAMEBUFFER_APPLE 0x8CA8
+#define GL_DRAW_FRAMEBUFFER_APPLE 0x8CA9
+#define GL_DRAW_FRAMEBUFFER_BINDING_APPLE 0x8CA6
+#define GL_READ_FRAMEBUFFER_BINDING_APPLE 0x8CAA
+#endif
+
+/* GL_APPLE_rgb_422 */
+#ifndef GL_APPLE_rgb_422
+#define GL_RGB_422_APPLE 0x8A1F
+#define GL_UNSIGNED_SHORT_8_8_APPLE 0x85BA
+#define GL_UNSIGNED_SHORT_8_8_REV_APPLE 0x85BB
+#endif
+
+/* GL_APPLE_sync */
+#ifndef GL_APPLE_sync
+
+#ifndef __gl3_h_
+/* These types are defined with reference to <inttypes.h>
+ * in the Apple extension spec, but here we use the Khronos
+ * portable types in khrplatform.h, and assume those types
+ * are always defined.
+ * If any other extensions using these types are defined,
+ * the typedefs must move out of this block and be shared.
+ */
+typedef khronos_int64_t GLint64;
+typedef khronos_uint64_t GLuint64;
+typedef struct __GLsync *GLsync;
+#endif
+
+#define GL_SYNC_OBJECT_APPLE 0x8A53
+#define GL_MAX_SERVER_WAIT_TIMEOUT_APPLE 0x9111
+#define GL_OBJECT_TYPE_APPLE 0x9112
+#define GL_SYNC_CONDITION_APPLE 0x9113
+#define GL_SYNC_STATUS_APPLE 0x9114
+#define GL_SYNC_FLAGS_APPLE 0x9115
+#define GL_SYNC_FENCE_APPLE 0x9116
+#define GL_SYNC_GPU_COMMANDS_COMPLETE_APPLE 0x9117
+#define GL_UNSIGNALED_APPLE 0x9118
+#define GL_SIGNALED_APPLE 0x9119
+#define GL_ALREADY_SIGNALED_APPLE 0x911A
+#define GL_TIMEOUT_EXPIRED_APPLE 0x911B
+#define GL_CONDITION_SATISFIED_APPLE 0x911C
+#define GL_WAIT_FAILED_APPLE 0x911D
+#define GL_SYNC_FLUSH_COMMANDS_BIT_APPLE 0x00000001
+#define GL_TIMEOUT_IGNORED_APPLE 0xFFFFFFFFFFFFFFFFull
+#endif
+
+/* GL_APPLE_texture_format_BGRA8888 */
+#ifndef GL_APPLE_texture_format_BGRA8888
+#define GL_BGRA_EXT 0x80E1
+#endif
+
+/* GL_APPLE_texture_max_level */
+#ifndef GL_APPLE_texture_max_level
+#define GL_TEXTURE_MAX_LEVEL_APPLE 0x813D
+#endif
+
+/*------------------------------------------------------------------------*
+ * ARM extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_ARM_mali_program_binary */
+#ifndef GL_ARM_mali_program_binary
+#define GL_MALI_PROGRAM_BINARY_ARM 0x8F61
+#endif
+
+/* GL_ARM_mali_shader_binary */
+#ifndef GL_ARM_mali_shader_binary
+#define GL_MALI_SHADER_BINARY_ARM 0x8F60
+#endif
+
+/* GL_ARM_rgba8 */
+/* No new tokens introduced by this extension. */
+
+/*------------------------------------------------------------------------*
+ * EXT extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_EXT_blend_minmax */
+#ifndef GL_EXT_blend_minmax
+#define GL_MIN_EXT 0x8007
+#define GL_MAX_EXT 0x8008
+#endif
+
+/* GL_EXT_color_buffer_half_float */
+#ifndef GL_EXT_color_buffer_half_float
+#define GL_RGBA16F_EXT 0x881A
+#define GL_RGB16F_EXT 0x881B
+#define GL_RG16F_EXT 0x822F
+#define GL_R16F_EXT 0x822D
+#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE_EXT 0x8211
+#define GL_UNSIGNED_NORMALIZED_EXT 0x8C17
+#endif
+
+/* GL_EXT_debug_label */
+#ifndef GL_EXT_debug_label
+#define GL_PROGRAM_PIPELINE_OBJECT_EXT 0x8A4F
+#define GL_PROGRAM_OBJECT_EXT 0x8B40
+#define GL_SHADER_OBJECT_EXT 0x8B48
+#define GL_BUFFER_OBJECT_EXT 0x9151
+#define GL_QUERY_OBJECT_EXT 0x9153
+#define GL_VERTEX_ARRAY_OBJECT_EXT 0x9154
+#endif
+
+/* GL_EXT_debug_marker */
+/* No new tokens introduced by this extension. */
+
+/* GL_EXT_discard_framebuffer */
+#ifndef GL_EXT_discard_framebuffer
+#define GL_COLOR_EXT 0x1800
+#define GL_DEPTH_EXT 0x1801
+#define GL_STENCIL_EXT 0x1802
+#endif
+
+/* GL_EXT_map_buffer_range */
+#ifndef GL_EXT_map_buffer_range
+#define GL_MAP_READ_BIT_EXT 0x0001
+#define GL_MAP_WRITE_BIT_EXT 0x0002
+#define GL_MAP_INVALIDATE_RANGE_BIT_EXT 0x0004
+#define GL_MAP_INVALIDATE_BUFFER_BIT_EXT 0x0008
+#define GL_MAP_FLUSH_EXPLICIT_BIT_EXT 0x0010
+#define GL_MAP_UNSYNCHRONIZED_BIT_EXT 0x0020
+#endif
+
+/* GL_EXT_multisampled_render_to_texture */
+#ifndef GL_EXT_multisampled_render_to_texture
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT 0x8D6C
+/* reuse values from GL_EXT_framebuffer_multisample (desktop extension) */
+#define GL_RENDERBUFFER_SAMPLES_EXT 0x8CAB
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT 0x8D56
+#define GL_MAX_SAMPLES_EXT 0x8D57
+#endif
+
+/* GL_EXT_multiview_draw_buffers */
+#ifndef GL_EXT_multiview_draw_buffers
+#define GL_COLOR_ATTACHMENT_EXT 0x90F0
+#define GL_MULTIVIEW_EXT 0x90F1
+#define GL_DRAW_BUFFER_EXT 0x0C01
+#define GL_READ_BUFFER_EXT 0x0C02
+#define GL_MAX_MULTIVIEW_BUFFERS_EXT 0x90F2
+#endif
+
+/* GL_EXT_multi_draw_arrays */
+/* No new tokens introduced by this extension. */
+
+/* GL_EXT_occlusion_query_boolean */
+#ifndef GL_EXT_occlusion_query_boolean
+#define GL_ANY_SAMPLES_PASSED_EXT 0x8C2F
+#define GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT 0x8D6A
+#define GL_CURRENT_QUERY_EXT 0x8865
+#define GL_QUERY_RESULT_EXT 0x8866
+#define GL_QUERY_RESULT_AVAILABLE_EXT 0x8867
+#endif
+
+/* GL_EXT_read_format_bgra */
+#ifndef GL_EXT_read_format_bgra
+#define GL_BGRA_EXT 0x80E1
+#define GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT 0x8365
+#define GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT 0x8366
+#endif
+
+/* GL_EXT_robustness */
+#ifndef GL_EXT_robustness
+/* reuse GL_NO_ERROR */
+#define GL_GUILTY_CONTEXT_RESET_EXT 0x8253
+#define GL_INNOCENT_CONTEXT_RESET_EXT 0x8254
+#define GL_UNKNOWN_CONTEXT_RESET_EXT 0x8255
+#define GL_CONTEXT_ROBUST_ACCESS_EXT 0x90F3
+#define GL_RESET_NOTIFICATION_STRATEGY_EXT 0x8256
+#define GL_LOSE_CONTEXT_ON_RESET_EXT 0x8252
+#define GL_NO_RESET_NOTIFICATION_EXT 0x8261
+#endif
+
+/* GL_EXT_separate_shader_objects */
+#ifndef GL_EXT_separate_shader_objects
+#define GL_VERTEX_SHADER_BIT_EXT 0x00000001
+#define GL_FRAGMENT_SHADER_BIT_EXT 0x00000002
+#define GL_ALL_SHADER_BITS_EXT 0xFFFFFFFF
+#define GL_PROGRAM_SEPARABLE_EXT 0x8258
+#define GL_ACTIVE_PROGRAM_EXT 0x8259
+#define GL_PROGRAM_PIPELINE_BINDING_EXT 0x825A
+#endif
+
+/* GL_EXT_shader_framebuffer_fetch */
+#ifndef GL_EXT_shader_framebuffer_fetch
+#define GL_FRAGMENT_SHADER_DISCARDS_SAMPLES_EXT 0x8A52
+#endif
+
+/* GL_EXT_shader_texture_lod */
+/* No new tokens introduced by this extension. */
+
+/* GL_EXT_shadow_samplers */
+#ifndef GL_EXT_shadow_samplers
+#define GL_TEXTURE_COMPARE_MODE_EXT 0x884C
+#define GL_TEXTURE_COMPARE_FUNC_EXT 0x884D
+#define GL_COMPARE_REF_TO_TEXTURE_EXT 0x884E
+#define GL_SAMPLER_2D_SHADOW_EXT 0x8B62
+#endif
+
+/* GL_EXT_sRGB */
+#ifndef GL_EXT_sRGB
+#define GL_SRGB_EXT 0x8C40
+#define GL_SRGB_ALPHA_EXT 0x8C42
+#define GL_SRGB8_ALPHA8_EXT 0x8C43
+#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT 0x8210
+#endif
+
+/* GL_EXT_texture_compression_dxt1 */
+#ifndef GL_EXT_texture_compression_dxt1
+#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0
+#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1
+#endif
+
+/* GL_EXT_texture_filter_anisotropic */
+#ifndef GL_EXT_texture_filter_anisotropic
+#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE
+#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF
+#endif
+
+/* GL_EXT_texture_format_BGRA8888 */
+#ifndef GL_EXT_texture_format_BGRA8888
+#define GL_BGRA_EXT 0x80E1
+#endif
+
+/* GL_EXT_texture_rg */
+#ifndef GL_EXT_texture_rg
+#define GL_RED_EXT 0x1903
+#define GL_RG_EXT 0x8227
+#define GL_R8_EXT 0x8229
+#define GL_RG8_EXT 0x822B
+#endif
+
+/* GL_EXT_texture_storage */
+#ifndef GL_EXT_texture_storage
+#define GL_TEXTURE_IMMUTABLE_FORMAT_EXT 0x912F
+#define GL_ALPHA8_EXT 0x803C
+#define GL_LUMINANCE8_EXT 0x8040
+#define GL_LUMINANCE8_ALPHA8_EXT 0x8045
+#define GL_RGBA32F_EXT 0x8814
+#define GL_RGB32F_EXT 0x8815
+#define GL_ALPHA32F_EXT 0x8816
+#define GL_LUMINANCE32F_EXT 0x8818
+#define GL_LUMINANCE_ALPHA32F_EXT 0x8819
+/* reuse GL_RGBA16F_EXT */
+/* reuse GL_RGB16F_EXT */
+#define GL_ALPHA16F_EXT 0x881C
+#define GL_LUMINANCE16F_EXT 0x881E
+#define GL_LUMINANCE_ALPHA16F_EXT 0x881F
+#define GL_RGB10_A2_EXT 0x8059
+#define GL_RGB10_EXT 0x8052
+#define GL_BGRA8_EXT 0x93A1
+#define GL_R8_EXT 0x8229
+#define GL_RG8_EXT 0x822B
+#define GL_R32F_EXT 0x822E
+#define GL_RG32F_EXT 0x8230
+#define GL_R16F_EXT 0x822D
+#define GL_RG16F_EXT 0x822F
+#endif
+
+/* GL_EXT_texture_type_2_10_10_10_REV */
+#ifndef GL_EXT_texture_type_2_10_10_10_REV
+#define GL_UNSIGNED_INT_2_10_10_10_REV_EXT 0x8368
+#endif
+
+/* GL_EXT_unpack_subimage */
+#ifndef GL_EXT_unpack_subimage
+#define GL_UNPACK_ROW_LENGTH_EXT 0x0CF2
+#define GL_UNPACK_SKIP_ROWS_EXT 0x0CF3
+#define GL_UNPACK_SKIP_PIXELS_EXT 0x0CF4
+#endif
+
+/*------------------------------------------------------------------------*
+ * DMP extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_DMP_shader_binary */
+#ifndef GL_DMP_shader_binary
+#define GL_SHADER_BINARY_DMP 0x9250
+#endif
+
+/*------------------------------------------------------------------------*
+ * FJ extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_FJ_shader_binary_GCCSO */
+#ifndef GL_FJ_shader_binary_GCCSO
+#define GL_GCCSO_SHADER_BINARY_F 0x9260
+#endif
+
+/*------------------------------------------------------------------------*
+ * IMG extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_IMG_program_binary */
+#ifndef GL_IMG_program_binary
+#define GL_SGX_PROGRAM_BINARY_IMG 0x9130
+#endif
+
+/* GL_IMG_read_format */
+#ifndef GL_IMG_read_format
+#define GL_BGRA_IMG 0x80E1
+#define GL_UNSIGNED_SHORT_4_4_4_4_REV_IMG 0x8365
+#endif
+
+/* GL_IMG_shader_binary */
+#ifndef GL_IMG_shader_binary
+#define GL_SGX_BINARY_IMG 0x8C0A
+#endif
+
+/* GL_IMG_texture_compression_pvrtc */
+#ifndef GL_IMG_texture_compression_pvrtc
+#define GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG 0x8C00
+#define GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG 0x8C01
+#define GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG 0x8C02
+#define GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG 0x8C03
+#endif
+
+/* GL_IMG_texture_compression_pvrtc2 */
+#ifndef GL_IMG_texture_compression_pvrtc2
+#define GL_COMPRESSED_RGBA_PVRTC_2BPPV2_IMG 0x9137
+#define GL_COMPRESSED_RGBA_PVRTC_4BPPV2_IMG 0x9138
+#endif
+
+/* GL_IMG_multisampled_render_to_texture */
+#ifndef GL_IMG_multisampled_render_to_texture
+#define GL_RENDERBUFFER_SAMPLES_IMG 0x9133
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_IMG 0x9134
+#define GL_MAX_SAMPLES_IMG 0x9135
+#define GL_TEXTURE_SAMPLES_IMG 0x9136
+#endif
+
+/*------------------------------------------------------------------------*
+ * NV extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_NV_coverage_sample */
+#ifndef GL_NV_coverage_sample
+#define GL_COVERAGE_COMPONENT_NV 0x8ED0
+#define GL_COVERAGE_COMPONENT4_NV 0x8ED1
+#define GL_COVERAGE_ATTACHMENT_NV 0x8ED2
+#define GL_COVERAGE_BUFFERS_NV 0x8ED3
+#define GL_COVERAGE_SAMPLES_NV 0x8ED4
+#define GL_COVERAGE_ALL_FRAGMENTS_NV 0x8ED5
+#define GL_COVERAGE_EDGE_FRAGMENTS_NV 0x8ED6
+#define GL_COVERAGE_AUTOMATIC_NV 0x8ED7
+#define GL_COVERAGE_BUFFER_BIT_NV 0x8000
+#endif
+
+/* GL_NV_depth_nonlinear */
+#ifndef GL_NV_depth_nonlinear
+#define GL_DEPTH_COMPONENT16_NONLINEAR_NV 0x8E2C
+#endif
+
+/* GL_NV_draw_buffers */
+#ifndef GL_NV_draw_buffers
+#define GL_MAX_DRAW_BUFFERS_NV 0x8824
+#define GL_DRAW_BUFFER0_NV 0x8825
+#define GL_DRAW_BUFFER1_NV 0x8826
+#define GL_DRAW_BUFFER2_NV 0x8827
+#define GL_DRAW_BUFFER3_NV 0x8828
+#define GL_DRAW_BUFFER4_NV 0x8829
+#define GL_DRAW_BUFFER5_NV 0x882A
+#define GL_DRAW_BUFFER6_NV 0x882B
+#define GL_DRAW_BUFFER7_NV 0x882C
+#define GL_DRAW_BUFFER8_NV 0x882D
+#define GL_DRAW_BUFFER9_NV 0x882E
+#define GL_DRAW_BUFFER10_NV 0x882F
+#define GL_DRAW_BUFFER11_NV 0x8830
+#define GL_DRAW_BUFFER12_NV 0x8831
+#define GL_DRAW_BUFFER13_NV 0x8832
+#define GL_DRAW_BUFFER14_NV 0x8833
+#define GL_DRAW_BUFFER15_NV 0x8834
+#define GL_COLOR_ATTACHMENT0_NV 0x8CE0
+#define GL_COLOR_ATTACHMENT1_NV 0x8CE1
+#define GL_COLOR_ATTACHMENT2_NV 0x8CE2
+#define GL_COLOR_ATTACHMENT3_NV 0x8CE3
+#define GL_COLOR_ATTACHMENT4_NV 0x8CE4
+#define GL_COLOR_ATTACHMENT5_NV 0x8CE5
+#define GL_COLOR_ATTACHMENT6_NV 0x8CE6
+#define GL_COLOR_ATTACHMENT7_NV 0x8CE7
+#define GL_COLOR_ATTACHMENT8_NV 0x8CE8
+#define GL_COLOR_ATTACHMENT9_NV 0x8CE9
+#define GL_COLOR_ATTACHMENT10_NV 0x8CEA
+#define GL_COLOR_ATTACHMENT11_NV 0x8CEB
+#define GL_COLOR_ATTACHMENT12_NV 0x8CEC
+#define GL_COLOR_ATTACHMENT13_NV 0x8CED
+#define GL_COLOR_ATTACHMENT14_NV 0x8CEE
+#define GL_COLOR_ATTACHMENT15_NV 0x8CEF
+#endif
+
+/* GL_EXT_draw_buffers */
+#ifndef GL_EXT_draw_buffers
+#define GL_MAX_DRAW_BUFFERS_EXT 0x8824
+#define GL_DRAW_BUFFER0_EXT 0x8825
+#define GL_DRAW_BUFFER1_EXT 0x8826
+#define GL_DRAW_BUFFER2_EXT 0x8827
+#define GL_DRAW_BUFFER3_EXT 0x8828
+#define GL_DRAW_BUFFER4_EXT 0x8829
+#define GL_DRAW_BUFFER5_EXT 0x882A
+#define GL_DRAW_BUFFER6_EXT 0x882B
+#define GL_DRAW_BUFFER7_EXT 0x882C
+#define GL_DRAW_BUFFER8_EXT 0x882D
+#define GL_DRAW_BUFFER9_EXT 0x882E
+#define GL_DRAW_BUFFER10_EXT 0x882F
+#define GL_DRAW_BUFFER11_EXT 0x8830
+#define GL_DRAW_BUFFER12_EXT 0x8831
+#define GL_DRAW_BUFFER13_EXT 0x8832
+#define GL_DRAW_BUFFER14_EXT 0x8833
+#define GL_DRAW_BUFFER15_EXT 0x8834
+#define GL_COLOR_ATTACHMENT0_EXT 0x8CE0
+#define GL_COLOR_ATTACHMENT1_EXT 0x8CE1
+#define GL_COLOR_ATTACHMENT2_EXT 0x8CE2
+#define GL_COLOR_ATTACHMENT3_EXT 0x8CE3
+#define GL_COLOR_ATTACHMENT4_EXT 0x8CE4
+#define GL_COLOR_ATTACHMENT5_EXT 0x8CE5
+#define GL_COLOR_ATTACHMENT6_EXT 0x8CE6
+#define GL_COLOR_ATTACHMENT7_EXT 0x8CE7
+#define GL_COLOR_ATTACHMENT8_EXT 0x8CE8
+#define GL_COLOR_ATTACHMENT9_EXT 0x8CE9
+#define GL_COLOR_ATTACHMENT10_EXT 0x8CEA
+#define GL_COLOR_ATTACHMENT11_EXT 0x8CEB
+#define GL_COLOR_ATTACHMENT12_EXT 0x8CEC
+#define GL_COLOR_ATTACHMENT13_EXT 0x8CED
+#define GL_COLOR_ATTACHMENT14_EXT 0x8CEE
+#define GL_COLOR_ATTACHMENT15_EXT 0x8CEF
+#define GL_MAX_COLOR_ATTACHMENTS_EXT 0x8CDF
+#endif
+
+/* GL_NV_draw_instanced */
+/* No new tokens introduced by this extension. */
+
+/* GL_NV_fbo_color_attachments */
+#ifndef GL_NV_fbo_color_attachments
+#define GL_MAX_COLOR_ATTACHMENTS_NV 0x8CDF
+/* GL_COLOR_ATTACHMENT{0-15}_NV defined in GL_NV_draw_buffers already. */
+#endif
+
+/* GL_NV_fence */
+#ifndef GL_NV_fence
+#define GL_ALL_COMPLETED_NV 0x84F2
+#define GL_FENCE_STATUS_NV 0x84F3
+#define GL_FENCE_CONDITION_NV 0x84F4
+#endif
+
+/* GL_NV_framebuffer_blit */
+#ifndef GL_NV_framebuffer_blit
+#define GL_READ_FRAMEBUFFER_NV 0x8CA8
+#define GL_DRAW_FRAMEBUFFER_NV 0x8CA9
+#define GL_DRAW_FRAMEBUFFER_BINDING_NV 0x8CA6
+#define GL_READ_FRAMEBUFFER_BINDING_NV 0x8CAA
+#endif
+
+/* GL_NV_framebuffer_multisample */
+#ifndef GL_NV_framebuffer_multisample
+#define GL_RENDERBUFFER_SAMPLES_NV 0x8CAB
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_NV 0x8D56
+#define GL_MAX_SAMPLES_NV 0x8D57
+#endif
+
+/* GL_NV_generate_mipmap_sRGB */
+/* No new tokens introduced by this extension. */
+
+/* GL_NV_instanced_arrays */
+#ifndef GL_NV_instanced_arrays
+#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR_NV 0x88FE
+#endif
+
+/* GL_NV_read_buffer */
+#ifndef GL_NV_read_buffer
+#define GL_READ_BUFFER_NV 0x0C02
+#endif
+
+/* GL_NV_read_buffer_front */
+/* No new tokens introduced by this extension. */
+
+/* GL_NV_read_depth */
+/* No new tokens introduced by this extension. */
+
+/* GL_NV_read_depth_stencil */
+/* No new tokens introduced by this extension. */
+
+/* GL_NV_read_stencil */
+/* No new tokens introduced by this extension. */
+
+/* GL_NV_shadow_samplers_array */
+#ifndef GL_NV_shadow_samplers_array
+#define GL_SAMPLER_2D_ARRAY_SHADOW_NV 0x8DC4
+#endif
+
+/* GL_NV_shadow_samplers_cube */
+#ifndef GL_NV_shadow_samplers_cube
+#define GL_SAMPLER_CUBE_SHADOW_NV 0x8DC5
+#endif
+
+/* GL_NV_sRGB_formats */
+#ifndef GL_NV_sRGB_formats
+#define GL_SLUMINANCE_NV 0x8C46
+#define GL_SLUMINANCE_ALPHA_NV 0x8C44
+#define GL_SRGB8_NV 0x8C41
+#define GL_SLUMINANCE8_NV 0x8C47
+#define GL_SLUMINANCE8_ALPHA8_NV 0x8C45
+#define GL_COMPRESSED_SRGB_S3TC_DXT1_NV 0x8C4C
+#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_NV 0x8C4D
+#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_NV 0x8C4E
+#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_NV 0x8C4F
+#define GL_ETC1_SRGB8_NV 0x88EE
+#endif
+
+/* GL_NV_texture_border_clamp */
+#ifndef GL_NV_texture_border_clamp
+#define GL_TEXTURE_BORDER_COLOR_NV 0x1004
+#define GL_CLAMP_TO_BORDER_NV 0x812D
+#endif
+
+/* GL_NV_texture_compression_s3tc_update */
+/* No new tokens introduced by this extension. */
+
+/* GL_NV_texture_npot_2D_mipmap */
+/* No new tokens introduced by this extension. */
+
+/*------------------------------------------------------------------------*
+ * QCOM extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_QCOM_alpha_test */
+#ifndef GL_QCOM_alpha_test
+#define GL_ALPHA_TEST_QCOM 0x0BC0
+#define GL_ALPHA_TEST_FUNC_QCOM 0x0BC1
+#define GL_ALPHA_TEST_REF_QCOM 0x0BC2
+#endif
+
+/* GL_QCOM_binning_control */
+#ifndef GL_QCOM_binning_control
+#define GL_BINNING_CONTROL_HINT_QCOM 0x8FB0
+#define GL_CPU_OPTIMIZED_QCOM 0x8FB1
+#define GL_GPU_OPTIMIZED_QCOM 0x8FB2
+#define GL_RENDER_DIRECT_TO_FRAMEBUFFER_QCOM 0x8FB3
+#endif
+
+/* GL_QCOM_driver_control */
+/* No new tokens introduced by this extension. */
+
+/* GL_QCOM_extended_get */
+#ifndef GL_QCOM_extended_get
+#define GL_TEXTURE_WIDTH_QCOM 0x8BD2
+#define GL_TEXTURE_HEIGHT_QCOM 0x8BD3
+#define GL_TEXTURE_DEPTH_QCOM 0x8BD4
+#define GL_TEXTURE_INTERNAL_FORMAT_QCOM 0x8BD5
+#define GL_TEXTURE_FORMAT_QCOM 0x8BD6
+#define GL_TEXTURE_TYPE_QCOM 0x8BD7
+#define GL_TEXTURE_IMAGE_VALID_QCOM 0x8BD8
+#define GL_TEXTURE_NUM_LEVELS_QCOM 0x8BD9
+#define GL_TEXTURE_TARGET_QCOM 0x8BDA
+#define GL_TEXTURE_OBJECT_VALID_QCOM 0x8BDB
+#define GL_STATE_RESTORE 0x8BDC
+#endif
+
+/* GL_QCOM_extended_get2 */
+/* No new tokens introduced by this extension. */
+
+/* GL_QCOM_perfmon_global_mode */
+#ifndef GL_QCOM_perfmon_global_mode
+#define GL_PERFMON_GLOBAL_MODE_QCOM 0x8FA0
+#endif
+
+/* GL_QCOM_writeonly_rendering */
+#ifndef GL_QCOM_writeonly_rendering
+#define GL_WRITEONLY_RENDERING_QCOM 0x8823
+#endif
+
+/* GL_QCOM_tiled_rendering */
+#ifndef GL_QCOM_tiled_rendering
+#define GL_COLOR_BUFFER_BIT0_QCOM 0x00000001
+#define GL_COLOR_BUFFER_BIT1_QCOM 0x00000002
+#define GL_COLOR_BUFFER_BIT2_QCOM 0x00000004
+#define GL_COLOR_BUFFER_BIT3_QCOM 0x00000008
+#define GL_COLOR_BUFFER_BIT4_QCOM 0x00000010
+#define GL_COLOR_BUFFER_BIT5_QCOM 0x00000020
+#define GL_COLOR_BUFFER_BIT6_QCOM 0x00000040
+#define GL_COLOR_BUFFER_BIT7_QCOM 0x00000080
+#define GL_DEPTH_BUFFER_BIT0_QCOM 0x00000100
+#define GL_DEPTH_BUFFER_BIT1_QCOM 0x00000200
+#define GL_DEPTH_BUFFER_BIT2_QCOM 0x00000400
+#define GL_DEPTH_BUFFER_BIT3_QCOM 0x00000800
+#define GL_DEPTH_BUFFER_BIT4_QCOM 0x00001000
+#define GL_DEPTH_BUFFER_BIT5_QCOM 0x00002000
+#define GL_DEPTH_BUFFER_BIT6_QCOM 0x00004000
+#define GL_DEPTH_BUFFER_BIT7_QCOM 0x00008000
+#define GL_STENCIL_BUFFER_BIT0_QCOM 0x00010000
+#define GL_STENCIL_BUFFER_BIT1_QCOM 0x00020000
+#define GL_STENCIL_BUFFER_BIT2_QCOM 0x00040000
+#define GL_STENCIL_BUFFER_BIT3_QCOM 0x00080000
+#define GL_STENCIL_BUFFER_BIT4_QCOM 0x00100000
+#define GL_STENCIL_BUFFER_BIT5_QCOM 0x00200000
+#define GL_STENCIL_BUFFER_BIT6_QCOM 0x00400000
+#define GL_STENCIL_BUFFER_BIT7_QCOM 0x00800000
+#define GL_MULTISAMPLE_BUFFER_BIT0_QCOM 0x01000000
+#define GL_MULTISAMPLE_BUFFER_BIT1_QCOM 0x02000000
+#define GL_MULTISAMPLE_BUFFER_BIT2_QCOM 0x04000000
+#define GL_MULTISAMPLE_BUFFER_BIT3_QCOM 0x08000000
+#define GL_MULTISAMPLE_BUFFER_BIT4_QCOM 0x10000000
+#define GL_MULTISAMPLE_BUFFER_BIT5_QCOM 0x20000000
+#define GL_MULTISAMPLE_BUFFER_BIT6_QCOM 0x40000000
+#define GL_MULTISAMPLE_BUFFER_BIT7_QCOM 0x80000000
+#endif
+
+/*------------------------------------------------------------------------*
+ * VIV extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_VIV_shader_binary */
+#ifndef GL_VIV_shader_binary
+#define GL_SHADER_BINARY_VIV 0x8FC4
+#endif
+
+/*------------------------------------------------------------------------*
+ * End of extension tokens, start of corresponding extension functions
+ *------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------*
+ * OES extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_OES_compressed_ETC1_RGB8_texture */
+#ifndef GL_OES_compressed_ETC1_RGB8_texture
+#define GL_OES_compressed_ETC1_RGB8_texture 1
+#endif
+
+/* GL_OES_compressed_paletted_texture */
+#ifndef GL_OES_compressed_paletted_texture
+#define GL_OES_compressed_paletted_texture 1
+#endif
+
+/* GL_OES_depth24 */
+#ifndef GL_OES_depth24
+#define GL_OES_depth24 1
+#endif
+
+/* GL_OES_depth32 */
+#ifndef GL_OES_depth32
+#define GL_OES_depth32 1
+#endif
+
+/* GL_OES_depth_texture */
+#ifndef GL_OES_depth_texture
+#define GL_OES_depth_texture 1
+#endif
+
+/* GL_OES_EGL_image */
+#ifndef GL_OES_EGL_image
+#define GL_OES_EGL_image 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glEGLImageTargetTexture2DOES (GLenum target, GLeglImageOES image);
+GL_APICALL void GL_APIENTRY glEGLImageTargetRenderbufferStorageOES (GLenum target, GLeglImageOES image);
+#endif
+typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) (GLenum target, GLeglImageOES image);
+typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC) (GLenum target, GLeglImageOES image);
+#endif
+
+/* GL_OES_EGL_image_external */
+#ifndef GL_OES_EGL_image_external
+#define GL_OES_EGL_image_external 1
+/* glEGLImageTargetTexture2DOES defined in GL_OES_EGL_image already. */
+#endif
+
+/* GL_OES_element_index_uint */
+#ifndef GL_OES_element_index_uint
+#define GL_OES_element_index_uint 1
+#endif
+
+/* GL_OES_fbo_render_mipmap */
+#ifndef GL_OES_fbo_render_mipmap
+#define GL_OES_fbo_render_mipmap 1
+#endif
+
+/* GL_OES_fragment_precision_high */
+#ifndef GL_OES_fragment_precision_high
+#define GL_OES_fragment_precision_high 1
+#endif
+
+/* GL_OES_get_program_binary */
+#ifndef GL_OES_get_program_binary
+#define GL_OES_get_program_binary 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glGetProgramBinaryOES (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, GLvoid *binary);
+GL_APICALL void GL_APIENTRY glProgramBinaryOES (GLuint program, GLenum binaryFormat, const GLvoid *binary, GLint length);
+#endif
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMBINARYOESPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, GLvoid *binary);
+typedef void (GL_APIENTRYP PFNGLPROGRAMBINARYOESPROC) (GLuint program, GLenum binaryFormat, const GLvoid *binary, GLint length);
+#endif
+
+/* GL_OES_mapbuffer */
+#ifndef GL_OES_mapbuffer
+#define GL_OES_mapbuffer 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void* GL_APIENTRY glMapBufferOES (GLenum target, GLenum access);
+GL_APICALL GLboolean GL_APIENTRY glUnmapBufferOES (GLenum target);
+GL_APICALL void GL_APIENTRY glGetBufferPointervOES (GLenum target, GLenum pname, GLvoid** params);
+#endif
+typedef void* (GL_APIENTRYP PFNGLMAPBUFFEROESPROC) (GLenum target, GLenum access);
+typedef GLboolean (GL_APIENTRYP PFNGLUNMAPBUFFEROESPROC) (GLenum target);
+typedef void (GL_APIENTRYP PFNGLGETBUFFERPOINTERVOESPROC) (GLenum target, GLenum pname, GLvoid** params);
+#endif
+
+/* GL_OES_packed_depth_stencil */
+#ifndef GL_OES_packed_depth_stencil
+#define GL_OES_packed_depth_stencil 1
+#endif
+
+/* GL_OES_required_internalformat */
+#ifndef GL_OES_required_internalformat
+#define GL_OES_required_internalformat 1
+#endif
+
+/* GL_OES_rgb8_rgba8 */
+#ifndef GL_OES_rgb8_rgba8
+#define GL_OES_rgb8_rgba8 1
+#endif
+
+/* GL_OES_standard_derivatives */
+#ifndef GL_OES_standard_derivatives
+#define GL_OES_standard_derivatives 1
+#endif
+
+/* GL_OES_stencil1 */
+#ifndef GL_OES_stencil1
+#define GL_OES_stencil1 1
+#endif
+
+/* GL_OES_stencil4 */
+#ifndef GL_OES_stencil4
+#define GL_OES_stencil4 1
+#endif
+
+#ifndef GL_OES_surfaceless_context
+#define GL_OES_surfaceless_context 1
+#endif
+
+/* GL_OES_texture_3D */
+#ifndef GL_OES_texture_3D
+#define GL_OES_texture_3D 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glTexImage3DOES (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid* pixels);
+GL_APICALL void GL_APIENTRY glTexSubImage3DOES (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid* pixels);
+GL_APICALL void GL_APIENTRY glCopyTexSubImage3DOES (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glCompressedTexImage3DOES (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data);
+GL_APICALL void GL_APIENTRY glCompressedTexSubImage3DOES (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid* data);
+GL_APICALL void GL_APIENTRY glFramebufferTexture3DOES (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
+#endif
+typedef void (GL_APIENTRYP PFNGLTEXIMAGE3DOESPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid* pixels);
+typedef void (GL_APIENTRYP PFNGLTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid* pixels);
+typedef void (GL_APIENTRYP PFNGLCOPYTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXIMAGE3DOESPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data);
+typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid* data);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE3DOES) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
+#endif
+
+/* GL_OES_texture_float */
+#ifndef GL_OES_texture_float
+#define GL_OES_texture_float 1
+#endif
+
+/* GL_OES_texture_float_linear */
+#ifndef GL_OES_texture_float_linear
+#define GL_OES_texture_float_linear 1
+#endif
+
+/* GL_OES_texture_half_float */
+#ifndef GL_OES_texture_half_float
+#define GL_OES_texture_half_float 1
+#endif
+
+/* GL_OES_texture_half_float_linear */
+#ifndef GL_OES_texture_half_float_linear
+#define GL_OES_texture_half_float_linear 1
+#endif
+
+/* GL_OES_texture_npot */
+#ifndef GL_OES_texture_npot
+#define GL_OES_texture_npot 1
+#endif
+
+/* GL_OES_vertex_array_object */
+#ifndef GL_OES_vertex_array_object
+#define GL_OES_vertex_array_object 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glBindVertexArrayOES (GLuint array);
+GL_APICALL void GL_APIENTRY glDeleteVertexArraysOES (GLsizei n, const GLuint *arrays);
+GL_APICALL void GL_APIENTRY glGenVertexArraysOES (GLsizei n, GLuint *arrays);
+GL_APICALL GLboolean GL_APIENTRY glIsVertexArrayOES (GLuint array);
+#endif
+typedef void (GL_APIENTRYP PFNGLBINDVERTEXARRAYOESPROC) (GLuint array);
+typedef void (GL_APIENTRYP PFNGLDELETEVERTEXARRAYSOESPROC) (GLsizei n, const GLuint *arrays);
+typedef void (GL_APIENTRYP PFNGLGENVERTEXARRAYSOESPROC) (GLsizei n, GLuint *arrays);
+typedef GLboolean (GL_APIENTRYP PFNGLISVERTEXARRAYOESPROC) (GLuint array);
+#endif
+
+/* GL_OES_vertex_half_float */
+#ifndef GL_OES_vertex_half_float
+#define GL_OES_vertex_half_float 1
+#endif
+
+/* GL_OES_vertex_type_10_10_10_2 */
+#ifndef GL_OES_vertex_type_10_10_10_2
+#define GL_OES_vertex_type_10_10_10_2 1
+#endif
+
+/*------------------------------------------------------------------------*
+ * KHR extension functions
+ *------------------------------------------------------------------------*/
+
+#ifndef GL_KHR_debug
+#define GL_KHR_debug 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glDebugMessageControl (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled);
+GL_APICALL void GL_APIENTRY glDebugMessageInsert (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf);
+GL_APICALL void GL_APIENTRY glDebugMessageCallback (GLDEBUGPROC callback, const void *userParam);
+GL_APICALL GLuint GL_APIENTRY glGetDebugMessageLog (GLuint count, GLsizei bufsize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog);
+GL_APICALL void GL_APIENTRY glPushDebugGroup (GLenum source, GLuint id, GLsizei length, const GLchar *message);
+GL_APICALL void GL_APIENTRY glPopDebugGroup (void);
+GL_APICALL void GL_APIENTRY glObjectLabel (GLenum identifier, GLuint name, GLsizei length, const GLchar *label);
+GL_APICALL void GL_APIENTRY glGetObjectLabel (GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *length, GLchar *label);
+GL_APICALL void GL_APIENTRY glObjectPtrLabel (const void *ptr, GLsizei length, const GLchar *label);
+GL_APICALL void GL_APIENTRY glGetObjectPtrLabel (const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label);
+GL_APICALL void GL_APIENTRY glGetPointerv (GLenum pname, void **params);
+#endif
+typedef void (GL_APIENTRYP PFNGLDEBUGMESSAGECONTROLPROC) (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled);
+typedef void (GL_APIENTRYP PFNGLDEBUGMESSAGEINSERTPROC) (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf);
+typedef void (GL_APIENTRYP PFNGLDEBUGMESSAGECALLBACKPROC) (GLDEBUGPROC callback, const void *userParam);
+typedef GLuint (GL_APIENTRYP PFNGLGETDEBUGMESSAGELOGPROC) (GLuint count, GLsizei bufsize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog);
+typedef void (GL_APIENTRYP PFNGLPUSHDEBUGGROUPPROC) (GLenum source, GLuint id, GLsizei length, const GLchar *message);
+typedef void (GL_APIENTRYP PFNGLPOPDEBUGGROUPPROC) (void);
+typedef void (GL_APIENTRYP PFNGLOBJECTLABELPROC) (GLenum identifier, GLuint name, GLsizei length, const GLchar *label);
+typedef void (GL_APIENTRYP PFNGLGETOBJECTLABELPROC) (GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *length, GLchar *label);
+typedef void (GL_APIENTRYP PFNGLOBJECTPTRLABELPROC) (const void *ptr, GLsizei length, const GLchar *label);
+typedef void (GL_APIENTRYP PFNGLGETOBJECTPTRLABELPROC) (const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label);
+typedef void (GL_APIENTRYP PFNGLGETPOINTERVPROC) (GLenum pname, void **params);
+#endif
+
+#ifndef GL_KHR_texture_compression_astc_ldr
+#define GL_KHR_texture_compression_astc_ldr 1
+#endif
+
+
+/*------------------------------------------------------------------------*
+ * AMD extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_AMD_compressed_3DC_texture */
+#ifndef GL_AMD_compressed_3DC_texture
+#define GL_AMD_compressed_3DC_texture 1
+#endif
+
+/* GL_AMD_compressed_ATC_texture */
+#ifndef GL_AMD_compressed_ATC_texture
+#define GL_AMD_compressed_ATC_texture 1
+#endif
+
+/* AMD_performance_monitor */
+#ifndef GL_AMD_performance_monitor
+#define GL_AMD_performance_monitor 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glGetPerfMonitorGroupsAMD (GLint *numGroups, GLsizei groupsSize, GLuint *groups);
+GL_APICALL void GL_APIENTRY glGetPerfMonitorCountersAMD (GLuint group, GLint *numCounters, GLint *maxActiveCounters, GLsizei counterSize, GLuint *counters);
+GL_APICALL void GL_APIENTRY glGetPerfMonitorGroupStringAMD (GLuint group, GLsizei bufSize, GLsizei *length, GLchar *groupString);
+GL_APICALL void GL_APIENTRY glGetPerfMonitorCounterStringAMD (GLuint group, GLuint counter, GLsizei bufSize, GLsizei *length, GLchar *counterString);
+GL_APICALL void GL_APIENTRY glGetPerfMonitorCounterInfoAMD (GLuint group, GLuint counter, GLenum pname, GLvoid *data);
+GL_APICALL void GL_APIENTRY glGenPerfMonitorsAMD (GLsizei n, GLuint *monitors);
+GL_APICALL void GL_APIENTRY glDeletePerfMonitorsAMD (GLsizei n, GLuint *monitors);
+GL_APICALL void GL_APIENTRY glSelectPerfMonitorCountersAMD (GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint *countersList);
+GL_APICALL void GL_APIENTRY glBeginPerfMonitorAMD (GLuint monitor);
+GL_APICALL void GL_APIENTRY glEndPerfMonitorAMD (GLuint monitor);
+GL_APICALL void GL_APIENTRY glGetPerfMonitorCounterDataAMD (GLuint monitor, GLenum pname, GLsizei dataSize, GLuint *data, GLint *bytesWritten);
+#endif
+typedef void (GL_APIENTRYP PFNGLGETPERFMONITORGROUPSAMDPROC) (GLint *numGroups, GLsizei groupsSize, GLuint *groups);
+typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERSAMDPROC) (GLuint group, GLint *numCounters, GLint *maxActiveCounters, GLsizei counterSize, GLuint *counters);
+typedef void (GL_APIENTRYP PFNGLGETPERFMONITORGROUPSTRINGAMDPROC) (GLuint group, GLsizei bufSize, GLsizei *length, GLchar *groupString);
+typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERSTRINGAMDPROC) (GLuint group, GLuint counter, GLsizei bufSize, GLsizei *length, GLchar *counterString);
+typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERINFOAMDPROC) (GLuint group, GLuint counter, GLenum pname, GLvoid *data);
+typedef void (GL_APIENTRYP PFNGLGENPERFMONITORSAMDPROC) (GLsizei n, GLuint *monitors);
+typedef void (GL_APIENTRYP PFNGLDELETEPERFMONITORSAMDPROC) (GLsizei n, GLuint *monitors);
+typedef void (GL_APIENTRYP PFNGLSELECTPERFMONITORCOUNTERSAMDPROC) (GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint *countersList);
+typedef void (GL_APIENTRYP PFNGLBEGINPERFMONITORAMDPROC) (GLuint monitor);
+typedef void (GL_APIENTRYP PFNGLENDPERFMONITORAMDPROC) (GLuint monitor);
+typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERDATAAMDPROC) (GLuint monitor, GLenum pname, GLsizei dataSize, GLuint *data, GLint *bytesWritten);
+#endif
+
+/* GL_AMD_program_binary_Z400 */
+#ifndef GL_AMD_program_binary_Z400
+#define GL_AMD_program_binary_Z400 1
+#endif
+
+/*------------------------------------------------------------------------*
+ * ANGLE extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_ANGLE_depth_texture */
+#ifndef GL_ANGLE_depth_texture
+#define GL_ANGLE_depth_texture 1
+#endif
+
+/* GL_ANGLE_framebuffer_blit */
+#ifndef GL_ANGLE_framebuffer_blit
+#define GL_ANGLE_framebuffer_blit 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glBlitFramebufferANGLE (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+#endif
+typedef void (GL_APIENTRYP PFNGLBLITFRAMEBUFFERANGLEPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+#endif
+
+/* GL_ANGLE_framebuffer_multisample */
+#ifndef GL_ANGLE_framebuffer_multisample
+#define GL_ANGLE_framebuffer_multisample 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleANGLE (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+#endif
+typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEANGLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+#endif
+
+#ifndef GL_ANGLE_instanced_arrays
+#define GL_ANGLE_instanced_arrays 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glDrawArraysInstancedANGLE (GLenum mode, GLint first, GLsizei count, GLsizei primcount);
+GL_APICALL void GL_APIENTRY glDrawElementsInstancedANGLE (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount);
+GL_APICALL void GL_APIENTRY glVertexAttribDivisorANGLE (GLuint index, GLuint divisor);
+#endif
+typedef void (GL_APIENTRYP PFNGLDRAWARRAYSINSTANCEDANGLEPROC) (GLenum mode, GLint first, GLsizei count, GLsizei primcount);
+typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDANGLEPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBDIVISORANGLEPROC) (GLuint index, GLuint divisor);
+#endif
+
+/* GL_ANGLE_pack_reverse_row_order */
+#ifndef GL_ANGLE_pack_reverse_row_order
+#define GL_ANGLE_pack_reverse_row_order 1
+#endif
+
+/* GL_ANGLE_program_binary */
+#ifndef GL_ANGLE_program_binary
+#define GL_ANGLE_program_binary 1
+#endif
+
+/* GL_ANGLE_texture_compression_dxt3 */
+#ifndef GL_ANGLE_texture_compression_dxt3
+#define GL_ANGLE_texture_compression_dxt3 1
+#endif
+
+/* GL_ANGLE_texture_compression_dxt5 */
+#ifndef GL_ANGLE_texture_compression_dxt5
+#define GL_ANGLE_texture_compression_dxt5 1
+#endif
+
+/* GL_ANGLE_texture_usage */
+#ifndef GL_ANGLE_texture_usage
+#define GL_ANGLE_texture_usage 1
+#endif
+
+#ifndef GL_ANGLE_translated_shader_source
+#define GL_ANGLE_translated_shader_source 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glGetTranslatedShaderSourceANGLE (GLuint shader, GLsizei bufsize, GLsizei *length, GLchar *source);
+#endif
+typedef void (GL_APIENTRYP PFNGLGETTRANSLATEDSHADERSOURCEANGLEPROC) (GLuint shader, GLsizei bufsize, GLsizei *length, GLchar *source);
+#endif
+
+/*------------------------------------------------------------------------*
+ * APPLE extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_APPLE_copy_texture_levels */
+#ifndef GL_APPLE_copy_texture_levels
+#define GL_APPLE_copy_texture_levels 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glCopyTextureLevelsAPPLE (GLuint destinationTexture, GLuint sourceTexture, GLint sourceBaseLevel, GLsizei sourceLevelCount);
+#endif
+typedef void (GL_APIENTRYP PFNGLCOPYTEXTURELEVELSAPPLEPROC) (GLuint destinationTexture, GLuint sourceTexture, GLint sourceBaseLevel, GLsizei sourceLevelCount);
+#endif
+
+/* GL_APPLE_framebuffer_multisample */
+#ifndef GL_APPLE_framebuffer_multisample
+#define GL_APPLE_framebuffer_multisample 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleAPPLE (GLenum, GLsizei, GLenum, GLsizei, GLsizei);
+GL_APICALL void GL_APIENTRY glResolveMultisampleFramebufferAPPLE (void);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEAPPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLRESOLVEMULTISAMPLEFRAMEBUFFERAPPLEPROC) (void);
+#endif
+
+/* GL_APPLE_rgb_422 */
+#ifndef GL_APPLE_rgb_422
+#define GL_APPLE_rgb_422 1
+#endif
+
+/* GL_APPLE_sync */
+#ifndef GL_APPLE_sync
+#define GL_APPLE_sync 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL GLsync GL_APIENTRY glFenceSyncAPPLE (GLenum condition, GLbitfield flags);
+GL_APICALL GLboolean GL_APIENTRY glIsSyncAPPLE (GLsync sync);
+GL_APICALL void GL_APIENTRY glDeleteSyncAPPLE (GLsync sync);
+GL_APICALL GLenum GL_APIENTRY glClientWaitSyncAPPLE (GLsync sync, GLbitfield flags, GLuint64 timeout);
+GL_APICALL void GL_APIENTRY glWaitSyncAPPLE (GLsync sync, GLbitfield flags, GLuint64 timeout);
+GL_APICALL void GL_APIENTRY glGetInteger64vAPPLE (GLenum pname, GLint64 *params);
+GL_APICALL void GL_APIENTRY glGetSyncivAPPLE (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values);
+#endif
+typedef GLsync (GL_APIENTRYP PFNGLFENCESYNCAPPLEPROC) (GLenum condition, GLbitfield flags);
+typedef GLboolean (GL_APIENTRYP PFNGLISSYNCAPPLEPROC) (GLsync sync);
+typedef void (GL_APIENTRYP PFNGLDELETESYNCAPPLEPROC) (GLsync sync);
+typedef GLenum (GL_APIENTRYP PFNGLCLIENTWAITSYNCAPPLEPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout);
+typedef void (GL_APIENTRYP PFNGLWAITSYNCAPPLEPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout);
+typedef void (GL_APIENTRYP PFNGLGETINTEGER64VAPPLEPROC) (GLenum pname, GLint64 *params);
+typedef void (GL_APIENTRYP PFNGLGETSYNCIVAPPLEPROC) (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values);
+#endif
+
+/* GL_APPLE_texture_format_BGRA8888 */
+#ifndef GL_APPLE_texture_format_BGRA8888
+#define GL_APPLE_texture_format_BGRA8888 1
+#endif
+
+/* GL_APPLE_texture_max_level */
+#ifndef GL_APPLE_texture_max_level
+#define GL_APPLE_texture_max_level 1
+#endif
+
+/*------------------------------------------------------------------------*
+ * ARM extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_ARM_mali_program_binary */
+#ifndef GL_ARM_mali_program_binary
+#define GL_ARM_mali_program_binary 1
+#endif
+
+/* GL_ARM_mali_shader_binary */
+#ifndef GL_ARM_mali_shader_binary
+#define GL_ARM_mali_shader_binary 1
+#endif
+
+/* GL_ARM_rgba8 */
+#ifndef GL_ARM_rgba8
+#define GL_ARM_rgba8 1
+#endif
+
+/*------------------------------------------------------------------------*
+ * EXT extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_EXT_blend_minmax */
+#ifndef GL_EXT_blend_minmax
+#define GL_EXT_blend_minmax 1
+#endif
+
+/* GL_EXT_color_buffer_half_float */
+#ifndef GL_EXT_color_buffer_half_float
+#define GL_EXT_color_buffer_half_float 1
+#endif
+
+/* GL_EXT_debug_label */
+#ifndef GL_EXT_debug_label
+#define GL_EXT_debug_label 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glLabelObjectEXT (GLenum type, GLuint object, GLsizei length, const GLchar *label);
+GL_APICALL void GL_APIENTRY glGetObjectLabelEXT (GLenum type, GLuint object, GLsizei bufSize, GLsizei *length, GLchar *label);
+#endif
+typedef void (GL_APIENTRYP PFNGLLABELOBJECTEXTPROC) (GLenum type, GLuint object, GLsizei length, const GLchar *label);
+typedef void (GL_APIENTRYP PFNGLGETOBJECTLABELEXTPROC) (GLenum type, GLuint object, GLsizei bufSize, GLsizei *length, GLchar *label);
+#endif
+
+/* GL_EXT_debug_marker */
+#ifndef GL_EXT_debug_marker
+#define GL_EXT_debug_marker 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glInsertEventMarkerEXT (GLsizei length, const GLchar *marker);
+GL_APICALL void GL_APIENTRY glPushGroupMarkerEXT (GLsizei length, const GLchar *marker);
+GL_APICALL void GL_APIENTRY glPopGroupMarkerEXT (void);
+#endif
+typedef void (GL_APIENTRYP PFNGLINSERTEVENTMARKEREXTPROC) (GLsizei length, const GLchar *marker);
+typedef void (GL_APIENTRYP PFNGLPUSHGROUPMARKEREXTPROC) (GLsizei length, const GLchar *marker);
+typedef void (GL_APIENTRYP PFNGLPOPGROUPMARKEREXTPROC) (void);
+#endif
+
+/* GL_EXT_discard_framebuffer */
+#ifndef GL_EXT_discard_framebuffer
+#define GL_EXT_discard_framebuffer 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glDiscardFramebufferEXT (GLenum target, GLsizei numAttachments, const GLenum *attachments);
+#endif
+typedef void (GL_APIENTRYP PFNGLDISCARDFRAMEBUFFEREXTPROC) (GLenum target, GLsizei numAttachments, const GLenum *attachments);
+#endif
+
+/* GL_EXT_map_buffer_range */
+#ifndef GL_EXT_map_buffer_range
+#define GL_EXT_map_buffer_range 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void* GL_APIENTRY glMapBufferRangeEXT (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
+GL_APICALL void GL_APIENTRY glFlushMappedBufferRangeEXT (GLenum target, GLintptr offset, GLsizeiptr length);
+#endif
+typedef void* (GL_APIENTRYP PFNGLMAPBUFFERRANGEEXTPROC) (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
+typedef void (GL_APIENTRYP PFNGLFLUSHMAPPEDBUFFERRANGEEXTPROC) (GLenum target, GLintptr offset, GLsizeiptr length);
+#endif
+
+/* GL_EXT_multisampled_render_to_texture */
+#ifndef GL_EXT_multisampled_render_to_texture
+#define GL_EXT_multisampled_render_to_texture 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleEXT (GLenum, GLsizei, GLenum, GLsizei, GLsizei);
+GL_APICALL void GL_APIENTRY glFramebufferTexture2DMultisampleEXT (GLenum, GLenum, GLenum, GLuint, GLint, GLsizei);
+#endif
+typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples);
+#endif
+
+/* GL_EXT_multiview_draw_buffers */
+#ifndef GL_EXT_multiview_draw_buffers
+#define GL_EXT_multiview_draw_buffers 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glReadBufferIndexedEXT (GLenum src, GLint index);
+GL_APICALL void GL_APIENTRY glDrawBuffersIndexedEXT (GLint n, const GLenum *location, const GLint *indices);
+GL_APICALL void GL_APIENTRY glGetIntegeri_vEXT (GLenum target, GLuint index, GLint *data);
+#endif
+typedef void (GL_APIENTRYP PFNGLREADBUFFERINDEXEDEXTPROC) (GLenum src, GLint index);
+typedef void (GL_APIENTRYP PFNGLDRAWBUFFERSINDEXEDEXTPROC) (GLint n, const GLenum *location, const GLint *indices);
+typedef void (GL_APIENTRYP PFNGLGETINTEGERI_VEXTPROC) (GLenum target, GLuint index, GLint *data);
+#endif
+
+#ifndef GL_EXT_multi_draw_arrays
+#define GL_EXT_multi_draw_arrays 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glMultiDrawArraysEXT (GLenum, const GLint *, const GLsizei *, GLsizei);
+GL_APICALL void GL_APIENTRY glMultiDrawElementsEXT (GLenum, const GLsizei *, GLenum, const GLvoid* *, GLsizei);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (GL_APIENTRYP PFNGLMULTIDRAWARRAYSEXTPROC) (GLenum mode, GLint *first, GLsizei *count, GLsizei primcount);
+typedef void (GL_APIENTRYP PFNGLMULTIDRAWELEMENTSEXTPROC) (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount);
+#endif
+
+/* GL_EXT_occlusion_query_boolean */
+#ifndef GL_EXT_occlusion_query_boolean
+#define GL_EXT_occlusion_query_boolean 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glGenQueriesEXT (GLsizei n, GLuint *ids);
+GL_APICALL void GL_APIENTRY glDeleteQueriesEXT (GLsizei n, const GLuint *ids);
+GL_APICALL GLboolean GL_APIENTRY glIsQueryEXT (GLuint id);
+GL_APICALL void GL_APIENTRY glBeginQueryEXT (GLenum target, GLuint id);
+GL_APICALL void GL_APIENTRY glEndQueryEXT (GLenum target);
+GL_APICALL void GL_APIENTRY glGetQueryivEXT (GLenum target, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetQueryObjectuivEXT (GLuint id, GLenum pname, GLuint *params);
+#endif
+typedef void (GL_APIENTRYP PFNGLGENQUERIESEXTPROC) (GLsizei n, GLuint *ids);
+typedef void (GL_APIENTRYP PFNGLDELETEQUERIESEXTPROC) (GLsizei n, const GLuint *ids);
+typedef GLboolean (GL_APIENTRYP PFNGLISQUERYEXTPROC) (GLuint id);
+typedef void (GL_APIENTRYP PFNGLBEGINQUERYEXTPROC) (GLenum target, GLuint id);
+typedef void (GL_APIENTRYP PFNGLENDQUERYEXTPROC) (GLenum target);
+typedef void (GL_APIENTRYP PFNGLGETQUERYIVEXTPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETQUERYOBJECTUIVEXTPROC) (GLuint id, GLenum pname, GLuint *params);
+#endif
+
+/* GL_EXT_read_format_bgra */
+#ifndef GL_EXT_read_format_bgra
+#define GL_EXT_read_format_bgra 1
+#endif
+
+/* GL_EXT_robustness */
+#ifndef GL_EXT_robustness
+#define GL_EXT_robustness 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL GLenum GL_APIENTRY glGetGraphicsResetStatusEXT (void);
+GL_APICALL void GL_APIENTRY glReadnPixelsEXT (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data);
+GL_APICALL void GL_APIENTRY glGetnUniformfvEXT (GLuint program, GLint location, GLsizei bufSize, float *params);
+GL_APICALL void GL_APIENTRY glGetnUniformivEXT (GLuint program, GLint location, GLsizei bufSize, GLint *params);
+#endif
+typedef GLenum (GL_APIENTRYP PFNGLGETGRAPHICSRESETSTATUSEXTPROC) (void);
+typedef void (GL_APIENTRYP PFNGLREADNPIXELSEXTPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data);
+typedef void (GL_APIENTRYP PFNGLGETNUNIFORMFVEXTPROC) (GLuint program, GLint location, GLsizei bufSize, float *params);
+typedef void (GL_APIENTRYP PFNGLGETNUNIFORMIVEXTPROC) (GLuint program, GLint location, GLsizei bufSize, GLint *params);
+#endif
+
+/* GL_EXT_separate_shader_objects */
+#ifndef GL_EXT_separate_shader_objects
+#define GL_EXT_separate_shader_objects 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glUseProgramStagesEXT (GLuint pipeline, GLbitfield stages, GLuint program);
+GL_APICALL void GL_APIENTRY glActiveShaderProgramEXT (GLuint pipeline, GLuint program);
+GL_APICALL GLuint GL_APIENTRY glCreateShaderProgramvEXT (GLenum type, GLsizei count, const GLchar **strings);
+GL_APICALL void GL_APIENTRY glBindProgramPipelineEXT (GLuint pipeline);
+GL_APICALL void GL_APIENTRY glDeleteProgramPipelinesEXT (GLsizei n, const GLuint *pipelines);
+GL_APICALL void GL_APIENTRY glGenProgramPipelinesEXT (GLsizei n, GLuint *pipelines);
+GL_APICALL GLboolean GL_APIENTRY glIsProgramPipelineEXT (GLuint pipeline);
+GL_APICALL void GL_APIENTRY glProgramParameteriEXT (GLuint program, GLenum pname, GLint value);
+GL_APICALL void GL_APIENTRY glGetProgramPipelineivEXT (GLuint pipeline, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glProgramUniform1iEXT (GLuint program, GLint location, GLint x);
+GL_APICALL void GL_APIENTRY glProgramUniform2iEXT (GLuint program, GLint location, GLint x, GLint y);
+GL_APICALL void GL_APIENTRY glProgramUniform3iEXT (GLuint program, GLint location, GLint x, GLint y, GLint z);
+GL_APICALL void GL_APIENTRY glProgramUniform4iEXT (GLuint program, GLint location, GLint x, GLint y, GLint z, GLint w);
+GL_APICALL void GL_APIENTRY glProgramUniform1fEXT (GLuint program, GLint location, GLfloat x);
+GL_APICALL void GL_APIENTRY glProgramUniform2fEXT (GLuint program, GLint location, GLfloat x, GLfloat y);
+GL_APICALL void GL_APIENTRY glProgramUniform3fEXT (GLuint program, GLint location, GLfloat x, GLfloat y, GLfloat z);
+GL_APICALL void GL_APIENTRY glProgramUniform4fEXT (GLuint program, GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GL_APICALL void GL_APIENTRY glProgramUniform1ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform2ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform3ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform4ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform1fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniform2fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniform3fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniform4fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix2fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix3fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix4fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glValidateProgramPipelineEXT (GLuint pipeline);
+GL_APICALL void GL_APIENTRY glGetProgramPipelineInfoLogEXT (GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+#endif
+typedef void (GL_APIENTRYP PFNGLUSEPROGRAMSTAGESEXTPROC) (GLuint pipeline, GLbitfield stages, GLuint program);
+typedef void (GL_APIENTRYP PFNGLACTIVESHADERPROGRAMEXTPROC) (GLuint pipeline, GLuint program);
+typedef GLuint (GL_APIENTRYP PFNGLCREATESHADERPROGRAMVEXTPROC) (GLenum type, GLsizei count, const GLchar **strings);
+typedef void (GL_APIENTRYP PFNGLBINDPROGRAMPIPELINEEXTPROC) (GLuint pipeline);
+typedef void (GL_APIENTRYP PFNGLDELETEPROGRAMPIPELINESEXTPROC) (GLsizei n, const GLuint *pipelines);
+typedef void (GL_APIENTRYP PFNGLGENPROGRAMPIPELINESEXTPROC) (GLsizei n, GLuint *pipelines);
+typedef GLboolean (GL_APIENTRYP PFNGLISPROGRAMPIPELINEEXTPROC) (GLuint pipeline);
+typedef void (GL_APIENTRYP PFNGLPROGRAMPARAMETERIEXTPROC) (GLuint program, GLenum pname, GLint value);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMPIPELINEIVEXTPROC) (GLuint pipeline, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1IEXTPROC) (GLuint program, GLint location, GLint x);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2IEXTPROC) (GLuint program, GLint location, GLint x, GLint y);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3IEXTPROC) (GLuint program, GLint location, GLint x, GLint y, GLint z);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4IEXTPROC) (GLuint program, GLint location, GLint x, GLint y, GLint z, GLint w);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1FEXTPROC) (GLuint program, GLint location, GLfloat x);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2FEXTPROC) (GLuint program, GLint location, GLfloat x, GLfloat y);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3FEXTPROC) (GLuint program, GLint location, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4FEXTPROC) (GLuint program, GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLVALIDATEPROGRAMPIPELINEEXTPROC) (GLuint pipeline);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMPIPELINEINFOLOGEXTPROC) (GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+#endif
+
+/* GL_EXT_shader_framebuffer_fetch */
+#ifndef GL_EXT_shader_framebuffer_fetch
+#define GL_EXT_shader_framebuffer_fetch 1
+#endif
+
+/* GL_EXT_shader_texture_lod */
+#ifndef GL_EXT_shader_texture_lod
+#define GL_EXT_shader_texture_lod 1
+#endif
+
+/* GL_EXT_shadow_samplers */
+#ifndef GL_EXT_shadow_samplers
+#define GL_EXT_shadow_samplers 1
+#endif
+
+/* GL_EXT_sRGB */
+#ifndef GL_EXT_sRGB
+#define GL_EXT_sRGB 1
+#endif
+
+/* GL_EXT_texture_compression_dxt1 */
+#ifndef GL_EXT_texture_compression_dxt1
+#define GL_EXT_texture_compression_dxt1 1
+#endif
+
+/* GL_EXT_texture_filter_anisotropic */
+#ifndef GL_EXT_texture_filter_anisotropic
+#define GL_EXT_texture_filter_anisotropic 1
+#endif
+
+/* GL_EXT_texture_format_BGRA8888 */
+#ifndef GL_EXT_texture_format_BGRA8888
+#define GL_EXT_texture_format_BGRA8888 1
+#endif
+
+/* GL_EXT_texture_rg */
+#ifndef GL_EXT_texture_rg
+#define GL_EXT_texture_rg 1
+#endif
+
+/* GL_EXT_texture_storage */
+#ifndef GL_EXT_texture_storage
+#define GL_EXT_texture_storage 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glTexStorage1DEXT (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width);
+GL_APICALL void GL_APIENTRY glTexStorage2DEXT (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glTexStorage3DEXT (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+GL_APICALL void GL_APIENTRY glTextureStorage1DEXT (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width);
+GL_APICALL void GL_APIENTRY glTextureStorage2DEXT (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glTextureStorage3DEXT (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+#endif
+typedef void (GL_APIENTRYP PFNGLTEXSTORAGE1DEXTPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width);
+typedef void (GL_APIENTRYP PFNGLTEXSTORAGE2DEXTPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLTEXSTORAGE3DEXTPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+typedef void (GL_APIENTRYP PFNGLTEXTURESTORAGE1DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width);
+typedef void (GL_APIENTRYP PFNGLTEXTURESTORAGE2DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLTEXTURESTORAGE3DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+#endif
+
+/* GL_EXT_texture_type_2_10_10_10_REV */
+#ifndef GL_EXT_texture_type_2_10_10_10_REV
+#define GL_EXT_texture_type_2_10_10_10_REV 1
+#endif
+
+/* GL_EXT_unpack_subimage */
+#ifndef GL_EXT_unpack_subimage
+#define GL_EXT_unpack_subimage 1
+#endif
+
+/*------------------------------------------------------------------------*
+ * DMP extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_DMP_shader_binary */
+#ifndef GL_DMP_shader_binary
+#define GL_DMP_shader_binary 1
+#endif
+
+/*------------------------------------------------------------------------*
+ * FJ extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_FJ_shader_binary_GCCSO */
+#ifndef GL_FJ_shader_binary_GCCSO
+#define GL_FJ_shader_binary_GCCSO 1
+#endif
+
+/*------------------------------------------------------------------------*
+ * IMG extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_IMG_program_binary */
+#ifndef GL_IMG_program_binary
+#define GL_IMG_program_binary 1
+#endif
+
+/* GL_IMG_read_format */
+#ifndef GL_IMG_read_format
+#define GL_IMG_read_format 1
+#endif
+
+/* GL_IMG_shader_binary */
+#ifndef GL_IMG_shader_binary
+#define GL_IMG_shader_binary 1
+#endif
+
+/* GL_IMG_texture_compression_pvrtc */
+#ifndef GL_IMG_texture_compression_pvrtc
+#define GL_IMG_texture_compression_pvrtc 1
+#endif
+
+/* GL_IMG_texture_compression_pvrtc2 */
+#ifndef GL_IMG_texture_compression_pvrtc2
+#define GL_IMG_texture_compression_pvrtc2 1
+#endif
+
+/* GL_IMG_multisampled_render_to_texture */
+#ifndef GL_IMG_multisampled_render_to_texture
+#define GL_IMG_multisampled_render_to_texture 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleIMG (GLenum, GLsizei, GLenum, GLsizei, GLsizei);
+GL_APICALL void GL_APIENTRY glFramebufferTexture2DMultisampleIMG (GLenum, GLenum, GLenum, GLuint, GLint, GLsizei);
+#endif
+typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEIMGPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEIMGPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples);
+#endif
+
+/*------------------------------------------------------------------------*
+ * NV extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_NV_coverage_sample */
+#ifndef GL_NV_coverage_sample
+#define GL_NV_coverage_sample 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glCoverageMaskNV (GLboolean mask);
+GL_APICALL void GL_APIENTRY glCoverageOperationNV (GLenum operation);
+#endif
+typedef void (GL_APIENTRYP PFNGLCOVERAGEMASKNVPROC) (GLboolean mask);
+typedef void (GL_APIENTRYP PFNGLCOVERAGEOPERATIONNVPROC) (GLenum operation);
+#endif
+
+/* GL_NV_depth_nonlinear */
+#ifndef GL_NV_depth_nonlinear
+#define GL_NV_depth_nonlinear 1
+#endif
+
+/* GL_NV_draw_buffers */
+#ifndef GL_NV_draw_buffers
+#define GL_NV_draw_buffers 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glDrawBuffersNV (GLsizei n, const GLenum *bufs);
+#endif
+typedef void (GL_APIENTRYP PFNGLDRAWBUFFERSNVPROC) (GLsizei n, const GLenum *bufs);
+#endif
+
+/* GL_EXT_draw_buffers */
+#ifndef GL_EXT_draw_buffers
+#define GL_EXT_draw_buffers 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glDrawBuffersEXT (GLsizei n, const GLenum *bufs);
+#endif
+typedef void (GL_APIENTRYP PFNGLDRAWBUFFERSEXTPROC) (GLsizei n, const GLenum *bufs);
+#endif
+
+/* GL_NV_draw_instanced */
+#ifndef GL_NV_draw_instanced
+#define GL_NV_draw_instanced 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glDrawArraysInstancedNV (GLenum mode, GLint first, GLsizei count, GLsizei primcount);
+GL_APICALL void GL_APIENTRY glDrawElementsInstancedNV (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount);
+#endif
+typedef void (GL_APIENTRYP PFNDRAWARRAYSINSTANCEDNVPROC) (GLenum mode, GLint first, GLsizei count, GLsizei primcount);
+typedef void (GL_APIENTRYP PFNDRAWELEMENTSINSTANCEDNVPROC) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount);
+#endif
+
+/* GL_NV_fbo_color_attachments */
+#ifndef GL_NV_fbo_color_attachments
+#define GL_NV_fbo_color_attachments 1
+#endif
+
+/* GL_NV_fence */
+#ifndef GL_NV_fence
+#define GL_NV_fence 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glDeleteFencesNV (GLsizei, const GLuint *);
+GL_APICALL void GL_APIENTRY glGenFencesNV (GLsizei, GLuint *);
+GL_APICALL GLboolean GL_APIENTRY glIsFenceNV (GLuint);
+GL_APICALL GLboolean GL_APIENTRY glTestFenceNV (GLuint);
+GL_APICALL void GL_APIENTRY glGetFenceivNV (GLuint, GLenum, GLint *);
+GL_APICALL void GL_APIENTRY glFinishFenceNV (GLuint);
+GL_APICALL void GL_APIENTRY glSetFenceNV (GLuint, GLenum);
+#endif
+typedef void (GL_APIENTRYP PFNGLDELETEFENCESNVPROC) (GLsizei n, const GLuint *fences);
+typedef void (GL_APIENTRYP PFNGLGENFENCESNVPROC) (GLsizei n, GLuint *fences);
+typedef GLboolean (GL_APIENTRYP PFNGLISFENCENVPROC) (GLuint fence);
+typedef GLboolean (GL_APIENTRYP PFNGLTESTFENCENVPROC) (GLuint fence);
+typedef void (GL_APIENTRYP PFNGLGETFENCEIVNVPROC) (GLuint fence, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLFINISHFENCENVPROC) (GLuint fence);
+typedef void (GL_APIENTRYP PFNGLSETFENCENVPROC) (GLuint fence, GLenum condition);
+#endif
+
+/* GL_NV_framebuffer_blit */
+#ifndef GL_NV_framebuffer_blit
+#define GL_NV_framebuffer_blit 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glBlitFramebufferNV (int srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+#endif
+typedef void (GL_APIENTRYP PFNBLITFRAMEBUFFERNVPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+#endif
+
+/* GL_NV_framebuffer_multisample */
+#ifndef GL_NV_framebuffer_multisample
+#define GL_NV_framebuffer_multisample 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleNV ( GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+#endif
+typedef void (GL_APIENTRYP PFNRENDERBUFFERSTORAGEMULTISAMPLENVPROC) ( GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+#endif
+
+/* GL_NV_generate_mipmap_sRGB */
+#ifndef GL_NV_generate_mipmap_sRGB
+#define GL_NV_generate_mipmap_sRGB 1
+#endif
+
+/* GL_NV_instanced_arrays */
+#ifndef GL_NV_instanced_arrays
+#define GL_NV_instanced_arrays 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glVertexAttribDivisorNV (GLuint index, GLuint divisor);
+#endif
+typedef void (GL_APIENTRYP PFNVERTEXATTRIBDIVISORNVPROC) (GLuint index, GLuint divisor);
+#endif
+
+/* GL_NV_read_buffer */
+#ifndef GL_NV_read_buffer
+#define GL_NV_read_buffer 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glReadBufferNV (GLenum mode);
+#endif
+typedef void (GL_APIENTRYP PFNGLREADBUFFERNVPROC) (GLenum mode);
+#endif
+
+/* GL_NV_read_buffer_front */
+#ifndef GL_NV_read_buffer_front
+#define GL_NV_read_buffer_front 1
+#endif
+
+/* GL_NV_read_depth */
+#ifndef GL_NV_read_depth
+#define GL_NV_read_depth 1
+#endif
+
+/* GL_NV_read_depth_stencil */
+#ifndef GL_NV_read_depth_stencil
+#define GL_NV_read_depth_stencil 1
+#endif
+
+/* GL_NV_read_stencil */
+#ifndef GL_NV_read_stencil
+#define GL_NV_read_stencil 1
+#endif
+
+/* GL_NV_shadow_samplers_array */
+#ifndef GL_NV_shadow_samplers_array
+#define GL_NV_shadow_samplers_array 1
+#endif
+
+/* GL_NV_shadow_samplers_cube */
+#ifndef GL_NV_shadow_samplers_cube
+#define GL_NV_shadow_samplers_cube 1
+#endif
+
+/* GL_NV_sRGB_formats */
+#ifndef GL_NV_sRGB_formats
+#define GL_NV_sRGB_formats 1
+#endif
+
+/* GL_NV_texture_border_clamp */
+#ifndef GL_NV_texture_border_clamp
+#define GL_NV_texture_border_clamp 1
+#endif
+
+/* GL_NV_texture_compression_s3tc_update */
+#ifndef GL_NV_texture_compression_s3tc_update
+#define GL_NV_texture_compression_s3tc_update 1
+#endif
+
+/* GL_NV_texture_npot_2D_mipmap */
+#ifndef GL_NV_texture_npot_2D_mipmap
+#define GL_NV_texture_npot_2D_mipmap 1
+#endif
+
+/*------------------------------------------------------------------------*
+ * QCOM extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_QCOM_alpha_test */
+#ifndef GL_QCOM_alpha_test
+#define GL_QCOM_alpha_test 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glAlphaFuncQCOM (GLenum func, GLclampf ref);
+#endif
+typedef void (GL_APIENTRYP PFNGLALPHAFUNCQCOMPROC) (GLenum func, GLclampf ref);
+#endif
+
+/* GL_QCOM_binning_control */
+#ifndef GL_QCOM_binning_control
+#define GL_QCOM_binning_control 1
+#endif
+
+/* GL_QCOM_driver_control */
+#ifndef GL_QCOM_driver_control
+#define GL_QCOM_driver_control 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glGetDriverControlsQCOM (GLint *num, GLsizei size, GLuint *driverControls);
+GL_APICALL void GL_APIENTRY glGetDriverControlStringQCOM (GLuint driverControl, GLsizei bufSize, GLsizei *length, GLchar *driverControlString);
+GL_APICALL void GL_APIENTRY glEnableDriverControlQCOM (GLuint driverControl);
+GL_APICALL void GL_APIENTRY glDisableDriverControlQCOM (GLuint driverControl);
+#endif
+typedef void (GL_APIENTRYP PFNGLGETDRIVERCONTROLSQCOMPROC) (GLint *num, GLsizei size, GLuint *driverControls);
+typedef void (GL_APIENTRYP PFNGLGETDRIVERCONTROLSTRINGQCOMPROC) (GLuint driverControl, GLsizei bufSize, GLsizei *length, GLchar *driverControlString);
+typedef void (GL_APIENTRYP PFNGLENABLEDRIVERCONTROLQCOMPROC) (GLuint driverControl);
+typedef void (GL_APIENTRYP PFNGLDISABLEDRIVERCONTROLQCOMPROC) (GLuint driverControl);
+#endif
+
+/* GL_QCOM_extended_get */
+#ifndef GL_QCOM_extended_get
+#define GL_QCOM_extended_get 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glExtGetTexturesQCOM (GLuint *textures, GLint maxTextures, GLint *numTextures);
+GL_APICALL void GL_APIENTRY glExtGetBuffersQCOM (GLuint *buffers, GLint maxBuffers, GLint *numBuffers);
+GL_APICALL void GL_APIENTRY glExtGetRenderbuffersQCOM (GLuint *renderbuffers, GLint maxRenderbuffers, GLint *numRenderbuffers);
+GL_APICALL void GL_APIENTRY glExtGetFramebuffersQCOM (GLuint *framebuffers, GLint maxFramebuffers, GLint *numFramebuffers);
+GL_APICALL void GL_APIENTRY glExtGetTexLevelParameterivQCOM (GLuint texture, GLenum face, GLint level, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glExtTexObjectStateOverrideiQCOM (GLenum target, GLenum pname, GLint param);
+GL_APICALL void GL_APIENTRY glExtGetTexSubImageQCOM (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, GLvoid *texels);
+GL_APICALL void GL_APIENTRY glExtGetBufferPointervQCOM (GLenum target, GLvoid **params);
+#endif
+typedef void (GL_APIENTRYP PFNGLEXTGETTEXTURESQCOMPROC) (GLuint *textures, GLint maxTextures, GLint *numTextures);
+typedef void (GL_APIENTRYP PFNGLEXTGETBUFFERSQCOMPROC) (GLuint *buffers, GLint maxBuffers, GLint *numBuffers);
+typedef void (GL_APIENTRYP PFNGLEXTGETRENDERBUFFERSQCOMPROC) (GLuint *renderbuffers, GLint maxRenderbuffers, GLint *numRenderbuffers);
+typedef void (GL_APIENTRYP PFNGLEXTGETFRAMEBUFFERSQCOMPROC) (GLuint *framebuffers, GLint maxFramebuffers, GLint *numFramebuffers);
+typedef void (GL_APIENTRYP PFNGLEXTGETTEXLEVELPARAMETERIVQCOMPROC) (GLuint texture, GLenum face, GLint level, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLEXTTEXOBJECTSTATEOVERRIDEIQCOMPROC) (GLenum target, GLenum pname, GLint param);
+typedef void (GL_APIENTRYP PFNGLEXTGETTEXSUBIMAGEQCOMPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, GLvoid *texels);
+typedef void (GL_APIENTRYP PFNGLEXTGETBUFFERPOINTERVQCOMPROC) (GLenum target, GLvoid **params);
+#endif
+
+/* GL_QCOM_extended_get2 */
+#ifndef GL_QCOM_extended_get2
+#define GL_QCOM_extended_get2 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glExtGetShadersQCOM (GLuint *shaders, GLint maxShaders, GLint *numShaders);
+GL_APICALL void GL_APIENTRY glExtGetProgramsQCOM (GLuint *programs, GLint maxPrograms, GLint *numPrograms);
+GL_APICALL GLboolean GL_APIENTRY glExtIsProgramBinaryQCOM (GLuint program);
+GL_APICALL void GL_APIENTRY glExtGetProgramBinarySourceQCOM (GLuint program, GLenum shadertype, GLchar *source, GLint *length);
+#endif
+typedef void (GL_APIENTRYP PFNGLEXTGETSHADERSQCOMPROC) (GLuint *shaders, GLint maxShaders, GLint *numShaders);
+typedef void (GL_APIENTRYP PFNGLEXTGETPROGRAMSQCOMPROC) (GLuint *programs, GLint maxPrograms, GLint *numPrograms);
+typedef GLboolean (GL_APIENTRYP PFNGLEXTISPROGRAMBINARYQCOMPROC) (GLuint program);
+typedef void (GL_APIENTRYP PFNGLEXTGETPROGRAMBINARYSOURCEQCOMPROC) (GLuint program, GLenum shadertype, GLchar *source, GLint *length);
+#endif
+
+/* GL_QCOM_perfmon_global_mode */
+#ifndef GL_QCOM_perfmon_global_mode
+#define GL_QCOM_perfmon_global_mode 1
+#endif
+
+/* GL_QCOM_writeonly_rendering */
+#ifndef GL_QCOM_writeonly_rendering
+#define GL_QCOM_writeonly_rendering 1
+#endif
+
+/* GL_QCOM_tiled_rendering */
+#ifndef GL_QCOM_tiled_rendering
+#define GL_QCOM_tiled_rendering 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glStartTilingQCOM (GLuint x, GLuint y, GLuint width, GLuint height, GLbitfield preserveMask);
+GL_APICALL void GL_APIENTRY glEndTilingQCOM (GLbitfield preserveMask);
+#endif
+typedef void (GL_APIENTRYP PFNGLSTARTTILINGQCOMPROC) (GLuint x, GLuint y, GLuint width, GLuint height, GLbitfield preserveMask);
+typedef void (GL_APIENTRYP PFNGLENDTILINGQCOMPROC) (GLbitfield preserveMask);
+#endif
+
+/*------------------------------------------------------------------------*
+ * VIV extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_VIV_shader_binary */
+#ifndef GL_VIV_shader_binary
+#define GL_VIV_shader_binary 1
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gl2ext_h_ */
diff --git a/platform/winrt/include/GLES2/gl2platform.h b/platform/winrt/include/GLES2/gl2platform.h
new file mode 100644
index 0000000000..38cb3b7b6f
--- /dev/null
+++ b/platform/winrt/include/GLES2/gl2platform.h
@@ -0,0 +1,30 @@
+#ifndef __gl2platform_h_
+#define __gl2platform_h_
+
+/* $Revision: 10602 $ on $Date:: 2010-03-04 22:35:34 -0800 #$ */
+
+/*
+ * This document is licensed under the SGI Free Software B License Version
+ * 2.0. For details, see http://oss.sgi.com/projects/FreeB/ .
+ */
+
+/* Platform-specific types and definitions for OpenGL ES 2.X gl2.h
+ *
+ * Adopters may modify khrplatform.h and this file to suit their platform.
+ * You are encouraged to submit all modifications to the Khronos group so that
+ * they can be included in future versions of this file. Please submit changes
+ * by sending them to the public Khronos Bugzilla (http://khronos.org/bugzilla)
+ * by filing a bug against product "OpenGL-ES" component "Registry".
+ */
+
+#include <KHR/khrplatform.h>
+
+#ifndef GL_APICALL
+#define GL_APICALL KHRONOS_APICALL
+#endif
+
+#ifndef GL_APIENTRY
+#define GL_APIENTRY KHRONOS_APIENTRY
+#endif
+
+#endif /* __gl2platform_h_ */
diff --git a/platform/winrt/include/GLES3/gl3.h b/platform/winrt/include/GLES3/gl3.h
new file mode 100644
index 0000000000..024edc4306
--- /dev/null
+++ b/platform/winrt/include/GLES3/gl3.h
@@ -0,0 +1,1061 @@
+#ifndef __gl3_h_
+#define __gl3_h_
+
+/*
+ * gl3.h last updated on $Date: 2013-02-12 14:37:24 -0800 (Tue, 12 Feb 2013) $
+ */
+
+#include <GLES3/gl3platform.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** Copyright (c) 2007-2013 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+/*-------------------------------------------------------------------------
+ * Data type definitions
+ *-----------------------------------------------------------------------*/
+
+/* OpenGL ES 2.0 */
+
+typedef void GLvoid;
+typedef char GLchar;
+typedef unsigned int GLenum;
+typedef unsigned char GLboolean;
+typedef unsigned int GLbitfield;
+typedef khronos_int8_t GLbyte;
+typedef short GLshort;
+typedef int GLint;
+typedef int GLsizei;
+typedef khronos_uint8_t GLubyte;
+typedef unsigned short GLushort;
+typedef unsigned int GLuint;
+typedef khronos_float_t GLfloat;
+typedef khronos_float_t GLclampf;
+typedef khronos_int32_t GLfixed;
+typedef khronos_intptr_t GLintptr;
+typedef khronos_ssize_t GLsizeiptr;
+
+/* OpenGL ES 3.0 */
+
+typedef unsigned short GLhalf;
+typedef khronos_int64_t GLint64;
+typedef khronos_uint64_t GLuint64;
+typedef struct __GLsync *GLsync;
+
+/*-------------------------------------------------------------------------
+ * Token definitions
+ *-----------------------------------------------------------------------*/
+
+/* OpenGL ES core versions */
+#define GL_ES_VERSION_3_0 1
+#define GL_ES_VERSION_2_0 1
+
+/* OpenGL ES 2.0 */
+
+/* ClearBufferMask */
+#define GL_DEPTH_BUFFER_BIT 0x00000100
+#define GL_STENCIL_BUFFER_BIT 0x00000400
+#define GL_COLOR_BUFFER_BIT 0x00004000
+
+/* Boolean */
+#define GL_FALSE 0
+#define GL_TRUE 1
+
+/* BeginMode */
+#define GL_POINTS 0x0000
+#define GL_LINES 0x0001
+#define GL_LINE_LOOP 0x0002
+#define GL_LINE_STRIP 0x0003
+#define GL_TRIANGLES 0x0004
+#define GL_TRIANGLE_STRIP 0x0005
+#define GL_TRIANGLE_FAN 0x0006
+
+/* BlendingFactorDest */
+#define GL_ZERO 0
+#define GL_ONE 1
+#define GL_SRC_COLOR 0x0300
+#define GL_ONE_MINUS_SRC_COLOR 0x0301
+#define GL_SRC_ALPHA 0x0302
+#define GL_ONE_MINUS_SRC_ALPHA 0x0303
+#define GL_DST_ALPHA 0x0304
+#define GL_ONE_MINUS_DST_ALPHA 0x0305
+
+/* BlendingFactorSrc */
+/* GL_ZERO */
+/* GL_ONE */
+#define GL_DST_COLOR 0x0306
+#define GL_ONE_MINUS_DST_COLOR 0x0307
+#define GL_SRC_ALPHA_SATURATE 0x0308
+/* GL_SRC_ALPHA */
+/* GL_ONE_MINUS_SRC_ALPHA */
+/* GL_DST_ALPHA */
+/* GL_ONE_MINUS_DST_ALPHA */
+
+/* BlendEquationSeparate */
+#define GL_FUNC_ADD 0x8006
+#define GL_BLEND_EQUATION 0x8009
+#define GL_BLEND_EQUATION_RGB 0x8009 /* same as BLEND_EQUATION */
+#define GL_BLEND_EQUATION_ALPHA 0x883D
+
+/* BlendSubtract */
+#define GL_FUNC_SUBTRACT 0x800A
+#define GL_FUNC_REVERSE_SUBTRACT 0x800B
+
+/* Separate Blend Functions */
+#define GL_BLEND_DST_RGB 0x80C8
+#define GL_BLEND_SRC_RGB 0x80C9
+#define GL_BLEND_DST_ALPHA 0x80CA
+#define GL_BLEND_SRC_ALPHA 0x80CB
+#define GL_CONSTANT_COLOR 0x8001
+#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002
+#define GL_CONSTANT_ALPHA 0x8003
+#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004
+#define GL_BLEND_COLOR 0x8005
+
+/* Buffer Objects */
+#define GL_ARRAY_BUFFER 0x8892
+#define GL_ELEMENT_ARRAY_BUFFER 0x8893
+#define GL_ARRAY_BUFFER_BINDING 0x8894
+#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895
+
+#define GL_STREAM_DRAW 0x88E0
+#define GL_STATIC_DRAW 0x88E4
+#define GL_DYNAMIC_DRAW 0x88E8
+
+#define GL_BUFFER_SIZE 0x8764
+#define GL_BUFFER_USAGE 0x8765
+
+#define GL_CURRENT_VERTEX_ATTRIB 0x8626
+
+/* CullFaceMode */
+#define GL_FRONT 0x0404
+#define GL_BACK 0x0405
+#define GL_FRONT_AND_BACK 0x0408
+
+/* DepthFunction */
+/* GL_NEVER */
+/* GL_LESS */
+/* GL_EQUAL */
+/* GL_LEQUAL */
+/* GL_GREATER */
+/* GL_NOTEQUAL */
+/* GL_GEQUAL */
+/* GL_ALWAYS */
+
+/* EnableCap */
+#define GL_TEXTURE_2D 0x0DE1
+#define GL_CULL_FACE 0x0B44
+#define GL_BLEND 0x0BE2
+#define GL_DITHER 0x0BD0
+#define GL_STENCIL_TEST 0x0B90
+#define GL_DEPTH_TEST 0x0B71
+#define GL_SCISSOR_TEST 0x0C11
+#define GL_POLYGON_OFFSET_FILL 0x8037
+#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E
+#define GL_SAMPLE_COVERAGE 0x80A0
+
+/* ErrorCode */
+#define GL_NO_ERROR 0
+#define GL_INVALID_ENUM 0x0500
+#define GL_INVALID_VALUE 0x0501
+#define GL_INVALID_OPERATION 0x0502
+#define GL_OUT_OF_MEMORY 0x0505
+
+/* FrontFaceDirection */
+#define GL_CW 0x0900
+#define GL_CCW 0x0901
+
+/* GetPName */
+#define GL_LINE_WIDTH 0x0B21
+#define GL_ALIASED_POINT_SIZE_RANGE 0x846D
+#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E
+#define GL_CULL_FACE_MODE 0x0B45
+#define GL_FRONT_FACE 0x0B46
+#define GL_DEPTH_RANGE 0x0B70
+#define GL_DEPTH_WRITEMASK 0x0B72
+#define GL_DEPTH_CLEAR_VALUE 0x0B73
+#define GL_DEPTH_FUNC 0x0B74
+#define GL_STENCIL_CLEAR_VALUE 0x0B91
+#define GL_STENCIL_FUNC 0x0B92
+#define GL_STENCIL_FAIL 0x0B94
+#define GL_STENCIL_PASS_DEPTH_FAIL 0x0B95
+#define GL_STENCIL_PASS_DEPTH_PASS 0x0B96
+#define GL_STENCIL_REF 0x0B97
+#define GL_STENCIL_VALUE_MASK 0x0B93
+#define GL_STENCIL_WRITEMASK 0x0B98
+#define GL_STENCIL_BACK_FUNC 0x8800
+#define GL_STENCIL_BACK_FAIL 0x8801
+#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802
+#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803
+#define GL_STENCIL_BACK_REF 0x8CA3
+#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4
+#define GL_STENCIL_BACK_WRITEMASK 0x8CA5
+#define GL_VIEWPORT 0x0BA2
+#define GL_SCISSOR_BOX 0x0C10
+/* GL_SCISSOR_TEST */
+#define GL_COLOR_CLEAR_VALUE 0x0C22
+#define GL_COLOR_WRITEMASK 0x0C23
+#define GL_UNPACK_ALIGNMENT 0x0CF5
+#define GL_PACK_ALIGNMENT 0x0D05
+#define GL_MAX_TEXTURE_SIZE 0x0D33
+#define GL_MAX_VIEWPORT_DIMS 0x0D3A
+#define GL_SUBPIXEL_BITS 0x0D50
+#define GL_RED_BITS 0x0D52
+#define GL_GREEN_BITS 0x0D53
+#define GL_BLUE_BITS 0x0D54
+#define GL_ALPHA_BITS 0x0D55
+#define GL_DEPTH_BITS 0x0D56
+#define GL_STENCIL_BITS 0x0D57
+#define GL_POLYGON_OFFSET_UNITS 0x2A00
+/* GL_POLYGON_OFFSET_FILL */
+#define GL_POLYGON_OFFSET_FACTOR 0x8038
+#define GL_TEXTURE_BINDING_2D 0x8069
+#define GL_SAMPLE_BUFFERS 0x80A8
+#define GL_SAMPLES 0x80A9
+#define GL_SAMPLE_COVERAGE_VALUE 0x80AA
+#define GL_SAMPLE_COVERAGE_INVERT 0x80AB
+
+/* GetTextureParameter */
+/* GL_TEXTURE_MAG_FILTER */
+/* GL_TEXTURE_MIN_FILTER */
+/* GL_TEXTURE_WRAP_S */
+/* GL_TEXTURE_WRAP_T */
+
+#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2
+#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3
+
+/* HintMode */
+#define GL_DONT_CARE 0x1100
+#define GL_FASTEST 0x1101
+#define GL_NICEST 0x1102
+
+/* HintTarget */
+#define GL_GENERATE_MIPMAP_HINT 0x8192
+
+/* DataType */
+#define GL_BYTE 0x1400
+#define GL_UNSIGNED_BYTE 0x1401
+#define GL_SHORT 0x1402
+#define GL_UNSIGNED_SHORT 0x1403
+#define GL_INT 0x1404
+#define GL_UNSIGNED_INT 0x1405
+#define GL_FLOAT 0x1406
+#define GL_FIXED 0x140C
+
+/* PixelFormat */
+#define GL_DEPTH_COMPONENT 0x1902
+#define GL_ALPHA 0x1906
+#define GL_RGB 0x1907
+#define GL_RGBA 0x1908
+#define GL_LUMINANCE 0x1909
+#define GL_LUMINANCE_ALPHA 0x190A
+
+/* PixelType */
+/* GL_UNSIGNED_BYTE */
+#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033
+#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034
+#define GL_UNSIGNED_SHORT_5_6_5 0x8363
+
+/* Shaders */
+#define GL_FRAGMENT_SHADER 0x8B30
+#define GL_VERTEX_SHADER 0x8B31
+#define GL_MAX_VERTEX_ATTRIBS 0x8869
+#define GL_MAX_VERTEX_UNIFORM_VECTORS 0x8DFB
+#define GL_MAX_VARYING_VECTORS 0x8DFC
+#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D
+#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C
+#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872
+#define GL_MAX_FRAGMENT_UNIFORM_VECTORS 0x8DFD
+#define GL_SHADER_TYPE 0x8B4F
+#define GL_DELETE_STATUS 0x8B80
+#define GL_LINK_STATUS 0x8B82
+#define GL_VALIDATE_STATUS 0x8B83
+#define GL_ATTACHED_SHADERS 0x8B85
+#define GL_ACTIVE_UNIFORMS 0x8B86
+#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87
+#define GL_ACTIVE_ATTRIBUTES 0x8B89
+#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A
+#define GL_SHADING_LANGUAGE_VERSION 0x8B8C
+#define GL_CURRENT_PROGRAM 0x8B8D
+
+/* StencilFunction */
+#define GL_NEVER 0x0200
+#define GL_LESS 0x0201
+#define GL_EQUAL 0x0202
+#define GL_LEQUAL 0x0203
+#define GL_GREATER 0x0204
+#define GL_NOTEQUAL 0x0205
+#define GL_GEQUAL 0x0206
+#define GL_ALWAYS 0x0207
+
+/* StencilOp */
+/* GL_ZERO */
+#define GL_KEEP 0x1E00
+#define GL_REPLACE 0x1E01
+#define GL_INCR 0x1E02
+#define GL_DECR 0x1E03
+#define GL_INVERT 0x150A
+#define GL_INCR_WRAP 0x8507
+#define GL_DECR_WRAP 0x8508
+
+/* StringName */
+#define GL_VENDOR 0x1F00
+#define GL_RENDERER 0x1F01
+#define GL_VERSION 0x1F02
+#define GL_EXTENSIONS 0x1F03
+
+/* TextureMagFilter */
+#define GL_NEAREST 0x2600
+#define GL_LINEAR 0x2601
+
+/* TextureMinFilter */
+/* GL_NEAREST */
+/* GL_LINEAR */
+#define GL_NEAREST_MIPMAP_NEAREST 0x2700
+#define GL_LINEAR_MIPMAP_NEAREST 0x2701
+#define GL_NEAREST_MIPMAP_LINEAR 0x2702
+#define GL_LINEAR_MIPMAP_LINEAR 0x2703
+
+/* TextureParameterName */
+#define GL_TEXTURE_MAG_FILTER 0x2800
+#define GL_TEXTURE_MIN_FILTER 0x2801
+#define GL_TEXTURE_WRAP_S 0x2802
+#define GL_TEXTURE_WRAP_T 0x2803
+
+/* TextureTarget */
+/* GL_TEXTURE_2D */
+#define GL_TEXTURE 0x1702
+
+#define GL_TEXTURE_CUBE_MAP 0x8513
+#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A
+#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C
+
+/* TextureUnit */
+#define GL_TEXTURE0 0x84C0
+#define GL_TEXTURE1 0x84C1
+#define GL_TEXTURE2 0x84C2
+#define GL_TEXTURE3 0x84C3
+#define GL_TEXTURE4 0x84C4
+#define GL_TEXTURE5 0x84C5
+#define GL_TEXTURE6 0x84C6
+#define GL_TEXTURE7 0x84C7
+#define GL_TEXTURE8 0x84C8
+#define GL_TEXTURE9 0x84C9
+#define GL_TEXTURE10 0x84CA
+#define GL_TEXTURE11 0x84CB
+#define GL_TEXTURE12 0x84CC
+#define GL_TEXTURE13 0x84CD
+#define GL_TEXTURE14 0x84CE
+#define GL_TEXTURE15 0x84CF
+#define GL_TEXTURE16 0x84D0
+#define GL_TEXTURE17 0x84D1
+#define GL_TEXTURE18 0x84D2
+#define GL_TEXTURE19 0x84D3
+#define GL_TEXTURE20 0x84D4
+#define GL_TEXTURE21 0x84D5
+#define GL_TEXTURE22 0x84D6
+#define GL_TEXTURE23 0x84D7
+#define GL_TEXTURE24 0x84D8
+#define GL_TEXTURE25 0x84D9
+#define GL_TEXTURE26 0x84DA
+#define GL_TEXTURE27 0x84DB
+#define GL_TEXTURE28 0x84DC
+#define GL_TEXTURE29 0x84DD
+#define GL_TEXTURE30 0x84DE
+#define GL_TEXTURE31 0x84DF
+#define GL_ACTIVE_TEXTURE 0x84E0
+
+/* TextureWrapMode */
+#define GL_REPEAT 0x2901
+#define GL_CLAMP_TO_EDGE 0x812F
+#define GL_MIRRORED_REPEAT 0x8370
+
+/* Uniform Types */
+#define GL_FLOAT_VEC2 0x8B50
+#define GL_FLOAT_VEC3 0x8B51
+#define GL_FLOAT_VEC4 0x8B52
+#define GL_INT_VEC2 0x8B53
+#define GL_INT_VEC3 0x8B54
+#define GL_INT_VEC4 0x8B55
+#define GL_BOOL 0x8B56
+#define GL_BOOL_VEC2 0x8B57
+#define GL_BOOL_VEC3 0x8B58
+#define GL_BOOL_VEC4 0x8B59
+#define GL_FLOAT_MAT2 0x8B5A
+#define GL_FLOAT_MAT3 0x8B5B
+#define GL_FLOAT_MAT4 0x8B5C
+#define GL_SAMPLER_2D 0x8B5E
+#define GL_SAMPLER_CUBE 0x8B60
+
+/* Vertex Arrays */
+#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622
+#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623
+#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624
+#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625
+#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A
+#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645
+#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F
+
+/* Read Format */
+#define GL_IMPLEMENTATION_COLOR_READ_TYPE 0x8B9A
+#define GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B
+
+/* Shader Source */
+#define GL_COMPILE_STATUS 0x8B81
+#define GL_INFO_LOG_LENGTH 0x8B84
+#define GL_SHADER_SOURCE_LENGTH 0x8B88
+#define GL_SHADER_COMPILER 0x8DFA
+
+/* Shader Binary */
+#define GL_SHADER_BINARY_FORMATS 0x8DF8
+#define GL_NUM_SHADER_BINARY_FORMATS 0x8DF9
+
+/* Shader Precision-Specified Types */
+#define GL_LOW_FLOAT 0x8DF0
+#define GL_MEDIUM_FLOAT 0x8DF1
+#define GL_HIGH_FLOAT 0x8DF2
+#define GL_LOW_INT 0x8DF3
+#define GL_MEDIUM_INT 0x8DF4
+#define GL_HIGH_INT 0x8DF5
+
+/* Framebuffer Object. */
+#define GL_FRAMEBUFFER 0x8D40
+#define GL_RENDERBUFFER 0x8D41
+
+#define GL_RGBA4 0x8056
+#define GL_RGB5_A1 0x8057
+#define GL_RGB565 0x8D62
+#define GL_DEPTH_COMPONENT16 0x81A5
+#define GL_STENCIL_INDEX8 0x8D48
+
+#define GL_RENDERBUFFER_WIDTH 0x8D42
+#define GL_RENDERBUFFER_HEIGHT 0x8D43
+#define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44
+#define GL_RENDERBUFFER_RED_SIZE 0x8D50
+#define GL_RENDERBUFFER_GREEN_SIZE 0x8D51
+#define GL_RENDERBUFFER_BLUE_SIZE 0x8D52
+#define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53
+#define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54
+#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55
+
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3
+
+#define GL_COLOR_ATTACHMENT0 0x8CE0
+#define GL_DEPTH_ATTACHMENT 0x8D00
+#define GL_STENCIL_ATTACHMENT 0x8D20
+
+#define GL_NONE 0
+
+#define GL_FRAMEBUFFER_COMPLETE 0x8CD5
+#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6
+#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7
+#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS 0x8CD9
+#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD
+
+#define GL_FRAMEBUFFER_BINDING 0x8CA6
+#define GL_RENDERBUFFER_BINDING 0x8CA7
+#define GL_MAX_RENDERBUFFER_SIZE 0x84E8
+
+#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506
+
+/* OpenGL ES 3.0 */
+
+#define GL_READ_BUFFER 0x0C02
+#define GL_UNPACK_ROW_LENGTH 0x0CF2
+#define GL_UNPACK_SKIP_ROWS 0x0CF3
+#define GL_UNPACK_SKIP_PIXELS 0x0CF4
+#define GL_PACK_ROW_LENGTH 0x0D02
+#define GL_PACK_SKIP_ROWS 0x0D03
+#define GL_PACK_SKIP_PIXELS 0x0D04
+#define GL_COLOR 0x1800
+#define GL_DEPTH 0x1801
+#define GL_STENCIL 0x1802
+#define GL_RED 0x1903
+#define GL_RGB8 0x8051
+#define GL_RGBA8 0x8058
+#define GL_RGB10_A2 0x8059
+#define GL_TEXTURE_BINDING_3D 0x806A
+#define GL_UNPACK_SKIP_IMAGES 0x806D
+#define GL_UNPACK_IMAGE_HEIGHT 0x806E
+#define GL_TEXTURE_3D 0x806F
+#define GL_TEXTURE_WRAP_R 0x8072
+#define GL_MAX_3D_TEXTURE_SIZE 0x8073
+#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368
+#define GL_MAX_ELEMENTS_VERTICES 0x80E8
+#define GL_MAX_ELEMENTS_INDICES 0x80E9
+#define GL_TEXTURE_MIN_LOD 0x813A
+#define GL_TEXTURE_MAX_LOD 0x813B
+#define GL_TEXTURE_BASE_LEVEL 0x813C
+#define GL_TEXTURE_MAX_LEVEL 0x813D
+#define GL_MIN 0x8007
+#define GL_MAX 0x8008
+#define GL_DEPTH_COMPONENT24 0x81A6
+#define GL_MAX_TEXTURE_LOD_BIAS 0x84FD
+#define GL_TEXTURE_COMPARE_MODE 0x884C
+#define GL_TEXTURE_COMPARE_FUNC 0x884D
+#define GL_CURRENT_QUERY 0x8865
+#define GL_QUERY_RESULT 0x8866
+#define GL_QUERY_RESULT_AVAILABLE 0x8867
+#define GL_BUFFER_MAPPED 0x88BC
+#define GL_BUFFER_MAP_POINTER 0x88BD
+#define GL_STREAM_READ 0x88E1
+#define GL_STREAM_COPY 0x88E2
+#define GL_STATIC_READ 0x88E5
+#define GL_STATIC_COPY 0x88E6
+#define GL_DYNAMIC_READ 0x88E9
+#define GL_DYNAMIC_COPY 0x88EA
+#define GL_MAX_DRAW_BUFFERS 0x8824
+#define GL_DRAW_BUFFER0 0x8825
+#define GL_DRAW_BUFFER1 0x8826
+#define GL_DRAW_BUFFER2 0x8827
+#define GL_DRAW_BUFFER3 0x8828
+#define GL_DRAW_BUFFER4 0x8829
+#define GL_DRAW_BUFFER5 0x882A
+#define GL_DRAW_BUFFER6 0x882B
+#define GL_DRAW_BUFFER7 0x882C
+#define GL_DRAW_BUFFER8 0x882D
+#define GL_DRAW_BUFFER9 0x882E
+#define GL_DRAW_BUFFER10 0x882F
+#define GL_DRAW_BUFFER11 0x8830
+#define GL_DRAW_BUFFER12 0x8831
+#define GL_DRAW_BUFFER13 0x8832
+#define GL_DRAW_BUFFER14 0x8833
+#define GL_DRAW_BUFFER15 0x8834
+#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS 0x8B49
+#define GL_MAX_VERTEX_UNIFORM_COMPONENTS 0x8B4A
+#define GL_SAMPLER_3D 0x8B5F
+#define GL_SAMPLER_2D_SHADOW 0x8B62
+#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT 0x8B8B
+#define GL_PIXEL_PACK_BUFFER 0x88EB
+#define GL_PIXEL_UNPACK_BUFFER 0x88EC
+#define GL_PIXEL_PACK_BUFFER_BINDING 0x88ED
+#define GL_PIXEL_UNPACK_BUFFER_BINDING 0x88EF
+#define GL_FLOAT_MAT2x3 0x8B65
+#define GL_FLOAT_MAT2x4 0x8B66
+#define GL_FLOAT_MAT3x2 0x8B67
+#define GL_FLOAT_MAT3x4 0x8B68
+#define GL_FLOAT_MAT4x2 0x8B69
+#define GL_FLOAT_MAT4x3 0x8B6A
+#define GL_SRGB 0x8C40
+#define GL_SRGB8 0x8C41
+#define GL_SRGB8_ALPHA8 0x8C43
+#define GL_COMPARE_REF_TO_TEXTURE 0x884E
+#define GL_MAJOR_VERSION 0x821B
+#define GL_MINOR_VERSION 0x821C
+#define GL_NUM_EXTENSIONS 0x821D
+#define GL_RGBA32F 0x8814
+#define GL_RGB32F 0x8815
+#define GL_RGBA16F 0x881A
+#define GL_RGB16F 0x881B
+#define GL_VERTEX_ATTRIB_ARRAY_INTEGER 0x88FD
+#define GL_MAX_ARRAY_TEXTURE_LAYERS 0x88FF
+#define GL_MIN_PROGRAM_TEXEL_OFFSET 0x8904
+#define GL_MAX_PROGRAM_TEXEL_OFFSET 0x8905
+#define GL_MAX_VARYING_COMPONENTS 0x8B4B
+#define GL_TEXTURE_2D_ARRAY 0x8C1A
+#define GL_TEXTURE_BINDING_2D_ARRAY 0x8C1D
+#define GL_R11F_G11F_B10F 0x8C3A
+#define GL_UNSIGNED_INT_10F_11F_11F_REV 0x8C3B
+#define GL_RGB9_E5 0x8C3D
+#define GL_UNSIGNED_INT_5_9_9_9_REV 0x8C3E
+#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH 0x8C76
+#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE 0x8C7F
+#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS 0x8C80
+#define GL_TRANSFORM_FEEDBACK_VARYINGS 0x8C83
+#define GL_TRANSFORM_FEEDBACK_BUFFER_START 0x8C84
+#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE 0x8C85
+#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN 0x8C88
+#define GL_RASTERIZER_DISCARD 0x8C89
+#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS 0x8C8A
+#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS 0x8C8B
+#define GL_INTERLEAVED_ATTRIBS 0x8C8C
+#define GL_SEPARATE_ATTRIBS 0x8C8D
+#define GL_TRANSFORM_FEEDBACK_BUFFER 0x8C8E
+#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING 0x8C8F
+#define GL_RGBA32UI 0x8D70
+#define GL_RGB32UI 0x8D71
+#define GL_RGBA16UI 0x8D76
+#define GL_RGB16UI 0x8D77
+#define GL_RGBA8UI 0x8D7C
+#define GL_RGB8UI 0x8D7D
+#define GL_RGBA32I 0x8D82
+#define GL_RGB32I 0x8D83
+#define GL_RGBA16I 0x8D88
+#define GL_RGB16I 0x8D89
+#define GL_RGBA8I 0x8D8E
+#define GL_RGB8I 0x8D8F
+#define GL_RED_INTEGER 0x8D94
+#define GL_RGB_INTEGER 0x8D98
+#define GL_RGBA_INTEGER 0x8D99
+#define GL_SAMPLER_2D_ARRAY 0x8DC1
+#define GL_SAMPLER_2D_ARRAY_SHADOW 0x8DC4
+#define GL_SAMPLER_CUBE_SHADOW 0x8DC5
+#define GL_UNSIGNED_INT_VEC2 0x8DC6
+#define GL_UNSIGNED_INT_VEC3 0x8DC7
+#define GL_UNSIGNED_INT_VEC4 0x8DC8
+#define GL_INT_SAMPLER_2D 0x8DCA
+#define GL_INT_SAMPLER_3D 0x8DCB
+#define GL_INT_SAMPLER_CUBE 0x8DCC
+#define GL_INT_SAMPLER_2D_ARRAY 0x8DCF
+#define GL_UNSIGNED_INT_SAMPLER_2D 0x8DD2
+#define GL_UNSIGNED_INT_SAMPLER_3D 0x8DD3
+#define GL_UNSIGNED_INT_SAMPLER_CUBE 0x8DD4
+#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY 0x8DD7
+#define GL_BUFFER_ACCESS_FLAGS 0x911F
+#define GL_BUFFER_MAP_LENGTH 0x9120
+#define GL_BUFFER_MAP_OFFSET 0x9121
+#define GL_DEPTH_COMPONENT32F 0x8CAC
+#define GL_DEPTH32F_STENCIL8 0x8CAD
+#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV 0x8DAD
+#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING 0x8210
+#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE 0x8211
+#define GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE 0x8212
+#define GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE 0x8213
+#define GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE 0x8214
+#define GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE 0x8215
+#define GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE 0x8216
+#define GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE 0x8217
+#define GL_FRAMEBUFFER_DEFAULT 0x8218
+#define GL_FRAMEBUFFER_UNDEFINED 0x8219
+#define GL_DEPTH_STENCIL_ATTACHMENT 0x821A
+#define GL_DEPTH_STENCIL 0x84F9
+#define GL_UNSIGNED_INT_24_8 0x84FA
+#define GL_DEPTH24_STENCIL8 0x88F0
+#define GL_UNSIGNED_NORMALIZED 0x8C17
+#define GL_DRAW_FRAMEBUFFER_BINDING GL_FRAMEBUFFER_BINDING
+#define GL_READ_FRAMEBUFFER 0x8CA8
+#define GL_DRAW_FRAMEBUFFER 0x8CA9
+#define GL_READ_FRAMEBUFFER_BINDING 0x8CAA
+#define GL_RENDERBUFFER_SAMPLES 0x8CAB
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER 0x8CD4
+#define GL_MAX_COLOR_ATTACHMENTS 0x8CDF
+#define GL_COLOR_ATTACHMENT1 0x8CE1
+#define GL_COLOR_ATTACHMENT2 0x8CE2
+#define GL_COLOR_ATTACHMENT3 0x8CE3
+#define GL_COLOR_ATTACHMENT4 0x8CE4
+#define GL_COLOR_ATTACHMENT5 0x8CE5
+#define GL_COLOR_ATTACHMENT6 0x8CE6
+#define GL_COLOR_ATTACHMENT7 0x8CE7
+#define GL_COLOR_ATTACHMENT8 0x8CE8
+#define GL_COLOR_ATTACHMENT9 0x8CE9
+#define GL_COLOR_ATTACHMENT10 0x8CEA
+#define GL_COLOR_ATTACHMENT11 0x8CEB
+#define GL_COLOR_ATTACHMENT12 0x8CEC
+#define GL_COLOR_ATTACHMENT13 0x8CED
+#define GL_COLOR_ATTACHMENT14 0x8CEE
+#define GL_COLOR_ATTACHMENT15 0x8CEF
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56
+#define GL_MAX_SAMPLES 0x8D57
+#define GL_HALF_FLOAT 0x140B
+#define GL_MAP_READ_BIT 0x0001
+#define GL_MAP_WRITE_BIT 0x0002
+#define GL_MAP_INVALIDATE_RANGE_BIT 0x0004
+#define GL_MAP_INVALIDATE_BUFFER_BIT 0x0008
+#define GL_MAP_FLUSH_EXPLICIT_BIT 0x0010
+#define GL_MAP_UNSYNCHRONIZED_BIT 0x0020
+#define GL_RG 0x8227
+#define GL_RG_INTEGER 0x8228
+#define GL_R8 0x8229
+#define GL_RG8 0x822B
+#define GL_R16F 0x822D
+#define GL_R32F 0x822E
+#define GL_RG16F 0x822F
+#define GL_RG32F 0x8230
+#define GL_R8I 0x8231
+#define GL_R8UI 0x8232
+#define GL_R16I 0x8233
+#define GL_R16UI 0x8234
+#define GL_R32I 0x8235
+#define GL_R32UI 0x8236
+#define GL_RG8I 0x8237
+#define GL_RG8UI 0x8238
+#define GL_RG16I 0x8239
+#define GL_RG16UI 0x823A
+#define GL_RG32I 0x823B
+#define GL_RG32UI 0x823C
+#define GL_VERTEX_ARRAY_BINDING 0x85B5
+#define GL_R8_SNORM 0x8F94
+#define GL_RG8_SNORM 0x8F95
+#define GL_RGB8_SNORM 0x8F96
+#define GL_RGBA8_SNORM 0x8F97
+#define GL_SIGNED_NORMALIZED 0x8F9C
+#define GL_PRIMITIVE_RESTART_FIXED_INDEX 0x8D69
+#define GL_COPY_READ_BUFFER 0x8F36
+#define GL_COPY_WRITE_BUFFER 0x8F37
+#define GL_COPY_READ_BUFFER_BINDING GL_COPY_READ_BUFFER
+#define GL_COPY_WRITE_BUFFER_BINDING GL_COPY_WRITE_BUFFER
+#define GL_UNIFORM_BUFFER 0x8A11
+#define GL_UNIFORM_BUFFER_BINDING 0x8A28
+#define GL_UNIFORM_BUFFER_START 0x8A29
+#define GL_UNIFORM_BUFFER_SIZE 0x8A2A
+#define GL_MAX_VERTEX_UNIFORM_BLOCKS 0x8A2B
+#define GL_MAX_FRAGMENT_UNIFORM_BLOCKS 0x8A2D
+#define GL_MAX_COMBINED_UNIFORM_BLOCKS 0x8A2E
+#define GL_MAX_UNIFORM_BUFFER_BINDINGS 0x8A2F
+#define GL_MAX_UNIFORM_BLOCK_SIZE 0x8A30
+#define GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS 0x8A31
+#define GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS 0x8A33
+#define GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT 0x8A34
+#define GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH 0x8A35
+#define GL_ACTIVE_UNIFORM_BLOCKS 0x8A36
+#define GL_UNIFORM_TYPE 0x8A37
+#define GL_UNIFORM_SIZE 0x8A38
+#define GL_UNIFORM_NAME_LENGTH 0x8A39
+#define GL_UNIFORM_BLOCK_INDEX 0x8A3A
+#define GL_UNIFORM_OFFSET 0x8A3B
+#define GL_UNIFORM_ARRAY_STRIDE 0x8A3C
+#define GL_UNIFORM_MATRIX_STRIDE 0x8A3D
+#define GL_UNIFORM_IS_ROW_MAJOR 0x8A3E
+#define GL_UNIFORM_BLOCK_BINDING 0x8A3F
+#define GL_UNIFORM_BLOCK_DATA_SIZE 0x8A40
+#define GL_UNIFORM_BLOCK_NAME_LENGTH 0x8A41
+#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS 0x8A42
+#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES 0x8A43
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER 0x8A44
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER 0x8A46
+#define GL_INVALID_INDEX 0xFFFFFFFFu
+#define GL_MAX_VERTEX_OUTPUT_COMPONENTS 0x9122
+#define GL_MAX_FRAGMENT_INPUT_COMPONENTS 0x9125
+#define GL_MAX_SERVER_WAIT_TIMEOUT 0x9111
+#define GL_OBJECT_TYPE 0x9112
+#define GL_SYNC_CONDITION 0x9113
+#define GL_SYNC_STATUS 0x9114
+#define GL_SYNC_FLAGS 0x9115
+#define GL_SYNC_FENCE 0x9116
+#define GL_SYNC_GPU_COMMANDS_COMPLETE 0x9117
+#define GL_UNSIGNALED 0x9118
+#define GL_SIGNALED 0x9119
+#define GL_ALREADY_SIGNALED 0x911A
+#define GL_TIMEOUT_EXPIRED 0x911B
+#define GL_CONDITION_SATISFIED 0x911C
+#define GL_WAIT_FAILED 0x911D
+#define GL_SYNC_FLUSH_COMMANDS_BIT 0x00000001
+#define GL_TIMEOUT_IGNORED 0xFFFFFFFFFFFFFFFFull
+#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR 0x88FE
+#define GL_ANY_SAMPLES_PASSED 0x8C2F
+#define GL_ANY_SAMPLES_PASSED_CONSERVATIVE 0x8D6A
+#define GL_SAMPLER_BINDING 0x8919
+#define GL_RGB10_A2UI 0x906F
+#define GL_TEXTURE_SWIZZLE_R 0x8E42
+#define GL_TEXTURE_SWIZZLE_G 0x8E43
+#define GL_TEXTURE_SWIZZLE_B 0x8E44
+#define GL_TEXTURE_SWIZZLE_A 0x8E45
+#define GL_GREEN 0x1904
+#define GL_BLUE 0x1905
+#define GL_INT_2_10_10_10_REV 0x8D9F
+#define GL_TRANSFORM_FEEDBACK 0x8E22
+#define GL_TRANSFORM_FEEDBACK_PAUSED 0x8E23
+#define GL_TRANSFORM_FEEDBACK_ACTIVE 0x8E24
+#define GL_TRANSFORM_FEEDBACK_BINDING 0x8E25
+#define GL_PROGRAM_BINARY_RETRIEVABLE_HINT 0x8257
+#define GL_PROGRAM_BINARY_LENGTH 0x8741
+#define GL_NUM_PROGRAM_BINARY_FORMATS 0x87FE
+#define GL_PROGRAM_BINARY_FORMATS 0x87FF
+#define GL_COMPRESSED_R11_EAC 0x9270
+#define GL_COMPRESSED_SIGNED_R11_EAC 0x9271
+#define GL_COMPRESSED_RG11_EAC 0x9272
+#define GL_COMPRESSED_SIGNED_RG11_EAC 0x9273
+#define GL_COMPRESSED_RGB8_ETC2 0x9274
+#define GL_COMPRESSED_SRGB8_ETC2 0x9275
+#define GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9276
+#define GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9277
+#define GL_COMPRESSED_RGBA8_ETC2_EAC 0x9278
+#define GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC 0x9279
+#define GL_TEXTURE_IMMUTABLE_FORMAT 0x912F
+#define GL_MAX_ELEMENT_INDEX 0x8D6B
+#define GL_NUM_SAMPLE_COUNTS 0x9380
+#define GL_TEXTURE_IMMUTABLE_LEVELS 0x82DF
+
+/*-------------------------------------------------------------------------
+ * Entrypoint definitions
+ *-----------------------------------------------------------------------*/
+
+/* OpenGL ES 2.0 */
+
+GL_APICALL void GL_APIENTRY glActiveTexture (GLenum texture);
+GL_APICALL void GL_APIENTRY glAttachShader (GLuint program, GLuint shader);
+GL_APICALL void GL_APIENTRY glBindAttribLocation (GLuint program, GLuint index, const GLchar* name);
+GL_APICALL void GL_APIENTRY glBindBuffer (GLenum target, GLuint buffer);
+GL_APICALL void GL_APIENTRY glBindFramebuffer (GLenum target, GLuint framebuffer);
+GL_APICALL void GL_APIENTRY glBindRenderbuffer (GLenum target, GLuint renderbuffer);
+GL_APICALL void GL_APIENTRY glBindTexture (GLenum target, GLuint texture);
+GL_APICALL void GL_APIENTRY glBlendColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+GL_APICALL void GL_APIENTRY glBlendEquation (GLenum mode);
+GL_APICALL void GL_APIENTRY glBlendEquationSeparate (GLenum modeRGB, GLenum modeAlpha);
+GL_APICALL void GL_APIENTRY glBlendFunc (GLenum sfactor, GLenum dfactor);
+GL_APICALL void GL_APIENTRY glBlendFuncSeparate (GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+GL_APICALL void GL_APIENTRY glBufferData (GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage);
+GL_APICALL void GL_APIENTRY glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data);
+GL_APICALL GLenum GL_APIENTRY glCheckFramebufferStatus (GLenum target);
+GL_APICALL void GL_APIENTRY glClear (GLbitfield mask);
+GL_APICALL void GL_APIENTRY glClearColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+GL_APICALL void GL_APIENTRY glClearDepthf (GLfloat depth);
+GL_APICALL void GL_APIENTRY glClearStencil (GLint s);
+GL_APICALL void GL_APIENTRY glColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+GL_APICALL void GL_APIENTRY glCompileShader (GLuint shader);
+GL_APICALL void GL_APIENTRY glCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* data);
+GL_APICALL void GL_APIENTRY glCompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid* data);
+GL_APICALL void GL_APIENTRY glCopyTexImage2D (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+GL_APICALL void GL_APIENTRY glCopyTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+GL_APICALL GLuint GL_APIENTRY glCreateProgram (void);
+GL_APICALL GLuint GL_APIENTRY glCreateShader (GLenum type);
+GL_APICALL void GL_APIENTRY glCullFace (GLenum mode);
+GL_APICALL void GL_APIENTRY glDeleteBuffers (GLsizei n, const GLuint* buffers);
+GL_APICALL void GL_APIENTRY glDeleteFramebuffers (GLsizei n, const GLuint* framebuffers);
+GL_APICALL void GL_APIENTRY glDeleteProgram (GLuint program);
+GL_APICALL void GL_APIENTRY glDeleteRenderbuffers (GLsizei n, const GLuint* renderbuffers);
+GL_APICALL void GL_APIENTRY glDeleteShader (GLuint shader);
+GL_APICALL void GL_APIENTRY glDeleteTextures (GLsizei n, const GLuint* textures);
+GL_APICALL void GL_APIENTRY glDepthFunc (GLenum func);
+GL_APICALL void GL_APIENTRY glDepthMask (GLboolean flag);
+GL_APICALL void GL_APIENTRY glDepthRangef (GLfloat n, GLfloat f);
+GL_APICALL void GL_APIENTRY glDetachShader (GLuint program, GLuint shader);
+GL_APICALL void GL_APIENTRY glDisable (GLenum cap);
+GL_APICALL void GL_APIENTRY glDisableVertexAttribArray (GLuint index);
+GL_APICALL void GL_APIENTRY glDrawArrays (GLenum mode, GLint first, GLsizei count);
+GL_APICALL void GL_APIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const GLvoid* indices);
+GL_APICALL void GL_APIENTRY glEnable (GLenum cap);
+GL_APICALL void GL_APIENTRY glEnableVertexAttribArray (GLuint index);
+GL_APICALL void GL_APIENTRY glFinish (void);
+GL_APICALL void GL_APIENTRY glFlush (void);
+GL_APICALL void GL_APIENTRY glFramebufferRenderbuffer (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+GL_APICALL void GL_APIENTRY glFramebufferTexture2D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+GL_APICALL void GL_APIENTRY glFrontFace (GLenum mode);
+GL_APICALL void GL_APIENTRY glGenBuffers (GLsizei n, GLuint* buffers);
+GL_APICALL void GL_APIENTRY glGenerateMipmap (GLenum target);
+GL_APICALL void GL_APIENTRY glGenFramebuffers (GLsizei n, GLuint* framebuffers);
+GL_APICALL void GL_APIENTRY glGenRenderbuffers (GLsizei n, GLuint* renderbuffers);
+GL_APICALL void GL_APIENTRY glGenTextures (GLsizei n, GLuint* textures);
+GL_APICALL void GL_APIENTRY glGetActiveAttrib (GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name);
+GL_APICALL void GL_APIENTRY glGetActiveUniform (GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name);
+GL_APICALL void GL_APIENTRY glGetAttachedShaders (GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders);
+GL_APICALL GLint GL_APIENTRY glGetAttribLocation (GLuint program, const GLchar* name);
+GL_APICALL void GL_APIENTRY glGetBooleanv (GLenum pname, GLboolean* params);
+GL_APICALL void GL_APIENTRY glGetBufferParameteriv (GLenum target, GLenum pname, GLint* params);
+GL_APICALL GLenum GL_APIENTRY glGetError (void);
+GL_APICALL void GL_APIENTRY glGetFloatv (GLenum pname, GLfloat* params);
+GL_APICALL void GL_APIENTRY glGetFramebufferAttachmentParameteriv (GLenum target, GLenum attachment, GLenum pname, GLint* params);
+GL_APICALL void GL_APIENTRY glGetIntegerv (GLenum pname, GLint* params);
+GL_APICALL void GL_APIENTRY glGetProgramiv (GLuint program, GLenum pname, GLint* params);
+GL_APICALL void GL_APIENTRY glGetProgramInfoLog (GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog);
+GL_APICALL void GL_APIENTRY glGetRenderbufferParameteriv (GLenum target, GLenum pname, GLint* params);
+GL_APICALL void GL_APIENTRY glGetShaderiv (GLuint shader, GLenum pname, GLint* params);
+GL_APICALL void GL_APIENTRY glGetShaderInfoLog (GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog);
+GL_APICALL void GL_APIENTRY glGetShaderPrecisionFormat (GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision);
+GL_APICALL void GL_APIENTRY glGetShaderSource (GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source);
+GL_APICALL const GLubyte* GL_APIENTRY glGetString (GLenum name);
+GL_APICALL void GL_APIENTRY glGetTexParameterfv (GLenum target, GLenum pname, GLfloat* params);
+GL_APICALL void GL_APIENTRY glGetTexParameteriv (GLenum target, GLenum pname, GLint* params);
+GL_APICALL void GL_APIENTRY glGetUniformfv (GLuint program, GLint location, GLfloat* params);
+GL_APICALL void GL_APIENTRY glGetUniformiv (GLuint program, GLint location, GLint* params);
+GL_APICALL GLint GL_APIENTRY glGetUniformLocation (GLuint program, const GLchar* name);
+GL_APICALL void GL_APIENTRY glGetVertexAttribfv (GLuint index, GLenum pname, GLfloat* params);
+GL_APICALL void GL_APIENTRY glGetVertexAttribiv (GLuint index, GLenum pname, GLint* params);
+GL_APICALL void GL_APIENTRY glGetVertexAttribPointerv (GLuint index, GLenum pname, GLvoid** pointer);
+GL_APICALL void GL_APIENTRY glHint (GLenum target, GLenum mode);
+GL_APICALL GLboolean GL_APIENTRY glIsBuffer (GLuint buffer);
+GL_APICALL GLboolean GL_APIENTRY glIsEnabled (GLenum cap);
+GL_APICALL GLboolean GL_APIENTRY glIsFramebuffer (GLuint framebuffer);
+GL_APICALL GLboolean GL_APIENTRY glIsProgram (GLuint program);
+GL_APICALL GLboolean GL_APIENTRY glIsRenderbuffer (GLuint renderbuffer);
+GL_APICALL GLboolean GL_APIENTRY glIsShader (GLuint shader);
+GL_APICALL GLboolean GL_APIENTRY glIsTexture (GLuint texture);
+GL_APICALL void GL_APIENTRY glLineWidth (GLfloat width);
+GL_APICALL void GL_APIENTRY glLinkProgram (GLuint program);
+GL_APICALL void GL_APIENTRY glPixelStorei (GLenum pname, GLint param);
+GL_APICALL void GL_APIENTRY glPolygonOffset (GLfloat factor, GLfloat units);
+GL_APICALL void GL_APIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels);
+GL_APICALL void GL_APIENTRY glReleaseShaderCompiler (void);
+GL_APICALL void GL_APIENTRY glRenderbufferStorage (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glSampleCoverage (GLfloat value, GLboolean invert);
+GL_APICALL void GL_APIENTRY glScissor (GLint x, GLint y, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glShaderBinary (GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length);
+GL_APICALL void GL_APIENTRY glShaderSource (GLuint shader, GLsizei count, const GLchar* const* string, const GLint* length);
+GL_APICALL void GL_APIENTRY glStencilFunc (GLenum func, GLint ref, GLuint mask);
+GL_APICALL void GL_APIENTRY glStencilFuncSeparate (GLenum face, GLenum func, GLint ref, GLuint mask);
+GL_APICALL void GL_APIENTRY glStencilMask (GLuint mask);
+GL_APICALL void GL_APIENTRY glStencilMaskSeparate (GLenum face, GLuint mask);
+GL_APICALL void GL_APIENTRY glStencilOp (GLenum fail, GLenum zfail, GLenum zpass);
+GL_APICALL void GL_APIENTRY glStencilOpSeparate (GLenum face, GLenum fail, GLenum zfail, GLenum zpass);
+GL_APICALL void GL_APIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* pixels);
+GL_APICALL void GL_APIENTRY glTexParameterf (GLenum target, GLenum pname, GLfloat param);
+GL_APICALL void GL_APIENTRY glTexParameterfv (GLenum target, GLenum pname, const GLfloat* params);
+GL_APICALL void GL_APIENTRY glTexParameteri (GLenum target, GLenum pname, GLint param);
+GL_APICALL void GL_APIENTRY glTexParameteriv (GLenum target, GLenum pname, const GLint* params);
+GL_APICALL void GL_APIENTRY glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* pixels);
+GL_APICALL void GL_APIENTRY glUniform1f (GLint location, GLfloat x);
+GL_APICALL void GL_APIENTRY glUniform1fv (GLint location, GLsizei count, const GLfloat* v);
+GL_APICALL void GL_APIENTRY glUniform1i (GLint location, GLint x);
+GL_APICALL void GL_APIENTRY glUniform1iv (GLint location, GLsizei count, const GLint* v);
+GL_APICALL void GL_APIENTRY glUniform2f (GLint location, GLfloat x, GLfloat y);
+GL_APICALL void GL_APIENTRY glUniform2fv (GLint location, GLsizei count, const GLfloat* v);
+GL_APICALL void GL_APIENTRY glUniform2i (GLint location, GLint x, GLint y);
+GL_APICALL void GL_APIENTRY glUniform2iv (GLint location, GLsizei count, const GLint* v);
+GL_APICALL void GL_APIENTRY glUniform3f (GLint location, GLfloat x, GLfloat y, GLfloat z);
+GL_APICALL void GL_APIENTRY glUniform3fv (GLint location, GLsizei count, const GLfloat* v);
+GL_APICALL void GL_APIENTRY glUniform3i (GLint location, GLint x, GLint y, GLint z);
+GL_APICALL void GL_APIENTRY glUniform3iv (GLint location, GLsizei count, const GLint* v);
+GL_APICALL void GL_APIENTRY glUniform4f (GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GL_APICALL void GL_APIENTRY glUniform4fv (GLint location, GLsizei count, const GLfloat* v);
+GL_APICALL void GL_APIENTRY glUniform4i (GLint location, GLint x, GLint y, GLint z, GLint w);
+GL_APICALL void GL_APIENTRY glUniform4iv (GLint location, GLsizei count, const GLint* v);
+GL_APICALL void GL_APIENTRY glUniformMatrix2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+GL_APICALL void GL_APIENTRY glUniformMatrix3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+GL_APICALL void GL_APIENTRY glUniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+GL_APICALL void GL_APIENTRY glUseProgram (GLuint program);
+GL_APICALL void GL_APIENTRY glValidateProgram (GLuint program);
+GL_APICALL void GL_APIENTRY glVertexAttrib1f (GLuint indx, GLfloat x);
+GL_APICALL void GL_APIENTRY glVertexAttrib1fv (GLuint indx, const GLfloat* values);
+GL_APICALL void GL_APIENTRY glVertexAttrib2f (GLuint indx, GLfloat x, GLfloat y);
+GL_APICALL void GL_APIENTRY glVertexAttrib2fv (GLuint indx, const GLfloat* values);
+GL_APICALL void GL_APIENTRY glVertexAttrib3f (GLuint indx, GLfloat x, GLfloat y, GLfloat z);
+GL_APICALL void GL_APIENTRY glVertexAttrib3fv (GLuint indx, const GLfloat* values);
+GL_APICALL void GL_APIENTRY glVertexAttrib4f (GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GL_APICALL void GL_APIENTRY glVertexAttrib4fv (GLuint indx, const GLfloat* values);
+GL_APICALL void GL_APIENTRY glVertexAttribPointer (GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr);
+GL_APICALL void GL_APIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height);
+
+/* OpenGL ES 3.0 */
+
+GL_APICALL void GL_APIENTRY glReadBuffer (GLenum mode);
+GL_APICALL void GL_APIENTRY glDrawRangeElements (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid* indices);
+GL_APICALL void GL_APIENTRY glTexImage3D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid* pixels);
+GL_APICALL void GL_APIENTRY glTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid* pixels);
+GL_APICALL void GL_APIENTRY glCopyTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glCompressedTexImage3D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data);
+GL_APICALL void GL_APIENTRY glCompressedTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid* data);
+GL_APICALL void GL_APIENTRY glGenQueries (GLsizei n, GLuint* ids);
+GL_APICALL void GL_APIENTRY glDeleteQueries (GLsizei n, const GLuint* ids);
+GL_APICALL GLboolean GL_APIENTRY glIsQuery (GLuint id);
+GL_APICALL void GL_APIENTRY glBeginQuery (GLenum target, GLuint id);
+GL_APICALL void GL_APIENTRY glEndQuery (GLenum target);
+GL_APICALL void GL_APIENTRY glGetQueryiv (GLenum target, GLenum pname, GLint* params);
+GL_APICALL void GL_APIENTRY glGetQueryObjectuiv (GLuint id, GLenum pname, GLuint* params);
+GL_APICALL GLboolean GL_APIENTRY glUnmapBuffer (GLenum target);
+GL_APICALL void GL_APIENTRY glGetBufferPointerv (GLenum target, GLenum pname, GLvoid** params);
+GL_APICALL void GL_APIENTRY glDrawBuffers (GLsizei n, const GLenum* bufs);
+GL_APICALL void GL_APIENTRY glUniformMatrix2x3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+GL_APICALL void GL_APIENTRY glUniformMatrix3x2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+GL_APICALL void GL_APIENTRY glUniformMatrix2x4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+GL_APICALL void GL_APIENTRY glUniformMatrix4x2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+GL_APICALL void GL_APIENTRY glUniformMatrix3x4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+GL_APICALL void GL_APIENTRY glUniformMatrix4x3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+GL_APICALL void GL_APIENTRY glBlitFramebuffer (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisample (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glFramebufferTextureLayer (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
+GL_APICALL GLvoid* GL_APIENTRY glMapBufferRange (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
+GL_APICALL void GL_APIENTRY glFlushMappedBufferRange (GLenum target, GLintptr offset, GLsizeiptr length);
+GL_APICALL void GL_APIENTRY glBindVertexArray (GLuint array);
+GL_APICALL void GL_APIENTRY glDeleteVertexArrays (GLsizei n, const GLuint* arrays);
+GL_APICALL void GL_APIENTRY glGenVertexArrays (GLsizei n, GLuint* arrays);
+GL_APICALL GLboolean GL_APIENTRY glIsVertexArray (GLuint array);
+GL_APICALL void GL_APIENTRY glGetIntegeri_v (GLenum target, GLuint index, GLint* data);
+GL_APICALL void GL_APIENTRY glBeginTransformFeedback (GLenum primitiveMode);
+GL_APICALL void GL_APIENTRY glEndTransformFeedback (void);
+GL_APICALL void GL_APIENTRY glBindBufferRange (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
+GL_APICALL void GL_APIENTRY glBindBufferBase (GLenum target, GLuint index, GLuint buffer);
+GL_APICALL void GL_APIENTRY glTransformFeedbackVaryings (GLuint program, GLsizei count, const GLchar* const* varyings, GLenum bufferMode);
+GL_APICALL void GL_APIENTRY glGetTransformFeedbackVarying (GLuint program, GLuint index, GLsizei bufSize, GLsizei* length, GLsizei* size, GLenum* type, GLchar* name);
+GL_APICALL void GL_APIENTRY glVertexAttribIPointer (GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid* pointer);
+GL_APICALL void GL_APIENTRY glGetVertexAttribIiv (GLuint index, GLenum pname, GLint* params);
+GL_APICALL void GL_APIENTRY glGetVertexAttribIuiv (GLuint index, GLenum pname, GLuint* params);
+GL_APICALL void GL_APIENTRY glVertexAttribI4i (GLuint index, GLint x, GLint y, GLint z, GLint w);
+GL_APICALL void GL_APIENTRY glVertexAttribI4ui (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+GL_APICALL void GL_APIENTRY glVertexAttribI4iv (GLuint index, const GLint* v);
+GL_APICALL void GL_APIENTRY glVertexAttribI4uiv (GLuint index, const GLuint* v);
+GL_APICALL void GL_APIENTRY glGetUniformuiv (GLuint program, GLint location, GLuint* params);
+GL_APICALL GLint GL_APIENTRY glGetFragDataLocation (GLuint program, const GLchar *name);
+GL_APICALL void GL_APIENTRY glUniform1ui (GLint location, GLuint v0);
+GL_APICALL void GL_APIENTRY glUniform2ui (GLint location, GLuint v0, GLuint v1);
+GL_APICALL void GL_APIENTRY glUniform3ui (GLint location, GLuint v0, GLuint v1, GLuint v2);
+GL_APICALL void GL_APIENTRY glUniform4ui (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+GL_APICALL void GL_APIENTRY glUniform1uiv (GLint location, GLsizei count, const GLuint* value);
+GL_APICALL void GL_APIENTRY glUniform2uiv (GLint location, GLsizei count, const GLuint* value);
+GL_APICALL void GL_APIENTRY glUniform3uiv (GLint location, GLsizei count, const GLuint* value);
+GL_APICALL void GL_APIENTRY glUniform4uiv (GLint location, GLsizei count, const GLuint* value);
+GL_APICALL void GL_APIENTRY glClearBufferiv (GLenum buffer, GLint drawbuffer, const GLint* value);
+GL_APICALL void GL_APIENTRY glClearBufferuiv (GLenum buffer, GLint drawbuffer, const GLuint* value);
+GL_APICALL void GL_APIENTRY glClearBufferfv (GLenum buffer, GLint drawbuffer, const GLfloat* value);
+GL_APICALL void GL_APIENTRY glClearBufferfi (GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
+GL_APICALL const GLubyte* GL_APIENTRY glGetStringi (GLenum name, GLuint index);
+GL_APICALL void GL_APIENTRY glCopyBufferSubData (GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
+GL_APICALL void GL_APIENTRY glGetUniformIndices (GLuint program, GLsizei uniformCount, const GLchar* const* uniformNames, GLuint* uniformIndices);
+GL_APICALL void GL_APIENTRY glGetActiveUniformsiv (GLuint program, GLsizei uniformCount, const GLuint* uniformIndices, GLenum pname, GLint* params);
+GL_APICALL GLuint GL_APIENTRY glGetUniformBlockIndex (GLuint program, const GLchar* uniformBlockName);
+GL_APICALL void GL_APIENTRY glGetActiveUniformBlockiv (GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params);
+GL_APICALL void GL_APIENTRY glGetActiveUniformBlockName (GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei* length, GLchar* uniformBlockName);
+GL_APICALL void GL_APIENTRY glUniformBlockBinding (GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding);
+GL_APICALL void GL_APIENTRY glDrawArraysInstanced (GLenum mode, GLint first, GLsizei count, GLsizei instanceCount);
+GL_APICALL void GL_APIENTRY glDrawElementsInstanced (GLenum mode, GLsizei count, GLenum type, const GLvoid* indices, GLsizei instanceCount);
+GL_APICALL GLsync GL_APIENTRY glFenceSync (GLenum condition, GLbitfield flags);
+GL_APICALL GLboolean GL_APIENTRY glIsSync (GLsync sync);
+GL_APICALL void GL_APIENTRY glDeleteSync (GLsync sync);
+GL_APICALL GLenum GL_APIENTRY glClientWaitSync (GLsync sync, GLbitfield flags, GLuint64 timeout);
+GL_APICALL void GL_APIENTRY glWaitSync (GLsync sync, GLbitfield flags, GLuint64 timeout);
+GL_APICALL void GL_APIENTRY glGetInteger64v (GLenum pname, GLint64* params);
+GL_APICALL void GL_APIENTRY glGetSynciv (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei* length, GLint* values);
+GL_APICALL void GL_APIENTRY glGetInteger64i_v (GLenum target, GLuint index, GLint64* data);
+GL_APICALL void GL_APIENTRY glGetBufferParameteri64v (GLenum target, GLenum pname, GLint64* params);
+GL_APICALL void GL_APIENTRY glGenSamplers (GLsizei count, GLuint* samplers);
+GL_APICALL void GL_APIENTRY glDeleteSamplers (GLsizei count, const GLuint* samplers);
+GL_APICALL GLboolean GL_APIENTRY glIsSampler (GLuint sampler);
+GL_APICALL void GL_APIENTRY glBindSampler (GLuint unit, GLuint sampler);
+GL_APICALL void GL_APIENTRY glSamplerParameteri (GLuint sampler, GLenum pname, GLint param);
+GL_APICALL void GL_APIENTRY glSamplerParameteriv (GLuint sampler, GLenum pname, const GLint* param);
+GL_APICALL void GL_APIENTRY glSamplerParameterf (GLuint sampler, GLenum pname, GLfloat param);
+GL_APICALL void GL_APIENTRY glSamplerParameterfv (GLuint sampler, GLenum pname, const GLfloat* param);
+GL_APICALL void GL_APIENTRY glGetSamplerParameteriv (GLuint sampler, GLenum pname, GLint* params);
+GL_APICALL void GL_APIENTRY glGetSamplerParameterfv (GLuint sampler, GLenum pname, GLfloat* params);
+GL_APICALL void GL_APIENTRY glVertexAttribDivisor (GLuint index, GLuint divisor);
+GL_APICALL void GL_APIENTRY glBindTransformFeedback (GLenum target, GLuint id);
+GL_APICALL void GL_APIENTRY glDeleteTransformFeedbacks (GLsizei n, const GLuint* ids);
+GL_APICALL void GL_APIENTRY glGenTransformFeedbacks (GLsizei n, GLuint* ids);
+GL_APICALL GLboolean GL_APIENTRY glIsTransformFeedback (GLuint id);
+GL_APICALL void GL_APIENTRY glPauseTransformFeedback (void);
+GL_APICALL void GL_APIENTRY glResumeTransformFeedback (void);
+GL_APICALL void GL_APIENTRY glGetProgramBinary (GLuint program, GLsizei bufSize, GLsizei* length, GLenum* binaryFormat, GLvoid* binary);
+GL_APICALL void GL_APIENTRY glProgramBinary (GLuint program, GLenum binaryFormat, const GLvoid* binary, GLsizei length);
+GL_APICALL void GL_APIENTRY glProgramParameteri (GLuint program, GLenum pname, GLint value);
+GL_APICALL void GL_APIENTRY glInvalidateFramebuffer (GLenum target, GLsizei numAttachments, const GLenum* attachments);
+GL_APICALL void GL_APIENTRY glInvalidateSubFramebuffer (GLenum target, GLsizei numAttachments, const GLenum* attachments, GLint x, GLint y, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glTexStorage2D (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glTexStorage3D (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+GL_APICALL void GL_APIENTRY glGetInternalformativ (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint* params);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/platform/winrt/include/GLES3/gl3ext.h b/platform/winrt/include/GLES3/gl3ext.h
new file mode 100644
index 0000000000..199436c082
--- /dev/null
+++ b/platform/winrt/include/GLES3/gl3ext.h
@@ -0,0 +1,24 @@
+#ifndef __gl3ext_h_
+#define __gl3ext_h_
+
+/* $Revision: 17809 $ on $Date:: 2012-05-14 08:03:36 -0700 #$ */
+
+/*
+ * This document is licensed under the SGI Free Software B License Version
+ * 2.0. For details, see http://oss.sgi.com/projects/FreeB/ .
+ */
+
+/* OpenGL ES 3 Extensions
+ *
+ * After an OES extension's interactions with OpenGl ES 3.0 have been documented,
+ * its tokens and function definitions should be added to this file in a manner
+ * that does not conflict with gl2ext.h or gl3.h.
+ *
+ * Tokens and function definitions for extensions that have become standard
+ * features in OpenGL ES 3.0 will not be added to this file.
+ *
+ * Applications using OpenGL-ES-2-only extensions should include gl2ext.h
+ */
+
+#endif /* __gl3ext_h_ */
+
diff --git a/platform/winrt/include/GLES3/gl3platform.h b/platform/winrt/include/GLES3/gl3platform.h
new file mode 100644
index 0000000000..679e0dc3ca
--- /dev/null
+++ b/platform/winrt/include/GLES3/gl3platform.h
@@ -0,0 +1,30 @@
+#ifndef __gl3platform_h_
+#define __gl3platform_h_
+
+/* $Revision: 18437 $ on $Date:: 2012-07-08 23:31:39 -0700 #$ */
+
+/*
+ * This document is licensed under the SGI Free Software B License Version
+ * 2.0. For details, see http://oss.sgi.com/projects/FreeB/ .
+ */
+
+/* Platform-specific types and definitions for OpenGL ES 3.X gl3.h
+ *
+ * Adopters may modify khrplatform.h and this file to suit their platform.
+ * You are encouraged to submit all modifications to the Khronos group so that
+ * they can be included in future versions of this file. Please submit changes
+ * by sending them to the public Khronos Bugzilla (http://khronos.org/bugzilla)
+ * by filing a bug against product "OpenGL-ES" component "Registry".
+ */
+
+#include <KHR/khrplatform.h>
+
+#ifndef GL_APICALL
+#define GL_APICALL KHRONOS_APICALL
+#endif
+
+#ifndef GL_APIENTRY
+#define GL_APIENTRY KHRONOS_APIENTRY
+#endif
+
+#endif /* __gl3platform_h_ */
diff --git a/platform/winrt/include/GLSLANG/ShaderLang.h b/platform/winrt/include/GLSLANG/ShaderLang.h
new file mode 100644
index 0000000000..86bf221c90
--- /dev/null
+++ b/platform/winrt/include/GLSLANG/ShaderLang.h
@@ -0,0 +1,513 @@
+//
+// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+#ifndef _COMPILER_INTERFACE_INCLUDED_
+#define _COMPILER_INTERFACE_INCLUDED_
+
+#if defined(COMPONENT_BUILD) && !defined(ANGLE_TRANSLATOR_STATIC)
+#if defined(_WIN32) || defined(_WIN64)
+
+#if defined(ANGLE_TRANSLATOR_IMPLEMENTATION)
+#define COMPILER_EXPORT __declspec(dllexport)
+#else
+#define COMPILER_EXPORT __declspec(dllimport)
+#endif // defined(ANGLE_TRANSLATOR_IMPLEMENTATION)
+
+#else // defined(_WIN32) || defined(_WIN64)
+#define COMPILER_EXPORT __attribute__((visibility("default")))
+#endif
+
+#else // defined(COMPONENT_BUILD) && !defined(ANGLE_TRANSLATOR_STATIC)
+#define COMPILER_EXPORT
+#endif
+
+#include <stddef.h>
+
+#include "KHR/khrplatform.h"
+
+//
+// This is the platform independent interface between an OGL driver
+// and the shading language compiler.
+//
+
+namespace sh
+{
+// GLenum alias
+typedef unsigned int GLenum;
+}
+
+// Must be included after GLenum proxy typedef
+#include "ShaderVars.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Version number for shader translation API.
+// It is incremented every time the API changes.
+#define ANGLE_SH_VERSION 129
+
+typedef enum {
+ SH_GLES2_SPEC = 0x8B40,
+ SH_WEBGL_SPEC = 0x8B41,
+
+ // The CSS Shaders spec is a subset of the WebGL spec.
+ //
+ // In both CSS vertex and fragment shaders, ANGLE:
+ // (1) Reserves the "css_" prefix.
+ // (2) Renames the main function to css_main.
+ // (3) Disables the gl_MaxDrawBuffers built-in.
+ //
+ // In CSS fragment shaders, ANGLE:
+ // (1) Disables the gl_FragColor built-in.
+ // (2) Disables the gl_FragData built-in.
+ // (3) Enables the css_MixColor built-in.
+ // (4) Enables the css_ColorMatrix built-in.
+ //
+ // After passing a CSS shader through ANGLE, the browser is expected to append
+ // a new main function to it.
+ // This new main function will call the css_main function.
+ // It may also perform additional operations like varying assignment, texture
+ // access, and gl_FragColor assignment in order to implement the CSS Shaders
+ // blend modes.
+ //
+ SH_CSS_SHADERS_SPEC = 0x8B42
+} ShShaderSpec;
+
+typedef enum {
+ SH_ESSL_OUTPUT = 0x8B45,
+ SH_GLSL_OUTPUT = 0x8B46,
+ SH_HLSL_OUTPUT = 0x8B47,
+ SH_HLSL9_OUTPUT = 0x8B47,
+ SH_HLSL11_OUTPUT = 0x8B48
+} ShShaderOutput;
+
+typedef enum {
+ SH_PRECISION_HIGHP = 0x5001,
+ SH_PRECISION_MEDIUMP = 0x5002,
+ SH_PRECISION_LOWP = 0x5003,
+ SH_PRECISION_UNDEFINED = 0
+} ShPrecisionType;
+
+typedef enum {
+ SH_INFO_LOG_LENGTH = 0x8B84,
+ SH_OBJECT_CODE_LENGTH = 0x8B88, // GL_SHADER_SOURCE_LENGTH
+ SH_ACTIVE_UNIFORMS = 0x8B86,
+ SH_ACTIVE_UNIFORM_MAX_LENGTH = 0x8B87,
+ SH_ACTIVE_ATTRIBUTES = 0x8B89,
+ SH_ACTIVE_ATTRIBUTE_MAX_LENGTH = 0x8B8A,
+ SH_VARYINGS = 0x8BBB,
+ SH_VARYING_MAX_LENGTH = 0x8BBC,
+ SH_MAPPED_NAME_MAX_LENGTH = 0x6000,
+ SH_NAME_MAX_LENGTH = 0x6001,
+ SH_HASHED_NAME_MAX_LENGTH = 0x6002,
+ SH_HASHED_NAMES_COUNT = 0x6003,
+ SH_SHADER_VERSION = 0x6004,
+ SH_RESOURCES_STRING_LENGTH = 0x6005,
+ SH_OUTPUT_TYPE = 0x6006
+} ShShaderInfo;
+
+// Compile options.
+typedef enum {
+ SH_VALIDATE = 0,
+ SH_VALIDATE_LOOP_INDEXING = 0x0001,
+ SH_INTERMEDIATE_TREE = 0x0002,
+ SH_OBJECT_CODE = 0x0004,
+ SH_VARIABLES = 0x0008,
+ SH_LINE_DIRECTIVES = 0x0010,
+ SH_SOURCE_PATH = 0x0020,
+ SH_UNROLL_FOR_LOOP_WITH_INTEGER_INDEX = 0x0040,
+ // If a sampler array index happens to be a loop index,
+ // 1) if its type is integer, unroll the loop.
+ // 2) if its type is float, fail the shader compile.
+ // This is to work around a mac driver bug.
+ SH_UNROLL_FOR_LOOP_WITH_SAMPLER_ARRAY_INDEX = 0x0080,
+
+ // This is needed only as a workaround for certain OpenGL driver bugs.
+ SH_EMULATE_BUILT_IN_FUNCTIONS = 0x0100,
+
+ // This is an experimental flag to enforce restrictions that aim to prevent
+ // timing attacks.
+ // It generates compilation errors for shaders that could expose sensitive
+ // texture information via the timing channel.
+ // To use this flag, you must compile the shader under the WebGL spec
+ // (using the SH_WEBGL_SPEC flag).
+ SH_TIMING_RESTRICTIONS = 0x0200,
+
+ // This flag prints the dependency graph that is used to enforce timing
+ // restrictions on fragment shaders.
+ // This flag only has an effect if all of the following are true:
+ // - The shader spec is SH_WEBGL_SPEC.
+ // - The compile options contain the SH_TIMING_RESTRICTIONS flag.
+ // - The shader type is GL_FRAGMENT_SHADER.
+ SH_DEPENDENCY_GRAPH = 0x0400,
+
+ // Enforce the GLSL 1.017 Appendix A section 7 packing restrictions.
+ // This flag only enforces (and can only enforce) the packing
+ // restrictions for uniform variables in both vertex and fragment
+ // shaders. ShCheckVariablesWithinPackingLimits() lets embedders
+ // enforce the packing restrictions for varying variables during
+ // program link time.
+ SH_ENFORCE_PACKING_RESTRICTIONS = 0x0800,
+
+ // This flag ensures all indirect (expression-based) array indexing
+ // is clamped to the bounds of the array. This ensures, for example,
+ // that you cannot read off the end of a uniform, whether an array
+ // vec234, or mat234 type. The ShArrayIndexClampingStrategy enum,
+ // specified in the ShBuiltInResources when constructing the
+ // compiler, selects the strategy for the clamping implementation.
+ SH_CLAMP_INDIRECT_ARRAY_BOUNDS = 0x1000,
+
+ // This flag limits the complexity of an expression.
+ SH_LIMIT_EXPRESSION_COMPLEXITY = 0x2000,
+
+ // This flag limits the depth of the call stack.
+ SH_LIMIT_CALL_STACK_DEPTH = 0x4000,
+
+ // This flag initializes gl_Position to vec4(0,0,0,0) at the
+ // beginning of the vertex shader's main(), and has no effect in the
+ // fragment shader. It is intended as a workaround for drivers which
+ // incorrectly fail to link programs if gl_Position is not written.
+ SH_INIT_GL_POSITION = 0x8000,
+
+ // This flag replaces
+ // "a && b" with "a ? b : false",
+ // "a || b" with "a ? true : b".
+ // This is to work around a MacOSX driver bug that |b| is executed
+ // independent of |a|'s value.
+ SH_UNFOLD_SHORT_CIRCUIT = 0x10000,
+
+ // This flag initializes varyings without static use in vertex shader
+ // at the beginning of main(), and has no effects in the fragment shader.
+ // It is intended as a workaround for drivers which incorrectly optimize
+ // out such varyings and cause a link failure.
+ SH_INIT_VARYINGS_WITHOUT_STATIC_USE = 0x20000,
+
+ // This flag scalarizes vec/ivec/bvec/mat constructor args.
+ // It is intended as a workaround for Linux/Mac driver bugs.
+ SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS = 0x40000,
+} ShCompileOptions;
+
+// Defines alternate strategies for implementing array index clamping.
+typedef enum {
+ // Use the clamp intrinsic for array index clamping.
+ SH_CLAMP_WITH_CLAMP_INTRINSIC = 1,
+
+ // Use a user-defined function for array index clamping.
+ SH_CLAMP_WITH_USER_DEFINED_INT_CLAMP_FUNCTION
+} ShArrayIndexClampingStrategy;
+
+//
+// Driver must call this first, once, before doing any other
+// compiler operations.
+// If the function succeeds, the return value is nonzero, else zero.
+//
+COMPILER_EXPORT int ShInitialize();
+//
+// Driver should call this at shutdown.
+// If the function succeeds, the return value is nonzero, else zero.
+//
+COMPILER_EXPORT int ShFinalize();
+
+// The 64 bits hash function. The first parameter is the input string; the
+// second parameter is the string length.
+typedef khronos_uint64_t (*ShHashFunction64)(const char*, size_t);
+
+//
+// Implementation dependent built-in resources (constants and extensions).
+// The names for these resources has been obtained by stripping gl_/GL_.
+//
+typedef struct
+{
+ // Constants.
+ int MaxVertexAttribs;
+ int MaxVertexUniformVectors;
+ int MaxVaryingVectors;
+ int MaxVertexTextureImageUnits;
+ int MaxCombinedTextureImageUnits;
+ int MaxTextureImageUnits;
+ int MaxFragmentUniformVectors;
+ int MaxDrawBuffers;
+
+ // Extensions.
+ // Set to 1 to enable the extension, else 0.
+ int OES_standard_derivatives;
+ int OES_EGL_image_external;
+ int ARB_texture_rectangle;
+ int EXT_draw_buffers;
+ int EXT_frag_depth;
+ int EXT_shader_texture_lod;
+
+ // Set to 1 if highp precision is supported in the fragment language.
+ // Default is 0.
+ int FragmentPrecisionHigh;
+
+ // GLSL ES 3.0 constants.
+ int MaxVertexOutputVectors;
+ int MaxFragmentInputVectors;
+ int MinProgramTexelOffset;
+ int MaxProgramTexelOffset;
+
+ // Name Hashing.
+ // Set a 64 bit hash function to enable user-defined name hashing.
+ // Default is NULL.
+ ShHashFunction64 HashFunction;
+
+ // Selects a strategy to use when implementing array index clamping.
+ // Default is SH_CLAMP_WITH_CLAMP_INTRINSIC.
+ ShArrayIndexClampingStrategy ArrayIndexClampingStrategy;
+
+ // The maximum complexity an expression can be.
+ int MaxExpressionComplexity;
+
+ // The maximum depth a call stack can be.
+ int MaxCallStackDepth;
+} ShBuiltInResources;
+
+//
+// Initialize built-in resources with minimum expected values.
+//
+COMPILER_EXPORT void ShInitBuiltInResources(ShBuiltInResources* resources);
+
+//
+// ShHandle held by but opaque to the driver. It is allocated,
+// managed, and de-allocated by the compiler. Its contents
+// are defined by and used by the compiler.
+//
+// If handle creation fails, 0 will be returned.
+//
+typedef void* ShHandle;
+
+//
+// Returns the a concatenated list of the items in ShBuiltInResources as a string.
+// This function must be updated whenever ShBuiltInResources is changed.
+// Parameters:
+// handle: Specifies the handle of the compiler to be used.
+// outStringLen: Specifies the size of the buffer, in number of characters. The size
+// of the buffer required to store the resources string can be obtained
+// by calling ShGetInfo with SH_RESOURCES_STRING_LENGTH.
+// outStr: Returns a null-terminated string representing all the built-in resources.
+COMPILER_EXPORT void ShGetBuiltInResourcesString(const ShHandle handle, size_t outStringLen, char *outStr);
+
+//
+// Driver calls these to create and destroy compiler objects.
+//
+// Returns the handle of constructed compiler, null if the requested compiler is
+// not supported.
+// Parameters:
+// type: Specifies the type of shader - GL_FRAGMENT_SHADER or GL_VERTEX_SHADER.
+// spec: Specifies the language spec the compiler must conform to -
+// SH_GLES2_SPEC or SH_WEBGL_SPEC.
+// output: Specifies the output code type - SH_ESSL_OUTPUT, SH_GLSL_OUTPUT,
+// SH_HLSL9_OUTPUT or SH_HLSL11_OUTPUT.
+// resources: Specifies the built-in resources.
+COMPILER_EXPORT ShHandle ShConstructCompiler(
+ sh::GLenum type,
+ ShShaderSpec spec,
+ ShShaderOutput output,
+ const ShBuiltInResources* resources);
+COMPILER_EXPORT void ShDestruct(ShHandle handle);
+
+//
+// Compiles the given shader source.
+// If the function succeeds, the return value is nonzero, else zero.
+// Parameters:
+// handle: Specifies the handle of compiler to be used.
+// shaderStrings: Specifies an array of pointers to null-terminated strings
+// containing the shader source code.
+// numStrings: Specifies the number of elements in shaderStrings array.
+// compileOptions: A mask containing the following parameters:
+// SH_VALIDATE: Validates shader to ensure that it conforms to the spec
+// specified during compiler construction.
+// SH_VALIDATE_LOOP_INDEXING: Validates loop and indexing in the shader to
+// ensure that they do not exceed the minimum
+// functionality mandated in GLSL 1.0 spec,
+// Appendix A, Section 4 and 5.
+// There is no need to specify this parameter when
+// compiling for WebGL - it is implied.
+// SH_INTERMEDIATE_TREE: Writes intermediate tree to info log.
+// Can be queried by calling ShGetInfoLog().
+// SH_OBJECT_CODE: Translates intermediate tree to glsl or hlsl shader.
+// Can be queried by calling ShGetObjectCode().
+// SH_VARIABLES: Extracts attributes, uniforms, and varyings.
+// Can be queried by calling ShGetVariableInfo().
+//
+COMPILER_EXPORT int ShCompile(
+ const ShHandle handle,
+ const char* const shaderStrings[],
+ size_t numStrings,
+ int compileOptions
+ );
+
+// Returns a parameter from a compiled shader.
+// Parameters:
+// handle: Specifies the compiler
+// pname: Specifies the parameter to query.
+// The following parameters are defined:
+// SH_INFO_LOG_LENGTH: the number of characters in the information log
+// including the null termination character.
+// SH_OBJECT_CODE_LENGTH: the number of characters in the object code
+// including the null termination character.
+// SH_ACTIVE_ATTRIBUTES: the number of active attribute variables.
+// SH_ACTIVE_ATTRIBUTE_MAX_LENGTH: the length of the longest active attribute
+// variable name including the null
+// termination character.
+// SH_ACTIVE_UNIFORMS: the number of active uniform variables.
+// SH_ACTIVE_UNIFORM_MAX_LENGTH: the length of the longest active uniform
+// variable name including the null
+// termination character.
+// SH_VARYINGS: the number of varying variables.
+// SH_VARYING_MAX_LENGTH: the length of the longest varying variable name
+// including the null termination character.
+// SH_MAPPED_NAME_MAX_LENGTH: the length of the mapped variable name including
+// the null termination character.
+// SH_NAME_MAX_LENGTH: the max length of a user-defined name including the
+// null termination character.
+// SH_HASHED_NAME_MAX_LENGTH: the max length of a hashed name including the
+// null termination character.
+// SH_HASHED_NAMES_COUNT: the number of hashed names from the latest compile.
+// SH_SHADER_VERSION: the version of the shader language
+// SH_OUTPUT_TYPE: the currently set language output type
+//
+// params: Requested parameter
+COMPILER_EXPORT void ShGetInfo(const ShHandle handle,
+ ShShaderInfo pname,
+ size_t* params);
+
+// Returns nul-terminated information log for a compiled shader.
+// Parameters:
+// handle: Specifies the compiler
+// infoLog: Specifies an array of characters that is used to return
+// the information log. It is assumed that infoLog has enough memory
+// to accomodate the information log. The size of the buffer required
+// to store the returned information log can be obtained by calling
+// ShGetInfo with SH_INFO_LOG_LENGTH.
+COMPILER_EXPORT void ShGetInfoLog(const ShHandle handle, char* infoLog);
+
+// Returns null-terminated object code for a compiled shader.
+// Parameters:
+// handle: Specifies the compiler
+// infoLog: Specifies an array of characters that is used to return
+// the object code. It is assumed that infoLog has enough memory to
+// accomodate the object code. The size of the buffer required to
+// store the returned object code can be obtained by calling
+// ShGetInfo with SH_OBJECT_CODE_LENGTH.
+COMPILER_EXPORT void ShGetObjectCode(const ShHandle handle, char* objCode);
+
+// Returns information about a shader variable.
+// Parameters:
+// handle: Specifies the compiler
+// variableType: Specifies the variable type; options include
+// SH_ACTIVE_ATTRIBUTES, SH_ACTIVE_UNIFORMS, SH_VARYINGS.
+// index: Specifies the index of the variable to be queried.
+// length: Returns the number of characters actually written in the string
+// indicated by name (excluding the null terminator) if a value other
+// than NULL is passed.
+// size: Returns the size of the variable.
+// type: Returns the data type of the variable.
+// precision: Returns the precision of the variable.
+// staticUse: Returns 1 if the variable is accessed in a statement after
+// pre-processing, whether or not run-time flow of control will
+// cause that statement to be executed.
+// Returns 0 otherwise.
+// name: Returns a null terminated string containing the name of the
+// variable. It is assumed that name has enough memory to accormodate
+// the variable name. The size of the buffer required to store the
+// variable name can be obtained by calling ShGetInfo with
+// SH_ACTIVE_ATTRIBUTE_MAX_LENGTH, SH_ACTIVE_UNIFORM_MAX_LENGTH,
+// SH_VARYING_MAX_LENGTH.
+// mappedName: Returns a null terminated string containing the mapped name of
+// the variable, It is assumed that mappedName has enough memory
+// (SH_MAPPED_NAME_MAX_LENGTH), or NULL if don't care about the
+// mapped name. If the name is not mapped, then name and mappedName
+// are the same.
+COMPILER_EXPORT void ShGetVariableInfo(const ShHandle handle,
+ ShShaderInfo variableType,
+ int index,
+ size_t* length,
+ int* size,
+ sh::GLenum* type,
+ ShPrecisionType* precision,
+ int* staticUse,
+ char* name,
+ char* mappedName);
+
+// Returns information about a name hashing entry from the latest compile.
+// Parameters:
+// handle: Specifies the compiler
+// index: Specifies the index of the name hashing entry to be queried.
+// name: Returns a null terminated string containing the user defined name.
+// It is assumed that name has enough memory to accomodate the name.
+// The size of the buffer required to store the user defined name can
+// be obtained by calling ShGetInfo with SH_NAME_MAX_LENGTH.
+// hashedName: Returns a null terminated string containing the hashed name of
+// the uniform variable, It is assumed that hashedName has enough
+// memory to accomodate the name. The size of the buffer required
+// to store the name can be obtained by calling ShGetInfo with
+// SH_HASHED_NAME_MAX_LENGTH.
+COMPILER_EXPORT void ShGetNameHashingEntry(const ShHandle handle,
+ int index,
+ char* name,
+ char* hashedName);
+
+// Shader variable inspection.
+// Returns a pointer to a list of variables of the designated type.
+// (See ShaderVars.h for type definitions, included above)
+// Returns NULL on failure.
+// Parameters:
+// handle: Specifies the compiler
+COMPILER_EXPORT const std::vector<sh::Uniform> *ShGetUniforms(const ShHandle handle);
+COMPILER_EXPORT const std::vector<sh::Varying> *ShGetVaryings(const ShHandle handle);
+COMPILER_EXPORT const std::vector<sh::Attribute> *ShGetAttributes(const ShHandle handle);
+COMPILER_EXPORT const std::vector<sh::Attribute> *ShGetOutputVariables(const ShHandle handle);
+COMPILER_EXPORT const std::vector<sh::InterfaceBlock> *ShGetInterfaceBlocks(const ShHandle handle);
+
+typedef struct
+{
+ sh::GLenum type;
+ int size;
+} ShVariableInfo;
+
+// Returns 1 if the passed in variables pack in maxVectors following
+// the packing rules from the GLSL 1.017 spec, Appendix A, section 7.
+// Returns 0 otherwise. Also look at the SH_ENFORCE_PACKING_RESTRICTIONS
+// flag above.
+// Parameters:
+// maxVectors: the available rows of registers.
+// varInfoArray: an array of variable info (types and sizes).
+// varInfoArraySize: the size of the variable array.
+COMPILER_EXPORT int ShCheckVariablesWithinPackingLimits(
+ int maxVectors,
+ ShVariableInfo* varInfoArray,
+ size_t varInfoArraySize);
+
+// Gives the compiler-assigned register for an interface block.
+// The method writes the value to the output variable "indexOut".
+// Returns true if it found a valid interface block, false otherwise.
+// Parameters:
+// handle: Specifies the compiler
+// interfaceBlockName: Specifies the interface block
+// indexOut: output variable that stores the assigned register
+COMPILER_EXPORT bool ShGetInterfaceBlockRegister(const ShHandle handle,
+ const char *interfaceBlockName,
+ unsigned int *indexOut);
+
+// Gives the compiler-assigned register for uniforms in the default
+// interface block.
+// The method writes the value to the output variable "indexOut".
+// Returns true if it found a valid default uniform, false otherwise.
+// Parameters:
+// handle: Specifies the compiler
+// interfaceBlockName: Specifies the uniform
+// indexOut: output variable that stores the assigned register
+COMPILER_EXPORT bool ShGetUniformRegister(const ShHandle handle,
+ const char *uniformName,
+ unsigned int *indexOut);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _COMPILER_INTERFACE_INCLUDED_
diff --git a/platform/winrt/include/GLSLANG/ShaderVars.h b/platform/winrt/include/GLSLANG/ShaderVars.h
new file mode 100644
index 0000000000..03ddf956f1
--- /dev/null
+++ b/platform/winrt/include/GLSLANG/ShaderVars.h
@@ -0,0 +1,128 @@
+//
+// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// ShaderVars.h:
+// Types to represent GL variables (varyings, uniforms, etc)
+//
+
+#ifndef _COMPILER_INTERFACE_VARIABLES_
+#define _COMPILER_INTERFACE_VARIABLES_
+
+#include <string>
+#include <vector>
+#include <algorithm>
+
+// Assume ShaderLang.h is included before ShaderVars.h, for sh::GLenum
+
+namespace sh
+{
+
+// Varying interpolation qualifier, see section 4.3.9 of the ESSL 3.00.4 spec
+enum InterpolationType
+{
+ INTERPOLATION_SMOOTH,
+ INTERPOLATION_CENTROID,
+ INTERPOLATION_FLAT
+};
+
+// Uniform block layout qualifier, see section 4.3.8.3 of the ESSL 3.00.4 spec
+enum BlockLayoutType
+{
+ BLOCKLAYOUT_STANDARD,
+ BLOCKLAYOUT_PACKED,
+ BLOCKLAYOUT_SHARED
+};
+
+// Base class for all variables defined in shaders, including Varyings, Uniforms, etc
+// Note: we must override the copy constructor and assignment operator so we can
+// work around excessive GCC binary bloating:
+// See https://code.google.com/p/angleproject/issues/detail?id=697
+struct ShaderVariable
+{
+ ShaderVariable();
+ ShaderVariable(GLenum typeIn, unsigned int arraySizeIn);
+ ~ShaderVariable();
+ ShaderVariable(const ShaderVariable &other);
+ ShaderVariable &operator=(const ShaderVariable &other);
+
+ bool isArray() const { return arraySize > 0; }
+ unsigned int elementCount() const { return std::max(1u, arraySize); }
+
+ GLenum type;
+ GLenum precision;
+ std::string name;
+ std::string mappedName;
+ unsigned int arraySize;
+ bool staticUse;
+};
+
+struct Uniform : public ShaderVariable
+{
+ Uniform();
+ ~Uniform();
+ Uniform(const Uniform &other);
+ Uniform &operator=(const Uniform &other);
+
+ bool isStruct() const { return !fields.empty(); }
+
+ std::vector<Uniform> fields;
+};
+
+struct Attribute : public ShaderVariable
+{
+ Attribute();
+ ~Attribute();
+ Attribute(const Attribute &other);
+ Attribute &operator=(const Attribute &other);
+
+ int location;
+};
+
+struct InterfaceBlockField : public ShaderVariable
+{
+ InterfaceBlockField();
+ ~InterfaceBlockField();
+ InterfaceBlockField(const InterfaceBlockField &other);
+ InterfaceBlockField &operator=(const InterfaceBlockField &other);
+
+ bool isStruct() const { return !fields.empty(); }
+
+ bool isRowMajorMatrix;
+ std::vector<InterfaceBlockField> fields;
+};
+
+struct Varying : public ShaderVariable
+{
+ Varying();
+ ~Varying();
+ Varying(const Varying &other);
+ Varying &operator=(const Varying &other);
+
+ bool isStruct() const { return !fields.empty(); }
+
+ InterpolationType interpolation;
+ std::vector<Varying> fields;
+ std::string structName;
+};
+
+struct InterfaceBlock
+{
+ InterfaceBlock();
+ ~InterfaceBlock();
+ InterfaceBlock(const InterfaceBlock &other);
+ InterfaceBlock &operator=(const InterfaceBlock &other);
+
+ std::string name;
+ std::string mappedName;
+ unsigned int arraySize;
+ BlockLayoutType layout;
+ bool isRowMajorLayout;
+ bool staticUse;
+ std::vector<InterfaceBlockField> fields;
+};
+
+}
+
+#endif // _COMPILER_INTERFACE_VARIABLES_
diff --git a/platform/winrt/include/KHR/khrplatform.h b/platform/winrt/include/KHR/khrplatform.h
new file mode 100644
index 0000000000..0921b895a5
--- /dev/null
+++ b/platform/winrt/include/KHR/khrplatform.h
@@ -0,0 +1,282 @@
+#ifndef __khrplatform_h_
+#define __khrplatform_h_
+
+/*
+** Copyright (c) 2008-2009 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+/* Khronos platform-specific types and definitions.
+ *
+ * $Revision: 23298 $ on $Date: 2013-09-30 17:07:13 -0700 (Mon, 30 Sep 2013) $
+ *
+ * Adopters may modify this file to suit their platform. Adopters are
+ * encouraged to submit platform specific modifications to the Khronos
+ * group so that they can be included in future versions of this file.
+ * Please submit changes by sending them to the public Khronos Bugzilla
+ * (http://khronos.org/bugzilla) by filing a bug against product
+ * "Khronos (general)" component "Registry".
+ *
+ * A predefined template which fills in some of the bug fields can be
+ * reached using http://tinyurl.com/khrplatform-h-bugreport, but you
+ * must create a Bugzilla login first.
+ *
+ *
+ * See the Implementer's Guidelines for information about where this file
+ * should be located on your system and for more details of its use:
+ * http://www.khronos.org/registry/implementers_guide.pdf
+ *
+ * This file should be included as
+ * #include <KHR/khrplatform.h>
+ * by Khronos client API header files that use its types and defines.
+ *
+ * The types in khrplatform.h should only be used to define API-specific types.
+ *
+ * Types defined in khrplatform.h:
+ * khronos_int8_t signed 8 bit
+ * khronos_uint8_t unsigned 8 bit
+ * khronos_int16_t signed 16 bit
+ * khronos_uint16_t unsigned 16 bit
+ * khronos_int32_t signed 32 bit
+ * khronos_uint32_t unsigned 32 bit
+ * khronos_int64_t signed 64 bit
+ * khronos_uint64_t unsigned 64 bit
+ * khronos_intptr_t signed same number of bits as a pointer
+ * khronos_uintptr_t unsigned same number of bits as a pointer
+ * khronos_ssize_t signed size
+ * khronos_usize_t unsigned size
+ * khronos_float_t signed 32 bit floating point
+ * khronos_time_ns_t unsigned 64 bit time in nanoseconds
+ * khronos_utime_nanoseconds_t unsigned time interval or absolute time in
+ * nanoseconds
+ * khronos_stime_nanoseconds_t signed time interval in nanoseconds
+ * khronos_boolean_enum_t enumerated boolean type. This should
+ * only be used as a base type when a client API's boolean type is
+ * an enum. Client APIs which use an integer or other type for
+ * booleans cannot use this as the base type for their boolean.
+ *
+ * Tokens defined in khrplatform.h:
+ *
+ * KHRONOS_FALSE, KHRONOS_TRUE Enumerated boolean false/true values.
+ *
+ * KHRONOS_SUPPORT_INT64 is 1 if 64 bit integers are supported; otherwise 0.
+ * KHRONOS_SUPPORT_FLOAT is 1 if floats are supported; otherwise 0.
+ *
+ * Calling convention macros defined in this file:
+ * KHRONOS_APICALL
+ * KHRONOS_APIENTRY
+ * KHRONOS_APIATTRIBUTES
+ *
+ * These may be used in function prototypes as:
+ *
+ * KHRONOS_APICALL void KHRONOS_APIENTRY funcname(
+ * int arg1,
+ * int arg2) KHRONOS_APIATTRIBUTES;
+ */
+
+/*-------------------------------------------------------------------------
+ * Definition of KHRONOS_APICALL
+ *-------------------------------------------------------------------------
+ * This precedes the return type of the function in the function prototype.
+ */
+#if defined(_WIN32) && !defined(__SCITECH_SNAP__)
+# define KHRONOS_APICALL __declspec(dllimport)
+#elif defined (__SYMBIAN32__)
+# define KHRONOS_APICALL IMPORT_C
+#else
+# define KHRONOS_APICALL
+#endif
+
+/*-------------------------------------------------------------------------
+ * Definition of KHRONOS_APIENTRY
+ *-------------------------------------------------------------------------
+ * This follows the return type of the function and precedes the function
+ * name in the function prototype.
+ */
+#if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(__SCITECH_SNAP__)
+ /* Win32 but not WinCE */
+# define KHRONOS_APIENTRY __stdcall
+#else
+# define KHRONOS_APIENTRY
+#endif
+
+/*-------------------------------------------------------------------------
+ * Definition of KHRONOS_APIATTRIBUTES
+ *-------------------------------------------------------------------------
+ * This follows the closing parenthesis of the function prototype arguments.
+ */
+#if defined (__ARMCC_2__)
+#define KHRONOS_APIATTRIBUTES __softfp
+#else
+#define KHRONOS_APIATTRIBUTES
+#endif
+
+/*-------------------------------------------------------------------------
+ * basic type definitions
+ *-----------------------------------------------------------------------*/
+#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__GNUC__) || defined(__SCO__) || defined(__USLC__)
+
+
+/*
+ * Using <stdint.h>
+ */
+#include <stdint.h>
+typedef int32_t khronos_int32_t;
+typedef uint32_t khronos_uint32_t;
+typedef int64_t khronos_int64_t;
+typedef uint64_t khronos_uint64_t;
+#define KHRONOS_SUPPORT_INT64 1
+#define KHRONOS_SUPPORT_FLOAT 1
+
+#elif defined(__VMS ) || defined(__sgi)
+
+/*
+ * Using <inttypes.h>
+ */
+#include <inttypes.h>
+typedef int32_t khronos_int32_t;
+typedef uint32_t khronos_uint32_t;
+typedef int64_t khronos_int64_t;
+typedef uint64_t khronos_uint64_t;
+#define KHRONOS_SUPPORT_INT64 1
+#define KHRONOS_SUPPORT_FLOAT 1
+
+#elif defined(_WIN32) && !defined(__SCITECH_SNAP__)
+
+/*
+ * Win32
+ */
+typedef __int32 khronos_int32_t;
+typedef unsigned __int32 khronos_uint32_t;
+typedef __int64 khronos_int64_t;
+typedef unsigned __int64 khronos_uint64_t;
+#define KHRONOS_SUPPORT_INT64 1
+#define KHRONOS_SUPPORT_FLOAT 1
+
+#elif defined(__sun__) || defined(__digital__)
+
+/*
+ * Sun or Digital
+ */
+typedef int khronos_int32_t;
+typedef unsigned int khronos_uint32_t;
+#if defined(__arch64__) || defined(_LP64)
+typedef long int khronos_int64_t;
+typedef unsigned long int khronos_uint64_t;
+#else
+typedef long long int khronos_int64_t;
+typedef unsigned long long int khronos_uint64_t;
+#endif /* __arch64__ */
+#define KHRONOS_SUPPORT_INT64 1
+#define KHRONOS_SUPPORT_FLOAT 1
+
+#elif 0
+
+/*
+ * Hypothetical platform with no float or int64 support
+ */
+typedef int khronos_int32_t;
+typedef unsigned int khronos_uint32_t;
+#define KHRONOS_SUPPORT_INT64 0
+#define KHRONOS_SUPPORT_FLOAT 0
+
+#else
+
+/*
+ * Generic fallback
+ */
+#include <stdint.h>
+typedef int32_t khronos_int32_t;
+typedef uint32_t khronos_uint32_t;
+typedef int64_t khronos_int64_t;
+typedef uint64_t khronos_uint64_t;
+#define KHRONOS_SUPPORT_INT64 1
+#define KHRONOS_SUPPORT_FLOAT 1
+
+#endif
+
+
+/*
+ * Types that are (so far) the same on all platforms
+ */
+typedef signed char khronos_int8_t;
+typedef unsigned char khronos_uint8_t;
+typedef signed short int khronos_int16_t;
+typedef unsigned short int khronos_uint16_t;
+
+/*
+ * Types that differ between LLP64 and LP64 architectures - in LLP64,
+ * pointers are 64 bits, but 'long' is still 32 bits. Win64 appears
+ * to be the only LLP64 architecture in current use.
+ */
+#ifdef _WIN64
+typedef signed long long int khronos_intptr_t;
+typedef unsigned long long int khronos_uintptr_t;
+typedef signed long long int khronos_ssize_t;
+typedef unsigned long long int khronos_usize_t;
+#else
+typedef signed long int khronos_intptr_t;
+typedef unsigned long int khronos_uintptr_t;
+typedef signed long int khronos_ssize_t;
+typedef unsigned long int khronos_usize_t;
+#endif
+
+#if KHRONOS_SUPPORT_FLOAT
+/*
+ * Float type
+ */
+typedef float khronos_float_t;
+#endif
+
+#if KHRONOS_SUPPORT_INT64
+/* Time types
+ *
+ * These types can be used to represent a time interval in nanoseconds or
+ * an absolute Unadjusted System Time. Unadjusted System Time is the number
+ * of nanoseconds since some arbitrary system event (e.g. since the last
+ * time the system booted). The Unadjusted System Time is an unsigned
+ * 64 bit value that wraps back to 0 every 584 years. Time intervals
+ * may be either signed or unsigned.
+ */
+typedef khronos_uint64_t khronos_utime_nanoseconds_t;
+typedef khronos_int64_t khronos_stime_nanoseconds_t;
+#endif
+
+/*
+ * Dummy value used to pad enum types to 32 bits.
+ */
+#ifndef KHRONOS_MAX_ENUM
+#define KHRONOS_MAX_ENUM 0x7FFFFFFF
+#endif
+
+/*
+ * Enumerated boolean type
+ *
+ * Values other than zero should be considered to be true. Therefore
+ * comparisons should not be made against KHRONOS_TRUE.
+ */
+typedef enum {
+ KHRONOS_FALSE = 0,
+ KHRONOS_TRUE = 1,
+ KHRONOS_BOOLEAN_ENUM_FORCE_SIZE = KHRONOS_MAX_ENUM
+} khronos_boolean_enum_t;
+
+#endif /* __khrplatform_h_ */
diff --git a/platform/winrt/include/angle_gl.h b/platform/winrt/include/angle_gl.h
new file mode 100644
index 0000000000..fadae33e26
--- /dev/null
+++ b/platform/winrt/include/angle_gl.h
@@ -0,0 +1,23 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// angle_gl.h:
+// Includes all necessary GL headers and definitions for ANGLE.
+//
+
+#ifndef ANGLE_GL_H_
+#define ANGLE_GL_H_
+
+#include "GLES2/gl2.h"
+#include "GLES2/gl2ext.h"
+#include "GLES3/gl3.h"
+#include "GLES3/gl3ext.h"
+
+// The following enum is used in ANGLE, but is from desktop GL
+#ifndef GL_SAMPLER_2D_RECT_ARB
+#define GL_SAMPLER_2D_RECT_ARB 0x8B63
+#endif
+
+#endif // ANGLE_GL_H_
diff --git a/platform/winrt/logo.png b/platform/winrt/logo.png
new file mode 100644
index 0000000000..a27e14dde8
--- /dev/null
+++ b/platform/winrt/logo.png
Binary files differ
diff --git a/platform/winrt/os_winrt.cpp b/platform/winrt/os_winrt.cpp
new file mode 100644
index 0000000000..16a74c877c
--- /dev/null
+++ b/platform/winrt/os_winrt.cpp
@@ -0,0 +1,756 @@
+/*************************************************************************/
+/* os_windows.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#include "drivers/gles2/rasterizer_gles2.h"
+#include "drivers/gles1/rasterizer_gles1.h"
+#include "os_windows.h"
+#include "drivers/nedmalloc/memory_pool_static_nedmalloc.h"
+#include "drivers/unix/memory_pool_static_malloc.h"
+#include "os/memory_pool_dynamic_static.h"
+#include "drivers/windows/thread_windows.h"
+#include "drivers/windows/semaphore_windows.h"
+#include "drivers/windows/mutex_windows.h"
+#include "main/main.h"
+#include "drivers/windows/file_access_windows.h"
+#include "drivers/windows/dir_access_windows.h"
+
+
+#include "servers/visual/visual_server_raster.h"
+#include "servers/audio/audio_server_sw.h"
+#include "servers/visual/visual_server_wrap_mt.h"
+
+#include "tcp_server_winsock.h"
+#include "stream_peer_winsock.h"
+#include "os/pc_joystick_map.h"
+#include "lang_table.h"
+#include "os/memory_pool_dynamic_prealloc.h"
+#include "globals.h"
+#include "io/marshalls.h"
+
+int OSWinrt::get_video_driver_count() const {
+
+ return 2;
+}
+const char * OSWinrt::get_video_driver_name(int p_driver) const {
+
+ return p_driver==0?"GLES2":"GLES1";
+}
+
+OS::VideoMode OSWinrt::get_default_video_mode() const {
+
+ return VideoMode(800,600,false);
+}
+
+int OSWinrt::get_audio_driver_count() const {
+
+ return AudioDriverManagerSW::get_driver_count();
+}
+const char * OSWinrt::get_audio_driver_name(int p_driver) const {
+
+ AudioDriverSW* driver = AudioDriverManagerSW::get_driver(p_driver);
+ ERR_FAIL_COND_V( !driver, "" );
+ return AudioDriverManagerSW::get_driver(p_driver)->get_name();
+}
+
+static MemoryPoolStatic *mempool_static=NULL;
+static MemoryPoolDynamic *mempool_dynamic=NULL;
+
+void OSWinrt::initialize_core() {
+
+
+ last_button_state=0;
+
+ //RedirectIOToConsole();
+
+ ThreadWinrt::make_default();
+ //SemaphoreWindows::make_default();
+ MutexWindows::make_default();
+
+ FileAccess::make_default<FileAccessWindows>(FileAccess::ACCESS_RESOURCES);
+ FileAccess::make_default<FileAccessWindows>(FileAccess::ACCESS_USERDATA);
+ FileAccess::make_default<FileAccessWindows>(FileAccess::ACCESS_FILESYSTEM);
+ //FileAccessBufferedFA<FileAccessWindows>::make_default();
+ DirAccess::make_default<DirAccessWindows>(DirAccess::ACCESS_RESOURCES);
+ DirAccess::make_default<DirAccessWindows>(DirAccess::ACCESS_USERDATA);
+ DirAccess::make_default<DirAccessWindows>(DirAccess::ACCESS_FILESYSTEM);
+
+ //TCPServerWinsock::make_default();
+ //StreamPeerWinsock::make_default();
+
+ mempool_static = new MemoryPoolStaticMalloc;
+#if 1
+ mempool_dynamic = memnew( MemoryPoolDynamicStatic );
+#else
+#define DYNPOOL_SIZE 4*1024*1024
+ void * buffer = malloc( DYNPOOL_SIZE );
+ mempool_dynamic = memnew( MemoryPoolDynamicPrealloc(buffer,DYNPOOL_SIZE) );
+
+#endif
+
+ // We need to know how often the clock is updated
+ if( !QueryPerformanceFrequency((LARGE_INTEGER *)&ticks_per_second) )
+ ticks_per_second = 1000;
+ // If timeAtGameStart is 0 then we get the time since
+ // the start of the computer when we call GetGameTime()
+ ticks_start = 0;
+ ticks_start = get_ticks_usec();
+
+ cursor_shape=CURSOR_ARROW;
+}
+
+bool OSWinrt::can_draw() const {
+
+ return !minimized;
+};
+
+
+void OSWinrt::_touch_event(int idx, UINT uMsg, WPARAM wParam, LPARAM lParam) {
+
+ InputEvent event;
+ event.type = InputEvent::SCREEN_TOUCH;
+ event.ID=++last_id;
+ event.screen_touch.index = idx;
+
+ switch (uMsg) {
+ case WM_LBUTTONDOWN:
+ case WM_MBUTTONDOWN:
+ case WM_RBUTTONDOWN: {
+
+ event.screen_touch.pressed = true;
+ } break;
+
+ case WM_LBUTTONUP:
+ case WM_MBUTTONUP:
+ case WM_RBUTTONUP: {
+ event.screen_touch.pressed = false;
+ } break;
+ };
+
+ event.screen_touch.x=GET_X_LPARAM(lParam);
+ event.screen_touch.y=GET_Y_LPARAM(lParam);
+
+ if (main_loop) {
+ input->parse_input_event(event);
+ }
+};
+
+void OSWinrt::_drag_event(int idx,UINT uMsg, WPARAM wParam, LPARAM lParam) {
+
+ InputEvent event;
+ event.type = InputEvent::SCREEN_DRAG;
+ event.ID=++last_id;
+ event.screen_drag.index = idx;
+
+ event.screen_drag.x=GET_X_LPARAM(lParam);
+ event.screen_drag.y=GET_Y_LPARAM(lParam);
+
+ if (main_loop)
+ input->parse_input_event(event);
+};
+
+
+void OSWinrt::initialize(const VideoMode& p_desired,int p_video_driver,int p_audio_driver) {
+
+
+
+ main_loop=NULL;
+ outside=true;
+
+
+ visual_server = memnew( VisualServerRaster(rasterizer) );
+ if (get_render_thread_mode()!=RENDER_THREAD_UNSAFE) {
+
+ visual_server =memnew(VisualServerWrapMT(visual_server,get_render_thread_mode()==RENDER_SEPARATE_THREAD));
+ }
+
+ //
+ physics_server = memnew( PhysicsServerSW );
+ physics_server->init();
+
+ physics_2d_server = memnew( Physics2DServerSW );
+ physics_2d_server->init();
+
+ visual_server->init();
+
+ input = memnew( InputDefault );
+
+ AudioDriverManagerSW::get_driver(p_audio_driver)->set_singleton();
+
+ if (AudioDriverManagerSW::get_driver(p_audio_driver)->init()!=OK) {
+
+ ERR_PRINT("Initializing audio failed.");
+ }
+
+ sample_manager = memnew( SampleManagerMallocSW );
+ audio_server = memnew( AudioServerSW(sample_manager) );
+
+ audio_server->init();
+
+ spatial_sound_server = memnew( SpatialSoundServerSW );
+ spatial_sound_server->init();
+ spatial_sound_2d_server = memnew( SpatialSound2DServerSW );
+ spatial_sound_2d_server->init();
+
+
+ _ensure_data_dir();
+}
+
+void OSWinrt::set_clipboard(const String& p_text) {
+
+ if (!OpenClipboard(hWnd)) {
+ ERR_EXPLAIN("Unable to open clipboard.");
+ ERR_FAIL();
+ };
+ EmptyClipboard();
+
+ HGLOBAL mem = GlobalAlloc(GMEM_MOVEABLE, (p_text.length() + 1) * sizeof(CharType));
+ if (mem == NULL) {
+ ERR_EXPLAIN("Unable to allocate memory for clipboard contents.");
+ ERR_FAIL();
+ };
+ LPWSTR lptstrCopy = (LPWSTR)GlobalLock(mem);
+ memcpy(lptstrCopy, p_text.c_str(), (p_text.length() + 1) * sizeof(CharType));
+ //memset((lptstrCopy + p_text.length()), 0, sizeof(CharType));
+ GlobalUnlock(mem);
+
+ SetClipboardData(CF_UNICODETEXT, mem);
+
+ // set the CF_TEXT version (not needed?)
+ CharString utf8 = p_text.utf8();
+ mem = GlobalAlloc(GMEM_MOVEABLE, utf8.length() + 1);
+ if (mem == NULL) {
+ ERR_EXPLAIN("Unable to allocate memory for clipboard contents.");
+ ERR_FAIL();
+ };
+ LPTSTR ptr = (LPTSTR)GlobalLock(mem);
+ memcpy(ptr, utf8.get_data(), utf8.length());
+ ptr[utf8.length()] = 0;
+ GlobalUnlock(mem);
+
+ SetClipboardData(CF_TEXT, mem);
+
+ CloseClipboard();
+};
+
+String OSWinrt::get_clipboard() const {
+
+ String ret;
+ if (!OpenClipboard(hWnd)) {
+ ERR_EXPLAIN("Unable to open clipboard.");
+ ERR_FAIL_V("");
+ };
+
+ if (IsClipboardFormatAvailable(CF_UNICODETEXT)) {
+
+ HGLOBAL mem = GetClipboardData(CF_UNICODETEXT);
+ if (mem != NULL) {
+
+ LPWSTR ptr = (LPWSTR)GlobalLock(mem);
+ if (ptr != NULL) {
+
+ ret = String((CharType*)ptr);
+ GlobalUnlock(mem);
+ };
+ };
+
+ } else if (IsClipboardFormatAvailable(CF_TEXT)) {
+
+ HGLOBAL mem = GetClipboardData(CF_UNICODETEXT);
+ if (mem != NULL) {
+
+ LPTSTR ptr = (LPTSTR)GlobalLock(mem);
+ if (ptr != NULL) {
+
+ ret.parse_utf8((const char*)ptr);
+ GlobalUnlock(mem);
+ };
+ };
+ };
+
+ CloseClipboard();
+
+ return ret;
+};
+
+
+void OSWinrt::delete_main_loop() {
+
+ if (main_loop)
+ memdelete(main_loop);
+ main_loop=NULL;
+}
+
+void OSWinrt::set_main_loop( MainLoop * p_main_loop ) {
+
+ input->set_main_loop(p_main_loop);
+ main_loop=p_main_loop;
+}
+
+void OSWinrt::finalize() {
+
+ if(main_loop)
+ memdelete(main_loop);
+
+ main_loop=NULL;
+
+ visual_server->finish();
+ memdelete(visual_server);
+#ifdef OPENGL_ENABLED
+ if (gl_context)
+ memdelete(gl_context);
+#endif
+ if (rasterizer)
+ memdelete(rasterizer);
+
+ if (user_proc) {
+ SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)user_proc);
+ };
+
+ spatial_sound_server->finish();
+ memdelete(spatial_sound_server);
+ spatial_sound_2d_server->finish();
+ memdelete(spatial_sound_2d_server);
+
+ //if (debugger_connection_console) {
+// memdelete(debugger_connection_console);
+//}
+
+ audio_server->finish();
+ memdelete(audio_server);
+ memdelete(sample_manager);
+
+ memdelete(input);
+
+ physics_server->finish();
+ memdelete(physics_server);
+
+ physics_2d_server->finish();
+ memdelete(physics_2d_server);
+
+}
+void OSWinrt::finalize_core() {
+
+ memdelete(process_map);
+
+ if (mempool_dynamic)
+ memdelete( mempool_dynamic );
+ if (mempool_static)
+ delete mempool_static;
+
+
+ TCPServerWinsock::cleanup();
+ StreamPeerWinsock::cleanup();
+}
+
+void OSWinrt::vprint(const char* p_format, va_list p_list, bool p_stderr) {
+
+ char buf[16384+1];
+ int len = vsnprintf(buf,16384,p_format,p_list);
+ if (len<=0)
+ return;
+ buf[len]=0;
+
+
+ int wlen = MultiByteToWideChar(CP_UTF8,0,buf,len,NULL,0);
+ if (wlen<0)
+ return;
+
+ wchar_t *wbuf = (wchar_t*)malloc((len+1)*sizeof(wchar_t));
+ MultiByteToWideChar(CP_UTF8,0,buf,len,wbuf,wlen);
+ wbuf[wlen]=0;
+
+ if (p_stderr)
+ fwprintf(stderr,L"%s",wbuf);
+ else
+ wprintf(L"%s",wbuf);
+
+#ifdef STDOUT_FILE
+ //vwfprintf(stdo,p_format,p_list);
+#endif
+ free(wbuf);
+
+ fflush(stdout);
+};
+
+void OSWinrt::alert(const String& p_alert,const String& p_title) {
+
+ if (!is_no_window_mode_enabled())
+ MessageBoxW(NULL,p_alert.c_str(),p_title.c_str(),MB_OK|MB_ICONEXCLAMATION);
+ else
+ print_line("ALERT: "+p_alert);
+}
+
+void OSWinrt::set_mouse_mode(MouseMode p_mode) {
+
+}
+
+OSWinrt::MouseMode OSWinrt::get_mouse_mode() const{
+
+ return mouse_mode;
+}
+
+
+
+Point2 OSWinrt::get_mouse_pos() const {
+
+ return Point2(old_x, old_y);
+}
+
+int OSWinrt::get_mouse_button_state() const {
+
+ return last_button_state;
+}
+
+void OSWinrt::set_window_title(const String& p_title) {
+
+}
+
+void OSWinrt::set_video_mode(const VideoMode& p_video_mode,int p_screen) {
+
+
+}
+OS::VideoMode OSWinrt::get_video_mode(int p_screen) const {
+
+ return video_mode;
+}
+void OSWinrt::get_fullscreen_mode_list(List<VideoMode> *p_list,int p_screen) const {
+
+
+}
+
+void OSWinrt::print_error(const char* p_function,const char* p_file,int p_line,const char *p_code,const char*p_rationale,ErrorType p_type) {
+
+ HANDLE hCon=GetStdHandle(STD_OUTPUT_HANDLE);
+ if (!hCon || hCon==INVALID_HANDLE_VALUE) {
+ if (p_rationale && p_rationale[0]) {
+
+ print("\E[1;31;40mERROR: %s: \E[1;37;40m%s\n",p_function,p_rationale);
+ print("\E[0;31;40m At: %s:%i.\E[0;0;37m\n",p_file,p_line);
+
+ } else {
+ print("\E[1;31;40mERROR: %s: \E[1;37;40m%s\n",p_function,p_code);
+ print("\E[0;31;40m At: %s:%i.\E[0;0;37m\n",p_file,p_line);
+
+ }
+ } else {
+
+ CONSOLE_SCREEN_BUFFER_INFO sbi; //original
+ GetConsoleScreenBufferInfo(hCon,&sbi);
+
+ SetConsoleTextAttribute(hCon,sbi.wAttributes);
+
+
+
+ uint32_t basecol=0;
+ switch(p_type) {
+ case ERR_ERROR: basecol = FOREGROUND_RED; break;
+ case ERR_WARNING: basecol = FOREGROUND_RED|FOREGROUND_GREEN; break;
+ case ERR_SCRIPT: basecol = FOREGROUND_GREEN; break;
+ }
+
+ if (p_rationale && p_rationale[0]) {
+
+ SetConsoleTextAttribute(hCon,basecol|FOREGROUND_INTENSITY);
+
+
+ switch(p_type) {
+ case ERR_ERROR: print("ERROR: "); break;
+ case ERR_WARNING: print("WARNING: "); break;
+ case ERR_SCRIPT: print("SCRIPT ERROR: "); break;
+ }
+
+ SetConsoleTextAttribute(hCon,FOREGROUND_RED|FOREGROUND_BLUE|FOREGROUND_GREEN|FOREGROUND_INTENSITY);
+ print(" %s\n",p_rationale);
+ SetConsoleTextAttribute(hCon,basecol);
+ print("At: ");
+ SetConsoleTextAttribute(hCon,FOREGROUND_RED|FOREGROUND_BLUE|FOREGROUND_GREEN);
+ print(" %s:%i\n",p_file,p_line);
+
+
+ } else {
+ SetConsoleTextAttribute(hCon,basecol|FOREGROUND_INTENSITY);
+ switch(p_type) {
+ case ERR_ERROR: print("ERROR: %s: ",p_function); break;
+ case ERR_WARNING: print("WARNING: %s: ",p_function); break;
+ case ERR_SCRIPT: print("SCRIPT ERROR: %s: ",p_function); break;
+ }
+ SetConsoleTextAttribute(hCon,FOREGROUND_RED|FOREGROUND_BLUE|FOREGROUND_GREEN|FOREGROUND_INTENSITY);
+ print(" %s\n",p_code);
+ SetConsoleTextAttribute(hCon,basecol);
+ print("At: ");
+ SetConsoleTextAttribute(hCon,FOREGROUND_RED|FOREGROUND_BLUE|FOREGROUND_GREEN);
+ print(" %s:%i\n",p_file,p_line);
+ }
+
+ SetConsoleTextAttribute(hCon,sbi.wAttributes);
+ }
+
+}
+
+
+String OSWinrt::get_name() {
+
+ return "WinRT";
+}
+
+OS::Date OSWinrt::get_date() const {
+
+ SYSTEMTIME systemtime;
+ GetSystemTime(&systemtime);
+ Date date;
+ date.day=systemtime.wDay;
+ date.month=Month(systemtime.wMonth);
+ date.weekday=Weekday(systemtime.wDayOfWeek);
+ date.year=systemtime.wYear;
+ date.dst=false;
+ return date;
+}
+OS::Time OSWinrt::get_time() const {
+
+ SYSTEMTIME systemtime;
+ GetSystemTime(&systemtime);
+
+ Time time;
+ time.hour=systemtime.wHour;
+ time.min=systemtime.wMinute;
+ time.sec=systemtime.wSecond;
+ return time;
+}
+
+uint64_t OSWinrt::get_unix_time() const {
+
+ FILETIME ft;
+ SYSTEMTIME st;
+ GetSystemTime(&st);
+ SystemTimeToFileTime(&st, &ft);
+
+ SYSTEMTIME ep;
+ ep.wYear = 1970;
+ ep.wMonth = 1;
+ ep.wDayOfWeek = 4;
+ ep.wDay = 1;
+ ep.wHour = 0;
+ ep.wMinute = 0;
+ ep.wSecond = 0;
+ ep.wMilliseconds = 0;
+ FILETIME fep;
+ SystemTimeToFileTime(&ep, &fep);
+
+ return (*(uint64_t*)&ft - *(uint64_t*)&fep) / 10000000;
+};
+
+void OSWinrt::delay_usec(uint32_t p_usec) const {
+
+ if (p_usec < 1000)
+ Sleep(1);
+ else
+ Sleep(p_usec / 1000);
+
+}
+uint64_t OSWinrt::get_ticks_usec() const {
+
+ uint64_t ticks;
+ uint64_t time;
+ // This is the number of clock ticks since start
+ QueryPerformanceCounter((LARGE_INTEGER *)&ticks);
+ // Divide by frequency to get the time in seconds
+ time = ticks * 1000000L / ticks_per_second;
+ // Subtract the time at game start to get
+ // the time since the game started
+ time -= ticks_start;
+ return time;
+}
+
+
+void OSWinrt::process_events() {
+
+}
+
+void OSWinrt::set_cursor_shape(CursorShape p_shape) {
+
+}
+
+Error OSWinrt::execute(const String& p_path, const List<String>& p_arguments,bool p_blocking,ProcessID *r_child_id,String* r_pipe,int *r_exitcode) {
+
+ return FAILED;
+};
+
+Error OSWinrt::kill(const ProcessID& p_pid) {
+
+ return FAILED;
+};
+
+Error OSWinrt::set_cwd(const String& p_cwd) {
+
+ if (_wchdir(p_cwd.c_str())!=0)
+ return ERR_CANT_OPEN;
+
+ return OK;
+}
+
+String OSWinrt::get_executable_path() const {
+
+ wchar_t bufname[4096];
+ GetModuleFileNameW(NULL,bufname,4096);
+ String s= bufname;
+ print_line("EXEC PATHPó: "+s);
+ return s;
+}
+
+void OSWinrt::set_icon(const Image& p_icon) {
+
+}
+
+
+bool OSWinrt::has_environment(const String& p_var) const {
+
+ return getenv(p_var.utf8().get_data()) != NULL;
+};
+
+String OSWinrt::get_environment(const String& p_var) const {
+
+ char* val = getenv(p_var.utf8().get_data());
+ if (val)
+ return val;
+
+ return "";
+};
+
+String OSWinrt::get_stdin_string(bool p_block) {
+
+ if (p_block) {
+ char buff[1024];
+ return fgets(buff,1024,stdin);
+ };
+
+ return String();
+}
+
+
+void OSWinrt::move_window_to_foreground() {
+
+}
+
+Error OSWinrt::shell_open(String p_uri) {
+
+ return FAILED;
+}
+
+
+String OSWinrt::get_locale() const {
+
+ Platform::String ^language = Windows::Globalization::Language::CurrentInputMethodLanguageTag;
+ return language.Data();
+}
+
+void OSWinrt::release_rendering_thread() {
+
+ //gl_context->release_current();
+
+}
+
+void OSWinrt::make_rendering_thread() {
+
+ //gl_context->make_current();
+}
+
+void OSWinrt::swap_buffers() {
+
+ //gl_context->swap_buffers();
+}
+
+
+void OSWinrt::run() {
+
+ if (!main_loop)
+ return;
+
+ main_loop->init();
+
+ uint64_t last_ticks=get_ticks_usec();
+
+ int frames=0;
+ uint64_t frame=0;
+
+ while (!force_quit) {
+
+ process_events(); // get rid of pending events
+ if (Main::iteration()==true)
+ break;
+ };
+
+ main_loop->finish();
+
+}
+
+
+
+MainLoop *OSWinrt::get_main_loop() const {
+
+ return main_loop;
+}
+
+
+String OSWinrt::get_data_dir() const {
+
+ Windows::Storage::StorageFolder ^data_folder = Windows::Storage::ApplicationData::Current->LocalFolder;
+
+ return data_folder->Path->Data();
+}
+
+
+OSWinrt::OSWinrt(HINSTANCE _hInstance) {
+
+ key_event_pos=0;
+ force_quit=false;
+ alt_mem=false;
+ gr_mem=false;
+ shift_mem=false;
+ control_mem=false;
+ meta_mem=false;
+ minimized = false;
+
+ pressrc=0;
+ old_invalid=true;
+ last_id=0;
+ mouse_mode=MOUSE_MODE_VISIBLE;
+#ifdef STDOUT_FILE
+ stdo=fopen("stdout.txt","wb");
+#endif
+
+}
+
+
+OSWinrt::~OSWinrt()
+{
+#ifdef STDOUT_FILE
+ fclose(stdo);
+#endif
+}
+
+
diff --git a/platform/winrt/os_winrt.h b/platform/winrt/os_winrt.h
new file mode 100644
index 0000000000..bc7e188c20
--- /dev/null
+++ b/platform/winrt/os_winrt.h
@@ -0,0 +1,242 @@
+/*************************************************************************/
+/* OSWinrt.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#ifndef OSWinrt_H
+#define OSWinrt_H
+
+#include "os/input.h"
+#include "os/os.h"
+#include "servers/visual_server.h"
+#include "servers/visual/rasterizer.h"
+#include "servers/physics/physics_server_sw.h"
+
+#include "servers/audio/audio_server_sw.h"
+#include "servers/audio/sample_manager_sw.h"
+#include "servers/spatial_sound/spatial_sound_server_sw.h"
+#include "servers/spatial_sound_2d/spatial_sound_2d_server_sw.h"
+#include "servers/physics_2d/physics_2d_server_sw.h"
+
+
+#include <windows.h>
+
+#include "key_mapping_win.h"
+#include <windowsx.h>
+#include <io.h>
+
+#include <fcntl.h>
+#include <stdio.h>
+/**
+ @author Juan Linietsky <reduzio@gmail.com>
+*/
+class OSWinrt : public OS {
+
+ enum {
+ JOYSTICKS_MAX = 8,
+ JOY_AXIS_COUNT = 6,
+ MAX_JOY_AXIS = 32768, // I've no idea
+ KEY_EVENT_BUFFER_SIZE=512
+ };
+
+ FILE *stdo;
+
+
+ struct KeyEvent {
+
+ InputModifierState mod_state;
+ UINT uMsg;
+ WPARAM wParam;
+ LPARAM lParam;
+
+ };
+
+ KeyEvent key_event_buffer[KEY_EVENT_BUFFER_SIZE];
+ int key_event_pos;
+
+
+ uint64_t ticks_start;
+ uint64_t ticks_per_second;
+
+ bool minimized;
+ bool old_invalid;
+ bool outside;
+ int old_x,old_y;
+ Point2i center;
+ unsigned int last_id;
+ VisualServer *visual_server;
+ Rasterizer *rasterizer;
+ PhysicsServer *physics_server;
+ Physics2DServer *physics_2d_server;
+ int pressrc;
+
+ struct Joystick {
+
+ int id;
+ bool attached;
+
+ DWORD last_axis[JOY_AXIS_COUNT];
+ DWORD last_buttons;
+ DWORD last_pov;
+ String name;
+
+ Joystick() {
+ id = -1;
+ attached = false;
+ for (int i=0; i<JOY_AXIS_COUNT; i++) {
+
+ last_axis[i] = 0;
+ };
+ last_buttons = 0;
+ last_pov = 0;
+ };
+ };
+
+ List<Joystick> joystick_change_queue;
+ int joystick_count;
+ Joystick joysticks[JOYSTICKS_MAX];
+
+ VideoMode video_mode;
+
+ MainLoop *main_loop;
+
+ AudioServerSW *audio_server;
+ SampleManagerMallocSW *sample_manager;
+ SpatialSoundServerSW *spatial_sound_server;
+ SpatialSound2DServerSW *spatial_sound_2d_server;
+
+ MouseMode mouse_mode;
+ bool alt_mem;
+ bool gr_mem;
+ bool shift_mem;
+ bool control_mem;
+ bool meta_mem;
+ bool force_quit;
+ uint32_t last_button_state;
+
+ CursorShape cursor_shape;
+
+ InputDefault *input;
+
+ void _post_dpad(DWORD p_dpad, int p_device, bool p_pressed);
+
+ void _drag_event(int idx,UINT uMsg, WPARAM wParam, LPARAM lParam);
+ void _touch_event(int idx, UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+
+ // functions used by main to initialize/deintialize the OS
+protected:
+ virtual int get_video_driver_count() const;
+ virtual const char * get_video_driver_name(int p_driver) const;
+
+ virtual VideoMode get_default_video_mode() const;
+
+ virtual int get_audio_driver_count() const;
+ virtual const char * get_audio_driver_name(int p_driver) const;
+
+ virtual void initialize_core();
+ virtual void initialize(const VideoMode& p_desired,int p_video_driver,int p_audio_driver);
+
+ virtual void set_main_loop( MainLoop * p_main_loop );
+ virtual void delete_main_loop();
+
+ virtual void finalize();
+ virtual void finalize_core();
+
+ void process_events();
+
+ void probe_joysticks();
+ void process_joysticks();
+ void process_key_events();
+
+public:
+
+ void print_error(const char* p_function,const char* p_file,int p_line,const char *p_code,const char*p_rationale,ErrorType p_type);
+
+ virtual void vprint(const char *p_format, va_list p_list, bool p_stderr=false);
+ virtual void alert(const String& p_alert,const String& p_title="ALERT!");
+ String get_stdin_string(bool p_block);
+
+ void set_mouse_mode(MouseMode p_mode);
+ MouseMode get_mouse_mode() const;
+
+ virtual Point2 get_mouse_pos() const;
+ virtual int get_mouse_button_state() const;
+ virtual void set_window_title(const String& p_title);
+
+ virtual void set_video_mode(const VideoMode& p_video_mode,int p_screen=0);
+ virtual VideoMode get_video_mode(int p_screen=0) const;
+ virtual void get_fullscreen_mode_list(List<VideoMode> *p_list,int p_screen=0) const;
+
+ virtual MainLoop *get_main_loop() const;
+
+ virtual String get_name();
+
+ virtual Date get_date() const;
+ virtual Time get_time() const;
+ virtual uint64_t get_unix_time() const;
+
+ virtual bool can_draw() const;
+ virtual Error set_cwd(const String& p_cwd);
+
+ virtual void delay_usec(uint32_t p_usec) const;
+ virtual uint64_t get_ticks_usec() const;
+
+ virtual Error execute(const String& p_path, const List<String>& p_arguments,bool p_blocking,ProcessID *r_child_id=NULL,String* r_pipe=NULL,int *r_exitcode=NULL);
+ virtual Error kill(const ProcessID& p_pid);
+
+ virtual bool has_environment(const String& p_var) const;
+ virtual String get_environment(const String& p_var) const;
+
+ virtual void set_clipboard(const String& p_text);
+ virtual String get_clipboard() const;
+
+ void set_cursor_shape(CursorShape p_shape);
+ void set_icon(const Image& p_icon);
+
+ virtual String get_executable_path() const;
+
+ virtual String get_locale() const;
+
+ virtual void move_window_to_foreground();
+ virtual String get_data_dir() const;
+
+ virtual void release_rendering_thread();
+ virtual void make_rendering_thread();
+ virtual void swap_buffers();
+
+ virtual Error shell_open(String p_uri);
+
+ void run();
+
+ virtual bool get_swap_ok_cancel() { return true; }
+
+ OSWinrt();
+ ~OSWinrt();
+
+};
+
+#endif
diff --git a/platform/winrt/platform_config.h b/platform/winrt/platform_config.h
new file mode 100644
index 0000000000..91669ad489
--- /dev/null
+++ b/platform/winrt/platform_config.h
@@ -0,0 +1,2 @@
+#include <malloc.h>
+
diff --git a/platform/winrt/thread_winrt.cpp b/platform/winrt/thread_winrt.cpp
new file mode 100644
index 0000000000..3217292bee
--- /dev/null
+++ b/platform/winrt/thread_winrt.cpp
@@ -0,0 +1,42 @@
+#include "thread_winrt.h"
+
+#include "os/memory.h"
+
+Thread* ThreadWinrt::create_func_winrt(ThreadCreateCallback p_callback,void *p_user,const Settings&) {
+
+ ThreadWinrt* thread = memnew(ThreadWinrt);
+ std::thread new_thread(p_callback, p_user);
+ std::swap(thread->thread, new_thread);
+
+ return thread;
+};
+
+Thread::ID ThreadWinrt::get_thread_ID_func_winrt() {
+
+ return std::hash<std::thread::id>()(std::this_thread::get_id());
+};
+
+void ThreadWinrt::wait_to_finish_func_winrt(Thread* p_thread) {
+
+ ThreadWinrt *tp=static_cast<ThreadWinrt*>(p_thread);
+ tp->thread.join();
+};
+
+
+Thread::ID ThreadWinrt::get_ID() const {
+
+ return std::hash<std::thread::id>()(thread.get_id());
+};
+
+void ThreadWinrt::make_default() {
+
+};
+
+ThreadWinrt::ThreadWinrt() {
+
+};
+
+ThreadWinrt::~ThreadWinrt() {
+
+};
+
diff --git a/platform/winrt/thread_winrt.h b/platform/winrt/thread_winrt.h
new file mode 100644
index 0000000000..6140c9c506
--- /dev/null
+++ b/platform/winrt/thread_winrt.h
@@ -0,0 +1,35 @@
+#ifndef THREAD_WINRT_H
+#define THREAD_WINRT_H
+
+#ifdef WINRT_ENABLED
+
+#include "os/thread.h"
+
+#include <thread>
+
+class ThreadWinrt : public Thread {
+
+ std::thread thread;
+
+ static Thread* create_func_winrt(ThreadCreateCallback p_callback,void *,const Settings&);
+ static ID get_thread_ID_func_winrt();
+ static void wait_to_finish_func_winrt(Thread* p_thread);
+
+ ThreadWinrt();
+public:
+
+
+ virtual ID get_ID() const;
+
+ static void make_default();
+
+
+ ~ThreadWinrt();
+
+};
+
+
+#endif
+
+#endif
+
diff --git a/platform/x11/context_gl_x11.cpp b/platform/x11/context_gl_x11.cpp
index b56b54822e..38e3479e5d 100644
--- a/platform/x11/context_gl_x11.cpp
+++ b/platform/x11/context_gl_x11.cpp
@@ -129,17 +129,6 @@ Error ContextGL_X11::initialize() {
}
//};
- if (!OS::get_singleton()->get_video_mode().resizable) {
- XSizeHints *xsh;
- xsh = XAllocSizeHints();
- xsh->flags = PMinSize | PMaxSize;
- xsh->min_width = OS::get_singleton()->get_video_mode().width;
- xsh->max_width = OS::get_singleton()->get_video_mode().width;
- xsh->min_height = OS::get_singleton()->get_video_mode().height;
- xsh->max_height = OS::get_singleton()->get_video_mode().height;
- XSetWMNormalHints(x11_display, x11_window, xsh);
- }
-
if (!opengl_3_context) {
//oldstyle context:
diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp
index e7d9a4d691..e0dc594441 100644
--- a/platform/x11/os_x11.cpp
+++ b/platform/x11/os_x11.cpp
@@ -168,6 +168,55 @@ void OS_X11::initialize(const VideoMode& p_desired,int p_video_driver,int p_audi
visual_server =memnew(VisualServerWrapMT(visual_server,get_render_thread_mode()==RENDER_SEPARATE_THREAD));
}
+ // borderless fullscreen window mode
+ if (current_videomode.fullscreen) {
+ // needed for lxde/openbox, possibly others
+ Hints hints;
+ Atom property;
+ hints.flags = 2;
+ hints.decorations = 0;
+ property = XInternAtom(x11_display, "_MOTIF_WM_HINTS", True);
+ XChangeProperty(x11_display, x11_window, property, property, 32, PropModeReplace, (unsigned char *)&hints, 5);
+ XMapRaised(x11_display, x11_window);
+ XWindowAttributes xwa;
+ XGetWindowAttributes(x11_display, DefaultRootWindow(x11_display), &xwa);
+ XMoveResizeWindow(x11_display, x11_window, 0, 0, xwa.width, xwa.height);
+
+ // code for netwm-compliants
+ XEvent xev;
+ Atom wm_state = XInternAtom(x11_display, "_NET_WM_STATE", False);
+ Atom fullscreen = XInternAtom(x11_display, "_NET_WM_STATE_FULLSCREEN", False);
+
+ memset(&xev, 0, sizeof(xev));
+ xev.type = ClientMessage;
+ xev.xclient.window = x11_window;
+ xev.xclient.message_type = wm_state;
+ xev.xclient.format = 32;
+ xev.xclient.data.l[0] = 1;
+ xev.xclient.data.l[1] = fullscreen;
+ xev.xclient.data.l[2] = 0;
+
+ XSendEvent(x11_display, DefaultRootWindow(x11_display), False, SubstructureNotifyMask, &xev);
+ }
+
+ // disable resizeable window
+ if (!current_videomode.resizable) {
+ XSizeHints *xsh;
+ xsh = XAllocSizeHints();
+ xsh->flags = PMinSize | PMaxSize;
+ XWindowAttributes xwa;
+ if (current_videomode.fullscreen) {
+ XGetWindowAttributes(x11_display,DefaultRootWindow(x11_display),&xwa);
+ } else {
+ XGetWindowAttributes(x11_display,x11_window,&xwa);
+ }
+ xsh->min_width = xwa.width;
+ xsh->max_width = xwa.width;
+ xsh->min_height = xwa.height;
+ xsh->max_height = xwa.height;
+ XSetWMNormalHints(x11_display, x11_window, xsh);
+ }
+
AudioDriverManagerSW::get_driver(p_audio_driver)->set_singleton();
if (AudioDriverManagerSW::get_driver(p_audio_driver)->init()!=OK) {
@@ -382,7 +431,6 @@ void OS_X11::finalize() {
void OS_X11::set_mouse_mode(MouseMode p_mode) {
- print_line("WUTF "+itos(p_mode)+" old "+itos(mouse_mode));
if (p_mode==mouse_mode)
return;
@@ -1046,10 +1094,12 @@ void OS_X11::close_joystick(int p_id) {
close(joysticks[p_id].fd);
joysticks[p_id].fd = -1;
};
+ input->joy_connection_changed(p_id, false, "");
};
void OS_X11::probe_joystick(int p_id) {
#ifndef __FreeBSD__
+
if (p_id == -1) {
for (int i=0; i<JOYSTICKS_MAX; i++) {
@@ -1059,7 +1109,8 @@ void OS_X11::probe_joystick(int p_id) {
return;
};
- close_joystick(p_id);
+ if (joysticks[p_id].fd != -1)
+ close_joystick(p_id);
const char *joy_names[] = {
"/dev/input/js%d",
@@ -1072,12 +1123,22 @@ void OS_X11::probe_joystick(int p_id) {
char fname[64];
sprintf(fname, joy_names[i], p_id);
- int fd = open(fname, O_RDONLY);
+ int fd = open(fname, O_RDONLY|O_NONBLOCK);
if (fd != -1) {
- fcntl( fd, F_SETFL, O_NONBLOCK );
+ //fcntl( fd, F_SETFL, O_NONBLOCK );
joysticks[p_id] = Joystick(); // this will reset the axis array
joysticks[p_id].fd = fd;
+
+ String name;
+ char namebuf[255] = {0};
+ if (ioctl(fd, JSIOCGNAME(sizeof(namebuf)), namebuf) >= 0) {
+ name = namebuf;
+ } else {
+ name = "error";
+ };
+
+ input->joy_connection_changed(p_id, true, name);
break; // don't try the next name
};
@@ -1098,8 +1159,11 @@ void OS_X11::process_joysticks() {
InputEvent ievent;
for (int i=0; i<JOYSTICKS_MAX; i++) {
- if (joysticks[i].fd == -1)
- continue;
+ if (joysticks[i].fd == -1) {
+ probe_joystick(i);
+ if (joysticks[i].fd == -1)
+ continue;
+ };
ievent.device = i;
while ( (bytes = read(joysticks[i].fd, &events, sizeof(events))) > 0) {
@@ -1117,8 +1181,9 @@ void OS_X11::process_joysticks() {
case JS_EVENT_AXIS:
- if (joysticks[i].last_axis[event.number] != event.value) {
+ //if (joysticks[i].last_axis[event.number] != event.value) {
+ /*
if (event.number==5 || event.number==6) {
int axis=event.number-5;
@@ -1165,17 +1230,19 @@ void OS_X11::process_joysticks() {
dpad_last[axis]=val;
}
+ */
//print_line("ev: "+itos(event.number)+" val: "+ rtos((float)event.value / (float)MAX_JOY_AXIS));
- if (event.number >= JOY_AXIS_MAX)
- break;
+ //if (event.number >= JOY_AXIS_MAX)
+ // break;
//ERR_FAIL_COND(event.number >= JOY_AXIS_MAX);
ievent.type = InputEvent::JOYSTICK_MOTION;
ievent.ID = ++event_id;
- ievent.joy_motion.axis = _pc_joystick_get_native_axis(event.number);
+ ievent.joy_motion.axis = event.number; //_pc_joystick_get_native_axis(event.number);
ievent.joy_motion.axis_value = (float)event.value / (float)MAX_JOY_AXIS;
- joysticks[i].last_axis[event.number] = event.value;
+ if (event.number < JOY_AXIS_MAX)
+ joysticks[i].last_axis[event.number] = event.value;
input->parse_input_event( ievent );
- };
+ //};
break;
case JS_EVENT_BUTTON:
@@ -1183,13 +1250,16 @@ void OS_X11::process_joysticks() {
ievent.type = InputEvent::JOYSTICK_BUTTON;
ievent.ID = ++event_id;
- ievent.joy_button.button_index = _pc_joystick_get_native_button(event.number);
+ ievent.joy_button.button_index = event.number; // _pc_joystick_get_native_button(event.number);
ievent.joy_button.pressed = event.value;
input->parse_input_event( ievent );
break;
};
};
};
+ if (bytes == 0 || (bytes < 0 && errno != EAGAIN)) {
+ close_joystick(i);
+ };
};
#endif
};
diff --git a/platform/x11/os_x11.h b/platform/x11/os_x11.h
index 77ef37f6f4..fedf41ad0f 100644
--- a/platform/x11/os_x11.h
+++ b/platform/x11/os_x11.h
@@ -49,7 +49,15 @@
#include <X11/Xlib.h>
#include <X11/Xcursor/Xcursor.h>
-//bitch
+// Hints for X11 fullscreen
+typedef struct {
+ unsigned long flags;
+ unsigned long functions;
+ unsigned long decorations;
+ long inputMode;
+ unsigned long status;
+} Hints;
+
#undef CursorShape
/**
@author Juan Linietsky <reduzio@gmail.com>