Compare commits

...

56 Commits

Author SHA1 Message Date
Caten
ee230f91dd Fix hangover and update 2024-12-01 16:26:16 +08:00
Caten
b5cbda42cb Update code to 1.0.20.
Fix wps
2024-12-01 00:29:31 +08:00
Caten
fd535f0e20 Update code to v1.0.19-1
Update readme, move cmatrix and fonts to patch.tar.gz
2024-11-12 22:25:59 +08:00
Caten
a5a381604d Update code to v1.0.19
hangover, wechat, termux x11 xfce fix, locale.gen fix...
2024-11-10 14:43:29 +08:00
Caten
a911efdc54 Update code to v1.0.18 2024-09-21 15:44:39 +08:00
Caten
49c2377e46 some fix, dri3, wps, readme, ... 2024-09-21 11:43:14 +08:00
Caten
a117050fde Termux x11 port 2024-09-20 21:39:48 +08:00
Caten
958d7839ff submodule fix 2024-08-17 19:44:18 +08:00
Caten
106b5fc325 submodule 2024-08-17 16:25:36 +08:00
Caten
699f1eef37 submodule 2024-08-17 16:05:27 +08:00
Caten
905ff609b1 Try submodule 2024-08-17 15:57:08 +08:00
Caten
70c2018ddf Add a hint; Update code to v1.0.17 2024-08-11 12:12:58 +08:00
Caten
b1895af653 Auto enable getifaddrs bridge; Fix Signal 9 page 2024-08-11 12:04:32 +08:00
Caten
62995e0a5d Signal9Page Change & More 2024-08-11 10:49:28 +08:00
Caten
5ebbaf7073 Add more mirror site for box86/box64 and wine 2024-08-10 18:15:59 +08:00
Caten
cb1f4b23ee Turnip Option Added 2024-08-10 15:49:35 +08:00
Caten
0d2f5f4e91 Fix wps link; electron folder open 2024-08-10 12:28:31 +08:00
Caten
d54d1ef6f3 v1.0.16, fix wps link 2024-07-31 00:09:05 +08:00
Caten
0377aa7b8f Ads removal 2024-06-01 17:48:29 +08:00
Caten
232afe9929 Ready for v1.0.16 2024-06-01 06:43:48 +08:00
Caten
fcb472594d Adjust FAQ message 2024-04-16 20:20:24 +08:00
Caten
aa6d0feed7 Enable pip 2024-04-16 12:47:33 +08:00
Caten
1ee935105e Various fixes
1. 强制更新后调整系统语言到中文(Debian小版本更新时经常会出现系统语言变默认的问题);
2. 安装WPS时强制修复安装(经常有用户出现安装时清后台导致安装损坏的情况,索性每次安装前执行修复命令);
3. 第一次进入容器时修改默认分辨率到与用户设备一致
2024-04-16 12:43:44 +08:00
Caten
7242c45e38 Merge pull request #33 from wyq0918dev/avnc_md3
修复:AVNC原生界面与Flutter界面样式不符
2024-04-02 20:43:47 +08:00
王泳淇
d0a539d6dc 修复:AVNC原生界面与Flutter界面样式不符
1.更新Android端material库为1.11.0
2.在Android端启用动态颜色
3.更改主题样式为Material3
4.为两个原生页面启用边倒边沉浸
5.修改Android端项目名称为TinyComputer(顺手改了, 默认为android)
2024-04-02 14:57:50 +08:00
Caten
3e443ceedc Update code to v1.0.15 2024-03-12 22:06:10 +08:00
Caten
b50622787d Various fixes 2024-03-10 18:20:48 +08:00
Caten
231d1167e0 Change default settings 2024-03-05 22:20:37 +08:00
Caten
a956d26f6d Update code to v1.0.14 (10) 2024-02-29 19:35:00 +08:00
Caten
c2ee3b694c Update code to v1.0.13+1 2024-01-24 16:03:45 +08:00
Caten
09bf75beed Change WPS command, remove alipay 2024-01-13 07:52:53 +08:00
Caten
b00ede9483 Merge pull request #9 from wyq0918dev/md3
Modify user interface to material3
2024-01-12 18:57:06 +08:00
王泳淇
b8393dacfd Modify user interface to material3 2024-01-12 16:27:32 +08:00
Caten
ce5ad3b758 Update code to v1.0.12+3 2024-01-07 08:32:56 +08:00
Caten
cf15e2e07d HiDPI options added 2024-01-06 18:44:58 +08:00
Caten
938745036d Update code to v1.0.12+2
wakelock, modified proot with binfmt-like feature, more wine scripts
2023-12-11 15:07:07 +08:00
Caten
b3428555c6 box and wine initial support 2023-11-30 15:57:56 +08:00
Caten
2a19c5eb78 Audio fix, more install scripts 2023-11-25 08:20:12 +08:00
Caten
54a941da63 update readme 2023-11-11 21:28:48 +08:00
Caten
87beedef68 adjust readme 2023-11-11 18:05:11 +08:00
Caten
c6afc4d468 virgl support 2023-11-11 11:23:16 +08:00
Caten
6dbe710fdc getifaddrs fix 2023-11-10 21:29:07 +08:00
Caten
cf8ce47662 Organize the code 2023-11-09 12:48:55 +08:00
Caten
86ce2315d4 Add signal 9 info, adjust readme 2023-11-07 17:29:49 +08:00
Caten
6e51e5b2d2 fix tab key eaten 2023-10-19 23:45:33 +08:00
Caten
0971059111 backup 2023-10-10 18:16:56 +08:00
Caten
2cf19179f9 Fix keyboard plug in, streaming don't close 2023-10-09 06:47:57 +08:00
Caten
b6d4d2f11b Adjust ads watch settings, add saf documents provider, camera stream, more permission 2023-10-08 16:40:51 +08:00
Caten
5a6f04d094 Update help message 2023-10-03 21:50:59 +08:00
Caten
195a2f50a3 Fix boot options 2023-10-03 20:51:29 +08:00
Caten
16a14c8a3e Adjust help message 2023-10-03 13:15:11 +08:00
Caten
f15899be95 Fix enter and sticky key 2023-10-02 19:06:41 +08:00
Caten
27a5073551 Fix enter (pty) key, add broken stick key support 2023-10-02 15:44:52 +08:00
Caten
b4ca9ae4f7 Add font scale, terminal max line, vip skip ads feature 2023-10-02 05:47:08 +08:00
Caten
2ef590beb7 improve signal 9 page; print to debugPrint 2023-09-24 15:45:03 +08:00
Caten
e6555b2166 Update README.md 2023-09-21 23:54:19 +08:00
316 changed files with 40738 additions and 953 deletions

2
.gitignore vendored
View File

@@ -39,9 +39,11 @@ app.*.symbols
app.*.map.json
# Android Studio will place build artifacts here
/android/app/build
/android/app/debug
/android/app/profile
/android/app/release
/android/app/.cxx
/backup

77
.gitmodules vendored Normal file
View File

@@ -0,0 +1,77 @@
[submodule "android/extern/libvncserver"]
path = android/extern/libvncserver
url = https://github.com/gujjwal00/libvncserver.git
[submodule "android/extern/libjpeg-turbo"]
path = android/extern/libjpeg-turbo
url = https://github.com/libjpeg-turbo/libjpeg-turbo.git
[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

@@ -2,55 +2,74 @@
<img decoding="async" src="readme/cover0.png" width="50%">
即开即用的类PC环境内置火狐浏览器和fcitx输入法等常用软件
给所有安卓arm64设备的“PC应用引擎”平替
Click-to-run debian bookworm xfce on android for Chinese users, with fcitx pinyin input method and wps office preinstalled. No termux required.
Click-to-run Debian Bookworm XFCE on Android for Chinese users, with the Fcitx Pinyin input method preinstalled. No Termux is required. If you want to change the language in the container, run "tmoe", since this root filesystem is made using [tmoe](https://github.com/2moe/tmoe).
## 特点
- 一键安装,即开即用
- 来自kali-undercover的win10主题(仅xfce版本),友好的界面
<img decoding="async" src="readme/img1.png" width="50%">
- 提供常用软件的一键安装指令
<img decoding="async" src="readme/img2.png" width="50%">
- 可方便地改变屏幕缩放,不用担心屏幕过大或过小
<img decoding="async" src="readme/img3.gif" width="50%">
- 便捷访问设备文件或通过设备SAF访问软件文件
<img decoding="async" src="readme/img4.png" width="50%">
- 提供终端和众多可调节参数供高级用户使用
<img decoding="async" src="readme/img5.png" width="50%">
## 原理
使用proot运行debian环境
内置[noVNC](https://github.com/novnc/noVNC)显示图形界面
初次启动由于解压的缘故要点时间
以后点开就能用
只支持arm64安卓
内置[noVNC](https://github.com/novnc/noVNC)/[AVNC](https://github.com/gujjwal00/avnc)/[Termux:X11](https://github.com/termux/termux-x11)显示图形界面
## 项目结构
assets的文件来源如下:
assets的文件来源信息可以在[这里](extra/readme.md)找到。
- [proot](https://github.com/termux/proot/), 使用[build-proot-android](https://github.com/green-green-avk/build-proot-android)脚本编译
- [busybox](https://github.com/meefik/busybox)
- [Xserver XSDL, pulseaudio相关文件](https://github.com/pelya/commandergenius/tree/sdl_android/project/jni/application/xserver)
- [Tmoe Linux, debian包来源](https://github.com/2moe/tmoe)
其中busybox和pulseaudio相关文件都是直接用了二进制文件。
pulseaudio我真的编译不来如果你会的话请教教我吧
对debian容器进行了如下修改
- 使用tmoe安装了xfce环境和全套VNC
- 使用kali-undercover提供的Win10主题美化xfce
- (使用tmoe)安装了fcitx输入法和云拼音组件。按<Ctrl+空格>切换输入法。
- 强烈建议**不要**使用安卓中文输入法直接输入中文,而是使用英文键盘通过容器的输入法输入中文,避免丢字错字。
- 对noVNC进行[修改](https://github.com/Cateners/noVNC) (scale_factor分支)添加了scale factor滑块控制缩放添加了上下左右shift等按键
- 在主目录下可以方便地访问手机存储(如果提供了存储权限的话)
- 启动时会尝试挂载手机的一些字体目录(AppFiles/Fonts、Fonts和/system/fonts), 如果这些目录下有字体文件的话会一并加载到系统中,无需额外安装
- 最后采用tar.xz压缩用split命令分成了xa*等多个文件
完整的容器制作过程可以在[这里](extra/build-tiny-rootfs.md)看到。
数据包不再在assets中更新而是随releases提供主要是为了避免git越来越大
lib目录
- main.dart文件页面布局老实说已经有点乱
- main.dart文件页面布局有点乱
- workflow.dart文件逻辑部分目前也还可以理解
- Util 工具类
- TermPty 一个终端
- G 全局变量类
- Workflow 从软件点开到容器启动的所有步骤
## 编译
你需要配置好flutter和安卓sdk还需安装python3、bison、patch、gcc然后克隆此项目。
在编译之前需要在release中下载系统rootfs(或者[自行制作](extra/build-tiny-rootfs.md))之后使用split命令分割拷贝到assets。一般我将其分为98MB。
`split -b 98M debian.tar.xz`
还需要对flutter的一些默认配置作修改因为其与项目中build.gradle的一些设置冲突。
- 删除`flutter\packages\flutter_tools\gradle\src\main\groovy\flutter.groovy`路径下与`ShrinkResources`相关的`if`代码块。
接下来就可以编译了。我使用的命令如下:
`flutter build apk --target-platform android-arm64 --split-per-abi --obfuscate --split-debug-info=tiny_computer/sdi`
有一些C代码可能报错。比如KeyBind.c等文件报错一些符号未定义。但其实包含那些符号的函数并没有被使用所以可以把它们删掉再编译。
应该有编译选项可以避免这种情况但我对cmake不熟就先这样了:P
## 目前已知bug
多用户/分身情形无法sudo, 其它见issue

114
android/app/CMakeLists.txt Normal file
View File

@@ -0,0 +1,114 @@
cmake_minimum_required(VERSION 3.10)
project(NativeVNC C CXX ASM)
set(AVNC_EXTERN_DIR ${PROJECT_SOURCE_DIR}/../extern)
set(BUILD_SHARED_LIBS OFF CACHE BOOL "Build shared Libs" FORCE)
###############################################################################
# Utilities
###############################################################################
# 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'.")
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}")
elseif (CMAKE_ANDROID_ARCH STREQUAL "arm")
set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} --target=arm-linux-androideabi${ANDROID_NATIVE_API_LEVEL}")
endif ()
###############################################################################
# JPEG
###############################################################################
avnc_check_submodule(libjpeg-turbo)
set(AVNC_LIBJPEG_SRC_DIR ${AVNC_EXTERN_DIR}/libjpeg-turbo)
set(AVNC_LIBJPEG_BUILD_DIR ${CMAKE_BINARY_DIR}/libjpeg-turbo)
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)
# Create an interface library to manage include directories
add_library(libjpeg INTERFACE)
target_include_directories(libjpeg INTERFACE ${AVNC_LIBJPEG_SRC_DIR})
###############################################################################
# SSL
###############################################################################
avnc_check_submodule(wolfssl)
set(AVNC_LIBSSL_SRC_DIR ${AVNC_EXTERN_DIR}/wolfssl)
set(AVNC_LIBSSL_BUILD_DIR ${CMAKE_BINARY_DIR}/wolfssl)
# CMake support in wolfSSl is still under development, so we have to
# manually set some flags to enable OpenSSL compatibility layer
set(WOLFSSL_CRL yes)
set(WOLFSSL_DES3 yes)
set(WOLFSSL_CRYPT_TESTS no)
add_definitions(-DOPENSSL_ALL -DOPENSSL_EXTRA -DHAVE_CRL -DHAVE_EX_DATA
-DHAVE_ANON -DWOLFSSL_AES_DIRECT -DHAVE_AES_ECB -DWOLFSSL_DES_ECB
-DWC_NO_HARDEN)
add_subdirectory(${AVNC_LIBSSL_SRC_DIR} ${AVNC_LIBSSL_BUILD_DIR})
# Create an interface library to manage include directories
add_library(libssl INTERFACE)
target_include_directories(libssl INTERFACE ${AVNC_LIBSSL_SRC_DIR}/wolfssl)
###############################################################################
# LibVNC
###############################################################################
avnc_check_submodule(libvncserver)
set(AVNC_LIBVNC_SRC_DIR ${AVNC_EXTERN_DIR}/libvncserver)
set(AVNC_LIBVNC_BUILD_DIR ${CMAKE_BINARY_DIR}/libvncserver)
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 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})
# Link libraries
target_link_libraries(native-vnc
PRIVATE
libjpeg
libssl
libvnc
vncclient
)
# Link NDK libraries
find_library(LIB_LOG log)
find_library(LIB_GLES GLESv2)
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

@@ -2,6 +2,10 @@ plugins {
id "com.android.application"
id "kotlin-android"
id "dev.flutter.flutter-gradle-plugin"
id "org.jetbrains.kotlin.kapt"
id "org.jetbrains.kotlin.plugin.serialization" version "1.9.10"
id "org.jetbrains.kotlin.plugin.parcelize"
}
def localProperties = new Properties()
@@ -38,6 +42,7 @@ android {
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
main.java.srcDirs += 'src/main/java'
}
defaultConfig {
@@ -45,10 +50,19 @@ android {
applicationId "com.fct.tiny"
// You can update the following values to match your application needs.
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
minSdkVersion flutter.minSdkVersion
minSdkVersion 27 //proot version //ffmpeg_kit; flutter.minSdkVersion
targetSdkVersion 28 //https://github.com/termux/termux-app/issues/1072; native; linker; flutter.targetSdkVersion
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()]
}
}
}
buildTypes {
@@ -56,6 +70,35 @@ 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\groovy\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
}
externalNativeBuild {
cmake {
version '3.22.1'
path file('CMakeLists.txt')
}
}
@@ -63,10 +106,101 @@ android {
//checkReleaseBuilds false
abortOnError false
}
packagingOptions {
pickFirst 'lib/arm64-v8a/libc++_shared.so'
pickFirst 'lib/x86_64/libc++_shared.so'
pickFirst 'lib/armeabi-v7a/libc++_shared.so'
pickFirst 'lib/arm64-v8a/libc++_shared.so'
}
}
flutter {
source '../..'
}
dependencies {}
dependencies {
implementation "androidx.core:core-ktx:1.12.0"
implementation "androidx.activity:activity-ktx:1.8.2"
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"
implementation "androidx.biometric:biometric-ktx:1.2.0-alpha05"
implementation "androidx.recyclerview:recyclerview:1.2.1"
def roomVersion = "2.6.1"
implementation "androidx.room:room-runtime:$roomVersion"
implementation "androidx.room:room-ktx:$roomVersion"
kapt "androidx.room:room-compiler:$roomVersion"
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,160 @@
{
"formatVersion": 1,
"database": {
"version": 1,
"identityHash": "ccb0ad6d8acbefcb44a49c07f353adc8",
"entities": [
{
"tableName": "profiles",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`ID` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `host` TEXT NOT NULL, `port` INTEGER NOT NULL, `username` TEXT NOT NULL, `password` TEXT NOT NULL, `securityType` INTEGER NOT NULL, `channelType` INTEGER NOT NULL, `colorLevel` INTEGER NOT NULL, `imageQuality` INTEGER NOT NULL, `viewOnly` INTEGER NOT NULL, `useLocalCursor` INTEGER NOT NULL, `keyCompatMode` INTEGER NOT NULL, `useRepeater` INTEGER NOT NULL, `idOnRepeater` INTEGER NOT NULL, `sshHost` TEXT NOT NULL, `sshPort` INTEGER NOT NULL, `sshUsername` TEXT NOT NULL, `sshAuthType` INTEGER NOT NULL, `sshPassword` TEXT NOT NULL, `sshPrivateKey` TEXT NOT NULL, `sshPrivateKeyPassword` TEXT NOT NULL)",
"fields": [
{
"fieldPath": "ID",
"columnName": "ID",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "name",
"columnName": "name",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "host",
"columnName": "host",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "port",
"columnName": "port",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "username",
"columnName": "username",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "password",
"columnName": "password",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "securityType",
"columnName": "securityType",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "channelType",
"columnName": "channelType",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "colorLevel",
"columnName": "colorLevel",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "imageQuality",
"columnName": "imageQuality",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "viewOnly",
"columnName": "viewOnly",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "useLocalCursor",
"columnName": "useLocalCursor",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "keyCompatMode",
"columnName": "keyCompatMode",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "useRepeater",
"columnName": "useRepeater",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "idOnRepeater",
"columnName": "idOnRepeater",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "sshHost",
"columnName": "sshHost",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "sshPort",
"columnName": "sshPort",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "sshUsername",
"columnName": "sshUsername",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "sshAuthType",
"columnName": "sshAuthType",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "sshPassword",
"columnName": "sshPassword",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "sshPrivateKey",
"columnName": "sshPrivateKey",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "sshPrivateKeyPassword",
"columnName": "sshPrivateKeyPassword",
"affinity": "TEXT",
"notNull": true
}
],
"primaryKey": {
"columnNames": [
"ID"
],
"autoGenerate": true
},
"indices": [],
"foreignKeys": []
}
],
"views": [],
"setupQueries": [
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'ccb0ad6d8acbefcb44a49c07f353adc8')"
]
}
}

View File

@@ -0,0 +1,188 @@
{
"formatVersion": 1,
"database": {
"version": 2,
"identityHash": "d54a9ffbaa53dfe8f4ce8f5708a719ae",
"entities": [
{
"tableName": "profiles",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`ID` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `host` TEXT NOT NULL, `port` INTEGER NOT NULL, `username` TEXT NOT NULL, `password` TEXT NOT NULL, `securityType` INTEGER NOT NULL, `channelType` INTEGER NOT NULL, `colorLevel` INTEGER NOT NULL, `imageQuality` INTEGER NOT NULL, `useRawEncoding` INTEGER NOT NULL DEFAULT 0, `zoom1` REAL NOT NULL DEFAULT 1.0, `zoom2` REAL NOT NULL DEFAULT 1.0, `viewOnly` INTEGER NOT NULL, `useLocalCursor` INTEGER NOT NULL, `keyCompatMode` INTEGER NOT NULL, `gestureStyle` TEXT NOT NULL DEFAULT 'auto', `useRepeater` INTEGER NOT NULL, `idOnRepeater` INTEGER NOT NULL, `sshHost` TEXT NOT NULL, `sshPort` INTEGER NOT NULL, `sshUsername` TEXT NOT NULL, `sshAuthType` INTEGER NOT NULL, `sshPassword` TEXT NOT NULL, `sshPrivateKey` TEXT NOT NULL, `sshPrivateKeyPassword` TEXT NOT NULL)",
"fields": [
{
"fieldPath": "ID",
"columnName": "ID",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "name",
"columnName": "name",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "host",
"columnName": "host",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "port",
"columnName": "port",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "username",
"columnName": "username",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "password",
"columnName": "password",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "securityType",
"columnName": "securityType",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "channelType",
"columnName": "channelType",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "colorLevel",
"columnName": "colorLevel",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "imageQuality",
"columnName": "imageQuality",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "useRawEncoding",
"columnName": "useRawEncoding",
"affinity": "INTEGER",
"notNull": true,
"defaultValue": "0"
},
{
"fieldPath": "zoom1",
"columnName": "zoom1",
"affinity": "REAL",
"notNull": true,
"defaultValue": "1.0"
},
{
"fieldPath": "zoom2",
"columnName": "zoom2",
"affinity": "REAL",
"notNull": true,
"defaultValue": "1.0"
},
{
"fieldPath": "viewOnly",
"columnName": "viewOnly",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "useLocalCursor",
"columnName": "useLocalCursor",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "keyCompatMode",
"columnName": "keyCompatMode",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "gestureStyle",
"columnName": "gestureStyle",
"affinity": "TEXT",
"notNull": true,
"defaultValue": "'auto'"
},
{
"fieldPath": "useRepeater",
"columnName": "useRepeater",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "idOnRepeater",
"columnName": "idOnRepeater",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "sshHost",
"columnName": "sshHost",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "sshPort",
"columnName": "sshPort",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "sshUsername",
"columnName": "sshUsername",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "sshAuthType",
"columnName": "sshAuthType",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "sshPassword",
"columnName": "sshPassword",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "sshPrivateKey",
"columnName": "sshPrivateKey",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "sshPrivateKeyPassword",
"columnName": "sshPrivateKeyPassword",
"affinity": "TEXT",
"notNull": true
}
],
"primaryKey": {
"columnNames": [
"ID"
],
"autoGenerate": true
},
"indices": [],
"foreignKeys": []
}
],
"views": [],
"setupQueries": [
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'd54a9ffbaa53dfe8f4ce8f5708a719ae')"
]
}
}

View File

@@ -0,0 +1,209 @@
{
"formatVersion": 1,
"database": {
"version": 3,
"identityHash": "eb32c7692bb75a6297413b807713616c",
"entities": [
{
"tableName": "profiles",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`ID` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `host` TEXT NOT NULL, `port` INTEGER NOT NULL, `username` TEXT NOT NULL, `password` TEXT NOT NULL, `securityType` INTEGER NOT NULL, `channelType` INTEGER NOT NULL, `colorLevel` INTEGER NOT NULL, `imageQuality` INTEGER NOT NULL, `useRawEncoding` INTEGER NOT NULL DEFAULT 0, `zoom1` REAL NOT NULL DEFAULT 1.0, `zoom2` REAL NOT NULL DEFAULT 1.0, `viewOnly` INTEGER NOT NULL, `useLocalCursor` INTEGER NOT NULL, `serverTypeHint` TEXT NOT NULL DEFAULT '', `compatFlags` INTEGER NOT NULL, `gestureStyle` TEXT NOT NULL DEFAULT 'auto', `screenOrientation` TEXT NOT NULL DEFAULT 'auto', `shortcutRank` INTEGER NOT NULL DEFAULT 0, `useRepeater` INTEGER NOT NULL, `idOnRepeater` INTEGER NOT NULL, `sshHost` TEXT NOT NULL, `sshPort` INTEGER NOT NULL, `sshUsername` TEXT NOT NULL, `sshAuthType` INTEGER NOT NULL, `sshPassword` TEXT NOT NULL, `sshPrivateKey` TEXT NOT NULL, `sshPrivateKeyPassword` TEXT NOT NULL)",
"fields": [
{
"fieldPath": "ID",
"columnName": "ID",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "name",
"columnName": "name",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "host",
"columnName": "host",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "port",
"columnName": "port",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "username",
"columnName": "username",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "password",
"columnName": "password",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "securityType",
"columnName": "securityType",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "channelType",
"columnName": "channelType",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "colorLevel",
"columnName": "colorLevel",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "imageQuality",
"columnName": "imageQuality",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "useRawEncoding",
"columnName": "useRawEncoding",
"affinity": "INTEGER",
"notNull": true,
"defaultValue": "0"
},
{
"fieldPath": "zoom1",
"columnName": "zoom1",
"affinity": "REAL",
"notNull": true,
"defaultValue": "1.0"
},
{
"fieldPath": "zoom2",
"columnName": "zoom2",
"affinity": "REAL",
"notNull": true,
"defaultValue": "1.0"
},
{
"fieldPath": "viewOnly",
"columnName": "viewOnly",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "useLocalCursor",
"columnName": "useLocalCursor",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "serverTypeHint",
"columnName": "serverTypeHint",
"affinity": "TEXT",
"notNull": true,
"defaultValue": "''"
},
{
"fieldPath": "compatFlags",
"columnName": "compatFlags",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "gestureStyle",
"columnName": "gestureStyle",
"affinity": "TEXT",
"notNull": true,
"defaultValue": "'auto'"
},
{
"fieldPath": "screenOrientation",
"columnName": "screenOrientation",
"affinity": "TEXT",
"notNull": true,
"defaultValue": "'auto'"
},
{
"fieldPath": "shortcutRank",
"columnName": "shortcutRank",
"affinity": "INTEGER",
"notNull": true,
"defaultValue": "0"
},
{
"fieldPath": "useRepeater",
"columnName": "useRepeater",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "idOnRepeater",
"columnName": "idOnRepeater",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "sshHost",
"columnName": "sshHost",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "sshPort",
"columnName": "sshPort",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "sshUsername",
"columnName": "sshUsername",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "sshAuthType",
"columnName": "sshAuthType",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "sshPassword",
"columnName": "sshPassword",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "sshPrivateKey",
"columnName": "sshPrivateKey",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "sshPrivateKeyPassword",
"columnName": "sshPrivateKeyPassword",
"affinity": "TEXT",
"notNull": true
}
],
"primaryKey": {
"columnNames": [
"ID"
],
"autoGenerate": true
},
"indices": [],
"foreignKeys": []
}
],
"views": [],
"setupQueries": [
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'eb32c7692bb75a6297413b807713616c')"
]
}
}

View File

@@ -0,0 +1,216 @@
{
"formatVersion": 1,
"database": {
"version": 4,
"identityHash": "5ff9de8e52fb13b10ee86f9c75714cd5",
"entities": [
{
"tableName": "profiles",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`ID` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `host` TEXT NOT NULL, `port` INTEGER NOT NULL, `username` TEXT NOT NULL, `password` TEXT NOT NULL, `securityType` INTEGER NOT NULL, `channelType` INTEGER NOT NULL, `colorLevel` INTEGER NOT NULL, `imageQuality` INTEGER NOT NULL, `useRawEncoding` INTEGER NOT NULL DEFAULT 0, `zoom1` REAL NOT NULL DEFAULT 1.0, `zoom2` REAL NOT NULL DEFAULT 1.0, `viewOnly` INTEGER NOT NULL, `useLocalCursor` INTEGER NOT NULL, `serverTypeHint` TEXT NOT NULL DEFAULT '', `compatFlags` INTEGER NOT NULL, `gestureStyle` TEXT NOT NULL DEFAULT 'auto', `screenOrientation` TEXT NOT NULL DEFAULT 'auto', `shortcutRank` INTEGER NOT NULL DEFAULT 0, `useRepeater` INTEGER NOT NULL, `idOnRepeater` INTEGER NOT NULL, `resizeRemoteDesktop` INTEGER NOT NULL DEFAULT 0, `sshHost` TEXT NOT NULL, `sshPort` INTEGER NOT NULL, `sshUsername` TEXT NOT NULL, `sshAuthType` INTEGER NOT NULL, `sshPassword` TEXT NOT NULL, `sshPrivateKey` TEXT NOT NULL, `sshPrivateKeyPassword` TEXT NOT NULL)",
"fields": [
{
"fieldPath": "ID",
"columnName": "ID",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "name",
"columnName": "name",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "host",
"columnName": "host",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "port",
"columnName": "port",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "username",
"columnName": "username",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "password",
"columnName": "password",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "securityType",
"columnName": "securityType",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "channelType",
"columnName": "channelType",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "colorLevel",
"columnName": "colorLevel",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "imageQuality",
"columnName": "imageQuality",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "useRawEncoding",
"columnName": "useRawEncoding",
"affinity": "INTEGER",
"notNull": true,
"defaultValue": "0"
},
{
"fieldPath": "zoom1",
"columnName": "zoom1",
"affinity": "REAL",
"notNull": true,
"defaultValue": "1.0"
},
{
"fieldPath": "zoom2",
"columnName": "zoom2",
"affinity": "REAL",
"notNull": true,
"defaultValue": "1.0"
},
{
"fieldPath": "viewOnly",
"columnName": "viewOnly",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "useLocalCursor",
"columnName": "useLocalCursor",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "serverTypeHint",
"columnName": "serverTypeHint",
"affinity": "TEXT",
"notNull": true,
"defaultValue": "''"
},
{
"fieldPath": "compatFlags",
"columnName": "compatFlags",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "gestureStyle",
"columnName": "gestureStyle",
"affinity": "TEXT",
"notNull": true,
"defaultValue": "'auto'"
},
{
"fieldPath": "screenOrientation",
"columnName": "screenOrientation",
"affinity": "TEXT",
"notNull": true,
"defaultValue": "'auto'"
},
{
"fieldPath": "shortcutRank",
"columnName": "shortcutRank",
"affinity": "INTEGER",
"notNull": true,
"defaultValue": "0"
},
{
"fieldPath": "useRepeater",
"columnName": "useRepeater",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "idOnRepeater",
"columnName": "idOnRepeater",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "resizeRemoteDesktop",
"columnName": "resizeRemoteDesktop",
"affinity": "INTEGER",
"notNull": true,
"defaultValue": "0"
},
{
"fieldPath": "sshHost",
"columnName": "sshHost",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "sshPort",
"columnName": "sshPort",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "sshUsername",
"columnName": "sshUsername",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "sshAuthType",
"columnName": "sshAuthType",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "sshPassword",
"columnName": "sshPassword",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "sshPrivateKey",
"columnName": "sshPrivateKey",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "sshPrivateKeyPassword",
"columnName": "sshPrivateKeyPassword",
"affinity": "TEXT",
"notNull": true
}
],
"primaryKey": {
"columnNames": [
"ID"
],
"autoGenerate": true
},
"indices": [],
"foreignKeys": []
}
],
"views": [],
"setupQueries": [
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '5ff9de8e52fb13b10ee86f9c75714cd5')"
]
}
}

View File

@@ -0,0 +1,215 @@
{
"formatVersion": 1,
"database": {
"version": 5,
"identityHash": "8448d51fc9838e5760b91d4b5318ade2",
"entities": [
{
"tableName": "profiles",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`ID` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `host` TEXT NOT NULL, `port` INTEGER NOT NULL, `username` TEXT NOT NULL, `password` TEXT NOT NULL, `securityType` INTEGER NOT NULL, `channelType` INTEGER NOT NULL, `colorLevel` INTEGER NOT NULL, `imageQuality` INTEGER NOT NULL, `useRawEncoding` INTEGER NOT NULL DEFAULT 0, `zoom1` REAL NOT NULL DEFAULT 1.0, `zoom2` REAL NOT NULL DEFAULT 1.0, `viewOnly` INTEGER NOT NULL, `useLocalCursor` INTEGER NOT NULL, `serverTypeHint` TEXT NOT NULL DEFAULT '', `flags` INTEGER NOT NULL, `gestureStyle` TEXT NOT NULL DEFAULT 'auto', `screenOrientation` TEXT NOT NULL DEFAULT 'auto', `useCount` INTEGER NOT NULL, `useRepeater` INTEGER NOT NULL, `idOnRepeater` INTEGER NOT NULL, `resizeRemoteDesktop` INTEGER NOT NULL DEFAULT 0, `sshHost` TEXT NOT NULL, `sshPort` INTEGER NOT NULL, `sshUsername` TEXT NOT NULL, `sshAuthType` INTEGER NOT NULL, `sshPassword` TEXT NOT NULL, `sshPrivateKey` TEXT NOT NULL, `sshPrivateKeyPassword` TEXT NOT NULL)",
"fields": [
{
"fieldPath": "ID",
"columnName": "ID",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "name",
"columnName": "name",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "host",
"columnName": "host",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "port",
"columnName": "port",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "username",
"columnName": "username",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "password",
"columnName": "password",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "securityType",
"columnName": "securityType",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "channelType",
"columnName": "channelType",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "colorLevel",
"columnName": "colorLevel",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "imageQuality",
"columnName": "imageQuality",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "useRawEncoding",
"columnName": "useRawEncoding",
"affinity": "INTEGER",
"notNull": true,
"defaultValue": "0"
},
{
"fieldPath": "zoom1",
"columnName": "zoom1",
"affinity": "REAL",
"notNull": true,
"defaultValue": "1.0"
},
{
"fieldPath": "zoom2",
"columnName": "zoom2",
"affinity": "REAL",
"notNull": true,
"defaultValue": "1.0"
},
{
"fieldPath": "viewOnly",
"columnName": "viewOnly",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "useLocalCursor",
"columnName": "useLocalCursor",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "serverTypeHint",
"columnName": "serverTypeHint",
"affinity": "TEXT",
"notNull": true,
"defaultValue": "''"
},
{
"fieldPath": "flags",
"columnName": "flags",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "gestureStyle",
"columnName": "gestureStyle",
"affinity": "TEXT",
"notNull": true,
"defaultValue": "'auto'"
},
{
"fieldPath": "screenOrientation",
"columnName": "screenOrientation",
"affinity": "TEXT",
"notNull": true,
"defaultValue": "'auto'"
},
{
"fieldPath": "useCount",
"columnName": "useCount",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "useRepeater",
"columnName": "useRepeater",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "idOnRepeater",
"columnName": "idOnRepeater",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "resizeRemoteDesktop",
"columnName": "resizeRemoteDesktop",
"affinity": "INTEGER",
"notNull": true,
"defaultValue": "0"
},
{
"fieldPath": "sshHost",
"columnName": "sshHost",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "sshPort",
"columnName": "sshPort",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "sshUsername",
"columnName": "sshUsername",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "sshAuthType",
"columnName": "sshAuthType",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "sshPassword",
"columnName": "sshPassword",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "sshPrivateKey",
"columnName": "sshPrivateKey",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "sshPrivateKeyPassword",
"columnName": "sshPrivateKeyPassword",
"affinity": "TEXT",
"notNull": true
}
],
"primaryKey": {
"autoGenerate": true,
"columnNames": [
"ID"
]
},
"indices": [],
"foreignKeys": []
}
],
"views": [],
"setupQueries": [
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '8448d51fc9838e5760b91d4b5318ade2')"
]
}
}

View File

@@ -1,18 +1,34 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<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="${applicationName}"
android:name=".MainApplication"
android:icon="@mipmap/ic_launcher"
android:usesCleartextTraffic="true">
android:usesCleartextTraffic="true"
android:launchMode="singleInstance"
android:theme="@style/App.Theme">
<activity
android:name=".MainActivity"
android:exported="true"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:configChanges="navigation|orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<!-- Specifies an Android theme to apply to this Activity as soon as
@@ -28,6 +44,97 @@
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity android:name="com.example.tiny_computer.Signal9Activity" />
<activity-alias
android:name="com.gaurav.avnc.UriReceiverActivity"
android:targetActivity="com.gaurav.avnc.ui.vnc.IntentReceiverActivity">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="vnc" />
</intent-filter>
</activity-alias>
<activity
android:name="com.gaurav.avnc.ui.vnc.VncActivity"
android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation"
android:resizeableActivity="true"
android:supportsPictureInPicture="true"
tools:ignore="UnusedAttribute" />
<activity
android:name="com.gaurav.avnc.ui.vnc.IntentReceiverActivity"
android:theme="@style/App.SplashTheme.Dark" />
<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: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">
<!-- android:taskAffinity="com.termux.x11.MainActivity" -->
<!-- android:launchMode="singleInstance" -->
</activity>
<activity
android:name="com.termux.x11.XrActivity"
android:configChanges="density|orientation|screenSize|keyboard|keyboardHidden|uiMode"
android:exported="true"
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>
<!-- android:launchMode="singleTask" -->
</activity>
<activity
android:theme="@style/Theme.AppCompat.DayNight"
android:name="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>
<!-- android:excludeFromRecents="true" -->
<!-- android:taskAffinity="com.termux.x11.LoriePreferences" -->
</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"
android:exported="true"
android:grantUriPermissions="true"
android:permission="android.permission.MANAGE_DOCUMENTS">
<intent-filter>
<action android:name="android.content.action.DOCUMENTS_PROVIDER" />
</intent-filter>
</provider>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data

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

View File

@@ -0,0 +1,29 @@
The Modified (3-clause) BSD License
===================================
Copyright (C)2009-2021 D. R. Commander. All Rights Reserved.<br>
Copyright (C)2015 Viktor Szathmáry. 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 libjpeg-turbo Project 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 HOLDERS 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,674 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program 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 3 of the License, or
(at your option) any later version.
This program 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 program. If not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<https://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<https://www.gnu.org/licenses/why-not-lgpl.html>.

View File

@@ -0,0 +1,48 @@
/***********************************************************
Copyright 1987, 1994, 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.
Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts
All Rights Reserved
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the name of Digital not be
used in advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
SOFTWARE.
******************************************************************/

View File

@@ -0,0 +1,87 @@
Copyright (c) 2007-2008 Trilead AG (http://www.trilead.com)
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
a.) Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
b.) 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.
c.) Neither the name of Trilead 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 OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Trilead SSH-2 for Java includes code that was written by Dr. Christian Plattner
during his PhD at ETH Zurich. The license states the following:
Copyright (c) 2005 - 2006 Swiss Federal Institute of Technology (ETH Zurich),
Department of Computer Science (http://www.inf.ethz.ch),
Christian Plattner. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
a.) Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
b.) 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.
c.) Neither the name of ETH Zurich 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 OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
The Java implementations of the AES, Blowfish and 3DES ciphers have been
taken (and slightly modified) from the cryptography package released by
"The Legion Of The Bouncy Castle".
Their license states the following:
Copyright (c) 2000 - 2004 The Legion Of The Bouncy Castle
(http://www.bouncycastle.org)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

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,87 @@
/*
* Copyright (c) 2022 Gaurav Ujjwal.
*
* SPDX-License-Identifier: GPL-3.0-or-later
*
* See COPYING.txt for more details.
*/
#ifndef AVNC_CLIENTEX_H
#define AVNC_CLIENTEX_H
#include <jni.h>
#include "Cursor.h"
/**
* We attach some additional data to every rfbClient.
* ClientEx is used as wrapper for this data.
*/
struct ClientEx {
// Reference to managed `VncClient`
jobject managedClient;
// Although frame width & height are maintained in rfbClient, those values
// are modified before our MallocFrameBuffer callback is triggered, and
// we cannot protect them with a mutex. So we maintain the framebuffer
// size here, protected with fbMutex.
int fbRealWidth;
int fbRealHeight;
// Cursor data used for client-side cursor rendering
Cursor *cursor;
// Protects modification to framebuffer & cursor
MUTEX(mutex);
};
const int ClientExTag = 1;
ClientEx *getClientExtension(rfbClient *client) {
return (ClientEx *) rfbClientGetClientData(client, (void *) &ClientExTag);
}
void setClientExtension(rfbClient *client, ClientEx *ex) {
rfbClientSetClientData(client, (void *) &ClientExTag, ex);
}
/**
* Returns reference to managed `VncClient` associated with given rfbClient.
*/
jobject getManagedClient(rfbClient *client) {
return getClientExtension(client)->managedClient;
}
/**
* Associate given rfbClient & managed `VncClient`.
*/
void setManagedClient(rfbClient *client, jobject managedClient) {
getClientExtension(client)->managedClient = managedClient;
}
/**
* Create new ClientEx and assign it to given client.
*/
ClientEx *assignClientExtension(rfbClient *client) {
auto ex = (ClientEx *) malloc(sizeof(ClientEx));
if (ex) {
INIT_MUTEX(ex->mutex);
ex->cursor = nullptr;
setClientExtension(client, ex);
}
return ex;
}
/**
* Free all resources related to client extension.
*/
void freeClientExtension(rfbClient *client) {
auto ex = getClientExtension(client);
if (ex) {
TINI_MUTEX(ex->mutex);
freeCursor(ex->cursor);
free(ex);
setClientExtension(client, nullptr);
}
}
#endif //AVNC_CLIENTEX_H

View File

@@ -0,0 +1,111 @@
/*
* Copyright (c) 2022 Gaurav Ujjwal.
*
* SPDX-License-Identifier: GPL-3.0-or-later
*
* See COPYING.txt for more details.
*/
#ifndef AVNC_CURSOR_H
#define AVNC_CURSOR_H
/******************************************************************************
* Some servers (e.g TigerVNC) may not send the cursor immediately after
* connection. To provide consistent experience to users, we use a default
* cursor as fallback.
*****************************************************************************/
const uint16_t DefaultCursorWidth = 10;
const uint16_t DefaultCursorHeight = 16;
const uint16_t DefaultCursorXHot = 1;
const uint16_t DefaultCursorYHot = 1;
const uint32_t DefaultCursorBuffer[DefaultCursorWidth * DefaultCursorHeight]
= {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00FFFFFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00FFFFFF, 0x00FFFFFF, 0, 0, 0, 0,
0, 0, 0, 0, 0x00FFFFFF, 0x00FFFFFF, 0x00FFFFFF, 0, 0, 0, 0, 0, 0, 0, 0x00FFFFFF, 0x00FFFFFF, 0x00FFFFFF,
0x00FFFFFF, 0, 0, 0, 0, 0, 0, 0x00FFFFFF, 0x00FFFFFF, 0x00FFFFFF, 0x00FFFFFF, 0x00FFFFFF, 0, 0, 0, 0, 0,
0x00FFFFFF, 0x00FFFFFF, 0x00FFFFFF, 0x00FFFFFF, 0x00FFFFFF, 0x00FFFFFF, 0, 0, 0, 0, 0x00FFFFFF, 0x00FFFFFF,
0x00FFFFFF, 0x00FFFFFF, 0x00FFFFFF, 0x00FFFFFF, 0x00FFFFFF, 0, 0, 0, 0x00FFFFFF, 0x00FFFFFF, 0x00FFFFFF,
0x00FFFFFF, 0x00FFFFFF, 0x00FFFFFF, 0x00FFFFFF, 0x00FFFFFF, 0, 0, 0x00FFFFFF, 0x00FFFFFF, 0x00FFFFFF,
0x00FFFFFF, 0x00FFFFFF, 0, 0, 0, 0, 0, 0x00FFFFFF, 0x00FFFFFF, 0, 0x00FFFFFF, 0x00FFFFFF, 0, 0, 0, 0, 0,
0x00FFFFFF, 0, 0, 0, 0x00FFFFFF, 0x00FFFFFF, 0, 0, 0, 0, 0, 0, 0, 0, 0x00FFFFFF, 0x00FFFFFF, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0x00FFFFFF, 0x00FFFFFF, 0, 0, 0, 0, 0, 0, 0, 0, 0x00FFFFFF, 0x00FFFFFF, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0};
const uint8_t DefaultCursorMask[DefaultCursorWidth * DefaultCursorHeight]
= {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0,
0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1,
1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0,
0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0};
/******************************************************************************
* Cursor management
*****************************************************************************/
/**
* Wrapper for cursor information.
*
* rfbClient struct does not maintain all cursor related information inside it.
* Things like xHot, yHot are passed only via the cursor shape callback.
* This wrapper holds all information necessary to render the cursor.
*/
struct Cursor {
uint8_t *buffer;
uint8_t *mask;
uint8_t *scratchBuffer; //Used during rendering
uint16_t width;
uint16_t height;
uint16_t xHot;
uint16_t yHot;
};
//Only 4-byte pixels are currently supported
const uint8_t PixelBytes = 4;
/**
* Creates a new CursorData, initialized with default cursor info.
*/
Cursor *newCursor() {
auto cursor = (Cursor *) malloc(sizeof(Cursor));
if (cursor) {
cursor->buffer = (uint8_t *) DefaultCursorBuffer;
cursor->mask = (uint8_t *) DefaultCursorMask;
cursor->scratchBuffer = (uint8_t *) malloc(DefaultCursorWidth * DefaultCursorHeight * PixelBytes);
cursor->width = DefaultCursorWidth;
cursor->height = DefaultCursorHeight;
cursor->xHot = DefaultCursorXHot;
cursor->yHot = DefaultCursorYHot;
}
return cursor;
}
void freeCursorBuffers(Cursor *cursor) {
if (cursor) {
free(cursor->scratchBuffer);
if (cursor->buffer != (uint8_t *) DefaultCursorBuffer) free(cursor->buffer);
if (cursor->mask != (uint8_t *) DefaultCursorMask) free(cursor->mask);
}
}
void freeCursor(Cursor *cursor) {
freeCursorBuffers(cursor);
free(cursor);
}
void updateCursor(Cursor *cursor, uint8_t *buffer, uint8_t *mask, uint16_t width, uint16_t height,
uint16_t xHot, uint16_t yHot) {
freeCursorBuffers(cursor);
cursor->buffer = buffer;
cursor->mask = mask;
cursor->scratchBuffer = (uint8_t *) malloc(width * height * PixelBytes);
cursor->width = width;
cursor->height = height;
cursor->xHot = xHot;
cursor->yHot = yHot;
}
#endif //AVNC_CURSOR_H

View File

@@ -0,0 +1,94 @@
/*
* Copyright (c) 2022 Gaurav Ujjwal.
*
* SPDX-License-Identifier: GPL-3.0-or-later
*
* See COPYING.txt for more details.
*/
#ifndef AVNC_UTILITY_H
#define AVNC_UTILITY_H
#include <stdarg.h>
#include <netdb.h>
#include <errno.h>
#include <android/log.h>
/******************************************************************************
* Utilities
*****************************************************************************/
/**
* Returns a native copy of the given jstring.
* Caller is responsible for releasing the memory.
*/
static char *getNativeStrCopy(JNIEnv *env, jstring jStr) {
const char *cStr = env->GetStringUTFChars(jStr, nullptr);
char *str = strdup(cStr);
env->ReleaseStringUTFChars(jStr, cStr);
return str;
}
/******************************************************************************
* Logging
*****************************************************************************/
const char *LOG_TAG = "NativeVnc";
void log_info(const char *fmt, ...) {
va_list args;
va_start(args, fmt);
__android_log_vprint(ANDROID_LOG_INFO, LOG_TAG, fmt, args);
va_end(args);
}
void log_error(const char *fmt, ...) {
va_list args;
va_start(args, fmt);
__android_log_vprint(ANDROID_LOG_ERROR, LOG_TAG, fmt, args);
va_end(args);
}
/**
* Converts given errno value to its description.
*/
static const char *errnoToStr(int e) {
// LibVNC is patched to report `getaddrinfo` errors as negative 'errno'.
// See ConnectClientToTcpAddr6WithTimeout() in sockets.c
if (e < -1000) {
return gai_strerror((-e) - 1000);
}
switch (e) {
case ENETDOWN:
case ENETRESET:
case ENETUNREACH:
case ECONNABORTED:
case EHOSTDOWN:
case EHOSTUNREACH:
case ETIMEDOUT:
case ENOMEM:
case EPROTO:
case EIO:
return strerror(e);
case ECONNREFUSED:
return "Connection refused! Server may be down or running on different port";
case ECONNRESET:
return "Connection closed by server";
case EACCES:
return "Authentication failed";
default:
// In this case we don't want to display errno description to user
// because it is more likely to be misleading (e.g. EINTR, EAGAIN).
// BUT add it to logs in case LibVNC didn't.
log_error("errnoToStr: (%d %s)", errno, strerror(errno));
return "";
}
}
#endif //AVNC_UTILITY_H

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,561 @@
/*
* Copyright (c) 2020 Gaurav Ujjwal.
*
* SPDX-License-Identifier: GPL-3.0-or-later
*
* See COPYING.txt for more details.
*/
#include <jni.h>
#include <GLES2/gl2.h>
#include <rfb/rfbclient.h>
#include "ClientEx.h"
#include "Utility.h"
/******************************************************************************
* Library Initialization
*****************************************************************************/
struct JniContext {
JavaVM *vm; //JVM Instance
jclass managedCls; //Managed `VncClient` class
jmethodID cbFramebufferUpdated; //Cached reference to managed callback
JNIEnv *getEnv() const {
JNIEnv *env = nullptr;
if (vm != nullptr && vm->GetEnv((void **) &env, JNI_VERSION_1_6) == JNI_OK)
return env;
return nullptr; //Should not happen
}
};
static JniContext context{};
/**
* Called when our library is loaded.
*/
JNIEXPORT jint
JNI_OnLoad(JavaVM *vm, void *unused) {
context.vm = vm;
if (context.getEnv() == nullptr)
return JNI_ERR;
return JNI_VERSION_1_6;
}
JNIEXPORT void
JNI_OnUnload(JavaVM *vm, void *reserved) {
if (context.managedCls != nullptr)
context.getEnv()->DeleteGlobalRef(context.managedCls);
}
extern "C"
JNIEXPORT void JNICALL
Java_com_gaurav_avnc_vnc_VncClient_initLibrary(JNIEnv *env, jclass clazz) {
context.managedCls = (jclass) env->NewGlobalRef(clazz);
context.cbFramebufferUpdated = env->GetMethodID(clazz, "cbFinishedFrameBufferUpdate", "()V");
//TODO: Cache more method IDs so we don't have to repeatedly search them
rfbClientLog = &log_info;
rfbClientErr = &log_error;
}
/******************************************************************************
* rfbClient Callbacks
*****************************************************************************/
static char *onGetPassword(rfbClient *client) {
auto obj = getManagedClient(client);
auto env = context.getEnv();
auto cls = context.managedCls;
auto mid = env->GetMethodID(cls, "cbGetPassword", "()Ljava/lang/String;");
auto jPassword = (jstring) env->CallObjectMethod(obj, mid);
return getNativeStrCopy(env, jPassword);
}
static rfbCredential *onGetCredential(rfbClient *client, int credentialType) {
if (credentialType != rfbCredentialTypeUser) {
//Only user credentials (i.e. username & password) are currently supported
rfbClientErr("Unsupported credential type requested");
return nullptr;
}
auto obj = getManagedClient(client);
auto env = context.getEnv();
auto cls = context.managedCls;
//Retrieve credentials
jmethodID mid = env->GetMethodID(cls, "cbGetCredential",
"()Lcom/gaurav/avnc/vnc/UserCredential;");
jobject jCredential = env->CallObjectMethod(obj, mid);
if (jCredential == nullptr) {
return nullptr;
}
//Extract username & password
auto jCredentialCls = env->GetObjectClass(jCredential);
auto usernameField = env->GetFieldID(jCredentialCls, "username", "Ljava/lang/String;");
auto jUsername = env->GetObjectField(jCredential, usernameField);
auto passwordField = env->GetFieldID(jCredentialCls, "password", "Ljava/lang/String;");
auto jPassword = env->GetObjectField(jCredential, passwordField);
//Create native rfbCredential
auto credential = (rfbCredential *) malloc(sizeof(rfbCredential));
credential->userCredential.username = getNativeStrCopy(env, (jstring) jUsername);
credential->userCredential.password = getNativeStrCopy(env, (jstring) jPassword);
return credential;
}
static void onBell(rfbClient *client) {
auto obj = getManagedClient(client);
auto env = context.getEnv();
auto cls = context.managedCls;
jmethodID mid = env->GetMethodID(cls, "cbBell", "()V");
env->CallVoidMethod(obj, mid);
}
static void onGotXCutText(rfbClient *client, const char *text, int len, bool is_utf8) {
auto obj = getManagedClient(client);
auto env = context.getEnv();
auto cls = context.managedCls;
jmethodID mid = env->GetMethodID(cls, "cbGotXCutText", "([BZ)V");
jbyteArray bytes = env->NewByteArray(len);
env->SetByteArrayRegion(bytes, 0, len, reinterpret_cast<const jbyte *>(text));
env->CallVoidMethod(obj, mid, bytes, is_utf8);
}
static void onGotXCutTextLatin1(rfbClient *client, const char *text, int len) {
onGotXCutText(client, text, len, false);
}
static void onGotXCutTextUTF8(rfbClient *client, const char *text, int len) {
onGotXCutText(client, text, len, true);
}
static rfbBool onHandleCursorPos(rfbClient *client, int x, int y) {
auto obj = getManagedClient(client);
auto env = context.getEnv();
auto cls = context.managedCls;
jmethodID mid = env->GetMethodID(cls, "cbHandleCursorPos", "(II)V");
env->CallVoidMethod(obj, mid, x, y);
return TRUE;
}
static void onFinishedFrameBufferUpdate(rfbClient *client) {
auto obj = getManagedClient(client);
auto env = context.getEnv();
env->CallVoidMethod(obj, context.cbFramebufferUpdated);
}
/**
* We need to use our own allocator to know when frame size has changed.
* and to acquire framebuffer lock during modification.
*/
static rfbBool onMallocFrameBuffer(rfbClient *client) {
const auto width = client->width;
const auto height = client->height;
const auto requestedSize = (uint64_t) width * height * client->format.bitsPerPixel / 8;
if (requestedSize >= SIZE_MAX) {
rfbClientErr("CRITICAL: cannot allocate frameBuffer, requested size is too large\n");
return FALSE;
}
auto allocSize = (size_t) requestedSize;
auto ex = getClientExtension(client);
LOCK(ex->mutex);
{
if (client->frameBuffer)
free(client->frameBuffer);
client->frameBuffer = static_cast<uint8_t *>(malloc(allocSize));
if (client->frameBuffer) {
ex->fbRealWidth = width;
ex->fbRealHeight = height;
memset(client->frameBuffer, 0, allocSize); //Clear any garbage
} else {
ex->fbRealWidth = 0;
ex->fbRealHeight = 0;
}
}
UNLOCK(ex->mutex);
if (client->frameBuffer == nullptr) {
rfbClientErr("CRITICAL: frameBuffer allocation failed\n");
return FALSE;
}
auto obj = getManagedClient(client);
auto env = context.getEnv();
auto cls = context.managedCls;
auto mid = env->GetMethodID(cls, "cbFramebufferSizeChanged", "(II)V");
env->CallVoidMethod(obj, mid, width, height);
return TRUE;
}
static void onGotCursorShape(rfbClient *client, int xHot, int yHot, int width, int height, int bytesPerPixel) {
auto ex = getClientExtension(client);
LOCK(ex->mutex);
//Steel buffers from rfbClient
updateCursor(ex->cursor, client->rcSource, client->rcMask, (uint16_t) width, (uint16_t) height,
(uint16_t) xHot, (uint16_t) yHot);
client->rcSource = NULL;
client->rcMask = NULL;
UNLOCK(ex->mutex);
//Fake framebuffer update to trigger rendering
onFinishedFrameBufferUpdate(client);
}
/**
* Hooks callbacks to rfbClient.
*/
static void setCallbacks(rfbClient *client) {
client->GetPassword = onGetPassword;
client->GetCredential = onGetCredential;
client->Bell = onBell;
client->GotXCutText = onGotXCutTextLatin1;
client->GotXCutTextUTF8 = onGotXCutTextUTF8;
client->HandleCursorPos = onHandleCursorPos;
client->FinishedFrameBufferUpdate = onFinishedFrameBufferUpdate;
client->MallocFrameBuffer = onMallocFrameBuffer;
client->GotCursorShape = onGotCursorShape;
}
/******************************************************************************
* Native method Implementation
*****************************************************************************/
extern "C"
JNIEXPORT jlong JNICALL
Java_com_gaurav_avnc_vnc_VncClient_nativeClientCreate(JNIEnv *env, jobject thiz) {
rfbClient *client = rfbGetClient(8, 3, 4);
if (client == nullptr)
return 0;
if (!assignClientExtension(client))
return 0;
setCallbacks(client);
client->canHandleNewFBSize = TRUE;
//Attach reference to managed object
auto obj = env->NewGlobalRef(thiz);
setManagedClient(client, obj);
return (jlong) client;
}
extern "C"
JNIEXPORT void JNICALL
Java_com_gaurav_avnc_vnc_VncClient_nativeConfigure(JNIEnv *env, jobject thiz, jlong client_ptr,
jint securityType, jboolean use_local_cursor, jint image_quality,
jboolean use_raw_encoding) {
auto client = (rfbClient *) client_ptr;
// 0 means all auth types
if (securityType != 0) {
uint32_t auth[1] = {static_cast<uint32_t>(securityType)};
SetClientAuthSchemes(client, auth, 1);
}
if (use_local_cursor) {
client->appData.useRemoteCursor = TRUE;
getClientExtension(client)->cursor = newCursor();
}
client->appData.qualityLevel = image_quality;
if (use_raw_encoding)
client->appData.encodingsString = "raw";
}
extern "C"
JNIEXPORT void JNICALL
Java_com_gaurav_avnc_vnc_VncClient_nativeSetDest(JNIEnv *env, jobject thiz, jlong client_ptr,
jstring host, jint port) {
auto client = (rfbClient *) client_ptr;
client->destHost = getNativeStrCopy(env, host);
client->destPort = port;
}
extern "C"
JNIEXPORT jboolean JNICALL
Java_com_gaurav_avnc_vnc_VncClient_nativeInit(JNIEnv *env, jobject thiz, jlong client_ptr,
jstring host, jint port) {
auto client = (rfbClient *) client_ptr;
client->serverHost = getNativeStrCopy(env, host);
client->serverPort = port < 100 ? port + 5900 : port;
if (rfbInitClient(client, nullptr, nullptr)) {
return JNI_TRUE;
}
return JNI_FALSE;
}
extern "C"
JNIEXPORT jboolean JNICALL
Java_com_gaurav_avnc_vnc_VncClient_nativeIsServerMacOS(JNIEnv *env, jobject thiz, jlong client_ptr) {
auto client = (rfbClient *) client_ptr;
return client->serverMajor == 3 && client->serverMinor == 889;
}
extern "C"
JNIEXPORT void JNICALL
Java_com_gaurav_avnc_vnc_VncClient_nativeCleanup(JNIEnv *env, jobject thiz,
jlong client_ptr) {
auto client = (rfbClient *) client_ptr;
if (client->frameBuffer) {
free(client->frameBuffer);
client->frameBuffer = nullptr;
}
auto managedClient = getManagedClient(client);
env->DeleteGlobalRef(managedClient);
freeClientExtension(client);
rfbClientCleanup(client);
}
extern "C"
JNIEXPORT jboolean JNICALL
Java_com_gaurav_avnc_vnc_VncClient_nativeProcessServerMessage(JNIEnv *env, jobject thiz,
jlong client_ptr,
jint u_sec_timeout) {
auto client = (rfbClient *) client_ptr;
auto waitResult = WaitForMessage(client, static_cast<unsigned int>(u_sec_timeout));
if (waitResult == 0) // Timeout
return JNI_TRUE;
if (waitResult > 0 && HandleRFBServerMessage(client))
return JNI_TRUE;
return JNI_FALSE;
}
extern "C"
JNIEXPORT jstring JNICALL
Java_com_gaurav_avnc_vnc_VncClient_nativeGetLastErrorStr(JNIEnv *env, jobject thiz) {
auto str = errnoToStr(errno);
return env->NewStringUTF(str);
}
extern "C"
JNIEXPORT jboolean JNICALL
Java_com_gaurav_avnc_vnc_VncClient_nativeSendKeyEvent(JNIEnv *env, jobject thiz, jlong client_ptr,
jint key_sym, jint xt_code, jboolean is_down) {
auto client = (rfbClient *) client_ptr;
rfbBool down = is_down ? TRUE : FALSE;
if (xt_code > 0 && SendExtendedKeyEvent(client, key_sym, xt_code, down))
return JNI_TRUE;
else
return SendKeyEvent(client, key_sym, down);
}
extern "C"
JNIEXPORT jboolean JNICALL
Java_com_gaurav_avnc_vnc_VncClient_nativeSendPointerEvent(JNIEnv *env, jobject thiz, jlong client_ptr, jint x, jint y,
jint mask) {
return (jboolean) SendPointerEvent((rfbClient *) client_ptr, x, y, mask);
}
extern "C"
JNIEXPORT jboolean JNICALL
Java_com_gaurav_avnc_vnc_VncClient_nativeSendCutText(JNIEnv *env, jobject thiz, jlong client_ptr, jbyteArray bytes,
jboolean is_utf8) {
auto client = (rfbClient *) client_ptr;
auto textBuffer = env->GetByteArrayElements(bytes, nullptr);
auto textLen = env->GetArrayLength(bytes);
auto textChars = reinterpret_cast<char *>(textBuffer);
rfbBool result = is_utf8
? SendClientCutTextUTF8(client, textChars, textLen)
: SendClientCutText(client, textChars, textLen);
env->ReleaseByteArrayElements(bytes, textBuffer, JNI_ABORT);
return (jboolean) result;
}
extern "C"
JNIEXPORT jboolean JNICALL
Java_com_gaurav_avnc_vnc_VncClient_nativeIsUTF8CutTextSupported(JNIEnv *env, jobject thiz, jlong client_ptr) {
return (jboolean) (((rfbClient *) client_ptr)->extendedClipboardServerCapabilities != 0);
}
extern "C"
JNIEXPORT jboolean JNICALL
Java_com_gaurav_avnc_vnc_VncClient_nativeSetDesktopSize(JNIEnv *env, jobject thiz, jlong client_ptr, jint width,
jint height) {
return (jboolean) SendExtDesktopSize((rfbClient *) client_ptr, width, height);
}
extern "C"
JNIEXPORT jboolean JNICALL
Java_com_gaurav_avnc_vnc_VncClient_nativeRefreshFrameBuffer(JNIEnv *env, jobject thiz, jlong clientPtr) {
auto client = (rfbClient *) clientPtr;
return (jboolean) SendFramebufferUpdateRequest(client, 0, 0, client->width, client->height, TRUE);
}
extern "C"
JNIEXPORT void JNICALL
Java_com_gaurav_avnc_vnc_VncClient_nativeSetAutomaticFramebufferUpdates(JNIEnv *env, jobject thiz, jlong client_ptr,
jboolean enabled) {
auto client = ((rfbClient *) client_ptr);
client->automaticUpdateRequests = enabled ? TRUE : FALSE;
if (enabled) SendIncrementalFramebufferUpdateRequest(client);
}
extern "C"
JNIEXPORT jstring JNICALL
Java_com_gaurav_avnc_vnc_VncClient_nativeGetDesktopName(JNIEnv *env, jobject thiz, jlong client_ptr) {
auto client = (rfbClient *) client_ptr;
return env->NewStringUTF(client->desktopName ? client->desktopName : "");
}
extern "C"
JNIEXPORT jint JNICALL
Java_com_gaurav_avnc_vnc_VncClient_nativeGetWidth(JNIEnv *env, jobject thiz, jlong client_ptr) {
return ((rfbClient *) client_ptr)->width;
}
extern "C"
JNIEXPORT jint JNICALL
Java_com_gaurav_avnc_vnc_VncClient_nativeGetHeight(JNIEnv *env, jobject thiz, jlong client_ptr) {
return ((rfbClient *) client_ptr)->height;
}
extern "C"
JNIEXPORT jboolean JNICALL
Java_com_gaurav_avnc_vnc_VncClient_nativeIsEncrypted(JNIEnv *env, jobject thiz, jlong client_ptr) {
return static_cast<jboolean>(((rfbClient *) client_ptr)->tlsSession ? JNI_TRUE : JNI_FALSE);
}
extern "C"
JNIEXPORT void JNICALL
Java_com_gaurav_avnc_vnc_VncClient_nativeUploadFrameTexture(JNIEnv *env, jobject thiz,
jlong client_ptr) {
auto client = (rfbClient *) client_ptr;
auto ex = getClientExtension(client);
LOCK(ex->mutex);
if (client->frameBuffer) {
glTexImage2D(GL_TEXTURE_2D,
0,
GL_RGBA,
ex->fbRealWidth,
ex->fbRealHeight,
0,
GL_RGBA,
GL_UNSIGNED_BYTE,
client->frameBuffer);
}
UNLOCK(ex->mutex);
}
extern "C"
JNIEXPORT void JNICALL
Java_com_gaurav_avnc_vnc_VncClient_nativeUploadCursor(JNIEnv *env, jobject thiz, jlong client_ptr, jint px, jint py) {
auto client = (rfbClient *) client_ptr;
auto ex = getClientExtension(client);
auto cursor = ex->cursor;
if (!cursor)
return;
//Current algo for cursor rendering is slightly weird. Main issue is that
//glTexSubImage2D() does not perform any composition with target texture.
//So, we have to manually blend transparent/invalid pixels of the cursor
//with corresponding pixels from framebuffer. scratchBuffer is used for
//this composition.
LOCK(ex->mutex);
//Effective cursor position in framebuffer
int32_t fbCursorX = px - cursor->xHot;
int32_t fbCursorY = py - cursor->yHot;
//Rectangular portion of the framebuffer to be updated.
//Cursor can overflow outside the framebuffer if moved near the edges,
//but glTexSubImage2D() doesn't allow values outside target texture,
//so we need to only update the intersection of framebuffer & cursor.
int32_t left = -1, top = -1, right = -1, bottom = -1;
auto fb = (uint32_t *) client->frameBuffer;
auto buffer = (uint32_t *) cursor->buffer;
auto scratch = (uint32_t *) cursor->scratchBuffer;
auto mask = cursor->mask;
//Scratch buffer index
int32_t z = 0;
for (int32_t y = 0; y < cursor->height; ++y) {
for (int32_t x = 0; x < cursor->width; ++x) {
//Corresponding pixel in framebuffer
auto fbX = fbCursorX + x;
auto fbY = fbCursorY + y;
if (fbX >= 0 && fbX < ex->fbRealWidth && fbY >= 0 && fbY < ex->fbRealHeight) {
auto isValidPixel = mask[y * cursor->width + x];
if (isValidPixel)
scratch[z++] = buffer[y * cursor->width + x];
else
scratch[z++] = fb[fbY * ex->fbRealWidth + fbX];
if (left == -1 && top == -1) {
left = fbX;
top = fbY;
}
right = fbX;
bottom = fbY;
}
}
}
if (left >= 0 && top >= 0)
glTexSubImage2D(GL_TEXTURE_2D,
0,
left,
top,
right - left + 1,
bottom - top + 1,
GL_RGBA,
GL_UNSIGNED_BYTE,
scratch);
UNLOCK(ex->mutex);
}

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,270 @@
package com.example.tiny_computer.filepicker;
import android.annotation.TargetApi;
import android.content.res.AssetFileDescriptor;
import android.database.Cursor;
import android.database.MatrixCursor;
import android.graphics.Point;
import android.os.Build;
import android.os.CancellationSignal;
import android.os.ParcelFileDescriptor;
import android.provider.DocumentsContract.Document;
import android.provider.DocumentsContract.Root;
import android.provider.DocumentsProvider;
import android.webkit.MimeTypeMap;
import com.example.tiny_computer.R;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Collections;
import java.util.LinkedList;
//This file is mainly copied from Termux :P
/**
* A document provider for the Storage Access Framework which exposes the files in the
* $HOME/ directory to other apps.
* <p/>
* Note that this replaces providing an activity matching the ACTION_GET_CONTENT intent:
* <p/>
* "A document provider and ACTION_GET_CONTENT should be considered mutually exclusive. If you
* support both of them simultaneously, your app will appear twice in the system picker UI,
* offering two different ways of accessing your stored data. This would be confusing for users."
* - http://developer.android.com/guide/topics/providers/document-provider.html#43
*/
public class TinyDocumentsProvider extends DocumentsProvider {
private static final String ALL_MIME_TYPES = "*/*";
// The default columns to return information about a root if no specific
// columns are requested in a query.
private static final String[] DEFAULT_ROOT_PROJECTION = new String[]{
Root.COLUMN_ROOT_ID,
Root.COLUMN_MIME_TYPES,
Root.COLUMN_FLAGS,
Root.COLUMN_ICON,
Root.COLUMN_TITLE,
Root.COLUMN_SUMMARY,
Root.COLUMN_DOCUMENT_ID,
Root.COLUMN_AVAILABLE_BYTES
};
// The default columns to return information about a document if no specific
// columns are requested in a query.
private static final String[] DEFAULT_DOCUMENT_PROJECTION = new String[]{
Document.COLUMN_DOCUMENT_ID,
Document.COLUMN_MIME_TYPE,
Document.COLUMN_DISPLAY_NAME,
Document.COLUMN_LAST_MODIFIED,
Document.COLUMN_FLAGS,
Document.COLUMN_SIZE
};
@Override
public Cursor queryRoots(String[] projection) {
final MatrixCursor result = new MatrixCursor(projection != null ? projection : DEFAULT_ROOT_PROJECTION);
final String applicationName = "小小电脑";
final File BASE_DIR = new File(getContext().getFilesDir(), "containers");
final MatrixCursor.RowBuilder row = result.newRow();
row.add(Root.COLUMN_ROOT_ID, getDocIdForFile(BASE_DIR));
row.add(Root.COLUMN_DOCUMENT_ID, getDocIdForFile(BASE_DIR));
row.add(Root.COLUMN_SUMMARY, null);
row.add(Root.COLUMN_FLAGS, Root.FLAG_SUPPORTS_CREATE | Root.FLAG_SUPPORTS_SEARCH | Root.FLAG_SUPPORTS_IS_CHILD);
row.add(Root.COLUMN_TITLE, applicationName);
row.add(Root.COLUMN_MIME_TYPES, ALL_MIME_TYPES);
row.add(Root.COLUMN_AVAILABLE_BYTES, BASE_DIR.getFreeSpace());
row.add(Root.COLUMN_ICON, R.mipmap.ic_launcher);
return result;
}
@Override
public Cursor queryDocument(String documentId, String[] projection) throws FileNotFoundException {
final MatrixCursor result = new MatrixCursor(projection != null ? projection : DEFAULT_DOCUMENT_PROJECTION);
includeFile(result, documentId, null);
return result;
}
@Override
public Cursor queryChildDocuments(String parentDocumentId, String[] projection, String sortOrder) throws FileNotFoundException {
final MatrixCursor result = new MatrixCursor(projection != null ? projection : DEFAULT_DOCUMENT_PROJECTION);
final File parent = getFileForDocId(parentDocumentId);
for (File file : parent.listFiles()) {
includeFile(result, null, file);
}
return result;
}
@Override
public ParcelFileDescriptor openDocument(final String documentId, String mode, CancellationSignal signal) throws FileNotFoundException {
final File file = getFileForDocId(documentId);
final int accessMode = ParcelFileDescriptor.parseMode(mode);
return ParcelFileDescriptor.open(file, accessMode);
}
@Override
public AssetFileDescriptor openDocumentThumbnail(String documentId, Point sizeHint, CancellationSignal signal) throws FileNotFoundException {
final File file = getFileForDocId(documentId);
final ParcelFileDescriptor pfd = ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
return new AssetFileDescriptor(pfd, 0, file.length());
}
@Override
public boolean onCreate() {
return true;
}
@Override
public String createDocument(String parentDocumentId, String mimeType, String displayName) throws FileNotFoundException {
File newFile = new File(parentDocumentId, displayName);
int noConflictId = 2;
while (newFile.exists()) {
newFile = new File(parentDocumentId, displayName + " (" + noConflictId++ + ")");
}
try {
boolean succeeded;
if (Document.MIME_TYPE_DIR.equals(mimeType)) {
succeeded = newFile.mkdir();
} else {
succeeded = newFile.createNewFile();
}
if (!succeeded) {
throw new FileNotFoundException("Failed to create document with id " + newFile.getPath());
}
} catch (IOException e) {
throw new FileNotFoundException("Failed to create document with id " + newFile.getPath());
}
return newFile.getPath();
}
@Override
public void deleteDocument(String documentId) throws FileNotFoundException {
File file = getFileForDocId(documentId);
if (!file.delete()) {
throw new FileNotFoundException("Failed to delete document with id " + documentId);
}
}
@Override
public String getDocumentType(String documentId) throws FileNotFoundException {
File file = getFileForDocId(documentId);
return getMimeType(file);
}
@Override
public Cursor querySearchDocuments(String rootId, String query, String[] projection) throws FileNotFoundException {
final MatrixCursor result = new MatrixCursor(projection != null ? projection : DEFAULT_DOCUMENT_PROJECTION);
final File parent = getFileForDocId(rootId);
// This example implementation searches file names for the query and doesn't rank search
// results, so we can stop as soon as we find a sufficient number of matches. Other
// implementations might rank results and use other data about files, rather than the file
// name, to produce a match.
final LinkedList<File> pending = new LinkedList<>();
pending.add(parent);
final int MAX_SEARCH_RESULTS = 50;
while (!pending.isEmpty() && result.getCount() < MAX_SEARCH_RESULTS) {
final File file = pending.removeFirst();
// Avoid directories outside the $HOME directory linked with symlinks (to avoid e.g. search
// through the whole SD card).
boolean isInsideHome;
try {
isInsideHome = file.getCanonicalPath().startsWith(new File(getContext().getFilesDir(), "containers").getAbsolutePath());
} catch (IOException e) {
isInsideHome = true;
}
if (isInsideHome) {
if (file.isDirectory()) {
Collections.addAll(pending, file.listFiles());
} else {
if (file.getName().toLowerCase().contains(query)) {
includeFile(result, null, file);
}
}
}
}
return result;
}
@Override
public boolean isChildDocument(String parentDocumentId, String documentId) {
return documentId.startsWith(parentDocumentId);
}
/**
* Get the document id given a file. This document id must be consistent across time as other
* applications may save the ID and use it to reference documents later.
* <p/>
* The reverse of @{link #getFileForDocId}.
*/
private static String getDocIdForFile(File file) {
return file.getAbsolutePath();
}
/**
* Get the file given a document id (the reverse of {@link #getDocIdForFile(File)}).
*/
private static File getFileForDocId(String docId) throws FileNotFoundException {
final File f = new File(docId);
if (!f.exists()) throw new FileNotFoundException(f.getAbsolutePath() + " not found");
return f;
}
private static String getMimeType(File file) {
if (file.isDirectory()) {
return Document.MIME_TYPE_DIR;
} else {
final String name = file.getName();
final int lastDot = name.lastIndexOf('.');
if (lastDot >= 0) {
final String extension = name.substring(lastDot + 1).toLowerCase();
final String mime = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
if (mime != null) return mime;
}
return "application/octet-stream";
}
}
/**
* Add a representation of a file to a cursor.
*
* @param result the cursor to modify
* @param docId the document ID representing the desired file (may be null if given file)
* @param file the File object representing the desired file (may be null if given docID)
*/
private void includeFile(MatrixCursor result, String docId, File file)
throws FileNotFoundException {
if (docId == null) {
docId = getDocIdForFile(file);
} else {
file = getFileForDocId(docId);
}
int flags = 0;
if (file.isDirectory()) {
if (file.canWrite()) flags |= Document.FLAG_DIR_SUPPORTS_CREATE;
} else if (file.canWrite()) {
flags |= Document.FLAG_SUPPORTS_WRITE;
}
if (file.getParentFile().canWrite()) flags |= Document.FLAG_SUPPORTS_DELETE;
final String displayName = file.getName();
final String mimeType = getMimeType(file);
if (mimeType.startsWith("image/")) flags |= Document.FLAG_SUPPORTS_THUMBNAIL;
final MatrixCursor.RowBuilder row = result.newRow();
row.add(Document.COLUMN_DOCUMENT_ID, docId);
row.add(Document.COLUMN_DISPLAY_NAME, displayName);
row.add(Document.COLUMN_SIZE, file.length());
row.add(Document.COLUMN_MIME_TYPE, mimeType);
row.add(Document.COLUMN_LAST_MODIFIED, file.lastModified());
row.add(Document.COLUMN_FLAGS, flags);
row.add(Document.COLUMN_ICON, R.mipmap.ic_launcher);
}
}

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 = 7897;
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,830 @@
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);
// }
private String[] getArrayItems(int resourceId, Resources resources) {
ArrayList<String> itemList = new ArrayList<>();
TypedArray typedArray = resources.obtainTypedArray(resourceId);
try {
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)));
}
}
} finally {
typedArray.recycle();
}
return itemList.toArray(new String[0]);
}
}
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 = 7897;
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;
}
}

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