Termux x11 port

This commit is contained in:
Caten
2024-09-20 21:39:48 +08:00
parent 958d7839ff
commit a117050fde
136 changed files with 19410 additions and 92 deletions

68
.gitmodules vendored
View File

@@ -7,3 +7,71 @@
[submodule "android/extern/wolfssl"]
path = android/extern/wolfssl
url = https://github.com/wolfSSL/wolfssl.git
[submodule "android/app/src/main/cpp/libtirpc"]
path = android/app/src/main/cpp/libtirpc
url = https://github.com/alisw/libtirpc
ignore = dirty
[submodule "android/app/src/main/cpp/pixman"]
path = android/app/src/main/cpp/pixman
url = https://gitlab.freedesktop.org/pixman/pixman
ignore = dirty
[submodule "android/app/src/main/cpp/libfontenc"]
path = android/app/src/main/cpp/libfontenc
url = https://gitlab.freedesktop.org/xorg/lib/libfontenc
ignore = dirty
[submodule "android/app/src/main/cpp/libxau"]
path = android/app/src/main/cpp/libxau
url = https://gitlab.freedesktop.org/xorg/lib/libxau
ignore = dirty
[submodule "android/app/src/main/cpp/libxdmcp"]
path = android/app/src/main/cpp/libxdmcp
url = https://gitlab.freedesktop.org/xorg/lib/libxdmcp
ignore = dirty
[submodule "android/app/src/main/cpp/libxfont"]
path = android/app/src/main/cpp/libxfont
url = https://gitlab.freedesktop.org/xorg/lib/libxfont
ignore = dirty
[submodule "android/app/src/main/cpp/libxkbfile"]
path = android/app/src/main/cpp/libxkbfile
url = https://gitlab.freedesktop.org/xorg/lib/libxkbfile
ignore = dirty
[submodule "android/app/src/main/cpp/libxshmfence"]
path = android/app/src/main/cpp/libxshmfence
url = https://gitlab.freedesktop.org/xorg/lib/libxshmfence
ignore = dirty
[submodule "android/app/src/main/cpp/libxtrans"]
path = android/app/src/main/cpp/libxtrans
url = https://gitlab.freedesktop.org/xorg/lib/libxtrans
ignore = dirty
[submodule "android/app/src/main/cpp/libepoxy"]
path = android/app/src/main/cpp/libepoxy
url = https://github.com/anholt/libepoxy
ignore = dirty
[submodule "android/app/src/main/cpp/libxcvt"]
path = android/app/src/main/cpp/libxcvt
url = https://gitlab.freedesktop.org/xorg/lib/libxcvt
ignore = dirty
[submodule "android/app/src/main/cpp/libx11"]
path = android/app/src/main/cpp/libx11
url = https://gitlab.freedesktop.org/xorg/lib/libx11
ignore = dirty
[submodule "android/app/src/main/cpp/xorgproto"]
path = android/app/src/main/cpp/xorgproto
url = https://gitlab.freedesktop.org/xorg/proto/xorgproto
ignore = dirty
[submodule "android/app/src/main/cpp/xkbcomp"]
path = android/app/src/main/cpp/xkbcomp
url = https://gitlab.freedesktop.org/xorg/app/xkbcomp
ignore = dirty
[submodule "android/app/src/main/cpp/xserver"]
path = android/app/src/main/cpp/xserver
url = https://gitlab.freedesktop.org/xorg/xserver
ignore = dirty
[submodule "android/app/src/main/cpp/bzip2"]
path = android/app/src/main/cpp/bzip2
url = https://gitlab.com/bzip2/bzip2
ignore = dirty
[submodule "android/app/src/main/cpp/OpenXR-SDK"]
path = android/app/src/main/cpp/OpenXR-SDK
url = https://github.com/KhronosGroup/OpenXR-SDK.git
ignore = dirty

View File

@@ -1,4 +1,3 @@
cmake_minimum_required(VERSION 3.10)
project(NativeVNC C CXX ASM)
@@ -13,12 +12,10 @@ set(BUILD_SHARED_LIBS OFF CACHE BOOL "Build shared Libs" FORCE)
# Make sure given submodule is checked out
macro(avnc_check_submodule name)
if (NOT EXISTS "${AVNC_EXTERN_DIR}/${name}/CMakeLists.txt")
message(FATAL_ERROR "git submodule for ${name} is not initialized.
Please run 'git submodule update --init'.")
message(FATAL_ERROR "git submodule for ${name} is not initialized. Please run 'git submodule update --init'.")
endif ()
endmacro()
# Required to enable SIMD support on ARM
if (CMAKE_ANDROID_ARCH STREQUAL "arm64")
set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} --target=aarch64-linux-android${ANDROID_NATIVE_API_LEVEL}")
@@ -26,7 +23,6 @@ elseif (CMAKE_ANDROID_ARCH STREQUAL "arm")
set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} --target=arm-linux-androideabi${ANDROID_NATIVE_API_LEVEL}")
endif ()
###############################################################################
# JPEG
###############################################################################
@@ -39,10 +35,10 @@ add_subdirectory(${AVNC_LIBJPEG_SRC_DIR} ${AVNC_LIBJPEG_BUILD_DIR})
# Set these variables so FindJPEG can find the library
set(JPEG_LIBRARY ${AVNC_LIBJPEG_BUILD_DIR}/libturbojpeg.a)
set(JPEG_INCLUDE_DIR ${AVNC_LIBJPEG_SRC_DIR})
include_directories(${AVNC_LIBJPEG_SRC_DIR} ${AVNC_LIBJPEG_BUILD_DIR})
# Create an interface library to manage include directories
add_library(libjpeg INTERFACE)
target_include_directories(libjpeg INTERFACE ${AVNC_LIBJPEG_SRC_DIR})
###############################################################################
# SSL
@@ -63,13 +59,9 @@ add_definitions(-DOPENSSL_ALL -DOPENSSL_EXTRA -DHAVE_CRL -DHAVE_EX_DATA
add_subdirectory(${AVNC_LIBSSL_SRC_DIR} ${AVNC_LIBSSL_BUILD_DIR})
# Set these variables so FindOpenSSL can find the library
set(OPENSSL_SSL_LIBRARY ${AVNC_LIBSSL_BUILD_DIR}/libwolfssl.a)
set(OPENSSL_CRYPTO_LIBRARY ${AVNC_LIBSSL_BUILD_DIR}/libwolfssl.a)
set(OPENSSL_INCLUDE_DIR ${AVNC_LIBSSL_SRC_DIR}/wolfssl)
include_directories(${AVNC_LIBSSL_SRC_DIR})
# Create an interface library to manage include directories
add_library(libssl INTERFACE)
target_include_directories(libssl INTERFACE ${AVNC_LIBSSL_SRC_DIR}/wolfssl)
###############################################################################
# LibVNC
@@ -78,29 +70,45 @@ avnc_check_submodule(libvncserver)
set(AVNC_LIBVNC_SRC_DIR ${AVNC_EXTERN_DIR}/libvncserver)
set(AVNC_LIBVNC_BUILD_DIR ${CMAKE_BINARY_DIR}/libvncserver)
set(WITH_LIBSSH2 OFF CACHE BOOL "Find LibSSH" FORCE)
add_subdirectory(${AVNC_LIBVNC_SRC_DIR} ${AVNC_LIBVNC_BUILD_DIR}) # (source dir, build dir)
include_directories(${AVNC_LIBVNC_SRC_DIR}/include ${AVNC_LIBVNC_BUILD_DIR}/include)
add_subdirectory(${AVNC_LIBVNC_SRC_DIR} ${AVNC_LIBVNC_BUILD_DIR})
# Create an interface library to manage include directories
add_library(libvnc INTERFACE)
target_include_directories(libvnc INTERFACE ${AVNC_LIBVNC_SRC_DIR}/include ${AVNC_LIBVNC_BUILD_DIR}/include)
###############################################################################
# Native VNC
#
# It contains implementation of JNI native methods, some NDK scaffolding and
# some helpers for OpenGL ES rendring. This is the library loaded from Java.
# some helpers for OpenGL ES rendering. This is the library loaded from Java.
###############################################################################
set(AVNC_NATIVE_SOURCE src/main/cpp/native-vnc.cpp)
add_library(native-vnc SHARED ${AVNC_NATIVE_SOURCE})
target_link_libraries(native-vnc vncclient)
# Link libraries
target_link_libraries(native-vnc
PRIVATE
libjpeg
libssl
libvnc
vncclient
)
# Link NDK libraries
find_library(LIB_LOG log)
target_link_libraries(native-vnc ${LIB_LOG})
find_library(LIB_GLES GLESv2)
target_link_libraries(native-vnc ${LIB_GLES})
target_link_libraries(native-vnc
PRIVATE
${LIB_LOG}
${LIB_GLES}
)
###############################################################################
# Termux X11
#
###############################################################################
set(X11_EXTERN_DIR ${PROJECT_SOURCE_DIR}/src/main/cpp)
add_subdirectory(${X11_EXTERN_DIR})

View File

@@ -55,6 +55,8 @@ android {
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
buildConfigField "String", "COMMIT", "\"" + ("git rev-parse HEAD\n".execute().getText().trim() ?: (System.getenv('CURRENT_COMMIT') ?: "NO_COMMIT")) + "\""
javaCompileOptions {
annotationProcessorOptions {
arguments += ["room.schemaLocation": "$projectDir/roomSchema/".toString()]
@@ -68,10 +70,27 @@ android {
// TODO: Add your own signing config for the release build.
// Signing with the debug keys for now, so `flutter run --release` works.
signingConfig signingConfigs.debug
// remove flutter's default ShrinkResources settings at flutter\packages\flutter_tools\gradle\src\main\flutter.groovy
postprocessing {
removeUnusedCode true
removeUnusedResources true
obfuscate false
optimizeCode true
}
}
debug {
signingConfig signingConfigs.debug
postprocessing {
removeUnusedCode true
removeUnusedResources true
obfuscate false
optimizeCode true
}
}
}
buildFeatures {
aidl true
dataBinding true
buildConfig true
}
@@ -106,6 +125,7 @@ dependencies {
implementation "androidx.fragment:fragment-ktx:1.6.2"
implementation "androidx.appcompat:appcompat:1.6.1"
implementation "androidx.preference:preference-ktx:1.2.1"
implementation "androidx.preference:preference:1.2.1"
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.2"
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.6.2"
implementation "androidx.dynamicanimation:dynamicanimation:1.0.0"
@@ -122,5 +142,65 @@ dependencies {
implementation "com.google.android.material:material:1.11.0"
implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.0"
implementation "org.connectbot:sshlib:2.2.23"
implementation 'com.github.tiann:FreeReflection:3.1.0'
compileOnly project(':shell-loader:stub')
}
afterEvaluate {
tasks.register("generatePrefs") {
//noinspection UnnecessaryQualifiedReference
def xml = groovy.xml.DOMBuilder.parse((new StringReader(file('src/main/res/xml/preferences.xml').text)))
def preferenceNodes = xml.documentElement.getElementsByTagName("*")
def preferences = []
for (int i = 0; i < preferenceNodes.length; i++) {
def node = preferenceNodes.item(i)
if (node.nodeName == 'EditTextPreference' && node.getAttribute("app:key") != "extra_keys_config")
preferences << [ type: 'String', key: node.getAttribute("app:key"), default: node.getAttribute("app:defaultValue") ]
else if (node.nodeName == 'SeekBarPreference')
preferences << [ type: 'Int', key: node.getAttribute("app:key"), default: node.getAttribute("app:defaultValue") ]
else if (node.nodeName == 'ListPreference') {
def entries = node.getAttribute("app:entries")
def values = node.getAttribute("app:entryValues")
preferences << [type: 'List', key: node.getAttribute("app:key"), default: node.getAttribute("app:defaultValue"),
entries: entries.substring(7, entries.length()), values: values.substring(7, values.length())]
}
else if (node.nodeName == 'SwitchPreferenceCompat')
preferences << [ type: 'Boolean', key: node.getAttribute("app:key"), default: node.getAttribute("app:defaultValue") ]
}
def out = file('build/generated/java/com/termux/x11/Prefs.java')
out.getParentFile().exists() || out.getParentFile().mkdirs()
out.delete()
out.createNewFile()
out << 'package com.termux.x11;\n'
out << 'import java.util.HashMap;\n'
out << 'import android.content.Context;\n'
out << 'import com.termux.x11.utils.TermuxX11ExtraKeys;\n'
out << 'import com.example.tiny_computer.R;\n'
out << '\n'
out << 'public class Prefs extends LoriePreferences.PrefsProto {\n'
preferences.each {
if (it.type == 'Int' || it.type == 'Boolean')
out << " public final ${it.type}Preference ${it.key} = new ${it.type}Preference(\"${it.key}\", ${it.default});\n"
else if (it.type == 'String')
out << " public final StringPreference ${it.key} = new StringPreference(\"${it.key}\", \"${it.default}\");\n"
else if (it.type == 'List')
out << " public final ${it.type}Preference ${it.key} = new ${it.type}Preference(\"${it.key}\", \"${it.default}\", R.array.${it.entries}, R.array.${it.values});\n"
}
out << ' public final StringPreference extra_keys_config = new StringPreference("extra_keys_config", TermuxX11ExtraKeys.DEFAULT_IVALUE_EXTRA_KEYS);\n'
out << ' public final HashMap<String, Preference> keys = new HashMap<String, Preference>() {{\n'
preferences.each { out << ' put("' + it.key + '", ' + it.key + ');\n' }
out << ' put("extra_keys_config", extra_keys_config);\n'
out << ' }};\n'
out << '\n'
out << ' public Prefs(Context ctx) {\n'
out << ' super(ctx);\n'
out << ' }\n'
out << '}\n'
}
android.sourceSets.main.java.srcDirs += 'build/generated/java'
preBuild.dependsOn generatePrefs
}

View File

@@ -0,0 +1,108 @@
package com.termux.x11;
import java.util.HashMap;
import android.content.Context;
import com.termux.x11.utils.TermuxX11ExtraKeys;
import com.example.tiny_computer.R;
public class Prefs extends LoriePreferences.PrefsProto {
public final ListPreference displayResolutionMode = new ListPreference("displayResolutionMode", "native", R.array.displayResolutionVariants, R.array.displayResolutionVariants);
public final IntPreference displayScale = new IntPreference("displayScale", 100);
public final ListPreference displayResolutionExact = new ListPreference("displayResolutionExact", "1280x1024", R.array.displayResolution, R.array.displayResolution);
public final StringPreference displayResolutionCustom = new StringPreference("displayResolutionCustom", "1280x1024");
public final BooleanPreference adjustResolution = new BooleanPreference("adjustResolution", false);
public final BooleanPreference displayStretch = new BooleanPreference("displayStretch", false);
public final BooleanPreference Reseed = new BooleanPreference("Reseed", true);
public final BooleanPreference PIP = new BooleanPreference("PIP", true);
public final BooleanPreference fullscreen = new BooleanPreference("fullscreen", true);
public final ListPreference forceOrientation = new ListPreference("forceOrientation", "no", R.array.forceOrientationVariants, R.array.forceOrientationVariants);
public final BooleanPreference hideCutout = new BooleanPreference("hideCutout", false);
public final BooleanPreference keepScreenOn = new BooleanPreference("keepScreenOn", true);
public final BooleanPreference xrMode = new BooleanPreference("xrMode", false);
public final ListPreference touchMode = new ListPreference("touchMode", "1", R.array.touchscreenInputModesEntries, R.array.touchscreenInputModesValues);
public final BooleanPreference scaleTouchpad = new BooleanPreference("scaleTouchpad", true);
public final BooleanPreference showStylusClickOverride = new BooleanPreference("showStylusClickOverride", false);
public final BooleanPreference stylusIsMouse = new BooleanPreference("stylusIsMouse", false);
public final BooleanPreference stylusButtonContactModifierMode = new BooleanPreference("stylusButtonContactModifierMode", false);
public final BooleanPreference showMouseHelper = new BooleanPreference("showMouseHelper", false);
public final BooleanPreference pointerCapture = new BooleanPreference("pointerCapture", false);
public final ListPreference transformCapturedPointer = new ListPreference("transformCapturedPointer", "no", R.array.transformCapturedPointerEntries, R.array.transformCapturedPointerValues);
public final IntPreference capturedPointerSpeedFactor = new IntPreference("capturedPointerSpeedFactor", 100);
public final BooleanPreference tapToMove = new BooleanPreference("tapToMove", true);
public final BooleanPreference showAdditionalKbd = new BooleanPreference("showAdditionalKbd", true);
public final BooleanPreference additionalKbdVisible = new BooleanPreference("additionalKbdVisible", true);
public final BooleanPreference showIMEWhileExternalConnected = new BooleanPreference("showIMEWhileExternalConnected", true);
public final BooleanPreference preferScancodes = new BooleanPreference("preferScancodes", false);
public final BooleanPreference hardwareKbdScancodesWorkaround = new BooleanPreference("hardwareKbdScancodesWorkaround", true);
public final BooleanPreference dexMetaKeyCapture = new BooleanPreference("dexMetaKeyCapture", false);
public final BooleanPreference enableAccessibilityServiceAutomatically = new BooleanPreference("enableAccessibilityServiceAutomatically", false);
public final BooleanPreference pauseKeyInterceptingWithEsc = new BooleanPreference("pauseKeyInterceptingWithEsc", false);
public final BooleanPreference filterOutWinkey = new BooleanPreference("filterOutWinkey", false);
public final BooleanPreference enableGboardCJK = new BooleanPreference("enableGboardCJK", false);
public final BooleanPreference clipboardEnable = new BooleanPreference("clipboardEnable", true);
public final BooleanPreference storeSecondaryDisplayPreferencesSeparately = new BooleanPreference("storeSecondaryDisplayPreferencesSeparately", false);
public final BooleanPreference adjustHeightForEK = new BooleanPreference("adjustHeightForEK", true);
public final BooleanPreference useTermuxEKBarBehaviour = new BooleanPreference("useTermuxEKBarBehaviour", true);
public final IntPreference opacityEKBar = new IntPreference("opacityEKBar", 100);
public final ListPreference swipeUpAction = new ListPreference("swipeUpAction", "no action", R.array.userActionsValues, R.array.userActionsValues);
public final ListPreference swipeDownAction = new ListPreference("swipeDownAction", "toggle additional key bar", R.array.userActionsValues, R.array.userActionsValues);
public final ListPreference volumeUpAction = new ListPreference("volumeUpAction", "no action", R.array.userActionsVolumeUpValues, R.array.userActionsVolumeUpValues);
public final ListPreference volumeDownAction = new ListPreference("volumeDownAction", "no action", R.array.userActionsVolumeDownValues, R.array.userActionsVolumeDownValues);
public final ListPreference backButtonAction = new ListPreference("backButtonAction", "toggle additional key bar", R.array.userActionsValues, R.array.userActionsValues);
public final ListPreference notificationTapAction = new ListPreference("notificationTapAction", "open preferences", R.array.userActionsValues, R.array.userActionsValues);
public final ListPreference notificationButton0Action = new ListPreference("notificationButton0Action", "open preferences", R.array.userActionsValues, R.array.userActionsValues);
public final ListPreference notificationButton1Action = new ListPreference("notificationButton1Action", "exit", R.array.userActionsValues, R.array.userActionsValues);
public final StringPreference extra_keys_config = new StringPreference("extra_keys_config", TermuxX11ExtraKeys.DEFAULT_IVALUE_EXTRA_KEYS);
public final HashMap<String, Preference> keys = new HashMap<String, Preference>() {{
put("displayResolutionMode", displayResolutionMode);
put("displayScale", displayScale);
put("displayResolutionExact", displayResolutionExact);
put("displayResolutionCustom", displayResolutionCustom);
put("adjustResolution", adjustResolution);
put("displayStretch", displayStretch);
put("Reseed", Reseed);
put("PIP", PIP);
put("fullscreen", fullscreen);
put("forceOrientation", forceOrientation);
put("hideCutout", hideCutout);
put("keepScreenOn", keepScreenOn);
put("xrMode", xrMode);
put("touchMode", touchMode);
put("scaleTouchpad", scaleTouchpad);
put("showStylusClickOverride", showStylusClickOverride);
put("stylusIsMouse", stylusIsMouse);
put("stylusButtonContactModifierMode", stylusButtonContactModifierMode);
put("showMouseHelper", showMouseHelper);
put("pointerCapture", pointerCapture);
put("transformCapturedPointer", transformCapturedPointer);
put("capturedPointerSpeedFactor", capturedPointerSpeedFactor);
put("tapToMove", tapToMove);
put("showAdditionalKbd", showAdditionalKbd);
put("additionalKbdVisible", additionalKbdVisible);
put("showIMEWhileExternalConnected", showIMEWhileExternalConnected);
put("preferScancodes", preferScancodes);
put("hardwareKbdScancodesWorkaround", hardwareKbdScancodesWorkaround);
put("dexMetaKeyCapture", dexMetaKeyCapture);
put("enableAccessibilityServiceAutomatically", enableAccessibilityServiceAutomatically);
put("pauseKeyInterceptingWithEsc", pauseKeyInterceptingWithEsc);
put("filterOutWinkey", filterOutWinkey);
put("enableGboardCJK", enableGboardCJK);
put("clipboardEnable", clipboardEnable);
put("storeSecondaryDisplayPreferencesSeparately", storeSecondaryDisplayPreferencesSeparately);
put("adjustHeightForEK", adjustHeightForEK);
put("useTermuxEKBarBehaviour", useTermuxEKBarBehaviour);
put("opacityEKBar", opacityEKBar);
put("swipeUpAction", swipeUpAction);
put("swipeDownAction", swipeDownAction);
put("volumeUpAction", volumeUpAction);
put("volumeDownAction", volumeDownAction);
put("backButtonAction", backButtonAction);
put("notificationTapAction", notificationTapAction);
put("notificationButton0Action", notificationButton0Action);
put("notificationButton1Action", notificationButton1Action);
put("extra_keys_config", extra_keys_config);
}};
public Prefs(Context ctx) {
super(ctx);
}
}

View File

@@ -6,11 +6,22 @@
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS"/>
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
<uses-feature android:name="android.hardware.vr.headtracking" android:required="false" />
<uses-feature android:name="com.oculus.feature.PASSTHROUGH" android:required="false" />
<uses-feature android:name="oculus.software.handtracking" android:required="false" />
<uses-feature android:name="oculus.software.overlay_keyboard" android:required="false" />
<application
android:label="小小电脑"
android:name=".MainApplication"
android:icon="@mipmap/ic_launcher"
android:usesCleartextTraffic="true"
android:theme="@style/App.Theme">
<activity
android:name=".MainActivity"
@@ -60,6 +71,60 @@
<activity android:name="com.gaurav.avnc.ui.prefs.PrefsActivity" />
<activity android:name="com.gaurav.avnc.ui.about.AboutActivity" />
<activity
android:name="com.termux.x11.MainActivity"
android:taskAffinity="com.termux.x11.MainActivity"
android:launchMode="singleInstance"
android:supportsPictureInPicture="true"
android:configChanges="fontScale|orientation|screenSize|keyboard|keyboardHidden|layoutDirection|locale|mcc|mnc|navigation|screenLayout|touchscreen|uiMode|smallestScreenSize|density"
android:resizeableActivity="true"
android:windowSoftInputMode="stateHidden"
android:process=":x11">
</activity>
<activity
android:name="com.termux.x11.XrActivity"
android:configChanges="density|orientation|screenSize|keyboard|keyboardHidden|uiMode"
android:exported="true"
android:launchMode="singleTask"
android:resizeableActivity="false"
android:screenOrientation="landscape"
android:process=":vr_process">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="com.oculus.intent.category.VR" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:theme="@style/Theme.AppCompat.DayNight"
android:excludeFromRecents="true"
android:name="com.termux.x11.LoriePreferences"
android:taskAffinity="com.termux.x11.LoriePreferences"
android:supportsPictureInPicture="false"
android:resizeableActivity="true"
android:process=":x11">
<intent-filter>
<action android:name="android.intent.action.APPLICATION_PREFERENCES" />
<action android:name="android.intent.action.MAIN" />
</intent-filter>
</activity>
<meta-data android:name="com.samsung.android.multidisplay.keep_process_alive" android:value="false"/>
<meta-data android:name="android.allow_multiple_resumed_activities" android:value="true" />
<service android:name="com.termux.x11.utils.KeyInterceptor"
android:exported="true"
android:label="Termux:X11 KeyInterceptor"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"
android:process=":x11">
<intent-filter>
<action android:name="android.accessibilityservice.AccessibilityService" />
</intent-filter>
<meta-data
android:name="android.accessibilityservice"
android:resource="@xml/accessibility_service_config" />
</service>
<provider
android:name="com.example.tiny_computer.filepicker.TinyDocumentsProvider"
android:authorities="com.example.tiny_computer.documents"

View File

@@ -0,0 +1,8 @@
package com.termux.x11;
// This interface is used by utility on termux side.
interface ICmdEntryInterface {
void windowChanged(in Surface surface, String name);
ParcelFileDescriptor getXConnection();
ParcelFileDescriptor getLogcatOutput();
}

View File

@@ -0,0 +1,107 @@
cmake_minimum_required(VERSION 3.22)
project(lorie)
set(can_use_assembler TRUE)
enable_language(ASM)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_BUILD_TYPE RelWithDebInfo)
include(TestBigEndian)
include(CheckIncludeFile)
include(CheckSourceCompiles)
include(CheckCCompilerFlag)
include(CheckSymbolExists)
include(CheckFunctionExists)
include(CheckTypeSize)
find_package(Python3 REQUIRED)
find_package(BISON REQUIRED)
# function(target_apply_patch patch_target d p)
# execute_process(COMMAND "bash" "-c" "patch -p1 -d ${d} -i ${p} -R --dry-run > /dev/null 2>&1 || patch -p1 -N -d ${d} -i ${p} -r -")
# endfunction()
function(target_apply_patch patch_target d p)
execute_process(
COMMAND powershell -Command "& {
$patchCommand = \"patch -p1 -d ${d} -i ${p} -R --dry-run 2>&1\"
if (Invoke-Expression $patchCommand) {
Invoke-Expression \"patch -p1 -N -d ${d} -i ${p} -r -\"
}
}"
)
endfunction()
set(test_compile_options
"-Wall"
"-Wpointer-arith"
"-Wmissing-declarations"
"-Wformat=2"
"-Winvalid-pch"
"-Wstrict-prototypes"
"-Wmissing-prototypes"
"-Wnested-externs"
"-Wbad-function-cast"
"-Wold-style-definition"
"-Wunused"
"-Wuninitialized"
"-Wshadow"
"-Wmissing-noreturn"
"-Wmissing-format-attribute"
"-Wredundant-decls"
"-Wlogical-op"
"-Werror=implicit"
"-Werror=nonnull"
"-Werror=init-self"
"-Werror=main"
"-Werror=missing-braces"
"-Werror=sequence-point"
"-Werror=return-type"
"-Werror=trigraphs"
"-Werror=array-bounds"
"-Werror=write-strings"
"-Werror=address"
"-Werror=int-to-pointer-cast"
"-Werror=pointer-to-int-cast"
"-fno-strict-aliasing"
"-Wno-unused-but-set-variable"
"-Wno-unused-parameter"
"-Wno-unused-variable"
"-Wno-unused-function"
"-Wno-missing-prototypes"
"-Wno-macro-redefined"
"-Wno-uninitialized"
"-Wno-shadow")
set(CMAKE_REQUIRED_QUIET_OLD ${CMAKE_REQUIRED_QUIET})
set(CMAKE_REQUIRED_QUIET 1)
set(common_compile_options)
set(I 0)
foreach (option ${test_compile_options})
check_c_compiler_flag(${option} COMPILER_TEST_${I})
if (COMPILER_TEST_${I})
set(common_compile_options ${common_compile_options} ${option})
endif()
MATH(EXPR I "${I}+1")
endforeach ()
set(CMAKE_REQUIRED_QUIET ${CMAKE_REQUIRED_QUIET_OLD})
foreach(project xorgproto fontenc md pixman tirpc xshmfence Xdmcp Xau Xfont2 xkbcomp xserver)
include(recipes/${project}.cmake)
endforeach()
if(${ANDROID_ABI} MATCHES "arm64-v8a")
add_subdirectory(OpenXR-SDK)
add_library(XRio SHARED
"xrio/android.c"
"xrio/engine.c"
"xrio/framebuffer.c"
"xrio/input.c"
"xrio/math.c"
"xrio/renderer.c")
target_link_options(XRio PRIVATE "-Wl,--as-needed" "-Wl,--no-undefined" "-fvisibility=hidden")
target_link_libraries(XRio "-Wl,--whole-archive" "-Wl,--no-whole-archive" android log EGL GLESv2 openxr_loader)
endif()

View File

@@ -0,0 +1,283 @@
/*
Copyright 1993, 1998 The Open Group
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.
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 OPEN GROUP 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.
Except as contained in this notice, the name of The Open Group shall
not be used in advertising or otherwise to promote the sale, use or
other dealings in this Software without prior written authorization
from The Open Group.
*/
#include <X11/X.h>
#include "mi.h"
#include "scrnintstr.h"
#include "inputstr.h"
#include <X11/Xos.h>
#include <android/log.h>
#include "mipointer.h"
#include "xkbsrv.h"
#include "xserver-properties.h"
#include "exevents.h"
#include "renderer.h"
#define XI_PEN "TERMUX-X11 PEN"
#define XI_ERASER "TERMUX-X11 ERASER"
__unused DeviceIntPtr lorieMouse, lorieTouch, lorieKeyboard, loriePen, lorieEraser;
void
ProcessInputEvents(void) {
mieqProcessInputEvents();
}
void
DDXRingBell(__unused int volume, __unused int pitch, __unused int duration) {}
static int
lorieKeybdProc(DeviceIntPtr pDevice, int onoff) {
DevicePtr pDev = (DevicePtr) pDevice;
switch (onoff) {
case DEVICE_INIT:
InitKeyboardDeviceStruct(pDevice, NULL, NULL, NULL);
break;
case DEVICE_ON:
pDev->on = TRUE;
break;
case DEVICE_OFF:
pDev->on = FALSE;
break;
case DEVICE_CLOSE:
break;
default:
return BadMatch;
}
return Success;
}
static Bool
lorieInitPointerButtons(DeviceIntPtr device) {
#define NBUTTONS 10
BYTE map[NBUTTONS + 1];
int i;
Atom btn_labels[NBUTTONS] = { 0 };
for (i = 1; i <= NBUTTONS; i++)
map[i] = i;
btn_labels[0] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_LEFT);
btn_labels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE);
btn_labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT);
btn_labels[3] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_UP);
btn_labels[4] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_DOWN);
btn_labels[5] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_LEFT);
btn_labels[6] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_RIGHT);
/* don't know about the rest */
if (!InitButtonClassDeviceStruct(device, NBUTTONS, btn_labels, map))
return FALSE;
return TRUE;
#undef NBUTTONS
}
__unused static int
lorieMouseProc(DeviceIntPtr device, int what) {
#define NAXES 4
Atom axes_labels[NAXES] = { 0 };
switch (what) {
case DEVICE_INIT:
device->public.on = FALSE;
axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X);
axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y);
axes_labels[2] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_HWHEEL);
axes_labels[3] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_WHEEL);
if (!lorieInitPointerButtons(device)
|| !InitValuatorClassDeviceStruct(device, NAXES, axes_labels, GetMotionHistorySize(), Relative)
|| !InitValuatorAxisStruct(device, 0, axes_labels[0], NO_AXIS_LIMITS, NO_AXIS_LIMITS, 0, 0, 0, Relative)
|| !InitValuatorAxisStruct(device, 1, axes_labels[1], NO_AXIS_LIMITS, NO_AXIS_LIMITS, 0, 0, 0, Relative)
|| !InitValuatorAxisStruct(device, 2, axes_labels[2], NO_AXIS_LIMITS, NO_AXIS_LIMITS, 0, 0, 0, Relative)
|| !InitValuatorAxisStruct(device, 3, axes_labels[3], NO_AXIS_LIMITS, NO_AXIS_LIMITS, 0, 0, 0, Relative)
|| !SetScrollValuator(device, 2, SCROLL_TYPE_HORIZONTAL, 1.0, SCROLL_FLAG_NONE)
|| !SetScrollValuator(device, 3, SCROLL_TYPE_VERTICAL, 1.0, SCROLL_FLAG_PREFERRED)
|| !InitPtrFeedbackClassDeviceStruct(device, (PtrCtrlProcPtr) NoopDDA)
|| !InitPointerAccelerationScheme(device, PtrAccelPredictable))
return BadValue;
return Success;
case DEVICE_ON:
device->public.on = TRUE;
return Success;
case DEVICE_OFF:
case DEVICE_CLOSE:
device->public.on = FALSE;
return Success;
default:
return BadMatch;
}
#undef NAXES
}
static int
lorieTouchProc(DeviceIntPtr device, int what) {
#define NTOUCHPOINTS 20
#define NBUTTONS 1
#define NAXES 2
Atom btn_labels[NBUTTONS] = { 0 };
BYTE map[NBUTTONS + 1] = { 0 };
Atom axes_labels[NAXES] = { 0 };
switch (what) {
case DEVICE_INIT:
device->public.on = FALSE;
map[0] = 1;
btn_labels[0] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_LEFT);
axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_MT_POSITION_X);
axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_MT_POSITION_Y);
if (!InitValuatorClassDeviceStruct(device, NAXES, axes_labels, GetMotionHistorySize(), Absolute)
|| !InitButtonClassDeviceStruct(device, NBUTTONS, btn_labels, map)
|| !InitTouchClassDeviceStruct(device, NTOUCHPOINTS, XIDirectTouch, NAXES)
|| !InitValuatorAxisStruct(device, 0, axes_labels[0], 0, 0xFFFF, 10000, 0, 10000, Absolute)
|| !InitValuatorAxisStruct(device, 1, axes_labels[1], 0, 0xFFFF, 10000, 0, 10000, Absolute))
return BadValue;
return Success;
case DEVICE_ON:
device->public.on = TRUE;
return Success;
case DEVICE_OFF:
case DEVICE_CLOSE:
device->public.on = FALSE;
return Success;
default:
return BadMatch;
}
#undef NAXES
#undef NBUTTONS
#undef NTOUCHPOINTS
}
static int
lorieStylusProc(DeviceIntPtr device, int what) {
#define NBUTTONS 3
#define NAXES 6
Atom btn_labels[NBUTTONS] = { 0 };
Atom axes_labels[NAXES] = { 0 };
BYTE map[NBUTTONS + 1] = { 0 };
int i;
switch (what) {
case DEVICE_INIT:
device->public.on = FALSE;
for (i = 1; i <= NBUTTONS; i++)
map[i] = i;
axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_X);
axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_Y);
axes_labels[2] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_PRESSURE);
axes_labels[3] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_TILT_X);
axes_labels[4] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_TILT_Y);
axes_labels[5] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_WHEEL);
/* Valuators - match the xf86-input-wacom ranges */
if (!InitValuatorClassDeviceStruct(device, NAXES, axes_labels, GetMotionHistorySize(), Absolute)
|| !InitValuatorAxisStruct(device, 0, axes_labels[0], 0, 0x3FFFF, 10000, 0, 10000, Absolute)
|| !InitValuatorAxisStruct(device, 1, axes_labels[1], 0, 0x3FFFF, 10000, 0, 10000, Absolute)
|| !InitValuatorAxisStruct(device, 2, axes_labels[2], 0, 0xFFFF, 1, 0, 1, Absolute) // pressure
|| !InitValuatorAxisStruct(device, 3, axes_labels[3], -64, 63, 57, 0, 57, Absolute) // tilt x
|| !InitValuatorAxisStruct(device, 4, axes_labels[4], -64, 63, 57, 0, 57, Absolute) // tilt y
|| !InitValuatorAxisStruct(device, 5, axes_labels[5], -900, 899, 1, 0, 1, Absolute) // abs wheel (airbrush) or rotation (artpen)
|| !InitPtrFeedbackClassDeviceStruct(device, (PtrCtrlProcPtr) NoopDDA)
|| !InitButtonClassDeviceStruct(device, NBUTTONS, btn_labels, map))
return BadValue;
return Success;
case DEVICE_ON:
device->public.on = TRUE;
return Success;
case DEVICE_OFF:
case DEVICE_CLOSE:
device->public.on = FALSE;
return Success;
}
return BadMatch;
#undef NAXES
#undef NBUTTONS
}
void
lorieSetStylusEnabled(Bool enabled) {
__android_log_print(ANDROID_LOG_DEBUG, "LorieNative", "Requested stylus: %d, current loriePen %p, current lorieEraser %p\n", enabled, loriePen, lorieEraser);
if (enabled) {
if (loriePen == NULL) {
loriePen = AddInputDevice(serverClient, lorieStylusProc, TRUE);
AssignTypeAndName(loriePen, MakeAtom(XI_PEN, sizeof(XI_PEN) - 1, TRUE), "Lorie pen");
ActivateDevice(loriePen, FALSE);
EnableDevice(loriePen, TRUE);
AttachDevice(NULL, loriePen, inputInfo.pointer);
}
if (lorieEraser == NULL) {
lorieEraser = AddInputDevice(serverClient, lorieStylusProc, TRUE);
AssignTypeAndName(lorieEraser, MakeAtom(XI_ERASER, sizeof(XI_ERASER) - 1, TRUE), "Lorie eraser");
ActivateDevice(lorieEraser, FALSE);
EnableDevice(lorieEraser, TRUE);
AttachDevice(NULL, lorieEraser, inputInfo.pointer);
}
} else {
if (loriePen != NULL) {
RemoveDevice(loriePen, TRUE);
loriePen = NULL;
}
if (lorieEraser != NULL) {
RemoveDevice(lorieEraser, TRUE);
lorieEraser = NULL;
}
}
}
void
InitInput(__unused int argc, __unused char *argv[]) {
lorieMouse = AddInputDevice(serverClient, lorieMouseProc, TRUE);
lorieTouch = AddInputDevice(serverClient, lorieTouchProc, TRUE);
lorieKeyboard = AddInputDevice(serverClient, lorieKeybdProc, TRUE);
AssignTypeAndName(lorieMouse, MakeAtom(XI_MOUSE, sizeof(XI_MOUSE) - 1, TRUE), "Lorie mouse");
AssignTypeAndName(lorieTouch, MakeAtom(XI_TOUCHSCREEN, sizeof(XI_TOUCHSCREEN) - 1, TRUE), "Lorie touch");
AssignTypeAndName(lorieKeyboard, MakeAtom(XI_KEYBOARD, sizeof(XI_KEYBOARD) - 1, TRUE), "Lorie keyboard");
(void) mieqInit();
}
void
CloseInput(void) {
mieqFini();
}

View File

@@ -0,0 +1,758 @@
/*
Copyright 1993, 1998 The Open Group
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.
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 OPEN GROUP 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.
Except as contained in this notice, the name of The Open Group shall
not be used in advertising or otherwise to promote the sale, use or
other dealings in this Software without prior written authorization
from The Open Group.
*/
#pragma clang diagnostic ignored "-Wunknown-pragmas"
#pragma clang diagnostic ignored "-Wstrict-prototypes"
#pragma ide diagnostic ignored "cppcoreguidelines-narrowing-conversions"
#pragma ide diagnostic ignored "cert-err34-c"
#pragma ide diagnostic ignored "ConstantConditionsOC"
#pragma ide diagnostic ignored "ConstantFunctionResult"
#pragma ide diagnostic ignored "bugprone-integer-division"
#pragma clang diagnostic ignored "-Wmissing-noreturn"
#pragma clang diagnostic ignored "-Wformat-nonliteral"
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#include <stdio.h>
#include <sys/timerfd.h>
#include <sys/errno.h>
#include <libxcvt/libxcvt.h>
#include <X11/X.h>
#include <X11/Xos.h>
#include <android/log.h>
#include <android/native_window.h>
#include <android/hardware_buffer.h>
#include <sys/wait.h>
#include <selection.h>
#include <X11/Xatom.h>
#include <present.h>
#include <present_priv.h>
#include <dri3.h>
#include <sys/mman.h>
#include <busfault.h>
#include "scrnintstr.h"
#include "servermd.h"
#include "fb.h"
#include "input.h"
#include "mipointer.h"
#include "micmap.h"
#include "dix.h"
#include "miline.h"
#include "glx_extinit.h"
#include "randrstr.h"
#include "damagestr.h"
#include "cursorstr.h"
#include "propertyst.h"
#include "shmint.h"
#include "glxserver.h"
#include "glxutil.h"
#include "fbconfigs.h"
#include "renderer.h"
#include "inpututils.h"
#include "lorie.h"
#define unused __attribute__((unused))
#define wrap(priv, real, mem, func) { priv->mem = real->mem; real->mem = func; }
#define unwrap(priv, real, mem) { real->mem = priv->mem; }
#define USAGE (AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN | AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN)
#define log(prio, ...) __android_log_print(ANDROID_LOG_ ## prio, "LorieNative", __VA_ARGS__)
extern DeviceIntPtr lorieMouse, lorieKeyboard;
typedef struct {
CloseScreenProcPtr CloseScreen;
CreateScreenResourcesProcPtr CreateScreenResources;
DamagePtr damage;
OsTimerPtr redrawTimer;
OsTimerPtr fpsTimer;
Bool cursorMoved;
int timerFd;
struct {
AHardwareBuffer* buffer;
Bool locked;
Bool legacyDrawing;
uint8_t flip;
uint32_t width, height;
} root;
JavaVM* vm;
JNIEnv* env;
Bool dri3;
} lorieScreenInfo, *lorieScreenInfoPtr;
ScreenPtr pScreenPtr;
static lorieScreenInfo lorieScreen = { .root.width = 1280, .root.height = 1024, .dri3 = TRUE };
static lorieScreenInfoPtr pvfb = &lorieScreen;
static char *xstartup = NULL;
static Bool TrueNoop() { return TRUE; }
static Bool FalseNoop() { return FALSE; }
static void VoidNoop() {}
void
ddxGiveUp(unused enum ExitCode error) {
log(ERROR, "Server stopped (%d)", error);
CloseWellKnownConnections();
UnlockServer();
exit(error);
}
static void* ddxReadyThread(unused void* cookie) {
if (xstartup && serverGeneration == 1) {
pid_t pid = fork();
if (!pid) {
char DISPLAY[16] = "";
sprintf(DISPLAY, ":%s", display);
setenv("DISPLAY", DISPLAY, 1);
unsetenv("CLASSPATH");
execlp(xstartup, xstartup, NULL);
execlp("sh", "sh", "-c", xstartup, NULL);
dprintf(2, "Failed to start command `sh -c \"%s\"`: %s\n", xstartup, strerror(errno));
abort();
} else {
int status;
do {
pid_t w = waitpid(pid, &status, 0);
if (w == -1) {
perror("waitpid");
GiveUp(SIGKILL);
}
if (WIFEXITED(status)) {
printf("%d exited, status=%d\n", w, WEXITSTATUS(status));
} else if (WIFSIGNALED(status)) {
printf("%d killed by signal %d\n", w, WTERMSIG(status));
} else if (WIFSTOPPED(status)) {
printf("%d stopped by signal %d\n", w, WSTOPSIG(status));
} else if (WIFCONTINUED(status)) {
printf("%d continued\n", w);
}
} while (!WIFEXITED(status) && !WIFSIGNALED(status));
GiveUp(SIGINT);
}
}
return NULL;
}
void
ddxReady(void) {
if (!xstartup)
xstartup = getenv("TERMUX_X11_XSTARTUP");
if (!xstartup)
return;
pthread_t t;
pthread_create(&t, NULL, ddxReadyThread, NULL);
}
void
OsVendorInit(void) {
}
void
OsVendorFatalError(unused const char *f, unused va_list args) {
log(ERROR, f, args);
}
#if defined(DDXBEFORERESET)
void
ddxBeforeReset(void) {
return;
}
#endif
#if INPUTTHREAD
/** This function is called in Xserver/os/inputthread.c when starting
the input thread. */
void
ddxInputThreadInit(void) {}
#endif
void ddxUseMsg(void) {
ErrorF("-xstartup \"command\" start `command` after server startup\n");
ErrorF("-legacy-drawing use legacy drawing, without using AHardwareBuffers\n");
ErrorF("-force-bgra force flipping colours (RGBA->BGRA)\n");
ErrorF("-disable-dri3 disabling DRI3 support (to let lavapipe work)\n");
}
int ddxProcessArgument(unused int argc, unused char *argv[], unused int i) {
if (strcmp(argv[i], "-xstartup") == 0) { /* -xstartup "command" */
CHECK_FOR_REQUIRED_ARGUMENTS(1);
xstartup = argv[++i];
return 2;
}
if (strcmp(argv[i], "-legacy-drawing") == 0) {
pvfb->root.legacyDrawing = TRUE;
return 1;
}
if (strcmp(argv[i], "-force-bgra") == 0) {
pvfb->root.flip = TRUE;
return 1;
}
if (strcmp(argv[i], "-disable-dri3") == 0) {
pvfb->dri3 = FALSE;
return 1;
}
return 0;
}
static RRModePtr lorieCvt(int width, int height, int framerate) {
struct libxcvt_mode_info *info;
char name[128];
xRRModeInfo modeinfo = {0};
RRModePtr mode;
info = libxcvt_gen_mode_info(width, height, framerate, 0, 0);
snprintf(name, sizeof name, "%dx%d", info->hdisplay, info->vdisplay);
modeinfo.nameLength = strlen(name);
modeinfo.width = info->hdisplay;
modeinfo.height = info->vdisplay;
modeinfo.dotClock = info->dot_clock * 1000.0;
modeinfo.hSyncStart = info->hsync_start;
modeinfo.hSyncEnd = info->hsync_end;
modeinfo.hTotal = info->htotal;
modeinfo.vSyncStart = info->vsync_start;
modeinfo.vSyncEnd = info->vsync_end;
modeinfo.vTotal = info->vtotal;
modeinfo.modeFlags = info->mode_flags;
mode = RRModeGet(&modeinfo, name);
free(info);
return mode;
}
static void lorieMoveCursor(unused DeviceIntPtr pDev, unused ScreenPtr pScr, int x, int y) {
renderer_set_cursor_coordinates(x, y);
pvfb->cursorMoved = TRUE;
}
static void lorieConvertCursor(CursorPtr pCurs, CARD32 *data) {
CursorBitsPtr bits = pCurs->bits;
if (bits->argb) {
for (int i = 0; i < bits->width * bits->height; i++) {
/* Convert bgra to rgba */
CARD32 p = bits->argb[i];
data[i] = (p & 0xFF000000) | ((p & 0x00FF0000) >> 16) | (p & 0x0000FF00) | ((p & 0x000000FF) << 16);
}
} else {
CARD32 d, fg, bg, *p;
int x, y, stride, i, bit;
p = data;
fg = ((pCurs->foreBlue & 0xff00) << 8) | (pCurs->foreGreen & 0xff00) | (pCurs->foreRed >> 8);
bg = ((pCurs->backBlue & 0xff00) << 8) | (pCurs->backGreen & 0xff00) | (pCurs->backRed >> 8);
stride = BitmapBytePad(bits->width);
for (y = 0; y < bits->height; y++)
for (x = 0; x < bits->width; x++) {
i = y * stride + x / 8;
bit = 1 << (x & 7);
d = (bits->source[i] & bit) ? fg : bg;
d = (bits->mask[i] & bit) ? d | 0xff000000 : 0x00000000;
*p++ = d;
}
}
}
static void lorieSetCursor(unused DeviceIntPtr pDev, unused ScreenPtr pScr, CursorPtr pCurs, int x0, int y0) {
CursorBitsPtr bits = pCurs ? pCurs->bits : NULL;
if (pCurs && bits) {
CARD32 data[bits->width * bits->height * 4];
lorieConvertCursor(pCurs, data);
renderer_update_cursor(bits->width, bits->height, bits->xhot, bits->yhot, data);
} else
renderer_update_cursor(0, 0, 0, 0, NULL);
if (x0 >= 0 && y0 >= 0)
lorieMoveCursor(NULL, NULL, x0, y0);
}
static miPointerSpriteFuncRec loriePointerSpriteFuncs = {
.RealizeCursor = TrueNoop,
.UnrealizeCursor = TrueNoop,
.SetCursor = lorieSetCursor,
.MoveCursor = lorieMoveCursor,
.DeviceCursorInitialize = TrueNoop,
.DeviceCursorCleanup = VoidNoop
};
static miPointerScreenFuncRec loriePointerCursorFuncs = {
.CursorOffScreen = FalseNoop,
.CrossScreen = VoidNoop,
.WarpCursor = miPointerWarpCursor
};
static void lorieUpdateBuffer(void) {
AHardwareBuffer_Desc d0 = {}, d1 = {};
AHardwareBuffer *new = NULL, *old = pvfb->root.buffer;
int status, wasLocked = pvfb->root.locked;
void *data0 = NULL, *data1 = NULL;
if (pvfb->root.legacyDrawing) {
PixmapPtr pixmap = (PixmapPtr) pScreenPtr->devPrivate;
DrawablePtr draw = &pixmap->drawable;
data0 = malloc(pScreenPtr->width * pScreenPtr->height * 4);
data1 = (draw->width && draw->height) ? pixmap->devPrivate.ptr : NULL;
if (data1)
pixman_blt(data1, data0, draw->width, pScreenPtr->width, 32, 32, 0, 0, 0, 0,
min(draw->width, pScreenPtr->width), min(draw->height, pScreenPtr->height));
pScreenPtr->ModifyPixmapHeader(pScreenPtr->devPrivate, pScreenPtr->width, pScreenPtr->height, 32, 32, pScreenPtr->width * 4, data0);
free(data1);
return;
}
if (pScreenPtr->devPrivate) {
d0.width = pScreenPtr->width;
d0.height = pScreenPtr->height;
d0.layers = 1;
d0.usage = USAGE | AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
d0.format = pvfb->root.flip
? AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM
: AHARDWAREBUFFER_FORMAT_B8G8R8A8_UNORM;
/* I could use this, but in this case I must swap colours in the shader. */
// desc.format = AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM;
status = AHardwareBuffer_allocate(&d0, &new);
if (status != 0)
FatalError("Failed to allocate root window pixmap (error %d)", status);
AHardwareBuffer_describe(new, &d0);
status = AHardwareBuffer_lock(new, USAGE, -1, NULL, &data0);
if (status != 0)
FatalError("Failed to lock root window pixmap (error %d)", status);
pvfb->root.buffer = new;
pvfb->root.locked = TRUE;
pScreenPtr->ModifyPixmapHeader(pScreenPtr->devPrivate, d0.width, d0.height, 32, 32, d0.stride * 4, data0);
renderer_set_buffer(pvfb->env, new);
}
if (old) {
if (wasLocked)
AHardwareBuffer_unlock(old, NULL);
if (new && pvfb->root.locked) {
/*
* It is pretty easy. If there is old pixmap we should copy it's contents to new pixmap.
* If it is impossible we should simply request root window exposure.
*/
AHardwareBuffer_describe(old, &d1);
status = AHardwareBuffer_lock(old, USAGE, -1, NULL, &data1);
if (status == 0) {
pixman_blt(data1, data0, d1.stride, d0.stride,
32, 32, 0, 0, 0, 0,
min(d1.width, d0.width), min(d1.height, d0.height));
AHardwareBuffer_unlock(old, NULL);
} else {
RegionRec reg;
BoxRec box = {.x1 = 0, .y1 = 0, .x2 = d0.width, .y2 = d0.height};
RegionInit(&reg, &box, 1);
pScreenPtr->WindowExposures(pScreenPtr->root, &reg);
RegionUninit(&reg);
AHardwareBuffer_release(old);
return;
}
}
AHardwareBuffer_release(old);
}
}
static inline void loriePixmapUnlock(PixmapPtr pixmap) {
if (pvfb->root.legacyDrawing)
return renderer_update_root(pixmap->drawable.width, pixmap->drawable.height, pixmap->devPrivate.ptr, pvfb->root.flip);
if (pvfb->root.locked)
AHardwareBuffer_unlock(pvfb->root.buffer, NULL);
pvfb->root.locked = FALSE;
pixmap->drawable.pScreen->ModifyPixmapHeader(pixmap, -1, -1, -1, -1, -1, NULL);
}
static inline Bool loriePixmapLock(PixmapPtr pixmap) {
AHardwareBuffer_Desc desc = {};
void *data;
int status;
if (pvfb->root.legacyDrawing)
return TRUE;
if (!pvfb->root.buffer) {
pvfb->root.locked = FALSE;
return FALSE;
}
AHardwareBuffer_describe(pvfb->root.buffer, &desc);
status = AHardwareBuffer_lock(pvfb->root.buffer, USAGE, -1, NULL, &data);
pvfb->root.locked = status == 0;
if (pvfb->root.locked)
pixmap->drawable.pScreen->ModifyPixmapHeader(pixmap, desc.width, desc.height, -1, -1, desc.stride * 4, data);
else
FatalError("Failed to lock surface: %d\n", status);
return pvfb->root.locked;
}
static void lorieTimerCallback(int fd, unused int r, void *arg) {
char dummy[8];
read(fd, dummy, 8);
if (renderer_should_redraw() && RegionNotEmpty(DamageRegion(pvfb->damage))) {
int redrawn = FALSE;
ScreenPtr pScreen = (ScreenPtr) arg;
loriePixmapUnlock(pScreen->GetScreenPixmap(pScreen));
redrawn = renderer_redraw(pvfb->env, pvfb->root.flip);
if (loriePixmapLock(pScreen->GetScreenPixmap(pScreen)) && redrawn)
DamageEmpty(pvfb->damage);
} else if (pvfb->cursorMoved)
renderer_redraw(pvfb->env, pvfb->root.flip);
pvfb->cursorMoved = FALSE;
}
static CARD32 lorieFramecounter(unused OsTimerPtr timer, unused CARD32 time, unused void *arg) {
renderer_print_fps(5000);
return 5000;
}
static Bool lorieCreateScreenResources(ScreenPtr pScreen) {
Bool ret;
pScreen->CreateScreenResources = pvfb->CreateScreenResources;
ret = pScreen->CreateScreenResources(pScreen);
if (!ret)
return FALSE;
pScreen->devPrivate = fbCreatePixmap(pScreen, 0, 0, pScreen->rootDepth, CREATE_PIXMAP_USAGE_BACKING_PIXMAP);
pvfb->damage = DamageCreate(NULL, NULL, DamageReportNone, TRUE, pScreen, NULL);
if (!pvfb->damage)
FatalError("Couldn't setup damage\n");
DamageRegister(&(*pScreen->GetScreenPixmap)(pScreen)->drawable, pvfb->damage);
pvfb->fpsTimer = TimerSet(NULL, 0, 5000, lorieFramecounter, pScreen);
lorieUpdateBuffer();
return TRUE;
}
static Bool
lorieCloseScreen(ScreenPtr pScreen) {
unwrap(pvfb, pScreen, CloseScreen)
// No need to call fbDestroyPixmap since AllocatePixmap sets pixmap as PRIVATE_SCREEN so it is destroyed automatically.
return pScreen->CloseScreen(pScreen);
}
static Bool
lorieRRScreenSetSize(ScreenPtr pScreen, CARD16 width, CARD16 height, unused CARD32 mmWidth, unused CARD32 mmHeight) {
SetRootClip(pScreen, ROOT_CLIP_NONE);
pvfb->root.width = pScreen->width = width;
pvfb->root.height = pScreen->height = height;
pScreen->mmWidth = ((double) (width)) * 25.4 / monitorResolution;
pScreen->mmHeight = ((double) (height)) * 25.4 / monitorResolution;
lorieUpdateBuffer();
pScreen->ResizeWindow(pScreen->root, 0, 0, width, height, NULL);
DamageEmpty(pvfb->damage);
SetRootClip(pScreen, ROOT_CLIP_FULL);
RRScreenSizeNotify(pScreen);
update_desktop_dimensions();
pvfb->cursorMoved = TRUE;
return TRUE;
}
static Bool
lorieRRCrtcSet(unused ScreenPtr pScreen, RRCrtcPtr crtc, RRModePtr mode, int x, int y,
Rotation rotation, int numOutput, RROutputPtr *outputs) {
return RRCrtcNotify(crtc, mode, x, y, rotation, NULL, numOutput, outputs);
}
static Bool
lorieRRGetInfo(unused ScreenPtr pScreen, Rotation *rotations) {
*rotations = RR_Rotate_0;
return TRUE;
}
static Bool
lorieRandRInit(ScreenPtr pScreen) {
rrScrPrivPtr pScrPriv;
RROutputPtr output;
RRCrtcPtr crtc;
RRModePtr mode;
char screenName[1024] = "screen";
if (!RRScreenInit(pScreen))
return FALSE;
pScrPriv = rrGetScrPriv(pScreen);
pScrPriv->rrGetInfo = lorieRRGetInfo;
pScrPriv->rrCrtcSet = lorieRRCrtcSet;
pScrPriv->rrScreenSetSize = lorieRRScreenSetSize;
RRScreenSetSizeRange(pScreen, 1, 1, 32767, 32767);
if (FALSE
|| !(mode = lorieCvt(pScreen->width, pScreen->height, 30))
|| !(crtc = RRCrtcCreate(pScreen, NULL))
|| !RRCrtcGammaSetSize(crtc, 256)
|| !(output = RROutputCreate(pScreen, screenName, sizeof(screenName), NULL))
|| (output->nameLength = strlen(output->name), FalseNoop())
|| !RROutputSetClones(output, NULL, 0)
|| !RROutputSetModes(output, &mode, 1, 0)
|| !RROutputSetCrtcs(output, &crtc, 1)
|| !RROutputSetConnection(output, RR_Connected)
|| !RRCrtcNotify(crtc, mode, 0, 0, RR_Rotate_0, NULL, 1, &output))
return FALSE;
return TRUE;
}
static Bool resetRootCursor(unused ClientPtr pClient, unused void *closure) {
CursorVisible = TRUE;
pScreenPtr->DisplayCursor(lorieMouse, pScreenPtr, NullCursor);
pScreenPtr->DisplayCursor(lorieMouse, pScreenPtr, rootCursor);
return TRUE;
}
static Bool
lorieScreenInit(ScreenPtr pScreen, unused int argc, unused char **argv) {
static int timerFd = -1;
pScreenPtr = pScreen;
if (timerFd == -1) {
struct itimerspec spec = {0};
timerFd = timerfd_create(CLOCK_MONOTONIC, 0);
timerfd_settime(timerFd, 0, &spec, NULL);
}
pvfb->timerFd = timerFd;
SetNotifyFd(timerFd, lorieTimerCallback, X_NOTIFY_READ, pScreen);
miSetZeroLineBias(pScreen, 0);
pScreen->blackPixel = 0;
pScreen->whitePixel = 1;
if (FALSE
|| !miSetVisualTypesAndMasks(24, ((1 << TrueColor) | (1 << DirectColor)), 8, TrueColor, 0xFF0000, 0x00FF00, 0x0000FF)
|| !miSetPixmapDepths()
|| !fbScreenInit(pScreen, NULL, pvfb->root.width, pvfb->root.height, monitorResolution, monitorResolution, 0, 32)
|| !(!pvfb->dri3 || lorieInitDri3(pScreen))
|| !fbPictureInit(pScreen, 0, 0)
|| !lorieRandRInit(pScreen)
|| !miPointerInitialize(pScreen, &loriePointerSpriteFuncs, &loriePointerCursorFuncs, TRUE)
|| !fbCreateDefColormap(pScreen))
return FALSE;
wrap(pvfb, pScreen, CreateScreenResources, lorieCreateScreenResources)
wrap(pvfb, pScreen, CloseScreen, lorieCloseScreen)
QueueWorkProc(resetRootCursor, NULL, NULL);
ShmRegisterFbFuncs(pScreen);
return TRUE;
} /* end lorieScreenInit */
// From xfixes/cursor.c
static CursorPtr
CursorForDevice(DeviceIntPtr pDev) {
if (!CursorVisible || !EnableCursor)
return NULL;
if (pDev && pDev->spriteInfo) {
if (pDev->spriteInfo->anim.pCursor)
return pDev->spriteInfo->anim.pCursor;
return pDev->spriteInfo->sprite ? pDev->spriteInfo->sprite->current : NULL;
}
return NULL;
}
Bool lorieChangeScreenName(unused ClientPtr pClient, void *closure) {
RROutputPtr output = RRFirstOutput(pScreenPtr);
memset(output->name, 0, 1024);
strncpy(output->name, closure, 1024);
output->name[1023] = '\0';
output->nameLength = strlen(output->name);
free(closure);
return TRUE;
}
Bool lorieChangeWindow(unused ClientPtr pClient, void *closure) {
jobject surface = (jobject) closure;
renderer_set_window(pvfb->env, surface, pvfb->root.buffer);
lorieSetCursor(NULL, NULL, CursorForDevice(GetMaster(lorieMouse, MASTER_POINTER)), -1, -1);
if (pvfb->root.legacyDrawing) {
renderer_update_root(pScreenPtr->width, pScreenPtr->height, ((PixmapPtr) pScreenPtr->devPrivate)->devPrivate.ptr, pvfb->root.flip);
renderer_redraw(pvfb->env, pvfb->root.flip);
}
return TRUE;
}
void lorieConfigureNotify(int width, int height, int framerate) {
ScreenPtr pScreen = pScreenPtr;
RROutputPtr output = RRFirstOutput(pScreen);
if (output && width && height && (pScreen->width != width || pScreen->height != height)) {
CARD32 mmWidth, mmHeight;
RRModePtr mode = lorieCvt(width, height, framerate);
mmWidth = ((double) (mode->mode.width)) * 25.4 / monitorResolution;
mmHeight = ((double) (mode->mode.width)) * 25.4 / monitorResolution;
RROutputSetModes(output, &mode, 1, 0);
RRCrtcNotify(RRFirstEnabledCrtc(pScreen), mode,0, 0,RR_Rotate_0, NULL, 1, &output);
RRScreenSizeSet(pScreen, mode->mode.width, mode->mode.height, mmWidth, mmHeight);
}
if (framerate > 0) {
long nsecs = 1000 * 1000 * 1000 / framerate;
struct itimerspec spec = { { 0, nsecs }, { 0, nsecs } };
timerfd_settime(lorieScreen.timerFd, 0, &spec, NULL);
log(VERBOSE, "New framerate is %d", framerate);
FakeScreenFps = framerate;
present_fake_screen_init(pScreen);
}
}
void
InitOutput(ScreenInfo * screen_info, int argc, char **argv) {
int depths[] = { 1, 4, 8, 15, 16, 24, 32 };
int bpp[] = { 1, 8, 8, 16, 16, 32, 32 };
int i;
if (monitorResolution == 0)
monitorResolution = 96;
for(i = 0; i < ARRAY_SIZE(depths); i++) {
screen_info->formats[i].depth = depths[i];
screen_info->formats[i].bitsPerPixel = bpp[i];
screen_info->formats[i].scanlinePad = BITMAP_SCANLINE_PAD;
}
screen_info->imageByteOrder = IMAGE_BYTE_ORDER;
screen_info->bitmapScanlineUnit = BITMAP_SCANLINE_UNIT;
screen_info->bitmapScanlinePad = BITMAP_SCANLINE_PAD;
screen_info->bitmapBitOrder = BITMAP_BIT_ORDER;
screen_info->numPixmapFormats = ARRAY_SIZE(depths);
renderer_init(pvfb->env, &pvfb->root.legacyDrawing, &pvfb->root.flip);
xorgGlxCreateVendor();
lorieInitClipboard();
if (-1 == AddScreen(lorieScreenInit, argc, argv)) {
FatalError("Couldn't add screen %d\n", i);
}
}
void lorieSetVM(JavaVM* vm) {
pvfb->vm = vm;
(*vm)->AttachCurrentThread(vm, &pvfb->env, NULL);
}
static GLboolean drawableSwapBuffers(unused ClientPtr client, unused __GLXdrawable * drawable) { return TRUE; }
static void drawableCopySubBuffer(unused __GLXdrawable * basePrivate, unused int x, unused int y, unused int w, unused int h) {}
static __GLXdrawable * createDrawable(unused ClientPtr client, __GLXscreen * screen, DrawablePtr pDraw,
unused XID drawId, int type, XID glxDrawId, __GLXconfig * glxConfig) {
__GLXdrawable *private = calloc(1, sizeof *private);
if (private == NULL)
return NULL;
if (!__glXDrawableInit(private, screen, pDraw, type, glxDrawId, glxConfig)) {
free(private);
return NULL;
}
private->destroy = (void (*)(__GLXdrawable *)) free;
private->swapBuffers = drawableSwapBuffers;
private->copySubBuffer = drawableCopySubBuffer;
return private;
}
static void glXDRIscreenDestroy(__GLXscreen *baseScreen) {
free(baseScreen->GLXextensions);
free(baseScreen->GLextensions);
free(baseScreen->visuals);
free(baseScreen);
}
static __GLXscreen *glXDRIscreenProbe(ScreenPtr pScreen) {
__GLXscreen *screen;
screen = calloc(1, sizeof *screen);
if (screen == NULL)
return NULL;
screen->destroy = glXDRIscreenDestroy;
screen->createDrawable = createDrawable;
screen->pScreen = pScreen;
screen->fbconfigs = configs;
screen->glvnd = "mesa";
__glXInitExtensionEnableBits(screen->glx_enable_bits);
/* There is no real GLX support, but anyways swrast reports it. */
__glXEnableExtension(screen->glx_enable_bits, "GLX_MESA_copy_sub_buffer");
__glXEnableExtension(screen->glx_enable_bits, "GLX_EXT_no_config_context");
__glXEnableExtension(screen->glx_enable_bits, "GLX_ARB_create_context");
__glXEnableExtension(screen->glx_enable_bits, "GLX_ARB_create_context_no_error");
__glXEnableExtension(screen->glx_enable_bits, "GLX_ARB_create_context_profile");
__glXEnableExtension(screen->glx_enable_bits, "GLX_EXT_create_context_es_profile");
__glXEnableExtension(screen->glx_enable_bits, "GLX_EXT_create_context_es2_profile");
__glXEnableExtension(screen->glx_enable_bits, "GLX_EXT_framebuffer_sRGB");
__glXEnableExtension(screen->glx_enable_bits, "GLX_ARB_fbconfig_float");
__glXEnableExtension(screen->glx_enable_bits, "GLX_EXT_fbconfig_packed_float");
__glXEnableExtension(screen->glx_enable_bits, "GLX_EXT_texture_from_pixmap");
__glXScreenInit(screen, pScreen);
return screen;
}
__GLXprovider __glXDRISWRastProvider = {
glXDRIscreenProbe,
"DRISWRAST",
NULL
};

View File

@@ -0,0 +1,898 @@
/* Copyright (C) 2009 TightVNC Team
* Copyright (C) 2009 Red Hat, Inc.
* Copyright 2013-2018 Pierre Ossman for Cendio AB
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this software; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#pragma clang diagnostic ignored "-Wunknown-pragmas"
#pragma ide diagnostic ignored "UnusedValue"
#pragma ide diagnostic ignored "ConstantParameter"
#pragma ide diagnostic ignored "misc-no-recursion"
#pragma ide diagnostic ignored "OCDFAInspection"
#pragma clang diagnostic ignored "-Wdeclaration-after-statement"
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#include <stdio.h>
#include <globals.h>
#include "xkbsrv.h"
#include "xkbstr.h"
#include "eventstr.h"
#include "scrnintstr.h"
#include "mi.h"
#include <X11/keysym.h>
#include <selection.h>
#ifndef KEYBOARD_OR_FLOAT
#define KEYBOARD_OR_FLOAT MASTER_KEYBOARD
#endif
#define unused __attribute__((__unused__))
extern DeviceIntPtr lorieKeyboard;
static const KeyCode fakeKeys[] = {
92, 203, 204, 205, 206, 207
};
static KeySym pressedKeys[256] = {0};
/* altKeysym is a table of alternative keysyms which have the same meaning. */
static struct altKeysym_t {
KeySym a, b;
} altKeysym[] = {
{ XK_Shift_L, XK_Shift_R },
{ XK_Control_L, XK_Control_R },
{ XK_Meta_L, XK_Meta_R },
{ XK_Alt_L, XK_Alt_R },
{ XK_Super_L, XK_Super_R },
{ XK_Hyper_L, XK_Hyper_R },
{ XK_KP_Space, XK_space },
{ XK_KP_Tab, XK_Tab },
{ XK_KP_Enter, XK_Return },
{ XK_KP_F1, XK_F1 },
{ XK_KP_F2, XK_F2 },
{ XK_KP_F3, XK_F3 },
{ XK_KP_F4, XK_F4 },
{ XK_KP_Home, XK_Home },
{ XK_KP_Left, XK_Left },
{ XK_KP_Up, XK_Up },
{ XK_KP_Right, XK_Right },
{ XK_KP_Down, XK_Down },
{ XK_KP_Page_Up, XK_Page_Up },
{ XK_KP_Page_Down, XK_Page_Down },
{ XK_KP_End, XK_End },
{ XK_KP_Begin, XK_Begin },
{ XK_KP_Insert, XK_Insert },
{ XK_KP_Delete, XK_Delete },
{ XK_KP_Equal, XK_equal },
{ XK_KP_Multiply, XK_asterisk },
{ XK_KP_Add, XK_plus },
{ XK_KP_Separator, XK_comma },
{ XK_KP_Subtract, XK_minus },
{ XK_KP_Decimal, XK_period },
{ XK_KP_Divide, XK_slash },
{ XK_KP_0, XK_0 },
{ XK_KP_1, XK_1 },
{ XK_KP_2, XK_2 },
{ XK_KP_3, XK_3 },
{ XK_KP_4, XK_4 },
{ XK_KP_5, XK_5 },
{ XK_KP_6, XK_6 },
{ XK_KP_7, XK_7 },
{ XK_KP_8, XK_8 },
{ XK_KP_9, XK_9 },
{ XK_ISO_Level3_Shift, XK_Mode_switch },
};
void lorieKeysymKeyboardEvent(KeySym keysym, int down);
KeyCode lorieKeysymToKeycode(KeySym keysym, unsigned state, unsigned *new_state);
/* Stolen from libX11 */
static Bool
XkbTranslateKeyCode(register XkbDescPtr xkb, KeyCode key,
register unsigned int mods, unsigned int *mods_rtrn,
KeySym *keysym_rtrn) {
XkbKeyTypeRec *type;
int col,nKeyGroups;
unsigned preserve,effectiveGroup;
KeySym *syms;
if (mods_rtrn!=NULL)
*mods_rtrn = 0;
nKeyGroups= XkbKeyNumGroups(xkb,key);
if ((!XkbKeycodeInRange(xkb,key))||(nKeyGroups==0)) {
if (keysym_rtrn!=NULL)
*keysym_rtrn = NoSymbol;
return FALSE;
}
syms = XkbKeySymsPtr(xkb,key);
/* find the offset of the effective group */
col = 0;
effectiveGroup= XkbGroupForCoreState(mods);
if ( effectiveGroup>=nKeyGroups ) {
unsigned groupInfo= XkbKeyGroupInfo(xkb,key);
switch (XkbOutOfRangeGroupAction(groupInfo)) {
default:
effectiveGroup %= nKeyGroups;
break;
case XkbClampIntoRange:
effectiveGroup = nKeyGroups-1;
break;
case XkbRedirectIntoRange:
effectiveGroup = XkbOutOfRangeGroupNumber(groupInfo);
if (effectiveGroup>=nKeyGroups)
effectiveGroup= 0;
break;
}
}
col= (int) effectiveGroup * XkbKeyGroupsWidth(xkb,key);
type = XkbKeyKeyType(xkb,key,effectiveGroup);
preserve= 0;
if (type->map) { /* find the column (shift level) within the group */
register int i;
register XkbKTMapEntryPtr entry;
for (i=0,entry=type->map;i<type->map_count;i++,entry++) {
if ((entry->active)&&((mods&type->mods.mask)==entry->mods.mask)) {
col+= entry->level;
if (type->preserve)
preserve= type->preserve[i].mask;
break;
}
}
}
if (keysym_rtrn!=NULL)
*keysym_rtrn= syms[col];
if (mods_rtrn)
*mods_rtrn= type->mods.mask&(~preserve);
return (syms[col]!=NoSymbol);
}
static XkbAction *XkbKeyActionPtr(XkbDescPtr xkb, KeyCode key, unsigned int mods) {
XkbKeyTypeRec *type;
int col,nKeyGroups;
unsigned effectiveGroup;
unused XkbAction *acts;
if (!XkbKeyHasActions(xkb, key))
return NULL;
nKeyGroups= XkbKeyNumGroups(xkb,key);
if ((!XkbKeycodeInRange(xkb,key))||(nKeyGroups==0))
return NULL;
acts = XkbKeyActionsPtr(xkb,key);
/* find the offset of the effective group */
col = 0;
effectiveGroup= XkbGroupForCoreState(mods);
if ( effectiveGroup>=nKeyGroups ) {
unsigned groupInfo= XkbKeyGroupInfo(xkb,key);
switch (XkbOutOfRangeGroupAction(groupInfo)) {
default:
effectiveGroup %= nKeyGroups;
break;
case XkbClampIntoRange:
effectiveGroup = nKeyGroups-1;
break;
case XkbRedirectIntoRange:
effectiveGroup = XkbOutOfRangeGroupNumber(groupInfo);
if (effectiveGroup>=nKeyGroups)
effectiveGroup= 0;
break;
}
}
col= (int) effectiveGroup * XkbKeyGroupsWidth(xkb,key);
type = XkbKeyKeyType(xkb,key,effectiveGroup);
if (type->map) { /* find the column (shift level) within the group */
register int i;
register XkbKTMapEntryPtr entry;
for (i=0,entry=type->map;i<type->map_count;i++,entry++) {
if ((entry->active)&&((mods&type->mods.mask)==entry->mods.mask)) {
col+= entry->level;
break;
}
}
}
return &acts[col];
}
static unsigned XkbKeyEffectiveGroup(XkbDescPtr xkb, KeyCode key, unsigned int mods) {
int nKeyGroups;
unsigned effectiveGroup;
nKeyGroups= XkbKeyNumGroups(xkb,key);
if ((!XkbKeycodeInRange(xkb,key))||(nKeyGroups==0))
return 0;
effectiveGroup= XkbGroupForCoreState(mods);
if ( effectiveGroup>=nKeyGroups ) {
unsigned groupInfo= XkbKeyGroupInfo(xkb,key);
switch (XkbOutOfRangeGroupAction(groupInfo)) {
default:
effectiveGroup %= nKeyGroups;
break;
case XkbClampIntoRange:
effectiveGroup = nKeyGroups-1;
break;
case XkbRedirectIntoRange:
effectiveGroup = XkbOutOfRangeGroupNumber(groupInfo);
if (effectiveGroup>=nKeyGroups)
effectiveGroup= 0;
break;
}
}
return effectiveGroup;
}
static unsigned lorieGetKeyboardState(void) {
DeviceIntPtr master;
master = GetMaster(lorieKeyboard, KEYBOARD_OR_FLOAT);
return XkbStateFieldFromRec(&master->key->xkbInfo->state);
}
static unsigned lorieGetLevelThreeMask(void) {
unsigned state;
KeyCode keycode;
XkbDescPtr xkb;
XkbAction *act;
/* Group state is still important */
state = lorieGetKeyboardState();
state &= ~0xff;
keycode = lorieKeysymToKeycode(XK_ISO_Level3_Shift, state, NULL);
if (keycode == 0) {
keycode = lorieKeysymToKeycode(XK_Mode_switch, state, NULL);
if (keycode == 0)
return 0;
}
xkb = GetMaster(lorieKeyboard, KEYBOARD_OR_FLOAT)->key->xkbInfo->desc;
act = XkbKeyActionPtr(xkb, keycode, state);
if (act == NULL)
return 0;
if (act->type != XkbSA_SetMods)
return 0;
if (act->mods.flags & XkbSA_UseModMapMods)
return xkb->map->modmap[keycode];
else
return act->mods.mask;
}
static KeyCode loriePressShift(void) {
unsigned state;
XkbDescPtr xkb;
unsigned int key;
state = lorieGetKeyboardState();
if (state & ShiftMask)
return 0;
xkb = GetMaster(lorieKeyboard, KEYBOARD_OR_FLOAT)->key->xkbInfo->desc;
for (key = xkb->min_key_code; key <= xkb->max_key_code; key++) {
XkbAction *act;
unsigned char mask;
act = XkbKeyActionPtr(xkb, key, state);
if (act == NULL)
continue;
if (act->type != XkbSA_SetMods)
continue;
if (act->mods.flags & XkbSA_UseModMapMods)
mask = xkb->map->modmap[key];
else
mask = act->mods.mask;
if ((mask & ShiftMask) == ShiftMask)
return key;
}
return 0;
}
static size_t lorieReleaseShift(KeyCode *keys, size_t maxKeys) {
size_t count;
unsigned state;
DeviceIntPtr master;
XkbDescPtr xkb;
unsigned int key;
state = lorieGetKeyboardState();
if (!(state & ShiftMask))
return 0;
count = 0;
master = GetMaster(lorieKeyboard, KEYBOARD_OR_FLOAT);
xkb = master->key->xkbInfo->desc;
for (key = xkb->min_key_code; key <= xkb->max_key_code; key++) {
XkbAction *act;
unsigned char mask;
if (!key_is_down(master, (int) key, KEY_PROCESSED))
continue;
act = XkbKeyActionPtr(xkb, key, state);
if (act == NULL)
continue;
if (act->type != XkbSA_SetMods)
continue;
if (act->mods.flags & XkbSA_UseModMapMods)
mask = xkb->map->modmap[key];
else
mask = act->mods.mask;
if (!(mask & ShiftMask))
continue;
if (count >= maxKeys)
return 0;
keys[count++] = key;
}
return count;
}
static KeyCode loriePressLevelThree(void) {
unsigned state, mask;
KeyCode keycode;
XkbDescPtr xkb;
XkbAction *act;
mask = lorieGetLevelThreeMask();
if (mask == 0)
return 0;
state = lorieGetKeyboardState();
if (state & mask)
return 0;
keycode = lorieKeysymToKeycode(XK_ISO_Level3_Shift, state, NULL);
if (keycode == 0) {
keycode = lorieKeysymToKeycode(XK_Mode_switch, state, NULL);
if (keycode == 0)
return 0;
}
xkb = GetMaster(lorieKeyboard, KEYBOARD_OR_FLOAT)->key->xkbInfo->desc;
act = XkbKeyActionPtr(xkb, keycode, state);
if (act == NULL)
return 0;
if (act->type != XkbSA_SetMods)
return 0;
return keycode;
}
static size_t lorieReleaseLevelThree(KeyCode *keys, size_t maxKeys) {
size_t count;
unsigned state, mask;
DeviceIntPtr master;
XkbDescPtr xkb;
unsigned int key;
mask = lorieGetLevelThreeMask();
if (mask == 0)
return 0;
state = lorieGetKeyboardState();
if (!(state & mask))
return 0;
count = 0;
master = GetMaster(lorieKeyboard, KEYBOARD_OR_FLOAT);
xkb = master->key->xkbInfo->desc;
for (key = xkb->min_key_code; key <= xkb->max_key_code; key++) {
XkbAction *act;
unsigned char key_mask;
if (!key_is_down(master, (int) key, KEY_PROCESSED))
continue;
act = XkbKeyActionPtr(xkb, key, state);
if (act == NULL)
continue;
if (act->type != XkbSA_SetMods)
continue;
if (act->mods.flags & XkbSA_UseModMapMods)
key_mask = xkb->map->modmap[key];
else
key_mask = act->mods.mask;
if (!(key_mask & mask))
continue;
if (count >= maxKeys)
return 0;
keys[count++] = key;
}
return count;
}
KeyCode lorieKeysymToKeycode(KeySym keysym, unsigned state, unsigned *new_state) {
XkbDescPtr xkb;
unsigned int key; // KeyCode has insufficient range for the loop
KeyCode fallback;
KeySym ks;
unsigned level_three_mask;
if (new_state != NULL)
*new_state = state;
fallback = 0;
xkb = GetMaster(lorieKeyboard, KEYBOARD_OR_FLOAT)->key->xkbInfo->desc;
for (key = xkb->min_key_code; key <= xkb->max_key_code; key++) {
unsigned int state_out;
KeySym dummy;
size_t fakeIdx;
XkbTranslateKeyCode(xkb, key, state, &state_out, &ks);
if (ks == NoSymbol)
continue;
/*
* Despite every known piece of documentation on
* XkbTranslateKeyCode() stating that mods_rtrn returns
* the unconsumed modifiers, in reality it always
* returns the _potentially consumed_ modifiers.
*/
state_out = state & ~state_out;
if (state_out & LockMask)
XkbConvertCase(ks, &dummy, &ks);
if (ks != keysym)
continue;
/*
* Some keys are never sent by a real keyboard and are
* used in the default layouts as a fallback for
* modifiers. Make sure we use them last as some
* applications can be confused by these normally
* unused keys.
*/
for (fakeIdx = 0; fakeIdx < ARRAY_SIZE(fakeKeys); fakeIdx++) {
if (key == fakeKeys[fakeIdx]) {
if (fallback == 0)
fallback = key;
break;
}
}
if (fakeIdx < ARRAY_SIZE(fakeKeys))
continue;
return key;
}
/* Use the fallback key, if one was found */
if (fallback != 0)
return fallback;
if (new_state == NULL)
return 0;
*new_state = (state & ~ShiftMask) | ((state & ShiftMask) ? 0 : ShiftMask);
key = lorieKeysymToKeycode(keysym, *new_state, NULL);
if (key != 0)
return key;
level_three_mask = lorieGetLevelThreeMask();
if (level_three_mask == 0)
return 0;
*new_state = (state & ~level_three_mask) |
((state & level_three_mask) ? 0 : level_three_mask);
key = lorieKeysymToKeycode(keysym, *new_state, NULL);
if (key != 0)
return key;
*new_state = (state & ~(ShiftMask | level_three_mask)) |
((state & ShiftMask) ? 0 : ShiftMask) |
((state & level_three_mask) ? 0 : level_three_mask);
key = lorieKeysymToKeycode(keysym, *new_state, NULL);
if (key != 0)
return key;
return 0;
}
static int lorieIsAffectedByNumLock(KeyCode keycode) {
unsigned state;
KeyCode numlock_keycode;
unsigned numlock_mask;
XkbDescPtr xkb;
XkbAction *act;
XkbKeyTypeRec *type;
/* Group state is still important */
state = lorieGetKeyboardState();
state &= ~0xff;
/*
* Not sure if hunting for a virtual modifier called "NumLock",
* or following the keysym Num_Lock is the best approach. We
* try the latter.
*/
numlock_keycode = lorieKeysymToKeycode(XK_Num_Lock, state, NULL);
if (numlock_keycode == 0)
return 0;
xkb = GetMaster(lorieKeyboard, KEYBOARD_OR_FLOAT)->key->xkbInfo->desc;
act = XkbKeyActionPtr(xkb, numlock_keycode, state);
if (act == NULL)
return 0;
if (act->type != XkbSA_LockMods)
return 0;
if (act->mods.flags & XkbSA_UseModMapMods)
numlock_mask = xkb->map->modmap[keycode];
else
numlock_mask = act->mods.mask;
type = XkbKeyKeyType(xkb, keycode, XkbKeyEffectiveGroup(xkb, keycode, state));
if ((type->mods.mask & numlock_mask) == 0)
return 0;
return 1;
}
static KeyCode lorieAddKeysym(KeySym keysym, unused unsigned state) {
DeviceIntPtr master;
XkbDescPtr xkb;
unsigned int key;
XkbEventCauseRec cause;
XkbChangesRec changes;
int types[1];
KeySym *syms;
KeySym upper, lower;
master = GetMaster(lorieKeyboard, KEYBOARD_OR_FLOAT);
xkb = master->key->xkbInfo->desc;
static int curFakeKeyIdx = 0;
key = fakeKeys[curFakeKeyIdx++];
if (curFakeKeyIdx >= ARRAY_SIZE(fakeKeys))
curFakeKeyIdx = 0;
memset(&changes, 0, sizeof(changes));
memset(&cause, 0, sizeof(cause));
XkbSetCauseUnknown(&cause)
/*
* Tools like xkbcomp get confused if there isn't a name
* assigned to the keycode we're trying to use.
*/
if (xkb->names && xkb->names->keys &&
(xkb->names->keys[key].name[0] == '\0')) {
xkb->names->keys[key].name[0] = 'I';
xkb->names->keys[key].name[1] = '0' + (key / 100) % 10;
xkb->names->keys[key].name[2] = '0' + (key / 10) % 10;
xkb->names->keys[key].name[3] = '0' + (key / 1) % 10;
changes.names.changed |= XkbKeyNamesMask;
changes.names.first_key = key;
changes.names.num_keys = 1;
}
XkbConvertCase(keysym, &lower, &upper);
types[XkbGroup1Index] = XkbAlphabeticIndex;
XkbChangeTypesOfKey(xkb, (int) key, 1, XkbGroup1Mask, types, &changes.map);
syms = XkbKeySymsPtr(xkb, key);
syms[0] = lower;
syms[1] = upper;
changes.map.changed |= XkbKeySymsMask;
changes.map.first_key_sym = key;
changes.map.num_key_syms = 1;
XkbSendNotification(master, &changes, &cause);
return key;
}
/*
* lorieKeysymKeyboardEvent() - work out the best keycode corresponding
* to the keysym sent by the viewer. This is basically impossible in
* the general case, but we make a best effort by assuming that all
* useful keysyms can be reached using just the Shift and
* Level 3 (AltGr) modifiers. For core keyboards this is basically
* always true, and should be true for most sane, western XKB layouts.
*/
void lorieKeysymKeyboardEvent(KeySym keysym, int down) {
int i;
unsigned state, new_state;
KeyCode keycode;
unsigned level_three_mask;
KeyCode shift_press, level_three_press;
KeyCode shift_release[8], level_three_release[8];
size_t shift_release_count, level_three_release_count;
/*
* Release events must match the press event, so look up what
* keycode we sent for the press.
*/
if (!down) {
for (i = 0;i < 256;i++) {
if (pressedKeys[i] == keysym) {
pressedKeys[i] = NoSymbol;
QueueKeyboardEvents(lorieKeyboard, KeyRelease, i); // "keycode"
mieqProcessInputEvents();
return;
}
}
/*
* This can happen quite often as we ignore some
* key presses.
*/
LogMessageVerb(X_DEBUG, -1, "Unexpected release of keysym 0x%x\n", keysym);
return;
}
/*
* Since we are checking the current state to determine if we need
* to fake modifiers, we must make sure that everything put on the
* input queue is processed before we start. Otherwise, shift may be
* stuck down.
*/
mieqProcessInputEvents();
state = lorieGetKeyboardState();
keycode = lorieKeysymToKeycode(keysym, state, &new_state);
/* Try some equivalent keysyms if we couldn't find a perfect match */
if (keycode == 0) {
for (i = 0;i < sizeof(altKeysym)/sizeof(altKeysym[0]);i++) {
KeySym altsym;
if (altKeysym[i].a == keysym)
altsym = altKeysym[i].b;
else if (altKeysym[i].b == keysym)
altsym = altKeysym[i].a;
else
continue;
keycode = lorieKeysymToKeycode(altsym, state, &new_state);
if (keycode != 0)
break;
}
}
/* No matches. Will have to add a new entry... */
if (keycode == 0) {
keycode = lorieAddKeysym(keysym, state);
if (keycode == 0) {
LogMessageVerb(X_ERROR, -1, "Failure adding new keysym 0x%x\n", keysym);
return;
}
LogMessageVerb(X_INFO, 0, "Added unknown keysym 0x%x to keycode %d\n",
keysym, keycode);
/*
* The state given to addKeysym() is just a hint and
* the actual result might still require some state
* changes.
*/
keycode = lorieKeysymToKeycode(keysym, state, &new_state);
if (keycode == 0) {
LogMessageVerb(X_ERROR, -1, "Newly added keysym 0x%x cannot be generated\n", keysym);
return;
}
}
/*
* X11 generally lets shift toggle the keys on the numeric pad
* the same way NumLock does. This is however not the case on
* other systems like Windows. As a result, some applications
* get confused when we do a fake shift to get the same effect
* that having NumLock active would produce.
*
* Not all clients have proper NumLock synchronisation (so we
* can avoid faking shift) so we try to avoid the fake shifts
* if we can use an alternative keysym.
*/
if (((state & ShiftMask) != (new_state & ShiftMask)) && lorieIsAffectedByNumLock(keycode)) {
KeyCode keycode2;
unsigned new_state2;
LogMessageVerb(X_DEBUG, 0, "Finding alternative to keysym 0x%x to avoid fake shift for numpad\n", keysym);
for (i = 0;i < sizeof(altKeysym)/sizeof(altKeysym[0]);i++) {
KeySym altsym;
if (altKeysym[i].a == keysym)
altsym = altKeysym[i].b;
else if (altKeysym[i].b == keysym)
altsym = altKeysym[i].a;
else
continue;
keycode2 = lorieKeysymToKeycode(altsym, state, &new_state2);
if (keycode2 == 0)
continue;
if (((state & ShiftMask) != (new_state2 & ShiftMask)) &&
lorieIsAffectedByNumLock(keycode2))
continue;
break;
}
if (i == sizeof(altKeysym)/sizeof(altKeysym[0]))
LogMessageVerb(X_DEBUG, 0, "No alternative keysym found\n");
else {
keycode = keycode2;
new_state = new_state2;
}
}
/*
* "Shifted Tab" is a bit of a mess. Some systems have varying,
* special keysyms for this symbol. VNC mandates that clients
* should always send the plain XK_Tab keysym and the server
* should deduce the meaning based on current Shift state.
* To comply with this, we will find the keycode that sends
* XK_Tab, and make sure that Shift isn't cleared. This can
* possibly result in a different keysym than XK_Tab, but that
* is the desired behaviour.
*
* Note: We never get ISO_Left_Tab here because it's already
* been translated in VNCSConnectionST.
*/
if (keysym == XK_Tab && (state & ShiftMask))
new_state |= ShiftMask;
/*
* We need a bigger state change than just shift,
* so we need to know what the mask is for level 3 shifts.
*/
if ((new_state & ~ShiftMask) != (state & ~ShiftMask))
level_three_mask = lorieGetLevelThreeMask();
else
level_three_mask = 0;
shift_press = level_three_press = 0;
shift_release_count = level_three_release_count = 0;
/* Need a fake press or release of shift? */
if (!(state & ShiftMask) && (new_state & ShiftMask)) {
shift_press = loriePressShift();
if (shift_press == 0) {
LogMessageVerb(X_ERROR, -1, "Unable to find a modifier key for Shift\n");
return;
}
QueueKeyboardEvents(lorieKeyboard, KeyPress, shift_press); // "temp shift"
} else if ((state & ShiftMask) && !(new_state & ShiftMask)) {
shift_release_count = lorieReleaseShift(shift_release,
sizeof(shift_release)/sizeof(*shift_release));
if (shift_release_count == 0) {
LogMessageVerb(X_ERROR, -1, "Unable to find the modifier key(s) for releasing Shift\n");
return;
}
for (i = 0;i < shift_release_count;i++)
QueueKeyboardEvents(lorieKeyboard, KeyRelease, shift_release[i]); // "temp shift"
}
/* Need a fake press or release of level three shift? */
if (!(state & level_three_mask) && (new_state & level_three_mask)) {
level_three_press = loriePressLevelThree();
if (level_three_press == 0) {
LogMessageVerb(X_ERROR, -1, "Unable to find a modifier key for ISO_Level3_Shift/Mode_Switch\n");
return;
}
QueueKeyboardEvents(lorieKeyboard, KeyPress, level_three_press); // "temp level 3 shift"
} else if ((state & level_three_mask) && !(new_state & level_three_mask)) {
level_three_release_count = lorieReleaseLevelThree(level_three_release,
sizeof(level_three_release)/sizeof(*level_three_release));
if (level_three_release_count == 0) {
LogMessageVerb(X_ERROR, -1, "Unable to find the modifier key(s) for releasing ISO_Level3_Shift/Mode_Switch\n");
return;
}
for (i = 0;i < level_three_release_count;i++)
QueueKeyboardEvents(lorieKeyboard, KeyRelease, level_three_release[i]); // "temp level 3 shift"
}
/* Now press the actual key */
QueueKeyboardEvents(lorieKeyboard, KeyPress, keycode); // "keycode"
/* And store the mapping so that we can do a proper release later */
for (i = 0;i < 256;i++) {
if (i == keycode)
continue;
if (pressedKeys[i] == keysym) {
LogMessageVerb(X_ERROR, -1, "Keysym 0x%x generated by both keys %d and %d", keysym, i, keycode);
pressedKeys[i] = NoSymbol;
}
}
pressedKeys[keycode] = keysym;
/* Undo any fake level three shift */
if (level_three_press != 0)
QueueKeyboardEvents(lorieKeyboard, KeyRelease, level_three_press); // "temp level 3 shift"
else if (level_three_release_count != 0) {
for (i = 0;i < level_three_release_count;i++)
QueueKeyboardEvents(lorieKeyboard, KeyPress, level_three_release[i]); // "temp level 3 shift"
}
/* Undo any fake shift */
if (shift_press != 0)
QueueKeyboardEvents(lorieKeyboard, KeyRelease, shift_press); // "temp shift"
else if (shift_release_count != 0) {
for (i = 0;i < shift_release_count;i++)
QueueKeyboardEvents(lorieKeyboard, KeyPress, shift_release[i]); // "temp shift"
}
/*
* When faking a modifier we are putting a keycode (which can
* currently activate the desired modifier) on the input
* queue. A future modmap change can change the mapping so
* that this keycode means something else entirely. Guard
* against this by processing the queue now.
*/
mieqProcessInputEvents();
}

View File

@@ -0,0 +1,772 @@
#pragma clang diagnostic ignored "-Wunknown-pragmas"
#pragma clang diagnostic ignored "-Wmissing-prototypes"
#pragma ide diagnostic ignored "bugprone-reserved-identifier"
#pragma ide diagnostic ignored "OCUnusedMacroInspection"
#define __USE_GNU
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#include <jni.h>
#include <android/log.h>
#include <android/native_window_jni.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/prctl.h>
#include <sys/ioctl.h>
#include <libgen.h>
#include <globals.h>
#include <xkbsrv.h>
#include <errno.h>
#include <wchar.h>
#include <inpututils.h>
#include <randrstr.h>
#include "renderer.h"
#include "lorie.h"
#define log(prio, ...) __android_log_print(ANDROID_LOG_ ## prio, "LorieNative", __VA_ARGS__)
static int argc = 0;
static char** argv = NULL;
static int conn_fd = -1;
extern char *__progname; // NOLINT(bugprone-reserved-identifier)
extern DeviceIntPtr lorieMouse, lorieTouch, lorieKeyboard, loriePen, lorieEraser;
extern ScreenPtr pScreenPtr;
extern int ucs2keysym(long ucs);
void lorieKeysymKeyboardEvent(KeySym keysym, int down);
char *xtrans_unix_path_x11 = NULL;
char *xtrans_unix_dir_x11 = NULL;
typedef enum {
EVENT_SCREEN_SIZE,
EVENT_TOUCH,
EVENT_MOUSE,
EVENT_KEY,
EVENT_STYLUS,
EVENT_STYLUS_ENABLE,
EVENT_UNICODE,
EVENT_CLIPBOARD_ENABLE,
EVENT_CLIPBOARD_ANNOUNCE,
EVENT_CLIPBOARD_REQUEST,
EVENT_CLIPBOARD_SEND,
} eventType;
typedef union {
uint8_t type;
struct {
uint8_t t;
uint16_t width, height, framerate;
} screenSize;
struct {
uint8_t t;
uint16_t type, id, x, y;
} touch;
struct {
uint8_t t;
float x, y;
uint8_t detail, down, relative;
} mouse;
struct {
uint8_t t;
uint16_t key;
uint8_t state;
} key;
struct {
uint8_t t;
float x, y;
uint16_t pressure;
int8_t tilt_x, tilt_y;
int16_t orientation;
uint8_t buttons, eraser, mouse;
} stylus;
struct {
uint8_t t, enable;
} stylusEnable;
struct {
uint8_t t;
uint32_t code;
} unicode;
struct {
uint8_t t;
uint8_t enable;
} clipboardEnable;
struct {
uint8_t t;
uint32_t count;
} clipboardSend;
} lorieEvent;
static struct {
jclass self;
jmethodID forName;
jmethodID decode;
} Charset = {0};
static struct {
jclass self;
jmethodID toString;
} CharBuffer = {0};
static void* startServer(__unused void* cookie) {
lorieSetVM((JavaVM*) cookie);
char* envp[] = { NULL };
exit(dix_main(argc, (char**) argv, envp));
}
static jclass FindClassOrDie(JNIEnv *env, const char* name) {
jclass clazz = (*env)->FindClass(env, name);
if (!clazz) {
char buffer[1024] = {0};
sprintf(buffer, "class %s not found", name);
log(ERROR, "%s", buffer);
(*env)->FatalError(env, buffer);
return NULL;
}
return (*env)->NewGlobalRef(env, clazz);
}
static jclass FindMethodOrDie(JNIEnv *env, jclass clazz, const char* name, const char* signature, jboolean isStatic) {
__typeof__((*env)->GetMethodID) getMethodID = isStatic ? (*env)->GetStaticMethodID : (*env)->GetMethodID;
jmethodID method = getMethodID(env, clazz, name, signature);
if (!method) {
char buffer[1024] = {0};
sprintf(buffer, "method %s %s not found", name, signature);
log(ERROR, "%s", buffer);
(*env)->FatalError(env, buffer);
return NULL;
}
return method;
}
JNIEXPORT jboolean JNICALL
Java_com_termux_x11_CmdEntryPoint_start(JNIEnv *env, __unused jclass cls, jobjectArray args) {
pthread_t t;
JavaVM* vm = NULL;
// execv's argv array is a bit incompatible with Java's String[], so we do some converting here...
argc = (*env)->GetArrayLength(env, args) + 1; // Leading executable path
argv = (char**) calloc(argc, sizeof(char*));
argv[0] = (char*) "Xlorie";
for(int i=1; i<argc; i++) {
jstring js = (jstring)((*env)->GetObjectArrayElement(env, args, i - 1));
const char *pjc = (*env)->GetStringUTFChars(env, js, JNI_FALSE);
argv[i] = (char *) calloc(strlen(pjc) + 1, sizeof(char)); //Extra char for the terminating NULL
strcpy((char *) argv[i], pjc);
(*env)->ReleaseStringUTFChars(env, js, pjc);
}
{
cpu_set_t mask;
long num_cpus = sysconf(_SC_NPROCESSORS_ONLN);
for (int i = num_cpus/2; i < num_cpus; i++)
CPU_SET(i, &mask);
if (sched_setaffinity(0, sizeof(cpu_set_t), &mask) == -1)
log(ERROR, "Failed to set process affinity: %s", strerror(errno));
}
if (getenv("TERMUX_X11_DEBUG") && !fork()) {
// Printing logs of local logcat.
char pid[32] = {0};
prctl(PR_SET_PDEATHSIG, SIGTERM);
sprintf(pid, "%d", getppid());
execlp("logcat", "logcat", "--pid", pid, NULL);
}
// adb sets TMPDIR to /data/local/tmp which is pretty useless.
if (!strcmp("/data/local/tmp", getenv("TMPDIR") ?: ""))
unsetenv("TMPDIR");
if (!getenv("TMPDIR")) {
if (access("/tmp", F_OK) == 0)
setenv("TMPDIR", "/tmp", 1);
else if (access("/data/data/com.termux/files/usr/tmp", F_OK) == 0)
setenv("TMPDIR", "/data/data/com.termux/files/usr/tmp", 1);
}
if (!getenv("TMPDIR")) {
char* error = (char*) "$TMPDIR is not set. Normally it is pointing to /tmp of a container.";
log(ERROR, "%s", error);
dprintf(2, "%s\n", error);
return JNI_FALSE;
}
{
char* tmp = getenv("TMPDIR");
char cwd[1024] = {0};
if (!getcwd(cwd, sizeof(cwd)) || access(cwd, F_OK) != 0)
chdir(tmp);
asprintf(&xtrans_unix_path_x11, "%s/.X11-unix/X", tmp);
asprintf(&xtrans_unix_dir_x11, "%s/.X11-unix/", tmp);
}
log(VERBOSE, "Using TMPDIR=\"%s\"", getenv("TMPDIR"));
{
const char *root_dir = dirname(getenv("TMPDIR"));
const char* pathes[] = {
"/etc/X11/fonts", "/usr/share/fonts/X11", "/share/fonts", NULL
};
for (int i=0; pathes[i]; i++) {
char current_path[1024] = {0};
snprintf(current_path, sizeof(current_path), "%s%s", root_dir, pathes[i]);
if (access(current_path, F_OK) == 0) {
char default_font_path[4096] = {0};
snprintf(default_font_path, sizeof(default_font_path),
"%s/misc,%s/TTF,%s/OTF,%s/Type1,%s/100dpi,%s/75dpi",
current_path, current_path, current_path, current_path, current_path, current_path);
defaultFontPath = strdup(default_font_path);
break;
}
}
}
if (!getenv("XKB_CONFIG_ROOT")) {
// chroot case
const char *root_dir = dirname(getenv("TMPDIR"));
char current_path[1024] = {0};
snprintf(current_path, sizeof(current_path), "%s/usr/share/X11/xkb", root_dir);
if (access(current_path, F_OK) == 0)
setenv("XKB_CONFIG_ROOT", current_path, 1);
}
if (!getenv("XKB_CONFIG_ROOT")) {
// proot case
if (access("/usr/share/X11/xkb", F_OK) == 0)
setenv("XKB_CONFIG_ROOT", "/usr/share/X11/xkb", 1);
// Termux case
else if (access("/data/data/com.termux/files/usr/share/X11/xkb", F_OK) == 0)
setenv("XKB_CONFIG_ROOT", "/data/data/com.termux/files/usr/share/X11/xkb", 1);
}
if (!getenv("XKB_CONFIG_ROOT")) {
char* error = (char*) "$XKB_CONFIG_ROOT is not set. Normally it is pointing to /usr/share/X11/xkb of a container.";
log(ERROR, "%s", error);
dprintf(2, "%s\n", error);
return JNI_FALSE;
}
XkbBaseDirectory = getenv("XKB_CONFIG_ROOT");
if (access(XkbBaseDirectory, F_OK) != 0) {
log(ERROR, "%s is unaccessible: %s\n", XkbBaseDirectory, strerror(errno));
printf("%s is unaccessible: %s\n", XkbBaseDirectory, strerror(errno));
return JNI_FALSE;
}
(*env)->GetJavaVM(env, &vm);
pthread_create(&t, NULL, startServer, vm);
return JNI_TRUE;
}
JNIEXPORT void JNICALL
Java_com_termux_x11_CmdEntryPoint_windowChanged(JNIEnv *env, __unused jobject cls, jobject surface, jstring jname) {
const char *name = !jname ? NULL : (*env)->GetStringUTFChars(env, jname, JNI_FALSE);
QueueWorkProc(lorieChangeScreenName, NULL, name ? strndup(name, 1024) : strdup("screen"));
if (name)
(*env)->ReleaseStringUTFChars(env, jname, name);
QueueWorkProc(lorieChangeWindow, NULL, surface ? (*env)->NewGlobalRef(env, surface) : NULL);
}
static Bool sendConfigureNotify(__unused ClientPtr pClient, void *closure) {
// This must be done only on X server thread.
lorieEvent* e = closure;
__android_log_print(ANDROID_LOG_ERROR, "tx11-request", "window changed: %d %d", e->screenSize.width, e->screenSize.height);
lorieConfigureNotify(e->screenSize.width, e->screenSize.height, e->screenSize.framerate);
free(e);
return TRUE;
}
static Bool handleClipboardAnnounce(__unused ClientPtr pClient, __unused void *closure) {
// This must be done only on X server thread.
lorieHandleClipboardAnnounce();
return TRUE;
}
static Bool handleClipboardData(__unused ClientPtr pClient, void *closure) {
// This must be done only on X server thread.
lorieHandleClipboardData(closure);
return TRUE;
}
void handleLorieEvents(int fd, __unused int ready, __unused void *ignored) {
DrawablePtr screenDrawable = &pScreenPtr->GetScreenPixmap(pScreenPtr)->drawable;
ValuatorMask mask;
lorieEvent e = {0};
valuator_mask_zero(&mask);
if (ready & X_NOTIFY_ERROR) {
InputThreadUnregisterDev(fd);
close(fd);
conn_fd = -1;
lorieEnableClipboardSync(FALSE);
return;
}
again:
if (read(fd, &e, sizeof(e)) == sizeof(e)) {
switch(e.type) {
case EVENT_SCREEN_SIZE: {
lorieEvent *copy = calloc(1, sizeof(lorieEvent));
*copy = e;
QueueWorkProc(sendConfigureNotify, NULL, copy);
break;
}
case EVENT_TOUCH: {
double x = max(min((float) e.touch.x, screenDrawable->width), 0);
double y = max(min((float) e.touch.y, screenDrawable->height), 0);
DDXTouchPointInfoPtr touch = TouchFindByDDXID(lorieTouch, e.touch.id, FALSE);
// Avoid duplicating events
if (touch && touch->active) {
double oldx = 0, oldy = 0;
if (e.touch.type == XI_TouchUpdate &&
valuator_mask_fetch_double(touch->valuators, 0, &oldx) &&
valuator_mask_fetch_double(touch->valuators, 1, &oldy) &&
oldx == x && oldy == y)
break;
}
// Sometimes activity part does not send XI_TouchBegin and sends only XI_TouchUpdate.
if (e.touch.type == XI_TouchUpdate && (!touch || !touch->active))
e.touch.type = XI_TouchBegin;
if (e.touch.type == XI_TouchEnd && (!touch || !touch->active))
break;
valuator_mask_set_double(&mask, 0, x * 0xFFFF / (float) screenDrawable->width);
valuator_mask_set_double(&mask, 1, y * 0xFFFF / (float) screenDrawable->height);
QueueTouchEvents(lorieTouch, e.touch.type, e.touch.id, 0, &mask);
break;
}
case EVENT_STYLUS: {
static int buttons_prev = 0;
uint32_t released, pressed, diff;
DeviceIntPtr device = e.stylus.mouse ? lorieMouse : (e.stylus.eraser ? lorieEraser : loriePen);
if (!device) {
__android_log_print(ANDROID_LOG_DEBUG, "LorieNative", "got stylus event but device is not requested\n");
break;
}
__android_log_print(ANDROID_LOG_DEBUG, "LorieNative", "got stylus event %f %f %d %d %d %d %s\n", e.stylus.x, e.stylus.y, e.stylus.pressure, e.stylus.tilt_x, e.stylus.tilt_y, e.stylus.orientation,
device == lorieMouse ? "lorieMouse" : (device == loriePen ? "loriePen" : "lorieEraser"));
valuator_mask_set_double(&mask, 0, max(min(e.stylus.x, screenDrawable->width), 0));
valuator_mask_set_double(&mask, 1, max(min(e.stylus.y, screenDrawable->height), 0));
if (device != lorieMouse) {
valuator_mask_set_double(&mask, 2, e.stylus.pressure);
valuator_mask_set_double(&mask, 3, e.stylus.tilt_x);
valuator_mask_set_double(&mask, 4, e.stylus.tilt_y);
valuator_mask_set_double(&mask, 5, e.stylus.orientation);
}
QueuePointerEvents(device, MotionNotify, 0, POINTER_ABSOLUTE | POINTER_DESKTOP | (device == lorieMouse ? POINTER_NORAW : 0), &mask);
diff = buttons_prev ^ e.stylus.buttons;
released = diff & ~e.stylus.buttons;
pressed = diff & e.stylus.buttons;
for (int i=0; i<3; i++) {
if (released & 0x1) {
QueuePointerEvents(device, ButtonRelease, i + 1, POINTER_RELATIVE, NULL);
__android_log_print(ANDROID_LOG_DEBUG, "LorieNative", "sending %d press", i+1);
}
if (pressed & 0x1) {
QueuePointerEvents(device, ButtonPress, i + 1, POINTER_RELATIVE, NULL);
__android_log_print(ANDROID_LOG_DEBUG, "LorieNative", "sending %d release", i+1);
}
released >>= 1;
pressed >>= 1;
}
buttons_prev = e.stylus.buttons;
break;
}
case EVENT_STYLUS_ENABLE: {
lorieSetStylusEnabled(e.stylusEnable.enable);
break;
}
case EVENT_MOUSE: {
int flags;
switch(e.mouse.detail) {
case 0: // BUTTON_UNDEFINED
flags = (e.mouse.relative) ? POINTER_RELATIVE | POINTER_ACCELERATE : POINTER_ABSOLUTE | POINTER_SCREEN | POINTER_NORAW;
if (!e.mouse.relative) {
e.mouse.x = max(0, min(e.mouse.x, screenDrawable->width));
e.mouse.y = max(0, min(e.mouse.y, screenDrawable->height));
}
valuator_mask_set_double(&mask, 0, (double) e.mouse.x);
valuator_mask_set_double(&mask, 1, (double) e.mouse.y);
QueuePointerEvents(lorieMouse, MotionNotify, 0, flags, &mask);
break;
case 1: // BUTTON_LEFT
case 2: // BUTTON_MIDDLE
case 3: // BUTTON_RIGHT
QueuePointerEvents(lorieMouse, e.mouse.down ? ButtonPress : ButtonRelease, e.mouse.detail, POINTER_RELATIVE, NULL);
break;
case 4: // BUTTON_SCROLL
if (e.mouse.x) {
valuator_mask_zero(&mask);
valuator_mask_set_double(&mask, 2, (double) e.mouse.x / 120);
QueuePointerEvents(lorieMouse, MotionNotify, 0, POINTER_RELATIVE, &mask);
}
if (e.mouse.y) {
valuator_mask_zero(&mask);
valuator_mask_set_double(&mask, 3, (double) e.mouse.y / 120);
QueuePointerEvents(lorieMouse, MotionNotify, 0, POINTER_RELATIVE, &mask);
}
break;
}
break;
}
case EVENT_KEY:
QueueKeyboardEvents(lorieKeyboard, e.key.state ? KeyPress : KeyRelease, e.key.key);
break;
case EVENT_UNICODE: {
int ks = ucs2keysym((long) e.unicode.code);
__android_log_print(ANDROID_LOG_DEBUG, "LorieNative", "Trying to input keysym %d\n", ks);
lorieKeysymKeyboardEvent(ks, TRUE);
lorieKeysymKeyboardEvent(ks, FALSE);
break;
}
case EVENT_CLIPBOARD_ENABLE:
lorieEnableClipboardSync(e.clipboardEnable.enable);
break;
case EVENT_CLIPBOARD_ANNOUNCE:
QueueWorkProc(handleClipboardAnnounce, NULL, NULL);
break;
case EVENT_CLIPBOARD_SEND: {
char *data = calloc(1, e.clipboardSend.count + 1);
read(conn_fd, data, e.clipboardSend.count);
data[e.clipboardSend.count] = 0;
QueueWorkProc(handleClipboardData, NULL, data);
}
}
int n;
if (ioctl(fd, FIONREAD, &n) >= 0 && n > sizeof(e))
goto again;
}
}
void lorieSendClipboardData(const char* data) {
if (data && conn_fd != -1) {
size_t len = strlen(data);
lorieEvent e = { .clipboardSend = { .t = EVENT_CLIPBOARD_SEND, .count = len } };
write(conn_fd, &e, sizeof(e));
write(conn_fd, data, len);
}
}
void lorieRequestClipboard(void) {
if (conn_fd != -1) {
lorieEvent e = { .type = EVENT_CLIPBOARD_REQUEST };
write(conn_fd, &e, sizeof(e));
}
}
static Bool addFd(__unused ClientPtr pClient, void *closure) {
InputThreadRegisterDev((int) (int64_t) closure, handleLorieEvents, NULL);
conn_fd = (int) (int64_t) closure;
return TRUE;
}
JNIEXPORT jobject JNICALL
Java_com_termux_x11_CmdEntryPoint_getXConnection(JNIEnv *env, __unused jobject cls) {
int client[2];
jclass ParcelFileDescriptorClass = (*env)->FindClass(env, "android/os/ParcelFileDescriptor");
jmethodID adoptFd = (*env)->GetStaticMethodID(env, ParcelFileDescriptorClass, "adoptFd", "(I)Landroid/os/ParcelFileDescriptor;");
socketpair(AF_UNIX, SOCK_STREAM, 0, client);
fcntl(client[0], F_SETFL, fcntl(client[0], F_GETFL, 0) | O_NONBLOCK);
QueueWorkProc(addFd, NULL, (void*) (int64_t) client[1]);
return (*env)->CallStaticObjectMethod(env, ParcelFileDescriptorClass, adoptFd, client[0]);
}
void* logcatThread(void *arg) {
char buffer[4096];
size_t len;
while((len = read((int) (int64_t) arg, buffer, 4096)) >=0)
write(2, buffer, len);
close((int) (int64_t) arg);
return NULL;
}
JNIEXPORT jobject JNICALL
Java_com_termux_x11_CmdEntryPoint_getLogcatOutput(JNIEnv *env, __unused jobject cls) {
jclass ParcelFileDescriptorClass = (*env)->FindClass(env, "android/os/ParcelFileDescriptor");
jmethodID adoptFd = (*env)->GetStaticMethodID(env, ParcelFileDescriptorClass, "adoptFd", "(I)Landroid/os/ParcelFileDescriptor;");
const char *debug = getenv("TERMUX_X11_DEBUG");
if (debug && !strcmp(debug, "1")) {
pthread_t t;
int p[2];
pipe(p);
fchmod(p[1], 0777);
pthread_create(&t, NULL, logcatThread, (void*) (uint64_t) p[0]);
return (*env)->CallStaticObjectMethod(env, ParcelFileDescriptorClass, adoptFd, p[1]);
}
return NULL;
}
JNIEXPORT jboolean JNICALL
Java_com_termux_x11_CmdEntryPoint_connected(__unused JNIEnv *env, __unused jclass clazz) {
return conn_fd != -1;
}
static inline void checkConnection(JNIEnv* env) {
int retval, b = 0;
if (conn_fd == -1)
return;
if ((retval = recv(conn_fd, &b, 1, MSG_PEEK)) <= 0 && errno != EAGAIN) {
log(DEBUG, "recv %d %s", retval, strerror(errno));
jclass cls = (*env)->FindClass(env, "com/termux/x11/CmdEntryPoint");
jmethodID method = !cls ? NULL : (*env)->GetStaticMethodID(env, cls, "requestConnection", "()V");
if (method)
(*env)->CallStaticVoidMethod(env, cls, method);
close(conn_fd);
conn_fd = -1;
}
}
JNIEXPORT void JNICALL
Java_com_termux_x11_LorieView_connect(__unused JNIEnv* env, __unused jobject cls, jint fd) {
if (!Charset.self) {
// Init clipboard-related JNI stuff
Charset.self = FindClassOrDie(env, "java/nio/charset/Charset");
Charset.forName = FindMethodOrDie(env, Charset.self, "forName", "(Ljava/lang/String;)Ljava/nio/charset/Charset;", JNI_TRUE);
Charset.decode = FindMethodOrDie(env, Charset.self, "decode", "(Ljava/nio/ByteBuffer;)Ljava/nio/CharBuffer;", JNI_FALSE);
CharBuffer.self = FindClassOrDie(env, "java/nio/CharBuffer");
CharBuffer.toString = FindMethodOrDie(env, CharBuffer.self, "toString", "()Ljava/lang/String;", JNI_FALSE);
}
conn_fd = fd;
fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK);
checkConnection(env);
log(DEBUG, "XCB connection is successfull");
}
JNIEXPORT void JNICALL
Java_com_termux_x11_LorieView_handleXEvents(JNIEnv *env, jobject thiz) {
checkConnection(env);
if (conn_fd != -1) {
lorieEvent e = {0};
again:
if (read(conn_fd, &e, sizeof(e)) == sizeof(e)) {
switch(e.type) {
case EVENT_CLIPBOARD_SEND: {
char clipboard[e.clipboardSend.count + 1];
read(conn_fd, clipboard, sizeof(clipboard));
clipboard[e.clipboardSend.count] = 0;
log(DEBUG, "Clipboard content (%zu symbols) is %s", strlen(clipboard), clipboard);
jmethodID id = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, thiz), "setClipboardText","(Ljava/lang/String;)V");
jobject bb = (*env)->NewDirectByteBuffer(env, clipboard, strlen(clipboard));
jobject charset = (*env)->CallStaticObjectMethod(env, Charset.self, Charset.forName, (*env)->NewStringUTF(env, "UTF-8"));
jobject cb = (*env)->CallObjectMethod(env, charset, Charset.decode, bb);
(*env)->DeleteLocalRef(env, bb);
jstring str = (*env)->CallObjectMethod(env, cb, CharBuffer.toString);
(*env)->CallVoidMethod(env, thiz, id, str);
break;
}
case EVENT_CLIPBOARD_REQUEST: {
(*env)->CallVoidMethod(env, thiz, (*env)->GetMethodID(env, (*env)->GetObjectClass(env, thiz), "requestClipboard", "()V"));
break;
}
}
}
int n;
if (ioctl(conn_fd, FIONREAD, &n) >= 0 && n > sizeof(e))
goto again;
}
}
JNIEXPORT void JNICALL
Java_com_termux_x11_LorieView_startLogcat(JNIEnv *env, __unused jobject cls, jint fd) {
log(DEBUG, "Starting logcat with output to given fd");
switch(fork()) {
case -1:
log(ERROR, "fork: %s", strerror(errno));
return;
case 0:
dup2(fd, 1);
dup2(fd, 2);
prctl(PR_SET_PDEATHSIG, SIGTERM);
char buf[64] = {0};
sprintf(buf, "--pid=%d", getppid());
execl("/system/bin/logcat", "logcat", buf, NULL);
log(ERROR, "exec logcat: %s", strerror(errno));
(*env)->FatalError(env, "Exiting");
}
}
JNIEXPORT void JNICALL
Java_com_termux_x11_LorieView_setClipboardSyncEnabled(__unused JNIEnv* env, __unused jobject cls, jboolean enable, __unused jboolean ignored) {
if (conn_fd != -1) {
lorieEvent e = { .clipboardEnable = { .t = EVENT_CLIPBOARD_ENABLE, .enable = enable } };
write(conn_fd, &e, sizeof(e));
checkConnection(env);
}
}
JNIEXPORT void JNICALL
Java_com_termux_x11_LorieView_sendClipboardAnnounce(JNIEnv *env, __unused jobject thiz) {
if (conn_fd != -1) {
lorieEvent e = { .type = EVENT_CLIPBOARD_ANNOUNCE };
write(conn_fd, &e, sizeof(e));
checkConnection(env);
}
}
JNIEXPORT void JNICALL
Java_com_termux_x11_LorieView_sendClipboardEvent(JNIEnv *env, __unused jobject thiz, jbyteArray text) {
if (conn_fd != -1 && text) {
jsize length = (*env)->GetArrayLength(env, text);
jbyte* str = (*env)->GetByteArrayElements(env, text, NULL);
lorieEvent e = { .clipboardSend = { .t = EVENT_CLIPBOARD_SEND, .count = length } };
write(conn_fd, &e, sizeof(e));
write(conn_fd, str, length);
(*env)->ReleaseByteArrayElements(env, text, str, JNI_ABORT);
checkConnection(env);
}
}
JNIEXPORT void JNICALL
Java_com_termux_x11_LorieView_sendWindowChange(__unused JNIEnv* env, __unused jobject cls, jint width, jint height, jint framerate) {
if (conn_fd != -1) {
lorieEvent e = { .screenSize = { .t = EVENT_SCREEN_SIZE, .width = width, .height = height, .framerate = framerate } };
write(conn_fd, &e, sizeof(e));
checkConnection(env);
}
}
JNIEXPORT void JNICALL
Java_com_termux_x11_LorieView_sendMouseEvent(__unused JNIEnv* env, __unused jobject cls, jfloat x, jfloat y, jint which_button, jboolean button_down, jboolean relative) {
if (conn_fd != -1) {
lorieEvent e = { .mouse = { .t = EVENT_MOUSE, .x = x, .y = y, .detail = which_button, .down = button_down, .relative = relative } };
write(conn_fd, &e, sizeof(e));
checkConnection(env);
}
}
JNIEXPORT void JNICALL
Java_com_termux_x11_LorieView_sendTouchEvent(__unused JNIEnv* env, __unused jobject cls, jint action, jint id, jint x, jint y) {
if (conn_fd != -1 && action != -1) {
lorieEvent e = { .touch = { .t = EVENT_TOUCH, .type = action, .id = id, .x = x, .y = y } };
write(conn_fd, &e, sizeof(e));
checkConnection(env);
}
}
JNIEXPORT void JNICALL
Java_com_termux_x11_LorieView_sendStylusEvent(JNIEnv *env, __unused jobject thiz, jfloat x, jfloat y,
jint pressure, jint tilt_x, jint tilt_y,
jint orientation, jint buttons, jboolean eraser, jboolean mouse) {
if (conn_fd != -1) {
lorieEvent e = { .stylus = { .t = EVENT_STYLUS, .x = x, .y = y, .pressure = pressure, .tilt_x = tilt_x, .tilt_y = tilt_y, .orientation = orientation, .buttons = buttons, .eraser = eraser, .mouse = mouse } };
write(conn_fd, &e, sizeof(e));
checkConnection(env);
}
}
JNIEXPORT void JNICALL
Java_com_termux_x11_LorieView_requestStylusEnabled(JNIEnv *env, __unused jclass clazz, jboolean enabled) {
if (conn_fd != -1) {
lorieEvent e = { .stylusEnable = { .t = EVENT_STYLUS_ENABLE, .enable = enabled } };
write(conn_fd, &e, sizeof(e));
checkConnection(env);
}
}
JNIEXPORT jboolean JNICALL
Java_com_termux_x11_LorieView_sendKeyEvent(__unused JNIEnv* env, __unused jobject cls, jint scan_code, jint key_code, jboolean key_down) {
if (conn_fd != -1) {
int code = (scan_code) ?: android_to_linux_keycode[key_code];
log(DEBUG, "Sending key: %d (%d %d %d)", code + 8, scan_code, key_code, key_down);
lorieEvent e = { .key = { .t = EVENT_KEY, .key = code + 8, .state = key_down } };
write(conn_fd, &e, sizeof(e));
checkConnection(env);
}
return true;
}
JNIEXPORT void JNICALL
Java_com_termux_x11_LorieView_sendTextEvent(JNIEnv *env, __unused jobject thiz, jbyteArray text) {
if (conn_fd != -1 && text) {
jsize length = (*env)->GetArrayLength(env, text);
jbyte *str = (*env)->GetByteArrayElements(env, text, NULL);
char *p = (char*) str;
mbstate_t state = { 0 };
log(DEBUG, "Parsing text: %.*s", length, str);
while (*p) {
wchar_t wc;
size_t len = mbrtowc(&wc, p, MB_CUR_MAX, &state);
if (len == (size_t)-1 || len == (size_t)-2) {
log(ERROR, "Invalid UTF-8 sequence encountered");
break;
}
if (len == 0)
break;
log(DEBUG, "Sending unicode event: %lc (U+%X)", wc, wc);
lorieEvent e = { .unicode = { .t = EVENT_UNICODE, .code = wc } };
write(conn_fd, &e, sizeof(e));
p += len;
if (p - (char*) str >= length)
break;
usleep(30000);
}
(*env)->ReleaseByteArrayElements(env, text, str, JNI_ABORT);
checkConnection(env);
}
}
void abort(void) {
_exit(134);
}
void exit(int code) {
_exit(code);
}
#if 1
// It is needed to redirect stderr to logcat
static void* stderrToLogcatThread(__unused void* cookie) {
FILE *fp;
int p[2];
size_t len;
char *line = NULL;
pipe(p);
fp = fdopen(p[0], "r");
dup2(p[1], 2);
dup2(p[1], 1);
while ((getline(&line, &len, fp)) != -1) {
log(DEBUG, "%s%s", line, (line[len - 1] == '\n') ? "" : "\n");
}
return NULL;
}
__attribute__((constructor)) static void init(void) {
pthread_t t;
if (!strcmp("com.termux.x11", __progname))
pthread_create(&t, NULL, stderrToLogcatThread, NULL);
}
#endif

View File

@@ -0,0 +1,579 @@
/* Copyright 2016-2019 Pierre Ossman for Cendio AB
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this software; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#pragma clang diagnostic ignored "-Wunknown-pragmas"
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#include <android/log.h>
#include <X11/Xatom.h>
#include <windowstr.h>
#include <selection.h>
#include <propertyst.h>
#include <xacestr.h>
#include "lorie.h"
/* utility functions for text conversion */
static inline void lorieConvertLF(const char* src, char *dst, size_t bytes) {
size_t i = 0, j = 0;
for (; i < bytes; i++)
if (src[i] != '\r')
dst[j++] = src[i];
}
static inline void lorieLatin1ToUTF8(unsigned char* out, const unsigned char* in) {
while (*in)
if (*in < 128)
*out++ = *in++;
else
*out++ = 0xc2 + (*in > 0xbf), *out++ = (*in++ & 0x3f) + 0x80;
}
static inline int lorieCheckUTF8(const unsigned char *utf, size_t size) {
int ix;
unsigned char c;
for (ix = 0; (c = utf[ix]) && ix < size;) {
if (c & 0x80) {
if ((utf[ix + 1] & 0xc0) != 0x80)
return 0;
if ((c & 0xe0) == 0xe0) {
if ((utf[ix + 2] & 0xc0) != 0x80)
return 0;
if ((c & 0xf0) == 0xf0) {
if ((c & 0xf8) != 0xf0 || (utf[ix + 3] & 0xc0) != 0x80)
return 0;
ix += 4;
/* 4-byte code */
} else
/* 3-byte code */
ix += 3;
} else
/* 2-byte code */
ix += 2;
} else
/* 1-byte code */
ix++;
}
return 1;
}
static size_t lorieUtf8ToUCS4(const char* src, size_t max, unsigned* dst) {
size_t count, consumed;
*dst = 0xfffd;
if (max == 0)
return 0;
consumed = 1;
if ((*src & 0x80) == 0) {
*dst = *src;
count = 0;
} else if ((*src & 0xe0) == 0xc0) {
*dst = *src & 0x1f;
count = 1;
} else if ((*src & 0xf0) == 0xe0) {
*dst = *src & 0x0f;
count = 2;
} else if ((*src & 0xf8) == 0xf0) {
*dst = *src & 0x07;
count = 3;
} else {
// Invalid sequence, consume all continuation characters
src++;
max--;
while ((max-- > 0) && ((*src++ & 0xc0) == 0x80))
consumed++;
return consumed;
}
src++;
max--;
while (count--) {
consumed++;
// Invalid or truncated sequence?
if ((max == 0) || ((*src & 0xc0) != 0x80)) {
*dst = 0xfffd;
return consumed;
}
*dst <<= 6;
*dst |= *src & 0x3f;
src++;
max--;
}
// UTF-16 surrogate code point?
if ((*dst >= 0xd800) && (*dst < 0xe000))
*dst = 0xfffd;
return consumed;
}
static const char *lorieUtf8ToLatin1(const char *src) {
size_t sz;
const char* in;
size_t in_len;
// Compute output size
sz = 0;
in = src;
in_len = -1;
while ((in_len > 0) && (*in != '\0')) {
size_t len;
unsigned ucs;
len = lorieUtf8ToUCS4(in, in_len, &ucs);
in += len;
in_len -= len;
sz++;
}
// Reserve space
unsigned char out[sz + 1];
memset(out, 0, sz + 1);
size_t position = 0;
// And convert
in = src;
in_len = 4.294967295E9;
while ((in_len > 0) && (*in != '\0')) {
size_t len;
unsigned ucs;
len = lorieUtf8ToUCS4(in, in_len, &ucs);
in += len;
in_len -= len;
if (ucs > 0xff)
out[position++] = '?';
else
out[position++] = (unsigned char)ucs;
}
return strdup((const char*) out);
}
/* end utility functions */
#define log(prio, ...) __android_log_print(ANDROID_LOG_ ## prio, "LorieNative", __VA_ARGS__)
extern ScreenPtr pScreenPtr;
static int (*origProcSendEvent)(ClientPtr) = NULL;
static int (*origProcConvertSelection)(ClientPtr) = NULL;
static Atom xaTIMESTAMP = 0, xaTEXT = 0, xaCLIPBOARD = 0, xaTARGETS = 0, xaSTRING = 0, xaUTF8_STRING = 0;
static Bool clipboardEnabled = FALSE;
static const char* cachedData = NULL;
struct LorieDataTarget {
ClientPtr client;
Atom selection;
Atom target;
Atom property;
Window requestor;
CARD32 time;
struct LorieDataTarget* next;
} *lorieDataTargetHead;
void lorieEnableClipboardSync(Bool enable) {
clipboardEnabled = enable;
}
/* functions related to clipboard receiving */
static void lorieSelectionRequest(Atom selection, Atom target) {
Selection *pSel;
if (clipboardEnabled && dixLookupSelection(&pSel, selection, serverClient, DixGetAttrAccess) == Success) {
xEvent event = {0};
event.u.u.type = SelectionRequest;
event.u.selectionRequest.owner = pSel->window;
event.u.selectionRequest.time = currentTime.milliseconds;
event.u.selectionRequest.requestor = pScreenPtr->root->drawable.id;
event.u.selectionRequest.selection = selection;
event.u.selectionRequest.target = target;
event.u.selectionRequest.property = target;
WriteEventsToClient(pSel->client, 1, &event);
}
}
static Bool lorieHasAtom(Atom atom, const Atom list[], size_t size) {
for (size_t i = 0; i < size; i++)
if (list[i] == atom)
return TRUE;
return FALSE;
}
static void lorieHandleSelection(Atom target) {
PropertyPtr prop;
if (target != xaTARGETS && target != xaSTRING && target != xaUTF8_STRING)
return;
if (dixLookupProperty(&prop, pScreenPtr->root, target, serverClient, DixReadAccess) != Success)
return;
log(DEBUG, "Selection notification for CLIPBOARD (target %s, type %s)\n", NameForAtom(target), NameForAtom(prop->type));
if (target == xaTARGETS && prop->type == XA_ATOM && prop->format == 32) {
if (lorieHasAtom(xaUTF8_STRING, (const Atom*)prop->data, prop->size))
lorieSelectionRequest(xaCLIPBOARD, xaUTF8_STRING);
else if (lorieHasAtom(xaSTRING, (const Atom*)prop->data, prop->size))
lorieSelectionRequest(xaCLIPBOARD, xaSTRING);
} else if (target == xaSTRING && prop->type == xaSTRING && prop->format == 8) {
if (prop->format != 8 || prop->type != xaSTRING)
return;
char filtered[prop->size + 1], utf8[(prop->size + 1) * 2];
memset(filtered, 0, sizeof(filtered));
memset(utf8, 0, sizeof(utf8));
lorieConvertLF(prop->data, filtered, prop->size);
lorieLatin1ToUTF8((unsigned char*) utf8, (unsigned char*) filtered);
log(DEBUG, "Sending clipboard to clients (%zu bytes)\n", strlen(utf8));
lorieSendClipboardData(utf8);
} else if (target == xaUTF8_STRING && prop->type == xaUTF8_STRING && prop->format == 8) {
char filtered[prop->size + 1];
if (!lorieCheckUTF8(prop->data, prop->size)) {
dprintf(2, "Invalid UTF-8 sequence in clipboard\n");
return;
}
memset(filtered, 0, prop->size + 1);
lorieConvertLF(prop->data, filtered, prop->size);
log(DEBUG, "Sending clipboard to clients (%zu bytes)\n", strlen(filtered));
lorieSendClipboardData(filtered);
}
}
static int lorieProcSendEvent(ClientPtr client) {
REQUEST(xSendEventReq)
REQUEST_SIZE_MATCH(xSendEventReq);
__typeof__(stuff->event.u.selectionNotify)* e = &stuff->event.u.selectionNotify;
if (clipboardEnabled && e->requestor == pScreenPtr->root->drawable.id &&
stuff->event.u.u.type == SelectionNotify && e->selection == xaCLIPBOARD && e->target == e->property)
lorieHandleSelection(e->target);
return origProcSendEvent(client);
}
static void lorieSelectionCallback(__unused CallbackListPtr *callbacks, __unused void * data, void * args) {
SelectionInfoRec *info = (SelectionInfoRec *) args;
if (clipboardEnabled && info->selection->selection == xaCLIPBOARD && info->kind == SelectionSetOwner)
lorieSelectionRequest(xaCLIPBOARD, xaTARGETS);
}
/* end functions related to clipboard receiving */
/* functions related to clipboard announcing and sending */
static int lorieConvertSelection(ClientPtr client, Atom selection, Atom target, Atom property, Window requestor, CARD32 time, const char* data) {
Selection *pSel;
WindowPtr pWin;
int rc;
Atom realProperty;
xEvent event;
if (data == NULL) {
log(DEBUG, "Selection request for %s (type %s)",
NameForAtom(selection), NameForAtom(target));
} else {
log(DEBUG, "Sending data for selection request for %s (type %s)",
NameForAtom(selection), NameForAtom(target));
}
rc = dixLookupSelection(&pSel, selection, client, DixGetAttrAccess);
if (rc != Success)
return rc;
/* We do not validate the time argument because neither does
* dix/selection.c and some clients (e.g. Qt) relies on this */
rc = dixLookupWindow(&pWin, requestor, client, DixSetAttrAccess);
if (rc != Success)
return rc;
if (property != None)
realProperty = property;
else
realProperty = target;
/* FIXME: MULTIPLE target */
if (target == xaTARGETS) {
Atom targets[] = { xaTARGETS, xaTIMESTAMP,
xaSTRING, xaTEXT, xaUTF8_STRING };
rc = dixChangeWindowProperty(serverClient, pWin, realProperty,
XA_ATOM, 32, PropModeReplace,
sizeof(targets)/sizeof(targets[0]),
targets, TRUE);
if (rc != Success)
return rc;
} else if (target == xaTIMESTAMP) {
rc = dixChangeWindowProperty(serverClient, pWin, realProperty,
XA_INTEGER, 32, PropModeReplace, 1,
&pSel->lastTimeChanged.milliseconds,
TRUE);
if (rc != Success)
return rc;
} else {
if (data == NULL) {
struct LorieDataTarget* ldt;
if ((target != xaSTRING) && (target != xaTEXT) &&
(target != xaUTF8_STRING))
return BadMatch;
ldt = calloc(1, sizeof(struct LorieDataTarget));
if (ldt == NULL)
return BadAlloc;
ldt->client = client;
ldt->selection = selection;
ldt->target = target;
ldt->property = property;
ldt->requestor = requestor;
ldt->time = time;
ldt->next = lorieDataTargetHead;
lorieDataTargetHead = ldt;
log(DEBUG, "Requesting clipboard data from client");
lorieRequestClipboard();
return Success;
} else {
if ((target == xaSTRING) || (target == xaTEXT)) {
const char* latin1 = lorieUtf8ToLatin1(data);
if (latin1 == NULL)
return BadAlloc;
rc = dixChangeWindowProperty(serverClient, pWin, realProperty,
XA_STRING, 8, PropModeReplace,
strlen(latin1), latin1, TRUE);
free((void*) latin1);
if (rc != Success)
return rc;
} else if (target == xaUTF8_STRING) {
rc = dixChangeWindowProperty(serverClient, pWin, realProperty,
xaUTF8_STRING, 8, PropModeReplace,
strlen(data), data, TRUE);
if (rc != Success)
return rc;
} else {
return BadMatch;
}
}
}
event.u.u.type = SelectionNotify;
event.u.selectionNotify.time = time;
event.u.selectionNotify.requestor = requestor;
event.u.selectionNotify.selection = selection;
event.u.selectionNotify.target = target;
event.u.selectionNotify.property = property;
WriteEventsToClient(client, 1, &event);
return Success;
}
static int lorieProcConvertSelection(ClientPtr client) {
Bool paramsOkay;
WindowPtr pWin;
Selection *pSel;
int rc;
REQUEST(xConvertSelectionReq)
REQUEST_SIZE_MATCH(xConvertSelectionReq);
rc = dixLookupWindow(&pWin, stuff->requestor, client, DixSetAttrAccess);
if (rc != Success)
return rc;
paramsOkay = ValidAtom(stuff->selection) && ValidAtom(stuff->target);
paramsOkay &= (stuff->property == None) || ValidAtom(stuff->property);
if (!paramsOkay) {
client->errorValue = stuff->property;
return BadAtom;
}
/* Do we own this selection? */
rc = dixLookupSelection(&pSel, stuff->selection, client, DixReadAccess);
if (rc == Success && pSel->client == serverClient && pSel->window == pScreenPtr->root->drawable.id) {
/* cachedData will be NULL for the first request, but can then be
* reused once we've gotten the data once from the client */
rc = lorieConvertSelection(client, stuff->selection,
stuff->target, stuff->property,
stuff->requestor, stuff->time,
cachedData);
if (rc != Success) {
xEvent event;
memset(&event, 0, sizeof(xEvent));
event.u.u.type = SelectionNotify;
event.u.selectionNotify.time = stuff->time;
event.u.selectionNotify.requestor = stuff->requestor;
event.u.selectionNotify.selection = stuff->selection;
event.u.selectionNotify.target = stuff->target;
event.u.selectionNotify.property = None;
WriteEventsToClient(client, 1, &event);
}
return Success;
}
return origProcConvertSelection(client);
}
static int lorieOwnSelection(Atom selection) {
Selection *pSel;
int rc;
SelectionInfoRec info;
rc = dixLookupSelection(&pSel, selection, serverClient, DixSetAttrAccess);
if (rc == Success) {
if (pSel->client && (pSel->client != serverClient)) {
xEvent event = {
.u.selectionClear.time = currentTime.milliseconds,
.u.selectionClear.window = pSel->window,
.u.selectionClear.atom = pSel->selection
};
event.u.u.type = SelectionClear;
WriteEventsToClient(pSel->client, 1, &event);
}
} else if (rc == BadMatch) {
pSel = dixAllocateObjectWithPrivates(Selection, PRIVATE_SELECTION);
if (!pSel)
return BadAlloc;
pSel->selection = selection;
rc = XaceHookSelectionAccess(serverClient, &pSel, DixCreateAccess | DixSetAttrAccess);
if (rc != Success) {
free(pSel);
return rc;
}
pSel->next = CurrentSelections;
CurrentSelections = pSel;
}
else
return rc;
pSel->lastTimeChanged = currentTime;
pSel->window = pScreenPtr->root->drawable.id;
pSel->pWin = pScreenPtr->root;
pSel->client = serverClient;
log(DEBUG, "Grabbed %s selection", NameForAtom(selection));
info.selection = pSel;
info.client = serverClient;
info.kind = SelectionSetOwner;
CallCallbacks(&SelectionCallback, &info);
return Success;
}
void lorieHandleClipboardAnnounce(void) {
// The data has changed in some way, so whatever is in our cache is now stale
free((void*) cachedData);
cachedData = NULL;
int rc;
log(DEBUG, "Remote clipboard announced, grabbing local ownership");
rc = lorieOwnSelection(xaCLIPBOARD);
if (rc != Success)
log(ERROR, "Could not set CLIPBOARD selection");
}
void lorieHandleClipboardData(const char* data) {
struct LorieDataTarget* next;
log(DEBUG, "Got remote clipboard data, sending to X11 clients");
free((void*) cachedData);
cachedData = data;
while (lorieDataTargetHead != NULL) {
int rc;
xEvent event;
rc = lorieConvertSelection(lorieDataTargetHead->client,
lorieDataTargetHead->selection,
lorieDataTargetHead->target,
lorieDataTargetHead->property,
lorieDataTargetHead->requestor,
lorieDataTargetHead->time,
cachedData);
if (rc != Success) {
event.u.u.type = SelectionNotify;
event.u.selectionNotify.time = lorieDataTargetHead->time;
event.u.selectionNotify.requestor = lorieDataTargetHead->requestor;
event.u.selectionNotify.selection = lorieDataTargetHead->selection;
event.u.selectionNotify.target = lorieDataTargetHead->target;
event.u.selectionNotify.property = None;
WriteEventsToClient(lorieDataTargetHead->client, 1, &event);
}
next = lorieDataTargetHead->next;
free(lorieDataTargetHead);
lorieDataTargetHead = next;
}
}
/* end functions related to clipboard announcing and sending */
void lorieInitClipboard(void) {
#define ATOM(name) xa##name = MakeAtom(#name, strlen(#name), TRUE)
ATOM(TIMESTAMP); ATOM(TEXT); ATOM(CLIPBOARD); ATOM(TARGETS); ATOM(STRING); ATOM(UTF8_STRING);
if (!origProcConvertSelection) {
origProcConvertSelection = ProcVector[X_ConvertSelection];
ProcVector[X_ConvertSelection] = lorieProcConvertSelection;
}
if (!origProcSendEvent) {
origProcSendEvent = ProcVector[X_SendEvent];
ProcVector[X_SendEvent] = lorieProcSendEvent;
}
if (!AddCallback(&SelectionCallback, lorieSelectionCallback, NULL))
FatalError("Adding SelectionCallback failed\n");
}

View File

@@ -0,0 +1,583 @@
#pragma clang diagnostic ignored "-Wstrict-prototypes"
#include <android/log.h>
#include <gcstruct.h>
#include <privates.h>
#include <scrnintstr.h>
#include <dri3.h>
#include <sys/mman.h>
#include <fb.h>
#include <android/hardware_buffer.h>
#include <sys/stat.h>
#include <errno.h>
#include "screenint.h"
#include "lorie.h"
#include "renderer.h"
#define log(prio, ...) __android_log_print(ANDROID_LOG_ ## prio, "LorieNative", __VA_ARGS__)
/*
* Design is pretty simple.
* We need somehow attach Android's HardwareBuffers and turnip's textures to X11 pixmaps.
*
* About turnip.
* We can not simply import Mesa's texture since we do not use Mesa in project
* and even in the case it we ever use it we can not mix mesa with Android's libEGL.
* Xext's shm allows us to attach dmabuf fd with given width, height and offset,
* but does not let us specify stride of buffer.
* For this case we use DRI3's pixmap_from_fds request since it allows us specify
* width, height, stride and even import fd from client.
*
* About Android Hardware Buffers.
* NDK API does not let us simply flatten GraphicBuffer like it is done in regular AOSP code
* or even simply extract native handle which contains data and file descriptors
* needed to recreate GraphicBuffer in different process.
* But we have AHardwareBuffer_sendHandleToUnixSocket and AHardwareBuffer_recvHandleFromUnixSocket
* which let us send and receive AHardwareBuffer (aka GraphicBuffer) through Unix socket.
* So X11 client can simply open socketpair, wait for a while until server sends one byte
* and respond with AhardwareBuffer using AHardwareBuffer_sendHandleToUnixSocket.
* About attaching AHardwareBuffer to X11 pixmap:
* We can not simply do AHardwareBuffer_lock after creating pixmap and expect it to work.
* Some platforms (especially platforms with separate GPU memory which can not be accessed with CPU)
* explicitly copy contents of video memory to CPU memory on AHardwareBuffer_lock and content of buffer
* copied this way is not affected by any actions in X11 client process.
* So we must explicitly call AHardwareBuffer_lock when GC needs to access pixmap
* and call AHardwareBuffer_unlock when it finishes its work.
* Also we consider AHardwareBuffer we have to be read-only, write allowed only for X11 client.
* So all functions except CopyArea applied to pixmap with attached AHardwareBuffer should be no-ops.
*/
static DevPrivateKeyRec lorieGCPrivateKey;
static DevPrivateKeyRec lorieScrPrivateKey;
static DevPrivateKeyRec lorieAHBPixPrivateKey;
static DevPrivateKeyRec lorieMmappedPixPrivateKey;
typedef struct {
const GCOps *ops;
const GCFuncs *funcs;
} LorieGCPrivRec, *LorieGCPrivPtr;
typedef struct {
CreateGCProcPtr CreateGC;
DestroyPixmapProcPtr DestroyPixmap;
} LorieScrPrivRec, *LorieScrPrivPtr;
typedef struct {
AHardwareBuffer* buffer;
} LorieAHBPixPrivRec, *LorieAHBPixPrivPtr;
static Bool FalseNoop() { return FALSE; }
#define lorieGCPriv(pGC) LorieGCPrivPtr pGCPriv = dixLookupPrivate(&(pGC)->devPrivates, &lorieGCPrivateKey)
#define lorieScrPriv(pScr) LorieScrPrivPtr pScrPriv = ((LorieScrPrivPtr) dixLookupPrivate(&(pScr)->devPrivates, &lorieScrPrivateKey))
#define loriePixFromDrawable(pDrawable, suffix) \
PixmapPtr pDrawable ## Pix ## suffix = (pDrawable->type == DRAWABLE_PIXMAP) ? \
(PixmapPtr) (((char*) pDrawable) - offsetof(PixmapRec, drawable)) : 0
#define loriePixPriv(pDrawable, suffix) \
LorieAHBPixPrivPtr pPixPriv ## suffix = (pDrawable ## Pix ## suffix) ? ((LorieAHBPixPrivPtr) \
dixLookupPrivate(&(pDrawable ## Pix ## suffix)->devPrivates, &lorieAHBPixPrivateKey)) : 0
#define wrap(priv, real, mem, func) {\
priv->mem = real->mem; \
real->mem = func; \
}
#define LORIE_GC_OP_PROLOGUE(pGC) \
lorieGCPriv(pGC); \
const GCFuncs *oldFuncs = pGC->funcs; \
const GCOps *oldOps = pGC->ops; \
unwrap(pGCPriv, pGC, funcs); \
unwrap(pGCPriv, pGC, ops); \
#define LORIE_GC_OP_EPILOGUE(pGC) \
wrap(pGCPriv, pGC, funcs, oldFuncs); \
wrap(pGCPriv, pGC, ops, oldOps)
#define LORIE_GC_FUNC_PROLOGUE(pGC) \
lorieGCPriv(pGC); \
unwrap(pGCPriv, pGC, funcs); \
if (pGCPriv->ops) unwrap(pGCPriv, pGC, ops)
#define LORIE_GC_FUNC_EPILOGUE(pGC) \
wrap(pGCPriv, pGC, funcs, &lorieGCFuncs); \
if (pGCPriv->ops) wrap(pGCPriv, pGC, ops, &lorieGCOps)
#define unwrap(priv, real, mem) {\
real->mem = priv->mem; \
}
static const GCOps lorieGCOps;
static const GCFuncs lorieGCFuncs;
static void lorieValidateGC(GCPtr pGC, unsigned long stateChanges, DrawablePtr pDrawable) {
LORIE_GC_FUNC_PROLOGUE(pGC)
(*pGC->funcs->ValidateGC) (pGC, stateChanges, pDrawable);
LORIE_GC_FUNC_EPILOGUE(pGC)
}
static void lorieChangeGC(GCPtr pGC, unsigned long mask) {
LORIE_GC_FUNC_PROLOGUE(pGC)
(*pGC->funcs->ChangeGC) (pGC, mask);
LORIE_GC_FUNC_EPILOGUE(pGC)
}
static void lorieCopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst) {
LORIE_GC_FUNC_PROLOGUE(pGCSrc)
(*pGCSrc->funcs->CopyGC) (pGCSrc, mask, pGCDst);
LORIE_GC_FUNC_EPILOGUE(pGCSrc)
}
static void lorieDestroyGC(GCPtr pGC) {
LORIE_GC_FUNC_PROLOGUE(pGC)
(*pGC->funcs->DestroyGC) (pGC);
LORIE_GC_FUNC_EPILOGUE(pGC)
}
static void lorieChangeClip(GCPtr pGC, int type, void *pvalue, int nrects) {
LORIE_GC_FUNC_PROLOGUE(pGC)
(*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects);
LORIE_GC_FUNC_EPILOGUE(pGC)
}
static void lorieDestroyClip(GCPtr pGC) {
LORIE_GC_FUNC_PROLOGUE(pGC)
(*pGC->funcs->DestroyClip) (pGC);
LORIE_GC_FUNC_EPILOGUE(pGC)
}
static void lorieCopyClip(GCPtr pgcDst, GCPtr pgcSrc) {
LORIE_GC_FUNC_PROLOGUE(pgcDst)
(*pgcDst->funcs->CopyClip) (pgcDst, pgcSrc);
LORIE_GC_FUNC_EPILOGUE(pgcDst)
}
static const GCFuncs lorieGCFuncs = {
lorieValidateGC, lorieChangeGC, lorieCopyGC, lorieDestroyGC,
lorieChangeClip, lorieDestroyClip, lorieCopyClip
};
static void lorieFillSpans(DrawablePtr pDrawable, GCPtr pGC, int nInit, DDXPointPtr pptInit, int * pwidthInit, int fSorted) {
LORIE_GC_OP_PROLOGUE(pGC)
loriePixFromDrawable(pDrawable, 0);
loriePixPriv(pDrawable, 0);
if (!pPixPriv0)
(*pGC->ops->FillSpans) (pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted);
LORIE_GC_OP_EPILOGUE(pGC)
}
static void lorieSetSpans(DrawablePtr pDrawable, GCPtr pGC, char * psrc, DDXPointPtr ppt, int * pwidth, int nspans, int fSorted) {
LORIE_GC_OP_PROLOGUE(pGC)
loriePixFromDrawable(pDrawable, 0);
loriePixPriv(pDrawable, 0);
if (!pPixPriv0)
(*pGC->ops->SetSpans) (pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted);
LORIE_GC_OP_EPILOGUE(pGC)
}
static void loriePutImage(DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y, int w, int h, int leftPad, int format, char * pBits) {
LORIE_GC_OP_PROLOGUE(pGC)
loriePixFromDrawable(pDrawable, 0);
loriePixPriv(pDrawable, 0);
if (!pPixPriv0)
(*pGC->ops->PutImage) (pDrawable, pGC, depth, x, y, w, h, leftPad, format, pBits);
LORIE_GC_OP_EPILOGUE(pGC)
}
static RegionPtr lorieCopyArea(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, int srcx, int srcy, int w, int h, int dstx, int dsty) {
LORIE_GC_OP_PROLOGUE(pGC)
loriePixFromDrawable(pSrc, 0);
loriePixPriv(pSrc, 0);
loriePixFromDrawable(pDst, 1);
loriePixPriv(pDst, 1);
RegionPtr r = NULL;
Bool wasLocked = TRUE;
if (pPixPriv0 && !pPixPriv1) {
wasLocked = pSrcPix0->devPrivate.ptr != NULL;
if (!wasLocked) {
void *addr = NULL;
int error;
if ((error = AHardwareBuffer_lock(pPixPriv0->buffer, AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN, -1, NULL, &addr)) != 0)
log(ERROR, "DRI3: AHardwareBuffer_lock failed: %d", error);
if (addr)
pSrc->pScreen->ModifyPixmapHeader(pSrcPix0, 0, 0, 0, 0, 0, addr);
}
}
if (!pPixPriv1)
r = (*pGC->ops->CopyArea) (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty);
if (!wasLocked) {
AHardwareBuffer_unlock(pPixPriv0->buffer, NULL);
pSrcPix0->devPrivate.ptr = NULL;
}
LORIE_GC_OP_EPILOGUE(pGC)
return r;
}
static RegionPtr lorieCopyPlane(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC, int srcx, int srcy, int width, int height, int dstx, int dsty, unsigned long bitPlane) {
LORIE_GC_OP_PROLOGUE(pGC)
loriePixFromDrawable(pSrcDrawable, 0);
loriePixFromDrawable(pDstDrawable, 1);
loriePixPriv(pSrcDrawable, 0);
loriePixPriv(pDstDrawable, 1);
RegionPtr r = NULL;
if (!pPixPriv0 && !pPixPriv1)
r = (*pGC->ops->CopyPlane) (pSrcDrawable, pDstDrawable, pGC, srcx, srcy, width, height, dstx, dsty, bitPlane);
LORIE_GC_OP_EPILOGUE(pGC)
return r;
}
static void loriePolyPoint(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, DDXPointPtr pptInit) {
LORIE_GC_OP_PROLOGUE(pGC)
loriePixFromDrawable(pDrawable, 0);
loriePixPriv(pDrawable, 0);
if (!pPixPriv0)
(*pGC->ops->PolyPoint) (pDrawable, pGC, mode, npt, pptInit);
LORIE_GC_OP_EPILOGUE(pGC)
}
static void loriePolylines(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, DDXPointPtr pptInit) {
LORIE_GC_OP_PROLOGUE(pGC)
loriePixFromDrawable(pDrawable, 0);
loriePixPriv(pDrawable, 0);
if (!pPixPriv0)
(*pGC->ops->Polylines) (pDrawable, pGC, mode, npt, pptInit);
LORIE_GC_OP_EPILOGUE(pGC)
}
static void loriePolySegment(DrawablePtr pDrawable, GCPtr pGC, int nseg, xSegment * pSegs) {
LORIE_GC_OP_PROLOGUE(pGC)
loriePixFromDrawable(pDrawable, 0);
loriePixPriv(pDrawable, 0);
if (!pPixPriv0)
(*pGC->ops->PolySegment) (pDrawable, pGC, nseg, pSegs);
LORIE_GC_OP_EPILOGUE(pGC)
}
static void loriePolyRectangle(DrawablePtr pDrawable, GCPtr pGC, int nrects, xRectangle * pRects) {
LORIE_GC_OP_PROLOGUE(pGC)
loriePixFromDrawable(pDrawable, 0);
loriePixPriv(pDrawable, 0);
if (!pPixPriv0)
(*pGC->ops->PolyRectangle) (pDrawable, pGC, nrects, pRects);
LORIE_GC_OP_EPILOGUE(pGC)
}
static void loriePolyArc(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc * parcs) {
LORIE_GC_OP_PROLOGUE(pGC)
loriePixFromDrawable(pDrawable, 0);
loriePixPriv(pDrawable, 0);
if (!pPixPriv0)
(*pGC->ops->PolyArc) (pDrawable, pGC, narcs, parcs);
LORIE_GC_OP_EPILOGUE(pGC)
}
static void lorieFillPolygon(DrawablePtr pDrawable, GCPtr pGC, int shape, int mode, int count, DDXPointPtr pPts) {
LORIE_GC_OP_PROLOGUE(pGC)
loriePixFromDrawable(pDrawable, 0);
loriePixPriv(pDrawable, 0);
if (!pPixPriv0)
(*pGC->ops->FillPolygon) (pDrawable, pGC, shape, mode, count, pPts);
LORIE_GC_OP_EPILOGUE(pGC)
}
static void loriePolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrectFill, xRectangle * prectInit) {
LORIE_GC_OP_PROLOGUE(pGC)
loriePixFromDrawable(pDrawable, 0);
loriePixPriv(pDrawable, 0);
if (!pPixPriv0)
(*pGC->ops->PolyFillRect) (pDrawable, pGC, nrectFill, prectInit);
LORIE_GC_OP_EPILOGUE(pGC)
}
static void loriePolyFillArc(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc * parcs) {
LORIE_GC_OP_PROLOGUE(pGC)
loriePixFromDrawable(pDrawable, 0);
loriePixPriv(pDrawable, 0);
if (!pPixPriv0)
(*pGC->ops->PolyFillArc) (pDrawable, pGC, narcs, parcs);
LORIE_GC_OP_EPILOGUE(pGC)
}
static int loriePolyText8(DrawablePtr pDrawable, GCPtr pGC, int x, int y, int count, char * chars) {
LORIE_GC_OP_PROLOGUE(pGC)
int r = x;
loriePixFromDrawable(pDrawable, 0);
loriePixPriv(pDrawable, 0);
if (!pPixPriv0)
r = (*pGC->ops->PolyText8) (pDrawable, pGC, x, y, count, chars);
LORIE_GC_OP_EPILOGUE(pGC)
return r;
}
static int loriePolyText16(DrawablePtr pDrawable, GCPtr pGC, int x, int y, int count, unsigned short * chars) {
LORIE_GC_OP_PROLOGUE(pGC)
int r = x;
loriePixFromDrawable(pDrawable, 0);
loriePixPriv(pDrawable, 0);
if (!pPixPriv0)
r = (*pGC->ops->PolyText16) (pDrawable, pGC, x, y, count, chars);
LORIE_GC_OP_EPILOGUE(pGC)
return r;
}
static void lorieImageText8(DrawablePtr pDrawable, GCPtr pGC, int x, int y, int count, char * chars) {
LORIE_GC_OP_PROLOGUE(pGC)
loriePixFromDrawable(pDrawable, 0);
loriePixPriv(pDrawable, 0);
if (!pPixPriv0)
(*pGC->ops->ImageText8) (pDrawable, pGC, x, y, count, chars);
LORIE_GC_OP_EPILOGUE(pGC)
}
static void lorieImageText16(DrawablePtr pDrawable, GCPtr pGC, int x, int y, int count, unsigned short * chars) {
LORIE_GC_OP_PROLOGUE(pGC)
loriePixFromDrawable(pDrawable, 0);
loriePixPriv(pDrawable, 0);
if (!pPixPriv0)
(*pGC->ops->ImageText16) (pDrawable, pGC, x, y, count, chars);
LORIE_GC_OP_EPILOGUE(pGC)
}
static void lorieImageGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, int x, int y, unsigned int nglyph, CharInfoPtr *ppci, void *pglyphBase) {
LORIE_GC_OP_PROLOGUE(pGC)
loriePixFromDrawable(pDrawable, 0);
loriePixPriv(pDrawable, 0);
if (!pPixPriv0)
(*pGC->ops->ImageGlyphBlt) (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
LORIE_GC_OP_EPILOGUE(pGC)
}
static void loriePolyGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, int x, int y, unsigned int nglyph, CharInfoPtr *ppci, void *pglyphBase) {
LORIE_GC_OP_PROLOGUE(pGC)
loriePixFromDrawable(pDrawable, 0);
loriePixPriv(pDrawable, 0);
if (!pPixPriv0)
(*pGC->ops->PolyGlyphBlt) (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
LORIE_GC_OP_EPILOGUE(pGC)
}
static void loriePushPixels(GCPtr pGC, PixmapPtr pBitMapPix0, DrawablePtr pDst, int w, int h, int x, int y) {
LORIE_GC_OP_PROLOGUE(pGC)
loriePixFromDrawable(pDst, 1);
loriePixPriv(pBitMap, 0);
loriePixPriv(pDst, 1);
if (!pPixPriv0 && !pPixPriv1)
(*pGC->ops->PushPixels) (pGC, pBitMapPix0, pDst, w, h, x, y);
LORIE_GC_OP_EPILOGUE(pGC)
}
static const GCOps lorieGCOps = {
lorieFillSpans, lorieSetSpans,
loriePutImage, lorieCopyArea,
lorieCopyPlane, loriePolyPoint,
loriePolylines, loriePolySegment,
loriePolyRectangle, loriePolyArc,
lorieFillPolygon, loriePolyFillRect,
loriePolyFillArc, loriePolyText8,
loriePolyText16, lorieImageText8,
lorieImageText16, lorieImageGlyphBlt,
loriePolyGlyphBlt, loriePushPixels,
};
static Bool
lorieCreateGC(GCPtr pGC) {
ScreenPtr pScreen = pGC->pScreen;
lorieScrPriv(pScreen);
lorieGCPriv(pGC);
Bool ret;
unwrap(pScrPriv, pScreen, CreateGC)
if ((ret = (*pScreen->CreateGC) (pGC))) {
pGCPriv->ops = pGC->ops;
pGCPriv->funcs = pGC->funcs;
pGC->funcs = &lorieGCFuncs;
pGC->ops = &lorieGCOps;
}
wrap(pScrPriv, pScreen, CreateGC, lorieCreateGC)
return ret;
}
static Bool
lorieDestroyPixmap(PixmapPtr pPixmap) {
Bool ret;
void *ptr = NULL;
LorieAHBPixPrivPtr pPixPriv = NULL;
size_t size = 0;
ScreenPtr pScreen = pPixmap->drawable.pScreen;
lorieScrPriv(pScreen);
if (pPixmap->refcnt == 1 && pPixmap->drawable.width && pPixmap->drawable.height) {
ptr = dixLookupPrivate(&pPixmap->devPrivates, &lorieMmappedPixPrivateKey);
pPixPriv = dixLookupPrivate(&pPixmap->devPrivates, &lorieAHBPixPrivateKey);
size = pPixmap->devKind * pPixmap->drawable.height;
}
unwrap(pScrPriv, pScreen, DestroyPixmap)
ret = (*pScreen->DestroyPixmap) (pPixmap);
wrap(pScrPriv, pScreen, DestroyPixmap, lorieDestroyPixmap)
if (ptr)
munmap(ptr, size);
if (pPixPriv) {
if (pPixPriv->buffer)
AHardwareBuffer_release(pPixPriv->buffer);
free(pPixPriv);
}
return ret;
}
static PixmapPtr loriePixmapFromFds(ScreenPtr screen, CARD8 num_fds, const int *fds, CARD16 width, CARD16 height,
const CARD32 *strides, const CARD32 *offsets, CARD8 depth, __unused CARD8 bpp, CARD64 modifier) {
const CARD64 AHARDWAREBUFFER_SOCKET_FD = 1255;
const CARD64 RAW_MMAPPABLE_FD = 1274;
PixmapPtr pixmap = NullPixmap;
LorieAHBPixPrivPtr pPixPriv = NULL;
if (num_fds > 1) {
log(ERROR, "DRI3: More than 1 fd");
return NULL;
}
if (modifier != RAW_MMAPPABLE_FD && modifier != AHARDWAREBUFFER_SOCKET_FD) {
log(ERROR, "DRI3: Modifier is not RAW_MMAPPABLE_FD or AHARDWAREBUFFER_SOCKET_FD");
return NULL;
}
if (modifier == RAW_MMAPPABLE_FD) {
void *addr = mmap(NULL, strides[0] * height, PROT_READ, MAP_SHARED, fds[0], offsets[0]);
if (!addr || addr == MAP_FAILED) {
log(ERROR, "DRI3: RAW_MMAPPABLE_FD: mmap failed");
return NULL;
}
pixmap = fbCreatePixmap(screen, 0, 0, depth, 0);
if (!pixmap) {
log(ERROR, "DRI3: RAW_MMAPPABLE_FD: failed to create pixmap");
munmap(addr, strides[0] * height);
return NULL;
}
dixSetPrivate(&pixmap->devPrivates, &lorieMmappedPixPrivateKey, addr);
screen->ModifyPixmapHeader(pixmap, width, height, 0, 0, strides[0], addr);
return pixmap;
} else if (modifier == AHARDWAREBUFFER_SOCKET_FD) {
AHardwareBuffer_Desc desc;
struct stat info;
int r;
if (fstat(fds[0], &info) != 0) {
log(ERROR, "DRI3: fstat failed: %s", strerror(errno));
return NULL;
}
if (!S_ISSOCK(info.st_mode)) {
log(ERROR, "DRI3: modifier is AHARDWAREBUFFER_SOCKET_FD but fd is not a socket");
return NULL;
}
pPixPriv = calloc(1, sizeof(LorieAHBPixPrivRec));
if (!pPixPriv) {
log(ERROR, "DRI3: AHARDWAREBUFFER_SOCKET_FD: failed to allocate LorieAHBPixPrivRec");
return NULL;
}
pixmap = fbCreatePixmap(screen, 0, 0, depth, 0);
if (!pixmap) {
log(ERROR, "DRI3: failed to create pixmap");
goto fail;
}
dixSetPrivate(&pixmap->devPrivates, &lorieAHBPixPrivateKey, pPixPriv);
// Sending signal to other end of socket to send buffer.
uint8_t buf = 1;
if (write(fds[0], &buf, 1) != 1) {
log(ERROR, "DRI3: AHARDWAREBUFFER_SOCKET_FD: failed to write to socket: %s", strerror(errno));
goto fail;
}
if ((r = AHardwareBuffer_recvHandleFromUnixSocket(fds[0], &pPixPriv->buffer)) != 0) {
log(ERROR, "DRI3: AHARDWAREBUFFER_SOCKET_FD: failed to obtain AHardwareBuffer from socket: %d", r);
goto fail;
}
if (!pPixPriv->buffer) {
log(ERROR, "DRI3: AHARDWAREBUFFER_SOCKET_FD: did not receive AHardwareSocket from buffer");
goto fail;
}
AHardwareBuffer_describe(pPixPriv->buffer, &desc);
if (desc.format != AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM
&& desc.format != AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM
&& desc.format != AHARDWAREBUFFER_FORMAT_B8G8R8A8_UNORM) {
log(ERROR, "DRI3: AHARDWAREBUFFER_SOCKET_FD: wrong format of AHardwareBuffer. Must be one of: AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM, AHARDWAREBUFFER_FORMAT_B8G8R8A8_UNORM (stands for 5).");
goto fail;
}
pixmap->devPrivate.ptr = NULL;
screen->ModifyPixmapHeader(pixmap, desc.width, desc.height, 0, 0, desc.stride * 4, NULL);
return pixmap;
}
fail:
if (pPixPriv) {
if (pPixPriv->buffer)
AHardwareBuffer_release(pPixPriv->buffer);
free(pPixPriv);
}
if (pixmap)
fbDestroyPixmap(pixmap);
return NULL;
}
static int lorieGetFormats(__unused ScreenPtr screen, CARD32 *num_formats, CARD32 **formats) {
*num_formats = 0;
*formats = NULL;
return TRUE;
}
static int lorieGetModifiers(__unused ScreenPtr screen, __unused uint32_t format, uint32_t *num_modifiers, uint64_t **modifiers) {
*num_modifiers = 0;
*modifiers = NULL;
return TRUE;
}
static dri3_screen_info_rec dri3Info = {
.version = 2,
.fds_from_pixmap = FalseNoop,
.pixmap_from_fds = loriePixmapFromFds,
.get_formats = lorieGetFormats,
.get_modifiers = lorieGetModifiers,
.get_drawable_modifiers = FalseNoop
};
Bool lorieInitDri3(ScreenPtr pScreen) {
LorieScrPrivPtr pScrPriv;
if (!dixRegisterPrivateKey(&lorieScrPrivateKey, PRIVATE_SCREEN, 0))
return FALSE;
if (dixLookupPrivate(&pScreen->devPrivates, &lorieScrPrivateKey))
return TRUE;
if (!dixRegisterPrivateKey(&lorieGCPrivateKey, PRIVATE_GC, sizeof(LorieGCPrivRec))
|| !dixRegisterPrivateKey(&lorieAHBPixPrivateKey, PRIVATE_PIXMAP, 0)
|| !dixRegisterPrivateKey(&lorieMmappedPixPrivateKey, PRIVATE_PIXMAP, 0)
|| !dri3_screen_init(pScreen, &dri3Info))
return FALSE;
pScrPriv = malloc(sizeof(LorieScrPrivRec));
if (!pScrPriv)
return FALSE;
wrap(pScrPriv, pScreen, CreateGC, lorieCreateGC)
wrap(pScrPriv, pScreen, DestroyPixmap, lorieDestroyPixmap)
dixSetPrivate(&pScreen->devPrivates, &lorieScrPrivateKey, pScrPriv);
return TRUE;
}

View File

@@ -0,0 +1,871 @@
/*
* For some reasong configs generated on top of parameters
* extracted from GL configs do not work for glxgears and glmark
*/
/*
* dprintf(2, "static __GLXconfig configs[] = {\n");
* int index = 0;
* for (__GLXconfig *m = screen->base.fbconfigs; m != NULL; m = m->next) {
* dprintf(2, " (__GLXconfig) { NULL, %s, 0x%X, 0x%X, 0x%X, 0x%X, 0x%X, 0x%X, 0x%X, 0x%X, 0x%X, 0x%X, 0x%X, 0x%X, 0x%X, 0x%X, 0x%X, 0x%X, 0x%X, 0x%X, 0x%X, 0x%X, 0x%X, 0x%X, 0x%X, 0x%X, 0x%X, 0x%X, 0x%X, 0x%X, 0x%X, 0x%X, 0x%X, 0x%X, 0x%X, 0x%X, 0x%X, 0x%X, 0x%X, 0x%X, 0x%X, 0x%X, 0x%X, 0x%X, 0x%X, 0x%X, 0x%X, 0x%X, 0x%X },\n",
* m->duplicatedForComp ? "TRUE" : "FALSE",
* m->doubleBufferMode, m->stereoMode,
* m->redBits, m->greenBits, m->blueBits, m->alphaBits,
* m->redMask, m->greenMask, m->blueMask, m->alphaMask,
* m->rgbBits, m->indexBits,
* m->accumRedBits, m->accumGreenBits, m->accumBlueBits, m->accumAlphaBits,
* m->depthBits, m->stencilBits, m->numAuxBuffers, m->level,
* m->visualID, m->visualType, m->visualRating,
* m->transparentPixel, m->transparentRed, m->transparentGreen, m->transparentBlue, m->transparentAlpha,
* m->transparentIndex,
* m->sampleBuffers, m->samples, m->drawableType, m->renderType, m->fbconfigID,
* m->maxPbufferWidth, m->maxPbufferHeight, m->maxPbufferPixels, m->optimalPbufferWidth, m->optimalPbufferHeight,
* m->visualSelectGroup, m->swapMethod,
* m->bindToTextureRgb, m->bindToTextureRgba, m->bindToMipmapTexture, m->bindToTextureTargets,
* m->yInverted, m->sRGBCapable);
* }
* dprintf(2, "};\n");
*/
static __GLXconfig configs[] = {
(__GLXconfig) { &configs[1], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[2], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[3], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[4], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[5], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[6], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[7], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[8], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[9], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[10], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[11], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[12], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[13], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[14], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[15], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[16], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[17], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[18], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[19], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[20], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[21], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[22], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[23], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[24], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[25], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[26], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[27], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[28], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[29], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[30], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[31], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[32], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[33], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[34], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[35], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[36], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[37], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[38], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[39], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[40], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[41], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[42], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[43], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[44], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[45], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[46], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[47], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[48], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[49], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[50], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[51], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[52], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[53], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[54], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[55], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[56], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[57], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[58], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[59], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[60], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[61], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[62], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[63], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[64], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[65], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[66], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[67], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[68], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[69], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[70], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[71], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x10, 0x10, 0x10, 0x10, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[72], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[73], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x10, 0x10, 0x10, 0x10, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[74], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[75], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x10, 0x10, 0x10, 0x10, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[76], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[77], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[78], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[79], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[80], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[81], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[82], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[83], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[84], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[85], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[86], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[87], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[88], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[89], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[90], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[91], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[92], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[93], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[94], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[95], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[96], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[97], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[98], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[99], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[100], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[101], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[102], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[103], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[104], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[105], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[106], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[107], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[108], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[109], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[110], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[111], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[112], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[113], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[114], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[115], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[116], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[117], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[118], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[119], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[120], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[121], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[122], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[123], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[124], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[125], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[126], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[127], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[128], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[129], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[130], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[131], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[132], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[133], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[134], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[135], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[136], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[137], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[138], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[139], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[140], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[141], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[142], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[143], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[144], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[145], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[146], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[147], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[148], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[149], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[150], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[151], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[152], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[153], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[154], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[155], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[156], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[157], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[158], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[159], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[160], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[161], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x10, 0x10, 0x10, 0x10, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[162], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[163], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x10, 0x10, 0x10, 0x10, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[164], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[165], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x10, 0x10, 0x10, 0x10, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[166], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[167], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[168], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[169], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[170], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[171], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[172], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[173], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[174], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[175], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[176], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[177], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[178], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[179], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[180], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[181], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[182], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[183], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[184], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[185], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[186], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[187], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[188], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[189], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[190], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[191], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[192], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[193], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[194], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[195], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[196], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[197], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[198], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[199], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[200], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[201], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[202], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[203], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[204], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[205], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[206], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[207], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[208], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[209], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[210], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[211], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[212], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[213], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[214], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[215], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[216], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[217], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[218], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[219], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[220], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[221], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[222], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[223], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[224], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[225], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[226], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[227], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[228], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[229], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[230], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[231], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[232], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[233], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[234], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[235], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[236], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[237], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[238], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[239], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[240], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[241], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[242], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[243], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[244], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[245], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[246], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[247], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[248], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[249], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[250], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[251], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x10, 0x10, 0x10, 0x10, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[252], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[253], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x10, 0x10, 0x10, 0x10, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[254], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[255], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x10, 0x10, 0x10, 0x10, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[256], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[257], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[258], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[259], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[260], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[261], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[262], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[263], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[264], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[265], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[266], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[267], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[268], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[269], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[270], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[271], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[272], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[273], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[274], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[275], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[276], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[277], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[278], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[279], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[280], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[281], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[282], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[283], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[284], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[285], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[286], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[287], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[288], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[289], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[290], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[291], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[292], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[293], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[294], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[295], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[296], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[297], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[298], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[299], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[300], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[301], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[302], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[303], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[304], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[305], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[306], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[307], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[308], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[309], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[310], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[311], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[312], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[313], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[314], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[315], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[316], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[317], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[318], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[319], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[320], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[321], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[322], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[323], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[324], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[325], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[326], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[327], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[328], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[329], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[330], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[331], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[332], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[333], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[334], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[335], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[336], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[337], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[338], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[339], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[340], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[341], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x10, 0x10, 0x10, 0x10, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[342], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[343], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x10, 0x10, 0x10, 0x10, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[344], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[345], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x10, 0x10, 0x10, 0x10, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[346], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[347], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[348], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[349], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[350], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[351], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[352], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[353], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[354], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[355], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[356], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[357], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[358], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[359], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[360], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[361], FALSE, 0x0, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[362], FALSE, 0x0, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[363], FALSE, 0x1, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[364], FALSE, 0x1, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[365], FALSE, 0x1, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[366], FALSE, 0x1, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[367], FALSE, 0x0, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[368], FALSE, 0x0, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[369], FALSE, 0x1, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[370], FALSE, 0x1, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[371], FALSE, 0x1, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[372], FALSE, 0x1, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[373], FALSE, 0x0, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[374], FALSE, 0x0, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[375], FALSE, 0x1, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[376], FALSE, 0x1, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[377], FALSE, 0x1, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[378], FALSE, 0x1, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[379], FALSE, 0x0, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[380], FALSE, 0x0, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[381], FALSE, 0x1, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[382], FALSE, 0x1, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[383], FALSE, 0x1, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[384], FALSE, 0x1, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[385], FALSE, 0x0, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[386], FALSE, 0x0, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x10, 0x10, 0x10, 0x10, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[387], FALSE, 0x1, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[388], FALSE, 0x1, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x10, 0x10, 0x10, 0x10, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[389], FALSE, 0x1, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[390], FALSE, 0x1, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x10, 0x10, 0x10, 0x10, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[391], FALSE, 0x0, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[392], FALSE, 0x1, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[393], FALSE, 0x1, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[394], FALSE, 0x0, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[395], FALSE, 0x1, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[396], FALSE, 0x1, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[397], FALSE, 0x0, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[398], FALSE, 0x1, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[399], FALSE, 0x1, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[400], FALSE, 0x0, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[401], FALSE, 0x1, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[402], FALSE, 0x1, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[403], FALSE, 0x0, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[404], FALSE, 0x1, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[405], FALSE, 0x1, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[406], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[407], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[408], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[409], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[410], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[411], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[412], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[413], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[414], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[415], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[416], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[417], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[418], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[419], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[420], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[421], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[422], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[423], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[424], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[425], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[426], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[427], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[428], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[429], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[430], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[431], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[432], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[433], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[434], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[435], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[436], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[437], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[438], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[439], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[440], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[441], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[442], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[443], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[444], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[445], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[446], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[447], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[448], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[449], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[450], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[451], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[452], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[453], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[454], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[455], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[456], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[457], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[458], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[459], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[460], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[461], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[462], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[463], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[464], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[465], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[466], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[467], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[468], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[469], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[470], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[471], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[472], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[473], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[474], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[475], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[476], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x10, 0x10, 0x10, 0x10, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[477], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[478], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x10, 0x10, 0x10, 0x10, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[479], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[480], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x10, 0x10, 0x10, 0x10, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[481], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[482], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[483], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[484], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[485], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[486], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[487], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[488], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[489], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[490], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[491], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[492], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[493], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[494], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[495], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF00000, 0xFFC00, 0x3FF, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[496], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[497], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[498], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[499], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[500], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[501], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[502], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[503], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[504], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[505], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[506], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[507], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[508], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[509], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[510], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[511], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[512], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[513], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[514], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[515], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[516], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[517], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[518], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[519], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[520], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[521], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[522], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[523], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[524], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[525], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[526], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[527], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[528], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[529], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[530], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[531], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[532], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[533], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[534], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[535], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[536], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[537], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[538], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[539], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[540], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x2, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[541], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[542], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[543], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[544], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[545], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[546], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[547], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[548], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[549], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[550], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[551], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[552], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[553], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[554], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[555], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[556], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[557], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[558], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[559], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[560], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[561], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[562], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[563], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[564], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[565], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[566], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x10, 0x10, 0x10, 0x10, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[567], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[568], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x10, 0x10, 0x10, 0x10, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[569], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[570], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x10, 0x10, 0x10, 0x10, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[571], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[572], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[573], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[574], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[575], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[576], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[577], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[578], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[579], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[580], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[581], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[582], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[583], FALSE, 0x0, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[584], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[585], FALSE, 0x1, 0x0, 0xA, 0xA, 0xA, 0x0, 0x3FF, 0xFFC00, 0x3FF00000, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[586], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[587], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[588], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[589], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[590], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[591], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[592], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[593], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[594], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[595], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[596], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[597], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[598], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[599], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[600], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[601], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[602], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[603], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[604], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[605], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[606], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[607], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[608], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[609], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[610], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[611], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[612], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[613], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[614], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[615], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[616], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[617], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[618], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[619], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[620], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[621], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[622], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[623], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[624], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[625], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[626], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[627], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[628], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[629], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[630], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[631], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[632], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[633], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[634], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[635], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[636], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[637], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[638], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[639], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[640], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[641], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[642], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[643], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[644], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[645], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[646], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[647], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[648], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[649], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[650], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[651], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[652], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[653], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[654], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[655], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[656], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x10, 0x10, 0x10, 0x10, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[657], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[658], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x10, 0x10, 0x10, 0x10, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[659], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[660], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x10, 0x10, 0x10, 0x10, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[661], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[662], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[663], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[664], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[665], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[666], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[667], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[668], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[669], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[670], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[671], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[672], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[673], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[674], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[675], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[676], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[677], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[678], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[679], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[680], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[681], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[682], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[683], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[684], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[685], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[686], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[687], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[688], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[689], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[690], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[691], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[692], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[693], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[694], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[695], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[696], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[697], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[698], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[699], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[700], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[701], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[702], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[703], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[704], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[705], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x10, 0x10, 0x10, 0x10, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[706], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[707], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[708], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[709], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[710], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[711], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[712], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[713], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[714], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[715], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[716], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[717], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[718], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[719], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[720], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[721], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[722], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[723], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[724], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[725], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[726], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[727], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[728], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[729], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[730], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[731], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[732], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[733], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[734], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[735], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[736], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[737], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[738], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[739], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[740], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[741], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[742], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[743], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[744], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[745], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[746], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x10, 0x10, 0x10, 0x10, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[747], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[748], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x10, 0x10, 0x10, 0x10, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[749], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[750], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x10, 0x10, 0x10, 0x10, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[751], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[752], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[753], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[754], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[755], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[756], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[757], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[758], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[759], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[760], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[761], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[762], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[763], FALSE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[764], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[765], FALSE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x0, 0xFF0000, 0xFF00, 0xFF, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[766], FALSE, 0x0, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[767], FALSE, 0x0, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[768], FALSE, 0x1, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[769], FALSE, 0x1, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[770], FALSE, 0x1, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[771], FALSE, 0x1, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[772], FALSE, 0x0, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[773], FALSE, 0x0, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[774], FALSE, 0x1, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[775], FALSE, 0x1, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[776], FALSE, 0x1, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[777], FALSE, 0x1, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[778], FALSE, 0x0, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[779], FALSE, 0x0, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[780], FALSE, 0x1, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[781], FALSE, 0x1, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[782], FALSE, 0x1, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[783], FALSE, 0x1, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[784], FALSE, 0x0, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[785], FALSE, 0x0, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[786], FALSE, 0x1, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[787], FALSE, 0x1, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[788], FALSE, 0x1, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[789], FALSE, 0x1, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x10, 0x10, 0x10, 0x10, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[790], FALSE, 0x0, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[791], FALSE, 0x0, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x10, 0x10, 0x10, 0x10, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[792], FALSE, 0x1, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[793], FALSE, 0x1, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x10, 0x10, 0x10, 0x10, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[794], FALSE, 0x1, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[795], FALSE, 0x1, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x10, 0x10, 0x10, 0x10, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8001, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[796], FALSE, 0x0, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[797], FALSE, 0x1, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[798], FALSE, 0x1, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[799], FALSE, 0x0, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[800], FALSE, 0x1, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[801], FALSE, 0x1, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[802], FALSE, 0x0, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[803], FALSE, 0x1, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[804], FALSE, 0x1, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[805], FALSE, 0x0, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[806], FALSE, 0x1, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[807], FALSE, 0x1, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[808], FALSE, 0x0, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[809], FALSE, 0x1, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[810], FALSE, 0x1, 0x0, 0x5, 0x6, 0x5, 0x0, 0xF800, 0x7E0, 0x1F, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8003, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x1, 0x4, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[811], TRUE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[812], TRUE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[813], TRUE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[814], TRUE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[815], TRUE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[816], TRUE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[817], TRUE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[818], TRUE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[819], TRUE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[820], TRUE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[821], TRUE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[822], TRUE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[823], TRUE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[824], TRUE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[825], TRUE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x0 },
(__GLXconfig) { &configs[826], TRUE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[827], TRUE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[828], TRUE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[829], TRUE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[830], TRUE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[831], TRUE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[832], TRUE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[833], TRUE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[834], TRUE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[835], TRUE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[836], TRUE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[837], TRUE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x8, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[838], TRUE, 0x0, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { &configs[839], TRUE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8063, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
(__GLXconfig) { NULL, TRUE, 0x1, 0x0, 0x8, 0x8, 0x8, 0x8, 0xFF0000, 0xFF00, 0xFF, 0xFF000000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8002, 0x8000, 0x8000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8062, 0x1, 0x1, 0x0, 0x7, 0x1, 0x1 },
};

View File

@@ -0,0 +1,163 @@
#pragma once
#include <X11/keysymdef.h>
#include <jni.h>
#include "linux/input-event-codes.h"
void lorieSetVM(JavaVM* vm);
Bool lorieChangeScreenName(ClientPtr pClient, void *closure);
Bool lorieChangeWindow(ClientPtr pClient, void *closure);
void lorieConfigureNotify(int width, int height, int framerate);
void lorieEnableClipboardSync(Bool enable);
void lorieSendClipboardData(const char* data);
void lorieInitClipboard(void);
void lorieRequestClipboard(void);
void lorieHandleClipboardAnnounce(void);
void lorieHandleClipboardData(const char* data);
Bool lorieInitDri3(ScreenPtr pScreen);
void lorieSetStylusEnabled(Bool enabled);
static int android_to_linux_keycode[304] = {
[ 4 /* ANDROID_KEYCODE_BACK */] = KEY_ESC,
[ 7 /* ANDROID_KEYCODE_0 */] = KEY_0,
[ 8 /* ANDROID_KEYCODE_1 */] = KEY_1,
[ 9 /* ANDROID_KEYCODE_2 */] = KEY_2,
[ 10 /* ANDROID_KEYCODE_3 */] = KEY_3,
[ 11 /* ANDROID_KEYCODE_4 */] = KEY_4,
[ 12 /* ANDROID_KEYCODE_5 */] = KEY_5,
[ 13 /* ANDROID_KEYCODE_6 */] = KEY_6,
[ 14 /* ANDROID_KEYCODE_7 */] = KEY_7,
[ 15 /* ANDROID_KEYCODE_8 */] = KEY_8,
[ 16 /* ANDROID_KEYCODE_9 */] = KEY_9,
[ 17 /* ANDROID_KEYCODE_STAR */] = KEY_KPASTERISK,
[ 19 /* ANDROID_KEYCODE_DPAD_UP */] = KEY_UP,
[ 20 /* ANDROID_KEYCODE_DPAD_DOWN */] = KEY_DOWN,
[ 21 /* ANDROID_KEYCODE_DPAD_LEFT */] = KEY_LEFT,
[ 22 /* ANDROID_KEYCODE_DPAD_RIGHT */] = KEY_RIGHT,
[ 23 /* ANDROID_KEYCODE_DPAD_CENTER */] = KEY_ENTER,
[ 24 /* ANDROID_KEYCODE_VOLUME_UP */] = KEY_VOLUMEUP, // XF86XK_AudioRaiseVolume
[ 25 /* ANDROID_KEYCODE_VOLUME_DOWN */] = KEY_VOLUMEDOWN, // XF86XK_AudioLowerVolume
[ 26 /* ANDROID_KEYCODE_POWER */] = KEY_POWER,
[ 27 /* ANDROID_KEYCODE_CAMERA */] = KEY_CAMERA,
[ 28 /* ANDROID_KEYCODE_CLEAR */] = KEY_CLEAR,
[ 29 /* ANDROID_KEYCODE_A */] = KEY_A,
[ 30 /* ANDROID_KEYCODE_B */] = KEY_B,
[ 31 /* ANDROID_KEYCODE_C */] = KEY_C,
[ 32 /* ANDROID_KEYCODE_D */] = KEY_D,
[ 33 /* ANDROID_KEYCODE_E */] = KEY_E,
[ 34 /* ANDROID_KEYCODE_F */] = KEY_F,
[ 35 /* ANDROID_KEYCODE_G */] = KEY_G,
[ 36 /* ANDROID_KEYCODE_H */] = KEY_H,
[ 37 /* ANDROID_KEYCODE_I */] = KEY_I,
[ 38 /* ANDROID_KEYCODE_J */] = KEY_J,
[ 39 /* ANDROID_KEYCODE_K */] = KEY_K,
[ 40 /* ANDROID_KEYCODE_L */] = KEY_L,
[ 41 /* ANDROID_KEYCODE_M */] = KEY_M,
[ 42 /* ANDROID_KEYCODE_N */] = KEY_N,
[ 43 /* ANDROID_KEYCODE_O */] = KEY_O,
[ 44 /* ANDROID_KEYCODE_P */] = KEY_P,
[ 45 /* ANDROID_KEYCODE_Q */] = KEY_Q,
[ 46 /* ANDROID_KEYCODE_R */] = KEY_R,
[ 47 /* ANDROID_KEYCODE_S */] = KEY_S,
[ 48 /* ANDROID_KEYCODE_T */] = KEY_T,
[ 49 /* ANDROID_KEYCODE_U */] = KEY_U,
[ 50 /* ANDROID_KEYCODE_V */] = KEY_V,
[ 51 /* ANDROID_KEYCODE_W */] = KEY_W,
[ 52 /* ANDROID_KEYCODE_X */] = KEY_X,
[ 53 /* ANDROID_KEYCODE_Y */] = KEY_Y,
[ 54 /* ANDROID_KEYCODE_Z */] = KEY_Z,
[ 55 /* ANDROID_KEYCODE_COMMA */] = KEY_COMMA,
[ 56 /* ANDROID_KEYCODE_PERIOD */] = KEY_DOT,
[ 57 /* ANDROID_KEYCODE_ALT_LEFT */] = KEY_LEFTALT,
[ 58 /* ANDROID_KEYCODE_ALT_RIGHT */] = KEY_RIGHTALT,
[ 59 /* ANDROID_KEYCODE_SHIFT_LEFT */] = KEY_LEFTSHIFT,
[ 60 /* ANDROID_KEYCODE_SHIFT_RIGHT */] = KEY_RIGHTSHIFT,
[ 61 /* ANDROID_KEYCODE_TAB */] = KEY_TAB,
[ 62 /* ANDROID_KEYCODE_SPACE */] = KEY_SPACE,
[ 64 /* ANDROID_KEYCODE_EXPLORER */] = KEY_WWW,
[ 65 /* ANDROID_KEYCODE_ENVELOPE */] = KEY_MAIL,
[ 66 /* ANDROID_KEYCODE_ENTER */] = KEY_ENTER,
[ 67 /* ANDROID_KEYCODE_DEL */] = KEY_BACKSPACE,
[ 68 /* ANDROID_KEYCODE_GRAVE */] = KEY_GRAVE,
[ 69 /* ANDROID_KEYCODE_MINUS */] = KEY_MINUS,
[ 70 /* ANDROID_KEYCODE_EQUALS */] = KEY_EQUAL,
[ 71 /* ANDROID_KEYCODE_LEFT_BRACKET */] = KEY_LEFTBRACE,
[ 72 /* ANDROID_KEYCODE_RIGHT_BRACKET */] = KEY_RIGHTBRACE,
[ 73 /* ANDROID_KEYCODE_BACKSLASH */] = KEY_BACKSLASH,
[ 74 /* ANDROID_KEYCODE_SEMICOLON */] = KEY_SEMICOLON,
[ 75 /* ANDROID_KEYCODE_APOSTROPHE */] = KEY_APOSTROPHE,
[ 76 /* ANDROID_KEYCODE_SLASH */] = KEY_SLASH,
[ 81 /* ANDROID_KEYCODE_PLUS */] = KEY_KPPLUS,
[ 82 /* ANDROID_KEYCODE_MENU */] = KEY_CONTEXT_MENU,
[ 84 /* ANDROID_KEYCODE_SEARCH */] = KEY_SEARCH,
[ 85 /* ANDROID_KEYCODE_MEDIA_PLAY_PAUSE */] = KEY_PLAYPAUSE,
[ 86 /* ANDROID_KEYCODE_MEDIA_STOP */] = KEY_STOP_RECORD,
[ 87 /* ANDROID_KEYCODE_MEDIA_NEXT */] = KEY_NEXTSONG,
[ 88 /* ANDROID_KEYCODE_MEDIA_PREVIOUS */] = KEY_PREVIOUSSONG,
[ 89 /* ANDROID_KEYCODE_MEDIA_REWIND */] = KEY_REWIND,
[ 90 /* ANDROID_KEYCODE_MEDIA_FAST_FORWARD */] = KEY_FASTFORWARD,
[ 91 /* ANDROID_KEYCODE_MUTE */] = KEY_MUTE,
[ 92 /* ANDROID_KEYCODE_PAGE_UP */] = KEY_PAGEUP,
[ 93 /* ANDROID_KEYCODE_PAGE_DOWN */] = KEY_PAGEDOWN,
[ 111 /* ANDROID_KEYCODE_ESCAPE */] = KEY_ESC,
[ 112 /* ANDROID_KEYCODE_FORWARD_DEL */] = KEY_DELETE,
[ 113 /* ANDROID_KEYCODE_CTRL_LEFT */] = KEY_LEFTCTRL,
[ 114 /* ANDROID_KEYCODE_CTRL_RIGHT */] = KEY_RIGHTCTRL,
[ 115 /* ANDROID_KEYCODE_CAPS_LOCK */] = KEY_CAPSLOCK,
[ 116 /* ANDROID_KEYCODE_SCROLL_LOCK */] = KEY_SCROLLLOCK,
[ 117 /* ANDROID_KEYCODE_META_LEFT */] = KEY_LEFTMETA,
[ 118 /* ANDROID_KEYCODE_META_RIGHT */] = KEY_RIGHTMETA,
[ 120 /* ANDROID_KEYCODE_SYSRQ */] = KEY_PRINT,
[ 121 /* ANDROID_KEYCODE_BREAK */] = KEY_BREAK,
[ 122 /* ANDROID_KEYCODE_MOVE_HOME */] = KEY_HOME,
[ 123 /* ANDROID_KEYCODE_MOVE_END */] = KEY_END,
[ 124 /* ANDROID_KEYCODE_INSERT */] = KEY_INSERT,
[ 125 /* ANDROID_KEYCODE_FORWARD */] = KEY_FORWARD,
[ 126 /* ANDROID_KEYCODE_MEDIA_PLAY */] = KEY_PLAYCD,
[ 127 /* ANDROID_KEYCODE_MEDIA_PAUSE */] = KEY_PAUSECD,
[ 128 /* ANDROID_KEYCODE_MEDIA_CLOSE */] = KEY_CLOSECD,
[ 129 /* ANDROID_KEYCODE_MEDIA_EJECT */] = KEY_EJECTCD,
[ 130 /* ANDROID_KEYCODE_MEDIA_RECORD */] = KEY_RECORD,
[ 131 /* ANDROID_KEYCODE_F1 */] = KEY_F1,
[ 132 /* ANDROID_KEYCODE_F2 */] = KEY_F2,
[ 133 /* ANDROID_KEYCODE_F3 */] = KEY_F3,
[ 134 /* ANDROID_KEYCODE_F4 */] = KEY_F4,
[ 135 /* ANDROID_KEYCODE_F5 */] = KEY_F5,
[ 136 /* ANDROID_KEYCODE_F6 */] = KEY_F6,
[ 137 /* ANDROID_KEYCODE_F7 */] = KEY_F7,
[ 138 /* ANDROID_KEYCODE_F8 */] = KEY_F8,
[ 139 /* ANDROID_KEYCODE_F9 */] = KEY_F9,
[ 140 /* ANDROID_KEYCODE_F10 */] = KEY_F10,
[ 141 /* ANDROID_KEYCODE_F11 */] = KEY_F11,
[ 142 /* ANDROID_KEYCODE_F12 */] = KEY_F12,
[ 143 /* ANDROID_KEYCODE_NUM_LOCK */] = KEY_NUMLOCK,
[ 144 /* ANDROID_KEYCODE_NUMPAD_0 */] = KEY_KP0,
[ 145 /* ANDROID_KEYCODE_NUMPAD_1 */] = KEY_KP1,
[ 146 /* ANDROID_KEYCODE_NUMPAD_2 */] = KEY_KP2,
[ 147 /* ANDROID_KEYCODE_NUMPAD_3 */] = KEY_KP3,
[ 148 /* ANDROID_KEYCODE_NUMPAD_4 */] = KEY_KP4,
[ 149 /* ANDROID_KEYCODE_NUMPAD_5 */] = KEY_KP5,
[ 150 /* ANDROID_KEYCODE_NUMPAD_6 */] = KEY_KP6,
[ 151 /* ANDROID_KEYCODE_NUMPAD_7 */] = KEY_KP7,
[ 152 /* ANDROID_KEYCODE_NUMPAD_8 */] = KEY_KP8,
[ 153 /* ANDROID_KEYCODE_NUMPAD_9 */] = KEY_KP9,
[ 154 /* ANDROID_KEYCODE_NUMPAD_DIVIDE */] = KEY_KPSLASH,
[ 155 /* ANDROID_KEYCODE_NUMPAD_MULTIPLY */] = KEY_KPASTERISK,
[ 156 /* ANDROID_KEYCODE_NUMPAD_SUBTRACT */] = KEY_KPMINUS,
[ 157 /* ANDROID_KEYCODE_NUMPAD_ADD */] = KEY_KPPLUS,
[ 158 /* ANDROID_KEYCODE_NUMPAD_DOT */] = KEY_KPDOT,
[ 159 /* ANDROID_KEYCODE_NUMPAD_COMMA */] = KEY_KPCOMMA,
[ 160 /* ANDROID_KEYCODE_NUMPAD_ENTER */] = KEY_KPENTER,
[ 161 /* ANDROID_KEYCODE_NUMPAD_EQUALS */] = KEY_KPEQUAL,
[ 162 /* ANDROID_KEYCODE_NUMPAD_LEFT_PAREN */] = KEY_KPLEFTPAREN,
[ 163 /* ANDROID_KEYCODE_NUMPAD_RIGHT_PAREN */] = KEY_KPRIGHTPAREN,
[ 164 /* ANDROID_KEYCODE_VOLUME_MUTE */] = KEY_MUTE,
[ 165 /* ANDROID_KEYCODE_INFO */] = KEY_INFO,
[ 166 /* ANDROID_KEYCODE_CHANNEL_UP */] = KEY_CHANNELUP,
[ 167 /* ANDROID_KEYCODE_CHANNEL_DOWN */] = KEY_CHANNELDOWN,
[ 168 /* ANDROID_KEYCODE_ZOOM_IN */] = KEY_ZOOMIN,
[ 169 /* ANDROID_KEYCODE_ZOOM_OUT */] = KEY_ZOOMOUT,
[ 170 /* ANDROID_KEYCODE_TV */] = KEY_TV,
[ 208 /* ANDROID_KEYCODE_CALENDAR */] = KEY_CALENDAR,
[ 210 /* ANDROID_KEYCODE_CALCULATOR */] = KEY_CALC,
};

View File

@@ -0,0 +1,714 @@
#pragma clang diagnostic ignored "-Wunknown-pragmas"
#pragma ide diagnostic ignored "UnusedParameter"
#pragma ide diagnostic ignored "DanglingPointer"
#pragma ide diagnostic ignored "ConstantConditionsOC"
#pragma ide diagnostic ignored "OCUnusedGlobalDeclarationInspection"
#pragma ide diagnostic ignored "UnreachableCode"
#pragma ide diagnostic ignored "OCUnusedMacroInspection"
#pragma ide diagnostic ignored "misc-no-recursion"
#define EGL_EGLEXT_PROTOTYPES
#define GL_GLEXT_PROTOTYPES
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#include <android/native_window_jni.h>
#include <android/log.h>
#include <dlfcn.h>
#include "renderer.h"
#include "os.h"
#define log(...) __android_log_print(ANDROID_LOG_DEBUG, "gles-renderer", __VA_ARGS__)
#define loge(...) __android_log_print(ANDROID_LOG_ERROR, "gles-renderer", __VA_ARGS__)
static GLuint create_program(const char* p_vertex_source, const char* p_fragment_source);
static int eglCheckError(int line) {
char* desc;
int err = eglGetError();
switch(err) {
#define E(code, text) case code: desc = (char*) text; break
case EGL_SUCCESS: desc = NULL; // "No error"
E(EGL_NOT_INITIALIZED, "EGL not initialized or failed to initialize");
E(EGL_BAD_ACCESS, "Resource inaccessible");
E(EGL_BAD_ALLOC, "Cannot allocate resources");
E(EGL_BAD_ATTRIBUTE, "Unrecognized attribute or attribute value");
E(EGL_BAD_CONTEXT, "Invalid EGL context");
E(EGL_BAD_CONFIG, "Invalid EGL frame buffer configuration");
E(EGL_BAD_CURRENT_SURFACE, "Current surface is no longer valid");
E(EGL_BAD_DISPLAY, "Invalid EGL display");
E(EGL_BAD_SURFACE, "Invalid surface");
E(EGL_BAD_MATCH, "Inconsistent arguments");
E(EGL_BAD_PARAMETER, "Invalid argument");
E(EGL_BAD_NATIVE_PIXMAP, "Invalid native pixmap");
E(EGL_BAD_NATIVE_WINDOW, "Invalid native window");
E(EGL_CONTEXT_LOST, "Context lost");
#undef E
default: desc = (char*) "Unknown error";
}
if (desc)
log("Xlorie: egl error on line %d: %s\n", line, desc);
return err;
}
static const char* eglErrorLabel(int code) {
switch(code) {
case EGL_SUCCESS: return NULL; // "No error"
#define E(code) case code: return #code; break
E(EGL_NOT_INITIALIZED);
E(EGL_BAD_ACCESS);
E(EGL_BAD_ALLOC);
E(EGL_BAD_ATTRIBUTE);
E(EGL_BAD_CONTEXT);
E(EGL_BAD_CONFIG);
E(EGL_BAD_CURRENT_SURFACE);
E(EGL_BAD_DISPLAY);
E(EGL_BAD_SURFACE);
E(EGL_BAD_MATCH);
E(EGL_BAD_PARAMETER);
E(EGL_BAD_NATIVE_PIXMAP);
E(EGL_BAD_NATIVE_WINDOW);
E(EGL_CONTEXT_LOST);
#undef E
default: return "EGL_UNKNOWN_ERROR";
}
}
static void checkGlError(int line) {
GLenum error;
char *desc = NULL;
for (error = glGetError(); error; error = glGetError()) {
switch (error) {
#define E(code) case code: desc = (char*)#code; break
E(GL_INVALID_ENUM);
E(GL_INVALID_VALUE);
E(GL_INVALID_OPERATION);
E(GL_STACK_OVERFLOW_KHR);
E(GL_STACK_UNDERFLOW_KHR);
E(GL_OUT_OF_MEMORY);
E(GL_INVALID_FRAMEBUFFER_OPERATION);
E(GL_CONTEXT_LOST_KHR);
default:
continue;
#undef E
}
log("Xlorie: GLES %d ERROR: %s.\n", line, desc);
return;
}
}
#define checkGlError() checkGlError(__LINE__)
static const char vertex_shader[] =
"attribute vec4 position;\n"
"attribute vec2 texCoords;"
"varying vec2 outTexCoords;\n"
"void main(void) {\n"
" outTexCoords = texCoords;\n"
" gl_Position = position;\n"
"}\n";
#define FRAGMENT_SHADER(texture) \
"precision mediump float;\n" \
"varying vec2 outTexCoords;\n" \
"uniform sampler2D texture;\n" \
"void main(void) {\n" \
" gl_FragColor = texture2D(texture, outTexCoords)" texture ";\n" \
"}\n"
static const char fragment_shader[] = FRAGMENT_SHADER();
static const char fragment_shader_bgra[] = FRAGMENT_SHADER(".bgra");
static EGLDisplay egl_display = EGL_NO_DISPLAY;
static EGLContext ctx = EGL_NO_CONTEXT;
static EGLSurface sfc = EGL_NO_SURFACE;
static EGLConfig cfg = 0;
static EGLNativeWindowType win = 0;
static jobject surface = NULL;
static AHardwareBuffer *buffer = NULL;
static EGLImageKHR image = NULL;
static int renderedFrames = 0;
static jmethodID Surface_release = NULL;
static jmethodID Surface_destroy = NULL;
static struct {
GLuint id;
float width, height;
} display;
static struct {
GLuint id;
float x, y, width, height, xhot, yhot;
} cursor;
GLuint g_texture_program = 0, gv_pos = 0, gv_coords = 0;
GLuint g_texture_program_bgra = 0, gv_pos_bgra = 0, gv_coords_bgra = 0;
int renderer_init(JNIEnv* env, int* legacy_drawing, uint8_t* flip) {
EGLint major, minor;
EGLint numConfigs;
const EGLint configAttribs[] = {
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_ALPHA_SIZE, 0,
EGL_NONE
};
const EGLint configAttribs2[] = {
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_ALPHA_SIZE, 8,
EGL_NONE
};
const EGLint ctxattribs[] = {
EGL_CONTEXT_CLIENT_VERSION,2, EGL_NONE
};
if (ctx)
return 1;
jclass Surface = (*env)->FindClass(env, "android/view/Surface");
Surface_release = (*env)->GetMethodID(env, Surface, "release", "()V");
Surface_destroy = (*env)->GetMethodID(env, Surface, "destroy", "()V");
if (!Surface_release) {
loge("Failed to find required Surface.release method. Aborting.\n");
abort();
}
if (!Surface_destroy) {
loge("Failed to find required Surface.destroy method. Aborting.\n");
abort();
}
egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
if (egl_display == EGL_NO_DISPLAY) {
log("Xlorie: Got no EGL display.\n");
eglCheckError(__LINE__);
return 0;
}
if (eglInitialize(egl_display, &major, &minor) != EGL_TRUE) {
log("Xlorie: Unable to initialize EGL\n");
eglCheckError(__LINE__);
return 0;
}
log("Xlorie: Initialized EGL version %d.%d\n", major, minor);
eglBindAPI(EGL_OPENGL_ES_API);
if (eglChooseConfig(egl_display, configAttribs, &cfg, 1, &numConfigs) != EGL_TRUE &&
eglChooseConfig(egl_display, configAttribs2, &cfg, 1, &numConfigs) != EGL_TRUE) {
log("Xlorie: eglChooseConfig failed.\n");
eglCheckError(__LINE__);
return 0;
}
ctx = eglCreateContext(egl_display, cfg, NULL, ctxattribs);
if (ctx == EGL_NO_CONTEXT) {
log("Xlorie: eglCreateContext failed.\n");
eglCheckError(__LINE__);
return 0;
}
if (eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT) != EGL_TRUE) {
log("Xlorie: eglMakeCurrent failed.\n");
eglCheckError(__LINE__);
return 0;
}
{
// Some devices do not support sampling from HAL_PIXEL_FORMAT_BGRA_8888, here we are checking it.
const EGLint imageAttributes[] = {EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE};
EGLClientBuffer clientBuffer;
EGLImageKHR img;
AHardwareBuffer *new = NULL;
int status;
AHardwareBuffer_Desc d0 = {
.width = 64,
.height = 64,
.layers = 1,
.usage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE | AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN | AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN,
.format = AHARDWAREBUFFER_FORMAT_B8G8R8A8_UNORM
};
status = AHardwareBuffer_allocate(&d0, &new);
if (status != 0 || new == NULL) {
loge("Failed to allocate native buffer (%p, error %d)", new, status);
loge("Forcing legacy drawing");
*legacy_drawing = 1;
return 1;
}
uint32_t *pixels;
if (AHardwareBuffer_lock(new, AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN | AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN, -1, NULL, (void **) &pixels) == 0) {
pixels[0] = 0xAABBCCDD;
AHardwareBuffer_unlock(new, NULL);
} else {
loge("Failed to lock native buffer (%p, error %d)", new, status);
loge("Forcing legacy drawing");
*legacy_drawing = 1;
return 1;
}
clientBuffer = eglGetNativeClientBufferANDROID(new);
if (!clientBuffer) {
eglCheckError(__LINE__);
loge("Failed to obtain EGLClientBuffer from AHardwareBuffer");
loge("Forcing legacy drawing");
*legacy_drawing = 1;
return 1;
}
if (!(img = eglCreateImageKHR(egl_display, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, clientBuffer, imageAttributes))) {
if (eglGetError() == EGL_BAD_PARAMETER) {
loge("Sampling from HAL_PIXEL_FORMAT_BGRA_8888 is not supported, forcing AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM");
*flip = 1;
} else {
loge("Failed to obtain EGLImageKHR from EGLClientBuffer");
loge("Forcing legacy drawing");
*legacy_drawing = 1;
}
} else {
// For some reason all devices I checked had no GL_EXT_texture_format_BGRA8888 support, but some of them still provided BGRA extension.
// EGL does not provide functions to query texture format in runtime.
// Workarounds are less performant but at least they let us use Termux:X11 on devices with missing BGRA support.
// We handle two cases.
// If resulting texture has BGRA format but still drawing RGBA we should flip format to RGBA and flip pixels manually in shader.
// In the case if for some reason we can not use HAL_PIXEL_FORMAT_BGRA_8888 we should fallback to legacy drawing method (uploading pixels via glTexImage2D).
const EGLint configAttributes[] = {
EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_ALPHA_SIZE, 8,
EGL_NONE
};
EGLConfig checkcfg = 0;
GLuint fbo = 0, texture = 0;
if (eglChooseConfig(egl_display, configAttributes, &checkcfg, 1, &numConfigs) != EGL_TRUE) {
log("Xlorie: check eglChooseConfig failed.\n");
eglCheckError(__LINE__);
return 0;
}
EGLContext testctx = eglCreateContext(egl_display, checkcfg, NULL, ctxattribs);
if (testctx == EGL_NO_CONTEXT) {
log("Xlorie: check eglCreateContext failed.\n");
eglCheckError(__LINE__);
return 0;
}
const EGLint pbufferAttributes[] = {
EGL_WIDTH, 64,
EGL_HEIGHT, 64,
EGL_NONE,
};
EGLSurface checksfc = eglCreatePbufferSurface(egl_display, checkcfg, pbufferAttributes);
if (eglMakeCurrent(egl_display, checksfc, checksfc, testctx) != EGL_TRUE) {
log("Xlorie: check eglMakeCurrent failed.\n");
eglCheckError(__LINE__);
return 0;
}
glActiveTexture(GL_TEXTURE0); checkGlError();
glGenTextures(1, &texture); checkGlError();
glBindTexture(GL_TEXTURE_2D, texture); checkGlError();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); checkGlError();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); checkGlError();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); checkGlError();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); checkGlError();
glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, img); checkGlError();
glGenFramebuffers(1, &fbo); checkGlError();
glBindFramebuffer(GL_FRAMEBUFFER, fbo); checkGlError();
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); checkGlError();
uint32_t pixel[64*64];
glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixel); checkGlError();
if (pixel[0] == 0xAABBCCDD) {
log("Xlorie: GLES draws pixels unchanged, probably system does not support AHARDWAREBUFFER_FORMAT_B8G8R8A8_UNORM. Forcing bgra.\n");
*flip = 1;
} else if (pixel[0] != 0xAADDCCBB) {
log("Xlorie: GLES receives broken pixels. Forcing legacy drawing. 0x%X\n", pixel[0]);
*legacy_drawing = 1;
}
eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
}
}
return 1;
}
static void renderer_unset_buffer(void) {
if (eglGetCurrentContext() == EGL_NO_CONTEXT) {
loge("There is no current context, `renderer_set_buffer` call is cancelled");
return;
}
log("renderer_set_buffer0");
if (image)
eglDestroyImageKHR(egl_display, image);
if (buffer)
AHardwareBuffer_release(buffer);
buffer = NULL;
}
void renderer_set_buffer(JNIEnv* env, AHardwareBuffer* buf) {
const EGLint imageAttributes[] = {EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE};
EGLClientBuffer clientBuffer;
AHardwareBuffer_Desc desc = {0};
uint8_t flip = 0;
if (eglGetCurrentContext() == EGL_NO_CONTEXT) {
loge("There is no current context, `renderer_set_buffer` call is cancelled");
return;
}
renderer_unset_buffer();
buffer = buf;
glBindTexture(GL_TEXTURE_2D, display.id); checkGlError();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); checkGlError();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); checkGlError();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); checkGlError();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); checkGlError();
if (buffer) {
AHardwareBuffer_acquire(buffer);
AHardwareBuffer_describe(buffer, &desc);
display.width = (float) desc.width;
display.height = (float) desc.height;
clientBuffer = eglGetNativeClientBufferANDROID(buffer);
if (!clientBuffer) {
eglCheckError(__LINE__);
loge("Failed to obtain EGLClientBuffer from AHardwareBuffer");
}
image = clientBuffer ? eglCreateImageKHR(egl_display, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, clientBuffer, imageAttributes) : NULL;
if (image != NULL) {
glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
flip = desc.format != AHARDWAREBUFFER_FORMAT_B8G8R8A8_UNORM;
} else {
if (clientBuffer) {
eglCheckError(__LINE__);
loge("Binding AHardwareBuffer to an EGLImage failed.");
}
display.width = 1;
display.height = 1;
uint32_t data = {0};
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data);
checkGlError();
}
checkGlError();
} else {
display.width = 1;
display.height = 1;
uint32_t data = {0};
loge("There is no AHardwareBuffer, nothing to be bound.");
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data); checkGlError();
}
renderer_redraw(env, flip);
log("renderer_set_buffer %p %d %d", buffer, desc.width, desc.height);
}
void renderer_set_window(JNIEnv* env, jobject new_surface, AHardwareBuffer* new_buffer) {
EGLNativeWindowType window;
if (new_surface && surface && new_surface != surface && (*env)->IsSameObject(env, new_surface, surface)) {
(*env)->DeleteGlobalRef(env, new_surface);
new_surface = NULL;
return;
}
window = new_surface ? ANativeWindow_fromSurface(env, new_surface) : NULL;
int width = window ? ANativeWindow_getWidth(window) : 0;
int height = window ? ANativeWindow_getHeight(window) : 0;
log("renderer_set_window %p %d %d", window, width, height);
if (window && win == window)
return;
if (sfc != EGL_NO_SURFACE) {
if (eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT) != EGL_TRUE) {
log("Xlorie: eglMakeCurrent (EGL_NO_SURFACE) failed.\n");
eglCheckError(__LINE__);
return;
}
if (eglDestroySurface(egl_display, sfc) != EGL_TRUE) {
log("Xlorie: eglDestoySurface failed.\n");
eglCheckError(__LINE__);
return;
}
}
sfc = EGL_NO_SURFACE;
if (win)
ANativeWindow_release(win);
if (surface) {
(*env)->CallVoidMethod(env, surface, Surface_release);
(*env)->CallVoidMethod(env, surface, Surface_destroy);
(*env)->DeleteGlobalRef(env, surface);
}
if (window && (width <= 0 || height <= 0)) {
log("Xlorie: We've got invalid surface. Probably it became invalid before we started working with it.\n");
ANativeWindow_release(window);
window = NULL;
if (new_surface) {
(*env)->CallVoidMethod(env, new_surface, Surface_release);
(*env)->CallVoidMethod(env, new_surface, Surface_destroy);
(*env)->DeleteGlobalRef(env, new_surface);
new_surface = NULL;
}
}
win = window;
surface = new_surface;
if (!win)
return;
sfc = eglCreateWindowSurface(egl_display, cfg, win, NULL);
if (sfc == EGL_NO_SURFACE) {
log("Xlorie: eglCreateWindowSurface failed.\n");
eglCheckError(__LINE__);
return;
}
if (eglMakeCurrent(egl_display, sfc, sfc, ctx) != EGL_TRUE) {
log("Xlorie: eglMakeCurrent failed.\n");
eglCheckError(__LINE__);
return;
}
if (!g_texture_program) {
g_texture_program = create_program(vertex_shader, fragment_shader);
if (!g_texture_program) {
log("Xlorie: GLESv2: Unable to create shader program.\n");
eglCheckError(__LINE__);
return;
}
g_texture_program_bgra = create_program(vertex_shader, fragment_shader_bgra);
if (!g_texture_program_bgra) {
log("Xlorie: GLESv2: Unable to create bgra shader program.\n");
eglCheckError(__LINE__);
return;
}
gv_pos = (GLuint) glGetAttribLocation(g_texture_program, "position"); checkGlError();
gv_coords = (GLuint) glGetAttribLocation(g_texture_program, "texCoords"); checkGlError();
gv_pos_bgra = (GLuint) glGetAttribLocation(g_texture_program_bgra, "position"); checkGlError();
gv_coords_bgra = (GLuint) glGetAttribLocation(g_texture_program_bgra, "texCoords"); checkGlError();
glActiveTexture(GL_TEXTURE0); checkGlError();
glGenTextures(1, &display.id); checkGlError();
glGenTextures(1, &cursor.id); checkGlError();
}
eglSwapInterval(egl_display, 0);
if (win && ctx && ANativeWindow_getWidth(win) > 0 && ANativeWindow_getHeight(win) > 0)
glViewport(0, 0, ANativeWindow_getWidth(win), ANativeWindow_getHeight(win)); checkGlError();
log("Xlorie: new surface applied: %p\n", sfc);
if (!new_buffer) {
glClearColor(0.f, 0.f, 0.f, 0.0f); checkGlError();
glClear(GL_COLOR_BUFFER_BIT); checkGlError();
} else renderer_set_buffer(env, new_buffer);
}
void renderer_update_root(int w, int h, void* data, uint8_t flip) {
if (eglGetCurrentContext() == EGL_NO_CONTEXT || !w || !h)
return;
if (display.width != (float) w || display.height != (float) h) {
display.width = (float) w;
display.height = (float) h;
glBindTexture(GL_TEXTURE_2D, display.id); checkGlError();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); checkGlError();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); checkGlError();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); checkGlError();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); checkGlError();
glTexImage2D(GL_TEXTURE_2D, 0, flip ? GL_RGBA : GL_BGRA_EXT, w, h, 0, flip ? GL_RGBA : GL_BGRA_EXT, GL_UNSIGNED_BYTE, data); checkGlError();
} else {
glBindTexture(GL_TEXTURE_2D, display.id); checkGlError();
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, flip ? GL_RGBA : GL_BGRA_EXT, GL_UNSIGNED_BYTE, data);
checkGlError();
}
}
void renderer_update_cursor(int w, int h, int xhot, int yhot, void* data) {
log("Xlorie: updating cursor\n");
cursor.width = (float) w;
cursor.height = (float) h;
cursor.xhot = (float) xhot;
cursor.yhot = (float) yhot;
if (eglGetCurrentContext() == EGL_NO_CONTEXT || !cursor.width || !cursor.height)
return;
glBindTexture(GL_TEXTURE_2D, cursor.id); checkGlError();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); checkGlError();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); checkGlError();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); checkGlError();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); checkGlError();
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); checkGlError();
}
void renderer_set_cursor_coordinates(int x, int y) {
cursor.x = (float) x;
cursor.y = (float) y;
}
static void draw(GLuint id, float x0, float y0, float x1, float y1, uint8_t flip);
static void draw_cursor(void);
float ia = 0;
int renderer_should_redraw(void) {
return sfc != EGL_NO_SURFACE && eglGetCurrentContext() != EGL_NO_CONTEXT;
}
int renderer_redraw(JNIEnv* env, uint8_t flip) {
int err = EGL_SUCCESS;
if (!sfc || eglGetCurrentContext() == EGL_NO_CONTEXT)
return FALSE;
draw(display.id, -1.f, -1.f, 1.f, 1.f, flip);
draw_cursor();
if (eglSwapBuffers(egl_display, sfc) != EGL_TRUE) {
err = eglGetError();
eglCheckError(__LINE__);
if (err == EGL_BAD_NATIVE_WINDOW || err == EGL_BAD_SURFACE) {
log("We've got %s so window is to be destroyed. "
"Native window disconnected/abandoned, probably activity is destroyed or in background",
eglErrorLabel(err));
renderer_set_window(env, NULL, NULL);
return FALSE;
}
}
renderedFrames++;
return TRUE;
}
void renderer_print_fps(float millis) {
if (renderedFrames)
log("%d frames in %.1f seconds = %.1f FPS",
renderedFrames, millis / 1000, (float) renderedFrames * 1000 / millis);
renderedFrames = 0;
}
static GLuint load_shader(GLenum shaderType, const char* pSource) {
GLint compiled = 0;
GLuint shader = glCreateShader(shaderType); checkGlError();
if (shader) {
glShaderSource(shader, 1, &pSource, NULL); checkGlError();
glCompileShader(shader); checkGlError();
glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); checkGlError();
if (!compiled) {
GLint infoLen = 0;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen); checkGlError();
if (infoLen) {
char* buf = (char*) malloc(infoLen);
if (buf) {
glGetShaderInfoLog(shader, infoLen, NULL, buf); checkGlError();
log("Xlorie: Could not compile shader %d:\n%s\n", shaderType, buf);
free(buf);
}
glDeleteShader(shader); checkGlError();
shader = 0;
}
}
}
return shader;
}
static GLuint create_program(const char* p_vertex_source, const char* p_fragment_source) {
GLuint program, vertexShader, pixelShader;
GLint linkStatus = GL_FALSE;
vertexShader = load_shader(GL_VERTEX_SHADER, p_vertex_source);
pixelShader = load_shader(GL_FRAGMENT_SHADER, p_fragment_source);
if (!pixelShader || !vertexShader) {
return 0;
}
program = glCreateProgram(); checkGlError();
if (program) {
glAttachShader(program, vertexShader); checkGlError();
glAttachShader(program, pixelShader); checkGlError();
glLinkProgram(program); checkGlError();
glGetProgramiv(program, GL_LINK_STATUS, &linkStatus); checkGlError();
if (linkStatus != GL_TRUE) {
GLint bufLength = 0;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength); checkGlError();
if (bufLength) {
char* buf = (char*) malloc(bufLength);
if (buf) {
glGetProgramInfoLog(program, bufLength, NULL, buf); checkGlError();
log("Xlorie: Could not link program:\n%s\n", buf);
free(buf);
}
}
glDeleteProgram(program); checkGlError();
program = 0;
}
}
return program;
}
static void draw(GLuint id, float x0, float y0, float x1, float y1, uint8_t flip) {
float coords[20] = {
x0, -y0, 0.f, 0.f, 0.f,
x1, -y0, 0.f, 1.f, 0.f,
x0, -y1, 0.f, 0.f, 1.f,
x1, -y1, 0.f, 1.f, 1.f,
};
GLuint p = flip ? gv_pos_bgra : gv_pos, c = flip ? gv_coords_bgra : gv_coords;
glActiveTexture(GL_TEXTURE0); checkGlError();
glUseProgram(flip ? g_texture_program_bgra : g_texture_program); checkGlError();
glBindTexture(GL_TEXTURE_2D, id); checkGlError();
glVertexAttribPointer(p, 3, GL_FLOAT, GL_FALSE, 20, coords); checkGlError();
glVertexAttribPointer(c, 2, GL_FLOAT, GL_FALSE, 20, &coords[3]); checkGlError();
glEnableVertexAttribArray(p); checkGlError();
glEnableVertexAttribArray(c); checkGlError();
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); checkGlError();
}
__unused static void draw_cursor(void) {
float x, y, w, h;
if (!cursor.width || !cursor.height)
return;
x = 2.f * (cursor.x - cursor.xhot) / display.width - 1.f;
y = 2.f * (cursor.y - cursor.yhot) / display.height - 1.f;
w = 2.f * cursor.width / display.width;
h = 2.f * cursor.height / display.height;
glEnable(GL_BLEND); checkGlError();
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); checkGlError();
draw(cursor.id, x, y, x + w, y + h, false);
glDisable(GL_BLEND); checkGlError();
}

View File

@@ -0,0 +1,23 @@
#pragma once
#include <jni.h>
#include <android/hardware_buffer.h>
// X server is already linked to mesa so linking to Android's GLESv2 will confuse the linker.
// That is a reason why we should compile renderer as separate hared library with its own dependencies.
// In that case part of X server's api is unavailable,
// so we should pass addresses to all needed functions to the renderer lib.
typedef void (*renderer_message_func_type) (int type, int verb, const char *format, ...);
__unused void renderer_message_func(renderer_message_func_type function);
__unused int renderer_init(JNIEnv* env, int* legacy_drawing, uint8_t* flip);
__unused void renderer_set_buffer(JNIEnv* env, AHardwareBuffer* buffer);
__unused void renderer_set_window(JNIEnv* env, jobject surface, AHardwareBuffer* buffer);
__unused int renderer_should_redraw(void);
__unused int renderer_redraw(JNIEnv* env, uint8_t flip);
__unused void renderer_print_fps(float millis);
__unused void renderer_update_root(int w, int h, void* data, uint8_t flip);
__unused void renderer_update_cursor(int w, int h, int xhot, int yhot, void* data);
__unused void renderer_set_cursor_coordinates(int x, int y);
#define AHARDWAREBUFFER_FORMAT_B8G8R8A8_UNORM 5 // Stands to HAL_PIXEL_FORMAT_BGRA_8888

View File

@@ -0,0 +1,28 @@
Copyright (c) 2013, Sergii Pylypenko
Copyright (c) 2017, Fredrik Fornwall
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
* Neither the name of the {organization} nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -0,0 +1,11 @@
libandroid-shmem
================
System V shared memory (shmget, shmat, shmdt and shmctl) emulation on Android using ashmem for use in [Termux](https://termux.com/).
The shared memory segments it creates will be automatically destroyed when the creating process destroys them or dies, which differs from the System V shared memory behaviour.
Based on previous work in https://github.com/pelya/android-shmem.
Hacking
=======
The project can be developed on Android devices using Termux. Clone the repo and run `make` in the `tests/` folder after editing the library or test cases.

View File

@@ -0,0 +1,36 @@
#ifndef _SYS_SHM_H
#define _SYS_SHM_H
#include <linux/shm.h>
#include <stdint.h>
#include <sys/types.h>
__BEGIN_DECLS
#ifndef shmid_ds
# define shmid_ds shmid64_ds
#endif
/* Shared memory control operations. */
#undef shmctl
#define shmctl libandroid_shmctl
extern int shmctl(int shmid, int cmd, struct shmid_ds* buf);
/* Get shared memory area identifier. */
#undef shmget
#define shmget libandroid_shmget
extern int shmget(key_t key, size_t size, int shmflg);
/* Attach shared memory segment. */
#undef shmat
#define shmat libandroid_shmat
extern void *shmat(int shmid, void const* shmaddr, int shmflg);
/* Detach shared memory segment. */
#undef shmdt
#define shmdt libandroid_shmdt
extern int shmdt(void const* shmaddr);
__END_DECLS
#endif

View File

@@ -0,0 +1,638 @@
#ifdef ANDROID
#include <android/log.h>
#endif
#include <errno.h>
#include <pthread.h>
#include <fcntl.h>
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/socket.h>
#include <sys/syscall.h>
#include <sys/un.h>
#include <unistd.h>
#include <paths.h>
#include <ctype.h>
#define __u32 uint32_t
#ifdef ANDROID
#include <linux/ashmem.h>
#include <libgen.h>
#endif
#include "shm.h"
#define DBG(...)
#define ANDROID_SHMEM_SOCKNAME "/dev/shm/%08x"
#define ROUND_UP(N, S) ((((N) + (S) - 1) / (S)) * (S))
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
typedef struct {
// The shmid (shared memory id) contains the socket address (16 bits)
// and a local id (15 bits).
int id;
void *addr;
int descriptor;
size_t size;
bool markedForDeletion;
key_t key;
} shmem_t;
static shmem_t* shmem = NULL;
static size_t shmem_amount = 0;
static uint8_t syscall_supported = 0;
#define ANDROID_LINUX_SHM
#undef SYS_ipc
static bool isProot(void) {
char buf[4096];
char path[256];
char exe_path[256];
int tpid;
const int status_fd = open("/proc/self/status", O_RDONLY);
if (status_fd == -1)
return false;
read(status_fd, buf, sizeof(buf) - 1);
close(status_fd);
const char *tracer_str = strstr(buf, "TracerPid:");
if (tracer_str || sscanf(tracer_str, "TracerPid: %d", &tpid) != 1 || !tpid)
return false;
snprintf(path, sizeof(path), "/proc/%d/exe", tpid);
ssize_t len = readlink(path, exe_path, sizeof(exe_path) - 1);
if (len == -1)
return false;
exe_path[len] = '\0';
return (!strcmp(basename(exe_path), "proot"));
}
__attribute__((unused, constructor))
static void check_syscall_support(void) {
if (!isProot())
return;
errno = 0;
#ifdef ANDROID_LINUX_SHM
#ifdef SYS_ipc
syscall(SYS_ipc);
#else
syscall(SYS_shmat);
#endif
#endif
if (errno != ENOSYS)
syscall_supported = 1;
}
// The lower 16 bits of (getpid() + i), where i is a sequence number.
// It is unique among processes as it's only set when bound.
static int ashv_local_socket_id = 0;
// To handle forks we store which pid the ashv_local_socket_id was
// created for.
static int ashv_pid_setup = 0;
static pthread_t ashv_listening_thread_id = 0;
static int ancil_send_fd(int sock, int fd)
{
char nothing = '!';
struct iovec nothing_ptr = { .iov_base = &nothing, .iov_len = 1 };
struct {
struct cmsghdr align;
int fd[1];
} ancillary_data_buffer;
struct msghdr message_header = {
.msg_name = NULL,
.msg_namelen = 0,
.msg_iov = &nothing_ptr,
.msg_iovlen = 1,
.msg_flags = 0,
.msg_control = &ancillary_data_buffer,
.msg_controllen = sizeof(struct cmsghdr) + sizeof(int)
};
struct cmsghdr* cmsg = CMSG_FIRSTHDR(&message_header);
cmsg->cmsg_len = message_header.msg_controllen; // sizeof(int);
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
((int*) CMSG_DATA(cmsg))[0] = fd;
return sendmsg(sock, &message_header, 0) >= 0 ? 0 : -1;
}
static int ancil_recv_fd(int sock)
{
char nothing = '!';
struct iovec nothing_ptr = { .iov_base = &nothing, .iov_len = 1 };
struct {
struct cmsghdr align;
int fd[1];
} ancillary_data_buffer;
struct msghdr message_header = {
.msg_name = NULL,
.msg_namelen = 0,
.msg_iov = &nothing_ptr,
.msg_iovlen = 1,
.msg_flags = 0,
.msg_control = &ancillary_data_buffer,
.msg_controllen = sizeof(struct cmsghdr) + sizeof(int)
};
struct cmsghdr* cmsg = CMSG_FIRSTHDR(&message_header);
cmsg->cmsg_len = message_header.msg_controllen;
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
((int*) CMSG_DATA(cmsg))[0] = -1;
if (recvmsg(sock, &message_header, 0) < 0) return -1;
return ((int*) CMSG_DATA(cmsg))[0];
}
static int ashmem_get_size_region(int fd)
{
#ifdef ANDROID
//int ret = __ashmem_is_ashmem(fd, 1);
//if (ret < 0) return ret;
return TEMP_FAILURE_RETRY(ioctl(fd, ASHMEM_GET_SIZE, NULL));
#else
return -1;
#endif
}
/*
* From https://android.googlesource.com/platform/system/core/+/master/libcutils/ashmem-dev.c
*
* ashmem_create_region - creates a new named ashmem region and returns the file
* descriptor, or <0 on error.
*
* `name' is the label to give the region (visible in /proc/pid/maps)
* `size' is the size of the region, in page-aligned bytes
*/
static int ashmem_create_region(char const* name, size_t size)
{
#ifdef ANDROID
int fd = open("/dev/ashmem", O_RDWR);
if (fd < 0) return fd;
char name_buffer[ASHMEM_NAME_LEN] = {0};
strncpy(name_buffer, name, sizeof(name_buffer));
name_buffer[sizeof(name_buffer)-1] = 0;
int ret = ioctl(fd, ASHMEM_SET_NAME, name_buffer);
if (ret < 0) goto error;
ret = ioctl(fd, ASHMEM_SET_SIZE, size);
if (ret < 0) goto error;
return fd;
error:
close(fd);
return ret;
#endif
return -1;
}
static void ashv_check_pid()
{
pid_t mypid = getpid();
if (ashv_pid_setup == 0) {
ashv_pid_setup = mypid;
} else if (ashv_pid_setup != mypid) {
DBG("%s: Cleaning to new pid=%d from oldpid=%d", __PRETTY_FUNCTION__, mypid, ashv_pid_setup);
// We inherited old state across a fork.
ashv_pid_setup = mypid;
ashv_local_socket_id = 0;
ashv_listening_thread_id = 0;
shmem_amount = 0;
// Unlock if fork left us with held lock from parent thread.
pthread_mutex_unlock(&mutex);
if (shmem != NULL) free(shmem);
shmem = NULL;
}
}
// Store index in the lower 15 bits and the socket id in the
// higher 16 bits.
static int ashv_shmid_from_counter(unsigned int counter)
{
return ashv_local_socket_id * 0x10000 + counter;
}
static int ashv_socket_id_from_shmid(int shmid)
{
return shmid / 0x10000;
}
static int ashv_find_local_index(int shmid)
{
for (size_t i = 0; i < shmem_amount; i++)
if (shmem[i].id == shmid)
return i;
return -1;
}
static void* ashv_thread_function(void* arg)
{
int sock = *(int*)arg;
free(arg);
struct sockaddr_un addr;
socklen_t len = sizeof(addr);
int sendsock;
//DBG("%s: thread started", __PRETTY_FUNCTION__);
while ((sendsock = accept(sock, (struct sockaddr *)&addr, &len)) != -1) {
int shmid;
if (recv(sendsock, &shmid, sizeof(shmid), 0) != sizeof(shmid)) {
DBG("%s: ERROR: recv() returned not %zu bytes", __PRETTY_FUNCTION__, sizeof(shmid));
close(sendsock);
continue;
}
pthread_mutex_lock(&mutex);
int idx = ashv_find_local_index(shmid);
if (idx != -1) {
if (write(sendsock, &shmem[idx].key, sizeof(key_t)) != sizeof(key_t)) {
DBG("%s: ERROR: write failed: %s", __PRETTY_FUNCTION__, strerror(errno));
}
if (ancil_send_fd(sendsock, shmem[idx].descriptor) != 0) {
DBG("%s: ERROR: ancil_send_fd() failed: %s", __PRETTY_FUNCTION__, strerror(errno));
}
} else {
DBG("%s: ERROR: cannot find shmid 0x%x", __PRETTY_FUNCTION__, shmid);
}
pthread_mutex_unlock(&mutex);
close(sendsock);
len = sizeof(addr);
}
DBG ("%s: ERROR: listen() failed, thread stopped", __PRETTY_FUNCTION__);
return NULL;
}
static void android_shmem_delete(int idx)
{
if (shmem[idx].descriptor) close(shmem[idx].descriptor);
shmem_amount--;
memmove(&shmem[idx], &shmem[idx+1], (shmem_amount - idx) * sizeof(shmem_t));
}
static int ashv_read_remote_segment(int shmid)
{
struct sockaddr_un addr;
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
sprintf(&addr.sun_path[1], ANDROID_SHMEM_SOCKNAME, ashv_socket_id_from_shmid(shmid));
int addrlen = sizeof(addr.sun_family) + strlen(&addr.sun_path[1]) + 1;
int recvsock = socket(AF_UNIX, SOCK_STREAM, 0);
if (recvsock == -1) {
DBG ("%s: cannot create UNIX socket: %s", __PRETTY_FUNCTION__, strerror(errno));
return -1;
}
if (connect(recvsock, (struct sockaddr*) &addr, addrlen) != 0) {
DBG("%s: Cannot connect to UNIX socket %s: %s, len %d", __PRETTY_FUNCTION__, addr.sun_path + 1, strerror(errno), addrlen);
close(recvsock);
return -1;
}
if (send(recvsock, &shmid, sizeof(shmid), 0) != sizeof(shmid)) {
DBG ("%s: send() failed on socket %s: %s", __PRETTY_FUNCTION__, addr.sun_path + 1, strerror(errno));
close(recvsock);
return -1;
}
key_t key;
if (read(recvsock, &key, sizeof(key_t)) != sizeof(key_t)) {
DBG("%s: ERROR: failed read", __PRETTY_FUNCTION__);
close(recvsock);
return -1;
}
int descriptor = ancil_recv_fd(recvsock);
if (descriptor < 0) {
DBG("%s: ERROR: ancil_recv_fd() failed on socket %s: %s", __PRETTY_FUNCTION__, addr.sun_path + 1, strerror(errno));
close(recvsock);
return -1;
}
close(recvsock);
int size = ashmem_get_size_region(descriptor);
if (size == 0 || size == -1) {
DBG ("%s: ERROR: ashmem_get_size_region() returned %d on socket %s: %s", __PRETTY_FUNCTION__, size, addr.sun_path + 1, strerror(errno));
return -1;
}
int idx = shmem_amount;
shmem_amount ++;
shmem = realloc(shmem, shmem_amount * sizeof(shmem_t));
shmem[idx].id = shmid;
shmem[idx].descriptor = descriptor;
shmem[idx].size = size;
shmem[idx].addr = NULL;
shmem[idx].markedForDeletion = false;
shmem[idx].key = key;
return idx;
}
/* Get shared memory area identifier. */
int shmget(key_t key, size_t size, int flags)
{
(void) flags;
#ifdef ANDROID_LINUX_SHM
if (syscall_supported) {
if (size > PTRDIFF_MAX) size = SIZE_MAX;
#ifndef SYS_ipc
return syscall(SYS_shmget, key, size, flags);
#else
return syscall(SYS_ipc, IPCOP_shmget, key, size, flag);
#endif
}
#endif
ashv_check_pid();
// Counter wrapping around at 15 bits.
static size_t shmem_counter = 0;
if (!ashv_listening_thread_id) {
int sock = socket(AF_UNIX, SOCK_STREAM, 0);
if (!sock) {
DBG ("%s: cannot create UNIX socket: %s", __PRETTY_FUNCTION__, strerror(errno));
errno = EINVAL;
return -1;
}
int i;
for (i = 0; i < 4096; i++) {
struct sockaddr_un addr;
int len;
memset (&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
ashv_local_socket_id = (getpid() + i) & 0xffff;
sprintf(&addr.sun_path[1], ANDROID_SHMEM_SOCKNAME, ashv_local_socket_id);
len = sizeof(addr.sun_family) + strlen(&addr.sun_path[1]) + 1;
if (bind(sock, (struct sockaddr *)&addr, len) != 0) continue;
DBG("%s: bound UNIX socket %s in pid=%d", __PRETTY_FUNCTION__, addr.sun_path + 1, getpid());
break;
}
if (i == 4096) {
DBG("%s: cannot bind UNIX socket, bailing out", __PRETTY_FUNCTION__);
ashv_local_socket_id = 0;
errno = ENOMEM;
return -1;
}
if (listen(sock, 4) != 0) {
DBG("%s: listen failed", __PRETTY_FUNCTION__);
errno = ENOMEM;
return -1;
}
int* socket_arg = malloc(sizeof(int));
*socket_arg = sock;
pthread_create(&ashv_listening_thread_id, NULL, &ashv_thread_function, socket_arg);
}
int shmid = -1;
pthread_mutex_lock(&mutex);
char symlink_path[256];
if (key != IPC_PRIVATE) {
// (1) Check if symlink exists telling us where to connect.
// (2) If so, try to connect and open.
// (3) If connected and opened, done. If connection refused
// take ownership of the key and create the symlink.
// (4) If no symlink, create it.
sprintf(symlink_path, "%s/ashv_key_%d", _PATH_TMP, key);
char path_buffer[256];
char num_buffer[64];
while (true) {
int path_length = readlink(symlink_path, path_buffer, sizeof(path_buffer) - 1);
if (path_length != -1) {
path_buffer[path_length] = '\0';
int shmid = atoi(path_buffer);
if (shmid != 0) {
int idx = ashv_find_local_index(shmid);
if (idx == -1) {
idx = ashv_read_remote_segment(shmid);
}
if (idx != -1) {
pthread_mutex_unlock(&mutex);
return shmem[idx].id;
}
}
// TODO: Not sure we should try to remove previous owner if e.g.
// there was a tempporary failture to get a soket. Need to
// distinguish between why ashv_read_remote_segment failed.
unlink(symlink_path);
}
// Take ownership.
// TODO: HAndle error (out of resouces, no infinite loop)
if (shmid == -1) {
shmem_counter = (shmem_counter + 1) & 0x7fff;
shmid = ashv_shmid_from_counter(shmem_counter);
sprintf(num_buffer, "%d", shmid);
}
if (symlink(num_buffer, symlink_path) == 0) break;
}
}
int idx = shmem_amount;
char buf[256];
sprintf(buf, ANDROID_SHMEM_SOCKNAME "-%d", ashv_local_socket_id, idx);
shmem_amount++;
if (shmid == -1) {
shmem_counter = (shmem_counter + 1) & 0x7fff;
shmid = ashv_shmid_from_counter(shmem_counter);
}
shmem = realloc(shmem, shmem_amount * sizeof(shmem_t));
size = ROUND_UP(size, getpagesize());
shmem[idx].size = size;
shmem[idx].descriptor = ashmem_create_region(buf, size);
shmem[idx].addr = NULL;
shmem[idx].id = shmid;
shmem[idx].markedForDeletion = false;
shmem[idx].key = key;
if (shmem[idx].descriptor < 0) {
DBG("%s: ashmem_create_region() failed for size %zu: %s", __PRETTY_FUNCTION__, size, strerror(errno));
shmem_amount --;
shmem = realloc(shmem, shmem_amount * sizeof(shmem_t));
pthread_mutex_unlock (&mutex);
return -1;
}
pthread_mutex_unlock(&mutex);
return shmid;
}
/* Attach shared memory segment. */
void* shmat(int shmid, void const* shmaddr, int shmflg)
{
#ifdef ANDROID_LINUX_SHM
if (syscall_supported) {
#ifndef SYS_ipc
return (void *)syscall(SYS_shmat, shmid, shmaddr, shmflg);
#else
unsigned long ret;
ret = syscall(SYS_ipc, IPCOP_shmat, shmid, shmflg, &shmaddr, shmaddr);
return (ret > -(unsigned long)SHMLBA) ? (void *)ret : (void *)shmaddr;
#endif
}
#endif
ashv_check_pid();
int socket_id = ashv_socket_id_from_shmid(shmid);
void *addr;
pthread_mutex_lock(&mutex);
int idx = ashv_find_local_index(shmid);
if (idx == -1 && socket_id != ashv_local_socket_id) {
idx = ashv_read_remote_segment(shmid);
}
if (idx == -1) {
DBG ("%s: shmid %x does not exist", __PRETTY_FUNCTION__, shmid);
pthread_mutex_unlock(&mutex);
errno = EINVAL;
return (void*) -1;
}
if (shmem[idx].addr == NULL) {
shmem[idx].addr = mmap((void*) shmaddr, shmem[idx].size, PROT_READ | (shmflg == 0 ? PROT_WRITE : 0), MAP_SHARED, shmem[idx].descriptor, 0);
if (shmem[idx].addr == MAP_FAILED) {
DBG ("%s: mmap() failed for ID %x FD %d: %s", __PRETTY_FUNCTION__, idx, shmem[idx].descriptor, strerror(errno));
shmem[idx].addr = NULL;
}
}
addr = shmem[idx].addr;
DBG ("%s: mapped addr %p for FD %d ID %d", __PRETTY_FUNCTION__, addr, shmem[idx].descriptor, idx);
pthread_mutex_unlock (&mutex);
return addr ? addr : (void *)-1;
}
/* Detach shared memory segment. */
int shmdt(void const* shmaddr)
{
#ifdef ANDROID_LINUX_SHM
if (syscall_supported) {
#ifndef SYS_ipc
return syscall(SYS_shmdt, shmaddr);
#else
return syscall(SYS_ipc, IPCOP_shmdt, 0, 0, 0, shmaddr);
#endif
}
#endif
ashv_check_pid();
pthread_mutex_lock(&mutex);
for (size_t i = 0; i < shmem_amount; i++) {
if (shmem[i].addr == shmaddr) {
if (munmap(shmem[i].addr, shmem[i].size) != 0) {
DBG("%s: munmap %p failed", __PRETTY_FUNCTION__, shmaddr);
}
shmem[i].addr = NULL;
DBG("%s: unmapped addr %p for FD %d ID %zu shmid %x", __PRETTY_FUNCTION__, shmaddr, shmem[i].descriptor, i, shmem[i].id);
if (shmem[i].markedForDeletion || ashv_socket_id_from_shmid(shmem[i].id) != ashv_local_socket_id) {
DBG ("%s: deleting shmid %x", __PRETTY_FUNCTION__, shmem[i].id);
android_shmem_delete(i);
}
pthread_mutex_unlock(&mutex);
return 0;
}
}
pthread_mutex_unlock(&mutex);
DBG("%s: invalid address %p", __PRETTY_FUNCTION__, shmaddr);
/* Could be a remove segment, do not report an error for that. */
return 0;
}
/* Shared memory control operation. */
int shmctl(int shmid, int cmd, struct shmid_ds *buf)
{
#ifdef ANDROID_LINUX_SHM
if (syscall_supported) {
#ifndef SYS_ipc
return syscall(SYS_shmctl, shmid, cmd, buf);
#else
return syscall(SYS_ipc, IPCOP_shmctl, shmid, cmd, 0, buf, 0);
#endif
}
#endif
ashv_check_pid();
if (cmd == IPC_RMID) {
DBG("%s: IPC_RMID for shmid=%x", __PRETTY_FUNCTION__, shmid);
pthread_mutex_lock(&mutex);
int idx = ashv_find_local_index(shmid);
if (idx == -1) {
DBG("%s: shmid=%x does not exist locally", __PRETTY_FUNCTION__, shmid);
/* We do not rm non-local regions, but do not report an error for that. */
pthread_mutex_unlock(&mutex);
return 0;
}
if (shmem[idx].addr) {
// shmctl(2): The segment will actually be destroyed only
// after the last process detaches it (i.e., when the shm_nattch
// member of the associated structure shmid_ds is zero.
shmem[idx].markedForDeletion = true;
} else {
android_shmem_delete(idx);
}
pthread_mutex_unlock(&mutex);
return 0;
} else if (cmd == IPC_STAT) {
if (!buf) {
DBG ("%s: ERROR: buf == NULL for shmid %x", __PRETTY_FUNCTION__, shmid);
errno = EINVAL;
return -1;
}
pthread_mutex_lock(&mutex);
int idx = ashv_find_local_index(shmid);
if (idx == -1) {
DBG ("%s: ERROR: shmid %x does not exist", __PRETTY_FUNCTION__, shmid);
pthread_mutex_unlock (&mutex);
errno = EINVAL;
return -1;
}
/* Report max permissive mode */
memset(buf, 0, sizeof(struct shmid_ds));
buf->shm_segsz = shmem[idx].size;
buf->shm_nattch = 1;
buf->shm_perm.key = shmem[idx].key;
buf->shm_perm.uid = geteuid();
buf->shm_perm.gid = getegid();
buf->shm_perm.cuid = geteuid();
buf->shm_perm.cgid = getegid();
buf->shm_perm.mode = 0666;
buf->shm_perm.seq = 1;
pthread_mutex_unlock (&mutex);
return 0;
}
DBG("%s: cmd %d not implemented yet!", __PRETTY_FUNCTION__, cmd);
errno = EINVAL;
return -1;
}

View File

@@ -0,0 +1,127 @@
diff --git a/Xtranssock.c b/Xtranssock.c
index b06579c..bb5238b 100644
--- a/Xtranssock.c
+++ b/Xtranssock.c
@@ -200,20 +200,28 @@ static int TRANS(SocketINETClose) (XtransConnInfo ciptr);
#if defined(X11_t)
-#define UNIX_PATH "/tmp/.X11-unix/X"
-#define UNIX_DIR "/tmp/.X11-unix"
+extern char* xtrans_unix_path_x11;
+extern char* xtrans_unix_dir_x11;
+#define UNIX_PATH xtrans_unix_path_x11
+#define UNIX_DIR xtrans_unix_dir_x11
#endif /* X11_t */
#if defined(XIM_t)
-#define UNIX_PATH "/tmp/.XIM-unix/XIM"
-#define UNIX_DIR "/tmp/.XIM-unix"
+extern char* xtrans_unix_path_xim;
+extern char* xtrans_unix_dir_xim;
+#define UNIX_PATH xtrans_unix_path_xim
+#define UNIX_DIR xtrans_unix_dir_xim
#endif /* XIM_t */
#if defined(FS_t) || defined(FONT_t)
-#define UNIX_PATH "/tmp/.font-unix/fs"
-#define UNIX_DIR "/tmp/.font-unix"
+extern char* xtrans_unix_path_fs;
+extern char* xtrans_unix_dir_fs;
+#define UNIX_PATH xtrans_unix_path_fs
+#define UNIX_DIR xtrans_unix_dir_fs
#endif /* FS_t || FONT_t */
#if defined(ICE_t)
-#define UNIX_PATH "/tmp/.ICE-unix/"
-#define UNIX_DIR "/tmp/.ICE-unix"
+extern char* xtrans_unix_path_ice;
+extern char* xtrans_unix_dir_ice;
+#define UNIX_PATH xtrans_unix_path_ice
+#define UNIX_DIR xtrans_unix_dir_ice
#endif /* ICE_t */
diff --git a/Xtransutil.c b/Xtransutil.c
index 63f0fc3..a9620a6 100644
--- a/Xtransutil.c
+++ b/Xtransutil.c
@@ -478,27 +478,6 @@
}
/* Dir doesn't exist. Try to create it */
-#if !defined(WIN32) && !defined(__CYGWIN__)
- /*
- * 'sticky' bit requested: assume application makes
- * certain security implications. If effective user ID
- * is != 0: fail as we may not be able to meet them.
- */
- if (geteuid() != 0) {
- if (mode & 01000) {
- prmsg(1, "mkdir: ERROR: euid != 0,"
- "directory %s will not be created.\n",
- path);
-#ifdef FAIL_HARD
- return -1;
-#endif
- } else {
- prmsg(1, "mkdir: Cannot create %s with root ownership\n",
- path);
- }
- }
-#endif
-
#ifndef WIN32
if (mkdir(path, mode) == 0) {
if (chmod(path, mode)) {
@@ -521,14 +500,9 @@
} else {
if (S_ISDIR(buf.st_mode)) {
- int updateOwner = 0;
int updateMode = 0;
- int updatedOwner = 0;
int updatedMode = 0;
int status = 0;
- /* Check if the directory's ownership is OK. */
- if (buf.st_uid != 0)
- updateOwner = 1;
/*
* Check if the directory's mode is OK. An exact match isn't
@@ -566,7 +540,7 @@
* directory's owner and mode. Otherwise it isn't safe to attempt
* to do this.
*/
- if (updateMode || updateOwner) {
+ if (updateMode) {
int fd = -1;
struct stat fbuf;
if ((fd = open(path, O_RDONLY)) != -1) {
@@ -588,8 +562,6 @@
close(fd);
return -1;
}
- if (updateOwner && fchown(fd, 0, 0) == 0)
- updatedOwner = 1;
if (updateMode && fchmod(fd, mode) == 0)
updatedMode = 1;
close(fd);
@@ -597,20 +569,6 @@
}
#endif
- if (updateOwner && !updatedOwner) {
-#ifdef FAIL_HARD
- if (status & FAIL_IF_NOT_ROOT) {
- prmsg(1, "mkdir: ERROR: Owner of %s must be set to root\n",
- path);
- return -1;
- }
-#endif
-#if !defined(__APPLE_CC__) && !defined(__CYGWIN__)
- prmsg(1, "mkdir: Owner of %s should be set to root\n",
- path);
-#endif
- }
-
if (updateMode && !updatedMode) {
#ifdef FAIL_HARD
if (status & FAIL_IF_NOMODE) {

View File

@@ -0,0 +1,207 @@
#pragma once
#define _DIX_CONFIG_H_ 1
#define HAVE_TYPEOF 1
#define MONOTONIC_CLOCK 1
#undef XSERVER_DTRACE
#define X_BYTE_ORDER X_LITTLE_ENDIAN
#define _GNU_SOURCE 1
#undef HAS_APERTURE_DRV
#define INPUTTHREAD 1
#define HAVE_PTHREAD_SETNAME_NP_WITH_TID 1
#undef HAVE_PTHREAD_SETNAME_NP_WITHOUT_TID
#undef HAVE_LIBBSD
#undef HAVE_SYSTEMD_DAEMON
#undef CONFIG_UDEV
#undef CONFIG_UDEV_KMS
#undef HAVE_DBUS
#undef CONFIG_HAL
#undef SYSTEMD_LOGIND
#undef NEED_DBUS
#undef CONFIG_WSCONS
#define HAVE_XSHMFENCE 1
#undef WITH_LIBDRM
#undef GLAMOR_HAS_EGL_QUERY_DMABUF
#undef GLAMOR_HAS_EGL_QUERY_DRIVER
#define GLXEXT 1
#undef GLAMOR
#undef GLAMOR_HAS_GBM
#undef GLAMOR_HAS_GBM_LINEAR
#undef GBM_BO_WITH_MODIFIERS
#undef GBM_BO_FD_FOR_PLANE
#define SERVER_MISC_CONFIG_PATH "/usr/lib/xorg"
#define PROJECTROOT "/usr"
#define SYSCONFDIR "/usr/etc"
#define SUID_WRAPPER_DIR "/usr/libexec"
#define COMPILEDDEFAULTFONTPATH "/usr/share/fonts/X11/misc,/usr/share/fonts/X11/TTF,/usr/share/fonts/X11/OTF,/usr/share/fonts/X11/Type1,/usr/share/fonts/X11/100dpi,/usr/share/fonts/X11/75dpi"
#define HASXDMAUTH 1
#define SECURE_RPC 1
#define HAVE_DLFCN_H 1
#define HAVE_EXECINFO_H 1
#define HAVE_FNMATCH_H 1
#define HAVE_LINUX_AGPGART_H 1
#define HAVE_STRINGS_H 1
#define HAVE_SYS_AGPGART_H 1
#define HAVE_SYS_UN_H 1
#define HAVE_SYS_UTSNAME_H 1
#define HAVE_SYS_SYSMACROS_H 1
#define HAVE_ARC4RANDOM_BUF 1
#undef HAVE_BACKTRACE
#undef HAVE_LIBUNWIND
#undef HAVE_PSTACK
#define HAVE_CBRT 1
#define HAVE_EPOLL_CREATE1 1
#define HAVE_GETUID 1
#define HAVE_GETEUID 1
#undef HAVE_ISASTREAM
#undef HAVE_ISSETUGID
#define HAVE_GETIFADDRS 1
#undef HAVE_GETPEEREID
#undef HAVE_GETPEERUCRED
#define HAVE_GETPROGNAME 1
#undef HAVE_GETZONEID
#define HAVE_MEMFD_CREATE 1
#define HAVE_MKOSTEMP 1
#define HAVE_MMAP 1
#undef HAVE_OPEN_DEVICE
#define HAVE_POLL 1
#undef HAVE_POLLSET_CREATE
#define HAVE_POSIX_FALLOCATE 1
#undef HAVE_PORT_CREATE
#undef HAVE_REALLOCARRAY
#define HAVE_SETEUID 1
#define HAVE_SETITIMER 1
#undef HAVE_SHMCTL64
#define HAVE_SIGACTION 1
#define HAVE_SIGPROCMASK 1
#define HAVE_STRCASECMP 1
#define HAVE_STRCASESTR 1
#define HAVE_STRLCAT 1
#define HAVE_STRLCPY 1
#define HAVE_STRNCASECMP 1
#define HAVE_STRNDUP 1
#undef HAVE_TIMINGSAFE_MEMCMP
#define HAVE_VASPRINTF 1
#define HAVE_VSNPRINTF 1
#undef HAVE_WALKCONTEXT
#define BUSFAULT 1
#define _XTYPEDEF_POINTER 1
#define _XITYPEDEF_POINTER 1
#define LISTEN_UNIX
#define LISTEN_LOCAL
#define XTRANS_SEND_FDS 1
#define TCPCONN 1
#define UNIXCONN 1
#define IPv6 1
#define BIGREQS 1
#define COMPOSITE 1
#define DAMAGE 1
#define DBE 1
#define DGA 1
#define DPMSExtension 1
#define DRI2 1
#define DRI3 1
#define HAS_SHM 1
#define MITSHM 1
#define PANORAMIX 1
#define PRESENT 1
#define RANDR 1
#define RES 1
#define RENDER 1
#define SCREENSAVER 1
#define SHAPE 1
#define XACE 1
#define XCMISC 1
#undef XCSECURITY
#define XDMCP 1
#undef XF86BIGFONT
#define XF86DRI 1
#define XF86VIDMODE 1
#define XFIXES 1
#define XFreeXDGA 1
#define XINERAMA 1
#define XINPUT 1
#define XRECORD 1
#undef XSELINUX
#define XSYNC 1
#define XTEST 1
#define XV 1
#define XvExtension 1
#define XvMCExtension 1
/* Use libmd SHA1 functions */
#define HAVE_SHA1_IN_LIBMD 1
#define HAVE_APM 1
#define HAVE_ACPI 1
#undef DDXOSVERRORF
#undef DDXBEFORERESET
#undef DEBUG
#define XVENDORNAME "The X.Org Foundation"
#define XVENDORNAMESHORT "X.Org"
#define __VENDORDWEBSUPPORT__ "http://wiki.x.org"
#define BUILDERADDR "xorg@lists.freedesktop.org"
#define BUILDERSTRING ""
#undef SVR4
#define XKB_DFLT_RULES "evdev"
#undef XORGSERVER
#define XCONFIGFILE "xorg.conf"
#define __XSERVERNAME__ "Xorg"
#define WITH_VGAHW 1
#undef CSRG_BASED
#undef PCCONS_SUPPORT
#undef PCVT_SUPPORT
#undef SYSCONS_SUPPORT
#undef WSCONS_SUPPORT
#undef XSERVER_LIBPCIACCESS
#undef XSERVER_PLATFORM_BUS
#ifdef ANDROID
typedef long long quad_t;
typedef unsigned long long u_quad_t;
#include <unistd.h>
__attribute__((unused))
static int memfd_create(const char *name, unsigned int flags) {
#ifndef __NR_memfd_create
#if defined __i386__
#define __NR_memfd_create 356
#elif defined __x86_64__
#define __NR_memfd_create 319
#elif defined __arm__
#define __NR_memfd_create 385
#elif defined __aarch64__
#define __NR_memfd_create 279
#endif
#endif
#ifdef __NR_memfd_create
return syscall(__NR_memfd_create, name, flags); // NOLINT(cppcoreguidelines-narrowing-conversions)
#else
errno = ENOSYS;
return -1;
#endif
}
#endif
#ifdef __ANDROID__
#define CHECK_EUID 0
extern int execl_xkbcomp(const char * path, const char * arg, ...);
#define setgid(a) 0
#define setuid(a) 0
#endif

View File

@@ -0,0 +1,170 @@
diff --git a/src/gen_dispatch.py b/src/gen_dispatch.py
index 3daad84..b27931d 100755
--- a/src/gen_dispatch.py
+++ b/src/gen_dispatch.py
@@ -222,7 +222,7 @@ class Generator(object):
for child in t:
if child.tag == 'apientry':
- self.typedefs += 'APIENTRY'
+ self.typedefs += ''
if child.text:
self.typedefs += child.text
if child.tail:
@@ -462,13 +462,14 @@ class Generator(object):
def write_function_ptr_typedefs(self):
for func in self.sorted_functions:
- self.outln('typedef {0} (GLAPIENTRY *{1})({2});'.format(func.ret_type,
+ self.outln('typedef {0} (*{1})({2});'.format(func.ret_type,
func.ptr_type,
func.args_decl))
def write_header_header(self, out_file):
self.close()
self.out_file = open(out_file, 'w')
+ self.out_file.truncate(0)
self.outln('/* GL dispatch header.')
self.outln(' * This is code-generated from the GL API XML files from Khronos.')
@@ -482,7 +483,7 @@ class Generator(object):
self.outln('#include <stddef.h>')
self.outln('')
- def write_header(self, out_file):
+ def write_header2(self, out_file):
self.write_header_header(out_file)
self.outln('#include "epoxy/common.h"')
@@ -858,6 +859,82 @@ class Generator(object):
for func in self.sorted_functions:
self.write_function_pointer(func)
+ def write_header(self, out_file):
+ self.close()
+ self.out_file = open(out_file, 'w')
+ self.out_file.truncate(0)
+
+ self.outln('/* GL dispatch header.')
+ self.outln(' * This is code-generated from the GL API XML files from Khronos.')
+ self.write_copyright_comment_body()
+ self.outln(' */')
+ self.outln('')
+
+ self.outln('#pragma once')
+
+ self.outln('#include <inttypes.h>')
+ self.outln('#include <stddef.h>')
+ self.outln('')
+
+ # Add some ridiculous inttypes.h redefinitions that are
+ # from khrplatform.h and not included in the XML. We
+ # don't directly include khrplatform.h because it's not
+ # present on many systems, and coming up with #ifdefs to
+ # decide when it's not present would be hard.
+ self.outln('#define __khrplatform_h_ 1')
+ self.outln('typedef int8_t khronos_int8_t;')
+ self.outln('typedef int16_t khronos_int16_t;')
+ self.outln('typedef int32_t khronos_int32_t;')
+ self.outln('typedef int64_t khronos_int64_t;')
+ self.outln('typedef uint8_t khronos_uint8_t;')
+ self.outln('typedef uint16_t khronos_uint16_t;')
+ self.outln('typedef uint32_t khronos_uint32_t;')
+ self.outln('typedef uint64_t khronos_uint64_t;')
+ self.outln('typedef float khronos_float_t;')
+ self.outln('#ifdef _WIN64')
+ self.outln('typedef signed long long int khronos_intptr_t;')
+ self.outln('typedef unsigned long long int khronos_uintptr_t;')
+ self.outln('typedef signed long long int khronos_ssize_t;')
+ self.outln('typedef unsigned long long int khronos_usize_t;')
+ self.outln('#else')
+ self.outln('typedef signed long int khronos_intptr_t;')
+ self.outln('typedef unsigned long int khronos_uintptr_t;')
+ self.outln('typedef signed long int khronos_ssize_t;')
+ self.outln('typedef unsigned long int khronos_usize_t;')
+ self.outln('#endif')
+ self.outln('typedef uint64_t khronos_utime_nanoseconds_t;')
+ self.outln('typedef int64_t khronos_stime_nanoseconds_t;')
+ self.outln('#define KHRONOS_MAX_ENUM 0x7FFFFFFF')
+ self.outln('typedef enum {')
+ self.outln(' KHRONOS_FALSE = 0,')
+ self.outln(' KHRONOS_TRUE = 1,')
+ self.outln(' KHRONOS_BOOLEAN_ENUM_FORCE_SIZE = KHRONOS_MAX_ENUM')
+ self.outln('} khronos_boolean_enum_t;')
+
+ if self.target == "glx":
+ self.outln('#include <X11/Xlib.h>')
+ self.outln('#include <X11/Xutil.h>')
+
+ self.out(self.typedefs)
+ self.outln('')
+ self.write_enums()
+ self.outln('')
+ self.write_function_ptr_typedefs()
+
+ for func in self.sorted_functions:
+ ret = ""
+ if func.ret_type in ("void"):
+ ret = ""
+ elif func.ret_type in ("GLhandleARB", "GLsync", "const GLubyte *", "GLVULKANPROCNV", "void *"):
+ ret = "NULL"
+ elif func.ret_type in ("GLuint", "GLboolean", "GLenum", "GLint", "GLfloat", "GLushort", \
+ "GLintptr", "GLbitfield", "GLvdpauSurfaceNV", "GLsizei", "GLuint64"):
+ ret = "0"
+ else:
+ raise ValueError('Wrong return type "' + func.ret_type + '"')
+ self.outln('#define {0}(...) {1}'.format(func.name, ret))
+
+
def close(self):
if self.out_file:
self.out_file.close()
@@ -869,10 +946,6 @@ argparser.add_argument('files', metavar='file.xml', nargs='+', help='GL API XML
argparser.add_argument('--outputdir', metavar='dir', required=False, help='Destination directory for files (default to current dir)')
argparser.add_argument('--includedir', metavar='dir', required=False, help='Destination directory for headers')
argparser.add_argument('--srcdir', metavar='dir', required=False, help='Destination directory for source')
-argparser.add_argument('--source', dest='source', action='store_true', required=False, help='Generate the source file')
-argparser.add_argument('--no-source', dest='source', action='store_false', required=False, help='Do not generate the source file')
-argparser.add_argument('--header', dest='header', action='store_true', required=False, help='Generate the header file')
-argparser.add_argument('--no-header', dest='header', action='store_false', required=False, help='Do not generate the header file')
args = argparser.parse_args()
if args.outputdir:
@@ -890,13 +963,6 @@ if args.srcdir:
else:
srcdir = outputdir
-build_source = args.source
-build_header = args.header
-
-if not build_source and not build_header:
- build_source = True
- build_header = True
-
for f in args.files:
name = os.path.basename(f).split('.xml')[0]
generator = Generator(name)
@@ -911,22 +977,8 @@ for f in args.files:
generator.sort_functions()
generator.resolve_aliases()
- generator.fixup_bootstrap_function('glGetString',
- 'epoxy_get_bootstrap_proc_address({0})')
- generator.fixup_bootstrap_function('glGetIntegerv',
- 'epoxy_get_bootstrap_proc_address({0})')
-
- # While this is technically exposed as a GLX extension, it's
- # required to be present as a public symbol by the Linux OpenGL
- # ABI.
- generator.fixup_bootstrap_function('glXGetProcAddress',
- 'epoxy_glx_dlsym({0})')
generator.prepare_provider_enum()
-
- if build_header:
- generator.write_header(os.path.join(includedir, name + '_generated.h'))
- if build_source:
- generator.write_source(os.path.join(srcdir, name + '_generated_dispatch.c'))
+ generator.write_header(os.path.join(includedir, name + '.h'))
generator.close()

View File

@@ -0,0 +1,35 @@
diff -u -r ../pixman-0.32.6/pixman/pixman-arm.c ./pixman/pixman-arm.c
--- ../pixman-0.32.6/pixman/pixman-arm.c 2013-11-17 09:43:18.000000000 +0100
+++ ./pixman/pixman-arm.c 2014-08-05 12:54:39.252322492 +0200
@@ -96,30 +96,10 @@
#elif defined(__ANDROID__) || defined(ANDROID) /* Android */
-#include <cpu-features.h>
-
static arm_cpu_features_t
detect_cpu_features (void)
{
- arm_cpu_features_t features = 0;
- AndroidCpuFamily cpu_family;
- uint64_t cpu_features;
-
- cpu_family = android_getCpuFamily();
- cpu_features = android_getCpuFeatures();
-
- if (cpu_family == ANDROID_CPU_FAMILY_ARM)
- {
- if (cpu_features & ANDROID_CPU_ARM_FEATURE_ARMv7)
- features |= ARM_V7;
-
- if (cpu_features & ANDROID_CPU_ARM_FEATURE_VFPv3)
- features |= ARM_VFP;
-
- if (cpu_features & ANDROID_CPU_ARM_FEATURE_NEON)
- features |= ARM_NEON;
- }
-
+ arm_cpu_features_t features = (ARM_V7 | ARM_VFP | ARM_NEON);
return features;
}

View File

@@ -0,0 +1,58 @@
diff --git a/src/Quarks.c b/src/Quarks.c
index 0dd91968..dbaf5086 100644
--- a/src/Quarks.c
+++ b/src/Quarks.c
@@ -105,6 +105,11 @@ static XrmQuark nextUniq = -1; /* next quark from XrmUniqueQuark */
#define CLEARPERM(q) BYTEREF(q) &= ~(1 << ((q) & 7))
#endif
+#undef _XLockMutex
+#undef _XUnlockMutex
+#define _XLockMutex(m)
+#define _XUnlockMutex(m)
+
/* Permanent memory allocation */
#define WALIGN sizeof(unsigned long)
diff --git a/src/Xrm.c b/src/Xrm.c
index a8ebf883..d716fdb0 100644
--- a/src/Xrm.c
+++ b/src/Xrm.c
@@ -301,6 +301,13 @@ typedef unsigned char XrmBits;
#define is_simple(bits) ((bits) & (NORMAL|BSLASH))
#define is_special(bits) ((bits) & (ENDOF|BSLASH))
+#undef _XLockMutex
+#undef _XUnlockMutex
+#undef _XCreateMutex
+#define _XLockMutex(m)
+#define _XUnlockMutex(m)
+#define _XCreateMutex(m)
+
/* parsing types */
static XrmBits const xrmtypes[256] = {
EOS,0,0,0,0,0,0,0,
@@ -500,9 +507,7 @@ static XrmDatabase NewDatabase(void)
_XCreateMutex(&db->linfo);
db->table = (NTable)NULL;
db->mbstate = (XPointer)NULL;
- db->methods = _XrmInitParseInfo(&db->mbstate);
- if (!db->methods)
- db->methods = &mb_methods;
+ db->methods = &mb_methods;
}
return db;
}
--- a/include/X11/Xlocale.h
+++ b/include/X11/Xlocale.h
@@ -32,6 +32,9 @@ from The Open Group.
#include <X11/Xfuncproto.h>
#include <X11/Xosdefs.h>
+struct __locale_t;
+typedef struct __locale_t* locale_t;
+
#include <locale.h>
#endif /* _X11_XLOCALE_H_ */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,27 @@
diff --git a/src/xkbatom.c b/src/xkbatom.c
index 564cc83..723e6da 100644
--- a/src/xkbatom.c
+++ b/src/xkbatom.c
@@ -202,9 +202,7 @@ XkbAtomGetString(Display *dpy, Atom atm)
{
if (atm == None)
return NULL;
- if (dpy == NULL)
- return _XkbNameForAtom(atm);
- return XGetAtomName(dpy, atm);
+ return _XkbNameForAtom(atm);
}
/***====================================================================***/
@@ -214,10 +212,7 @@ XkbInternAtom(Display *dpy, const char *name, Bool onlyIfExists)
{
if (name == NULL)
return None;
- if (dpy == NULL) {
- return _XkbMakeAtom(name, strlen(name), (!onlyIfExists));
- }
- return XInternAtom(dpy, name, onlyIfExists);
+ return _XkbMakeAtom(name, strlen(name), (!onlyIfExists));
}
/***====================================================================***/

View File

@@ -0,0 +1,208 @@
diff --git a/Xext/shm.c b/Xext/shm.c
index 071bd1a41..011969283 100644
--- a/Xext/shm.c
+++ b/Xext/shm.c
@@ -193,6 +193,10 @@ CheckForShmSyscall(void)
#endif
+const DevPrivateKey ShmGetDevPrivateKeyRec(void) {
+ return shmPixmapPrivateKey;
+}
+
static Bool
ShmCloseScreen(ScreenPtr pScreen)
{
diff --git a/Xext/shmint.h b/Xext/shmint.h
index 9dadea756..e4e6f4db6 100644
--- a/Xext/shmint.h
+++ b/Xext/shmint.h
@@ -80,6 +80,8 @@ typedef struct _ShmDesc {
#define SHMDESC_IS_FD(shmdesc) (0)
#endif
+extern const DevPrivateKey ShmGetDevPrivateKeyRec(void);
+
extern _X_EXPORT void
ShmRegisterFuncs(ScreenPtr pScreen, ShmFuncsPtr funcs);
diff --git a/dix/main.c b/dix/main.c
index bfc8addbe..56fb30b63 100644
--- a/dix/main.c
+++ b/dix/main.c
@@ -266,6 +266,7 @@ dix_main(int argc, char *argv[], char *envp[])
}
NotifyParentProcess();
+ ddxReady();
InputThreadInit();
diff --git a/include/os.h b/include/os.h
index bb3348b18..1a5400717 100644
--- a/include/os.h
+++ b/include/os.h
@@ -560,6 +560,8 @@ enum ExitCode {
extern _X_EXPORT void
ddxGiveUp(enum ExitCode error);
extern _X_EXPORT void
+ddxReady(void);
+extern _X_EXPORT void
ddxInputThreadInit(void);
extern _X_EXPORT int
TimeSinceLastInputEvent(void);
diff --git a/include/xkbfile.h b/include/xkbfile.h
index f93d31ab0..f65338ac4 100644
--- a/include/xkbfile.h
+++ b/include/xkbfile.h
@@ -79,6 +79,36 @@ typedef void (*XkbFileAddOnFunc) (FILE * /* file */ ,
/***====================================================================***/
+#define XkbInternAtom XXkbInternAtom
+#define XkbAtomText XXkbAtomText
+#define XkbStringText XXkbStringText
+#define XkbVModIndexText XXkbVModIndexText
+#define XkbVModMaskText XXkbVModMaskText
+#define XkbModMaskText XXkbModMaskText
+#define XkbModIndexText XXkbModIndexText
+#define XkbConfigText XXkbConfigText
+#define XkbKeysymText XXkbKeysymText
+#define XkbKeyNameText XXkbKeyNameText
+#define XkbSIMatchText XXkbSIMatchText
+#define XkbIMWhichStateMaskText XXkbIMWhichStateMaskText
+#define XkbControlsMaskText XXkbControlsMaskText
+#define XkbGeomFPText XXkbGeomFPText
+#define XkbDoodadTypeText XXkbDoodadTypeText
+#define XkbActionTypeText XXkbActionTypeText
+#define XkbActionText XXkbActionText
+#define XkbBehaviorText XXkbBehaviorText
+#define XkbIndentText XXkbIndentText
+#define XkbWriteXKBKeycodes XXkbWriteXKBKeycodes
+#define XkbWriteXKBKeyTypes XXkbWriteXKBKeyTypes
+#define XkbWriteXKBCompatMap XXkbWriteXKBCompatMap
+#define XkbWriteXKBSymbols XXkbWriteXKBSymbols
+#define XkbWriteXKBGeometry XXkbWriteXKBGeometry
+#define XkbWriteXKBKeymapForNames XXkbWriteXKBKeymapForNames
+#define XkbFindKeycodeByName XXkbFindKeycodeByName
+#define XkbConvertGetByNameComponents XXkbConvertGetByNameComponents
+#define XkbNameMatchesPattern XXkbNameMatchesPattern
+#define _XkbKSCheckCase _XXkbKSCheckCase
+
_XFUNCPROTOBEGIN
extern _X_EXPORT char *XkbIndentText(unsigned /* size */
diff --git a/os/osinit.c b/os/osinit.c
index 8575319ff..06c44a416 100644
--- a/os/osinit.c
+++ b/os/osinit.c
@@ -170,11 +170,11 @@ OsInit(void)
#endif
if (!been_here) {
-#if !defined(WIN32) || defined(__CYGWIN__)
+#if !defined(WIN32) || defined(__CYGWIN__) || !defined(__ANDROID__)
struct sigaction act, oact;
int i;
- int siglist[] = { SIGSEGV, SIGQUIT, SIGILL, SIGFPE, SIGBUS,
+ int siglist[] = { SIGQUIT, SIGILL, SIGFPE, SIGBUS,
SIGABRT,
SIGSYS,
SIGXCPU,
diff --git a/os/utils.c b/os/utils.c
index 92a66e81a..d2ca69684 100644
--- a/os/utils.c
+++ b/os/utils.c
@@ -212,6 +212,8 @@ OsSignal(int sig, OsSigHandlerPtr handler)
{
#if defined(WIN32) && !defined(__CYGWIN__)
return signal(sig, handler);
+#elif defined(__ANDROID__)
+ return SIG_DFL;
#else
struct sigaction act, oact;
@@ -232,7 +234,7 @@ OsSignal(int sig, OsSigHandlerPtr handler)
* server at a time. This keeps the servers from stomping on each other
* if the user forgets to give them different display numbers.
*/
-#define LOCK_DIR "/tmp"
+#define LOCK_DIR (getenv("TMPDIR") ?: "/tmp")
#define LOCK_TMP_PREFIX "/.tX"
#define LOCK_PREFIX "/.X"
#define LOCK_SUFFIX "-lock"
@@ -324,7 +326,7 @@ LockServer(void)
i = 0;
haslock = 0;
while ((!haslock) && (i++ < 3)) {
- haslock = (link(tmp, LockFile) == 0);
+ haslock = (rename(tmp, LockFile) == 0);
if (haslock) {
/*
* We're done.
@@ -1412,6 +1414,10 @@ static struct pid {
int pid;
} *pidlist;
+extern char* xkbcomp_argv[];
+extern int xkbcomp_argc;
+int xkbcomp_main(int argc, char *argv[]);
+
void *
Popen(const char *command, const char *type)
{
@@ -1475,8 +1481,11 @@ Popen(const char *command, const char *type)
}
close(pdes[1]);
}
- execl("/bin/sh", "sh", "-c", command, (char *) NULL);
- _exit(127);
+
+ for(int j=1; j<= SIGUNUSED; j++)
+ signal(j, SIG_DFL);
+
+ _exit(xkbcomp_main(xkbcomp_argc, xkbcomp_argv));
}
/* Avoid EINTR during stdio calls */
diff --git a/xkb/ddxLoad.c b/xkb/ddxLoad.c
index f9b7b06d9..f4b2aeddc 100644
--- a/xkb/ddxLoad.c
+++ b/xkb/ddxLoad.c
@@ -56,6 +56,9 @@ THE USE OR PERFORMANCE OF THIS SOFTWARE.
#define PATHSEPARATOR "/"
#endif
+char* xkbcomp_argv[16] = {0};
+int xkbcomp_argc = 0;
+
static unsigned
LoadXKM(unsigned want, unsigned need, const char *keymap, XkbDescPtr *xkbRtrn);
@@ -152,6 +155,25 @@ RunXkbComp(xkbcomp_buffer_callback callback, void *userdata)
xkm_output_dir, keymap) == -1)
buf = NULL;
+ char buf2[256];
+ char buf3[256];
+ sprintf(buf2, "-R%s", XkbBaseDirectory);
+ sprintf(buf3, "%s%s.xkm", xkm_output_dir, keymap);
+ xkbcomp_argv[0] = "xkbcomp";
+ xkbcomp_argv[1] = "-w";
+ xkbcomp_argv[2] = "1";
+ xkbcomp_argv[3] = buf2;
+ xkbcomp_argv[4] = "-xkm";
+ xkbcomp_argv[5] = (char*) xkmfile;
+ xkbcomp_argv[6] = "-em1";
+ xkbcomp_argv[7] = PRE_ERROR_MSG;
+ xkbcomp_argv[8] = "-emp";
+ xkbcomp_argv[9] = ERROR_PREFIX;
+ xkbcomp_argv[10] = "-eml";
+ xkbcomp_argv[11] = POST_ERROR_MSG1;
+ xkbcomp_argv[12] = buf3;
+ xkbcomp_argc = 13;
+
free(xkbbasedirflag);
if (!buf) {

View File

@@ -0,0 +1,5 @@
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/Xau")
add_library(Xau STATIC "libxau/AuDispose.c" "libxau/AuRead.c")
target_include_directories(Xau PUBLIC "libxau/include")
target_compile_options(Xdmcp PRIVATE ${common_compile_options} "-D_GNU_SOURCE=1" "-DHAVE_EXPLICIT_BZERO" "-fPIC")
target_link_libraries(Xau xorgproto)

View File

@@ -0,0 +1,5 @@
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/Xdmcp")
add_library(Xdmcp STATIC "libxdmcp/Array.c" "libxdmcp/Fill.c" "libxdmcp/Flush.c" "libxdmcp/Key.c" "libxdmcp/Read.c" "libxdmcp/Unwrap.c" "libxdmcp/Wrap.c" "libxdmcp/Wraphelp.c" "libxdmcp/Write.c")
target_compile_options(Xdmcp PRIVATE "-D_GNU_SOURCE=1" "-DHASXDMAUTH=1" "-DHAVE_ARC4RANDOM_BUF=1" "-DHAVE_GETENTROPY=1" "-DHAVE_LRAND48=1" "-DHAVE_SRAND48=1" "-DHAVE_SYS_RANDOM_H=1" ${common_compile_options})
target_include_directories(Xdmcp PUBLIC "libxdmcp/include" "${CMAKE_CURRENT_BINARY_DIR}/Xdmcp")
target_link_libraries(Xdmcp PRIVATE xorgproto)

View File

@@ -0,0 +1,70 @@
add_library(Xfont2 STATIC
"libxfont/src/stubs/atom.c"
"libxfont/src/stubs/libxfontstubs.c"
"libxfont/src/util/fontaccel.c"
"libxfont/src/util/fontnames.c"
"libxfont/src/util/fontutil.c"
"libxfont/src/util/fontxlfd.c"
"libxfont/src/util/format.c"
"libxfont/src/util/miscutil.c"
"libxfont/src/util/patcache.c"
"libxfont/src/util/private.c"
"libxfont/src/util/utilbitmap.c"
"libxfont/src/util/reallocarray.c"
"libxfont/src/fontfile/bitsource.c"
"libxfont/src/fontfile/bufio.c"
"libxfont/src/fontfile/decompress.c"
"libxfont/src/fontfile/defaults.c"
"libxfont/src/fontfile/dirfile.c"
"libxfont/src/fontfile/fileio.c"
"libxfont/src/fontfile/filewr.c"
"libxfont/src/fontfile/fontdir.c"
"libxfont/src/fontfile/fontencc.c"
"libxfont/src/fontfile/fontfile.c"
"libxfont/src/fontfile/fontscale.c"
"libxfont/src/fontfile/gunzip.c"
"libxfont/src/fontfile/register.c"
"libxfont/src/fontfile/renderers.c"
"libxfont/src/fontfile/catalogue.c"
"libxfont/src/bitmap/bitmap.c"
"libxfont/src/bitmap/bitmapfunc.c"
"libxfont/src/bitmap/bitmaputil.c"
"libxfont/src/bitmap/bitscale.c"
"libxfont/src/bitmap/fontink.c"
"libxfont/src/bitmap/bdfread.c"
"libxfont/src/bitmap/bdfutils.c"
"libxfont/src/bitmap/pcfread.c"
"libxfont/src/bitmap/pcfwrite.c"
"libxfont/src/builtins/dir.c"
"libxfont/src/builtins/file.c"
"libxfont/src/builtins/fonts.c"
"libxfont/src/builtins/fpe.c"
"libxfont/src/builtins/render.c")
target_compile_options(Xfont2 PRIVATE
${common_compile_options}
"-fvisibility=hidden"
"-DHAVE_ERR_H"
"-DHAVE_STDINT_H=1"
"-DHAVE_READLINK"
"-UHAVE_REALLOCARRAY"
"-DHAVE_REALPATH"
"-DHAVE_STRLCPY"
"-DXFONT_BDFFORMAT=1"
"-DXFONT_BITMAP=1"
"-UXFONT_FREETYPE"
"-DXFONT_PCFFORMAT=1"
"-UXFONT_SNFFORMAT"
"-UX_BZIP2_FONT_COMPRESSION"
"-DX_GZIP_FONT_COMPRESSION=1"
"-D_GNU_SOURCE=1"
"-D_DEFAULT_SOURCE=1"
"-D_BSD_SOURCE=1"
"-DHAS_FCHOWN"
"-DHAS_STICKY_DIR_BIT"
"-D_XOPEN_SOURCE"
"-DNOFILES_MAX=512")
target_include_directories(Xfont2 PRIVATE "libxfont" "libxfont/include" "libfontenc/include")
target_link_libraries(Xfont2 PUBLIC xorgproto)

View File

@@ -0,0 +1,4 @@
add_library(fontenc STATIC "libfontenc/src/fontenc.c" "libfontenc/src/encparse.c" "libfontenc/src/reallocarray.c")
target_include_directories(fontenc PUBLIC "libfontenc/include")
target_link_libraries(fontenc PUBLIC xorgproto)
target_compile_options(fontenc PRIVATE "-DFONT_ENCODINGS_DIRECTORY=\"/\"")

View File

@@ -0,0 +1,193 @@
file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/sha1.h" CONTENT "
/*
* SHA-1 in C
* By Steve Reid <steve@edmweb.com>
* 100% Public Domain
*/
#ifndef _SHA1_H
#define _SHA1_H
#include <sys/types.h>
#include <stdint.h>
#define SHA1_BLOCK_LENGTH 64
#define SHA1_DIGEST_LENGTH 20
typedef struct {
uint32_t state[5];
uint64_t count;
uint8_t buffer[SHA1_BLOCK_LENGTH];
} SHA1_CTX;
void SHA1Init(SHA1_CTX *);
void SHA1Pad(SHA1_CTX *);
void SHA1Transform(uint32_t [5], const uint8_t [SHA1_BLOCK_LENGTH]);
void SHA1Update(SHA1_CTX *, const uint8_t *, size_t);
void SHA1Final(uint8_t [SHA1_DIGEST_LENGTH], SHA1_CTX *);
#endif /* _SHA1_H */
")
file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/libmd/sha1.c" CONTENT "
/*
* SHA-1 in C
* By Steve Reid <steve@edmweb.com>
* 100% Public Domain
*/
#include <string.h>
#include <sha1.h>
#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
/*
* blk0() and blk() perform the initial expand.
* I got the idea of expanding during the round function from SSLeay
*/
#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) |(rol(block->l[i],8)&0x00FF00FF))
#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] ^block->l[(i+2)&15]^block->l[i&15],1))
/*
* (R0+R1), R2, R3, R4 are the different operations (rounds) used in SHA1
*/
#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
typedef union {
uint8_t c[64];
uint32_t l[16];
} CHAR64LONG16;
/*
* Hash a single 512-bit block. This is the core of the algorithm.
*/
void
SHA1Transform(uint32_t state[5], const uint8_t buffer[SHA1_BLOCK_LENGTH])
{
uint32_t a, b, c, d, e;
uint8_t workspace[SHA1_BLOCK_LENGTH];
CHAR64LONG16 *block = (CHAR64LONG16 *)workspace;
(void)memcpy(block, buffer, SHA1_BLOCK_LENGTH);
/* Copy context->state[] to working vars */
a = state[0];
b = state[1];
c = state[2];
d = state[3];
e = state[4];
/* 4 rounds of 20 operations each. Loop unrolled. */
R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
/* Add the working vars back into context.state[] */
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
state[4] += e;
/* Wipe variables */
a = b = c = d = e = 0;
}
/*
* SHA1Init - Initialize new context
*/
void
SHA1Init(SHA1_CTX *context)
{
/* SHA1 initialization constants */
context->count = 0;
context->state[0] = 0x67452301;
context->state[1] = 0xEFCDAB89;
context->state[2] = 0x98BADCFE;
context->state[3] = 0x10325476;
context->state[4] = 0xC3D2E1F0;
}
/*
* Run your data through this.
*/
void
SHA1Update(SHA1_CTX *context, const uint8_t *data, size_t len)
{
size_t i, j;
j = (size_t)((context->count >> 3) & 63);
context->count += (len << 3);
if ((j + len) > 63) {
(void)memcpy(&context->buffer[j], data, (i = 64-j));
SHA1Transform(context->state, context->buffer);
for ( ; i + 63 < len; i += 64)
SHA1Transform(context->state, (uint8_t *)&data[i]);
j = 0;
} else {
i = 0;
}
(void)memcpy(&context->buffer[j], &data[i], len - i);
}
/*
* Add padding and return the message digest.
*/
void
SHA1Pad(SHA1_CTX *context)
{
uint8_t finalcount[8];
unsigned int i;
for (i = 0; i < 8; i++)
finalcount[i] = (uint8_t)((context->count >> ((7 - (i & 7)) * 8)) & 255); /* Endian independent */
SHA1Update(context, (uint8_t *)\"\\200\", 1);
while ((context->count & 504) != 448)
SHA1Update(context, (uint8_t *)\"\\0\", 1);
SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */
}
void
SHA1Final(uint8_t digest[SHA1_DIGEST_LENGTH], SHA1_CTX *context)
{
unsigned int i;
SHA1Pad(context);
if (digest) {
for (i = 0; i < SHA1_DIGEST_LENGTH; i++) {
digest[i] = (uint8_t)
((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
}
memset(context, 0, sizeof(*context));
}
}
")
add_library(md STATIC "${CMAKE_CURRENT_BINARY_DIR}/libmd/sha1.c")
target_include_directories(md PUBLIC "${CMAKE_CURRENT_BINARY_DIR}")

View File

@@ -0,0 +1,91 @@
file(GENERATE
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/pixman-config.h"
CONTENT "")
file(GENERATE
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/pixman-version.h"
CONTENT "
#pragma once
#ifndef PIXMAN_H__
# error pixman-version.h should only be included by pixman.h
#endif
#define PIXMAN_VERSION_MAJOR 0
#define PIXMAN_VERSION_MINOR 43
#define PIXMAN_VERSION_MICRO 4
#define PIXMAN_VERSION_STRING \"0.43.4\"
#define PIXMAN_VERSION 4304
#ifndef PIXMAN_API
# define PIXMAN_API
#endif
")
check_type_size("long" SIZEOF_LONG)
set(PIXMAN_SRC
pixman/pixman/pixman.c
pixman/pixman/pixman-access.c
pixman/pixman/pixman-access-accessors.c
pixman/pixman/pixman-bits-image.c
pixman/pixman/pixman-combine32.c
pixman/pixman/pixman-combine-float.c
pixman/pixman/pixman-conical-gradient.c
pixman/pixman/pixman-filter.c
pixman/pixman/pixman-x86.c
pixman/pixman/pixman-mips.c
pixman/pixman/pixman-arm.c
pixman/pixman/pixman-ppc.c
pixman/pixman/pixman-edge.c
pixman/pixman/pixman-edge-accessors.c
pixman/pixman/pixman-fast-path.c
pixman/pixman/pixman-glyph.c
pixman/pixman/pixman-general.c
pixman/pixman/pixman-gradient-walker.c
pixman/pixman/pixman-image.c
pixman/pixman/pixman-implementation.c
pixman/pixman/pixman-linear-gradient.c
pixman/pixman/pixman-matrix.c
pixman/pixman/pixman-noop.c
pixman/pixman/pixman-radial-gradient.c
pixman/pixman/pixman-region16.c
pixman/pixman/pixman-region32.c
pixman/pixman/pixman-solid-fill.c
pixman/pixman/pixman-timer.c
pixman/pixman/pixman-trap.c
pixman/pixman/pixman-utils.c)
set(PIXMAN_CFLAGS
"-DHAVE_BUILTIN_CLZ=1"
"-DHAVE_PTHREADS=1"
"-DPACKAGE=\"pixman\""
"-DTLS=__thread"
"-DSIZEOF_LONG=${SIZEOF_LONG}"
"-DUSE_OPENMP=1"
"-Wno-unknown-attributes")
if("${CMAKE_ANDROID_ARCH_ABI}" STREQUAL "arm64-v8a")
set(PIXMAN_SRC ${PIXMAN_SRC}
"pixman/pixman/pixman-arm-neon.c"
"pixman/pixman/pixman-arma64-neon-asm.S"
"pixman/pixman/pixman-arma64-neon-asm-bilinear.S")
set(PIXMAN_CFLAGS ${PIXMAN_CFLAGS} "-DUSE_ARM_A64_NEON=1")
endif()
if("${CMAKE_ANDROID_ARCH_ABI}" STREQUAL "armeabi-v7a")
set(PIXMAN_SRC ${PIXMAN_SRC}
"pixman/pixman/pixman-arm-neon.c"
"pixman/pixman/pixman-arm-neon-asm.S"
"pixman/pixman/pixman-arm-neon-asm-bilinear.S"
"pixman/pixman/pixman-arm-simd-asm.S"
"pixman/pixman/pixman-arm-simd-asm-scaled.S")
set(PIXMAN_CFLAGS ${PIXMAN_CFLAGS} "-DUSE_ARM_SIMD=1" "-DUSE_ARM_NEON=1" "-v")
endif()
if ("${CMAKE_ANDROID_ARCH_ABI}" STREQUAL "x86" OR "${CMAKE_ANDROID_ARCH_ABI}" STREQUAL "x86_64")
set(PIXMAN_CFLAGS ${PIXMAN_CFLAGS} "-msse2" "-Winline" "-mssse3" "-Winline")
endif()
add_library(pixman STATIC ${PIXMAN_SRC})
target_compile_options(pixman PRIVATE ${PIXMAN_CFLAGS})
target_include_directories(pixman PRIVATE pixman "${CMAKE_CURRENT_BINARY_DIR}")
target_apply_patch(pixman "${CMAKE_CURRENT_SOURCE_DIR}/pixman" "${CMAKE_CURRENT_SOURCE_DIR}/patches/pixman.patch")

View File

@@ -0,0 +1,50 @@
add_library(tirpc STATIC
"libtirpc/src/auth_none.c"
"libtirpc/src/auth_unix.c"
"libtirpc/src/authunix_prot.c"
"libtirpc/src/binddynport.c"
"libtirpc/src/clnt_bcast.c"
"libtirpc/src/clnt_dg.c"
"libtirpc/src/clnt_generic.c"
"libtirpc/src/clnt_perror.c"
"libtirpc/src/clnt_raw.c"
"libtirpc/src/clnt_simple.c"
"libtirpc/src/clnt_vc.c"
"libtirpc/src/rpc_dtablesize.c"
"libtirpc/src/getnetconfig.c"
"libtirpc/src/getnetpath.c"
"libtirpc/src/mt_misc.c"
"libtirpc/src/pmap_clnt.c"
"libtirpc/src/pmap_getport.c"
"libtirpc/src/pmap_prot.c"
"libtirpc/src/pmap_prot2.c"
"libtirpc/src/pmap_rmt.c"
"libtirpc/src/rpc_prot.c"
"libtirpc/src/rpc_commondata.c"
"libtirpc/src/rpc_callmsg.c"
"libtirpc/src/rpc_generic.c"
"libtirpc/src/rpc_soc.c"
"libtirpc/src/rpcb_clnt.c"
"libtirpc/src/rpcb_prot.c"
"libtirpc/src/svc.c"
"libtirpc/src/svc_auth.c"
"libtirpc/src/svc_dg.c"
"libtirpc/src/svc_auth_unix.c"
"libtirpc/src/svc_auth_none.c"
"libtirpc/src/svc_generic.c"
"libtirpc/src/svc_raw.c"
"libtirpc/src/svc_simple.c"
"libtirpc/src/svc_vc.c"
"libtirpc/src/getpeereid.c"
"libtirpc/src/debug.c"
"libtirpc/src/xdr.c"
"libtirpc/src/xdr_rec.c"
"libtirpc/src/xdr_array.c"
"libtirpc/src/xdr_mem.c"
"libtirpc/src/xdr_reference.c")
target_include_directories(tirpc PUBLIC "libtirpc/tirpc")
target_compile_options(tirpc PRIVATE "-DPORTMAP" "-DINET6=1" "-DHAVE_FEATURES_H=1"
"-DHAVE_GETRPCBYNAME=1" "-DHAVE_GETRPCBYNUMBER=1" "-DHAVE_SETRPCENT=1" "-DHAVE_ENDRPCENT=1"
"-DHAVE_GETRPCENT=1" "-UHAVE_GSSAPI_GSSAPI_EXT_H" "-UAUTHDES_SUPPORT" "-Dquad_t=long long"
"-Du_quad_t=unsigned long long" "-Dgetdtablesize()=sysconf(_SC_OPEN_MAX)" "-D_GNU_SOURCE"
"-Wall" "-pipe" "-fPIC" "-DPIC" "-Wno-deprecated-non-prototype" "-Wno-macro-redefined")

View File

@@ -0,0 +1,71 @@
# Normally xkbcomp is build as executable, but in our case it is better to embed it.
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/X11")
add_custom_command(
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/ks_tables.h"
COMMAND "gcc" "-o" "${CMAKE_CURRENT_BINARY_DIR}/makekeys" "${CMAKE_CURRENT_SOURCE_DIR}/libx11/src/util/makekeys.c" "&&"
"${CMAKE_CURRENT_BINARY_DIR}/makekeys" "keysymdef.h" "XF86keysym.h" "Sunkeysym.h" "DECkeysym.h" "HPkeysym.h" ">" "${CMAKE_CURRENT_BINARY_DIR}/ks_tables.h"
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/xorgproto/include/X11"
COMMENT "Generating source code (ks_tables.h)"
VERBATIM)
BISON_TARGET(xkbcomp_parser xkbcomp/xkbparse.y ${CMAKE_CURRENT_BINARY_DIR}/xkbparse.c)
add_library(xkbcomp STATIC
"libx11/src/KeyBind.c"
"libx11/src/KeysymStr.c"
"libx11/src/Quarks.c"
"libx11/src/StrKeysym.c"
"libx11/src/Xrm.c"
"libx11/src/xkb/XKBGeom.c"
"libx11/src/xkb/XKBMisc.c"
"libx11/src/xkb/XKBMAlloc.c"
"libx11/src/xkb/XKBGAlloc.c"
"libx11/src/xkb/XKBAlloc.c"
"libxkbfile/src/xkbatom.c"
"libxkbfile/src/xkberrs.c"
"libxkbfile/src/xkbmisc.c"
"libxkbfile/src/xkbout.c"
"libxkbfile/src/xkbtext.c"
"libxkbfile/src/xkmout.c"
"xkbcomp/action.c"
"xkbcomp/alias.c"
"xkbcomp/compat.c"
"xkbcomp/expr.c"
"xkbcomp/geometry.c"
"xkbcomp/indicators.c"
"xkbcomp/keycodes.c"
"xkbcomp/keymap.c"
"xkbcomp/keytypes.c"
"xkbcomp/listing.c"
"xkbcomp/misc.c"
"xkbcomp/parseutils.c"
"xkbcomp/symbols.c"
"xkbcomp/utils.c"
"xkbcomp/vmod.c"
"xkbcomp/xkbcomp.c"
"xkbcomp/xkbparse.y"
"xkbcomp/xkbpath.c"
"xkbcomp/xkbscan.c"
"${CMAKE_CURRENT_BINARY_DIR}/ks_tables.h"
"${CMAKE_CURRENT_BINARY_DIR}/xkbparse.c")
target_include_directories(xkbcomp
PUBLIC
"libxkbfile/include"
PRIVATE
"xkbcomp"
"libx11/include"
"libx11/include/X11"
"libx11/src"
"libx11/src/xlibi18n"
"libxkbfile/include/X11/extensions"
"${CMAKE_CURRENT_BINARY_DIR}")
target_link_libraries(xkbcomp PRIVATE xorgproto)
target_link_options(xkbcomp PRIVATE "-fPIE" "-fPIC")
target_compile_options(xkbcomp PRIVATE ${common_compile_options} "-fvisibility=hidden" "-DHAVE_STRCASECMP" "-DHAVE_STRDUP" "-DDFLT_XKB_CONFIG_ROOT=\"/\"" "-DHAVE_SYS_IOCTL_H" "-fPIE" "-fPIC" "-DPACKAGE_VERSION=\"2.70\"" "-Wno-shadow")
target_apply_patch(xkbcomp "${CMAKE_CURRENT_SOURCE_DIR}/xkbcomp" "${CMAKE_CURRENT_SOURCE_DIR}/patches/xkbcomp.patch")
target_apply_patch(xkbfile "${CMAKE_CURRENT_SOURCE_DIR}/libxkbfile" "${CMAKE_CURRENT_SOURCE_DIR}/patches/xkbfile.patch")
target_apply_patch(X11 "${CMAKE_CURRENT_SOURCE_DIR}/libx11" "${CMAKE_CURRENT_SOURCE_DIR}/patches/x11.patch")

View File

@@ -0,0 +1,9 @@
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/X11")
file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/X11/XlibConf.h" CONTENT "\n#pragma once\n#define XTHREADS 1\n#define XUSE_MTSAFE_API 1")
execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink "${CMAKE_CURRENT_SOURCE_DIR}/libxtrans" "${CMAKE_CURRENT_BINARY_DIR}/X11/Xtrans")
add_library(xorgproto INTERFACE)
target_include_directories(xorgproto INTERFACE "xorgproto/include")
set(USE_FDS_BITS 1)
configure_file("xorgproto/include/X11/Xpoll.h.in" "${CMAKE_CURRENT_BINARY_DIR}/X11/Xpoll.h" @ONLY)
target_apply_patch(Xtrans "${CMAKE_CURRENT_SOURCE_DIR}/libxtrans" "${CMAKE_CURRENT_SOURCE_DIR}/patches/Xtrans.patch")

View File

@@ -0,0 +1,280 @@
check_type_size("unsigned long" SIZEOF_UNSIGNED_LONG)
configure_file("patches/dix-config.h.in" "${CMAKE_CURRENT_BINARY_DIR}/dix-config.h")
file(GENERATE
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/version-config.h
CONTENT "
#pragma once
#define VENDOR_NAME \"The X.Org Foundation\"
#define VENDOR_RELEASE 12101099
")
file(GENERATE
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/xkb-config.h
CONTENT "
#pragma once
#define XKB_BASE_DIRECTORY \"/usr/share/X11/xkb/\"
#define XKB_BIN_DIRECTORY \"\"
#define XKB_DFLT_LAYOUT \"us\"
#define XKB_DFLT_MODEL \"pc105\"
#define XKB_DFLT_OPTIONS \"\"
#define XKB_DFLT_RULES \"evdev\"
#define XKB_DFLT_VARIANT \"\"
#define XKM_OUTPUT_DIR (getenv(\"TMPDIR\") ?: \"/tmp\")
")
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/xserver")
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/xserver/GL")
file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/xserver/GL/glext.h" CONTENT "#include <GL/gl.h>")
add_custom_command(
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/xserver/GL/gl.h"
COMMAND Python3::Interpreter "${CMAKE_CURRENT_SOURCE_DIR}/libepoxy/src/gen_dispatch.py"
"--outputdir=${CMAKE_CURRENT_BINARY_DIR}/xserver/GL" "${CMAKE_CURRENT_SOURCE_DIR}/libepoxy/registry/gl.xml"
COMMENT "Generating source code (GL/gl.h)"
VERBATIM)
set(inc "${CMAKE_CURRENT_BINARY_DIR}"
"${CMAKE_CURRENT_BINARY_DIR}/xserver"
"libxfont/include"
"pixman/pixman"
"xorgproto/include"
"libxkbfile/include"
"xserver/Xext"
"xserver/Xi"
"xserver/composite"
"xserver/damageext"
"xserver/fb"
"xserver/mi"
"xserver/miext/damage"
"xserver/miext/shadow"
"xserver/miext/sync"
"xserver/dbe"
"xserver/dri3"
"xserver/include"
"xserver/present"
"xserver/randr"
"xserver/render"
"xserver/xfixes"
"xserver/glx")
set(compile_options
${common_compile_options}
"-std=gnu99"
"-DHAVE_DIX_CONFIG_H"
"-fno-strict-aliasing"
"-fvisibility=hidden"
"-fPIC"
"-D_DEFAULT_SOURCE"
"-D_BSD_SOURCE"
"-DHAS_FCHOWN"
"-DHAS_STICKY_DIR_BIT"
"-D_PATH_TMP=getenv(\"TMPDIR\")?:\"/tmp\""
"-include" "${CMAKE_CURRENT_SOURCE_DIR}/lorie/shm/shm.h")
if (SIZEOF_UNSIGNED_LONG EQUAL 8)
set(compile_options ${compile_options} "-D_XSERVER64=1")
endif ()
set(DIX_SOURCES
atom.c colormap.c cursor.c devices.c dispatch.c dixfonts.c main.c dixutils.c enterleave.c
events.c eventconvert.c extension.c gc.c gestures.c getevents.c globals.c glyphcurs.c
grabs.c initatoms.c inpututils.c pixmap.c privates.c property.c ptrveloc.c region.c
registry.c resource.c selection.c swaprep.c swapreq.c tables.c touch.c window.c)
list(TRANSFORM DIX_SOURCES PREPEND "xserver/dix/")
add_library(xserver_dix STATIC ${DIX_SOURCES})
target_include_directories(xserver_dix PRIVATE ${inc})
target_compile_options(xserver_dix PRIVATE ${compile_options})
add_library(xserver_main STATIC
"xserver/dix/stubmain.c")
target_include_directories(xserver_main PRIVATE ${inc})
target_compile_options(xserver_main PRIVATE ${compile_options})
file(GENERATE
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/drm_fourcc.h"
CONTENT "
#pragma once
#define fourcc_code(a, b, c, d) ((uint32_t)(a) | ((uint32_t)(b) << 8) | ((uint32_t)(c) << 16) | ((uint32_t)(d) << 24))
#define DRM_FORMAT_RGB565 fourcc_code('R', 'G', '1', '6')
#define DRM_FORMAT_XRGB8888 fourcc_code('X', 'R', '2', '4')
#define DRM_FORMAT_XRGB2101010 fourcc_code('X', 'R', '3', '0')
#define DRM_FORMAT_ARGB8888 fourcc_code('A', 'R', '2', '4')
#define DRM_FORMAT_MOD_INVALID -1
")
add_library(xserver_dri3 STATIC
"xserver/dri3/dri3.c"
"xserver/dri3/dri3_request.c"
"xserver/dri3/dri3_screen.c")
target_include_directories(xserver_dri3 PRIVATE ${inc})
target_compile_options(xserver_dri3 PRIVATE ${compile_options})
set(FB_SOURCES
fballpriv.c fbarc.c fbbits.c fbblt.c fbbltone.c fbcmap_mi.c fbcopy.c fbfill.c fbfillrect.c
fbfillsp.c fbgc.c fbgetsp.c fbglyph.c fbimage.c fbline.c fboverlay.c fbpict.c fbpixmap.c
fbpoint.c fbpush.c fbscreen.c fbseg.c fbsetsp.c fbsolid.c fbtrap.c fbutil.c fbwindow.c)
list(TRANSFORM FB_SOURCES PREPEND "xserver/fb/")
add_library(xserver_fb STATIC ${FB_SOURCES})
target_include_directories(xserver_fb PRIVATE ${inc})
target_compile_options(xserver_fb PRIVATE ${compile_options})
set(MI_SOURCES
miarc.c mibitblt.c micmap.c micopy.c midash.c midispcur.c mieq.c miexpose.c mifillarc.c
mifillrct.c migc.c miglblt.c mioverlay.c mipointer.c mipoly.c mipolypnt.c mipolyrect.c
mipolyseg.c mipolytext.c mipushpxl.c miscrinit.c misprite.c mivaltree.c miwideline.c
miwindow.c mizerarc.c mizerclip.c mizerline.c)
list(TRANSFORM MI_SOURCES PREPEND "xserver/mi/")
add_library(xserver_mi STATIC ${MI_SOURCES})
target_include_directories(xserver_mi PRIVATE ${inc})
target_compile_options(xserver_mi PRIVATE ${compile_options})
set(OS_SOURCES
WaitFor.c access.c auth.c backtrace.c client.c connection.c inputthread.c io.c mitauth.c
oscolor.c osinit.c ospoll.c utils.c xdmauth.c xsha1.c xstrans.c xprintf.c log.c strlcpy.c
busfault.c timingsafe_memcmp.c rpcauth.c xdmcp.c)
list(TRANSFORM OS_SOURCES PREPEND "xserver/os/")
add_library(xserver_os STATIC ${OS_SOURCES})
target_include_directories(xserver_os PRIVATE ${inc})
target_link_libraries(xserver_os PRIVATE md Xdmcp Xau tirpc)
target_compile_options(xserver_os PRIVATE ${compile_options} "-DCLIENTIDS")
set(COMPOSITE_SOURCES compalloc.c compext.c compinit.c compoverlay.c compwindow.c)
list(TRANSFORM COMPOSITE_SOURCES PREPEND "xserver/composite/")
add_library(xserver_composite STATIC ${COMPOSITE_SOURCES})
target_include_directories(xserver_composite PRIVATE ${inc})
target_compile_options(xserver_composite PRIVATE ${compile_options})
add_library(xserver_damageext STATIC "xserver/damageext/damageext.c")
target_include_directories(xserver_damageext PRIVATE ${inc})
target_compile_options(xserver_damageext PRIVATE ${compile_options})
add_library(xserver_dbe STATIC "xserver/dbe/dbe.c" "xserver/dbe/midbe.c")
target_include_directories(xserver_dbe PRIVATE ${inc})
target_compile_options(xserver_dbe PRIVATE ${compile_options})
add_library(xserver_miext_damage STATIC "xserver/miext/damage/damage.c")
target_include_directories(xserver_miext_damage PRIVATE ${inc})
target_compile_options(xserver_miext_damage PRIVATE ${compile_options})
set(MIEXT_SYNC_SOURCES misync.c misyncfd.c misyncshm.c)
list(TRANSFORM MIEXT_SYNC_SOURCES PREPEND "xserver/miext/sync/")
add_library(xserver_miext_sync STATIC ${MIEXT_SYNC_SOURCES})
target_include_directories(xserver_miext_sync PRIVATE ${inc})
target_compile_options(xserver_miext_sync PRIVATE ${compile_options})
set(PRESENT_SOURCES
present.c present_event.c present_execute.c present_fake.c present_fence.c present_notify.c
present_request.c present_scmd.c present_screen.c present_vblank.c)
list(TRANSFORM PRESENT_SOURCES PREPEND "xserver/present/")
add_library(xserver_present STATIC ${PRESENT_SOURCES})
target_include_directories(xserver_present PRIVATE ${inc})
target_compile_options(xserver_present PRIVATE ${compile_options})
set(RANDR_SOURCES
randr.c rrcrtc.c rrdispatch.c rrinfo.c rrlease.c rrmode.c rrmonitor.c rroutput.c rrpointer.c
rrproperty.c rrprovider.c rrproviderproperty.c rrscreen.c rrsdispatch.c rrtransform.c
rrxinerama.c)
list(TRANSFORM RANDR_SOURCES PREPEND "xserver/randr/")
add_library(xserver_randr STATIC ${RANDR_SOURCES})
target_include_directories(xserver_randr PRIVATE ${inc})
target_compile_options(xserver_randr PRIVATE ${compile_options})
add_library(xserver_record STATIC xserver/record/record.c xserver/record/set.c)
target_include_directories(xserver_record PRIVATE ${inc})
target_compile_options(xserver_record PRIVATE ${compile_options})
set(RENDER_SOURCES
animcur.c filter.c glyph.c matrix.c miindex.c mipict.c mirect.c mitrap.c mitri.c picture.c
render.c)
list(TRANSFORM RENDER_SOURCES PREPEND "xserver/render/")
add_library(xserver_render STATIC ${RENDER_SOURCES})
target_include_directories(xserver_render PRIVATE ${inc})
target_compile_options(xserver_render PRIVATE ${compile_options})
set(XFIXES_SOURCES cursor.c disconnect.c region.c saveset.c select.c xfixes.c)
list(TRANSFORM XFIXES_SOURCES PREPEND "xserver/xfixes/")
add_library(xserver_xfixes STATIC ${XFIXES_SOURCES})
target_include_directories(xserver_xfixes PRIVATE ${inc})
target_compile_options(xserver_xfixes PRIVATE ${compile_options})
set(XKB_SOURCES
ddxBeep.c ddxCtrls.c ddxLEDs.c ddxLoad.c maprules.c xkmread.c xkbtext.c xkbfmisc.c xkbout.c
xkb.c xkbUtils.c xkbEvents.c xkbAccessX.c xkbSwap.c xkbLEDs.c xkbInit.c xkbActions.c
xkbPrKeyEv.c XKBMisc.c XKBAlloc.c XKBGAlloc.c XKBMAlloc.c)
list(TRANSFORM XKB_SOURCES PREPEND "xserver/xkb/")
add_library(xserver_xkb STATIC ${XKB_SOURCES})
target_include_directories(xserver_xkb PRIVATE ${inc})
target_compile_options(xserver_xkb PRIVATE ${compile_options} "-DXkbFreeGeomOverlayKeys=XkbFreeGeomOverlayKeysInternal")
set(XKB_STUBS_SOURCES ddxKillSrv.c ddxPrivate.c ddxVT.c)
list(TRANSFORM XKB_STUBS_SOURCES PREPEND "xserver/xkb/")
add_library(xserver_xkb_stubs STATIC ${XKB_STUBS_SOURCES})
target_include_directories(xserver_xkb_stubs PRIVATE ${inc})
target_compile_options(xserver_xkb_stubs PRIVATE ${compile_options})
set(XEXT_SOURCES
bigreq.c geext.c shape.c sleepuntil.c sync.c xcmisc.c xtest.c dpms.c shm.c hashtable.c
xres.c saver.c xace.c xf86bigfont.c panoramiX.c panoramiXprocs.c panoramiXSwap.c xvmain.c
xvdisp.c xvmc.c vidmode.c)
list(TRANSFORM XEXT_SOURCES PREPEND "xserver/Xext/")
add_library(xserver_xext STATIC ${XEXT_SOURCES})
target_include_directories(xserver_xext PRIVATE ${inc})
target_compile_options(xserver_xext PRIVATE ${compile_options})
set(XI_SOURCES
allowev.c chgdctl.c chgfctl.c chgkbd.c chgkmap.c chgprop.c chgptr.c closedev.c devbell.c
exevents.c extinit.c getbmap.c getdctl.c getfctl.c getfocus.c getkmap.c getmmap.c getprop.c
getselev.c getvers.c grabdev.c grabdevb.c grabdevk.c gtmotion.c listdev.c opendev.c queryst.c
selectev.c sendexev.c setbmap.c setdval.c setfocus.c setmmap.c setmode.c ungrdev.c ungrdevb.c
ungrdevk.c xiallowev.c xibarriers.c xichangecursor.c xichangehierarchy.c xigetclientpointer.c
xigrabdev.c xipassivegrab.c xiproperty.c xiquerydevice.c xiquerypointer.c xiqueryversion.c
xiselectev.c xisetclientpointer.c xisetdevfocus.c xiwarppointer.c)
list(TRANSFORM XI_SOURCES PREPEND "xserver/Xi/")
add_library(xserver_xi STATIC ${XI_SOURCES})
target_include_directories(xserver_xi PRIVATE ${inc})
target_compile_options(xserver_xi PRIVATE ${compile_options})
add_library(xserver_xi_stubs STATIC "xserver/Xi/stubs.c")
target_include_directories(xserver_xi_stubs PRIVATE ${inc})
target_compile_options(xserver_xi_stubs PRIVATE ${compile_options})
set(GLX_SOURCES
glxext.c indirect_dispatch.c indirect_dispatch_swap.c indirect_reqsize.c indirect_size_get.c
indirect_table.c clientinfo.c createcontext.c extension_string.c indirect_util.c
indirect_program.c indirect_texture_compression.c glxcmds.c glxcmdsswap.c glxext.c
glxscreens.c render2.c render2swap.c renderpix.c renderpixswap.c rensize.c single2.c
single2swap.c singlepix.c singlepixswap.c singlesize.c swap_interval.c xfont.c)
list(TRANSFORM GLX_SOURCES PREPEND "xserver/glx/")
add_library(xserver_glx STATIC ${GLX_SOURCES} "${CMAKE_CURRENT_BINARY_DIR}/xserver/GL/gl.h")
target_include_directories(xserver_glx PRIVATE ${inc})
target_compile_options(xserver_glx PRIVATE ${compile_options})
set(GLXVND_SOURCES
vndcmds.c vndext.c vndservermapping.c vndservervendor.c)
list(TRANSFORM GLXVND_SOURCES PREPEND "xserver/glx/")
add_library(xserver_glxvnd STATIC ${GLXVND_SOURCES})
target_include_directories(xserver_glxvnd PRIVATE ${inc})
target_compile_options(xserver_glxvnd PRIVATE ${compile_options})
set(XSERVER_LIBS tirpc Xdmcp Xau pixman Xfont2 fontenc GLESv2 xshmfence xkbcomp)
foreach (part glx glxvnd fb mi dix composite damageext dbe randr miext_damage render present xext
dri3 miext_sync xfixes xi xkb record xi_stubs xkb_stubs os)
set(XSERVER_LIBS ${XSERVER_LIBS} xserver_${part})
endforeach ()
add_library(Xlorie SHARED
"xserver/mi/miinitext.c"
"xserver/hw/xquartz/keysym2ucs.c"
"libxcvt/lib/libxcvt.c"
"lorie/shm/shmem.c"
"lorie/android.c"
"lorie/clipboard.c"
"lorie/dri3.c"
"lorie/InitOutput.c"
"lorie/InitInput.c"
"lorie/InputXKB.c"
"lorie/renderer.c")
target_include_directories(Xlorie PRIVATE ${inc} "libxcvt/include")
target_link_options(Xlorie PRIVATE "-Wl,--as-needed" "-Wl,--no-undefined" "-fvisibility=hidden")
target_link_libraries(Xlorie "-Wl,--whole-archive" ${XSERVER_LIBS} "-Wl,--no-whole-archive" android log m z EGL GLESv2)
target_compile_options(Xlorie PRIVATE ${compile_options})
target_apply_patch(Xlorie "${CMAKE_CURRENT_SOURCE_DIR}/xserver" "${CMAKE_CURRENT_SOURCE_DIR}/patches/xserver.patch")
target_apply_patch(Xlorie "${CMAKE_CURRENT_SOURCE_DIR}/libepoxy" "${CMAKE_CURRENT_SOURCE_DIR}/patches/libepoxy.patch")

View File

@@ -0,0 +1,5 @@
file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/values.h" CONTENT "#include <limits.h>")
execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink "${CMAKE_CURRENT_SOURCE_DIR}/libxshmfence/src/xshmfence.h" "${CMAKE_CURRENT_BINARY_DIR}/X11/xshmfence.h")
add_library(xshmfence STATIC "libxshmfence/src/xshmfence_alloc.c" "libxshmfence/src/xshmfence_futex.c")
target_include_directories(xshmfence PRIVATE "xorgproto/include" "${CMAKE_CURRENT_BINARY_DIR}")
target_compile_options(xshmfence PRIVATE "-DSHMDIR=\"/\"" "-DHAVE_FUTEX" "-DMAXINT=INT_MAX")

View File

@@ -0,0 +1,195 @@
#include <string.h>
#include "engine.h"
#include "input.h"
#include "math.h"
#include "renderer.h"
struct XrEngine xr_engine;
struct XrInput xr_input;
struct XrRenderer xr_renderer;
bool xr_initialized = false;
int xr_params[6] = {};
#if defined(_DEBUG)
#include <GLES2/gl2.h>
void GLCheckErrors(const char* file, int line) {
for (int i = 0; i < 10; i++) {
const GLenum error = glGetError();
if (error == GL_NO_ERROR) {
break;
}
ALOGE("OpenGL error on line %s:%d %d", file, line, error);
}
}
void OXRCheckErrors(XrResult result, const char* file, int line) {
if (XR_FAILED(result)) {
char errorBuffer[XR_MAX_RESULT_STRING_SIZE];
xrResultToString(xr_engine->Instance, result, errorBuffer);
ALOGE("OpenXR error on line %s:%d %s", file, line, errorBuffer);
}
}
#endif
JNIEXPORT void JNICALL Java_com_termux_x11_XrActivity_init(JNIEnv *env, jobject obj) {
// Do not allow second initialization
if (xr_initialized) {
return;
}
// Set platform flags
memset(&xr_engine, 0, sizeof(xr_engine));
xr_engine.PlatformFlag[PLATFORM_CONTROLLER_QUEST] = true;
xr_engine.PlatformFlag[PLATFORM_EXTENSION_PASSTHROUGH] = true;
xr_engine.PlatformFlag[PLATFORM_EXTENSION_PERFORMANCE] = true;
// Get Java VM
JavaVM* vm;
(*env)->GetJavaVM(env, &vm);
// Init XR
xrJava java;
java.vm = vm;
java.activity = (*env)->NewGlobalRef(env, obj);
XrEngineInit(&xr_engine, &java, "termux-x11", 1);
XrEngineEnter(&xr_engine);
XrInputInit(&xr_engine, &xr_input);
XrRendererInit(&xr_engine, &xr_renderer);
XrRendererGetResolution(&xr_engine, &xr_renderer, &xr_params[4], &xr_params[5]);
xr_initialized = true;
ALOGV("Init called");
}
JNIEXPORT void JNICALL Java_com_termux_x11_XrActivity_teardown(JNIEnv *env, jobject obj) {
if (!xr_initialized) {
return;
}
XrRendererDestroy(&xr_engine, &xr_renderer);
XrEngineLeave(&xr_engine);
XrEngineDestroy(&xr_engine);
memset(&xr_engine, 0, sizeof(xr_engine));
memset(&xr_input, 0, sizeof(xr_input));
memset(&xr_renderer, 0, sizeof(xr_renderer));
xr_initialized = false;
}
JNIEXPORT jboolean JNICALL Java_com_termux_x11_XrActivity_beginFrame(JNIEnv *env, jobject obj) {
if (XrRendererInitFrame(&xr_engine, &xr_renderer)) {
// Set renderer
int mode = xr_params[1] ? RENDER_MODE_MONO_6DOF : RENDER_MODE_MONO_SCREEN;
xr_renderer.ConfigFloat[CONFIG_CANVAS_DISTANCE] = xr_params[0];
xr_renderer.ConfigInt[CONFIG_PASSTHROUGH] = xr_params[2];
xr_renderer.ConfigInt[CONFIG_MODE] = mode;
xr_renderer.ConfigInt[CONFIG_SBS] = xr_params[3];
// Recenter if mode switched
static bool last_immersive = false;
if (last_immersive != xr_params[1]) {
XrRendererRecenter(&xr_engine, &xr_renderer);
last_immersive = xr_params[1];
}
// Update controllers state
XrInputUpdate(&xr_engine, &xr_input);
// Lock framebuffer
XrRendererBeginFrame(&xr_renderer, 0);
return true;
}
return false;
}
JNIEXPORT void JNICALL Java_com_termux_x11_XrActivity_finishFrame(JNIEnv *env, jobject obj) {
XrRendererEndFrame(&xr_renderer);
XrRendererFinishFrame(&xr_engine, &xr_renderer);
}
JNIEXPORT jfloatArray JNICALL Java_com_termux_x11_XrActivity_getAxes(JNIEnv *env, jobject obj) {
XrPosef lPose = XrInputGetPose(&xr_input, 0);
XrPosef rPose = XrInputGetPose(&xr_input, 1);
XrVector2f lThumbstick = XrInputGetJoystickState(&xr_input, 0);
XrVector2f rThumbstick = XrInputGetJoystickState(&xr_input, 1);
XrVector3f lPosition = xr_renderer.Projections[0].pose.position;
XrVector3f rPosition = xr_renderer.Projections[1].pose.position;
XrVector3f angles = xr_renderer.HmdOrientation;
int count = 0;
float data[32];
data[count++] = XrQuaternionfEulerAngles(lPose.orientation).x; //L_PITCH
data[count++] = XrQuaternionfEulerAngles(lPose.orientation).y; //L_YAW
data[count++] = XrQuaternionfEulerAngles(lPose.orientation).z; //L_ROLL
data[count++] = lThumbstick.x; //L_THUMBSTICK_X
data[count++] = lThumbstick.y; //L_THUMBSTICK_Y
data[count++] = lPose.position.x; //L_X
data[count++] = lPose.position.y; //L_Y
data[count++] = lPose.position.z; //L_Z
data[count++] = XrQuaternionfEulerAngles(rPose.orientation).x; //R_PITCH
data[count++] = XrQuaternionfEulerAngles(rPose.orientation).y; //R_YAW
data[count++] = XrQuaternionfEulerAngles(rPose.orientation).z; //R_ROLL
data[count++] = rThumbstick.x; //R_THUMBSTICK_X
data[count++] = rThumbstick.y; //R_THUMBSTICK_Y
data[count++] = rPose.position.x; //R_X
data[count++] = rPose.position.y; //R_Y
data[count++] = rPose.position.z; //R_Z
data[count++] = angles.x; //HMD_PITCH
data[count++] = angles.y; //HMD_YAW
data[count++] = angles.z; //HMD_ROLL
data[count++] = (lPosition.x + rPosition.x) * 0.5f; //HMD_X
data[count++] = (lPosition.y + rPosition.y) * 0.5f; //HMD_Y
data[count++] = (lPosition.z + rPosition.z) * 0.5f; //HMD_Z
data[count++] = XrVector3fDistance(lPosition, rPosition); //HMD_IPD
jfloat values[count];
memcpy(values, data, count * sizeof(float));
jfloatArray output = (*env)->NewFloatArray(env, count);
(*env)->SetFloatArrayRegion(env, output, (jsize)0, (jsize)count, values);
return output;
}
JNIEXPORT jbooleanArray JNICALL Java_com_termux_x11_XrActivity_getButtons(JNIEnv *env, jobject obj) {
uint32_t l = XrInputGetButtonState(&xr_input, 0);
uint32_t r = XrInputGetButtonState(&xr_input, 1);
int count = 0;
bool data[32];
data[count++] = l & (int)Grip; //L_GRIP
data[count++] = l & (int)Enter; //L_MENU
data[count++] = l & (int)LThumb; //L_THUMBSTICK_PRESS
data[count++] = l & (int)Left; //L_THUMBSTICK_LEFT
data[count++] = l & (int)Right; //L_THUMBSTICK_RIGHT
data[count++] = l & (int)Up; //L_THUMBSTICK_UP
data[count++] = l & (int)Down; //L_THUMBSTICK_DOWN
data[count++] = l & (int)Trigger; //L_TRIGGER
data[count++] = l & (int)X; //L_X
data[count++] = l & (int)Y; //L_Y
data[count++] = r & (int)A; //R_A
data[count++] = r & (int)B; //R_B
data[count++] = r & (int)Grip; //R_GRIP
data[count++] = r & (int)RThumb; //R_THUMBSTICK_PRESS
data[count++] = r & (int)Left; //R_THUMBSTICK_LEFT
data[count++] = r & (int)Right; //R_THUMBSTICK_RIGHT
data[count++] = r & (int)Up; //R_THUMBSTICK_UP
data[count++] = r & (int)Down; //R_THUMBSTICK_DOWN
data[count++] = r & (int)Trigger; //R_TRIGGER
jboolean values[count];
memcpy(values, data, count * sizeof(jboolean));
jbooleanArray output = (*env)->NewBooleanArray(env, count);
(*env)->SetBooleanArrayRegion(env, output, (jsize)0, (jsize)count, values);
return output;
}
JNIEXPORT jint JNICALL Java_com_termux_x11_XrActivity_getRenderParam(JNIEnv *env, jobject obj, jint param) {
return xr_params[param];
}
JNIEXPORT void JNICALL Java_com_termux_x11_XrActivity_setRenderParam(JNIEnv *env, jobject obj, jint param, jint value) {
xr_params[param] = value;
}

View File

@@ -0,0 +1,190 @@
#include "engine.h"
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
void XrEngineInit(struct XrEngine* engine, void* system, const char* name, int version) {
if (engine->Initialized)
return;
memset(engine, 0, sizeof(engine));
#ifdef ANDROID
PFN_xrInitializeLoaderKHR xrInitializeLoaderKHR;
xrGetInstanceProcAddr(XR_NULL_HANDLE, "xrInitializeLoaderKHR",
(PFN_xrVoidFunction*)&xrInitializeLoaderKHR);
if (xrInitializeLoaderKHR != NULL) {
xrJava* java = (xrJava*)system;
XrLoaderInitInfoAndroidKHR loader_info;
memset(&loader_info, 0, sizeof(loader_info));
loader_info.type = XR_TYPE_LOADER_INIT_INFO_ANDROID_KHR;
loader_info.next = NULL;
loader_info.applicationVM = java->vm;
loader_info.applicationContext = java->activity;
xrInitializeLoaderKHR((XrLoaderInitInfoBaseHeaderKHR*)&loader_info);
}
#endif
int count = 0;
const char* extensions[32];
#ifdef XR_USE_GRAPHICS_API_OPENGL_ES
extensions[count++] = XR_KHR_OPENGL_ES_ENABLE_EXTENSION_NAME;
#endif
#ifdef ANDROID
if (engine->PlatformFlag[PLATFORM_EXTENSION_INSTANCE]) {
extensions[count++] = XR_KHR_ANDROID_CREATE_INSTANCE_EXTENSION_NAME;
}
if (engine->PlatformFlag[PLATFORM_EXTENSION_PASSTHROUGH]) {
extensions[count++] = XR_FB_PASSTHROUGH_EXTENSION_NAME;
}
if (engine->PlatformFlag[PLATFORM_EXTENSION_PERFORMANCE]) {
extensions[count++] = XR_EXT_PERFORMANCE_SETTINGS_EXTENSION_NAME;
extensions[count++] = XR_KHR_ANDROID_THREAD_SETTINGS_EXTENSION_NAME;
}
#endif
// Create the OpenXR instance.
XrApplicationInfo app_info;
memset(&app_info, 0, sizeof(app_info));
strcpy(app_info.applicationName, name);
strcpy(app_info.engineName, name);
app_info.applicationVersion = version;
app_info.engineVersion = version;
app_info.apiVersion = XR_API_VERSION_1_0;
XrInstanceCreateInfo instance_info;
memset(&instance_info, 0, sizeof(instance_info));
instance_info.type = XR_TYPE_INSTANCE_CREATE_INFO;
instance_info.next = NULL;
instance_info.createFlags = 0;
instance_info.applicationInfo = app_info;
instance_info.enabledApiLayerCount = 0;
instance_info.enabledApiLayerNames = NULL;
instance_info.enabledExtensionCount = count;
instance_info.enabledExtensionNames = extensions;
#ifdef ANDROID
XrInstanceCreateInfoAndroidKHR instance_info_android = {XR_TYPE_INSTANCE_CREATE_INFO_ANDROID_KHR};
if (engine->PlatformFlag[PLATFORM_EXTENSION_INSTANCE]) {
xrJava* java = (xrJava*)system;
instance_info_android.applicationVM = java->vm;
instance_info_android.applicationActivity = java->activity;
instance_info.next = (XrBaseInStructure*)&instance_info_android;
}
#endif
XrResult result;
OXR(result = xrCreateInstance(&instance_info, &engine->Instance));
if (result != XR_SUCCESS) {
ALOGE("Failed to create XR instance: %d", (int)result);
exit(1);
}
XrInstanceProperties instance_properties;
instance_properties.type = XR_TYPE_INSTANCE_PROPERTIES;
instance_properties.next = NULL;
OXR(xrGetInstanceProperties(engine->Instance, &instance_properties));
ALOGV("Runtime %s: Version : %d.%d.%d", instance_properties.runtimeName,
XR_VERSION_MAJOR(instance_properties.runtimeVersion),
XR_VERSION_MINOR(instance_properties.runtimeVersion),
XR_VERSION_PATCH(instance_properties.runtimeVersion));
XrSystemGetInfo system_info;
memset(&system_info, 0, sizeof(system_info));
system_info.type = XR_TYPE_SYSTEM_GET_INFO;
system_info.next = NULL;
system_info.formFactor = XR_FORM_FACTOR_HEAD_MOUNTED_DISPLAY;
OXR(result = xrGetSystem(engine->Instance, &system_info, &engine->SystemId));
if (result != XR_SUCCESS) {
ALOGE("Failed to get system");
exit(1);
}
// Get the graphics requirements.
#ifdef XR_USE_GRAPHICS_API_OPENGL_ES
PFN_xrGetOpenGLESGraphicsRequirementsKHR pfnGetOpenGLESGraphicsRequirementsKHR = NULL;
OXR(xrGetInstanceProcAddr(engine->Instance, "xrGetOpenGLESGraphicsRequirementsKHR",
(PFN_xrVoidFunction*)(&pfnGetOpenGLESGraphicsRequirementsKHR)));
XrGraphicsRequirementsOpenGLESKHR graphics_requirements = {};
graphics_requirements.type = XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_ES_KHR;
OXR(pfnGetOpenGLESGraphicsRequirementsKHR(engine->Instance, engine->SystemId, &graphics_requirements));
#endif
#ifdef ANDROID
engine->MainThreadId = gettid();
#endif
engine->Initialized = true;
}
void XrEngineDestroy(struct XrEngine* engine) {
if (engine->Initialized) {
xrDestroyInstance(engine->Instance);
engine->Initialized = false;
}
}
void XrEngineEnter(struct XrEngine* engine) {
if (engine->Session) {
ALOGE("EnterXR called with existing session");
return;
}
// Create the OpenXR Session.
XrSessionCreateInfo session_info;
memset(&session_info, 0, sizeof(session_info));
#ifdef XR_USE_GRAPHICS_API_OPENGL_ES
XrGraphicsBindingOpenGLESAndroidKHR graphics_binding_gl = {};
graphics_binding_gl.type = XR_TYPE_GRAPHICS_BINDING_OPENGL_ES_ANDROID_KHR;
graphics_binding_gl.next = NULL;
graphics_binding_gl.display = eglGetCurrentDisplay();
graphics_binding_gl.config = NULL;
graphics_binding_gl.context = eglGetCurrentContext();
session_info.next = &graphics_binding_gl;
#endif
session_info.type = XR_TYPE_SESSION_CREATE_INFO;
session_info.createFlags = 0;
session_info.systemId = engine->SystemId;
XrResult result;
OXR(result = xrCreateSession(engine->Instance, &session_info, &engine->Session));
if (result != XR_SUCCESS) {
ALOGE("Failed to create XR session: %d", (int)result);
exit(1);
}
// Create a space to the first path
XrReferenceSpaceCreateInfo space_info = {};
space_info.type = XR_TYPE_REFERENCE_SPACE_CREATE_INFO;
space_info.referenceSpaceType = XR_REFERENCE_SPACE_TYPE_VIEW;
space_info.poseInReferenceSpace.orientation.w = 1.0f;
OXR(xrCreateReferenceSpace(engine->Session, &space_info, &engine->HeadSpace));
}
void XrEngineLeave(struct XrEngine* engine) {
if (engine->Session) {
OXR(xrDestroySpace(engine->HeadSpace));
// StageSpace is optional.
if (engine->StageSpace != XR_NULL_HANDLE) {
OXR(xrDestroySpace(engine->StageSpace));
}
OXR(xrDestroySpace(engine->FakeSpace));
engine->CurrentSpace = XR_NULL_HANDLE;
OXR(xrDestroySession(engine->Session));
engine->Session = XR_NULL_HANDLE;
}
}
void XrEngineWaitForFrame(struct XrEngine* engine) {
XrFrameWaitInfo wait_frame_info = {};
wait_frame_info.type = XR_TYPE_FRAME_WAIT_INFO;
wait_frame_info.next = NULL;
XrFrameState frame_state = {};
frame_state.type = XR_TYPE_FRAME_STATE;
frame_state.next = NULL;
OXR(xrWaitFrame(engine->Session, &wait_frame_info, &frame_state));
engine->PredictedDisplayTime = frame_state.predictedDisplayTime;
}

View File

@@ -0,0 +1,90 @@
#pragma once
#include <stdbool.h>
//#define _DEBUG
#if defined(_DEBUG)
void GLCheckErrors(const char* file, int line);
void OXRCheckErrors(XrResult result, const char* file, int line);
#define GL(func) func; GLCheckErrors(__FILE__ , __LINE__);
#define OXR(func) OXRCheckErrors(func, __FILE__ , __LINE__);
#else
#define GL(func) func;
#define OXR(func) func;
#endif
#ifdef ANDROID
#include <android/log.h>
#define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, "OpenXR", __VA_ARGS__);
#define ALOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, "OpenXR", __VA_ARGS__);
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <jni.h>
#define XR_USE_PLATFORM_ANDROID 1
#define XR_USE_GRAPHICS_API_OPENGL_ES 1
#else
#include <cstdio>
#define ALOGE(...) printf(__VA_ARGS__)
#define ALOGV(...) printf(__VA_ARGS__)
#endif
#include <openxr/openxr.h>
#include <openxr/openxr_platform.h>
enum {
XrMaxLayerCount = 2
};
enum {
XrMaxNumEyes = 2
};
enum XrPlatformFlag {
PLATFORM_CONTROLLER_PICO,
PLATFORM_CONTROLLER_QUEST,
PLATFORM_EXTENSION_INSTANCE,
PLATFORM_EXTENSION_PASSTHROUGH,
PLATFORM_EXTENSION_PERFORMANCE,
PLATFORM_TRACKING_FLOOR,
PLATFORM_MAX
};
typedef union {
XrCompositionLayerProjection projection;
XrCompositionLayerQuad quad;
} XrCompositorLayer;
#ifdef ANDROID
typedef struct {
jobject activity;
JNIEnv* env;
JavaVM* vm;
} xrJava;
#endif
struct XrEngine {
XrInstance Instance;
XrSession Session;
XrSystemId SystemId;
XrSpace CurrentSpace;
XrSpace FakeSpace;
XrSpace HeadSpace;
XrSpace StageSpace;
XrTime PredictedDisplayTime;
int MainThreadId;
int RenderThreadId;
bool PlatformFlag[PLATFORM_MAX];
bool Initialized;
};
void XrEngineInit(struct XrEngine* engine, void* system, const char* name, int version);
void XrEngineDestroy(struct XrEngine* engine);
void XrEngineEnter(struct XrEngine* engine);
void XrEngineLeave(struct XrEngine* engine);
void XrEngineWaitForFrame(struct XrEngine* engine);

View File

@@ -0,0 +1,127 @@
#include "framebuffer.h"
#if XR_USE_GRAPHICS_API_OPENGL_ES
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#endif
#include <stdlib.h>
#include <string.h>
bool XrFramebufferCreate(struct XrFramebuffer *framebuffer, XrSession session, int width, int height) {
memset(framebuffer, 0, sizeof(framebuffer));
#if XR_USE_GRAPHICS_API_OPENGL_ES
return XrFramebufferCreateGL(framebuffer, session, width, height);
#else
return false;
#endif
}
void XrFramebufferDestroy(struct XrFramebuffer *framebuffer) {
#if XR_USE_GRAPHICS_API_OPENGL_ES
GL(glDeleteRenderbuffers(framebuffer->SwapchainLength, framebuffer->GLDepthBuffers));
GL(glDeleteFramebuffers(framebuffer->SwapchainLength, framebuffer->GLFrameBuffers));
free(framebuffer->GLDepthBuffers);
free(framebuffer->GLFrameBuffers);
#endif
OXR(xrDestroySwapchain(framebuffer->Handle));
free(framebuffer->SwapchainImage);
}
void XrFramebufferAcquire(struct XrFramebuffer *framebuffer) {
XrSwapchainImageAcquireInfo acquire_info = {XR_TYPE_SWAPCHAIN_IMAGE_ACQUIRE_INFO, NULL};
OXR(xrAcquireSwapchainImage(framebuffer->Handle, &acquire_info, &framebuffer->SwapchainIndex));
XrSwapchainImageWaitInfo wait_info;
wait_info.type = XR_TYPE_SWAPCHAIN_IMAGE_WAIT_INFO;
wait_info.next = NULL;
wait_info.timeout = 1000000; /* timeout in nanoseconds */
XrResult res = xrWaitSwapchainImage(framebuffer->Handle, &wait_info);
int i = 0;
while ((res != XR_SUCCESS) && (i < 10)) {
res = xrWaitSwapchainImage(framebuffer->Handle, &wait_info);
i++;
ALOGV("Retry xrWaitSwapchainImage %d times due XR_TIMEOUT_EXPIRED (duration %lf ms",
i, wait_info.timeout * (1E-9));
}
framebuffer->Acquired = res == XR_SUCCESS;
XrFramebufferSetCurrent(framebuffer);
}
void XrFramebufferRelease(struct XrFramebuffer *framebuffer) {
if (framebuffer->Acquired) {
XrSwapchainImageReleaseInfo release_info = {XR_TYPE_SWAPCHAIN_IMAGE_RELEASE_INFO, NULL};
OXR(xrReleaseSwapchainImage(framebuffer->Handle, &release_info));
framebuffer->Acquired = false;
}
}
void XrFramebufferSetCurrent(struct XrFramebuffer *framebuffer) {
#if XR_USE_GRAPHICS_API_OPENGL_ES
GL(glBindFramebuffer(GL_FRAMEBUFFER, framebuffer->GLFrameBuffers[framebuffer->SwapchainIndex]));
#endif
}
#if XR_USE_GRAPHICS_API_OPENGL_ES
bool XrFramebufferCreateGL(struct XrFramebuffer *framebuffer, XrSession session, int width, int height) {
XrSwapchainCreateInfo swapchain_info;
memset(&swapchain_info, 0, sizeof(swapchain_info));
swapchain_info.type = XR_TYPE_SWAPCHAIN_CREATE_INFO;
swapchain_info.sampleCount = 1;
swapchain_info.width = width;
swapchain_info.height = height;
swapchain_info.faceCount = 1;
swapchain_info.mipCount = 1;
swapchain_info.arraySize = 1;
framebuffer->Width = swapchain_info.width;
framebuffer->Height = swapchain_info.height;
// Create the color swapchain.
swapchain_info.format = GL_SRGB8_ALPHA8_EXT;
swapchain_info.usageFlags = XR_SWAPCHAIN_USAGE_COLOR_ATTACHMENT_BIT;
OXR(xrCreateSwapchain(session, &swapchain_info, &framebuffer->Handle));
OXR(xrEnumerateSwapchainImages(framebuffer->Handle, 0, &framebuffer->SwapchainLength, NULL));
framebuffer->SwapchainImage = malloc(framebuffer->SwapchainLength * sizeof(XrSwapchainImageOpenGLESKHR));
// Populate the swapchain image array.
for (uint32_t i = 0; i < framebuffer->SwapchainLength; i++) {
XrSwapchainImageOpenGLESKHR* swapchain = (XrSwapchainImageOpenGLESKHR*)framebuffer->SwapchainImage;
swapchain[i].type = XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_ES_KHR;
swapchain[i].next = NULL;
}
OXR(xrEnumerateSwapchainImages(framebuffer->Handle, framebuffer->SwapchainLength,
&framebuffer->SwapchainLength,
(XrSwapchainImageBaseHeader*)framebuffer->SwapchainImage));
framebuffer->GLDepthBuffers = (GLuint*)malloc(framebuffer->SwapchainLength * sizeof(GLuint));
framebuffer->GLFrameBuffers = (GLuint*)malloc(framebuffer->SwapchainLength * sizeof(GLuint));
for (uint32_t i = 0; i < framebuffer->SwapchainLength; i++) {
// Create color and depth buffers.
GLuint color_texture = ((XrSwapchainImageOpenGLESKHR*)framebuffer->SwapchainImage)[i].image;
GL(glGenRenderbuffers(1, &framebuffer->GLDepthBuffers[i]));
GL(glBindRenderbuffer(GL_RENDERBUFFER, framebuffer->GLDepthBuffers[i]));
GL(glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES, width, height));
GL(glBindRenderbuffer(GL_RENDERBUFFER, 0));
// Create the frame buffer.
GL(glGenFramebuffers(1, &framebuffer->GLFrameBuffers[i]));
GL(glBindFramebuffer(GL_FRAMEBUFFER, framebuffer->GLFrameBuffers[i]));
GL(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
framebuffer->GLDepthBuffers[i]));
GL(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER,
framebuffer->GLDepthBuffers[i]));
GL(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
color_texture, 0));
GL(GLenum renderFramebufferStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER));
GL(glBindFramebuffer(GL_FRAMEBUFFER, 0));
if (renderFramebufferStatus != GL_FRAMEBUFFER_COMPLETE) {
ALOGE("Incomplete frame buffer object: %d", renderFramebufferStatus);
return false;
}
}
return true;
}
#endif

View File

@@ -0,0 +1,28 @@
#pragma once
#include "engine.h"
struct XrFramebuffer {
int Width;
int Height;
bool Acquired;
XrSwapchain Handle;
uint32_t SwapchainIndex;
uint32_t SwapchainLength;
void* SwapchainImage;
unsigned int* GLDepthBuffers;
unsigned int* GLFrameBuffers;
};
bool XrFramebufferCreate(struct XrFramebuffer *framebuffer, XrSession session, int width, int height);
void XrFramebufferDestroy(struct XrFramebuffer *framebuffer);
void XrFramebufferAcquire(struct XrFramebuffer *framebuffer);
void XrFramebufferRelease(struct XrFramebuffer *framebuffer);
void XrFramebufferSetCurrent(struct XrFramebuffer *framebuffer);
#if XR_USE_GRAPHICS_API_OPENGL_ES
bool XrFramebufferCreateGL(struct XrFramebuffer *framebuffer, XrSession session, int width, int height);
#endif

View File

@@ -0,0 +1,404 @@
#include "input.h"
#include "math.h"
#include <sys/time.h>
#include <string.h>
void XrInputInit(struct XrEngine* engine, struct XrInput* input) {
if (input->Initialized)
return;
memset(input, 0, sizeof(input));
// Actions
input->ActionSet = XrInputCreateActionSet(engine->Instance, "running_action_set", "Actionset");
input->IndexLeft = XrInputCreateAction(input->ActionSet, XR_ACTION_TYPE_BOOLEAN_INPUT, "index_left", "Index left", 0, NULL);
input->IndexRight = XrInputCreateAction(input->ActionSet, XR_ACTION_TYPE_BOOLEAN_INPUT, "index_right","Index right", 0, NULL);
input->ButtonMenu = XrInputCreateAction(input->ActionSet, XR_ACTION_TYPE_BOOLEAN_INPUT, "menu_action", "ButtonMenu", 0, NULL);
input->ButtonA = XrInputCreateAction(input->ActionSet, XR_ACTION_TYPE_BOOLEAN_INPUT, "button_a", "XrButton A", 0, NULL);
input->ButtonB = XrInputCreateAction(input->ActionSet, XR_ACTION_TYPE_BOOLEAN_INPUT, "button_b", "XrButton B", 0, NULL);
input->ButtonX = XrInputCreateAction(input->ActionSet, XR_ACTION_TYPE_BOOLEAN_INPUT, "button_x", "XrButton X", 0, NULL);
input->ButtonY = XrInputCreateAction(input->ActionSet, XR_ACTION_TYPE_BOOLEAN_INPUT, "button_y", "XrButton Y", 0, NULL);
input->GripLeft = XrInputCreateAction(input->ActionSet, XR_ACTION_TYPE_FLOAT_INPUT, "grip_left", "Grip left", 0, NULL);
input->GripRight = XrInputCreateAction(input->ActionSet, XR_ACTION_TYPE_FLOAT_INPUT, "grip_right", "Grip right", 0, NULL);
input->JoystickLeft = XrInputCreateAction(input->ActionSet, XR_ACTION_TYPE_VECTOR2F_INPUT, "move_on_left_joy","Move on left Joy", 0, NULL);
input->JoystickRight = XrInputCreateAction(input->ActionSet, XR_ACTION_TYPE_VECTOR2F_INPUT, "move_on_right_joy","Move on right Joy", 0, NULL);
input->ThumbLeft = XrInputCreateAction(input->ActionSet, XR_ACTION_TYPE_BOOLEAN_INPUT, "thumbstick_left","Thumbstick left", 0, NULL);
input->ThumbRight = XrInputCreateAction(input->ActionSet, XR_ACTION_TYPE_BOOLEAN_INPUT, "thumbstick_right","Thumbstick right", 0, NULL);
input->VibrateLeftFeedback = XrInputCreateAction(input->ActionSet, XR_ACTION_TYPE_VIBRATION_OUTPUT, "vibrate_left_feedback","Vibrate Left Controller", 0, NULL);
input->VibrateRightFeedback = XrInputCreateAction(input->ActionSet, XR_ACTION_TYPE_VIBRATION_OUTPUT, "vibrate_right_feedback","Vibrate Right Controller", 0, NULL);
OXR(xrStringToPath(engine->Instance, "/user/hand/left", &input->LeftHandPath));
OXR(xrStringToPath(engine->Instance, "/user/hand/right", &input->RightHandPath));
input->HandPoseLeft = XrInputCreateAction(input->ActionSet, XR_ACTION_TYPE_POSE_INPUT, "hand_pose_left", NULL,1, &input->LeftHandPath);
input->HandPoseRight = XrInputCreateAction(input->ActionSet, XR_ACTION_TYPE_POSE_INPUT, "hand_pose_right", NULL,1, &input->RightHandPath);
XrPath interactionProfilePath = XR_NULL_PATH;
if (engine->PlatformFlag[PLATFORM_CONTROLLER_QUEST]) {
OXR(xrStringToPath(engine->Instance, "/interaction_profiles/oculus/touch_controller",&interactionProfilePath));
} else if (engine->PlatformFlag[PLATFORM_CONTROLLER_PICO]) {
OXR(xrStringToPath(engine->Instance, "/interaction_profiles/pico/neo3_controller",&interactionProfilePath));
}
// Map bindings
XrInstance instance = engine->Instance;
XrActionSuggestedBinding bindings[32]; // large enough for all profiles
int curr = 0;
if (engine->PlatformFlag[PLATFORM_CONTROLLER_QUEST]) {
bindings[curr++] = XrInputGetBinding(instance, input->IndexLeft, "/user/hand/left/input/trigger");
bindings[curr++] = XrInputGetBinding(instance, input->IndexRight, "/user/hand/right/input/trigger");
bindings[curr++] = XrInputGetBinding(instance, input->ButtonMenu, "/user/hand/left/input/menu/click");
} else if (engine->PlatformFlag[PLATFORM_CONTROLLER_PICO]) {
bindings[curr++] = XrInputGetBinding(instance, input->IndexLeft, "/user/hand/left/input/trigger/click");
bindings[curr++] = XrInputGetBinding(instance, input->IndexRight, "/user/hand/right/input/trigger/click");
bindings[curr++] = XrInputGetBinding(instance, input->ButtonMenu, "/user/hand/left/input/back/click");
bindings[curr++] = XrInputGetBinding(instance, input->ButtonMenu, "/user/hand/right/input/back/click");
}
bindings[curr++] = XrInputGetBinding(instance, input->ButtonX, "/user/hand/left/input/x/click");
bindings[curr++] = XrInputGetBinding(instance, input->ButtonY, "/user/hand/left/input/y/click");
bindings[curr++] = XrInputGetBinding(instance, input->ButtonA, "/user/hand/right/input/a/click");
bindings[curr++] = XrInputGetBinding(instance, input->ButtonB, "/user/hand/right/input/b/click");
bindings[curr++] = XrInputGetBinding(instance, input->GripLeft, "/user/hand/left/input/squeeze/value");
bindings[curr++] = XrInputGetBinding(instance, input->GripRight, "/user/hand/right/input/squeeze/value");
bindings[curr++] = XrInputGetBinding(instance, input->JoystickLeft, "/user/hand/left/input/thumbstick");
bindings[curr++] = XrInputGetBinding(instance, input->JoystickRight, "/user/hand/right/input/thumbstick");
bindings[curr++] = XrInputGetBinding(instance, input->ThumbLeft, "/user/hand/left/input/thumbstick/click");
bindings[curr++] = XrInputGetBinding(instance, input->ThumbRight, "/user/hand/right/input/thumbstick/click");
bindings[curr++] = XrInputGetBinding(instance, input->VibrateLeftFeedback, "/user/hand/left/output/haptic");
bindings[curr++] = XrInputGetBinding(instance, input->VibrateRightFeedback, "/user/hand/right/output/haptic");
bindings[curr++] = XrInputGetBinding(instance, input->HandPoseLeft, "/user/hand/left/input/aim/pose");
bindings[curr++] = XrInputGetBinding(instance, input->HandPoseRight, "/user/hand/right/input/aim/pose");
XrInteractionProfileSuggestedBinding suggested_bindings = {};
suggested_bindings.type = XR_TYPE_INTERACTION_PROFILE_SUGGESTED_BINDING;
suggested_bindings.next = NULL;
suggested_bindings.interactionProfile = interactionProfilePath;
suggested_bindings.suggestedBindings = bindings;
suggested_bindings.countSuggestedBindings = curr;
OXR(xrSuggestInteractionProfileBindings(engine->Instance, &suggested_bindings));
// Attach actions
XrSessionActionSetsAttachInfo attach_info = {};
attach_info.type = XR_TYPE_SESSION_ACTION_SETS_ATTACH_INFO;
attach_info.next = NULL;
attach_info.countActionSets = 1;
attach_info.actionSets = &input->ActionSet;
OXR(xrAttachSessionActionSets(engine->Session, &attach_info));
// Enumerate actions
char string_buffer[256];
XrPath action_paths_buffer[32];
XrAction actions_to_enumerate[] = {input->IndexLeft,
input->IndexRight,
input->ButtonMenu,
input->ButtonA,
input->ButtonB,
input->ButtonX,
input->ButtonY,
input->GripLeft,
input->GripRight,
input->JoystickLeft,
input->JoystickRight,
input->ThumbLeft,
input->ThumbRight,
input->VibrateLeftFeedback,
input->VibrateRightFeedback,
input->HandPoseLeft,
input->HandPoseRight};
for (int i = 0; i < sizeof(actions_to_enumerate) / sizeof(XrAction); i++) {
XrBoundSourcesForActionEnumerateInfo e = {};
e.type = XR_TYPE_BOUND_SOURCES_FOR_ACTION_ENUMERATE_INFO;
e.next = NULL;
e.action = actions_to_enumerate[i];
// Get Count
uint32_t count_output = 0;
OXR(xrEnumerateBoundSourcesForAction(engine->Session, &e, 0, &count_output, NULL));
if (count_output < 32) {
OXR(xrEnumerateBoundSourcesForAction(engine->Session, &e, 32, &count_output,
action_paths_buffer));
for (uint32_t a = 0; a < count_output; ++a) {
XrInputSourceLocalizedNameGetInfo name_info = {};
name_info.type = XR_TYPE_INPUT_SOURCE_LOCALIZED_NAME_GET_INFO;
name_info.next = NULL;
name_info.sourcePath = action_paths_buffer[a];
name_info.whichComponents = XR_INPUT_SOURCE_LOCALIZED_NAME_USER_PATH_BIT |
XR_INPUT_SOURCE_LOCALIZED_NAME_INTERACTION_PROFILE_BIT |
XR_INPUT_SOURCE_LOCALIZED_NAME_COMPONENT_BIT;
uint32_t str_count = 0u;
OXR(xrGetInputSourceLocalizedName(engine->Session, &name_info, 0, &str_count, NULL));
if (str_count < 256) {
OXR(xrGetInputSourceLocalizedName(engine->Session, &name_info, 256, &str_count,
string_buffer));
char path_str[256];
uint32_t str_len = 0;
OXR(xrPathToString(engine->Instance, action_paths_buffer[a],
(uint32_t)sizeof(path_str), &str_len, path_str));
ALOGV("mapped %s -> %s", path_str, string_buffer);
}
}
}
}
input->Initialized = true;
}
uint32_t XrInputGetButtonState(struct XrInput* input, int controller) {
switch (controller) {
case 0:
return input->ButtonsLeft;
case 1:
return input->ButtonsRight;
default:
return 0;
}
}
XrVector2f XrInputGetJoystickState(struct XrInput* input, int controller) {
return input->JoystickState[controller].currentState;
}
XrPosef XrInputGetPose(struct XrInput* input, int controller) {
return input->ControllerPose[controller].pose;
}
void XrInputUpdate(struct XrEngine* engine, struct XrInput* input) {
// sync action data
XrActiveActionSet activeActionSet = {};
activeActionSet.actionSet = input->ActionSet;
activeActionSet.subactionPath = XR_NULL_PATH;
XrActionsSyncInfo sync_info = {};
sync_info.type = XR_TYPE_ACTIONS_SYNC_INFO;
sync_info.next = NULL;
sync_info.countActiveActionSets = 1;
sync_info.activeActionSets = &activeActionSet;
OXR(xrSyncActions(engine->Session, &sync_info));
// query input action states
XrActionStateGetInfo get_info = {};
get_info.type = XR_TYPE_ACTION_STATE_GET_INFO;
get_info.next = NULL;
get_info.subactionPath = XR_NULL_PATH;
XrSession session = engine->Session;
XrInputProcessHaptics(input, session);
if (input->LeftControllerSpace == XR_NULL_HANDLE) {
input->LeftControllerSpace = XrInputCreateActionSpace(session, input->HandPoseLeft, input->LeftHandPath);
}
if (input->RightControllerSpace == XR_NULL_HANDLE) {
input->RightControllerSpace = XrInputCreateActionSpace(session, input->HandPoseRight, input->RightHandPath);
}
// button mapping
input->ButtonsLeft = 0;
if (XrInputGetActionStateBoolean(session, input->ButtonMenu).currentState)
input->ButtonsLeft |= (int)Enter;
if (XrInputGetActionStateBoolean(session, input->ButtonX).currentState)
input->ButtonsLeft |= (int)X;
if (XrInputGetActionStateBoolean(session, input->ButtonY).currentState)
input->ButtonsLeft |= (int)Y;
if (XrInputGetActionStateBoolean(session, input->IndexLeft).currentState)
input->ButtonsLeft |= (int)Trigger;
if (XrInputGetActionStateFloat(session, input->GripLeft).currentState > 0.5f)
input->ButtonsLeft |= (int)Grip;
if (XrInputGetActionStateBoolean(session, input->ThumbLeft).currentState)
input->ButtonsLeft |= (int)LThumb;
input->ButtonsRight = 0;
if (XrInputGetActionStateBoolean(session, input->ButtonA).currentState)
input->ButtonsRight |= (int)A;
if (XrInputGetActionStateBoolean(session, input->ButtonB).currentState)
input->ButtonsRight |= (int)B;
if (XrInputGetActionStateBoolean(session, input->IndexRight).currentState)
input->ButtonsRight |= (int)Trigger;
if (XrInputGetActionStateFloat(session, input->GripRight).currentState > 0.5f)
input->ButtonsRight |= (int)Grip;
if (XrInputGetActionStateBoolean(session, input->ThumbRight).currentState)
input->ButtonsRight |= (int)RThumb;
// thumbstick
input->JoystickState[0] = XrInputGetActionStateVector2(session, input->JoystickLeft);
input->JoystickState[1] = XrInputGetActionStateVector2(session, input->JoystickRight);
if (input->JoystickState[0].currentState.x > 0.5)
input->ButtonsLeft |= (int)Right;
if (input->JoystickState[0].currentState.x < -0.5)
input->ButtonsLeft |= (int)Left;
if (input->JoystickState[0].currentState.y > 0.5)
input->ButtonsLeft |= (int)Up;
if (input->JoystickState[0].currentState.y < -0.5)
input->ButtonsLeft |= (int)Down;
if (input->JoystickState[1].currentState.x > 0.5)
input->ButtonsRight |= (int)Right;
if (input->JoystickState[1].currentState.x < -0.5)
input->ButtonsRight |= (int)Left;
if (input->JoystickState[1].currentState.y > 0.5)
input->ButtonsRight |= (int)Up;
if (input->JoystickState[1].currentState.y < -0.5)
input->ButtonsRight |= (int)Down;
// pose
for (int i = 0; i < 2; i++) {
memset(&input->ControllerPose[i], 0, sizeof(input->ControllerPose[i]));
input->ControllerPose[i].type = XR_TYPE_SPACE_LOCATION;
XrSpace aim_space[] = {input->LeftControllerSpace, input->RightControllerSpace};
xrLocateSpace(aim_space[i], engine->CurrentSpace,
(XrTime)(engine->PredictedDisplayTime), &input->ControllerPose[i]);
}
}
void XrInputVibrate(struct XrInput* input, int duration, int chan, float intensity) {
for (int i = 0; i < 2; ++i) {
int channel = i & chan;
if (channel) {
if (input->VibrationChannelDuration[channel] > 0.0f)
return;
if (input->VibrationChannelDuration[channel] == -1.0f && duration != 0.0f)
return;
input->VibrationChannelDuration[channel] = (float)duration;
input->VibrationChannelIntensity[channel] = intensity;
}
}
}
XrAction XrInputCreateAction(XrActionSet output_set, XrActionType type, const char* name,
const char* desc, int count_subaction_path, XrPath* subaction_path) {
XrActionCreateInfo action_info = {};
action_info.type = XR_TYPE_ACTION_CREATE_INFO;
action_info.next = NULL;
action_info.actionType = type;
if (count_subaction_path > 0) {
action_info.countSubactionPaths = count_subaction_path;
action_info.subactionPaths = subaction_path;
}
strcpy(action_info.actionName, name);
strcpy(action_info.localizedActionName, desc ? desc : name);
XrAction output = XR_NULL_HANDLE;
OXR(xrCreateAction(output_set, &action_info, &output));
return output;
}
XrActionSet XrInputCreateActionSet(XrInstance instance, const char* name, const char* desc) {
XrActionSetCreateInfo action_set_info = {};
action_set_info.type = XR_TYPE_ACTION_SET_CREATE_INFO;
action_set_info.next = NULL;
action_set_info.priority = 1;
strcpy(action_set_info.actionSetName, name);
strcpy(action_set_info.localizedActionSetName, desc);
XrActionSet output = XR_NULL_HANDLE;
OXR(xrCreateActionSet(instance, &action_set_info, &output));
return output;
}
XrSpace XrInputCreateActionSpace(XrSession session, XrAction action, XrPath subaction_path) {
XrActionSpaceCreateInfo action_space_info = {};
action_space_info.type = XR_TYPE_ACTION_SPACE_CREATE_INFO;
action_space_info.action = action;
action_space_info.poseInActionSpace.orientation.w = 1.0f;
action_space_info.subactionPath = subaction_path;
XrSpace output = XR_NULL_HANDLE;
OXR(xrCreateActionSpace(session, &action_space_info, &output));
return output;
}
XrActionStateBoolean XrInputGetActionStateBoolean(XrSession session, XrAction action) {
XrActionStateGetInfo get_info = {};
get_info.type = XR_TYPE_ACTION_STATE_GET_INFO;
get_info.action = action;
XrActionStateBoolean state = {};
state.type = XR_TYPE_ACTION_STATE_BOOLEAN;
OXR(xrGetActionStateBoolean(session, &get_info, &state));
return state;
}
XrActionStateFloat XrInputGetActionStateFloat(XrSession session, XrAction action) {
XrActionStateGetInfo get_info = {};
get_info.type = XR_TYPE_ACTION_STATE_GET_INFO;
get_info.action = action;
XrActionStateFloat state = {};
state.type = XR_TYPE_ACTION_STATE_FLOAT;
OXR(xrGetActionStateFloat(session, &get_info, &state));
return state;
}
XrActionStateVector2f XrInputGetActionStateVector2(XrSession session, XrAction action) {
XrActionStateGetInfo get_info = {};
get_info.type = XR_TYPE_ACTION_STATE_GET_INFO;
get_info.action = action;
XrActionStateVector2f state = {};
state.type = XR_TYPE_ACTION_STATE_VECTOR2F;
OXR(xrGetActionStateVector2f(session, &get_info, &state));
return state;
}
XrActionSuggestedBinding XrInputGetBinding(XrInstance instance, XrAction action, const char* name) {
XrPath bindingPath;
OXR(xrStringToPath(instance, name, &bindingPath));
XrActionSuggestedBinding output;
output.action = action;
output.binding = bindingPath;
return output;
}
int XrInputGetMilliseconds(struct XrInput* input) {
struct timeval tp;
gettimeofday(&tp, NULL);
if (!input->SysTimeBase) {
input->SysTimeBase = tp.tv_sec;
return tp.tv_usec / 1000;
}
return (tp.tv_sec - input->SysTimeBase) * 1000 + tp.tv_usec / 1000;
}
void XrInputProcessHaptics(struct XrInput* input, XrSession session) {
static float last_frame_timestamp = 0.0f;
float timestamp = (float)(XrInputGetMilliseconds(input));
float frametime = timestamp - last_frame_timestamp;
last_frame_timestamp = timestamp;
for (int i = 0; i < 2; ++i) {
if (input->VibrationChannelDuration[i] > 0.0f || input->VibrationChannelDuration[i] == -1.0f) {
// fire haptics using output action
XrHapticVibration vibration = {};
vibration.type = XR_TYPE_HAPTIC_VIBRATION;
vibration.next = NULL;
vibration.amplitude = input->VibrationChannelIntensity[i];
vibration.duration = ToXrTime(input->VibrationChannelDuration[i]);
vibration.frequency = 3000;
XrHapticActionInfo haptic_info = {};
haptic_info.type = XR_TYPE_HAPTIC_ACTION_INFO;
haptic_info.next = NULL;
haptic_info.action = i == 0 ? input->VibrateLeftFeedback : input->VibrateRightFeedback;
OXR(xrApplyHapticFeedback(session, &haptic_info, (const XrHapticBaseHeader*)&vibration));
if (input->VibrationChannelDuration[i] != -1.0f) {
input->VibrationChannelDuration[i] -= frametime;
if (input->VibrationChannelDuration[i] < 0.0f) {
input->VibrationChannelDuration[i] = 0.0f;
input->VibrationChannelIntensity[i] = 0.0f;
}
}
} else {
// Stop haptics
XrHapticActionInfo haptic_info = {};
haptic_info.type = XR_TYPE_HAPTIC_ACTION_INFO;
haptic_info.next = NULL;
haptic_info.action = i == 0 ? input->VibrateLeftFeedback : input->VibrateRightFeedback;
OXR(xrStopHapticFeedback(session, &haptic_info));
}
}
}

View File

@@ -0,0 +1,82 @@
#pragma once
#include "engine.h"
enum XrButton {
A = 0x00000001, // Set for trigger pulled on the Gear VR and Go Controllers
B = 0x00000002,
RThumb = 0x00000004,
X = 0x00000100,
Y = 0x00000200,
LThumb = 0x00000400,
Up = 0x00010000,
Down = 0x00020000,
Left = 0x00040000,
Right = 0x00080000,
Enter = 0x00100000, //< Set for touchpad click on the Go Controller, menu
// button on Left Quest Controller
Back = 0x00200000, //< Back button on the Go Controller (only set when
// a short press comes up)
Grip = 0x04000000, //< grip trigger engaged
Trigger = 0x20000000 //< Index Trigger engaged
};
struct XrInput {
bool Initialized;
// OpenXR controller mapping
XrActionSet ActionSet;
XrPath LeftHandPath;
XrPath RightHandPath;
XrAction HandPoseLeft;
XrAction HandPoseRight;
XrAction IndexLeft;
XrAction IndexRight;
XrAction ButtonMenu;
XrAction ButtonA;
XrAction ButtonB;
XrAction ButtonX;
XrAction ButtonY;
XrAction GripLeft;
XrAction GripRight;
XrAction JoystickLeft;
XrAction JoystickRight;
XrAction ThumbLeft;
XrAction ThumbRight;
XrAction VibrateLeftFeedback;
XrAction VibrateRightFeedback;
XrSpace LeftControllerSpace;
XrSpace RightControllerSpace;
// Controller state
uint32_t ButtonsLeft;
uint32_t ButtonsRight;
XrSpaceLocation ControllerPose[2];
XrActionStateVector2f JoystickState[2];
float VibrationChannelDuration[2];
float VibrationChannelIntensity[2];
// Timer
unsigned long SysTimeBase;
};
void XrInputInit(struct XrEngine* engine, struct XrInput* input);
uint32_t XrInputGetButtonState(struct XrInput* input, int controller);
XrVector2f XrInputGetJoystickState(struct XrInput* input, int controller);
XrPosef XrInputGetPose(struct XrInput* input, int controller);
void XrInputUpdate(struct XrEngine* engine, struct XrInput* input);
void XrInputVibrate(struct XrInput* input, int duration, int chan, float intensity);
XrAction XrInputCreateAction(XrActionSet output_set, XrActionType type, const char* name,
const char* desc, int count_subaction_path, XrPath* subaction_path);
XrActionSet XrInputCreateActionSet(XrInstance instance, const char* name, const char* desc);
XrSpace XrInputCreateActionSpace(XrSession session, XrAction action, XrPath subaction_path);
XrActionStateBoolean XrInputGetActionStateBoolean(XrSession session, XrAction action);
XrActionStateFloat XrInputGetActionStateFloat(XrSession session, XrAction action);
XrActionStateVector2f XrInputGetActionStateVector2(XrSession session, XrAction action);
XrActionSuggestedBinding XrInputGetBinding(XrInstance instance, XrAction action, const char* name);
int XrInputGetMilliseconds(struct XrInput* input);
void XrInputProcessHaptics(struct XrInput* input, XrSession session);

View File

@@ -0,0 +1,194 @@
#include "math.h"
#include <math.h>
#include <string.h>
double FromXrTime(const XrTime time) {
return (time * 1e-9);
}
XrTime ToXrTime(const double time_in_seconds) {
return (XrTime)(time_in_seconds * 1e9);
}
float ToDegrees(float rad) {
return (float)(rad / M_PI * 180.0f);
}
float ToRadians(float deg) {
return (float)(deg * M_PI / 180.0f);
}
/*
================================================================================
XrQuaternionf
================================================================================
*/
XrQuaternionf XrQuaternionfCreateFromVectorAngle(const XrVector3f axis, const float angle) {
XrQuaternionf r;
if (XrVector3fLengthSquared(axis) == 0.0f) {
r.x = 0;
r.y = 0;
r.z = 0;
r.w = 1;
return r;
}
XrVector3f unitAxis = XrVector3fNormalized(axis);
float sinHalfAngle = sinf(angle * 0.5f);
r.w = cosf(angle * 0.5f);
r.x = unitAxis.x * sinHalfAngle;
r.y = unitAxis.y * sinHalfAngle;
r.z = unitAxis.z * sinHalfAngle;
return r;
}
XrQuaternionf XrQuaternionfMultiply(const XrQuaternionf a, const XrQuaternionf b) {
XrQuaternionf c;
c.x = a.w * b.x + a.x * b.w + a.y * b.z - a.z * b.y;
c.y = a.w * b.y - a.x * b.z + a.y * b.w + a.z * b.x;
c.z = a.w * b.z + a.x * b.y - a.y * b.x + a.z * b.w;
c.w = a.w * b.w - a.x * b.x - a.y * b.y - a.z * b.z;
return c;
}
XrVector3f XrQuaternionfEulerAngles(const XrQuaternionf q) {
float M[16];
XrQuaternionfToMatrix4f(&q, M);
XrVector4f v1 = {0, 0, -1, 0};
XrVector4f v2 = {1, 0, 0, 0};
XrVector4f v3 = {0, 1, 0, 0};
XrVector4f forwardInVRSpace = XrVector4fMultiplyMatrix4f(M, &v1);
XrVector4f rightInVRSpace = XrVector4fMultiplyMatrix4f(M, &v2);
XrVector4f upInVRSpace = XrVector4fMultiplyMatrix4f(M, &v3);
XrVector3f forward = {-forwardInVRSpace.z, -forwardInVRSpace.x, forwardInVRSpace.y};
XrVector3f right = {-rightInVRSpace.z, -rightInVRSpace.x, rightInVRSpace.y};
XrVector3f up = {-upInVRSpace.z, -upInVRSpace.x, upInVRSpace.y};
XrVector3f forwardNormal = XrVector3fNormalized(forward);
XrVector3f rightNormal = XrVector3fNormalized(right);
XrVector3f upNormal = XrVector3fNormalized(up);
return XrVector3fGetAnglesFromVectors(forwardNormal, rightNormal, upNormal);
}
void XrQuaternionfToMatrix4f(const XrQuaternionf* q, float* m) {
const float ww = q->w * q->w;
const float xx = q->x * q->x;
const float yy = q->y * q->y;
const float zz = q->z * q->z;
float M[4][4];
M[0][0] = ww + xx - yy - zz;
M[0][1] = 2 * (q->x * q->y - q->w * q->z);
M[0][2] = 2 * (q->x * q->z + q->w * q->y);
M[0][3] = 0;
M[1][0] = 2 * (q->x * q->y + q->w * q->z);
M[1][1] = ww - xx + yy - zz;
M[1][2] = 2 * (q->y * q->z - q->w * q->x);
M[1][3] = 0;
M[2][0] = 2 * (q->x * q->z - q->w * q->y);
M[2][1] = 2 * (q->y * q->z + q->w * q->x);
M[2][2] = ww - xx - yy + zz;
M[2][3] = 0;
M[3][0] = 0;
M[3][1] = 0;
M[3][2] = 0;
M[3][3] = 1;
memcpy(m, &M, sizeof(float) * 16);
}
/*
================================================================================
XrVector3f, XrVector4f
================================================================================
*/
float XrVector3fDistance(const XrVector3f a, const XrVector3f b) {
XrVector3f diff;
diff.x = a.x - b.x;
diff.y = a.y - b.y;
diff.z = a.z - b.z;
return sqrt(XrVector3fLengthSquared(diff));
}
float XrVector3fLengthSquared(const XrVector3f v) {
return v.x * v.x + v.y * v.y + v.z * v.z;
}
XrVector3f XrVector3fGetAnglesFromVectors(XrVector3f forward, XrVector3f right, XrVector3f up) {
float sp = -forward.z;
float cp_x_cy = forward.x;
float cp_x_sy = forward.y;
float cp_x_sr = -right.z;
float cp_x_cr = up.z;
float yaw = atan2(cp_x_sy, cp_x_cy);
float roll = atan2(cp_x_sr, cp_x_cr);
float cy = cos(yaw);
float sy = sin(yaw);
float cr = cos(roll);
float sr = sin(roll);
float cp;
if (fabs(cy) > EPSILON) {
cp = cp_x_cy / cy;
} else if (fabs(sy) > EPSILON) {
cp = cp_x_sy / sy;
} else if (fabs(sr) > EPSILON) {
cp = cp_x_sr / sr;
} else if (fabs(cr) > EPSILON) {
cp = cp_x_cr / cr;
} else {
cp = cos(asin(sp));
}
float pitch = atan2(sp, cp);
XrVector3f angles;
angles.x = ToDegrees(pitch);
angles.y = ToDegrees(yaw);
angles.z = ToDegrees(roll);
return angles;
}
XrVector3f XrVector3fNormalized(const XrVector3f v) {
float rcpLen = 1.0f / sqrtf(XrVector3fLengthSquared(v));
return XrVector3fScalarMultiply(v, rcpLen);
}
XrVector3f XrVector3fScalarMultiply(const XrVector3f v, float scale) {
XrVector3f u;
u.x = v.x * scale;
u.y = v.y * scale;
u.z = v.z * scale;
return u;
}
XrVector4f XrVector4fMultiplyMatrix4f(const float* m, const XrVector4f* v) {
float M[4][4];
memcpy(&M, m, sizeof(float) * 16);
XrVector4f out;
out.x = M[0][0] * v->x + M[0][1] * v->y + M[0][2] * v->z + M[0][3] * v->w;
out.y = M[1][0] * v->x + M[1][1] * v->y + M[1][2] * v->z + M[1][3] * v->w;
out.z = M[2][0] * v->x + M[2][1] * v->y + M[2][2] * v->z + M[2][3] * v->w;
out.w = M[3][0] * v->x + M[3][1] * v->y + M[3][2] * v->z + M[3][3] * v->w;
return out;
}

View File

@@ -0,0 +1,26 @@
#pragma once
#include <openxr/openxr.h>
#ifndef EPSILON
#define EPSILON 0.001f
#endif
double FromXrTime(const XrTime time);
XrTime ToXrTime(const double time_in_seconds);
float ToDegrees(float rad);
float ToRadians(float deg);
// XrQuaternionf
XrQuaternionf XrQuaternionfCreateFromVectorAngle(const XrVector3f axis, const float angle);
XrQuaternionf XrQuaternionfMultiply(const XrQuaternionf a, const XrQuaternionf b);
XrVector3f XrQuaternionfEulerAngles(const XrQuaternionf q);
void XrQuaternionfToMatrix4f(const XrQuaternionf* q, float* m);
// XrVector3f, XrVector4f
float XrVector3fDistance(const XrVector3f a, const XrVector3f b);
float XrVector3fLengthSquared(const XrVector3f v);
XrVector3f XrVector3fGetAnglesFromVectors(XrVector3f forward, XrVector3f right, XrVector3f up);
XrVector3f XrVector3fNormalized(const XrVector3f v);
XrVector3f XrVector3fScalarMultiply(const XrVector3f v, float scale);
XrVector4f XrVector4fMultiplyMatrix4f(const float* m, const XrVector4f* v);

View File

@@ -0,0 +1,565 @@
#include <malloc.h>
#include <assert.h>
#include <string.h>
#include <math.h>
#include "engine.h"
#include "math.h"
#include "renderer.h"
#define DECL_PFN(pfn) PFN_##pfn pfn = NULL
#define INIT_PFN(pfn) OXR(xrGetInstanceProcAddr(engine->Instance, #pfn, (PFN_xrVoidFunction*)(&pfn)))
DECL_PFN(xrCreatePassthroughFB);
DECL_PFN(xrDestroyPassthroughFB);
DECL_PFN(xrPassthroughStartFB);
DECL_PFN(xrPassthroughPauseFB);
DECL_PFN(xrCreatePassthroughLayerFB);
DECL_PFN(xrDestroyPassthroughLayerFB);
DECL_PFN(xrPassthroughLayerPauseFB);
DECL_PFN(xrPassthroughLayerResumeFB);
void XrRendererInit(struct XrEngine* engine, struct XrRenderer* renderer) {
if (renderer->Initialized) {
XrRendererDestroy(engine, renderer);
}
memset(renderer, 0, sizeof(renderer));
if (engine->PlatformFlag[PLATFORM_EXTENSION_PASSTHROUGH]) {
INIT_PFN(xrCreatePassthroughFB);
INIT_PFN(xrDestroyPassthroughFB);
INIT_PFN(xrPassthroughStartFB);
INIT_PFN(xrPassthroughPauseFB);
INIT_PFN(xrCreatePassthroughLayerFB);
INIT_PFN(xrDestroyPassthroughLayerFB);
INIT_PFN(xrPassthroughLayerPauseFB);
INIT_PFN(xrPassthroughLayerResumeFB);
}
int eyeW, eyeH;
XrRendererGetResolution(engine, renderer, &eyeW, &eyeH);
renderer->ConfigInt[CONFIG_VIEWPORT_WIDTH] = eyeW;
renderer->ConfigInt[CONFIG_VIEWPORT_HEIGHT] = eyeH;
// Get the viewport configuration info for the chosen viewport configuration type.
renderer->ViewportConfig.type = XR_TYPE_VIEW_CONFIGURATION_PROPERTIES;
OXR(xrGetViewConfigurationProperties(engine->Instance, engine->SystemId,
XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO,
&renderer->ViewportConfig));
uint32_t num_spaces = 0;
OXR(xrEnumerateReferenceSpaces(engine->Session, 0, &num_spaces, NULL));
XrReferenceSpaceType* spaces = (XrReferenceSpaceType*)malloc(num_spaces * sizeof(XrReferenceSpaceType));
OXR(xrEnumerateReferenceSpaces(engine->Session, num_spaces, &num_spaces, spaces));
for (uint32_t i = 0; i < num_spaces; i++) {
if (spaces[i] == XR_REFERENCE_SPACE_TYPE_STAGE) {
renderer->StageSupported = true;
break;
}
}
free(spaces);
if (engine->CurrentSpace == XR_NULL_HANDLE) {
XrRendererRecenter(engine, renderer);
}
renderer->Projections = (XrView*)(malloc(XrMaxNumEyes * sizeof(XrView)));
for (int eye = 0; eye < XrMaxNumEyes; eye++) {
memset(&renderer->Projections[eye], 0, sizeof(XrView));
renderer->Projections[eye].type = XR_TYPE_VIEW;
}
// Create framebuffers.
int width = renderer->ViewConfig[0].recommendedImageRectWidth;
int height = renderer->ViewConfig[0].recommendedImageRectHeight;
for (int i = 0; i < XrMaxNumEyes; i++) {
XrFramebufferCreate(&renderer->Framebuffer[i], engine->Session, width, height);
}
if (engine->PlatformFlag[PLATFORM_EXTENSION_PASSTHROUGH]) {
XrPassthroughCreateInfoFB ptci = {XR_TYPE_PASSTHROUGH_CREATE_INFO_FB};
XrResult result;
OXR(result = xrCreatePassthroughFB(engine->Session, &ptci, &renderer->Passthrough));
if (XR_SUCCEEDED(result)) {
XrPassthroughLayerCreateInfoFB plci = {XR_TYPE_PASSTHROUGH_LAYER_CREATE_INFO_FB};
plci.passthrough = renderer->Passthrough;
plci.purpose = XR_PASSTHROUGH_LAYER_PURPOSE_RECONSTRUCTION_FB;
OXR(xrCreatePassthroughLayerFB(engine->Session, &plci, &renderer->PassthroughLayer));
}
OXR(xrPassthroughStartFB(renderer->Passthrough));
OXR(xrPassthroughLayerResumeFB(renderer->PassthroughLayer));
}
renderer->Initialized = true;
}
void XrRendererDestroy(struct XrEngine* engine, struct XrRenderer* renderer) {
if (!renderer->Initialized) {
return;
}
if (engine->PlatformFlag[PLATFORM_EXTENSION_PASSTHROUGH]) {
if (renderer->PassthroughRunning) {
OXR(xrPassthroughLayerPauseFB(renderer->PassthroughLayer));
}
OXR(xrPassthroughPauseFB(renderer->Passthrough));
OXR(xrDestroyPassthroughFB(renderer->Passthrough));
renderer->Passthrough = XR_NULL_HANDLE;
}
for (int i = 0; i < XrMaxNumEyes; i++) {
XrFramebufferDestroy(&renderer->Framebuffer[i]);
}
free(renderer->Projections);
renderer->Initialized = false;
}
void XrRendererGetResolution(struct XrEngine* engine, struct XrRenderer* renderer, int* pWidth, int* pHeight) {
static int width = 0;
static int height = 0;
if (engine) {
// Enumerate the viewport configurations.
uint32_t viewport_config_count = 0;
OXR(xrEnumerateViewConfigurations(engine->Instance, engine->SystemId, 0,
&viewport_config_count, NULL));
XrViewConfigurationType* viewport_configs =
(XrViewConfigurationType*)malloc(viewport_config_count * sizeof(XrViewConfigurationType));
OXR(xrEnumerateViewConfigurations(engine->Instance, engine->SystemId,
viewport_config_count, &viewport_config_count,
viewport_configs));
for (uint32_t i = 0; i < viewport_config_count; i++) {
const XrViewConfigurationType viewport_config_type = viewport_configs[i];
ALOGV("Viewport configuration type %d", (int)viewport_config_type);
XrViewConfigurationProperties viewport_config;
viewport_config.type = XR_TYPE_VIEW_CONFIGURATION_PROPERTIES;
OXR(xrGetViewConfigurationProperties(engine->Instance, engine->SystemId,
viewport_config_type, &viewport_config));
uint32_t view_count;
OXR(xrEnumerateViewConfigurationViews(engine->Instance, engine->SystemId,
viewport_config_type, 0, &view_count, NULL));
if (view_count > 0) {
XrViewConfigurationView* elements =
(XrViewConfigurationView*)malloc(view_count * sizeof(XrViewConfigurationView));
for (uint32_t e = 0; e < view_count; e++) {
elements[e].type = XR_TYPE_VIEW_CONFIGURATION_VIEW;
elements[e].next = NULL;
}
OXR(xrEnumerateViewConfigurationViews(engine->Instance, engine->SystemId,
viewport_config_type, view_count, &view_count,
elements));
// Cache the view config properties for the selected config type.
if (viewport_config_type == XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO) {
assert(view_count == XrMaxNumEyes);
for (uint32_t e = 0; e < view_count; e++) {
renderer->ViewConfig[e] = elements[e];
}
}
free(elements);
} else {
ALOGE("Empty viewport configuration");
}
}
free(viewport_configs);
*pWidth = width = renderer->ViewConfig[0].recommendedImageRectWidth;
*pHeight = height = renderer->ViewConfig[0].recommendedImageRectHeight;
} else {
// use cached values
*pWidth = width;
*pHeight = height;
}
}
bool XrRendererInitFrame(struct XrEngine* engine, struct XrRenderer* renderer) {
if (!renderer->Initialized) {
return false;
}
XrRendererHandleXrEvents(engine, renderer);
if (!renderer->SessionActive) {
return false;
}
XrRendererUpdateStageBounds(engine);
// Update passthrough
if (renderer->PassthroughRunning != renderer->ConfigInt[CONFIG_PASSTHROUGH]) {
if (renderer->ConfigInt[CONFIG_PASSTHROUGH]) {
OXR(xrPassthroughLayerResumeFB(renderer->PassthroughLayer));
} else {
OXR(xrPassthroughLayerPauseFB(renderer->PassthroughLayer));
}
renderer->PassthroughRunning = renderer->ConfigInt[CONFIG_PASSTHROUGH];
}
XrEngineWaitForFrame(engine);
XrViewLocateInfo projection_info = {};
projection_info.type = XR_TYPE_VIEW_LOCATE_INFO;
projection_info.next = NULL;
projection_info.viewConfigurationType = renderer->ViewportConfig.viewConfigurationType;
projection_info.displayTime = engine->PredictedDisplayTime;
projection_info.space = engine->CurrentSpace;
XrViewState view_state = {XR_TYPE_VIEW_STATE, NULL};
uint32_t projection_capacity = XrMaxNumEyes;
uint32_t projection_count = projection_capacity;
OXR(xrLocateViews(engine->Session, &projection_info, &view_state, projection_capacity,
&projection_count, renderer->Projections));
// Get the HMD pose, predicted for the middle of the time period during which
// the new eye images will be displayed. The number of frames predicted ahead
// depends on the pipeline depth of the engine and the synthesis rate.
// The better the prediction, the less black will be pulled in at the edges.
XrFrameBeginInfo begin_frame_info = {};
begin_frame_info.type = XR_TYPE_FRAME_BEGIN_INFO;
begin_frame_info.next = NULL;
OXR(xrBeginFrame(engine->Session, &begin_frame_info));
renderer->Fov.angleLeft = 0;
renderer->Fov.angleRight = 0;
renderer->Fov.angleUp = 0;
renderer->Fov.angleDown = 0;
for (int eye = 0; eye < XrMaxNumEyes; eye++) {
renderer->Fov.angleLeft += renderer->Projections[eye].fov.angleLeft / 2.0f;
renderer->Fov.angleRight += renderer->Projections[eye].fov.angleRight / 2.0f;
renderer->Fov.angleUp += renderer->Projections[eye].fov.angleUp / 2.0f;
renderer->Fov.angleDown += renderer->Projections[eye].fov.angleDown / 2.0f;
renderer->InvertedViewPose[eye] = renderer->Projections[eye].pose;
}
renderer->HmdOrientation = XrQuaternionfEulerAngles(renderer->InvertedViewPose[0].orientation);
renderer->LayerCount = 0;
memset(renderer->Layers, 0, sizeof(XrCompositorLayer) * XrMaxLayerCount);
return true;
}
void XrRendererBeginFrame(struct XrRenderer* renderer, int fbo_index) {
renderer->ConfigInt[CONFIG_CURRENT_FBO] = fbo_index;
XrFramebufferAcquire(&renderer->Framebuffer[fbo_index]);
}
void XrRendererEndFrame(struct XrRenderer* renderer) {
int fbo_index = renderer->ConfigInt[CONFIG_CURRENT_FBO];
XrFramebufferRelease(&renderer->Framebuffer[fbo_index]);
}
void XrRendererFinishFrame(struct XrEngine* engine, struct XrRenderer* renderer) {
int x = 0;
int y = 0;
int w = renderer->Framebuffer[0].Width;
int h = renderer->Framebuffer[0].Height;
if (renderer->ConfigInt[CONFIG_SBS]) {
w /= 2;
}
int mode = renderer->ConfigInt[CONFIG_MODE];
XrCompositionLayerProjectionView projection_layer_elements[2] = {};
if ((mode == RENDER_MODE_MONO_6DOF) || (mode == RENDER_MODE_STEREO_6DOF)) {
renderer->ConfigFloat[CONFIG_MENU_YAW] = renderer->HmdOrientation.y;
for (int eye = 0; eye < XrMaxNumEyes; eye++) {
struct XrFramebuffer* framebuffer = &renderer->Framebuffer[0];
XrPosef pose = renderer->InvertedViewPose[0];
if (renderer->ConfigInt[CONFIG_SBS] && (eye == 1)) {
x += w;
} else if (mode != RENDER_MODE_MONO_6DOF) {
framebuffer = &renderer->Framebuffer[eye];
pose = renderer->InvertedViewPose[eye];
}
XrVector3f pitch_axis = {1, 0, 0};
XrVector3f yaw_axis = {0, 1, 0};
XrVector3f rotation = XrQuaternionfEulerAngles(pose.orientation);
XrQuaternionf pitch = XrQuaternionfCreateFromVectorAngle(pitch_axis, -ToRadians(rotation.x));
XrQuaternionf yaw = XrQuaternionfCreateFromVectorAngle(yaw_axis, ToRadians(rotation.y));
pose.orientation = XrQuaternionfMultiply(pitch, yaw);
memset(&projection_layer_elements[eye], 0, sizeof(XrCompositionLayerProjectionView));
projection_layer_elements[eye].type = XR_TYPE_COMPOSITION_LAYER_PROJECTION_VIEW;
projection_layer_elements[eye].pose = pose;
projection_layer_elements[eye].fov = renderer->Fov;
memset(&projection_layer_elements[eye].subImage, 0, sizeof(XrSwapchainSubImage));
projection_layer_elements[eye].subImage.swapchain = framebuffer->Handle;
projection_layer_elements[eye].subImage.imageRect.offset.x = x;
projection_layer_elements[eye].subImage.imageRect.offset.y = y;
projection_layer_elements[eye].subImage.imageRect.extent.width = w;
projection_layer_elements[eye].subImage.imageRect.extent.height = h;
projection_layer_elements[eye].subImage.imageArrayIndex = 0;
}
XrCompositionLayerProjection projection_layer = {};
projection_layer.type = XR_TYPE_COMPOSITION_LAYER_PROJECTION;
projection_layer.layerFlags = XR_COMPOSITION_LAYER_BLEND_TEXTURE_SOURCE_ALPHA_BIT;
projection_layer.layerFlags |= XR_COMPOSITION_LAYER_CORRECT_CHROMATIC_ABERRATION_BIT;
projection_layer.space = engine->CurrentSpace;
projection_layer.viewCount = XrMaxNumEyes;
projection_layer.views = projection_layer_elements;
renderer->Layers[renderer->LayerCount++].projection = projection_layer;
} else if ((mode == RENDER_MODE_MONO_SCREEN) || (mode == RENDER_MODE_STEREO_SCREEN)) {
// Flat screen pose
float distance = renderer->ConfigFloat[CONFIG_CANVAS_DISTANCE];
float menu_pitch = ToRadians(renderer->ConfigFloat[CONFIG_MENU_PITCH]);
float menu_yaw = ToRadians(renderer->ConfigFloat[CONFIG_MENU_YAW]);
XrVector3f pos = {renderer->InvertedViewPose[0].position.x - sinf(menu_yaw) * cosf(menu_pitch) * distance,
renderer->InvertedViewPose[0].position.y - sinf(menu_pitch) * distance,
renderer->InvertedViewPose[0].position.z - cosf(menu_yaw) * cosf(menu_pitch) * distance};
XrVector3f pitch_axis = {1, 0, 0};
XrVector3f yaw_axis = {0, 1, 0};
XrQuaternionf pitch = XrQuaternionfCreateFromVectorAngle(pitch_axis, -menu_pitch);
XrQuaternionf yaw = XrQuaternionfCreateFromVectorAngle(yaw_axis, menu_yaw);
// Setup quad layer
struct XrFramebuffer* framebuffer = &renderer->Framebuffer[0];
XrCompositionLayerQuad quad_layer = {};
quad_layer.type = XR_TYPE_COMPOSITION_LAYER_QUAD;
quad_layer.layerFlags = XR_COMPOSITION_LAYER_BLEND_TEXTURE_SOURCE_ALPHA_BIT;
quad_layer.space = engine->CurrentSpace;
memset(&quad_layer.subImage, 0, sizeof(XrSwapchainSubImage));
quad_layer.subImage.imageRect.offset.x = x;
quad_layer.subImage.imageRect.offset.y = y;
quad_layer.subImage.imageRect.extent.width = w;
quad_layer.subImage.imageRect.extent.height = h;
quad_layer.subImage.swapchain = framebuffer->Handle;
quad_layer.subImage.imageArrayIndex = 0;
quad_layer.pose.orientation = XrQuaternionfMultiply(pitch, yaw);
quad_layer.pose.position = pos;
quad_layer.size.width = 4;
quad_layer.size.height = 4;
// Build the cylinder layer
if (renderer->ConfigInt[CONFIG_SBS]) {
quad_layer.eyeVisibility = XR_EYE_VISIBILITY_LEFT;
renderer->Layers[renderer->LayerCount++].quad = quad_layer;
quad_layer.eyeVisibility = XR_EYE_VISIBILITY_RIGHT;
quad_layer.subImage.imageRect.offset.x = w;
renderer->Layers[renderer->LayerCount++].quad = quad_layer;
} else if (mode == RENDER_MODE_MONO_SCREEN) {
quad_layer.eyeVisibility = XR_EYE_VISIBILITY_BOTH;
renderer->Layers[renderer->LayerCount++].quad = quad_layer;
} else {
quad_layer.eyeVisibility = XR_EYE_VISIBILITY_LEFT;
renderer->Layers[renderer->LayerCount++].quad = quad_layer;
quad_layer.eyeVisibility = XR_EYE_VISIBILITY_RIGHT;
quad_layer.subImage.swapchain = renderer->Framebuffer[1].Handle;
renderer->Layers[renderer->LayerCount++].quad = quad_layer;
}
} else {
assert(false);
}
// Compose the layers for this frame.
const XrCompositionLayerBaseHeader* layers[XrMaxLayerCount] = {};
for (int i = 0; i < renderer->LayerCount; i++) {
layers[i] = (const XrCompositionLayerBaseHeader*)&renderer->Layers[i];
}
XrFrameEndInfo end_frame_info = {};
end_frame_info.type = XR_TYPE_FRAME_END_INFO;
end_frame_info.displayTime = engine->PredictedDisplayTime;
end_frame_info.environmentBlendMode = XR_ENVIRONMENT_BLEND_MODE_OPAQUE;
end_frame_info.layerCount = renderer->LayerCount;
end_frame_info.layers = layers;
OXR(xrEndFrame(engine->Session, &end_frame_info));
}
void XrRendererBindFramebuffer(struct XrRenderer* renderer) {
if (!renderer->Initialized)
return;
int fbo_index = renderer->ConfigInt[CONFIG_CURRENT_FBO];
XrFramebufferSetCurrent(&renderer->Framebuffer[fbo_index]);
}
void XrRendererRecenter(struct XrEngine* engine, struct XrRenderer* renderer) {
// Calculate recenter reference
XrReferenceSpaceCreateInfo space_info = {};
space_info.type = XR_TYPE_REFERENCE_SPACE_CREATE_INFO;
space_info.poseInReferenceSpace.orientation.w = 1.0f;
if (engine->CurrentSpace != XR_NULL_HANDLE) {
XrSpaceLocation loc = {};
loc.type = XR_TYPE_SPACE_LOCATION;
OXR(xrLocateSpace(engine->HeadSpace, engine->CurrentSpace,
engine->PredictedDisplayTime, &loc));
renderer->HmdOrientation = XrQuaternionfEulerAngles(loc.pose.orientation);
renderer->ConfigFloat[CONFIG_RECENTER_YAW] += renderer->HmdOrientation.y;
float renceter_yaw = ToRadians(renderer->ConfigFloat[CONFIG_RECENTER_YAW]);
space_info.poseInReferenceSpace.orientation.x = 0;
space_info.poseInReferenceSpace.orientation.y = sinf(renceter_yaw / 2);
space_info.poseInReferenceSpace.orientation.z = 0;
space_info.poseInReferenceSpace.orientation.w = cosf(renceter_yaw / 2);
}
// Delete previous space instances
if (engine->StageSpace != XR_NULL_HANDLE) {
OXR(xrDestroySpace(engine->StageSpace));
}
if (engine->FakeSpace != XR_NULL_HANDLE) {
OXR(xrDestroySpace(engine->FakeSpace));
}
// Create a default stage space to use if SPACE_TYPE_STAGE is not
// supported, or calls to xrGetReferenceSpaceBoundsRect fail.
space_info.referenceSpaceType = XR_REFERENCE_SPACE_TYPE_LOCAL;
if (engine->PlatformFlag[PLATFORM_TRACKING_FLOOR]) {
space_info.poseInReferenceSpace.position.y = -1.6750f;
}
OXR(xrCreateReferenceSpace(engine->Session, &space_info, &engine->FakeSpace));
ALOGV("Created fake stage space from local space with offset");
engine->CurrentSpace = engine->FakeSpace;
if (renderer->StageSupported) {
space_info.referenceSpaceType = XR_REFERENCE_SPACE_TYPE_STAGE;
space_info.poseInReferenceSpace.position.y = 0.0;
OXR(xrCreateReferenceSpace(engine->Session, &space_info, &engine->StageSpace));
ALOGV("Created stage space");
if (engine->PlatformFlag[PLATFORM_TRACKING_FLOOR]) {
engine->CurrentSpace = engine->StageSpace;
}
}
// Update menu orientation
renderer->ConfigFloat[CONFIG_MENU_PITCH] = renderer->HmdOrientation.x;
renderer->ConfigFloat[CONFIG_MENU_YAW] = 0.0f;
}
void XrRendererHandleSessionStateChanges(struct XrEngine* engine, struct XrRenderer* renderer, XrSessionState state) {
if (state == XR_SESSION_STATE_READY) {
assert(renderer->SessionActive == false);
XrSessionBeginInfo session_begin_info;
memset(&session_begin_info, 0, sizeof(session_begin_info));
session_begin_info.type = XR_TYPE_SESSION_BEGIN_INFO;
session_begin_info.next = NULL;
session_begin_info.primaryViewConfigurationType = renderer->ViewportConfig.viewConfigurationType;
XrResult result;
OXR(result = xrBeginSession(engine->Session, &session_begin_info));
renderer->SessionActive = (result == XR_SUCCESS);
ALOGV("Session active = %d", renderer->SessionActive);
#ifdef ANDROID
if (renderer->SessionActive && engine->PlatformFlag[PLATFORM_EXTENSION_PERFORMANCE]) {
PFN_xrPerfSettingsSetPerformanceLevelEXT pfnPerfSettingsSetPerformanceLevelEXT = NULL;
OXR(xrGetInstanceProcAddr(engine->Instance, "xrPerfSettingsSetPerformanceLevelEXT",
(PFN_xrVoidFunction*)(&pfnPerfSettingsSetPerformanceLevelEXT)));
OXR(pfnPerfSettingsSetPerformanceLevelEXT(
engine->Session, XR_PERF_SETTINGS_DOMAIN_CPU_EXT, XR_PERF_SETTINGS_LEVEL_BOOST_EXT));
OXR(pfnPerfSettingsSetPerformanceLevelEXT(
engine->Session, XR_PERF_SETTINGS_DOMAIN_GPU_EXT, XR_PERF_SETTINGS_LEVEL_BOOST_EXT));
PFN_xrSetAndroidApplicationThreadKHR pfnSetAndroidApplicationThreadKHR = NULL;
OXR(xrGetInstanceProcAddr(engine->Instance, "xrSetAndroidApplicationThreadKHR",
(PFN_xrVoidFunction*)(&pfnSetAndroidApplicationThreadKHR)));
OXR(pfnSetAndroidApplicationThreadKHR(engine->Session,
XR_ANDROID_THREAD_TYPE_APPLICATION_MAIN_KHR,
engine->MainThreadId));
OXR(pfnSetAndroidApplicationThreadKHR(engine->Session,
XR_ANDROID_THREAD_TYPE_RENDERER_MAIN_KHR,
engine->RenderThreadId));
}
#endif
} else if (state == XR_SESSION_STATE_STOPPING) {
assert(renderer->SessionActive);
OXR(xrEndSession(engine->Session));
renderer->SessionActive = false;
}
}
void XrRendererHandleXrEvents(struct XrEngine* engine, struct XrRenderer* renderer) {
XrEventDataBuffer event_data_bufer = {};
// Poll for events
for (;;) {
XrEventDataBaseHeader* base_event_handler = (XrEventDataBaseHeader*)(&event_data_bufer);
base_event_handler->type = XR_TYPE_EVENT_DATA_BUFFER;
base_event_handler->next = NULL;
XrResult r;
OXR(r = xrPollEvent(engine->Instance, &event_data_bufer));
if (r != XR_SUCCESS) {
break;
}
switch (base_event_handler->type) {
case XR_TYPE_EVENT_DATA_EVENTS_LOST:
ALOGV("xrPollEvent: received XR_TYPE_EVENT_DATA_EVENTS_LOST");
break;
case XR_TYPE_EVENT_DATA_INSTANCE_LOSS_PENDING:
{
const XrEventDataInstanceLossPending* instance_loss_pending_event =
(XrEventDataInstanceLossPending*)(base_event_handler);
ALOGV("xrPollEvent: received XR_TYPE_EVENT_DATA_INSTANCE_LOSS_PENDING: time %lf",
FromXrTime(instance_loss_pending_event->lossTime));
}
break;
case XR_TYPE_EVENT_DATA_INTERACTION_PROFILE_CHANGED:
ALOGV("xrPollEvent: received XR_TYPE_EVENT_DATA_INTERACTION_PROFILE_CHANGED");
break;
case XR_TYPE_EVENT_DATA_PERF_SETTINGS_EXT:
break;
case XR_TYPE_EVENT_DATA_REFERENCE_SPACE_CHANGE_PENDING:
XrRendererRecenter(engine, renderer);
break;
case XR_TYPE_EVENT_DATA_SESSION_STATE_CHANGED:
{
const XrEventDataSessionStateChanged* session_state_changed_event =
(XrEventDataSessionStateChanged*)(base_event_handler);
switch (session_state_changed_event->state) {
case XR_SESSION_STATE_FOCUSED:
renderer->SessionFocused = true;
break;
case XR_SESSION_STATE_VISIBLE:
renderer->SessionFocused = false;
break;
case XR_SESSION_STATE_READY:
case XR_SESSION_STATE_STOPPING:
XrRendererHandleSessionStateChanges(engine, renderer, session_state_changed_event->state);
break;
default:
break;
}
break;
}
default:
ALOGV("xrPollEvent: Unknown event");
break;
}
}
}
void XrRendererUpdateStageBounds(struct XrEngine* engine) {
XrExtent2Df stage_bounds = {};
XrResult result;
OXR(result = xrGetReferenceSpaceBoundsRect(engine->Session, XR_REFERENCE_SPACE_TYPE_STAGE,
&stage_bounds));
if (result != XR_SUCCESS) {
stage_bounds.width = 1.0f;
stage_bounds.height = 1.0f;
engine->CurrentSpace = engine->FakeSpace;
}
}

View File

@@ -0,0 +1,76 @@
#pragma once
#include "engine.h"
#include "framebuffer.h"
enum XrConfigFloat {
// 2D canvas positioning
CONFIG_CANVAS_DISTANCE,
CONFIG_MENU_PITCH,
CONFIG_MENU_YAW,
CONFIG_RECENTER_YAW,
CONFIG_FLOAT_MAX
};
enum XrConfigInt {
// switching between modes
CONFIG_MODE,
CONFIG_PASSTHROUGH,
CONFIG_SBS,
// viewport setup
CONFIG_VIEWPORT_WIDTH,
CONFIG_VIEWPORT_HEIGHT,
// render status
CONFIG_CURRENT_FBO,
// end
CONFIG_INT_MAX
};
enum XrRenderMode {
RENDER_MODE_MONO_SCREEN,
RENDER_MODE_STEREO_SCREEN,
RENDER_MODE_MONO_6DOF,
RENDER_MODE_STEREO_6DOF
};
struct XrRenderer {
bool SessionActive;
bool SessionFocused;
bool Initialized;
bool StageSupported;
float ConfigFloat[CONFIG_FLOAT_MAX];
int ConfigInt[CONFIG_INT_MAX];
struct XrFramebuffer Framebuffer[XrMaxNumEyes];
int LayerCount;
XrCompositorLayer Layers[XrMaxLayerCount];
XrPassthroughFB Passthrough;
XrPassthroughLayerFB PassthroughLayer;
bool PassthroughRunning;
XrViewConfigurationProperties ViewportConfig;
XrViewConfigurationView ViewConfig[XrMaxNumEyes];
XrFovf Fov;
XrView* Projections;
XrPosef InvertedViewPose[2];
XrVector3f HmdOrientation;
};
void XrRendererInit(struct XrEngine* engine, struct XrRenderer* renderer);
void XrRendererDestroy(struct XrEngine* engine, struct XrRenderer* renderer);
void XrRendererGetResolution(struct XrEngine* engine, struct XrRenderer* renderer, int* pWidth, int* pHeight);
bool XrRendererInitFrame(struct XrEngine* engine, struct XrRenderer* renderer);
void XrRendererBeginFrame(struct XrRenderer* renderer, int fbo_index);
void XrRendererEndFrame(struct XrRenderer* renderer);
void XrRendererFinishFrame(struct XrEngine* engine, struct XrRenderer* renderer);
void XrRendererBindFramebuffer(struct XrRenderer* renderer);
void XrRendererRecenter(struct XrEngine* engine, struct XrRenderer* renderer);
void XrRendererHandleSessionStateChanges(struct XrEngine* engine, struct XrRenderer* renderer, XrSessionState state);
void XrRendererHandleXrEvents(struct XrEngine* engine, struct XrRenderer* renderer);
void XrRendererUpdateStageBounds(struct XrEngine* engine);

View File

@@ -0,0 +1,129 @@
package com.termux.shared.termux.extrakeys;
import android.text.TextUtils;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.Arrays;
import java.util.stream.Collectors;
public class ExtraKeyButton {
/** The key name for the name of the extra key if using a dict to define the extra key. {key: name, ...} */
public static final String KEY_KEY_NAME = "key";
/** The key name for the macro value of the extra key if using a dict to define the extra key. {macro: value, ...} */
public static final String KEY_MACRO = "macro";
/** The key name for the alternate display name of the extra key if using a dict to define the extra key. {display: name, ...} */
public static final String KEY_DISPLAY_NAME = "display";
/** The key name for the nested dict to define popup extra key info if using a dict to define the extra key. {popup: {key: name, ...}, ...} */
public static final String KEY_POPUP = "popup";
/**
* The key that will be sent to the terminal, either a control character, like defined in
* {@link ExtraKeysConstants#PRIMARY_KEY_CODES_FOR_STRINGS} (LEFT, RIGHT, PGUP...) or some text.
*/
public final String key;
/**
* If the key is a macro, i.e. a sequence of keys separated by space.
*/
public final boolean macro;
/**
* The text that will be displayed on the button.
*/
public final String display;
/**
* The {@link ExtraKeyButton} containing the information of the popup button (triggered by swipe up).
*/
@Nullable
public final ExtraKeyButton popup;
/**
* Initialize a {@link ExtraKeyButton}.
*
* @param config The {@link JSONObject} containing the info to create the {@link ExtraKeyButton}.
* @param extraKeyDisplayMap The {@link ExtraKeysConstants.ExtraKeyDisplayMap} that defines the
* display text mapping for the keys if a custom value is not defined
* by {@link #KEY_DISPLAY_NAME}.
* @param extraKeyAliasMap The {@link ExtraKeysConstants.ExtraKeyDisplayMap} that defines the
* aliases for the actual key names.
*/
public ExtraKeyButton(@NonNull JSONObject config,
@NonNull ExtraKeysConstants.ExtraKeyDisplayMap extraKeyDisplayMap,
@NonNull ExtraKeysConstants.ExtraKeyDisplayMap extraKeyAliasMap) throws JSONException {
this(config, null, extraKeyDisplayMap, extraKeyAliasMap);
}
/**
* Initialize a {@link ExtraKeyButton}.
*
* @param config The {@link JSONObject} containing the info to create the {@link ExtraKeyButton}.
* @param popup The {@link ExtraKeyButton} optional {@link #popup} button.
* @param extraKeyDisplayMap The {@link ExtraKeysConstants.ExtraKeyDisplayMap} that defines the
* display text mapping for the keys if a custom value is not defined
* by {@link #KEY_DISPLAY_NAME}.
* @param extraKeyAliasMap The {@link ExtraKeysConstants.ExtraKeyDisplayMap} that defines the
* aliases for the actual key names.
*/
public ExtraKeyButton(@NonNull JSONObject config, @Nullable ExtraKeyButton popup,
@NonNull ExtraKeysConstants.ExtraKeyDisplayMap extraKeyDisplayMap,
@NonNull ExtraKeysConstants.ExtraKeyDisplayMap extraKeyAliasMap) throws JSONException {
String keyFromConfig = getStringFromJson(config, KEY_KEY_NAME);
String macroFromConfig = getStringFromJson(config, KEY_MACRO);
String[] keys;
if (keyFromConfig != null && macroFromConfig != null) {
throw new JSONException("Both key and macro can't be set for the same key. key: \"" + keyFromConfig + "\", macro: \"" + macroFromConfig + "\"");
} else if (keyFromConfig != null) {
keys = new String[]{keyFromConfig};
this.macro = false;
} else if (macroFromConfig != null) {
keys = macroFromConfig.split(" ");
this.macro = true;
} else {
throw new JSONException("All keys have to specify either key or macro");
}
for (int i = 0; i < keys.length; i++) {
keys[i] = replaceAlias(extraKeyAliasMap, keys[i]);
}
this.key = TextUtils.join(" ", keys);
String displayFromConfig = getStringFromJson(config, KEY_DISPLAY_NAME);
if (displayFromConfig != null) {
this.display = displayFromConfig;
} else {
this.display = Arrays.stream(keys)
.map(key -> extraKeyDisplayMap.get(key, key))
.collect(Collectors.joining(" "));
}
this.popup = popup;
}
public String getStringFromJson(@NonNull JSONObject config, @NonNull String key) {
try {
return config.getString(key);
} catch (JSONException e) {
return null;
}
}
/**
* Replace the alias with its actual key name if found in extraKeyAliasMap.
*/
public static String replaceAlias(@NonNull ExtraKeysConstants.ExtraKeyDisplayMap extraKeyAliasMap, String key) {
return extraKeyAliasMap.get(key, key);
}
}

View File

@@ -0,0 +1,201 @@
package com.termux.shared.termux.extrakeys;
import android.view.KeyEvent;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class ExtraKeysConstants {
/** Defines the repetitive keys that can be passed to {@link ExtraKeysView#setRepetitiveKeys(List)}. */
public static List<String> PRIMARY_REPETITIVE_KEYS = Arrays.asList(
"UP", "DOWN", "LEFT", "RIGHT",
"BKSP", "DEL",
"PGUP", "PGDN");
/** Defines the {@link KeyEvent} for common keys. */
public static Map<String, Integer> PRIMARY_KEY_CODES_FOR_STRINGS = new HashMap<String, Integer>() {{
put("SPACE", KeyEvent.KEYCODE_SPACE);
put("ESC", KeyEvent.KEYCODE_ESCAPE);
put("TAB", KeyEvent.KEYCODE_TAB);
put("HOME", KeyEvent.KEYCODE_MOVE_HOME);
put("END", KeyEvent.KEYCODE_MOVE_END);
put("PGUP", KeyEvent.KEYCODE_PAGE_UP);
put("PGDN", KeyEvent.KEYCODE_PAGE_DOWN);
put("INS", KeyEvent.KEYCODE_INSERT);
put("DEL", KeyEvent.KEYCODE_FORWARD_DEL);
put("BKSP", KeyEvent.KEYCODE_DEL);
put("UP", KeyEvent.KEYCODE_DPAD_UP);
put("LEFT", KeyEvent.KEYCODE_DPAD_LEFT);
put("RIGHT", KeyEvent.KEYCODE_DPAD_RIGHT);
put("DOWN", KeyEvent.KEYCODE_DPAD_DOWN);
put("ENTER", KeyEvent.KEYCODE_ENTER);
put("F1", KeyEvent.KEYCODE_F1);
put("F2", KeyEvent.KEYCODE_F2);
put("F3", KeyEvent.KEYCODE_F3);
put("F4", KeyEvent.KEYCODE_F4);
put("F5", KeyEvent.KEYCODE_F5);
put("F6", KeyEvent.KEYCODE_F6);
put("F7", KeyEvent.KEYCODE_F7);
put("F8", KeyEvent.KEYCODE_F8);
put("F9", KeyEvent.KEYCODE_F9);
put("F10", KeyEvent.KEYCODE_F10);
put("F11", KeyEvent.KEYCODE_F11);
put("F12", KeyEvent.KEYCODE_F12);
}};
/**
* HashMap that implements Python dict.get(key, default) function.
* Default java.util .get(key) is then the same as .get(key, null);
*/
static class CleverMap<K,V> extends HashMap<K,V> {
V get(K key, V defaultValue) {
if (containsKey(key))
return get(key);
else
return defaultValue;
}
}
public static class ExtraKeyDisplayMap extends CleverMap<String, String> {}
/*
* Multiple maps are available to quickly change
* the style of the keys.
*/
public static class EXTRA_KEY_DISPLAY_MAPS {
/**
* Keys are displayed in a natural looking way, like "→" for "RIGHT"
*/
public static final ExtraKeyDisplayMap CLASSIC_ARROWS_DISPLAY = new ExtraKeyDisplayMap() {{
// classic arrow keys (for ◀ ▶ ▲ ▼ @see arrowVariationDisplay)
put("LEFT", ""); // U+2190 ← LEFTWARDS ARROW
put("RIGHT", ""); // U+2192 → RIGHTWARDS ARROW
put("UP", ""); // U+2191 ↑ UPWARDS ARROW
put("DOWN", ""); // U+2193 ↓ DOWNWARDS ARROW
}};
public static final ExtraKeyDisplayMap WELL_KNOWN_CHARACTERS_DISPLAY = new ExtraKeyDisplayMap() {{
// well known characters // https://en.wikipedia.org/wiki/{Enter_key, Tab_key, Delete_key}
put("ENTER", ""); // U+21B2 ↲ DOWNWARDS ARROW WITH TIP LEFTWARDS
put("TAB", ""); // U+21B9 ↹ LEFTWARDS ARROW TO BAR OVER RIGHTWARDS ARROW TO BAR
put("BKSP", ""); // U+232B ⌫ ERASE TO THE LEFT sometimes seen and easy to understand
put("DEL", ""); // U+2326 ⌦ ERASE TO THE RIGHT not well known but easy to understand
put("DRAWER", ""); // U+2630 ☰ TRIGRAM FOR HEAVEN not well known but easy to understand
put("KEYBOARD", ""); // U+2328 ⌨ KEYBOARD not well known but easy to understand
put("PASTE", ""); // U+2398
put("SCROLL", ""); // U+21F3
put("PREFERENCES", ""); // U+2699 GEAR not well known but easy to understand
put("EXIT", ""); // U+2573 BOX DRAWINGS LIGHT DIAGONAL CROSS not well known but easy to understand
put("MOUSE_HELPER", "\uD83D\uDDB1"); // U+1F5B1 THREE BUTTON MOUSE
put("STYLUS_HELPER", "\uD83D\uDD8C"); // U+1F58C LOWER LEFT PAINTBRUSH
}};
public static final ExtraKeyDisplayMap LESS_KNOWN_CHARACTERS_DISPLAY = new ExtraKeyDisplayMap() {{
// https://en.wikipedia.org/wiki/{Home_key, End_key, Page_Up_and_Page_Down_keys}
// home key can mean "goto the beginning of line" or "goto first page" depending on context, hence the diagonal
put("HOME", ""); // from IEC 9995 // U+21F1 ⇱ NORTH WEST ARROW TO CORNER
put("END", ""); // from IEC 9995 // ⇲ // U+21F2 ⇲ SOUTH EAST ARROW TO CORNER
put("PGUP", ""); // no ISO character exists, U+21D1 ⇑ UPWARDS DOUBLE ARROW will do the trick
put("PGDN", ""); // no ISO character exists, U+21D3 ⇓ DOWNWARDS DOUBLE ARROW will do the trick
}};
public static final ExtraKeyDisplayMap NOT_KNOWN_ISO_CHARACTERS = new ExtraKeyDisplayMap() {{
// Control chars that are more clear as text // https://en.wikipedia.org/wiki/{Function_key, Alt_key, Control_key, Esc_key}
// put("FN", "FN"); // no ISO character exists
put("CTRL", ""); // ISO character "U+2388 ⎈ HELM SYMBOL" is unknown to people and never printed on computers, however "U+25C7 ◇ WHITE DIAMOND" is a nice presentation, and "^" for terminal app and mac is often used
put("ALT", ""); // ISO character "U+2387 ⎇ ALTERNATIVE KEY SYMBOL'" is unknown to people and only printed as the Option key "⌥" on Mac computer
put("ESC", ""); // ISO character "U+238B ⎋ BROKEN CIRCLE WITH NORTHWEST ARROW" is unknown to people and not often printed on computers
}};
public static final ExtraKeyDisplayMap NICER_LOOKING_DISPLAY = new ExtraKeyDisplayMap() {{
// nicer looking for most cases
put("-", ""); // U+2015 ― HORIZONTAL BAR
}};
/**
* Full Iso
*/
public static final ExtraKeyDisplayMap FULL_ISO_CHAR_DISPLAY = new ExtraKeyDisplayMap() {{
putAll(CLASSIC_ARROWS_DISPLAY);
putAll(WELL_KNOWN_CHARACTERS_DISPLAY);
putAll(LESS_KNOWN_CHARACTERS_DISPLAY); // NEW
putAll(NICER_LOOKING_DISPLAY);
putAll(NOT_KNOWN_ISO_CHARACTERS); // NEW
}};
/**
* Only arrows
*/
public static final ExtraKeyDisplayMap ARROWS_ONLY_CHAR_DISPLAY = new ExtraKeyDisplayMap() {{
putAll(CLASSIC_ARROWS_DISPLAY);
/* putAll(wellKnownCharactersDisplay); */ // REMOVED
/* putAll(lessKnownCharactersDisplay); */ // REMOVED
putAll(NICER_LOOKING_DISPLAY);
}};
/**
* Classic symbols and less known symbols
*/
public static final ExtraKeyDisplayMap LOTS_OF_ARROWS_CHAR_DISPLAY = new ExtraKeyDisplayMap() {{
putAll(CLASSIC_ARROWS_DISPLAY);
putAll(WELL_KNOWN_CHARACTERS_DISPLAY);
putAll(LESS_KNOWN_CHARACTERS_DISPLAY); // NEW
putAll(NICER_LOOKING_DISPLAY);
}};
/**
* Some classic symbols everybody knows
*/
public static final ExtraKeyDisplayMap DEFAULT_CHAR_DISPLAY = new ExtraKeyDisplayMap() {{
putAll(CLASSIC_ARROWS_DISPLAY);
putAll(WELL_KNOWN_CHARACTERS_DISPLAY);
putAll(NICER_LOOKING_DISPLAY);
// all other characters are displayed as themselves
}};
}
/**
* Aliases for the keys
*/
public static final ExtraKeyDisplayMap CONTROL_CHARS_ALIASES = new ExtraKeyDisplayMap() {{
put("ESCAPE", "ESC");
put("CONTROL", "CTRL");
put("SHFT", "SHIFT");
put("RETURN", "ENTER"); // Technically different keys, but most applications won't see the difference
put("FUNCTION", "FN");
// no alias for ALT
// Directions are sometimes written as first and last letter for brevety
put("LT", "LEFT");
put("RT", "RIGHT");
put("DN", "DOWN");
// put("UP", "UP"); well, "UP" is already two letters
put("PAGEUP", "PGUP");
put("PAGE_UP", "PGUP");
put("PAGE UP", "PGUP");
put("PAGE-UP", "PGUP");
// no alias for HOME
// no alias for END
put("PAGEDOWN", "PGDN");
put("PAGE_DOWN", "PGDN");
put("PAGE-DOWN", "PGDN");
put("DELETE", "DEL");
put("BACKSPACE", "BKSP");
// easier for writing in termux.properties
put("BACKSLASH", "\\");
put("QUOTE", "\"");
put("APOSTROPHE", "'");
}};
}

View File

@@ -0,0 +1,209 @@
package com.termux.shared.termux.extrakeys;
import android.view.View;
import androidx.annotation.NonNull;
import com.termux.shared.termux.extrakeys.ExtraKeysConstants.EXTRA_KEY_DISPLAY_MAPS;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
/**
* A {@link Class} that defines the info needed by {@link ExtraKeysView} to display the extra key
* views.
*
* The {@code propertiesInfo} passed to the constructors of this class must be json array of arrays.
* Each array element of the json array will be considered a separate row of keys.
* Each key can either be simple string that defines the name of the key or a json dict that defines
* advance info for the key. The syntax can be `'KEY'` or `{key: 'KEY'}`.
* For example `HOME` or `{key: 'HOME', ...}.
*
* In advance json dict mode, the key can also be a sequence of space separated keys instead of one
* key. This can be done by replacing `key` key/value pair of the dict with a `macro` key/value pair.
* The syntax is `{macro: 'KEY COMBINATION'}`. For example {macro: 'HOME RIGHT', ...}.
*
* In advance json dict mode, you can define a nested json dict with the `popup` key which will be
* used as the popup key and will be triggered on swipe up. The syntax can be
* `{key: 'KEY', popup: 'POPUP_KEY'}` or `{key: 'KEY', popup: {macro: 'KEY COMBINATION', display: 'Key combo'}}`.
* For example `{key: 'HOME', popup: {KEY: 'END', ...}, ...}`.
*
* In advance json dict mode, the key can also have a custom display name that can be used as the
* text to display on the button by defining the `display` key. The syntax is `{display: 'DISPLAY'}`.
* For example {display: 'Custom name', ...}.
*
* Examples:
* {@code
* # Empty:
* []
*
* # Single row:
* [[ESC, TAB, CTRL, ALT, {key: '-', popup: '|'}, DOWN, UP]]
*
* # 2 row:
* [['ESC','/',{key: '-', popup: '|'},'HOME','UP','END','PGUP'],
* ['TAB','CTRL','ALT','LEFT','DOWN','RIGHT','PGDN']]
*
* # Advance:
* [[
* {key: ESC, popup: {macro: "CTRL f d", display: "tmux exit"}},
* {key: CTRL, popup: {macro: "CTRL f BKSP", display: "tmux ←"}},
* {key: ALT, popup: {macro: "CTRL f TAB", display: "tmux →"}},
* {key: TAB, popup: {macro: "ALT a", display: A-a}},
* {key: LEFT, popup: HOME},
* {key: DOWN, popup: PGDN},
* {key: UP, popup: PGUP},
* {key: RIGHT, popup: END},
* {macro: "ALT j", display: A-j, popup: {macro: "ALT g", display: A-g}},
* {key: KEYBOARD, popup: {macro: "CTRL d", display: exit}}
* ]]
* <p>
* }
*
* Aliases are also allowed for the keys that you can pass as {@code extraKeyAliasMap}. Check
* {@link ExtraKeysConstants#CONTROL_CHARS_ALIASES}.
* <p>
* Its up to the {@link ExtraKeysView.IExtraKeysView} client on how to handle individual key values
* of an {@link ExtraKeyButton}. They are sent as is via
* {@link ExtraKeysView.IExtraKeysView#onExtraKeyButtonClick(View, ExtraKeyButton, Button)}. The
* {@link com.termux.x11.utils.TermuxX11ExtraKeys} which is an implementation of the interface,
* checks if the key is one of {@link ExtraKeysConstants#PRIMARY_KEY_CODES_FOR_STRINGS} and generates
* a {@link android.view.KeyEvent} for it, and if its not, then converts the key to code points by
* calling {@link CharSequence#codePoints()} and passes them to the terminal as literal strings.
* <p>
* Examples:
* {@code
* "ENTER" will trigger the ENTER keycode
* "LEFT" will trigger the LEFT keycode and be displayed as "←"
* "→" will input a "→" character
* "" will input a "" character
* "-_-" will input the string "-_-"
* }
*
* For more info, check https://wiki.termux.com/wiki/Touch_Keyboard.
*/
public class ExtraKeysInfo {
/**
* Matrix of buttons to be displayed in {@link ExtraKeysView}.
*/
private final ExtraKeyButton[][] mButtons;
/**
* Initialize {@link ExtraKeysInfo}.
*
* @param propertiesInfo The {@link String} containing the info to create the {@link ExtraKeysInfo}.
* Check the class javadoc for details.
* @param style The style to pass to {@link #getCharDisplayMapForStyle(String)} to get the
* {@link ExtraKeysConstants.ExtraKeyDisplayMap} that defines the display text
* mapping for the keys if a custom value is not defined by
* {@link ExtraKeyButton#KEY_DISPLAY_NAME} for a key.
* @param extraKeyAliasMap The {@link ExtraKeysConstants.ExtraKeyDisplayMap} that defines the
* aliases for the actual key names. You can create your own or
* optionally pass {@link ExtraKeysConstants#CONTROL_CHARS_ALIASES}.
*/
public ExtraKeysInfo(@NonNull String propertiesInfo, String style,
@NonNull ExtraKeysConstants.ExtraKeyDisplayMap extraKeyAliasMap) throws JSONException {
mButtons = initExtraKeysInfo(propertiesInfo, getCharDisplayMapForStyle(style), extraKeyAliasMap);
}
/**
* Initialize {@link ExtraKeysInfo}.
*
* @param propertiesInfo The {@link String} containing the info to create the {@link ExtraKeysInfo}.
* Check the class javadoc for details.
* @param extraKeyDisplayMap The {@link ExtraKeysConstants.ExtraKeyDisplayMap} that defines the
* display text mapping for the keys if a custom value is not defined
* by {@link ExtraKeyButton#KEY_DISPLAY_NAME} for a key. You can create
* your own or optionally pass one of the values defined in
* {@link #getCharDisplayMapForStyle(String)}.
* @param extraKeyAliasMap The {@link ExtraKeysConstants.ExtraKeyDisplayMap} that defines the
* aliases for the actual key names. You can create your own or
* optionally pass {@link ExtraKeysConstants#CONTROL_CHARS_ALIASES}.
*/
public ExtraKeysInfo(@NonNull String propertiesInfo,
@NonNull ExtraKeysConstants.ExtraKeyDisplayMap extraKeyDisplayMap,
@NonNull ExtraKeysConstants.ExtraKeyDisplayMap extraKeyAliasMap) throws JSONException {
mButtons = initExtraKeysInfo(propertiesInfo, extraKeyDisplayMap, extraKeyAliasMap);
}
private ExtraKeyButton[][] initExtraKeysInfo(@NonNull String propertiesInfo,
@NonNull ExtraKeysConstants.ExtraKeyDisplayMap extraKeyDisplayMap,
@NonNull ExtraKeysConstants.ExtraKeyDisplayMap extraKeyAliasMap) throws JSONException {
// Convert String propertiesInfo to Array of Arrays
JSONArray arr = new JSONArray(propertiesInfo);
Object[][] matrix = new Object[arr.length()][];
for (int i = 0; i < arr.length(); i++) {
JSONArray line = arr.getJSONArray(i);
matrix[i] = new Object[line.length()];
for (int j = 0; j < line.length(); j++) {
matrix[i][j] = line.get(j);
}
}
// convert matrix to buttons
ExtraKeyButton[][] buttons = new ExtraKeyButton[matrix.length][];
for (int i = 0; i < matrix.length; i++) {
buttons[i] = new ExtraKeyButton[matrix[i].length];
for (int j = 0; j < matrix[i].length; j++) {
Object key = matrix[i][j];
JSONObject jobject = normalizeKeyConfig(key);
ExtraKeyButton button;
if (!jobject.has(ExtraKeyButton.KEY_POPUP)) {
// no popup
button = new ExtraKeyButton(jobject, extraKeyDisplayMap, extraKeyAliasMap);
} else {
// a popup
JSONObject popupJobject = normalizeKeyConfig(jobject.get(ExtraKeyButton.KEY_POPUP));
ExtraKeyButton popup = new ExtraKeyButton(popupJobject, extraKeyDisplayMap, extraKeyAliasMap);
button = new ExtraKeyButton(jobject, popup, extraKeyDisplayMap, extraKeyAliasMap);
}
buttons[i][j] = button;
}
}
return buttons;
}
/**
* Convert "value" -> {"key": "value"}. Required by
* {@link ExtraKeyButton#ExtraKeyButton(JSONObject, ExtraKeyButton, ExtraKeysConstants.ExtraKeyDisplayMap, ExtraKeysConstants.ExtraKeyDisplayMap)}.
*/
private static JSONObject normalizeKeyConfig(Object key) throws JSONException {
JSONObject jobject;
if (key instanceof String) {
jobject = new JSONObject();
jobject.put(ExtraKeyButton.KEY_KEY_NAME, key);
} else if (key instanceof JSONObject) {
jobject = (JSONObject) key;
} else {
throw new JSONException("An key in the extra-key matrix must be a string or an object");
}
return jobject;
}
public ExtraKeyButton[][] getMatrix() {
return mButtons;
}
@NonNull
public static ExtraKeysConstants.ExtraKeyDisplayMap getCharDisplayMapForStyle(String style) {
switch (style) {
case "arrows-only":
return EXTRA_KEY_DISPLAY_MAPS.ARROWS_ONLY_CHAR_DISPLAY;
case "arrows-all":
return EXTRA_KEY_DISPLAY_MAPS.LOTS_OF_ARROWS_CHAR_DISPLAY;
case "all":
return EXTRA_KEY_DISPLAY_MAPS.FULL_ISO_CHAR_DISPLAY;
case "none":
return new ExtraKeysConstants.ExtraKeyDisplayMap();
default:
return EXTRA_KEY_DISPLAY_MAPS.DEFAULT_CHAR_DISPLAY;
}
}
}

View File

@@ -0,0 +1,573 @@
package com.termux.shared.termux.extrakeys;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.provider.Settings;
import android.util.AttributeSet;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.ScheduledExecutorService;
import java.util.Map;
import java.util.stream.Collectors;
import android.view.HapticFeedbackConstants;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.GridLayout;
import android.widget.PopupWindow;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.termux.x11.utils.TermuxX11ExtraKeys;
/**
* A {@link View} showing extra keys (such as Escape, Ctrl, Alt) not normally available on an Android soft
* keyboards.
* <p>
* To use it, add following to a layout file and import it in your activity layout file or inflate
* it with a {@link androidx.viewpager.widget.ViewPager}.:
* {@code
* <?xml version="1.0" encoding="utf-8"?>
* <com.termux.shared.termux.extrakeys.ExtraKeysView xmlns:android="http://schemas.android.com/apk/res/android"
* android:id="@+id/extra_keys"
* style="?android:attr/buttonBarStyle"
* android:layout_width="match_parent"
* android:layout_height="match_parent"
* android:layout_alignParentBottom="true"
* android:orientation="horizontal" />
* }
*
* Then in your activity, get its reference by a call to {@link android.app.Activity#findViewById(int)}
* or {@link LayoutInflater#inflate(int, ViewGroup)} if using {@link androidx.viewpager.widget.ViewPager}.
* Then call {@link #setExtraKeysViewClient(IExtraKeysView)} and pass it the implementation of
* {@link IExtraKeysView} so that you can receive callbacks. You can also override other values set
* in {@link ExtraKeysView#ExtraKeysView(Context, AttributeSet)} by calling the respective functions.
* If you extend {@link ExtraKeysView}, you can also set them in the constructor, but do call super().
* <p>
* After this you will have to make a call to {@link ExtraKeysView#reload() and pass
* it the {@link ExtraKeysInfo} to load and display the extra keys. Read its class javadocs for more
* info on how to create it.
* <p>
* Termux app defines the view in res/layout/view_terminal_toolbar_extra_keys and
* inflates it in TerminalToolbarViewPager.instantiateItem() and sets the {@link ExtraKeysView} client
* and calls {@link ExtraKeysView#reload(ExtraKeysInfo).
* The {@link ExtraKeysInfo} is created by TermuxAppSharedProperties.setExtraKeys().
* Then its got and the view height is adjusted in TermuxActivity.setTerminalToolbarHeight().
* The client used is TermuxTerminalExtraKeys, which extends
* {@link com.termux.x11.utils.TermuxX11ExtraKeys } to handle Termux app specific logic and
* leave the rest to the super class.
*/
public final class ExtraKeysView extends GridLayout {
/** The client for the {@link ExtraKeysView}. */
public interface IExtraKeysView {
/**
* This is called by {@link ExtraKeysView} when a button is clicked. This is also called
* for {@link #mRepetitiveKeys} and {@link ExtraKeyButton} that have a popup set.
* However, this is not called for {@link #mSpecialButtons}, whose state can instead be read
* via a call to {@link #readSpecialButton(SpecialButton, boolean)}.
*
* @param view The view that was clicked.
* @param buttonInfo The {@link ExtraKeyButton} for the button that was clicked.
* The button may be a {@link ExtraKeyButton#KEY_MACRO} set which can be
* checked with a call to {@link ExtraKeyButton#macro}.
* @param button The {@link Button} that was clicked.
*/
void onExtraKeyButtonClick(View view, ExtraKeyButton buttonInfo, Button button);
/**
* This is called by {@link ExtraKeysView} when a button is clicked so that the client
* can perform any hepatic feedback. This is only called in the {@link Button.OnClickListener}
* and not for every repeat. Its also called for {@link #mSpecialButtons}.
*
* @param view The view that was clicked.
* @param buttonInfo The {@link ExtraKeyButton} for the button that was clicked.
* @param button The {@link Button} that was clicked.
* @return Return {@code true} if the client handled the feedback, otherwise {@code false}
* so that {@link ExtraKeysView#performExtraKeyButtonHapticFeedback(View, ExtraKeyButton, Button)}
* can handle it depending on system settings.
*/
boolean performExtraKeyButtonHapticFeedback(View view, ExtraKeyButton buttonInfo, Button button);
}
/** Defines the default value for {@link #mButtonTextColor} */
public static final int DEFAULT_BUTTON_TEXT_COLOR = 0xFFFFFFFF;
/** Defines the default value for {@link #mButtonActiveTextColor} */
public static final int DEFAULT_BUTTON_ACTIVE_TEXT_COLOR = 0xFF80DEEA;
/** Defines the default value for {@link #mButtonBackgroundColor} */
public static final int DEFAULT_BUTTON_BACKGROUND_COLOR = 0x00000000;
/** Defines the default value for {@link #mButtonActiveBackgroundColor} */
public static final int DEFAULT_BUTTON_ACTIVE_BACKGROUND_COLOR = 0xFF7F7F7F;
/** Defines the minimum allowed duration in milliseconds for {@link #mLongPressTimeout}. */
public static final int MIN_LONG_PRESS_DURATION = 200;
/** Defines the maximum allowed duration in milliseconds for {@link #mLongPressTimeout}. */
public static final int MAX_LONG_PRESS_DURATION = 3000;
/** Defines the fallback duration in milliseconds for {@link #mLongPressTimeout}. */
public static final int FALLBACK_LONG_PRESS_DURATION = 400;
/** Defines the minimum allowed duration in milliseconds for {@link #mLongPressRepeatDelay}. */
public static final int MIN_LONG_PRESS__REPEAT_DELAY = 5;
/** Defines the maximum allowed duration in milliseconds for {@link #mLongPressRepeatDelay}. */
public static final int MAX_LONG_PRESS__REPEAT_DELAY = 2000;
/** Defines the default duration in milliseconds for {@link #mLongPressRepeatDelay}. */
public static final int DEFAULT_LONG_PRESS_REPEAT_DELAY = 80;
/** The implementation of the {@link IExtraKeysView} that acts as a client for the {@link ExtraKeysView}. */
private IExtraKeysView mExtraKeysViewClient;
/** The map for the {@link SpecialButton} and their {@link SpecialButtonState}. Defaults to
* the one returned by {@link #getDefaultSpecialButtons(ExtraKeysView)}. */
private Map<SpecialButton, SpecialButtonState> mSpecialButtons;
/** The keys for the {@link SpecialButton} added to {@link #mSpecialButtons}. This is automatically
* set when the call to {@link #setSpecialButtons(Map)} is made. */
private Set<String> mSpecialButtonsKeys;
/**
* The list of keys for which auto repeat of key should be triggered if its extra keys button
* is long pressed. This is done by calling {@link IExtraKeysView#onExtraKeyButtonClick(View, ExtraKeyButton, Button)}
* every {@link #mLongPressRepeatDelay} seconds after {@link #mLongPressTimeout} has passed.
* The default keys are defined by {@link ExtraKeysConstants#PRIMARY_REPETITIVE_KEYS}.
*/
private List<String> mRepetitiveKeys;
/** The text color for the extra keys button. Defaults to {@link #DEFAULT_BUTTON_TEXT_COLOR}. */
private int mButtonTextColor;
/** The text color for the extra keys button when its active.
* Defaults to {@link #DEFAULT_BUTTON_ACTIVE_TEXT_COLOR}. */
private int mButtonActiveTextColor;
/** The background color for the extra keys button. Defaults to {@link #DEFAULT_BUTTON_BACKGROUND_COLOR}. */
private int mButtonBackgroundColor;
/** The background color for the extra keys button when its active. Defaults to
* {@link #DEFAULT_BUTTON_ACTIVE_BACKGROUND_COLOR}. */
private int mButtonActiveBackgroundColor;
/**
* Defines the duration in milliseconds before a press turns into a long press. The default
* duration used is the one returned by a call to {@link ViewConfiguration#getLongPressTimeout()}
* which will return the system defined duration which can be changed in accessibility settings.
* The duration must be in between {@link #MIN_LONG_PRESS_DURATION} and {@link #MAX_LONG_PRESS_DURATION},
* otherwise {@link #FALLBACK_LONG_PRESS_DURATION} is used.
*/
private int mLongPressTimeout;
/**
* Defines the duration in milliseconds for the delay between trigger of each repeat of
* {@link #mRepetitiveKeys}. The default value is defined by {@link #DEFAULT_LONG_PRESS_REPEAT_DELAY}.
* The duration must be in between {@link #MIN_LONG_PRESS__REPEAT_DELAY} and
* {@link #MAX_LONG_PRESS__REPEAT_DELAY}, otherwise {@link #DEFAULT_LONG_PRESS_REPEAT_DELAY} is used.
*/
private int mLongPressRepeatDelay;
/** The popup window shown if {@link ExtraKeyButton#popup} returns a {@code non-null} value
* and a swipe up action is done on an extra key. */
private PopupWindow mPopupWindow;
private ScheduledExecutorService mScheduledExecutor;
private Handler mHandler;
private SpecialButtonsLongHoldRunnable mSpecialButtonsLongHoldRunnable;
private int mLongPressCount;
public ExtraKeysView(Context context, AttributeSet attrs) {
super(context, attrs);
setRepetitiveKeys(ExtraKeysConstants.PRIMARY_REPETITIVE_KEYS);
setSpecialButtons(getDefaultSpecialButtons(this));
setButtonColors(DEFAULT_BUTTON_TEXT_COLOR, DEFAULT_BUTTON_ACTIVE_TEXT_COLOR, DEFAULT_BUTTON_BACKGROUND_COLOR, DEFAULT_BUTTON_ACTIVE_BACKGROUND_COLOR);
setLongPressTimeout(ViewConfiguration.getLongPressTimeout());
setLongPressRepeatDelay(DEFAULT_LONG_PRESS_REPEAT_DELAY);
}
/** Set {@link #mExtraKeysViewClient}. */
public void setExtraKeysViewClient(IExtraKeysView extraKeysViewClient) {
mExtraKeysViewClient = extraKeysViewClient;
}
/** Set {@link #mRepetitiveKeys}. Must not be {@code null}. */
public void setRepetitiveKeys(@NonNull List<String> repetitiveKeys) {
mRepetitiveKeys = repetitiveKeys;
}
/** Set {@link #mSpecialButtonsKeys}. Must not be {@code null}. */
public void setSpecialButtons(@NonNull Map<SpecialButton, SpecialButtonState> specialButtons) {
mSpecialButtons = specialButtons;
mSpecialButtonsKeys = this.mSpecialButtons.keySet().stream().map(SpecialButton::getKey).collect(Collectors.toSet());
}
/**
* Set the {@link ExtraKeysView} button colors.
*
* @param buttonTextColor The value for {@link #mButtonTextColor}.
* @param buttonActiveTextColor The value for {@link #mButtonActiveTextColor}.
* @param buttonBackgroundColor The value for {@link #mButtonBackgroundColor}.
* @param buttonActiveBackgroundColor The value for {@link #mButtonActiveBackgroundColor}.
*/
public void setButtonColors(int buttonTextColor, int buttonActiveTextColor, int buttonBackgroundColor, int buttonActiveBackgroundColor) {
mButtonTextColor = buttonTextColor;
mButtonActiveTextColor = buttonActiveTextColor;
mButtonBackgroundColor = buttonBackgroundColor;
mButtonActiveBackgroundColor = buttonActiveBackgroundColor;
}
/** Get {@link #mButtonTextColor}. */
public int getButtonTextColor() {
return mButtonTextColor;
}
/** Get {@link #mButtonActiveTextColor}. */
public int getButtonActiveTextColor() {
return mButtonActiveTextColor;
}
/** Set {@link #mLongPressTimeout}. */
public void setLongPressTimeout(int longPressDuration) {
if (longPressDuration >= MIN_LONG_PRESS_DURATION && longPressDuration <= MAX_LONG_PRESS_DURATION) {
mLongPressTimeout = longPressDuration;
} else {
mLongPressTimeout = FALLBACK_LONG_PRESS_DURATION;
}
}
/** Set {@link #mLongPressRepeatDelay}. */
public void setLongPressRepeatDelay(int longPressRepeatDelay) {
if (mLongPressRepeatDelay >= MIN_LONG_PRESS__REPEAT_DELAY && mLongPressRepeatDelay <= MAX_LONG_PRESS__REPEAT_DELAY) {
mLongPressRepeatDelay = longPressRepeatDelay;
} else {
mLongPressRepeatDelay = DEFAULT_LONG_PRESS_REPEAT_DELAY;
}
}
/** Get the default map that can be used for {@link #mSpecialButtons}. */
@NonNull
public Map<SpecialButton, SpecialButtonState> getDefaultSpecialButtons(ExtraKeysView extraKeysView) {
return new HashMap<SpecialButton, SpecialButtonState>() {{
put(SpecialButton.CTRL, new SpecialButtonState(extraKeysView));
put(SpecialButton.ALT, new SpecialButtonState(extraKeysView));
put(SpecialButton.SHIFT, new SpecialButtonState(extraKeysView));
put(SpecialButton.META, new SpecialButtonState(extraKeysView));
put(SpecialButton.FN, new SpecialButtonState(extraKeysView));
}};
}
/**
* Reload this instance of {@link ExtraKeysView} with the info passed in {@code extraKeysInfo}.
*/
@SuppressLint("ClickableViewAccessibility")
public void reload() {
TermuxX11ExtraKeys.setExtraKeys();
ExtraKeysInfo extraKeysInfo = TermuxX11ExtraKeys.getExtraKeysInfo();
if (extraKeysInfo == null)
return;
for(SpecialButtonState state : mSpecialButtons.values())
state.buttons = new ArrayList<>();
removeAllViews();
ExtraKeyButton[][] buttons = extraKeysInfo.getMatrix();
setRowCount(buttons.length);
setColumnCount(maximumLength(buttons));
for (int row = 0; row < buttons.length; row++) {
for (int col = 0; col < buttons[row].length; col++) {
final ExtraKeyButton buttonInfo = buttons[row][col];
Button button;
if (isSpecialButton(buttonInfo)) {
button = createSpecialButton(buttonInfo.key, true);
if (button == null) return;
} else {
button = new Button(getContext(), null, android.R.attr.buttonBarButtonStyle);
}
button.setBackground(new ColorDrawable(Color.BLACK) {
public boolean isStateful() {
return true;
}
public boolean hasFocusStateSpecified() {
return true;
}
});
button.setText(buttonInfo.display);
button.setTextColor(mButtonTextColor);
button.setAllCaps(true);
button.setPadding(0, 0, 0, 0);
button.setOnClickListener(view -> {
performExtraKeyButtonHapticFeedback(view, buttonInfo, button);
onAnyExtraKeyButtonClick(view, buttonInfo, button);
});
button.setOnTouchListener((view, event) -> {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
view.setBackgroundColor(mButtonActiveBackgroundColor);
// Start long press scheduled executors which will be stopped in next MotionEvent
startScheduledExecutors(view, buttonInfo, button);
return true;
case MotionEvent.ACTION_MOVE:
if (buttonInfo.popup != null) {
// Show popup on swipe up
if (mPopupWindow == null && event.getY() < 0) {
stopScheduledExecutors();
view.setBackgroundColor(mButtonBackgroundColor);
showPopup(view, buttonInfo.popup);
}
if (mPopupWindow != null && event.getY() > 0) {
view.setBackgroundColor(mButtonActiveBackgroundColor);
dismissPopup();
}
}
return true;
case MotionEvent.ACTION_CANCEL:
view.setBackgroundColor(mButtonBackgroundColor);
stopScheduledExecutors();
return true;
case MotionEvent.ACTION_UP:
view.setBackgroundColor(mButtonBackgroundColor);
stopScheduledExecutors();
// If ACTION_UP up was not from a repetitive key or was with a key with a popup button
if (mLongPressCount == 0 || mPopupWindow != null) {
// Trigger popup button click if swipe up complete
if (mPopupWindow != null) {
dismissPopup();
if (buttonInfo.popup != null) {
onAnyExtraKeyButtonClick(view, buttonInfo.popup, button);
}
} else {
view.performClick();
}
}
return true;
default:
return true;
}
});
LayoutParams param = new GridLayout.LayoutParams();
param.width = 0;
param.height = 0;
param.setMargins(0, 0, 0, 0);
param.columnSpec = GridLayout.spec(col, GridLayout.FILL, 1.f);
param.rowSpec = GridLayout.spec(row, GridLayout.FILL, 1.f);
button.setLayoutParams(param);
addView(button);
}
}
}
public void onExtraKeyButtonClick(View view, ExtraKeyButton buttonInfo, Button button) {
if (mExtraKeysViewClient != null)
mExtraKeysViewClient.onExtraKeyButtonClick(view, buttonInfo, button);
}
public void performExtraKeyButtonHapticFeedback(View view, ExtraKeyButton buttonInfo, Button button) {
if (mExtraKeysViewClient != null) {
// If client handled the feedback, then just return
if (mExtraKeysViewClient.performExtraKeyButtonHapticFeedback(view, buttonInfo, button))
return;
}
if (Settings.System.getInt(getContext().getContentResolver(),
Settings.System.HAPTIC_FEEDBACK_ENABLED, 0) != 0) {
if (Build.VERSION.SDK_INT >= 28) {
button.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP);
} else {
// Perform haptic feedback only if no total silence mode enabled.
if (Settings.Global.getInt(getContext().getContentResolver(), "zen_mode", 0) != 2) {
button.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP);
}
}
}
}
public void onAnyExtraKeyButtonClick(View view, @NonNull ExtraKeyButton buttonInfo, Button button) {
if (isSpecialButton(buttonInfo)) {
if (mLongPressCount > 0) return;
SpecialButtonState state = mSpecialButtons.get(SpecialButton.valueOf(buttonInfo.key));
if (state == null) return;
// Toggle active state and disable lock state if new state is not active
state.setIsActive(!state.isActive);
if (!state.isActive)
state.setIsLocked(false);
} else {
onExtraKeyButtonClick(view, buttonInfo, button);
}
}
public void startScheduledExecutors(View view, ExtraKeyButton buttonInfo, Button button) {
stopScheduledExecutors();
mLongPressCount = 0;
if (mRepetitiveKeys.contains(buttonInfo.key)) {
// Auto repeat key if long pressed until ACTION_UP stops it by calling stopScheduledExecutors.
// Currently, only one (last) repeat key can run at a time. Old ones are stopped.
mScheduledExecutor = Executors.newSingleThreadScheduledExecutor();
mScheduledExecutor.scheduleWithFixedDelay(() -> {
mLongPressCount++;
onExtraKeyButtonClick(view, buttonInfo, button);
}, mLongPressTimeout, mLongPressRepeatDelay, TimeUnit.MILLISECONDS);
} else if (isSpecialButton(buttonInfo)) {
// Lock the key if long pressed by running mSpecialButtonsLongHoldRunnable after
// waiting for mLongPressTimeout milliseconds. If user does not long press, then the
// ACTION_UP triggered will cancel the runnable by calling stopScheduledExecutors before
// it has a chance to run.
SpecialButtonState state = mSpecialButtons.get(SpecialButton.valueOf(buttonInfo.key));
if (state == null) return;
if (mHandler == null)
mHandler = new Handler(Looper.getMainLooper());
mSpecialButtonsLongHoldRunnable = new SpecialButtonsLongHoldRunnable(state);
mHandler.postDelayed(mSpecialButtonsLongHoldRunnable, mLongPressTimeout);
}
}
public void stopScheduledExecutors() {
if (mScheduledExecutor != null) {
mScheduledExecutor.shutdownNow();
mScheduledExecutor = null;
}
if (mSpecialButtonsLongHoldRunnable != null && mHandler != null) {
mHandler.removeCallbacks(mSpecialButtonsLongHoldRunnable);
mSpecialButtonsLongHoldRunnable = null;
}
}
public class SpecialButtonsLongHoldRunnable implements Runnable {
public final SpecialButtonState mState;
public SpecialButtonsLongHoldRunnable(SpecialButtonState state) {
mState = state;
}
public void run() {
// Toggle active and lock state
mState.setIsLocked(!mState.isActive);
mState.setIsActive(!mState.isActive);
mLongPressCount++;
}
}
void showPopup(View view, ExtraKeyButton extraButton) {
int width = view.getMeasuredWidth();
int height = view.getMeasuredHeight();
Button button;
if (isSpecialButton(extraButton)) {
button = createSpecialButton(extraButton.key, false);
if (button == null) return;
} else {
button = new Button(getContext(), null, android.R.attr.buttonBarButtonStyle);
button.setTextColor(mButtonTextColor);
}
button.setText(extraButton.display);
button.setAllCaps(true);
button.setPadding(0, 0, 0, 0);
button.setMinHeight(0);
button.setMinWidth(0);
button.setMinimumWidth(0);
button.setMinimumHeight(0);
button.setWidth(width);
button.setHeight(height);
button.setBackgroundColor(mButtonActiveBackgroundColor);
mPopupWindow = new PopupWindow(this);
mPopupWindow.setWidth(LayoutParams.WRAP_CONTENT);
mPopupWindow.setHeight(LayoutParams.WRAP_CONTENT);
mPopupWindow.setContentView(button);
mPopupWindow.setOutsideTouchable(true);
mPopupWindow.setFocusable(false);
mPopupWindow.showAsDropDown(view, 0, -2 * height);
}
public void dismissPopup() {
mPopupWindow.setContentView(null);
mPopupWindow.dismiss();
mPopupWindow = null;
}
/** Check whether a {@link ExtraKeyButton} is a {@link SpecialButton}. */
public boolean isSpecialButton(ExtraKeyButton button) {
return mSpecialButtonsKeys.contains(button.key);
}
/**
* Read whether {@link SpecialButton} registered in {@link #mSpecialButtons} is active or not.
*
* @param specialButton The {@link SpecialButton} to read.
* @param autoSetInActive Set to {@code true} if {@link SpecialButtonState#isActive} should be
* set {@code false} if button is not locked.
* @return Returns {@code null} if button does not exist in {@link #mSpecialButtons}. If button
* exists, then returns {@code true} if the button is created in {@link ExtraKeysView}
* and is active, otherwise {@code false}.
*/
@Nullable
public Boolean readSpecialButton(SpecialButton specialButton, boolean autoSetInActive) {
SpecialButtonState state = mSpecialButtons.get(specialButton);
if (state == null) return null;
if (!state.isCreated || !state.isActive)
return false;
// Disable active state only if not locked
if (autoSetInActive && !state.isLocked)
state.setIsActive(false);
return true;
}
public Button createSpecialButton(String buttonKey, boolean needUpdate) {
SpecialButtonState state = mSpecialButtons.get(SpecialButton.valueOf(buttonKey));
if (state == null) return null;
state.setIsCreated(true);
Button button = new Button(getContext(), null, android.R.attr.buttonBarButtonStyle);
button.setTextColor(state.isActive ? mButtonActiveTextColor : mButtonTextColor);
if (needUpdate) {
state.buttons.add(button);
}
return button;
}
/**
* General util function to compute the longest column length in a matrix.
*/
public static int maximumLength(Object[][] matrix) {
int m = 0;
for (Object[] row : matrix)
m = Math.max(m, row.length);
return m;
}
}

View File

@@ -0,0 +1,53 @@
package com.termux.shared.termux.extrakeys;
import androidx.annotation.NonNull;
import java.util.HashMap;
/** The {@link Class} that implements special buttons for {@link ExtraKeysView}. */
public class SpecialButton {
private static final HashMap<String, SpecialButton> map = new HashMap<>();
public static final SpecialButton CTRL = new SpecialButton("CTRL");
public static final SpecialButton ALT = new SpecialButton("ALT");
public static final SpecialButton SHIFT = new SpecialButton("SHIFT");
public static final SpecialButton META = new SpecialButton("META");
public static final SpecialButton FN = new SpecialButton("FN");
/** The special button key. */
private final String key;
/**
* Initialize a {@link SpecialButton}.
*
* @param key The unique key name for the special button. The key is registered in {@link #map}
* with which the {@link SpecialButton} can be retrieved via a call to
* {@link #valueOf(String)}.
*/
public SpecialButton(@NonNull final String key) {
this.key = key;
map.put(key, this);
}
/** Get {@link #key} for this {@link SpecialButton}. */
public String getKey() {
return key;
}
/**
* Get the {@link SpecialButton} for {@code key}.
*
* @param key The unique key name for the special button.
*/
public static SpecialButton valueOf(String key) {
return map.get(key);
}
@NonNull
@Override
public String toString() {
return key;
}
}

View File

@@ -0,0 +1,50 @@
package com.termux.shared.termux.extrakeys;
import android.widget.Button;
import java.util.ArrayList;
import java.util.List;
/** The {@link Class} that maintains a state of a {@link SpecialButton} */
public class SpecialButtonState {
/** If special button has been created for the {@link ExtraKeysView}. */
boolean isCreated = false;
/** If special button is active. */
boolean isActive = false;
/** If special button is locked due to long hold on it and should not be deactivated if its
* state is read. */
boolean isLocked = false;
List<Button> buttons = new ArrayList<>();
ExtraKeysView mExtraKeysView;
/**
* Initialize a {@link SpecialButtonState} to maintain state of a {@link SpecialButton}.
*
* @param extraKeysView The {@link ExtraKeysView} instance in which the {@link SpecialButton}
* is to be registered.
*/
public SpecialButtonState(ExtraKeysView extraKeysView) {
mExtraKeysView = extraKeysView;
}
/** Set {@link #isCreated}. */
public void setIsCreated(boolean value) {
isCreated = value;
}
/** Set {@link #isActive}. */
public void setIsActive(boolean value) {
isActive = value;
for (Button button : buttons) {
button.setTextColor(value ? mExtraKeysView.getButtonActiveTextColor() : mExtraKeysView.getButtonTextColor());
}
}
/** Set {@link #isLocked}. */
public void setIsLocked(boolean value) {
isLocked = value;
}
}

View File

@@ -0,0 +1,251 @@
package com.termux.x11;
import static android.system.Os.getuid;
import static android.system.Os.getenv;
import android.annotation.SuppressLint;
import android.app.IActivityManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.IIntentReceiver;
import android.content.IIntentSender;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.util.Log;
import android.view.Surface;
import androidx.annotation.Keep;
import java.io.DataInputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.ConnectException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.URL;
import java.util.Arrays;
import com.example.tiny_computer.BuildConfig;
@Keep @SuppressLint({"StaticFieldLeak", "UnsafeDynamicallyLoadedCode"})
public class CmdEntryPoint extends ICmdEntryInterface.Stub {
public static final String ACTION_START = "com.termux.x11.CmdEntryPoint.ACTION_START";
public static final int PORT = 7892;
public static final byte[] MAGIC = "0xDEADBEEF".getBytes();
private static final Handler handler;
public static Context ctx;
/**
* Command-line entry point.
*
* @param args The command-line arguments
*/
public static void main(String[] args) {
android.util.Log.i("CmdEntryPoint", "commit " + BuildConfig.COMMIT);
handler.post(() -> new CmdEntryPoint(args));
Looper.loop();
}
CmdEntryPoint(String[] args) {
if (!start(args))
System.exit(1);
spawnListeningThread();
sendBroadcastDelayed();
}
@SuppressLint({"WrongConstant", "PrivateApi"})
void sendBroadcast() {
String targetPackage = getenv("TERMUX_X11_OVERRIDE_PACKAGE");
if (targetPackage == null)
targetPackage = BuildConfig.APPLICATION_ID;
// We should not care about multiple instances, it should be called only by `Termux:X11` app
// which is single instance...
Bundle bundle = new Bundle();
bundle.putBinder(null, this);
Intent intent = new Intent(ACTION_START);
intent.putExtra(null, bundle);
intent.setPackage(targetPackage);
if (getuid() == 0 || getuid() == 2000)
intent.setFlags(0x00400000 /* FLAG_RECEIVER_FROM_SHELL */);
try {
ctx.sendBroadcast(intent);
} catch (Exception e) {
if (e instanceof NullPointerException && ctx == null)
Log.i("Broadcast", "Context is null, falling back to manual broadcasting");
else
Log.e("Broadcast", "Falling back to manual broadcasting, failed to broadcast intent through Context:", e);
String packageName;
try {
packageName = android.app.ActivityThread.getPackageManager().getPackagesForUid(getuid())[0];
} catch (RemoteException ex) {
throw new RuntimeException(ex);
}
IActivityManager am;
try {
//noinspection JavaReflectionMemberAccess
am = (IActivityManager) android.app.ActivityManager.class
.getMethod("getService")
.invoke(null);
} catch (Exception e2) {
try {
am = (IActivityManager) Class.forName("android.app.ActivityManagerNative")
.getMethod("getDefault")
.invoke(null);
} catch (Exception e3) {
throw new RuntimeException(e3);
}
}
assert am != null;
IIntentSender sender = am.getIntentSender(1, packageName, null, null, 0, new Intent[] { intent },
null, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT, null, 0);
try {
//noinspection JavaReflectionMemberAccess
IIntentSender.class
.getMethod("send", int.class, Intent.class, String.class, IBinder.class, IIntentReceiver.class, String.class, Bundle.class)
.invoke(sender, 0, intent, null, null, new IIntentReceiver.Stub() {
@Override public void performReceive(Intent i, int r, String d, Bundle e, boolean o, boolean s, int a) {}
}, null, null);
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
}
// In some cases Android Activity part can not connect opened port.
// In this case opened port works like a lock file.
private void sendBroadcastDelayed() {
if (!connected())
sendBroadcast();
handler.postDelayed(this::sendBroadcastDelayed, 1000);
}
void spawnListeningThread() {
new Thread(() -> { // New thread is needed to avoid android.os.NetworkOnMainThreadException
/*
The purpose of this function is simple. If the application has not been launched
before running termux-x11, the initial sendBroadcast had no effect because no one
received the intent. To allow the application to reconnect freely, we will listen on
port `PORT` and when receiving a magic phrase, we will send another intent.
*/
Log.e("CmdEntryPoint", "Listening port " + PORT);
try (ServerSocket listeningSocket =
new ServerSocket(PORT, 0, InetAddress.getByName("127.0.0.1"))) {
listeningSocket.setReuseAddress(true);
while(true) {
try (Socket client = listeningSocket.accept()) {
Log.e("CmdEntryPoint", "Somebody connected!");
// We should ensure that it is some
byte[] b = new byte[MAGIC.length];
DataInputStream reader = new DataInputStream(client.getInputStream());
reader.readFully(b);
if (Arrays.equals(MAGIC, b)) {
Log.e("CmdEntryPoint", "New client connection!");
sendBroadcast();
}
} catch (Exception e) {
e.printStackTrace(System.err);
}
}
} catch (Exception e) {
e.printStackTrace(System.err);
}
}).start();
}
public static void requestConnection() {
System.err.println("Requesting connection...");
new Thread(() -> { // New thread is needed to avoid android.os.NetworkOnMainThreadException
try (Socket socket = new Socket("127.0.0.1", CmdEntryPoint.PORT)) {
socket.getOutputStream().write(CmdEntryPoint.MAGIC);
} catch (ConnectException e) {
if (e.getMessage() != null && e.getMessage().contains("Connection refused")) {
Log.e("CmdEntryPoint", "ECONNREFUSED: Connection has been refused by the server");
} else
Log.e("CmdEntryPoint", "Something went wrong when we requested connection", e);
} catch (Exception e) {
Log.e("CmdEntryPoint", "Something went wrong when we requested connection", e);
}
}).start();
}
/** @noinspection DataFlowIssue*/
@SuppressLint("DiscouragedPrivateApi")
public static Context createContext() {
Context context;
PrintStream err = System.err;
try {
java.lang.reflect.Field f = Class.forName("sun.misc.Unsafe").getDeclaredField("theUnsafe");
f.setAccessible(true);
Object unsafe = f.get(null);
// Hiding harmless framework errors, like this:
// java.io.FileNotFoundException: /data/system/theme_config/theme_compatibility.xml: open failed: ENOENT (No such file or directory)
System.setErr(new PrintStream(new OutputStream() { public void write(int arg0) {} }));
if (System.getenv("OLD_CONTEXT") != null) {
context = android.app.ActivityThread.systemMain().getSystemContext();
} else {
context = ((android.app.ActivityThread) Class.
forName("sun.misc.Unsafe").
getMethod("allocateInstance", Class.class).
invoke(unsafe, android.app.ActivityThread.class))
.getSystemContext();
}
} catch (Exception e) {
Log.e("Context", "Failed to instantiate context:", e);
context = null;
} finally {
System.setErr(err);
}
return context;
}
public static native boolean start(String[] args);
public native void windowChanged(Surface surface, String name);
public native ParcelFileDescriptor getXConnection();
public native ParcelFileDescriptor getLogcatOutput();
private static native boolean connected();
static {
try {
if (Looper.getMainLooper() == null)
Looper.prepareMainLooper();
} catch (Exception e) {
Log.e("CmdEntryPoint", "Something went wrong when preparing MainLooper", e);
}
handler = new Handler();
ctx = createContext();
String path = "lib/" + Build.SUPPORTED_ABIS[0] + "/libXlorie.so";
ClassLoader loader = CmdEntryPoint.class.getClassLoader();
URL res = loader != null ? loader.getResource(path) : null;
String libPath = res != null ? res.getFile().replace("file:", "") : null;
if (libPath != null) {
try {
System.load(libPath);
} catch (Exception e) {
Log.e("CmdEntryPoint", "Failed to dlopen " + libPath, e);
System.err.println("Failed to load native library. Did you install the right apk? Try the universal one.");
System.exit(134);
}
} else {
// It is critical only when it is not running in Android application process
if (MainActivity.getInstance() == null) {
System.err.println("Failed to acquire native library. Did you install the right apk? Try the universal one.");
System.exit(134);
}
}
}
}

View File

@@ -0,0 +1,810 @@
package com.termux.x11;
import static android.Manifest.permission.POST_NOTIFICATIONS;
import static android.Manifest.permission.WRITE_SECURE_SETTINGS;
import static android.content.pm.PackageManager.PERMISSION_DENIED;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.os.Build.VERSION.SDK_INT;
import android.annotation.SuppressLint;
import android.content.BroadcastReceiver;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.database.ContentObserver;
import android.graphics.Typeface;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.preference.ListPreference;
import androidx.preference.Preference;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.preference.PreferenceManager;
import androidx.annotation.Nullable;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.preference.PreferenceDataStore;
import androidx.preference.PreferenceFragmentCompat;
import androidx.preference.Preference.OnPreferenceChangeListener;
import androidx.preference.PreferenceScreen;
import androidx.preference.SeekBarPreference;
import android.provider.Settings;
import android.text.method.LinkMovementMethod;
import android.util.Log;
import android.util.TypedValue;
import android.view.Display;
import android.view.InputDevice;
import android.view.MenuItem;
import android.view.View;
import android.view.WindowManager;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import com.termux.x11.utils.KeyInterceptor;
import com.termux.x11.utils.SamsungDexUtils;
import com.termux.x11.utils.TermuxX11ExtraKeys;
import com.example.tiny_computer.R;
import com.example.tiny_computer.BuildConfig;
import java.io.StringWriter;
import java.io.PrintWriter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Objects;
import java.util.Set;
import java.util.function.Consumer;
import java.util.regex.PatternSyntaxException;
@SuppressWarnings("deprecation")
public class LoriePreferences extends AppCompatActivity implements PreferenceFragmentCompat.OnPreferenceStartFragmentCallback {
static final String ACTION_PREFERENCES_CHANGED = "com.termux.x11.ACTION_PREFERENCES_CHANGED";
private static Prefs prefs = null;
private final BroadcastReceiver receiver = new BroadcastReceiver() {
@SuppressLint("UnspecifiedRegisterReceiverFlag")
@Override
public void onReceive(Context context, Intent intent) {
if (ACTION_PREFERENCES_CHANGED.equals(intent.getAction()) &&
intent.getBooleanExtra("fromBroadcast", false))
updatePreferencesLayout();
}
};
private final ContentObserver accessibilityObserver = new ContentObserver(null) {
private final Runnable updateLayout = () -> updatePreferencesLayout();
@Override
public void onChange(boolean selfChange) {
handler.removeCallbacks(updateLayout);
handler.postDelayed(updateLayout, 200);
}
@Override
public boolean deliverSelfNotifications() {
return true;
}
};
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (hasFocus)
updatePreferencesLayout();
}
private void updatePreferencesLayout() {
getSupportFragmentManager().getFragments().forEach(fragment -> {
if (fragment instanceof LoriePreferenceFragment)
((LoriePreferenceFragment) fragment).updatePreferencesLayout();
});
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
prefs = new Prefs(this);
getSupportFragmentManager().beginTransaction().replace(android.R.id.content, new LoriePreferenceFragment(null)).commit();
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setHomeButtonEnabled(true);
}
Uri ENABLED_ACCESSIBILITY_SERVICES = Settings.Secure.getUriFor(Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
Uri ACCESSIBILITY_ENABLED = Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_ENABLED);
getContentResolver().registerContentObserver(ENABLED_ACCESSIBILITY_SERVICES, true, accessibilityObserver);
getContentResolver().registerContentObserver(ACCESSIBILITY_ENABLED, true, accessibilityObserver);
}
@SuppressLint("WrongConstant")
@Override
protected void onResume() {
super.onResume();
IntentFilter filter = new IntentFilter(ACTION_PREFERENCES_CHANGED);
registerReceiver(receiver, filter, SDK_INT >= Build.VERSION_CODES.TIRAMISU ? RECEIVER_NOT_EXPORTED : 0);
}
@Override
protected void onPause() {
super.onPause();
unregisterReceiver(receiver);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == android.R.id.home) {
if (getSupportFragmentManager().getBackStackEntryCount() == 0)
finish();
else
onBackPressed();
return true;
}
return super.onOptionsItemSelected(item);
}
private void showFragment(PreferenceFragmentCompat fragment) {
getSupportFragmentManager().beginTransaction()
.setCustomAnimations(R.anim.slide_in_right, R.anim.slide_out_left, R.anim.slide_in_left, R.anim.slide_out_right)
.replace(android.R.id.content, fragment)
.addToBackStack(null)
.commit();
}
@Override
public boolean onPreferenceStartFragment(@NonNull PreferenceFragmentCompat caller, @NonNull Preference pref) {
final LoriePreferenceFragment fragment = new LoriePreferenceFragment(pref.getFragment());
fragment.setTargetFragment(caller, 0);
showFragment(fragment);
return true;
}
public static class LoriePreferenceFragment extends PreferenceFragmentCompat implements OnPreferenceChangeListener {
private final Runnable updateLayout = this::updatePreferencesLayout;
private static final Method onSetInitialValue;
static {
try {
//noinspection JavaReflectionMemberAccess
onSetInitialValue = Preference.class.getMethod("onSetInitialValue", boolean.class, Object.class);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
}
}
void onSetInitialValue(Preference p) {
try {
onSetInitialValue.invoke(p, false, null);
} catch (IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
}
final String root;
/** @noinspection unused*/ // Used by `androidx.fragment.app.Fragment.instantiate`...
public LoriePreferenceFragment() {
this(null);
}
public LoriePreferenceFragment(String root) {
this.root = root;
}
@Override
public void onResume() {
super.onResume();
//noinspection DataFlowIssue
((LoriePreferences) getActivity()).getSupportActionBar().setTitle(getPreferenceScreen().getTitle());
}
/** @noinspection SameParameterValue*/
private void with(CharSequence key, Consumer<Preference> action) {
Preference p = findPreference(key);
if (p != null)
action.accept(p);
}
@SuppressLint("DiscouragedApi")
int findId(String name) {
//noinspection DataFlowIssue
return getResources().getIdentifier("pref_" + name, "string", getContext().getPackageName());
}
/** @noinspection DataFlowIssue*/
@Override @SuppressLint("ApplySharedPref")
public void onCreatePreferences(@Nullable Bundle savedInstanceState, @Nullable String rootKey) {
getPreferenceManager().setPreferenceDataStore(prefs);
if ((Integer.parseInt(prefs.touchMode.get()) - 1) > 2)
prefs.touchMode.put("1");
setPreferencesFromResource(R.xml.preferences, root == null ? "main" : root);
int id;
PreferenceScreen screen = getPreferenceScreen();
if ((id = findId(screen.getKey())) != 0)
getPreferenceScreen().setTitle(getResources().getString(id));
for (int i=0; i<getPreferenceScreen().getPreferenceCount(); i++) {
Preference p = screen.getPreference(i);
p.setOnPreferenceChangeListener(this);
p.setPreferenceDataStore(prefs);
if ((id = findId(p.getKey())) != 0)
p.setTitle(getResources().getString(id));
if ((id = findId(p.getKey() + "_summary")) != 0)
p.setSummary(getResources().getString(id));
if (p instanceof ListPreference) {
ListPreference list = (ListPreference) p;
list.setEntries(prefs.keys.get(p.getKey()).asList().getEntries());
list.setEntryValues(prefs.keys.get(p.getKey()).asList().getValues());
list.setSummaryProvider(ListPreference.SimpleSummaryProvider.getInstance());
}
}
with("showAdditionalKbd", p -> p.setLayoutResource(R.layout.preference));
with("version", p -> p.setSummary(BuildConfig.VERSION_NAME));
setSummary("displayStretch", R.string.pref_summary_requiresExactOrCustom);
setSummary("adjustResolution", R.string.pref_summary_requiresExactOrCustom);
setSummary("pauseKeyInterceptingWithEsc", R.string.pref_summary_requiresIntercepting);
setSummary("scaleTouchpad", R.string.pref_summary_requiresTrackpadAndNative);
if (!SamsungDexUtils.available())
setVisible("dexMetaKeyCapture", false);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P)
setVisible("hideCutout", false);
boolean stylusAvailable = Arrays.stream(InputDevice.getDeviceIds())
.mapToObj(InputDevice::getDevice)
.filter(Objects::nonNull)
.anyMatch(d -> d.supportsSource(InputDevice.SOURCE_STYLUS));
setVisible("showStylusClickOverride", stylusAvailable);
setVisible("stylusIsMouse", stylusAvailable);
setVisible("stylusButtonContactModifierMode", stylusAvailable);
setVisible("xrMode", XrActivity.isSupported());
setNoActionOptionText(findPreference("volumeDownAction"), "android volume control");
setNoActionOptionText(findPreference("volumeUpAction"), "android volume control");
}
private void setSummary(CharSequence key, int disabled) {
Preference pref = findPreference(key);
if (pref != null)
pref.setSummaryProvider(new Preference.SummaryProvider<Preference>() {
@Nullable @Override public CharSequence provideSummary(@NonNull Preference p) {
return p.isEnabled() ? null : getResources().getString(disabled);
}
});
}
private void setVisible(CharSequence key, boolean value) {
Preference p = findPreference(key);
if (p != null)
p.setVisible(value);
}
private void setEnabled(CharSequence key, boolean value) {
Preference p = findPreference(key);
if (p != null)
p.setEnabled(value);
}
@SuppressWarnings("ConstantConditions")
void updatePreferencesLayout() {
if (getContext() == null)
return;
for (String key : prefs.keys.keySet()) {
Preference p = findPreference(key);
if (p != null)
onSetInitialValue(p);
}
String displayResMode = prefs.displayResolutionMode.get();
setVisible("displayScale", displayResMode.contentEquals("scaled"));
setVisible("displayResolutionExact", displayResMode.contentEquals("exact"));
setVisible("displayResolutionCustom", displayResMode.contentEquals("custom"));
setEnabled("dexMetaKeyCapture", !prefs.enableAccessibilityServiceAutomatically.get());
setEnabled("enableAccessibilityServiceAutomatically", !prefs.dexMetaKeyCapture.get());
setEnabled("pauseKeyInterceptingWithEsc", prefs.dexMetaKeyCapture.get() ||
prefs.enableAccessibilityServiceAutomatically.get() ||
KeyInterceptor.isLaunched());
setEnabled("enableAccessibilityServiceAutomatically", prefs.enableAccessibilityServiceAutomatically.get() || KeyInterceptor.isLaunched());
setEnabled("filterOutWinkey", prefs.enableAccessibilityServiceAutomatically.get() || KeyInterceptor.isLaunched());
boolean displayStretchEnabled = "exact".contentEquals(prefs.displayResolutionMode.get()) || "custom".contentEquals(prefs.displayResolutionMode.get());
setEnabled("displayStretch", displayStretchEnabled);
setEnabled("adjustResolution", displayStretchEnabled);
setEnabled("scaleTouchpad", "1".equals(prefs.touchMode.get()) && !"native".equals(prefs.displayResolutionMode.get()));
setEnabled("showMouseHelper", "1".equals(prefs.touchMode.get()));
boolean requestNotificationPermissionVisible =
Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU
&& ContextCompat.checkSelfPermission(requireContext(), POST_NOTIFICATIONS) == PERMISSION_DENIED;
setVisible("requestNotificationPermission", requestNotificationPermissionVisible);
}
/** @noinspection SameParameterValue*/
private void setNoActionOptionText(Preference preference, CharSequence text) {
if (preference == null)
return;
ListPreference p = (ListPreference) preference;
CharSequence[] options = p.getEntries();
for (int i=0; i<options.length; i++) {
if ("no action".contentEquals(options[i]))
options[i] = "no action (" + text + ")";
}
}
@Override
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
updatePreferencesLayout();
}
@Override
public boolean onPreferenceTreeClick(@NonNull Preference p) {
if (p.getKey() == null)
return super.onPreferenceTreeClick(p);
if ("version".contentEquals(p.getKey())) {
Context ctx = getContext();
if (ctx != null) {
((ClipboardManager) ctx.getSystemService(Context.CLIPBOARD_SERVICE))
.setPrimaryClip(ClipData.newPlainText(p.getSummary(), p.getSummary()));
Toast.makeText(ctx, "Copied to clipboard", Toast.LENGTH_SHORT).show();
}
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && "requestNotificationPermission".contentEquals(p.getKey())) {
ActivityCompat.requestPermissions(requireActivity(), new String[]{POST_NOTIFICATIONS}, 101);
return true;
}
updatePreferencesLayout();
return super.onPreferenceTreeClick(p);
}
@SuppressLint("ApplySharedPref")
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
String key = preference.getKey();
Log.e("Preferences", "changed preference: " + key);
handler.removeCallbacks(updateLayout);
handler.postDelayed(updateLayout, 50);
if ("displayScale".contentEquals(key)) {
int scale = (Integer) newValue;
if (scale % 10 != 0) {
scale = Math.round( ( (float) scale ) / 10 ) * 10;
((SeekBarPreference) preference).setValue(scale);
return false;
}
}
if ("displayResolutionCustom".contentEquals(key)) {
String value = (String) newValue;
try {
String[] resolution = value.split("x");
Integer.parseInt(resolution[0]);
Integer.parseInt(resolution[1]);
} catch (NumberFormatException | PatternSyntaxException ignored) {
Toast.makeText(getActivity(), "Wrong resolution format", Toast.LENGTH_SHORT).show();
return false;
}
}
if ("showAdditionalKbd".contentEquals(key) && (Boolean) newValue)
prefs.additionalKbdVisible.put(true);
if ("enableAccessibilityServiceAutomatically".contentEquals(key)) {
if (!((Boolean) newValue))
KeyInterceptor.shutdown(false);
if (requireContext().checkSelfPermission(WRITE_SECURE_SETTINGS) != PERMISSION_GRANTED) {
new AlertDialog.Builder(requireContext())
.setTitle("Permission denied")
.setMessage("Android requires WRITE_SECURE_SETTINGS permission to start accessibility service automatically.\n" +
"Please, launch this command using ADB:\n" +
"adb shell pm grant com.fct.tiny android.permission.WRITE_SECURE_SETTINGS")
.setNegativeButton("OK", null)
.create()
.show();
return false;
}
}
requireContext().sendBroadcast(new Intent(ACTION_PREFERENCES_CHANGED) {{
putExtra("key", key);
putExtra("fromBroadcast", true);
setPackage(BuildConfig.APPLICATION_ID);
}});
return true;
}
@Override
public void onDisplayPreferenceDialog(@NonNull Preference preference) {
if ("extra_keys_config".contentEquals(preference.getKey())) {
@SuppressLint("InflateParams")
View view = getLayoutInflater().inflate(R.layout.extra_keys_config, null, false);
EditText config = view.findViewById(R.id.extra_keys_config);
config.setTypeface(Typeface.MONOSPACE);
config.setText(prefs.extra_keys_config.get());
TextView desc = view.findViewById(R.id.extra_keys_config_description);
desc.setLinksClickable(true);
desc.setText(R.string.extra_keys_config_desc);
desc.setMovementMethod(LinkMovementMethod.getInstance());
new android.app.AlertDialog.Builder(getActivity())
.setView(view)
.setTitle("Extra keys config")
.setPositiveButton("OK",
(dialog, whichButton) -> {
String text = config.getText().toString();
prefs.extra_keys_config.put(!text.isEmpty() ? text : TermuxX11ExtraKeys.DEFAULT_IVALUE_EXTRA_KEYS);
}
)
.setNeutralButton("Reset",
(dialog, whichButton) -> prefs.extra_keys_config.put(TermuxX11ExtraKeys.DEFAULT_IVALUE_EXTRA_KEYS))
.setNegativeButton("Cancel", (dialog, whichButton) -> dialog.dismiss())
.create()
.show();
} else super.onDisplayPreferenceDialog(preference);
}
}
public static class Receiver extends BroadcastReceiver {
public Receiver() {
super();
}
@Override
public IBinder peekService(Context myContext, Intent service) {
return super.peekService(myContext, service);
}
/** @noinspection StringConcatenationInLoop*/
@SuppressLint("ApplySharedPref")
@Override
public void onReceive(Context context, Intent intent) {
try {
if (intent.getExtras() != null) {
Prefs p = (MainActivity.getInstance() != null) ? new Prefs(MainActivity.getInstance()) : (prefs != null ? prefs : new Prefs(context));
if (intent.getStringExtra("list") != null) {
String result = "";
for (PrefsProto.Preference pref : p.keys.values()) {
if (pref.type == String.class)
result += "\"" + pref.key + "\"=\"" + pref.asString().get() + "\"\n";
else if (pref.type == int.class)
result += "\"" + pref.key + "\"=\"" + pref.asInt().get() + "\"\n";
else if (pref.type == boolean.class)
result += "\"" + pref.key + "\"=\"" + pref.asBoolean().get() + "\"\n";
else if (pref.type == String[].class) {
String[] entries = context.getResources().getStringArray(pref.asList().entries);
String[] values = context.getResources().getStringArray(pref.asList().values);
String value = pref.asList().get();
int index = Arrays.asList(values).indexOf(value);
if (index != -1)
value = entries[index];
result += "\"" + pref.key + "\"=\"" + value + "\"\n";
}
}
setResultCode(2);
setResultData(result);
return;
}
SharedPreferences.Editor edit = p.get().edit();
for (String key : intent.getExtras().keySet()) {
String newValue = intent.getStringExtra(key);
if (newValue == null)
continue;
switch (key) {
case "displayResolutionCustom": {
try {
String[] resolution = newValue.split("x");
Integer.parseInt(resolution[0]);
Integer.parseInt(resolution[1]);
} catch (NumberFormatException | PatternSyntaxException ignored) {
setResultCode(1);
setResultData("displayResolutionCustom: Wrong resolution format.");
return;
}
edit.putString("displayResolutionCustom", newValue);
break;
}
case "enableAccessibilityServiceAutomatically": {
if (!"true".equals(newValue))
KeyInterceptor.shutdown(false);
else if (context.checkSelfPermission(WRITE_SECURE_SETTINGS) != PERMISSION_GRANTED) {
setResultCode(1);
setResultData("Permission denied.\n" +
"Android requires WRITE_SECURE_SETTINGS permission to change `enableAccessibilityServiceAutomatically` setting.\n" +
"Please, launch this command using ADB:\n" +
"adb shell pm grant com.fct.tiny android.permission.WRITE_SECURE_SETTINGS");
return;
}
edit.putBoolean("enableAccessibilityServiceAutomatically", "true".contentEquals(newValue));
break;
}
case "extra_keys_config": {
edit.putString(key, newValue);
break;
}
default: {
PrefsProto.Preference pref = p.keys.get(key);
if (pref != null && pref.type == boolean.class) {
edit.putBoolean(key, "true".contentEquals(newValue));
if ("showAdditionalKbd".contentEquals(key) && "true".contentEquals(newValue))
edit.putBoolean("additionalKbdVisible", true);
} else if (pref != null && pref.type == int.class) {
try {
edit.putInt(key, Integer.parseInt(newValue));
} catch (NumberFormatException | PatternSyntaxException exception) {
setResultCode(4);
setResultData(key + ": failed to parse integer: " + exception);
return;
}
} else if (pref != null && pref.type == String[].class) {
PrefsProto.ListPreference _p = (PrefsProto.ListPreference) pref;
String[] entries = _p.getEntries();
String[] values = _p.getValues();
int index = Arrays.asList(entries).indexOf(newValue);
if (index == -1 && _p.entries != _p.values)
index = Arrays.asList(values).indexOf(newValue);
if (index != -1) {
edit.putString(key, values[index]);
break;
}
setResultCode(1);
setResultData(key + ": can not be set to \"" + newValue + "\", possible options are " + Arrays.toString(entries) + (_p.entries != _p.values ? " or " + Arrays.toString(values) : ""));
return;
} else {
setResultCode(4);
setResultData(key + ": unrecognised option");
return;
}
}
}
Intent intent0 = new Intent(ACTION_PREFERENCES_CHANGED);
intent0.putExtra("key", key);
intent0.putExtra("fromBroadcast", true);
intent0.setPackage(BuildConfig.APPLICATION_ID);
context.sendBroadcast(intent0);
}
edit.commit();
}
setResultCode(2);
setResultData("Done");
} catch (Exception e) {
setResultCode(4);
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
setResultData(sw.toString());
}
}
}
static Handler handler = new Handler(Looper.getMainLooper());
public void onClick(View view) {
showFragment(new LoriePreferenceFragment("ekbar"));
}
/** @noinspection unused*/
@SuppressLint("ApplySharedPref")
public static class PrefsProto extends PreferenceDataStore {
public static class Preference {
protected final String key;
protected final Class<?> type;
protected final Object defValue;
protected Preference(String key, Class<?> class_, Object default_) {
this.key = key;
this.type = class_;
this.defValue = default_;
}
public ListPreference asList() {
return (ListPreference) this;
}
public StringPreference asString() {
return (StringPreference) this;
}
public IntPreference asInt() {
return (IntPreference) this;
}
public BooleanPreference asBoolean() {
return (BooleanPreference) this;
}
}
public class BooleanPreference extends Preference {
public BooleanPreference(String key, boolean defValue) {
super(key, boolean.class, defValue);
}
public boolean get() {
if ("storeSecondaryDisplayPreferencesSeparately".contentEquals(key))
return builtInDisplayPreferences.getBoolean(key, (boolean) defValue);
return preferences.getBoolean(key, (boolean) defValue);
}
public void put(boolean v) {
if ("storeSecondaryDisplayPreferencesSeparately".contentEquals(key)) {
builtInDisplayPreferences.edit().putBoolean(key, v).commit();
recheckStoringSecondaryDisplayPreferences();
}
preferences.edit().putBoolean(key, v).commit();
}
}
public class IntPreference extends Preference {
public IntPreference(String key, int defValue) {
super(key, int.class, defValue);
}
public int get() {
return preferences.getInt(key, (int) defValue);
}
public int defValue() {
return preferences.getInt(key, (int) defValue);
}
}
public class StringPreference extends Preference {
public StringPreference(String key, String defValue) {
super(key, String.class, defValue);
}
public String get() {
return preferences.getString(key, (String) defValue);
}
public void put(String v) {
preferences.edit().putString(key, v).commit();
}
}
public class ListPreference extends Preference {
private final int entries, values;
public ListPreference(String key, String defValue, int entries, int values) {
super(key, String[].class, defValue);
this.entries = entries;
this.values = values;
}
public String get() {
return preferences.getString(key, (String) defValue);
}
public void put(String v) {
preferences.edit().putString(key, v).commit();
}
public String[] getEntries() {
return getArrayItems(entries, ctx.getResources());
}
public String[] getValues() {
return getArrayItems(values, ctx.getResources());
}
private String[] getArrayItems(int resourceId, Resources resources) {
ArrayList<String> itemList = new ArrayList<>();
try(TypedArray typedArray = resources.obtainTypedArray(resourceId)) {
for (int i = 0; i < typedArray.length(); i++) {
int type = typedArray.getType(i);
if (type == TypedValue.TYPE_STRING) {
itemList.add(typedArray.getString(i));
} else if (type == TypedValue.TYPE_REFERENCE) {
int resIdOfArray = typedArray.getResourceId(i, 0);
itemList.addAll(Arrays.asList(resources.getStringArray(resIdOfArray)));
}
}
}
Object[] objectArray = itemList.toArray();
return Arrays.copyOf(objectArray, objectArray.length, String[].class);
}
}
static boolean storeSecondaryDisplayPreferencesSeparately = false;
protected Context ctx;
protected SharedPreferences preferences;
protected SharedPreferences builtInDisplayPreferences;
protected SharedPreferences secondaryDisplayPreferences;
private PrefsProto() {} // No instantiation allowed
protected PrefsProto(Context ctx) {
this.ctx = ctx;
builtInDisplayPreferences = PreferenceManager.getDefaultSharedPreferences(ctx);
secondaryDisplayPreferences = ctx.getSharedPreferences("secondary", Context.MODE_PRIVATE);
recheckStoringSecondaryDisplayPreferences();
}
protected void recheckStoringSecondaryDisplayPreferences() {
storeSecondaryDisplayPreferencesSeparately = builtInDisplayPreferences.getBoolean("storeSecondaryDisplayPreferencesSeparately", false);
boolean isExternalDisplay = ((WindowManager) ctx.getSystemService(WINDOW_SERVICE)).getDefaultDisplay().getDisplayId() != Display.DEFAULT_DISPLAY;
preferences = (storeSecondaryDisplayPreferencesSeparately && isExternalDisplay) ? secondaryDisplayPreferences : builtInDisplayPreferences;
}
@Override public void putBoolean(String k, boolean v) {
if ("storeSecondaryDisplayPreferencesSeparately".contentEquals(k)) {
builtInDisplayPreferences.edit().putBoolean(k, v).commit();
recheckStoringSecondaryDisplayPreferences();
} else
preferences.edit().putBoolean(k, v).commit();
}
@Override public boolean getBoolean(String k, boolean d) {
if ("storeSecondaryDisplayPreferencesSeparately".contentEquals(k))
return builtInDisplayPreferences.getBoolean(k, d);
return preferences.getBoolean(k, d);
}
@Override public void putString(String k, @Nullable String v) { prefs.get().edit().putString(k, v).commit(); }
@Override public void putStringSet(String k, @Nullable Set<String> v) { prefs.get().edit().putStringSet(k, v).commit(); }
@Override public void putInt(String k, int v) { prefs.get().edit().putInt(k, v).commit(); }
@Override public void putLong(String k, long v) { prefs.get().edit().putLong(k, v).commit(); }
@Override public void putFloat(String k, float v) { prefs.get().edit().putFloat(k, v).commit(); }
@Nullable @Override public String getString(String k, @Nullable String d) { return prefs.get().getString(k, d); }
@Nullable @Override public Set<String> getStringSet(String k, @Nullable Set<String> ds) { return prefs.get().getStringSet(k, ds); }
@Override public int getInt(String k, int d) { return prefs.get().getInt(k, d); }
@Override public long getLong(String k, long d) { return prefs.get().getLong(k, d); }
@Override public float getFloat(String k, float d) { return prefs.get().getFloat(k, d); }
public SharedPreferences get() {
return preferences;
}
public boolean isSecondaryDisplayPreferences() {
return preferences == secondaryDisplayPreferences;
}
}
}

View File

@@ -0,0 +1,381 @@
package com.termux.x11;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.ClipData;
import android.content.ClipDescription;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.ContextWrapper;
import android.graphics.Color;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
import android.os.Build;
import android.text.Editable;
import android.text.InputType;
import android.util.AttributeSet;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.inputmethod.BaseInputConnection;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputMethodManager;
import android.view.inputmethod.InputMethodSubtype;
import androidx.annotation.Keep;
import androidx.annotation.NonNull;
import com.termux.x11.input.InputStub;
import com.termux.x11.input.TouchInputHandler;
import java.nio.charset.StandardCharsets;
import java.util.regex.PatternSyntaxException;
@Keep @SuppressLint("WrongConstant")
@SuppressWarnings("deprecation")
public class LorieView extends SurfaceView implements InputStub {
public interface Callback {
void changed(Surface sfc, int surfaceWidth, int surfaceHeight, int screenWidth, int screenHeight);
}
interface PixelFormat {
int BGRA_8888 = 5; // Stands for HAL_PIXEL_FORMAT_BGRA_8888
}
private ClipboardManager clipboard;
private long lastClipboardTimestamp = System.currentTimeMillis();
private static boolean clipboardSyncEnabled = false;
private static boolean hardwareKbdScancodesWorkaround = false;
private final InputMethodManager mIMM = (InputMethodManager)getContext().getSystemService( Context.INPUT_METHOD_SERVICE);
private String mImeLang;
private boolean mImeCJK;
public boolean enableGboardCJK;
private Callback mCallback;
private final Point p = new Point();
private final SurfaceHolder.Callback mSurfaceCallback = new SurfaceHolder.Callback() {
@Override public void surfaceCreated(@NonNull SurfaceHolder holder) {
holder.setFormat(PixelFormat.BGRA_8888);
}
@Override public void surfaceChanged(@NonNull SurfaceHolder holder, int f, int width, int height) {
width = getMeasuredWidth();
height = getMeasuredHeight();
Log.d("SurfaceChangedListener", "Surface was changed: " + width + "x" + height);
if (mCallback == null)
return;
getDimensionsFromSettings();
mCallback.changed(holder.getSurface(), width, height, p.x, p.y);
}
@Override public void surfaceDestroyed(@NonNull SurfaceHolder holder) {
if (mCallback != null)
mCallback.changed(holder.getSurface(), 0, 0, 0, 0);
}
};
public LorieView(Context context) { super(context); init(); }
public LorieView(Context context, AttributeSet attrs) { super(context, attrs); init(); }
public LorieView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); }
@SuppressWarnings("unused")
public LorieView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); init(); }
private void init() {
getHolder().addCallback(mSurfaceCallback);
clipboard = (ClipboardManager) getContext().getSystemService(Context.CLIPBOARD_SERVICE);
}
public void setCallback(Callback callback) {
mCallback = callback;
triggerCallback();
}
public void regenerate() {
Callback callback = mCallback;
mCallback = null;
getHolder().setFormat(android.graphics.PixelFormat.RGBA_8888);
mCallback = callback;
triggerCallback();
}
public void triggerCallback() {
setFocusable(true);
setFocusableInTouchMode(true);
requestFocus();
setBackground(new ColorDrawable(Color.TRANSPARENT) {
public boolean isStateful() {
return true;
}
public boolean hasFocusStateSpecified() {
return true;
}
});
Rect r = getHolder().getSurfaceFrame();
getActivity().runOnUiThread(() -> mSurfaceCallback.surfaceChanged(getHolder(), PixelFormat.BGRA_8888, r.width(), r.height()));
}
private Activity getActivity() {
Context context = getContext();
while (context instanceof ContextWrapper) {
if (context instanceof Activity) {
return (Activity) context;
}
context = ((ContextWrapper) context).getBaseContext();
}
throw new NullPointerException();
}
void getDimensionsFromSettings() {
Prefs prefs = MainActivity.getPrefs();
int width = getMeasuredWidth();
int height = getMeasuredHeight();
if (XrActivity.isEnabled()) {
width = 1024;
height = 768;
}
int w = width;
int h = height;
switch(prefs.displayResolutionMode.get()) {
case "scaled": {
int scale = prefs.displayScale.get();
w = width * 100 / scale;
h = height * 100 / scale;
break;
}
case "exact": {
String[] resolution = prefs.displayResolutionExact.get().split("x");
w = Integer.parseInt(resolution[0]);
h = Integer.parseInt(resolution[1]);
break;
}
case "custom": {
try {
String[] resolution = prefs.displayResolutionCustom.get().split("x");
w = Integer.parseInt(resolution[0]);
h = Integer.parseInt(resolution[1]);
} catch (NumberFormatException | PatternSyntaxException ignored) {
w = 1280;
h = 1024;
}
break;
}
}
if (prefs.adjustResolution.get() && ((width < height && w > h) || (width > height && w < h)))
p.set(h, w);
else
p.set(w, h);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
Prefs prefs = MainActivity.getPrefs();
if (prefs.displayStretch.get()
|| "native".equals(prefs.displayResolutionMode.get())
|| "scaled".equals(prefs.displayResolutionMode.get())) {
if (!XrActivity.isEnabled()) {
getHolder().setSizeFromLayout();
return;
}
}
getDimensionsFromSettings();
if (p.x <= 0 || p.y <= 0)
return;
int width = getMeasuredWidth();
int height = getMeasuredHeight();
if (prefs.adjustResolution.get() && ((width < height && p.x > p.y) || (width > height && p.x < p.y)))
//noinspection SuspiciousNameCombination
p.set(p.y, p.x);
if (width > height * p.x / p.y)
width = height * p.x / p.y;
else
height = width * p.y / p.x;
getHolder().setFixedSize(p.x, p.y);
setMeasuredDimension(width, height);
// In the case if old fixed surface size equals new fixed surface size surfaceChanged will not be called.
// We should force it.
regenerate();
}
@Override
public void sendMouseWheelEvent(float deltaX, float deltaY) {
sendMouseEvent(deltaX, deltaY, BUTTON_SCROLL, false, true);
}
@Override
public boolean dispatchKeyEventPreIme(KeyEvent event) {
if (hardwareKbdScancodesWorkaround) return false;
Activity a = getActivity();
return (a instanceof MainActivity) && ((MainActivity) a).handleKey(event);
}
ClipboardManager.OnPrimaryClipChangedListener clipboardListener = this::handleClipboardChange;
public void reloadPreferences(Prefs p) {
hardwareKbdScancodesWorkaround = p.hardwareKbdScancodesWorkaround.get();
clipboardSyncEnabled = p.clipboardEnable.get();
setClipboardSyncEnabled(clipboardSyncEnabled, clipboardSyncEnabled);
TouchInputHandler.refreshInputDevices();
enableGboardCJK = p.enableGboardCJK.get();
mIMM.restartInput(this);
}
// It is used in native code
void setClipboardText(String text) {
clipboard.setPrimaryClip(ClipData.newPlainText("X11 clipboard", text));
// Android does not send PrimaryClipChanged event to the window which posted event
// But in the case we are owning focus and clipboard is unchanged it will be replaced by the same value on X server side.
// Not cool in the case if user installed some clipboard manager, clipboard content will be doubled.
lastClipboardTimestamp = System.currentTimeMillis() + 150;
}
/** @noinspection unused*/ // It is used in native code
void requestClipboard() {
if (!clipboardSyncEnabled) {
sendClipboardEvent("".getBytes(StandardCharsets.UTF_8));
return;
}
CharSequence clip = clipboard.getText();
if (clip != null) {
String text = String.valueOf(clipboard.getText());
sendClipboardEvent(text.getBytes(StandardCharsets.UTF_8));
Log.d("CLIP", "sending clipboard contents: " + text);
}
}
public void handleClipboardChange() {
checkForClipboardChange();
}
public void checkForClipboardChange() {
ClipDescription desc = clipboard.getPrimaryClipDescription();
if (clipboardSyncEnabled && desc != null &&
lastClipboardTimestamp < desc.getTimestamp() &&
desc.getMimeTypeCount() == 1 &&
(desc.hasMimeType(ClipDescription.MIMETYPE_TEXT_PLAIN) ||
desc.hasMimeType(ClipDescription.MIMETYPE_TEXT_HTML))) {
lastClipboardTimestamp = desc.getTimestamp();
sendClipboardAnnounce();
Log.d("CLIP", "sending clipboard announce");
}
}
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (hasFocus)
regenerate();
requestFocus();
if (clipboardSyncEnabled && hasFocus) {
clipboard.addPrimaryClipChangedListener(clipboardListener);
checkForClipboardChange();
} else
clipboard.removePrimaryClipChangedListener(clipboardListener);
TouchInputHandler.refreshInputDevices();
}
public void checkRestartInput(boolean recheck) {
if (!enableGboardCJK)
return;
InputMethodSubtype methodSubtype = mIMM.getCurrentInputMethodSubtype();
String languageTag = methodSubtype == null ? null : methodSubtype.getLanguageTag();
if (languageTag != null && languageTag.length() >= 2 && !languageTag.substring(0, 2).equals(mImeLang))
mIMM.restartInput(this);
else if (recheck) { // recheck needed because sometimes requestCursorUpdates() is called too fast, before InputMethodManager detect change in IM subtype
MainActivity.handler.postDelayed(() -> checkRestartInput(false), 40);
}
}
@Override
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
outAttrs.inputType = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS | InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD;
// Note that IME_ACTION_NONE cannot be used as that makes it impossible to input newlines using the on-screen
// keyboard on Android TV (see https://github.com/termux/termux-app/issues/221).
outAttrs.imeOptions = EditorInfo.IME_FLAG_NO_FULLSCREEN;
if (enableGboardCJK) {
InputMethodSubtype methodSubtype = mIMM.getCurrentInputMethodSubtype();
mImeLang = methodSubtype == null ? null : methodSubtype.getLanguageTag();
if (mImeLang != null && mImeLang.length() > 2)
mImeLang = mImeLang.substring(0, 2);
mImeCJK = mImeLang != null && (mImeLang.equals("zh") || mImeLang.equals("ko") || mImeLang.equals("ja"));
outAttrs.inputType = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS |
(mImeCJK ? InputType.TYPE_TEXT_VARIATION_NORMAL : InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD);
return new BaseInputConnection(this, false) {
// workaround for Gboard
// Gboard calls requestCursorUpdates() whenever switching language
// check and then restart keyboard in different inputType when needed
@Override
public Editable getEditable() {
checkRestartInput(true);
return super.getEditable();
}
@Override
public boolean requestCursorUpdates(int cursorUpdateMode) {
checkRestartInput(true);
return super.requestCursorUpdates(cursorUpdateMode);
}
@Override
public boolean commitText(CharSequence text, int newCursorPosition) {
boolean result = super.commitText(text, newCursorPosition);
if (mImeCJK)
// suppress Gboard CJK keyboard suggestion
// this workaround does not work well for non-CJK keyboards
// , when typing fast and two keypresses (commitText) are close in time
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU)
mIMM.invalidateInput(LorieView.this);
else
mIMM.restartInput(LorieView.this);
return result;
}
};
} else {
return super.onCreateInputConnection(outAttrs);
}
}
static native void connect(int fd);
native void handleXEvents();
static native void startLogcat(int fd);
static native void setClipboardSyncEnabled(boolean enabled, boolean ignored);
public native void sendClipboardAnnounce();
public native void sendClipboardEvent(byte[] text);
static native void sendWindowChange(int width, int height, int framerate);
public native void sendMouseEvent(float x, float y, int whichButton, boolean buttonDown, boolean relative);
public native void sendTouchEvent(int action, int id, int x, int y);
public native void sendStylusEvent(float x, float y, int pressure, int tiltX, int tiltY, int orientation, int buttons, boolean eraser, boolean mouseMode);
static public native void requestStylusEnabled(boolean enabled);
public native boolean sendKeyEvent(int scanCode, int keyCode, boolean keyDown);
public native void sendTextEvent(byte[] text);
static {
System.loadLibrary("Xlorie");
}
}

View File

@@ -0,0 +1,910 @@
package com.termux.x11;
import static android.Manifest.permission.WRITE_SECURE_SETTINGS;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.os.Build.VERSION.SDK_INT;
import static android.view.KeyEvent.*;
import static android.view.WindowManager.LayoutParams.*;
import static com.termux.x11.CmdEntryPoint.ACTION_START;
import static com.termux.x11.LoriePreferences.ACTION_PREFERENCES_CHANGED;
import android.Manifest;
import android.annotation.SuppressLint;
import android.app.AppOpsManager;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.BroadcastReceiver;
import android.content.ClipData;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.graphics.Canvas;
import android.graphics.Color;
import android.net.Uri;
import android.os.Build;
import android.os.Build.VERSION_CODES;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.os.SystemClock;
import android.service.notification.StatusBarNotification;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Display;
import android.view.DragEvent;
import android.view.InputDevice;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.PointerIcon;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowInsets;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.NotificationCompat;
import androidx.core.math.MathUtils;
import androidx.viewpager.widget.ViewPager;
import com.termux.x11.input.InputEventSender;
import com.termux.x11.input.InputStub;
import com.termux.x11.input.TouchInputHandler;
import com.termux.x11.utils.FullscreenWorkaround;
import com.termux.x11.utils.KeyInterceptor;
import com.termux.x11.utils.SamsungDexUtils;
import com.termux.x11.utils.TermuxX11ExtraKeys;
import com.termux.x11.utils.X11ToolbarViewPager;
import java.util.Map;
import com.example.tiny_computer.R;
@SuppressLint("ApplySharedPref")
@SuppressWarnings({"deprecation", "unused"})
public class MainActivity extends AppCompatActivity implements View.OnApplyWindowInsetsListener {
public static final String ACTION_STOP = "com.termux.x11.ACTION_STOP";
public static final String ACTION_CUSTOM = "com.termux.x11.ACTION_CUSTOM";
public static Handler handler = new Handler();
FrameLayout frm;
private TouchInputHandler mInputHandler;
protected ICmdEntryInterface service = null;
public TermuxX11ExtraKeys mExtraKeys;
private Notification mNotification;
private final int mNotificationId = 7892;
NotificationManager mNotificationManager;
static InputMethodManager inputMethodManager;
private static boolean showIMEWhileExternalConnected = true;
private static boolean externalKeyboardConnected = false;
private boolean mClientConnected = false;
private View.OnKeyListener mLorieKeyListener;
private boolean filterOutWinKey = false;
private boolean useTermuxEKBarBehaviour = false;
public static Prefs prefs = null;
private static boolean oldFullscreen = false, oldHideCutout = false, oldXrMode = false;
private final SharedPreferences.OnSharedPreferenceChangeListener preferencesChangedListener = (__, key) -> onPreferencesChanged(key);
private final BroadcastReceiver receiver = new BroadcastReceiver() {
@SuppressLint("UnspecifiedRegisterReceiverFlag")
@Override
public void onReceive(Context context, Intent intent) {
prefs.recheckStoringSecondaryDisplayPreferences();
if (ACTION_START.equals(intent.getAction())) {
try {
Log.v("LorieBroadcastReceiver", "Got new ACTION_START intent");
onReceiveConnection(intent);
} catch (Exception e) {
Log.e("MainActivity", "Something went wrong while we extracted connection details from binder.", e);
}
} else if (ACTION_STOP.equals(intent.getAction())) {
finishAffinity();
} else if (ACTION_PREFERENCES_CHANGED.equals(intent.getAction())) {
Log.d("MainActivity", "preference: " + intent.getStringExtra("key"));
if (!"additionalKbdVisible".equals(intent.getStringExtra("key")))
onPreferencesChanged("");
} else if (ACTION_CUSTOM.equals(intent.getAction())) {
android.util.Log.d("ACTION_CUSTOM", "action " + intent.getStringExtra("what"));
mInputHandler.extractUserActionFromPreferences(prefs, intent.getStringExtra("what")).accept(true);
}
}
};
@SuppressLint("StaticFieldLeak")
private static MainActivity instance;
public MainActivity() {
instance = this;
}
public static Prefs getPrefs() {
return prefs;
}
public static MainActivity getInstance() {
return instance;
}
@Override
@SuppressLint({"AppCompatMethod", "ObsoleteSdkInt", "ClickableViewAccessibility", "WrongConstant", "UnspecifiedRegisterReceiverFlag"})
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
prefs = new Prefs(this);
int modeValue = Integer.parseInt(prefs.touchMode.get()) - 1;
if (modeValue > 2)
prefs.touchMode.put("1");
oldFullscreen = prefs.fullscreen.get();
oldHideCutout = prefs.hideCutout.get();
oldXrMode = prefs.xrMode.get();
prefs.get().registerOnSharedPreferenceChangeListener(preferencesChangedListener);
getWindow().setFlags(FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS | FLAG_KEEP_SCREEN_ON | FLAG_TRANSLUCENT_STATUS, 0);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.main_activity);
frm = findViewById(R.id.frame);
findViewById(R.id.preferences_button).setOnClickListener((l) -> startActivity(new Intent(this, LoriePreferences.class) {{ setAction(Intent.ACTION_MAIN); }}));
findViewById(R.id.help_button).setOnClickListener((l) -> startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://github.com/termux/termux-x11/blob/master/README.md#running-graphical-applications"))));
findViewById(R.id.exit_button).setOnClickListener((l) -> finish());
LorieView lorieView = findViewById(R.id.lorieView);
View lorieParent = (View) lorieView.getParent();
mInputHandler = new TouchInputHandler(this, new InputEventSender(lorieView));
mLorieKeyListener = (v, k, e) -> {
InputDevice dev = e.getDevice();
boolean result = mInputHandler.sendKeyEvent(e);
// Do not steal dedicated buttons from a full external keyboard.
if (useTermuxEKBarBehaviour && mExtraKeys != null && (dev == null || dev.isVirtual()))
mExtraKeys.unsetSpecialKeys();
return result;
};
lorieParent.setOnTouchListener((v, e) -> mInputHandler.handleTouchEvent(lorieParent, lorieView, e));
lorieParent.setOnHoverListener((v, e) -> mInputHandler.handleTouchEvent(lorieParent, lorieView, e));
lorieParent.setOnGenericMotionListener((v, e) -> mInputHandler.handleTouchEvent(lorieParent, lorieView, e));
lorieView.setOnCapturedPointerListener((v, e) -> mInputHandler.handleTouchEvent(lorieView, lorieView, e));
lorieParent.setOnCapturedPointerListener((v, e) -> mInputHandler.handleTouchEvent(lorieView, lorieView, e));
lorieView.setOnKeyListener(mLorieKeyListener);
lorieView.setCallback((sfc, surfaceWidth, surfaceHeight, screenWidth, screenHeight) -> {
int framerate = (int) ((lorieView.getDisplay() != null) ? lorieView.getDisplay().getRefreshRate() : 30);
mInputHandler.handleHostSizeChanged(surfaceWidth, surfaceHeight);
mInputHandler.handleClientSizeChanged(screenWidth, screenHeight);
Log.d("DEBUG_TAG", "screenWidth: " + screenWidth + ", screenHeight: " + screenHeight + ", framerate: " + framerate);
LorieView.sendWindowChange(screenWidth, screenHeight, framerate);
if (service != null) {
try {
String name;
if (lorieView.getDisplay() == null || lorieView.getDisplay().getDisplayId() == Display.DEFAULT_DISPLAY)
name = "Builtin Display";
else if (SamsungDexUtils.checkDeXEnabled(this))
name = "Dex Display";
else
name = "External Display";
service.windowChanged(sfc, name);
} catch (RemoteException e) {
Log.e("MainActivity", "failed to send windowChanged request", e);
}
}
});
registerReceiver(receiver, new IntentFilter(ACTION_START) {{
addAction(ACTION_PREFERENCES_CHANGED);
addAction(ACTION_STOP);
addAction(ACTION_CUSTOM);
}}, SDK_INT >= VERSION_CODES.TIRAMISU ? RECEIVER_EXPORTED : 0);
inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
// Taken from Stackoverflow answer https://stackoverflow.com/questions/7417123/android-how-to-adjust-layout-in-full-screen-mode-when-softkeyboard-is-visible/7509285#
FullscreenWorkaround.assistActivity(this);
mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotification = buildNotification();
mNotificationManager.notify(mNotificationId, mNotification);
CmdEntryPoint.requestConnection();
onPreferencesChanged("");
toggleExtraKeys(false, false);
checkXEvents();
initStylusAuxButtons();
initMouseAuxButtons();
if (SDK_INT >= VERSION_CODES.TIRAMISU
&& checkSelfPermission(Manifest.permission.POST_NOTIFICATIONS) != PERMISSION_GRANTED
&& !shouldShowRequestPermissionRationale(Manifest.permission.POST_NOTIFICATIONS)) {
requestPermissions(new String[] { Manifest.permission.POST_NOTIFICATIONS }, 0);
}
onReceiveConnection(getIntent());
}
@Override
protected void onDestroy() {
unregisterReceiver(receiver);
super.onDestroy();
}
//Register the needed events to handle stylus as left, middle and right click
@SuppressLint("ClickableViewAccessibility")
private void initStylusAuxButtons() {
boolean stylusMenuEnabled = prefs.showStylusClickOverride.get() && mClientConnected;
final float menuUnselectedTrasparency = 0.66f;
final float menuSelectedTrasparency = 1.0f;
Button left = findViewById(R.id.button_left_click);
Button right = findViewById(R.id.button_right_click);
Button middle = findViewById(R.id.button_middle_click);
Button visibility = findViewById(R.id.button_visibility);
LinearLayout overlay = findViewById(R.id.mouse_helper_visibility);
LinearLayout buttons = findViewById(R.id.mouse_helper_secondary_layer);
overlay.setOnTouchListener((v, e) -> true);
overlay.setOnHoverListener((v, e) -> true);
overlay.setOnGenericMotionListener((v, e) -> true);
overlay.setOnCapturedPointerListener((v, e) -> true);
overlay.setVisibility(stylusMenuEnabled ? View.VISIBLE : View.GONE);
View.OnClickListener listener = view -> {
TouchInputHandler.STYLUS_INPUT_HELPER_MODE = (view.equals(left) ? 1 : (view.equals(middle) ? 2 : (view.equals(right) ? 4 : 0)));
left.setAlpha((TouchInputHandler.STYLUS_INPUT_HELPER_MODE == 1) ? menuSelectedTrasparency : menuUnselectedTrasparency);
middle.setAlpha((TouchInputHandler.STYLUS_INPUT_HELPER_MODE == 2) ? menuSelectedTrasparency : menuUnselectedTrasparency);
right.setAlpha((TouchInputHandler.STYLUS_INPUT_HELPER_MODE == 4) ? menuSelectedTrasparency : menuUnselectedTrasparency);
visibility.setAlpha(menuUnselectedTrasparency);
};
left.setOnClickListener(listener);
middle.setOnClickListener(listener);
right.setOnClickListener(listener);
visibility.setOnClickListener(view -> {
if (buttons.getVisibility() == View.VISIBLE) {
buttons.setVisibility(View.GONE);
visibility.setAlpha(menuUnselectedTrasparency);
int m = TouchInputHandler.STYLUS_INPUT_HELPER_MODE;
visibility.setText(m == 1 ? "L" : (m == 2 ? "M" : (m == 3 ? "R" : "U")));
} else {
buttons.setVisibility(View.VISIBLE);
visibility.setAlpha(menuUnselectedTrasparency);
visibility.setText("X");
//Calculate screen border making sure btn is fully inside the view
float maxX = frm.getWidth() - 4 * left.getWidth();
float maxY = frm.getHeight() - 4 * left.getHeight();
//Make sure the Stylus menu is fully inside the screen
overlay.setX(MathUtils.clamp(overlay.getX(), 0, maxX));
overlay.setY(MathUtils.clamp(overlay.getY(), 0, maxY));
int m = TouchInputHandler.STYLUS_INPUT_HELPER_MODE;
listener.onClick(m == 1 ? left : (m == 2 ? middle : (m == 3 ? right : left)));
}
});
//Simulated mouse click 1 = left , 2 = middle , 3 = right
TouchInputHandler.STYLUS_INPUT_HELPER_MODE = 1;
listener.onClick(left);
visibility.setOnLongClickListener(v -> {
v.startDragAndDrop(ClipData.newPlainText("", ""), new View.DragShadowBuilder(visibility) {
public void onDrawShadow(@NonNull Canvas canvas) {}
}, null, View.DRAG_FLAG_GLOBAL);
frm.setOnDragListener((v2, event) -> {
//Calculate screen border making sure btn is fully inside the view
float maxX = frm.getWidth() - visibility.getWidth();
float maxY = frm.getHeight() - visibility.getHeight();
switch (event.getAction()) {
case DragEvent.ACTION_DRAG_LOCATION:
//Center touch location with btn icon
float dX = event.getX() - visibility.getWidth() / 2.0f;
float dY = event.getY() - visibility.getHeight() / 2.0f;
//Make sure the dragged btn is inside the view with clamp
overlay.setX(MathUtils.clamp(dX, 0, maxX));
overlay.setY(MathUtils.clamp(dY, 0, maxY));
break;
case DragEvent.ACTION_DRAG_ENDED:
//Make sure the dragged btn is inside the view
overlay.setX(MathUtils.clamp(overlay.getX(), 0, maxX));
overlay.setY(MathUtils.clamp(overlay.getY(), 0, maxY));
break;
}
return true;
});
return true;
});
}
private void showStylusAuxButtons(boolean show) {
LinearLayout buttons = findViewById(R.id.mouse_helper_visibility);
if (mClientConnected && show) {
buttons.setVisibility(View.VISIBLE);
} else {
//Reset default input back to normal
TouchInputHandler.STYLUS_INPUT_HELPER_MODE = 1;
final float menuUnselectedTrasparency = 0.66f;
final float menuSelectedTrasparency = 1.0f;
findViewById(R.id.button_left_click).setAlpha(menuSelectedTrasparency);
findViewById(R.id.button_right_click).setAlpha(menuUnselectedTrasparency);
findViewById(R.id.button_middle_click).setAlpha(menuUnselectedTrasparency);
findViewById(R.id.button_visibility).setAlpha(menuUnselectedTrasparency);
buttons.setVisibility(View.GONE);
}
}
public void toggleStylusAuxButtons() {
showMouseAuxButtons(findViewById(R.id.mouse_helper_visibility).getVisibility() != View.VISIBLE);
}
private void showMouseAuxButtons(boolean show) {
findViewById(R.id.mouse_buttons)
.setVisibility((mClientConnected && show && "1".equals(prefs.touchMode.get())) ? View.VISIBLE : View.GONE);
}
public void toggleMouseAuxButtons() {
showMouseAuxButtons(findViewById(R.id.mouse_buttons).getVisibility() != View.VISIBLE);
}
void setSize(View v, int width, int height) {
ViewGroup.LayoutParams p = v.getLayoutParams();
p.width = (int) (width * getResources().getDisplayMetrics().density);
p.height = (int) (height * getResources().getDisplayMetrics().density);
v.setLayoutParams(p);
v.setMinimumWidth((int) (width * getResources().getDisplayMetrics().density));
v.setMinimumHeight((int) (height * getResources().getDisplayMetrics().density));
}
@SuppressLint("ClickableViewAccessibility")
void initMouseAuxButtons() {
Button left = findViewById(R.id.mouse_button_left_click);
Button right = findViewById(R.id.mouse_button_right_click);
Button middle = findViewById(R.id.mouse_button_middle_click);
ImageButton pos = findViewById(R.id.mouse_buttons_position);
LinearLayout primaryLayer = findViewById(R.id.mouse_buttons);
LinearLayout secondaryLayer = findViewById(R.id.mouse_buttons_secondary_layer);
boolean mouseHelperEnabled = prefs.showMouseHelper.get() && "1".equals(prefs.touchMode.get());
primaryLayer.setVisibility(mouseHelperEnabled ? View.VISIBLE : View.GONE);
pos.setOnClickListener((v) -> {
if (secondaryLayer.getOrientation() == LinearLayout.HORIZONTAL) {
setSize(left, 48, 96);
setSize(right, 48, 96);
secondaryLayer.setOrientation(LinearLayout.VERTICAL);
} else {
setSize(left, 96, 48);
setSize(right, 96, 48);
secondaryLayer.setOrientation(LinearLayout.HORIZONTAL);
}
handler.postDelayed(() -> {
int[] offset = new int[2];
frm.getLocationInWindow(offset);
primaryLayer.setX(MathUtils.clamp(primaryLayer.getX(), offset[0], offset[0] + frm.getWidth() - primaryLayer.getWidth()));
primaryLayer.setY(MathUtils.clamp(primaryLayer.getY(), offset[1], offset[1] + frm.getHeight() - primaryLayer.getHeight()));
}, 10);
});
Map.of(left, InputStub.BUTTON_LEFT, middle, InputStub.BUTTON_MIDDLE, right, InputStub.BUTTON_RIGHT)
.forEach((v, b) -> v.setOnTouchListener((__, e) -> {
switch(e.getAction()) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_POINTER_DOWN:
getLorieView().sendMouseEvent(0, 0, b, true, true);
v.setPressed(true);
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
getLorieView().sendMouseEvent(0, 0, b, false, true);
v.setPressed(false);
break;
}
return true;
}));
pos.setOnTouchListener(new View.OnTouchListener() {
final int touchSlop = (int) Math.pow(ViewConfiguration.get(MainActivity.this).getScaledTouchSlop(), 2);
final int tapTimeout = ViewConfiguration.getTapTimeout();
final float[] startOffset = new float[2];
final int[] startPosition = new int[2];
long startTime;
@Override
public boolean onTouch(View v, MotionEvent e) {
switch(e.getAction()) {
case MotionEvent.ACTION_DOWN:
primaryLayer.getLocationInWindow(startPosition);
startOffset[0] = e.getX();
startOffset[1] = e.getY();
startTime = SystemClock.uptimeMillis();
pos.setPressed(true);
break;
case MotionEvent.ACTION_MOVE: {
int[] offset = new int[2];
int[] offset2 = new int[2];
primaryLayer.getLocationInWindow(offset);
frm.getLocationInWindow(offset2);
primaryLayer.setX(MathUtils.clamp(offset[0] - startOffset[0] + e.getX(), offset2[0], offset2[0] + frm.getWidth() - primaryLayer.getWidth()));
primaryLayer.setY(MathUtils.clamp(offset[1] - startOffset[1] + e.getY(), offset2[1], offset2[1] + frm.getHeight() - primaryLayer.getHeight()));
break;
}
case MotionEvent.ACTION_UP: {
final int[] _pos = new int[2];
primaryLayer.getLocationInWindow(_pos);
int deltaX = (int) (startOffset[0] - e.getX()) + (startPosition[0] - _pos[0]);
int deltaY = (int) (startOffset[1] - e.getY()) + (startPosition[1] - _pos[1]);
pos.setPressed(false);
if (deltaX * deltaX + deltaY * deltaY < touchSlop && SystemClock.uptimeMillis() - startTime <= tapTimeout) {
v.performClick();
return true;
}
break;
}
}
return true;
}
});
}
void onReceiveConnection(Intent intent) {
Bundle bundle = intent == null ? null : intent.getBundleExtra(null);
IBinder ibinder = bundle == null ? null : bundle.getBinder(null);
if (ibinder == null)
return;
service = ICmdEntryInterface.Stub.asInterface(ibinder);
try {
service.asBinder().linkToDeath(() -> {
service = null;
CmdEntryPoint.requestConnection();
Log.v("Lorie", "Disconnected");
runOnUiThread(() -> clientConnectedStateChanged(false));
}, 0);
} catch (RemoteException ignored) {}
try {
if (service != null && service.asBinder().isBinderAlive()) {
Log.v("LorieBroadcastReceiver", "Extracting logcat fd.");
ParcelFileDescriptor logcatOutput = service.getLogcatOutput();
if (logcatOutput != null)
LorieView.startLogcat(logcatOutput.detachFd());
tryConnect();
if (intent != getIntent())
getIntent().putExtra(null, bundle);
}
} catch (Exception e) {
Log.e("MainActivity", "Something went wrong while we were establishing connection", e);
}
}
void tryConnect() {
if (mClientConnected)
return;
try {
ParcelFileDescriptor fd = service == null ? null : service.getXConnection();
if (fd != null) {
Log.v("MainActivity", "Extracting X connection socket.");
LorieView.connect(fd.detachFd());
getLorieView().triggerCallback();
clientConnectedStateChanged(true);
getLorieView().reloadPreferences(prefs);
} else
handler.postDelayed(this::tryConnect, 500);
} catch (Exception e) {
Log.e("MainActivity", "Something went wrong while we were establishing connection", e);
service = null;
// We should reset the View for the case if we have sent it's surface to the client.
getLorieView().regenerate();
}
}
void onPreferencesChanged(String key) {
if ("additionalKbdVisible".equals(key))
return;
handler.removeCallbacks(this::onPreferencesChangedCallback);
handler.postDelayed(this::onPreferencesChangedCallback, 100);
}
/** @noinspection CommentedOutCode*/
@SuppressLint("UnsafeIntentLaunch")
void onPreferencesChangedCallback() {
prefs.recheckStoringSecondaryDisplayPreferences();
if (oldXrMode != prefs.xrMode.get() && XrActivity.isSupported()) {
getBaseContext().startActivity(new Intent(this, MainActivity.class)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK));
if (oldXrMode) {
// XR process and 2D preferences screen are two different processes.
// To close XR, it is needed to do it using a broadcast.
Intent intent = new Intent(XrActivity.ACTION_STOP_XR);
intent.setPackage(getPackageName());
getBaseContext().sendBroadcast(intent);
}
finish();
return;
}
onWindowFocusChanged(hasWindowFocus());
LorieView lorieView = getLorieView();
mInputHandler.reloadPreferences(prefs);
lorieView.reloadPreferences(prefs);
setTerminalToolbarView();
lorieView.triggerCallback();
filterOutWinKey = prefs.filterOutWinkey.get();
if (prefs.enableAccessibilityServiceAutomatically.get())
KeyInterceptor.launch(this);
else if (checkSelfPermission(WRITE_SECURE_SETTINGS) == PERMISSION_GRANTED)
KeyInterceptor.shutdown(true);
useTermuxEKBarBehaviour = prefs.useTermuxEKBarBehaviour.get();
showIMEWhileExternalConnected = prefs.showIMEWhileExternalConnected.get();
findViewById(R.id.mouse_buttons).setVisibility(prefs.showMouseHelper.get() && "1".equals(prefs.touchMode.get()) && mClientConnected ? View.VISIBLE : View.GONE);
showMouseAuxButtons(prefs.showMouseHelper.get());
showStylusAuxButtons(prefs.showStylusClickOverride.get());
getTerminalToolbarViewPager().setAlpha(((float) prefs.opacityEKBar.get())/100);
lorieView.requestLayout();
lorieView.invalidate();
for (StatusBarNotification notification: mNotificationManager.getActiveNotifications())
if (notification.getId() == mNotificationId) {
mNotification = buildNotification();
mNotificationManager.notify(mNotificationId, mNotification);
}
}
@Override
public void onResume() {
super.onResume();
mNotification = buildNotification();
mNotificationManager.notify(mNotificationId, mNotification);
setTerminalToolbarView();
getLorieView().requestFocus();
}
@Override
public void onPause() {
inputMethodManager.hideSoftInputFromWindow(getWindow().getDecorView().getRootView().getWindowToken(), 0);
for (StatusBarNotification notification: mNotificationManager.getActiveNotifications())
if (notification.getId() == mNotificationId)
mNotificationManager.cancel(mNotificationId);
super.onPause();
}
public LorieView getLorieView() {
return findViewById(R.id.lorieView);
}
public ViewPager getTerminalToolbarViewPager() {
return findViewById(R.id.terminal_toolbar_view_pager);
}
private void setTerminalToolbarView() {
final ViewPager pager = getTerminalToolbarViewPager();
ViewGroup parent = (ViewGroup) pager.getParent();
boolean showNow = mClientConnected && prefs.showAdditionalKbd.get() && prefs.additionalKbdVisible.get();
pager.setVisibility(showNow ? View.VISIBLE : View.INVISIBLE);
if (showNow) {
pager.setAdapter(new X11ToolbarViewPager.PageAdapter(this, (v, k, e) -> mInputHandler.sendKeyEvent(e)));
pager.clearOnPageChangeListeners();
pager.addOnPageChangeListener(new X11ToolbarViewPager.OnPageChangeListener(this, pager));
pager.bringToFront();
} else {
parent.removeView(pager);
parent.addView(pager, 0);
if (mExtraKeys != null)
mExtraKeys.unsetSpecialKeys();
}
ViewGroup.LayoutParams layoutParams = pager.getLayoutParams();
layoutParams.height = Math.round(37.5f * getResources().getDisplayMetrics().density *
(TermuxX11ExtraKeys.getExtraKeysInfo() == null ? 0 : TermuxX11ExtraKeys.getExtraKeysInfo().getMatrix().length));
pager.setLayoutParams(layoutParams);
frm.setPadding(0, 0, 0, prefs.adjustHeightForEK.get() && showNow ? layoutParams.height : 0);
getLorieView().requestFocus();
}
public void toggleExtraKeys(boolean visible, boolean saveState) {
boolean enabled = prefs.showAdditionalKbd.get();
if (enabled && mClientConnected && saveState)
prefs.additionalKbdVisible.put(visible);
setTerminalToolbarView();
}
public void toggleExtraKeys() {
toggleExtraKeys(getTerminalToolbarViewPager().getVisibility() != View.VISIBLE, true);
}
public boolean handleKey(KeyEvent e) {
if (filterOutWinKey && (e.getKeyCode() == KEYCODE_META_LEFT || e.getKeyCode() == KEYCODE_META_RIGHT || e.isMetaPressed()))
return false;
return mLorieKeyListener.onKey(getLorieView(), e.getKeyCode(), e);
}
@SuppressLint("ObsoleteSdkInt")
Notification buildNotification() {
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, getNotificationChannel(mNotificationManager))
.setContentTitle("Termux:X11")
.setSmallIcon(R.drawable.ic_x11_icon)
.setContentText(getResources().getText(R.string.notification_content_text))
.setOngoing(true)
.setPriority(Notification.PRIORITY_MAX)
.setSilent(true)
.setShowWhen(false)
.setColor(0xFF607D8B);
return mInputHandler.setupNotification(prefs, builder).build();
}
private String getNotificationChannel(NotificationManager notificationManager){
String channelId = getResources().getString(R.string.app_name);
String channelName = getResources().getString(R.string.app_name);
NotificationChannel channel = new NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_HIGH);
channel.setImportance(NotificationManager.IMPORTANCE_HIGH);
channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
if (SDK_INT >= VERSION_CODES.Q)
channel.setAllowBubbles(false);
notificationManager.createNotificationChannel(channel);
return channelId;
}
int orientation;
@Override
public void onConfigurationChanged(@NonNull Configuration newConfig) {
super.onConfigurationChanged(newConfig);
if (newConfig.orientation != orientation)
inputMethodManager.hideSoftInputFromWindow(getWindow().getDecorView().getRootView().getWindowToken(), 0);
orientation = newConfig.orientation;
setTerminalToolbarView();
}
@SuppressLint("WrongConstant")
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
KeyInterceptor.recheck();
prefs.recheckStoringSecondaryDisplayPreferences();
Window window = getWindow();
View decorView = window.getDecorView();
boolean fullscreen = prefs.fullscreen.get();
boolean hideCutout = prefs.hideCutout.get();
boolean reseed = prefs.Reseed.get();
if (oldHideCutout != hideCutout || oldFullscreen != fullscreen) {
oldHideCutout = hideCutout;
oldFullscreen = fullscreen;
// For some reason cutout or fullscreen change makes layout calculations wrong and invalid.
// I did not find simple and reliable way to fix it so it is better to start from the beginning.
recreate();
return;
}
int requestedOrientation;
switch (prefs.forceOrientation.get()) {
case "portrait": requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT; break;
case "landscape": requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE; break;
case "reverse portrait": requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT; break;
case "reverse landscape": requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE; break;
default: requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
}
if (getRequestedOrientation() != requestedOrientation)
setRequestedOrientation(requestedOrientation);
if (hasFocus) {
if (SDK_INT >= VERSION_CODES.P) {
if (hideCutout)
getWindow().getAttributes().layoutInDisplayCutoutMode = (SDK_INT >= VERSION_CODES.R) ?
LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS :
LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
else
getWindow().getAttributes().layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT;
}
window.setStatusBarColor(Color.BLACK);
window.setNavigationBarColor(Color.BLACK);
}
window.setFlags(FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS | FLAG_KEEP_SCREEN_ON | FLAG_TRANSLUCENT_STATUS, 0);
if (hasFocus) {
if (fullscreen) {
window.addFlags(FLAG_FULLSCREEN);
decorView.setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
} else {
window.clearFlags(FLAG_FULLSCREEN);
decorView.setSystemUiVisibility(0);
}
}
if (prefs.keepScreenOn.get())
window.addFlags(FLAG_KEEP_SCREEN_ON);
else
window.clearFlags(FLAG_KEEP_SCREEN_ON);
window.setSoftInputMode((reseed ? SOFT_INPUT_ADJUST_RESIZE : SOFT_INPUT_ADJUST_PAN) | SOFT_INPUT_STATE_HIDDEN);
((FrameLayout) findViewById(android.R.id.content)).getChildAt(0).setFitsSystemWindows(!fullscreen);
}
@Override
public void onBackPressed() {
}
public static boolean hasPipPermission(@NonNull Context context) {
AppOpsManager appOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
if (appOpsManager == null)
return false;
else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)
return appOpsManager.unsafeCheckOpNoThrow(AppOpsManager.OPSTR_PICTURE_IN_PICTURE, android.os.Process.myUid(), context.getPackageName()) == AppOpsManager.MODE_ALLOWED;
else
return appOpsManager.checkOpNoThrow(AppOpsManager.OPSTR_PICTURE_IN_PICTURE, android.os.Process.myUid(), context.getPackageName()) == AppOpsManager.MODE_ALLOWED;
}
@Override
public void onUserLeaveHint() {
if (prefs.PIP.get() && hasPipPermission(this)) {
enterPictureInPictureMode();
}
}
@Override
public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode, @NonNull Configuration newConfig) {
if (isInPictureInPictureMode)
toggleExtraKeys(false, false);
else
setTerminalToolbarView();
super.onPictureInPictureModeChanged(isInPictureInPictureMode, newConfig);
}
/** @noinspection NullableProblems*/
@SuppressLint("WrongConstant")
@Override
public WindowInsets onApplyWindowInsets(View v, WindowInsets insets) {
handler.postDelayed(() -> getLorieView().triggerCallback(), 100);
return insets;
}
/**
* Manually toggle soft keyboard visibility
* @param context calling context
*/
public static void toggleKeyboardVisibility(Context context) {
Log.d("MainActivity", "Toggling keyboard visibility");
if(inputMethodManager != null) {
android.util.Log.d("toggleKeyboardVisibility", "externalKeyboardConnected " + externalKeyboardConnected + " showIMEWhileExternalConnected " + showIMEWhileExternalConnected);
if (!externalKeyboardConnected || showIMEWhileExternalConnected)
inputMethodManager.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
else
inputMethodManager.hideSoftInputFromWindow(getInstance().getWindow().getDecorView().getRootView().getWindowToken(), 0);
getInstance().getLorieView().requestFocus();
}
}
@SuppressWarnings("SameParameterValue")
void clientConnectedStateChanged(boolean connected) {
if (connected && XrActivity.isEnabled() && !(this instanceof XrActivity)) {
XrActivity.openIntent(this);
mClientConnected = true;
return;
}
runOnUiThread(()-> {
mClientConnected = connected;
setTerminalToolbarView();
findViewById(R.id.mouse_buttons).setVisibility(prefs.showMouseHelper.get() && "1".equals(prefs.touchMode.get()) && mClientConnected ? View.VISIBLE : View.GONE);
findViewById(R.id.stub).setVisibility(connected?View.INVISIBLE:View.VISIBLE);
getLorieView().setVisibility(connected?View.VISIBLE:View.INVISIBLE);
getLorieView().regenerate();
// We should recover connection in the case if file descriptor for some reason was broken...
if (!connected)
tryConnect();
if (connected)
getLorieView().setPointerIcon(PointerIcon.getSystemIcon(this, PointerIcon.TYPE_NULL));
});
}
public static boolean isConnected() {
if (getInstance() == null)
return false;
return getInstance().mClientConnected;
}
private void checkXEvents() {
getLorieView().handleXEvents();
// an imperfect workaround for Gboard CJK keyboard in DeX soft keyboard mode
// in that particular mode during language switching, InputConnection#requestCursorUpdates() is not called and no signal can be picked up.
// therefore, check to activate CJK keyboard is done upon a keypress.
if (getLorieView().enableGboardCJK && SamsungDexUtils.checkDeXEnabled(this))
getLorieView().checkRestartInput(false);
handler.postDelayed(this::checkXEvents, 300);
}
public static void getRealMetrics(DisplayMetrics m) {
if (getInstance() != null &&
getInstance().getLorieView() != null &&
getInstance().getLorieView().getDisplay() != null)
getInstance().getLorieView().getDisplay().getRealMetrics(m);
}
public static void setCapturingEnabled(boolean enabled) {
if (getInstance() == null || getInstance().mInputHandler == null)
return;
getInstance().mInputHandler.setCapturingEnabled(enabled);
}
public boolean shouldInterceptKeys() {
View textInput = findViewById(R.id.terminal_toolbar_text_input);
if (mInputHandler == null || !hasWindowFocus() || (textInput != null && textInput.isFocused()))
return false;
return mInputHandler.shouldInterceptKeys();
}
public void setExternalKeyboardConnected(boolean connected) {
externalKeyboardConnected = connected;
EditText textInput = findViewById(R.id.terminal_toolbar_text_input);
if (textInput != null)
textInput.setShowSoftInputOnFocus(!connected || showIMEWhileExternalConnected);
if (connected && !showIMEWhileExternalConnected)
inputMethodManager.hideSoftInputFromWindow(getWindow().getDecorView().getRootView().getWindowToken(), 0);
getLorieView().requestFocus();
}
}

View File

@@ -0,0 +1,386 @@
package com.termux.x11;
import android.app.Activity;
import android.app.ActivityOptions;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Rect;
import android.graphics.SurfaceTexture;
import android.opengl.GLES11Ext;
import android.opengl.GLSurfaceView;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.RemoteException;
import android.util.Log;
import android.view.Display;
import android.view.KeyEvent;
import android.view.Surface;
import android.view.inputmethod.InputMethodManager;
import com.termux.x11.input.InputStub;
import com.termux.x11.utils.GLUtility;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
public class XrActivity extends MainActivity implements GLSurfaceView.Renderer {
// Order of the enum has to be the same as in xrio/android.c
public enum ControllerAxis {
L_PITCH, L_YAW, L_ROLL, L_THUMBSTICK_X, L_THUMBSTICK_Y, L_X, L_Y, L_Z,
R_PITCH, R_YAW, R_ROLL, R_THUMBSTICK_X, R_THUMBSTICK_Y, R_X, R_Y, R_Z,
HMD_PITCH, HMD_YAW, HMD_ROLL, HMD_X, HMD_Y, HMD_Z, HMD_IPD
}
// Order of the enum has to be the same as in xrio/android.c
public enum ControllerButton {
L_GRIP, L_MENU, L_THUMBSTICK_PRESS, L_THUMBSTICK_LEFT, L_THUMBSTICK_RIGHT, L_THUMBSTICK_UP, L_THUMBSTICK_DOWN, L_TRIGGER, L_X, L_Y,
R_A, R_B, R_GRIP, R_THUMBSTICK_PRESS, R_THUMBSTICK_LEFT, R_THUMBSTICK_RIGHT, R_THUMBSTICK_UP, R_THUMBSTICK_DOWN, R_TRIGGER,
}
// Order of the enum has to be the same as in xrio/android.c
public enum RenderParam {
CANVAS_DISTANCE, IMMERSIVE, PASSTHROUGH, SBS, VIEWPORT_WIDTH, VIEWPORT_HEIGHT,
}
public static final String ACTION_STOP_XR = "com.termux.x11.CmdEntryPoint.ACTION_STOP_XR";
private static boolean isDeviceDetectionFinished = false;
private static boolean isDeviceSupported = false;
private boolean isImmersive = false;
private boolean isSBS = false;
private boolean keyboardDisabled;
private long lastEnter;
private final float[] lastAxes = new float[ControllerAxis.values().length];
private final boolean[] lastButtons = new boolean[ControllerButton.values().length];
private final float[] mouse = new float[2];
private int program;
private int texture;
private SurfaceTexture surface;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
GLSurfaceView view = new GLSurfaceView(this);
view.setEGLContextClientVersion(2);
view.setRenderer(this);
frm.addView(view);
registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (ACTION_STOP_XR.equals(intent.getAction())) {
teardown();
System.exit(0);
}
}
}, new IntentFilter(ACTION_STOP_XR) {}, 0);
}
@Override
public void onDestroy() {
super.onDestroy();
teardown();
// Going back to the Android 2D rendering isn't supported.
// Kill the app to ensure there is no unexpected behaviour.
System.exit(0);
}
public static boolean isEnabled() {
return prefs.xrMode.get() && isSupported();
}
public static boolean isSupported() {
if (!isDeviceDetectionFinished) {
if (Build.MANUFACTURER.compareToIgnoreCase("META") == 0) {
isDeviceSupported = true;
}
if (Build.MANUFACTURER.compareToIgnoreCase("OCULUS") == 0) {
isDeviceSupported = true;
}
isDeviceDetectionFinished = true;
}
return isDeviceSupported;
}
public static void openIntent(Activity context) {
// 0. Create the launch intent
Intent intent = new Intent(context, XrActivity.class);
// 1. Locate the main display ID and add that to the intent
final int mainDisplayId = Display.DEFAULT_DISPLAY;
ActivityOptions options = ActivityOptions.makeBasic().setLaunchDisplayId(mainDisplayId);
// 2. Set the flags: start in a new task
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
// 3. Launch the activity.
// Don't use the container's ContextWrapper, which is adding arguments
context.getBaseContext().startActivity(intent, options.toBundle());
// 4. Finish the previous activity: this avoids an audio bug
context.finish();
}
@Override
void clientConnectedStateChanged(boolean connected) {
if (!connected && (surface != null)) {
teardown();
// Going back to the Android 2D rendering isn't supported.
// Kill the app to ensure there is no unexpected behaviour.
System.exit(0);
} else {
super.clientConnectedStateChanged(connected);
}
}
@Override
public void onSurfaceCreated(GL10 gl10, EGLConfig eglConfig) {
System.loadLibrary("XRio");
if (isSupported()) {
init();
}
}
@Override
public void onSurfaceChanged(GL10 gl10, int w, int h) {
texture = GLUtility.createTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES);
program = GLUtility.createProgram(true);
surface = new SurfaceTexture(texture);
runOnUiThread(() -> getLorieView().setCallback((sfc, surfaceWidth, surfaceHeight, screenWidth, screenHeight) -> {
LorieView.sendWindowChange(screenWidth, screenHeight, 60);
surface.setDefaultBufferSize(screenWidth, screenHeight);
if (service != null) {
try {
service.windowChanged(new Surface(surface), "OpenXR");
} catch (RemoteException e) {
Log.e("XrActivity", "failed to send windowChanged request", e);
}
}
}));
}
@Override
public void onDrawFrame(GL10 gl10) {
if (isSupported()) {
setRenderParam(RenderParam.CANVAS_DISTANCE.ordinal(), 5);
setRenderParam(RenderParam.IMMERSIVE.ordinal(), isImmersive ? 1 : 0);
setRenderParam(RenderParam.PASSTHROUGH.ordinal(), isImmersive ? 0 : 1);
setRenderParam(RenderParam.SBS.ordinal(), isSBS ? 1 : 0);
if (beginFrame()) {
renderFrame(gl10);
finishFrame();
processInput();
}
} else {
renderFrame(gl10);
}
}
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (hasFocus) {
keyboardDisabled = true;
new Handler().postDelayed(() -> keyboardDisabled = false, 250);
}
}
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
// Ignore event madness when disabling software keyboard
if (keyboardDisabled) {
return true;
}
// Bluetooth/OTG keyboards work properly with the standard flow
if (hasWindowFocus()) {
return super.dispatchKeyEvent(event);
}
// Meta HorizonOS sends up event only (as for in v66)
if (event.getAction() == KeyEvent.ACTION_UP) {
// The OS sends 4x enter event, filter it
if (event.getKeyCode() == KeyEvent.KEYCODE_ENTER) {
if (event.getDownTime() - lastEnter < 250) {
return true;
}
lastEnter = event.getDownTime();
}
// Send key press, give system chance to notice it and send key release
getLorieView().sendKeyEvent(0, event.getKeyCode(), true);
try {
Thread.sleep(50);
} catch (Exception e) {
e.printStackTrace();
}
getLorieView().sendKeyEvent(0, event.getKeyCode(), false);
}
return true;
}
private void processInput() {
float[] axes = getAxes();
boolean[] buttons = getButtons();
LorieView view = getLorieView();
Rect frame = view.getHolder().getSurfaceFrame();
// Mouse control with hand
float meter2px = frame.width() * 10.0f;
float dx = (axes[ControllerAxis.R_X.ordinal()] - lastAxes[ControllerAxis.R_X.ordinal()]) * meter2px;
float dy = (axes[ControllerAxis.R_Y.ordinal()] - lastAxes[ControllerAxis.R_Y.ordinal()]) * meter2px;
// Mouse control with head
if (isImmersive) {
float angle2px = frame.width() * 0.05f;
dx = getAngleDiff(lastAxes[ControllerAxis.HMD_YAW.ordinal()], axes[ControllerAxis.HMD_YAW.ordinal()]) * angle2px;
dy = getAngleDiff(lastAxes[ControllerAxis.HMD_PITCH.ordinal()], axes[ControllerAxis.HMD_PITCH.ordinal()]) * angle2px;
if (Float.isNaN(dy)) {
dy = 0;
}
}
// Mouse speed adjust
float mouseSpeed = isImmersive ? 1 : 0.25f;
dx *= mouseSpeed;
dy *= mouseSpeed;
// Mouse "snap turn"
int snapturn = 125;
if (getButtonClicked(buttons, ControllerButton.R_THUMBSTICK_LEFT)) {
dx = -snapturn;
}
if (getButtonClicked(buttons, ControllerButton.R_THUMBSTICK_RIGHT)) {
dx = snapturn;
}
// Mouse smoothing
if (isImmersive) {
mouse[0] = dx;
mouse[1] = dy;
} else {
float smoothFactor = 0.75f;
mouse[0] = mouse[0] * smoothFactor + dx * (1 - smoothFactor);
mouse[1] = mouse[1] * smoothFactor + dy * (1 - smoothFactor);
}
// Set mouse status
int scrollStep = 150;
view.sendMouseEvent(mouse[0], -mouse[1], 0, false, true);
mapMouse(view, buttons, ControllerButton.R_TRIGGER, InputStub.BUTTON_LEFT);
mapMouse(view, buttons, ControllerButton.R_GRIP, InputStub.BUTTON_RIGHT);
mapScroll(view, buttons, ControllerButton.R_THUMBSTICK_UP, 0, -scrollStep);
mapScroll(view, buttons, ControllerButton.R_THUMBSTICK_DOWN, 0, scrollStep);
// Switch immersive/SBS mode
if (getButtonClicked(buttons, ControllerButton.L_THUMBSTICK_PRESS)) {
if (buttons[ControllerButton.R_GRIP.ordinal()]) {
isSBS = !isSBS;
}
else {
isImmersive = !isImmersive;
}
}
// Show system keyboard
if (getButtonClicked(buttons, ControllerButton.R_THUMBSTICK_PRESS)) {
getInstance().runOnUiThread(() -> {
isSBS = false;
isImmersive = false;
getWindow().getDecorView().postDelayed(() -> {
InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
}, 500L);
});
}
// Update keyboard
mapKey(view, buttons, ControllerButton.R_A, KeyEvent.KEYCODE_A);
mapKey(view, buttons, ControllerButton.R_B, KeyEvent.KEYCODE_B);
mapKey(view, buttons, ControllerButton.L_X, KeyEvent.KEYCODE_X);
mapKey(view, buttons, ControllerButton.L_Y, KeyEvent.KEYCODE_Y);
mapKey(view, buttons, ControllerButton.L_GRIP, KeyEvent.KEYCODE_SPACE);
mapKey(view, buttons, ControllerButton.L_MENU, KeyEvent.KEYCODE_BACK);
mapKey(view, buttons, ControllerButton.L_TRIGGER, KeyEvent.KEYCODE_ENTER);
mapKey(view, buttons, ControllerButton.L_THUMBSTICK_LEFT, KeyEvent.KEYCODE_DPAD_LEFT);
mapKey(view, buttons, ControllerButton.L_THUMBSTICK_RIGHT, KeyEvent.KEYCODE_DPAD_RIGHT);
mapKey(view, buttons, ControllerButton.L_THUMBSTICK_UP, KeyEvent.KEYCODE_DPAD_UP);
mapKey(view, buttons, ControllerButton.L_THUMBSTICK_DOWN, KeyEvent.KEYCODE_DPAD_DOWN);
// Store the OpenXR data
System.arraycopy(axes, 0, lastAxes, 0, axes.length);
System.arraycopy(buttons, 0, lastButtons, 0, buttons.length);
}
private float getAngleDiff(float oldAngle, float newAngle) {
float diff = oldAngle - newAngle;
while (diff > 180) {
diff -= 360;
}
while (diff < -180) {
diff += 360;
}
return diff;
}
private boolean getButtonClicked(boolean[] buttons, ControllerButton button) {
return buttons[button.ordinal()] && !lastButtons[button.ordinal()];
}
private void mapKey(LorieView v, boolean[] buttons, ControllerButton b, int keycode) {
if (buttons[b.ordinal()] != lastButtons[b.ordinal()]) {
v.sendKeyEvent(0, keycode, buttons[b.ordinal()]);
}
}
private void mapMouse(LorieView v, boolean[] buttons, ControllerButton b, int button) {
if (buttons[b.ordinal()] != lastButtons[b.ordinal()]) {
v.sendMouseEvent(0, 0, button, buttons[b.ordinal()], true);
}
}
private void mapScroll(LorieView v, boolean[] buttons, ControllerButton b, float x, float y) {
if (getButtonClicked(buttons, b)) {
v.sendMouseWheelEvent(x, y);
}
}
private void renderFrame(GL10 gl10) {
if (isSupported()) {
int w = getRenderParam(RenderParam.VIEWPORT_WIDTH.ordinal());
int h = getRenderParam(RenderParam.VIEWPORT_HEIGHT.ordinal());
gl10.glViewport(0, 0, w, h);
}
surface.updateTexImage();
float aspect = 1;
if (isSupported()) {
LorieView view = getLorieView();
int w = view.getWidth();
int h = view.getHeight();
aspect = Math.min(w, h) / (float)Math.max(w, h);
}
GLUtility.drawTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, program, texture, -aspect);
}
private native void init();
private native void teardown();
private native boolean beginFrame();
private native void finishFrame();
private native float[] getAxes();
private native boolean[] getButtons();
private native int getRenderParam(int param);
private native void setRenderParam(int param, int value);
}

View File

@@ -0,0 +1,237 @@
// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package com.termux.x11.input;
import static android.view.KeyEvent.*;
import static android.view.MotionEvent.*;
import static androidx.core.math.MathUtils.clamp;
import static com.termux.x11.input.InputStub.*;
import static java.nio.charset.StandardCharsets.UTF_8;
import android.graphics.PointF;
import android.view.KeyEvent;
import android.view.MotionEvent;
import com.termux.x11.MainActivity;
import java.util.List;
import java.util.TreeSet;
/**
* A set of functions to send users' activities, which are represented by Android classes, to
* remote host machine. This class uses a {@link InputStub} to do the real injections.
*/
public final class InputEventSender {
private static final int XI_TouchBegin = 18;
private static final int XI_TouchUpdate = 19;
private static final int XI_TouchEnd = 20;
private final InputStub mInjector;
public boolean tapToMove = false;
public boolean preferScancodes = false;
public boolean pointerCapture = false;
public boolean scaleTouchpad = false;
public float capturedPointerSpeedFactor = 100;
public boolean dexMetaKeyCapture = false;
public boolean pauseKeyInterceptingWithEsc = false;
public boolean stylusIsMouse = false;
public boolean stylusButtonContactModifierMode = false;
/** Set of pressed keys for which we've sent TextEvent. */
private final TreeSet<Integer> mPressedTextKeys;
private final TreeSet<Integer> mPressedKeys;
public InputEventSender(InputStub injector) {
if (injector == null)
throw new NullPointerException();
mInjector = injector;
mPressedTextKeys = new TreeSet<>();
mPressedKeys = new TreeSet<>();
}
private static final List<Integer> buttons = List.of(BUTTON_UNDEFINED, BUTTON_LEFT, BUTTON_MIDDLE, BUTTON_RIGHT);
public void sendMouseEvent(PointF pos, int button, boolean down, boolean relative) {
if (!buttons.contains(button))
return;
mInjector.sendMouseEvent(pos != null ? (int) pos.x : 0, pos != null ? (int) pos.y : 0, button, down, relative);
}
public void sendStylusEvent(float x, float y, int pressure, int tiltX, int tiltY, int orientation, int buttons, boolean eraser, boolean mouse) {
mInjector.sendStylusEvent(x, y, pressure, tiltX, tiltY, orientation, buttons, eraser, mouse);
android.util.Log.d("STYLUS_EVENT", "transformed x " + x + " y " + y + " pressure " + pressure + " tiltX " + tiltX + " tiltY " + tiltY + " orientation " + orientation + " buttons " + buttons + " eraser " + eraser + " mouseMode " + mouse);
}
public void sendMouseDown(int button, boolean relative) {
if (!buttons.contains(button))
return;
mInjector.sendMouseEvent(0, 0, button, true, relative);
}
public void sendMouseUp(int button, boolean relative) {
if (!buttons.contains(button))
return;
mInjector.sendMouseEvent(0, 0, button, false, relative);
}
public void sendMouseClick(int button, boolean relative) {
if (!buttons.contains(button))
return;
mInjector.sendMouseEvent(0, 0, button, true, relative);
mInjector.sendMouseEvent(0, 0, button, false, relative);
}
public void sendCursorMove(float x, float y, boolean relative) {
mInjector.sendMouseEvent(x, y, BUTTON_UNDEFINED, false, relative);
}
public void sendMouseWheelEvent(float distanceX, float distanceY) {
mInjector.sendMouseWheelEvent(distanceX, distanceY);
}
final boolean[] pointers = new boolean[10];
/**
* Extracts the touch point data from a MotionEvent, converts each point into a marshallable
* object and passes the set of points to the JNI layer to be transmitted to the remote host.
*
* @param event The event to send to the remote host for injection. NOTE: This object must be
* updated to represent the remote machine's coordinate system before calling this
* function.
*/
public void sendTouchEvent(MotionEvent event, RenderData renderData) {
int action = event.getActionMasked();
if (action == ACTION_MOVE || action == ACTION_HOVER_MOVE || action == ACTION_HOVER_ENTER || action == ACTION_HOVER_EXIT) {
// In order to process all of the events associated with an ACTION_MOVE event, we need
// to walk the list of historical events in order and add each event to our list, then
// retrieve the current move event data.
int pointerCount = event.getPointerCount();
for (int p = 0; p < pointerCount; p++)
pointers[event.getPointerId(p)] = false;
for (int p = 0; p < pointerCount; p++) {
int x = clamp((int) (event.getX(p) * renderData.scale.x), 0, renderData.screenWidth);
int y = clamp((int) (event.getY(p) * renderData.scale.y), 0, renderData.screenHeight);
pointers[event.getPointerId(p)] = true;
mInjector.sendTouchEvent(XI_TouchUpdate, event.getPointerId(p), x, y);
}
// Sometimes Android does not send ACTION_POINTER_UP/ACTION_UP so some pointers are "stuck" in pressed state.
for (int p = 0; p < 10; p++) {
if (!pointers[p])
mInjector.sendTouchEvent(XI_TouchEnd, p, 0, 0);
}
} else {
// For all other events, we only want to grab the current/active pointer. The event
// contains a list of every active pointer but passing all of of these to the host can
// cause confusion on the remote OS side and result in broken touch gestures.
int activePointerIndex = event.getActionIndex();
int id = event.getPointerId(activePointerIndex);
int x = clamp((int) (event.getX(activePointerIndex) * renderData.scale.x), 0, renderData.screenWidth);
int y = clamp((int) (event.getY(activePointerIndex) * renderData.scale.y), 0, renderData.screenHeight);
int a = (action == MotionEvent.ACTION_DOWN || action == ACTION_POINTER_DOWN) ? XI_TouchBegin : XI_TouchEnd;
if (a == XI_TouchEnd)
mInjector.sendTouchEvent(XI_TouchUpdate, id, x, y);
mInjector.sendTouchEvent(a, id, x, y);
}
}
/**
* Converts the {@link KeyEvent} into low-level events and sends them to the host as either
* key-events or text-events. This contains some logic for handling some special keys, and
* avoids sending a key-up event for a key that was previously injected as a text-event.
*/
public boolean sendKeyEvent(KeyEvent e) {
int keyCode = e.getKeyCode();
boolean pressed = e.getAction() == KeyEvent.ACTION_DOWN;
if ((e.getFlags() & KeyEvent.FLAG_CANCELED) == KeyEvent.FLAG_CANCELED) {
android.util.Log.d("KeyEvent", "We've got key event with FLAG_CANCELED, it will not be consumed. Details: " + e);
return true;
}
// Events received from software keyboards generate TextEvent in two
// cases:
// 1. This is an ACTION_MULTIPLE event.
// 2. Ctrl, Alt and Meta are not pressed.
// This ensures that on-screen keyboard always injects input that
// correspond to what user sees on the screen, while physical keyboard
// acts as if it is connected to the remote host.
if (e.getAction() == ACTION_MULTIPLE) {
if (e.getCharacters() != null)
mInjector.sendTextEvent(e.getCharacters().getBytes(UTF_8));
else if (e.getUnicodeChar() != 0)
mInjector.sendTextEvent(String.valueOf((char)e.getUnicodeChar()).getBytes(UTF_8));
return true;
}
boolean no_modifiers = (!e.isAltPressed() && !e.isCtrlPressed() && !e.isMetaPressed())
|| ((e.getMetaState() & META_ALT_RIGHT_ON) != 0 && (e.getCharacters() != null || e.getUnicodeChar() != 0)); // For layouts with AltGr
// For Enter getUnicodeChar() returns 10 (line feed), but we still
// want to send it as KeyEvent.
char unicode = keyCode != KEYCODE_ENTER ? (char) e.getUnicodeChar() : 0;
int scancode = (preferScancodes || !no_modifiers) ? e.getScanCode(): 0;
if (!preferScancodes) {
if (pressed && unicode != 0 && no_modifiers) {
mPressedTextKeys.add(keyCode);
if ((e.getMetaState() & META_ALT_RIGHT_ON) != 0)
mInjector.sendKeyEvent(0, KEYCODE_ALT_RIGHT, false); // For layouts with AltGr
mInjector.sendTextEvent(String.valueOf(unicode).getBytes(UTF_8));
if ((e.getMetaState() & META_ALT_RIGHT_ON) != 0)
mInjector.sendKeyEvent(0, KEYCODE_ALT_RIGHT, true); // For layouts with AltGr
return true;
}
if (!pressed && mPressedTextKeys.contains(keyCode)) {
mPressedTextKeys.remove(keyCode);
return true;
}
}
// KEYCODE_AT, KEYCODE_POUND, KEYCODE_STAR and KEYCODE_PLUS are
// deprecated, but they still need to be here for older devices and
// third-party keyboards that may still generate these events. See
// https://source.android.com/devices/input/keyboard-devices.html#legacy-unsupported-keys
char[][] chars = {
{ KEYCODE_AT, '@', KEYCODE_2 },
{ KEYCODE_POUND, '#', KEYCODE_3 },
{ KEYCODE_STAR, '*', KEYCODE_8 },
{ KEYCODE_PLUS, '+', KEYCODE_EQUALS }
};
for (char[] i: chars) {
if (e.getKeyCode() != i[0])
continue;
if ((e.getCharacters() != null && String.valueOf(i[1]).contentEquals(e.getCharacters()))
|| e.getUnicodeChar() == i[1]) {
mInjector.sendKeyEvent(0, KEYCODE_SHIFT_LEFT, pressed);
mInjector.sendKeyEvent(0, i[2], pressed);
return true;
}
}
// Ignoring Android's autorepeat.
// But some weird IMEs (or firmwares) send first event with repeatCount=1 (not 0)
// Probably related to preceding event with FLAG_CANCELLED flag
if (e.getRepeatCount() > 0 && mPressedKeys.contains(keyCode))
return true;
if (pressed)
mPressedKeys.add(keyCode);
else
mPressedKeys.remove(keyCode);
if (keyCode == KEYCODE_ESCAPE && !pressed && e.hasNoModifiers())
MainActivity.setCapturingEnabled(false);
// We try to send all other key codes to the host directly.
return mInjector.sendKeyEvent(scancode, keyCode, pressed);
}
}

View File

@@ -0,0 +1,235 @@
// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package com.termux.x11.input;
import android.content.Context;
import android.graphics.PointF;
import android.os.SystemClock;
import android.view.MotionEvent;
import android.view.ViewConfiguration;
/**
* This interface defines the methods used to customize input handling for
* a particular strategy. The implementing class is responsible for sending
* remote input events and defining implementation specific behavior.
*/
public interface InputStrategyInterface {
/**
* Called when a user tap has been detected.
*
* @param button The button value for the tap event.
*/
void onTap(int button);
/**
* Called when the user has put one or more fingers down on the screen for a period of time.
*
* @param button The button value for the tap event.
* @return A boolean representing whether the event was handled.
*/
boolean onPressAndHold(int button, boolean force);
/**
* Called when a MotionEvent is received. This method allows the input strategy to store or
* react to specific MotionEvents as needed.
*
* @param event The original event for the current touch motion.
*/
void onMotionEvent(MotionEvent event);
/**
* Called when the user is attempting to scroll/pan the remote UI.
*
* @param distanceX The distance moved along the x-axis.
* @param distanceY The distance moved along the y-axis.
*/
void onScroll(float distanceX, float distanceY);
class NullInputStrategy implements InputStrategyInterface {
@Override public void onTap(int button) {}
@Override public boolean onPressAndHold(int button, boolean force) { return false; }
@Override public void onScroll(float distanceX, float distanceY) {}
@Override public void onMotionEvent(MotionEvent event) {}
}
/**
* This class receives local touch events and translates them into the appropriate mouse based
* events for the remote host. The net result is that the local input method feels like a touch
* interface but the remote host will be given mouse events to inject.
*/
class SimulatedTouchInputStrategy implements InputStrategyInterface {
/** Used to adjust the size of the region used for double tap detection. */
private static final float DOUBLE_TAP_SLOP_SCALE_FACTOR = 0.25f;
private final RenderData mRenderData;
private final InputEventSender mInjector;
/**
* Stores the time of the most recent left button single tap processed.
*/
private long mLastTapTimeInMs;
/**
* Stores the position of the last left button single tap processed.
*/
private PointF mLastTapPoint;
/**
* The maximum distance, in pixels, between two points in order for them to be considered a
* double tap gesture.
*/
private final int mDoubleTapSlopSquareInPx;
/**
* The interval, measured in milliseconds, in which two consecutive left button taps must
* occur in order to be considered a double tap gesture.
*/
private final long mDoubleTapDurationInMs;
/** Mouse-button currently held down, or BUTTON_UNDEFINED otherwise. */
private int mHeldButton = InputStub.BUTTON_UNDEFINED;
public SimulatedTouchInputStrategy(
RenderData renderData, InputEventSender injector, Context context) {
if (injector == null)
throw new NullPointerException();
mRenderData = renderData;
mInjector = injector;
mDoubleTapDurationInMs = ViewConfiguration.getDoubleTapTimeout();
// In order to detect whether the user is attempting to double tap a target, we define a
// region around the first point within which the second tap must occur. The standard way
// to do this in an Android UI (meaning a UI comprised of UI elements which conform to the
// visual guidelines for the platform which are 'Touch Friendly') is to use the
// getScaledDoubleTapSlop() value for checking this distance (or use a GestureDetector).
// Our scenario is a bit different as our UI consists of an image of a remote machine where
// the UI elements were probably designed for mouse and keyboard (meaning smaller targets)
// and the image itself which can be zoomed to change the size of the targets. Ths adds up
// to the target to be invoked often being either larger or much smaller than a standard
// Android UI element. Our approach to this problem is to make double-tap detection
// consistent regardless of the zoom level or remote target size so that the user can rely
// on their muscle memory when interacting with our UI. With respect to the original
// problem, getScaledDoubleTapSlop() gives a value which is optimized for an Android based
// UI however this value is too large for interacting with remote elements in our app.
// Our solution is to use the original value from getScaledDoubleTapSlop() (which includes
// scaling to account for display differences between devices) and apply a fudge/scale
// factor to make the interaction more intuitive and useful for our scenario.
ViewConfiguration config = ViewConfiguration.get(context);
int scaledDoubleTapSlopInPx = config.getScaledDoubleTapSlop();
scaledDoubleTapSlopInPx = (int) (scaledDoubleTapSlopInPx * DOUBLE_TAP_SLOP_SCALE_FACTOR);
mDoubleTapSlopSquareInPx = scaledDoubleTapSlopInPx * scaledDoubleTapSlopInPx;
}
@Override
public void onTap(int button) {
PointF currentTapPoint = mRenderData.getCursorPosition();
if (button == InputStub.BUTTON_LEFT) {
// Left clicks are handled a little differently than the events for other buttons.
// This is needed because translating touch events to mouse events has a problem with
// location consistency for double clicks. If you take the center location of each tap
// and inject them as mouse clicks, the distance between those two points will often
// cause the remote OS to recognize the gesture as two distinct clicks instead of a
// double click. In order to increase the success rate of double taps/clicks, we
// squirrel away the time and coordinates of each single tap and if we detect the user
// attempting a double tap, we use the original event's location for that second tap.
long tapInterval = SystemClock.uptimeMillis() - mLastTapTimeInMs;
if (isDoubleTap(currentTapPoint.x, currentTapPoint.y, tapInterval)) {
mLastTapPoint = null;
mLastTapTimeInMs = 0;
} else {
mLastTapPoint = currentTapPoint;
mLastTapTimeInMs = SystemClock.uptimeMillis();
}
} else {
mLastTapPoint = null;
mLastTapTimeInMs = 0;
}
mInjector.sendMouseClick(button, false);
}
@Override
public boolean onPressAndHold(int button, boolean force) {
mInjector.sendMouseDown(button, false);
mHeldButton = button;
return true;
}
@Override
public void onScroll(float distanceX, float distanceY) {
mInjector.sendMouseWheelEvent(distanceX, distanceY);
}
@Override
public void onMotionEvent(MotionEvent event) {
if (event.getActionMasked() == MotionEvent.ACTION_UP && mHeldButton != InputStub.BUTTON_UNDEFINED) {
mInjector.sendMouseUp(mHeldButton, false);
mHeldButton = InputStub.BUTTON_UNDEFINED;
}
}
private boolean isDoubleTap(float currentX, float currentY, long tapInterval) {
if (tapInterval > mDoubleTapDurationInMs || mLastTapPoint == null) {
return false;
}
// Convert the image based coordinates back to screen coordinates so the user experiences
// consistent double tap behavior regardless of zoom level.
//
float[] currentValues = {currentX * mRenderData.scale.x, currentY * mRenderData.scale.y};
float[] previousValues = {mLastTapPoint.x * mRenderData.scale.x, mLastTapPoint.y * mRenderData.scale.y};
int deltaX = (int) (currentValues[0] - previousValues[0]);
int deltaY = (int) (currentValues[1] - previousValues[1]);
return ((deltaX * deltaX + deltaY * deltaY) <= mDoubleTapSlopSquareInPx);
}
}
/**
* Defines a set of behavior and methods to simulate trackpad behavior when responding to
* local input event data. This class is also responsible for forwarding input event data
* to the remote host for injection there.
*/
class TrackpadInputStrategy implements InputStrategyInterface {
private final InputEventSender mInjector;
/** Mouse-button currently held down, or BUTTON_UNDEFINED otherwise. */
private int mHeldButton = InputStub.BUTTON_UNDEFINED;
public TrackpadInputStrategy(InputEventSender injector) {
if ((mInjector = injector) == null)
throw new NullPointerException();
}
@Override
public void onTap(int button) {
mInjector.sendMouseClick(button, true);
}
@Override
public boolean onPressAndHold(int button, boolean force) {
if (mInjector.tapToMove && !force)
return false;
mInjector.sendMouseDown(button, true);
mHeldButton = button;
return true;
}
@Override
public void onScroll(float distanceX, float distanceY) {
mInjector.sendMouseWheelEvent(distanceX, distanceY);
}
@Override
public void onMotionEvent(MotionEvent event) {
if (event.getActionMasked() == MotionEvent.ACTION_UP && mHeldButton != InputStub.BUTTON_UNDEFINED) {
mInjector.sendMouseUp(mHeldButton, true);
mHeldButton = InputStub.BUTTON_UNDEFINED;
}
}
}
}

View File

@@ -0,0 +1,45 @@
// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package com.termux.x11.input;
/**
* A set of functions to send client users' activities to remote host machine. This interface
* represents low level functions without relationships with Android system. Consumers can use
* {@link InputEventSender} to avoid conversions between Android classes and JNI types. The
* implementations of this interface are not required to be thread-safe. All these functions should
* be called from Android UI thread.
*/
public interface InputStub {
// These constants must match those in the generated struct protocol::MouseEvent_MouseButton.
int BUTTON_UNDEFINED = 0;
int BUTTON_LEFT = 1;
int BUTTON_MIDDLE = 2;
int BUTTON_RIGHT = 3;
int BUTTON_SCROLL = 4;
/** Sends a mouse event. */
void sendMouseEvent(float x, float y, int whichButton, boolean buttonDown, boolean relative);
/** Sends a mouse wheel event. */
void sendMouseWheelEvent(float deltaX, float deltaY);
/**
* Sends a key event, and returns false if both scanCode and keyCode are not able to be
* converted to a known usb key code. Nothing will be sent to remote host, if this function
* returns false.
*/
boolean sendKeyEvent(int scanCode, int keyCode, boolean keyDown);
/**
* Sends a string literal. This function is useful to handle outputs from Android input
* methods.
*/
void sendTextEvent(byte[] utf8Bytes);
/** Sends an event, not flushing connection. */
void sendTouchEvent(int action, int pointerId, int x, int y);
void sendStylusEvent(float x, float y, int pressure, int tiltX, int tiltY, int orientation, int buttons, boolean eraser, boolean mouseMode);
}

View File

@@ -0,0 +1,56 @@
// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package com.termux.x11.input;
import android.graphics.Matrix;
import android.graphics.PointF;
/**
* This class stores UI configuration that will be used when rendering the remote desktop.
*/
public class RenderData {
public PointF scale = new PointF();
public int screenWidth;
public int screenHeight;
public int imageWidth;
public int imageHeight;
/**
* Specifies the position, in image coordinates, at which the cursor image will be drawn.
* This will normally be at the location of the most recently injected motion event.
*/
private final PointF mCursorPosition = new PointF();
/**
* Returns the position of the rendered cursor.
*
* @return A point representing the current position.
*/
public PointF getCursorPosition() {
return new PointF(mCursorPosition.x, mCursorPosition.y);
}
/**
* Sets the position of the cursor which is used for rendering.
*
* @param newX The new value of the x coordinate.
* @param newY The new value of the y coordinate
* @return True if the cursor position has changed.
*/
public boolean setCursorPosition(float newX, float newY) {
boolean cursorMoved = false;
if (newX != mCursorPosition.x) {
mCursorPosition.x = newX;
cursorMoved = true;
}
if (newY != mCursorPosition.y) {
mCursorPosition.y = newY;
cursorMoved = true;
}
return cursorMoved;
}
}

View File

@@ -0,0 +1,126 @@
// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package com.termux.x11.input;
import android.content.Context;
import android.view.MotionEvent;
import android.view.ViewConfiguration;
/**
* Helper class for disambiguating whether to treat a two-finger gesture as a swipe or a pinch.
* Initially, the status will be unknown, until the fingers have moved sufficiently far to
* determine the intent.
*/
@SuppressWarnings("ConstantConditions")
public class SwipeDetector {
private boolean mInSwipe = false;
/** Initial coordinates of the two pointers in the current gesture. */
private float mFirstX0;
private float mFirstY0;
private float mFirstX1;
private float mFirstY1;
/**
* The initial coordinates above are valid when this flag is set. Used to determine whether a
* MotionEvent's pointer coordinates are the first ones of the gesture.
*/
private boolean mInGesture;
/**
* Threshold squared-distance, in pixels, to use for motion-detection.
*/
private final int mTouchSlopSquare;
private void reset() {
mInSwipe = false;
mInGesture = false;
}
/** Construct a new detector, using the context to determine movement thresholds. */
public SwipeDetector(Context context) {
ViewConfiguration config = ViewConfiguration.get(context);
int touchSlop = config.getScaledTouchSlop();
mTouchSlopSquare = touchSlop * touchSlop;
}
/** Returns whether a swipe is in progress. */
public boolean isSwiping() {
return mInSwipe;
}
/**
* Analyzes the touch event to determine whether the user is swiping or pinching. Only
* motion events with 2 pointers are considered here. Once the gesture is determined to be a
* swipe or a pinch, further 2-finger motion-events will be ignored. When a different event is
* passed in (motion event with != 2 pointers, or some other event type), this object will
* revert back to the original UNKNOWN state.
*/
public void onTouchEvent(MotionEvent event) {
if (event.getPointerCount() != 2) {
reset();
return;
}
// Only MOVE or DOWN events are considered - all other events should finish any current
// gesture and reset the detector. In addition, a DOWN event should reset the detector,
// since it signals the start of the gesture. If the events are consistent, a DOWN event
// will occur at the start of the gesture, but this implementation tries to cope in case
// the first event is MOVE rather than DOWN.
int action = event.getActionMasked();
if (action != MotionEvent.ACTION_MOVE) {
reset();
if (action != MotionEvent.ACTION_POINTER_DOWN)
return;
}
// If the gesture is known, there is no need for further processing - the state should
// remain the same until the gesture is complete, as tested above.
if (mInSwipe)
return;
float currentX0 = event.getX(0);
float currentY0 = event.getY(0);
float currentX1 = event.getX(1);
float currentY1 = event.getY(1);
if (!mInGesture) {
// This is the first event of the gesture, so store the pointer coordinates.
mFirstX0 = currentX0;
mFirstY0 = currentY0;
mFirstX1 = currentX1;
mFirstY1 = currentY1;
mInGesture = true;
return;
}
float deltaX0 = currentX0 - mFirstX0;
float deltaY0 = currentY0 - mFirstY0;
float deltaX1 = currentX1 - mFirstX1;
float deltaY1 = currentY1 - mFirstY1;
float squaredDistance0 = deltaX0 * deltaX0 + deltaY0 * deltaY0;
float squaredDistance1 = deltaX1 * deltaX1 + deltaY1 * deltaY1;
// If both fingers have moved beyond the touch-slop, it is safe to recognize the gesture.
// However, one finger might be held stationary whilst the other finger is moved a long
// distance. In this case, it is preferable to trigger a PINCH. This should be detected
// soon enough to avoid triggering a sudden large change in the zoom level, but not so
// soon that SWIPE never gets triggered.
boolean finger0Moved = squaredDistance0 > mTouchSlopSquare;
boolean finger1Moved = squaredDistance1 > mTouchSlopSquare;
if ((!finger0Moved && !finger1Moved) || (finger0Moved && !finger1Moved) || (!finger0Moved && finger1Moved))
return;
// Both fingers have moved, so determine SWIPE/PINCH status. If the fingers have moved in
// the same direction, this is a SWIPE, otherwise it's a PINCH. This can be measured by
// taking the scalar product of the direction vectors. This product is positive if the
// vectors are pointing in the same direction, and negative if they're in opposite
// directions.
float scalarProduct = deltaX0 * deltaX1 + deltaY0 * deltaY1;
mInSwipe = scalarProduct > 0;
}
}

View File

@@ -0,0 +1,214 @@
// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package com.termux.x11.input;
import android.content.Context;
import android.graphics.PointF;
import android.os.Handler;
import android.os.Message;
import android.util.SparseArray;
import android.view.MotionEvent;
import android.view.ViewConfiguration;
import java.lang.ref.WeakReference;
/**
* This class detects multi-finger tap and long-press events. This is provided since the stock
* Android gesture-detectors only detect taps/long-presses made with one finger.
*/
public class TapGestureDetector {
/** The listener for receiving notifications of tap gestures. */
public interface OnTapListener {
/**
* Notified when a tap event occurs.
*
* @param pointerCount The number of fingers that were tapped.
* @param x The x coordinate of the initial finger tapped.
* @param y The y coordinate of the initial finger tapped.
*/
void onTap(int pointerCount, float x, float y);
/**
* Notified when a long-touch event occurs.
*
* @param pointerCount The number of fingers held down.
* @param x The x coordinate of the initial finger tapped.
* @param y The y coordinate of the initial finger tapped.
*/
void onLongPress(int pointerCount, float x, float y);
}
/** The listener to which notifications are sent. */
private final OnTapListener mListener;
/** Handler used for posting tasks to be executed in the future. */
private final Handler mHandler;
/**
* Stores the location of each down MotionEvent (by pointer ID), for detecting motion of any
* pointer beyond the TouchSlop region.
*/
private final SparseArray<PointF> mInitialPositions = new SparseArray<>();
/**
* Threshold squared-distance, in pixels, to use for motion-detection. If a finger moves less
* than this distance, the gesture is still eligible to be a tap event.
*/
private final int mTouchSlopSquare;
/** The maximum number of fingers seen in the gesture. */
private int mPointerCount;
/** The coordinates of the first finger down seen in the gesture. */
private PointF mInitialPoint;
/** Set to true whenever motion is detected in the gesture, or a long-touch is triggered. */
private boolean mTapCancelled;
/** @noinspection NullableProblems*/
// This static inner class holds a WeakReference to the outer object, to avoid triggering the
// lint HandlerLeak warning.
@SuppressWarnings("deprecation")
private static class EventHandler extends Handler {
private final WeakReference<TapGestureDetector> mDetector;
public EventHandler(TapGestureDetector detector) {
mDetector = new WeakReference<>(detector);
}
@Override
public void handleMessage(Message message) {
TapGestureDetector detector = mDetector.get();
if (detector != null) {
detector.mTapCancelled = true;
detector.mListener.onLongPress(detector.mPointerCount, detector.mInitialPoint.x, detector.mInitialPoint.y);
detector.mInitialPoint = null;
}
}
}
public TapGestureDetector(Context context, OnTapListener listener) {
mListener = listener;
mHandler = new EventHandler(this);
ViewConfiguration config = ViewConfiguration.get(context);
int touchSlop = config.getScaledTouchSlop();
mTouchSlopSquare = touchSlop * touchSlop;
}
/**
* Analyzes the touch event to determine whether to notify the listener.
*/
public void onTouchEvent(MotionEvent event) {
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
reset();
trackDownEvent(event);
// Cause a long-press notification to be triggered after the timeout.
mHandler.sendEmptyMessageDelayed(0, ViewConfiguration.getLongPressTimeout());
mPointerCount = 1;
break;
case MotionEvent.ACTION_POINTER_DOWN:
trackDownEvent(event);
mPointerCount = Math.max(mPointerCount, event.getPointerCount());
break;
case MotionEvent.ACTION_MOVE:
if (!mTapCancelled) {
if (trackMoveEvent(event)) {
cancelLongTouchNotification();
mTapCancelled = true;
}
}
break;
case MotionEvent.ACTION_UP:
cancelLongTouchNotification();
if (!mTapCancelled)
mListener.onTap(mPointerCount, mInitialPoint.x, mInitialPoint.y);
mInitialPoint = null;
break;
case MotionEvent.ACTION_POINTER_UP:
cancelLongTouchNotification();
trackUpEvent(event);
break;
case MotionEvent.ACTION_CANCEL:
cancelLongTouchNotification();
break;
default:
break;
}
}
/** Stores the location of the ACTION_DOWN or ACTION_POINTER_DOWN event. */
private void trackDownEvent(MotionEvent event) {
int pointerIndex = 0;
if (event.getActionMasked() == MotionEvent.ACTION_POINTER_DOWN) {
pointerIndex = event.getActionIndex();
}
int pointerId = event.getPointerId(pointerIndex);
PointF eventPosition = new PointF(event.getX(pointerIndex), event.getY(pointerIndex));
mInitialPositions.put(pointerId, eventPosition);
if (mInitialPoint == null) {
mInitialPoint = eventPosition;
}
}
/** Removes the ACTION_UP or ACTION_POINTER_UP event from the stored list. */
private void trackUpEvent(MotionEvent event) {
int pointerIndex = 0;
if (event.getActionMasked() == MotionEvent.ACTION_POINTER_UP) {
pointerIndex = event.getActionIndex();
}
int pointerId = event.getPointerId(pointerIndex);
mInitialPositions.remove(pointerId);
}
/**
* Processes an ACTION_MOVE event and returns whether a pointer moved beyond the TouchSlop
* threshold.
*
* @return True if motion was detected.
*/
private boolean trackMoveEvent(MotionEvent event) {
int pointerCount = event.getPointerCount();
for (int i = 0; i < pointerCount; i++) {
int pointerId = event.getPointerId(i);
float currentX = event.getX(i);
float currentY = event.getY(i);
PointF downPoint = mInitialPositions.get(pointerId);
if (downPoint == null) {
// There was no corresponding DOWN event, so add it. This is an inconsistency
// which shouldn't normally occur.
mInitialPositions.put(pointerId, new PointF(currentX, currentY));
continue;
}
float deltaX = currentX - downPoint.x;
float deltaY = currentY - downPoint.y;
if (deltaX * deltaX + deltaY * deltaY > mTouchSlopSquare) {
return true;
}
}
return false;
}
/** Cleans up any stored data for the gesture. */
private void reset() {
cancelLongTouchNotification();
mPointerCount = 0;
mInitialPositions.clear();
mTapCancelled = false;
}
/** Cancels any pending long-touch notifications from the message-queue. */
private void cancelLongTouchNotification() {
mHandler.removeMessages(0);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,63 @@
package com.termux.x11.utils;
import static android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN;
import android.graphics.Rect;
import android.widget.FrameLayout;
import android.view.View;
import android.app.Activity;
import com.termux.x11.MainActivity;
import com.termux.x11.Prefs;
public class FullscreenWorkaround {
// For more information, see https://issuetracker.google.com/issues/36911528
// To use this class, simply invoke assistActivity() on an Activity that already has its content view set.
public static void assistActivity(Activity activity) {
new FullscreenWorkaround(activity);
}
private final Activity mActivity;
private int usableHeightPrevious;
private FullscreenWorkaround(Activity activity) {
mActivity = activity;
FrameLayout content = activity.findViewById(android.R.id.content);
content.getViewTreeObserver().addOnGlobalLayoutListener(this::possiblyResizeChildOfContent);
}
private void possiblyResizeChildOfContent() {
Prefs p = MainActivity.getPrefs();
if (
!mActivity.hasWindowFocus() ||
!((mActivity.getWindow().getAttributes().flags & FLAG_FULLSCREEN) == FLAG_FULLSCREEN) ||
!p.Reseed.get() || !p.fullscreen.get() || SamsungDexUtils.checkDeXEnabled(mActivity)
)
return;
FrameLayout content = (FrameLayout) ((FrameLayout) mActivity.findViewById(android.R.id.content)).getChildAt(0);
FrameLayout.LayoutParams frameLayoutParams = (FrameLayout.LayoutParams) content.getLayoutParams();
int usableHeightNow = computeUsableHeight(content);
if (usableHeightNow != usableHeightPrevious) {
int usableHeightSansKeyboard = content.getRootView().getHeight();
int heightDifference = usableHeightSansKeyboard - usableHeightNow;
if (heightDifference > (usableHeightSansKeyboard/4)) {
// keyboard probably just became visible
frameLayoutParams.height = usableHeightSansKeyboard - heightDifference;
} else {
// keyboard probably just became hidden
frameLayoutParams.height = usableHeightSansKeyboard;
}
content.requestLayout();
usableHeightPrevious = usableHeightNow;
}
}
private int computeUsableHeight(View v) {
Rect r = new Rect();
v.getWindowVisibleDisplayFrame(r);
return (r.bottom - r.top);
}
}

View File

@@ -0,0 +1,130 @@
package com.termux.x11.utils;
import android.opengl.GLES20;
import android.util.Log;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
public class GLUtility {
private static final String SIMPLE_FRAGMENT_SHADER =
"precision highp float;\n" +
"uniform sampler2D u_Texture;\n" +
"varying vec2 v_TexCoord;\n" +
"\n" +
"void main(void){\n" +
" gl_FragColor = texture2D(u_Texture, v_TexCoord);\n" +
"}";
private static final String SIMPLE_FRAGMENT_EXT_SHADER =
"#extension GL_OES_EGL_image_external : require\n" +
"precision highp float;\n" +
"uniform samplerExternalOES u_Texture;\n" +
"varying vec2 v_TexCoord;\n" +
"\n" +
"void main(void){\n" +
" gl_FragColor = texture2D(u_Texture, v_TexCoord);\n" +
"}";
private static final String SIMPLE_VERTEX_SHADER =
"precision highp float;\n" +
"attribute vec3 a_Position;\n" +
"attribute vec2 a_TexCoord;\n" +
"varying vec2 v_TexCoord;\n" +
"\n" +
"void main(void)\n" +
"{\n" +
" gl_Position = vec4(a_Position, 1.0);\n" +
" v_TexCoord = a_TexCoord;\n" +
"}";
private static final String TAG = "GLUtility";
private static float lastAspect;
public static int createProgram(boolean externalTexture) {
if (externalTexture) {
return createProgram(SIMPLE_VERTEX_SHADER, SIMPLE_FRAGMENT_EXT_SHADER);
} else {
return createProgram(SIMPLE_VERTEX_SHADER, SIMPLE_FRAGMENT_SHADER);
}
}
public static int createProgram(String vertexShader, String fragmentShader) {
int program = GLES20.glCreateProgram();
GLES20.glAttachShader(program, compileShader(GLES20.GL_VERTEX_SHADER, vertexShader));
GLES20.glAttachShader(program, compileShader(GLES20.GL_FRAGMENT_SHADER, fragmentShader));
GLES20.glLinkProgram(program);
GLES20.glUseProgram(program);
return program;
}
public static int createTexture(int type) {
int[] texture = new int[1];
GLES20.glGenTextures(texture.length, texture, 0);
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(type, texture[0]);
GLES20.glTexParameteri(type, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(type, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
return texture[0];
}
public static void drawTexture(int type, int program, int texture, float aspect) {
if (Math.abs(lastAspect - aspect) > 0.00001f) {
float[] vertices = new float[] {
-1, aspect, -1, -aspect, 1, -aspect,
-1, aspect, 1, -aspect, 1, aspect,
};
float[] uvs = new float[] {
0, 1, 0, 0, 1, 0,
0, 1, 1, 0, 1, 1
};
attribPointer(program, "a_Position", vertices, 2);
attribPointer(program, "a_TexCoord", uvs, 2);
lastAspect = aspect;
}
GLES20.glUseProgram(program);
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(type, texture);
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 6);
}
private static void attribPointer(int program, String location, float[] data, int stride) {
int handle = GLES20.glGetAttribLocation(program, location);
GLES20.glEnableVertexAttribArray(handle);
GLES20.glVertexAttribPointer(
handle,
stride,
GLES20.GL_FLOAT,
false,
0,
ByteBuffer.allocateDirect(data.length * 4)
.order(ByteOrder.nativeOrder())
.asFloatBuffer()
.put(data)
.position(0)
);
}
private static int compileShader(int shaderType, String shaderSource) {
int shader = GLES20.glCreateShader(shaderType);
if (shader != 0) {
GLES20.glShaderSource(shader, shaderSource);
GLES20.glCompileShader(shader);
final int[] compileStatus = new int[1];
GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compileStatus, 0);
if (compileStatus[0] == GLES20.GL_FALSE) {
Log.e(TAG, "Error compiling shader: " + GLES20.glGetShaderInfoLog(shader));
GLES20.glDeleteShader(shader);
shader = 0;
}
}
return shader;
}
}

View File

@@ -0,0 +1,123 @@
package com.termux.x11.utils;
import android.accessibilityservice.AccessibilityService;
import android.accessibilityservice.AccessibilityServiceInfo;
import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.provider.Settings;
import android.view.KeyEvent;
import android.view.accessibility.AccessibilityEvent;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import com.termux.x11.MainActivity;
import java.util.LinkedHashSet;
public class KeyInterceptor extends AccessibilityService {
LinkedHashSet<Integer> pressedKeys = new LinkedHashSet<>();
private static final Handler handler = new Handler(Looper.getMainLooper());
private static KeyInterceptor self;
private static boolean launchedAutomatically = false;
private boolean enabled = false;
public KeyInterceptor() {
self = this;
}
public static void launch(@NonNull Context ctx) {
try {
Settings.Secure.putString(ctx.getContentResolver(), Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, "com.termux.x11/.utils.KeyInterceptor");
Settings.Secure.putString(ctx.getContentResolver(), Settings.Secure.ACCESSIBILITY_ENABLED, "1");
launchedAutomatically = true;
} catch (SecurityException e) {
new AlertDialog.Builder(ctx)
.setTitle("Permission denied")
.setMessage("Android requires WRITE_SECURE_SETTINGS permission to start accessibility service automatically.\n" +
"Please, launch this command using ADB:\n" +
"adb shell pm grant com.termux.x11 android.permission.WRITE_SECURE_SETTINGS")
.setNegativeButton("OK", null)
.create()
.show();
MainActivity.prefs.enableAccessibilityServiceAutomatically.put(false);
}
}
public static void shutdown(boolean onlyIfEnabledAutomatically) {
if (onlyIfEnabledAutomatically && !launchedAutomatically)
return;
if (self != null) {
self.disableSelf();
self.pressedKeys.clear();
self = null;
}
}
public static boolean isLaunched() {
AccessibilityServiceInfo info = self == null ? null : self.getServiceInfo();
return info != null && info.getId() != null;
}
private static final Runnable disableImmediatelyCallback = KeyInterceptor::disableImmediately;
private static void disableImmediately() {
if (self == null)
return;
android.util.Log.d("KeyInterceptor", "disabling interception service");
self.setServiceInfo(new AccessibilityServiceInfo() {{ flags = DEFAULT; }});
self.enabled = false;
}
public static void recheck() {
MainActivity a = MainActivity.getInstance();
boolean shouldBeEnabled = (a != null && self != null) && (a.hasWindowFocus() || !self.pressedKeys.isEmpty());
if (self != null && shouldBeEnabled != self.enabled) {
if (shouldBeEnabled) {
handler.removeCallbacks(disableImmediatelyCallback);
android.util.Log.d("KeyInterceptor", "enabling interception service");
self.setServiceInfo(new AccessibilityServiceInfo() {{ flags = FLAG_REQUEST_FILTER_KEY_EVENTS; }});
self.enabled = true;
} else
// In the case if service info is changed Android current dragging processes
// so it is impossible to pull notification bar or call recents screen by swiping activity up.
handler.postDelayed(disableImmediatelyCallback, 120000);
}
}
@Override
public boolean onKeyEvent(KeyEvent event) {
boolean ret = false;
MainActivity instance = MainActivity.getInstance();
if (instance == null)
return false;
boolean intercept = instance.shouldInterceptKeys();
if (intercept || (event.getAction() == KeyEvent.ACTION_UP && pressedKeys.contains(event.getKeyCode())))
ret = instance.handleKey(event);
if (intercept && event.getAction() == KeyEvent.ACTION_DOWN)
pressedKeys.add(event.getKeyCode());
else
// We should send key releases to activity for the case if user was pressing some keys when Activity lost focus.
// I.e. if user switched window with Win+Tab or if he was pressing Ctrl while switching activity.
if (event.getAction() == KeyEvent.ACTION_UP)
pressedKeys.remove(event.getKeyCode());
recheck();
return ret;
}
@Override
public void onAccessibilityEvent(AccessibilityEvent e) {}
@Override
public void onInterrupt() {}
}

View File

@@ -0,0 +1,55 @@
package com.termux.x11.utils;
import android.app.Activity;
import android.content.Context;
import android.content.res.Configuration;
import android.util.Log;
import java.lang.reflect.Method;
public class SamsungDexUtils {
private static final String TAG = SamsungDexUtils.class.getSimpleName();
private static Method requestMetaKeyEventMethod;
private static Object manager;
static {
try {
Class<?> clazz = Class.forName("com.samsung.android.view.SemWindowManager");
Method obtain = clazz.getMethod("getInstance");
requestMetaKeyEventMethod = clazz.getDeclaredMethod("requestMetaKeyEvent", android.content.ComponentName.class, boolean.class);
manager = obtain.invoke(null);
android.util.Log.d(TAG, "com.samsung.android.view.SemWindowManager is available");
} catch (Exception ignored) {
requestMetaKeyEventMethod = null;
manager = null;
android.util.Log.d(TAG, "com.samsung.android.view.SemWindowManager is not available");
}
}
static public boolean available() {
return requestMetaKeyEventMethod != null && manager != null;
}
static public void dexMetaKeyCapture(Activity activity, boolean enable) {
if (!available())
return;
try {
requestMetaKeyEventMethod.invoke(manager, activity.getComponentName(), enable);
} catch (Exception it) {
Log.d(TAG, "Could not call com.samsung.android.view.SemWindowManager.requestMetaKeyEvent");
Log.d(TAG, it.getClass().getCanonicalName() + ": " + it.getMessage());
}
}
@SuppressWarnings("JavaReflectionMemberAccess")
public static boolean checkDeXEnabled(Context ctx) {
Configuration config = ctx.getResources().getConfiguration();
try {
Class<?> c = config.getClass();
return c.getField("SEM_DESKTOP_MODE_ENABLED").getInt(c)
== c.getField("semDesktopModeEnabled").getInt(config);
} catch (NoSuchFieldException | IllegalArgumentException | IllegalAccessException ignored) {}
return false;
}
}

View File

@@ -0,0 +1,225 @@
package com.termux.x11.utils;
import static com.termux.shared.termux.extrakeys.ExtraKeysConstants.PRIMARY_KEY_CODES_FOR_STRINGS;
import static com.termux.x11.MainActivity.isConnected;
import static com.termux.x11.MainActivity.toggleKeyboardVisibility;
import static java.nio.charset.StandardCharsets.UTF_8;
import android.annotation.SuppressLint;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.Intent;
import android.text.TextUtils;
import android.util.Log;
import android.view.KeyCharacterMap;
import android.view.KeyEvent;
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.Toast;
import androidx.annotation.NonNull;
import com.termux.shared.termux.extrakeys.*;
import com.termux.x11.LoriePreferences;
import com.termux.x11.MainActivity;
import com.example.tiny_computer.R;
import org.json.JSONException;
public class TermuxX11ExtraKeys implements ExtraKeysView.IExtraKeysView {
@SuppressWarnings("FieldCanBeLocal")
private static final String LOG_TAG = "TermuxX11ExtraKeys";
private final View.OnKeyListener mEventListener;
private final MainActivity mActivity;
private final ExtraKeysView mExtraKeysView;
private final ClipboardManager mClipboardManager;
static private ExtraKeysInfo mExtraKeysInfo;
private boolean ctrlDown;
private boolean altDown;
private boolean shiftDown;
private boolean metaDown;
/** Defines the key for extra keys */
public static final String DEFAULT_IVALUE_EXTRA_KEYS = "[['ESC','/',{key: '-', popup: '|'},'HOME','UP','END','PGUP','EXIT'], ['TAB','CTRL','ALT','LEFT','DOWN','RIGHT','PGDN','KEYBOARD']]"; // Double row
public TermuxX11ExtraKeys(@NonNull View.OnKeyListener eventlistener, MainActivity activity, ExtraKeysView extrakeysview) {
mEventListener = eventlistener;
mActivity = activity;
mExtraKeysView = extrakeysview;
mClipboardManager = (ClipboardManager) mActivity.getSystemService(Context.CLIPBOARD_SERVICE);
}
private final KeyCharacterMap mVirtualKeyboardKeyCharacterMap = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD);
static final String ACTION_START_PREFERENCES_ACTIVITY = "com.termux.x11.start_preferences_activity";
@Override
public void onExtraKeyButtonClick(View view, ExtraKeyButton buttonInfo, Button button) {
Log.e("keys", "key " + buttonInfo.display);
if (buttonInfo.macro) {
String[] keys = buttonInfo.key.split(" ");
boolean ctrlDown = false;
boolean altDown = false;
boolean shiftDown = false;
boolean metaDown = false;
boolean fnDown = false;
for (String key : keys) {
if (SpecialButton.CTRL.getKey().equals(key)) {
ctrlDown = true;
} else if (SpecialButton.ALT.getKey().equals(key)) {
altDown = true;
} else if (SpecialButton.SHIFT.getKey().equals(key)) {
shiftDown = true;
} else if (SpecialButton.META.getKey().equals(key)) {
metaDown = true;
} else if (SpecialButton.FN.getKey().equals(key)) {
fnDown = true;
} else {
ctrlDown = false;
altDown = false;
shiftDown = false;
metaDown = false;
fnDown = false;
}
onLorieExtraKeyButtonClick(view, key, ctrlDown, altDown, shiftDown, metaDown, fnDown);
}
} else {
onLorieExtraKeyButtonClick(view, buttonInfo.key, false, false, false, false, false);
}
}
protected void onTerminalExtraKeyButtonClick(@SuppressWarnings("unused") View view, String key, boolean ctrlDown, boolean altDown, boolean shiftDown, boolean metaDown, @SuppressWarnings("unused") boolean fnDown) {
if (this.ctrlDown != ctrlDown) {
this.ctrlDown = ctrlDown;
mActivity.getLorieView().sendKeyEvent(0, KeyEvent.KEYCODE_CTRL_LEFT, ctrlDown);
}
if (this.altDown != altDown) {
this.altDown = altDown;
mActivity.getLorieView().sendKeyEvent(0, KeyEvent.KEYCODE_ALT_LEFT, altDown);
}
if (this.shiftDown != shiftDown) {
this.shiftDown = shiftDown;
mActivity.getLorieView().sendKeyEvent(0, KeyEvent.KEYCODE_SHIFT_LEFT, shiftDown);
}
if (this.metaDown != metaDown) {
this.metaDown = metaDown;
mActivity.getLorieView().sendKeyEvent(0, KeyEvent.KEYCODE_META_LEFT, metaDown);
}
if (PRIMARY_KEY_CODES_FOR_STRINGS.containsKey(key)) {
Integer keyCode = PRIMARY_KEY_CODES_FOR_STRINGS.get(key);
if (keyCode == null) return;
mActivity.getLorieView().sendKeyEvent(0, keyCode, true);
mActivity.getLorieView().sendKeyEvent(0, keyCode, false);
} else {
// not a control char
mActivity.getLorieView().sendTextEvent(key.getBytes(UTF_8));
}
}
public void unsetSpecialKeys() {
if (mExtraKeysView == null)
return;
if (Boolean.TRUE.equals(mExtraKeysView.readSpecialButton(SpecialButton.CTRL, true)))
mActivity.getLorieView().sendKeyEvent(0, KeyEvent.KEYCODE_CTRL_LEFT, false);
if (Boolean.TRUE.equals(mExtraKeysView.readSpecialButton(SpecialButton.ALT, true)))
mActivity.getLorieView().sendKeyEvent(0, KeyEvent.KEYCODE_ALT_LEFT, false);
if (Boolean.TRUE.equals(mExtraKeysView.readSpecialButton(SpecialButton.SHIFT, true)))
mActivity.getLorieView().sendKeyEvent(0, KeyEvent.KEYCODE_SHIFT_LEFT, false);
if (Boolean.TRUE.equals(mExtraKeysView.readSpecialButton(SpecialButton.META, true)))
mActivity.getLorieView().sendKeyEvent(0, KeyEvent.KEYCODE_META_LEFT, false);
}
@Override
public boolean performExtraKeyButtonHapticFeedback(View view, ExtraKeyButton buttonInfo, Button button) {
MainActivity.handler.postDelayed(() -> {
boolean pressed;
switch (buttonInfo.key) {
case "CTRL":
pressed = Boolean.TRUE.equals(mExtraKeysView.readSpecialButton(SpecialButton.CTRL, false));
mActivity.getLorieView().sendKeyEvent(0, KeyEvent.KEYCODE_CTRL_LEFT, pressed);
break;
case "ALT":
pressed = Boolean.TRUE.equals(mExtraKeysView.readSpecialButton(SpecialButton.ALT, false));
mActivity.getLorieView().sendKeyEvent(0, KeyEvent.KEYCODE_ALT_LEFT, pressed);
break;
case "SHIFT":
pressed = Boolean.TRUE.equals(mExtraKeysView.readSpecialButton(SpecialButton.SHIFT, false));
mActivity.getLorieView().sendKeyEvent(0, KeyEvent.KEYCODE_SHIFT_LEFT, pressed);
break;
case "META":
pressed = Boolean.TRUE.equals(mExtraKeysView.readSpecialButton(SpecialButton.META, false));
mActivity.getLorieView().sendKeyEvent(0, KeyEvent.KEYCODE_META_LEFT, pressed);
break;
}
}, 100);
return false;
}
@SuppressLint("RtlHardcoded")
public void onLorieExtraKeyButtonClick(View view, String key, boolean ctrlDown, boolean altDown, boolean shiftDown, boolean metaDown, boolean fnDown) {
if ("KEYBOARD".equals(key))
toggleKeyboardVisibility(mActivity);
else if ("DRAWER".equals(key) || "PREFERENCES".equals(key))
mActivity.startActivity(new Intent(mActivity, LoriePreferences.class) {{ setAction(ACTION_START_PREFERENCES_ACTIVITY); }});
else if ("EXIT".equals(key))
mActivity.finish();
else if ("PASTE".equals(key)) {
ClipData clipData = mClipboardManager.getPrimaryClip();
if (clipData != null) {
CharSequence pasted = clipData.getItemAt(0).coerceToText(mActivity);
if (!TextUtils.isEmpty(pasted)) {
KeyEvent[] events = mVirtualKeyboardKeyCharacterMap.getEvents(pasted.toString().toCharArray());
if (events != null)
for (KeyEvent event : events)
mEventListener.onKey(mActivity.getLorieView(), event.getKeyCode(), event);
}
}
} else if ("MOUSE_HELPER".equals(key))
mActivity.toggleMouseAuxButtons();
else if ("STYLUS_HELPER".equals(key))
mActivity.toggleStylusAuxButtons();
else
onTerminalExtraKeyButtonClick(view, key, ctrlDown, altDown, shiftDown, metaDown, fnDown);
}
/**
* Set the terminal extra keys and style.
*/
public static void setExtraKeys() {
mExtraKeysInfo = null;
try {
// The mMap stores the extra key and style string values while loading properties
// Check {@link #getExtraKeysInternalPropertyValueFromValue(String)} and
// {@link #getExtraKeysStyleInternalPropertyValueFromValue(String)}
String extrakeys = MainActivity.getPrefs().extra_keys_config.get();
mExtraKeysInfo = new ExtraKeysInfo(extrakeys, "extra-keys-style", ExtraKeysConstants.CONTROL_CHARS_ALIASES);
} catch (JSONException e) {
Toast.makeText(MainActivity.getInstance(), "Could not load and set the \"extra-keys\" property from the properties file: " + e, Toast.LENGTH_LONG).show();
Log.e(LOG_TAG, "Could not load and set the \"extra-keys\" property from the properties file: ", e);
try {
mExtraKeysInfo = new ExtraKeysInfo(TermuxX11ExtraKeys.DEFAULT_IVALUE_EXTRA_KEYS, "default", ExtraKeysConstants.CONTROL_CHARS_ALIASES);
} catch (JSONException e2) {
Toast.makeText(MainActivity.getInstance(), "Can't create default extra keys", Toast.LENGTH_LONG).show();
Log.e(LOG_TAG, "Could create default extra keys: ", e);
mExtraKeysInfo = null;
}
}
}
public static ExtraKeysInfo getExtraKeysInfo() {
if (mExtraKeysInfo == null)
setExtraKeys();
return mExtraKeysInfo;
}
}

View File

@@ -0,0 +1,133 @@
package com.termux.x11.utils;
import android.annotation.SuppressLint;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.KeyEvent;
import android.view.KeyCharacterMap;
import android.widget.Button;
import android.widget.EditText;
import androidx.annotation.NonNull;
import androidx.viewpager.widget.PagerAdapter;
import androidx.viewpager.widget.ViewPager;
import com.termux.shared.termux.extrakeys.ExtraKeysView;
import com.termux.x11.MainActivity;
import com.example.tiny_computer.R;
public class X11ToolbarViewPager {
public static class PageAdapter extends PagerAdapter {
final MainActivity mActivity;
private final View.OnKeyListener mEventListener;
public PageAdapter(MainActivity activity, View.OnKeyListener listen) {
this.mActivity = activity;
this.mEventListener = listen;
}
@Override
public int getCount() {
return 2;
}
@Override
public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
return view == object;
}
@SuppressLint("ClickableViewAccessibility")
@NonNull
@Override
public Object instantiateItem(@NonNull ViewGroup collection, int position) {
LayoutInflater inflater = LayoutInflater.from(mActivity);
View layout;
if (position == 0) {
layout = inflater.inflate(R.layout.view_terminal_toolbar_extra_keys, collection, false);
ExtraKeysView extraKeysView = (ExtraKeysView) layout;
mActivity.mExtraKeys = new TermuxX11ExtraKeys(mEventListener, mActivity, extraKeysView);
extraKeysView.reload();
extraKeysView.setExtraKeysViewClient(mActivity.mExtraKeys);
extraKeysView.setOnHoverListener((v, e) -> true);
extraKeysView.setOnGenericMotionListener((v, e) -> true);
} else {
layout = inflater.inflate(R.layout.view_terminal_toolbar_text_input, collection, false);
final EditText editText = layout.findViewById(R.id.terminal_toolbar_text_input);
final Button back = layout.findViewById(R.id.terminal_toolbar_back_button);
editText.setOnEditorActionListener((v, actionId, event) -> {
String textToSend = editText.getText().toString();
if (textToSend.isEmpty()) textToSend = "\r";
KeyEvent e = new KeyEvent(0, textToSend, KeyCharacterMap.VIRTUAL_KEYBOARD, 0);
mEventListener.onKey(mActivity.getLorieView(), 0, e);
editText.setText("");
return true;
});
editText.setOnCapturedPointerListener((v2, e2) -> {
MainActivity.setCapturingEnabled(false);
return false;
});
back.setOnClickListener(v -> mActivity.getTerminalToolbarViewPager().setCurrentItem(0, true));
back.setTextColor(0xFFFFFFFF);
back.setPadding(0, 0, 0, 0);
back.setBackground(new ColorDrawable(Color.BLACK) {
public boolean isStateful() {
return true;
}
public boolean hasFocusStateSpecified() {
return true;
}
});
back.setOnTouchListener((view, event) -> {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
view.setBackgroundColor(0xFF7F7F7F);
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
view.setBackgroundColor(0x00000000);
break;
}
return false;
});
}
collection.addView(layout);
return layout;
}
@Override
public void destroyItem(@NonNull ViewGroup collection, int position, @NonNull Object view) {
collection.removeView((View) view);
}
}
public static class OnPageChangeListener extends ViewPager.SimpleOnPageChangeListener {
final MainActivity act;
final ViewPager mTerminalToolbarViewPager;
public OnPageChangeListener(MainActivity activity, ViewPager viewPager) {
this.act = activity;
this.mTerminalToolbarViewPager = viewPager;
}
@Override
public void onPageSelected(int position) {
if (position == 0) {
act.getLorieView().requestFocus();
} else {
final EditText editText = mTerminalToolbarViewPager.findViewById(R.id.terminal_toolbar_text_input);
if (editText != null) editText.requestFocus();
}
}
}
}

View File

@@ -1,5 +1,7 @@
package com.example.tiny_computer
import android.system.Os.setenv
import android.content.Intent
import androidx.annotation.NonNull
import androidx.annotation.Keep
@@ -28,7 +30,7 @@ class MainActivity: FlutterActivity() {
super.configureFlutterEngine(flutterEngine)
prefs = AppPreferences(this)
prefs.ui.theme.observeForever { updateNightMode(it) }
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, "avnc").setMethodCallHandler {
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, "android").setMethodCallHandler {
// 注册通道并设置方法调用处理器
call, result ->
// 判断方法名
@@ -49,6 +51,21 @@ class MainActivity: FlutterActivity() {
startActivity(Intent(this, Signal9Activity::class.java))
result.success(0)
}
"launchX11PrefsPage" -> {
startActivity(Intent(this, com.termux.x11.LoriePreferences::class.java))
result.success(0)
}
"launchXServer" -> {
setenv("TMPDIR", call.argument("tmpdir")!!, true)
setenv("XKB_CONFIG_ROOT", call.argument("xkb")!!, true)
setenv("TERMUX_X11_DEBUG", "1", true)
com.termux.x11.CmdEntryPoint.main(arrayOf(":4"))
result.success(0)
}
"launchX11Page" -> {
startActivity(Intent(this, com.termux.x11.MainActivity::class.java))
result.success(0)
}
else -> {
// 不支持的方法名
result.notImplemented()

View File

@@ -1,7 +1,9 @@
package com.example.tiny_computer
import android.content.Context
import com.google.android.material.color.DynamicColors
import io.flutter.app.FlutterApplication
import me.weishu.reflection.Reflection
class MainApplication : FlutterApplication() {
@@ -9,4 +11,9 @@ class MainApplication : FlutterApplication() {
super.onCreate()
DynamicColors.applyToActivitiesIfAvailable(this@MainApplication)
}
override fun attachBaseContext(base: Context?) {
super.attachBaseContext(base)
Reflection.unseal(base)
}
}

View File

@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/* //device/apps/common/res/anim/slide_in_left.xml
**
** Copyright 2007, 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.
*/
-->
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:fromXDelta="-50%p" android:toXDelta="0"
android:duration="@android:integer/config_mediumAnimTime"/>
<alpha android:fromAlpha="0.0" android:toAlpha="1.0"
android:duration="@android:integer/config_mediumAnimTime" />
</set>

View File

@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/* //device/apps/common/res/anim/slide_in_right.xml
**
** Copyright 2007, 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.
*/
-->
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:fromXDelta="50%p" android:toXDelta="0"
android:duration="@android:integer/config_mediumAnimTime"/>
<alpha android:fromAlpha="0.0" android:toAlpha="1.0"
android:duration="@android:integer/config_mediumAnimTime" />
</set>

View File

@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/* //device/apps/common/res/anim/slide_out_left.xml
**
** Copyright 2007, 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.
*/
-->
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:fromXDelta="0" android:toXDelta="-50%p"
android:duration="@android:integer/config_mediumAnimTime"/>
<alpha android:fromAlpha="1.0" android:toAlpha="0.0"
android:duration="@android:integer/config_mediumAnimTime" />
</set>

View File

@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/* //device/apps/common/res/anim/slide_out_right.xml
**
** Copyright 2007, 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.
*/
-->
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:fromXDelta="0" android:toXDelta="50%p"
android:duration="@android:integer/config_mediumAnimTime"/>
<alpha android:fromAlpha="1.0" android:toAlpha="0.0"
android:duration="@android:integer/config_mediumAnimTime" />
</set>

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="500dp"
android:height="410dp"
android:viewportWidth="500"
android:viewportHeight="410">
<group>
<path
android:strokeWidth="1"
android:pathData="M 0 0 H 501 V 407 H 0 V 0 Z" />
<group>
<path
android:fillColor="#ffffff"
android:strokeWidth="1"
android:pathData="M 13,15 L 154,201 154,203 13,390 85,390 190,249 226,297 297,297 85,15 13,15 Z" />
<path
android:fillColor="#ffffff"
android:strokeWidth="1"
android:pathData="M 485,343 L 273,343 273,390 485,390 485,343 485,343 Z" />
<path
android:fillColor="#ffffff"
android:strokeWidth="1"
android:pathData="M 367,15 L 296,15 205,136 240,183 367,15 367,15 Z" />
</group>
</group>
</vector>

View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true">
<shape android:shape="rectangle">
<solid android:color="#777777" />
<stroke android:width="2dp" android:color="#000000" />
</shape>
</item>
<item>
<shape android:shape="rectangle">
<solid android:color="#FFFFFF" />
<stroke android:width="0.5dp" android:color="#000000" />
</shape>
</item>
</selector>

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