Failed attempt to use the GL1 renderer with GL4ES

just turning into too much hassle, but going to keep this branch in case I want to come back to it
This commit is contained in:
Simon 2022-03-23 20:14:37 +00:00
parent 2500ffe780
commit 538a7021d0
17 changed files with 4135 additions and 105 deletions

View file

@ -33,7 +33,7 @@ ifndef BUILD_MISSIONPACK
BUILD_MISSIONPACK=
endif
ifndef BUILD_RENDERER_OPENGL2
BUILD_RENDERER_OPENGL2=
BUILD_RENDERER_OPENGL2=0
endif
ifndef BUILD_AUTOUPDATER # DON'T build unless you mean to!
BUILD_AUTOUPDATER=0
@ -466,6 +466,10 @@ ifeq ($(PLATFORM),android)
RENDERER_LIBS += $(LIBSDIR)/android/arm64-v8a/libSDL2.so
CLIENT_EXTRA_FILES += $(LIBSDIR)/android/arm64-v8a/libSDL2.so
# GL4ES
# CLIENT_LIBS += $(LIBSDIR)/android/arm64-v8a/libgl4es.so
CLIENT_EXTRA_FILES += $(LIBSDIR)/android/arm64-v8a/libgl4es.so
# VrApi
BASE_CFLAGS += -I$(VRAPIDIR)/Include
CLIENT_LIBS += $(VRAPIDIR)/Libs/Android/arm64-v8a/Release/libvrapi.so
@ -1166,6 +1170,8 @@ ifeq ($(USE_MUMBLE),1)
CLIENT_CFLAGS += -DUSE_MUMBLE
endif
CLIENT_CFLAGS += -DHAVE_GLES
ifeq ($(USE_INTERNAL_ZLIB),1)
ZLIB_CFLAGS = -DNO_GZIP -I$(ZDIR)
else
@ -1932,8 +1938,7 @@ Q3ROBJ = \
$(B)/renderergl1/tr_surface.o \
$(B)/renderergl1/tr_world.o \
\
$(B)/renderergl1/sdl_gamma.o \
$(B)/renderergl1/sdl_glimp.o
$(B)/renderergl1/android_glimp.o
ifneq ($(USE_RENDERER_DLOPEN), 0)
Q3ROBJ += \
@ -2791,6 +2796,9 @@ $(B)/renderergl1/%.o: $(RGL1DIR)/%.c
$(B)/renderergl1/tr_altivec.o: $(RGL1DIR)/tr_altivec.c
$(DO_REF_CC_ALTIVEC)
$(B)/renderergl1/android_glimp.o: $(ANDROIDDIR)/android_glimp.c
$(DO_REF_CC_ALTIVEC)
$(B)/renderergl2/glsl/%.c: $(RGL2DIR)/glsl/%.glsl
$(DO_REF_STR)

3175
Makefile.bkup Normal file

File diff suppressed because it is too large Load diff

View file

@ -2,8 +2,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.drbeef.ioq3quest"
android:installLocation="preferExternal"
android:versionCode="39"
android:versionName="0.26.2">
android:versionCode="41"
android:versionName="0.27.1">
<uses-feature android:name="android.hardware.vr.headtracking" android:version="1" android:required="true" />
<uses-feature android:glEsVersion="0x00030001" />
<!-- <uses-feature android:name="oculus.software.overlay_keyboard" android:required="false"/>-->
@ -19,7 +19,8 @@
android:fullBackupContent="false"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:hasCode="true">
android:hasCode="true"
android:extractNativeLibs="true">
<meta-data android:name="com.samsung.android.vr.application.mode" android:value="vr_only"/>
<meta-data android:name="com.oculus.supportedDevices" android:value="quest|quest2"/>
<meta-data android:name="com.oculus.ossplash" android:value="true"/>

View file

@ -13,7 +13,8 @@ if(CMAKE_BUILD_TYPE MATCHES "Debug")
SET(BUILD_FOLDER debug-android-aarch64)
endif()
add_custom_target(copy_libs
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/../../../../../build/${BUILD_FOLDER}/libioquake3_opengl2.so ${CMAKE_SOURCE_DIR}/../jniLibs/arm64-v8a/libioquake3_opengl2.so
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/../../../../../build/${BUILD_FOLDER}/libioquake3.so ${CMAKE_SOURCE_DIR}/../jniLibs/arm64-v8a/libioquake3.so
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/../../../../../build/${BUILD_FOLDER}/libgl4es.so ${CMAKE_SOURCE_DIR}/../jniLibs/arm64-v8a/libgl4es.so
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/../../../../../build/${BUILD_FOLDER}/libSDL2.so ${CMAKE_SOURCE_DIR}/../jniLibs/arm64-v8a/libSDL2.so
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/../../../../../build/${BUILD_FOLDER}/libvrapi.so ${CMAKE_SOURCE_DIR}/../jniLibs/arm64-v8a/libvrapi.so
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/../../../../../build/${BUILD_FOLDER}/baseq3/cgameaarch64.so ${CMAKE_SOURCE_DIR}/../jniLibs/arm64-v8a/libcgameaarch64_baseq3.so
@ -38,7 +39,7 @@ find_library(log-lib log)
target_link_libraries(main
android
ioquake3_opengl2
ioquake3
SDL2
vrapi
${log-lib})

View file

@ -0,0 +1,703 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code 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.
RTCW SP Source Code 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 RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
/*
** GLW_IMP.C
**
** This file contains ALL Linux specific stuff having to do with the
** OpenGL refresh. When a port is being made the following functions
** must be implemented by the port:
**
** GLimp_EndFrame
** GLimp_Init
** GLimp_Shutdown
** GLimp_SwitchFullscreen
** GLimp_SetGamma
**
*/
#include <termios.h>
#include <sys/ioctl.h>
#ifdef __linux__
#include <sys/stat.h>
#include <sys/vt.h>
#endif
#include <stdarg.h>
#include <stdio.h>
#include <signal.h>
#include <pthread.h>
#include <semaphore.h>
// bk001204
#include <dlfcn.h>
// bk001206 - from my Heretic2 by way of Ryan's Fakk2
// Needed for the new X11_PendingInput() function.
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include "../renderergl1/tr_local.h"
#include "../client/client.h"
#include "android_local.h" // bk001130
#include "EGL/egl.h"
#define WINDOW_CLASS_NAME "Return to Castle Wolfenstein"
typedef enum
{
RSERR_OK,
RSERR_INVALID_FULLSCREEN,
RSERR_INVALID_MODE,
RSERR_UNKNOWN
} rserr_t;
void myglMultiTexCoord2f( GLenum texture, GLfloat s, GLfloat t )
{
glMultiTexCoord4f(texture, s, t, 0, 1);
}
static cvar_t *in_mouse;
static cvar_t *in_dgamouse;
// bk001130 - from cvs1.17 (mkv), but not static
cvar_t *in_joystick = NULL;
cvar_t *in_joystickDebug = NULL;
cvar_t *joy_threshold = NULL;
cvar_t *r_allowSoftwareGL; // don't abort out if the pixelformat claims software
cvar_t *r_previousglDriver;
//static int default_dotclock_vidmode; // bk001204 - unused
static int num_vidmodes;
static qboolean vidmode_active = qfalse;
void IN_ActivateMouse( void ) {
}
void IN_DeactivateMouse( void ) {
}
/*****************************************************************************/
static qboolean signalcaught = qfalse;;
void Sys_Exit( int ); // bk010104 - abstraction
static void signal_handler( int sig ) { // bk010104 - replace this... (NOTE TTimo huh?)
if ( signalcaught ) {
printf( "DOUBLE SIGNAL FAULT: Received signal %d, exiting...\n", sig );
Sys_Exit( 1 ); // bk010104 - abstraction
}
signalcaught = qtrue;
printf( "Received signal %d, exiting...\n", sig );
GLimp_Shutdown(); // bk010104 - shouldn't this be CL_Shutdown
Sys_Exit( 0 ); // bk010104 - abstraction NOTE TTimo send a 0 to avoid DOUBLE SIGNAL FAULT
}
static void InitSig( void ) {
return;
signal( SIGHUP, signal_handler );
signal( SIGQUIT, signal_handler );
signal( SIGILL, signal_handler );
signal( SIGTRAP, signal_handler );
signal( SIGIOT, signal_handler );
signal( SIGBUS, signal_handler );
signal( SIGFPE, signal_handler );
signal( SIGSEGV, signal_handler );
signal( SIGTERM, signal_handler );
}
/*
** GLimp_SetGamma
**
** This routine should only be called if glConfig.deviceSupportsGamma is TRUE
*/
void GLimp_SetGamma( unsigned char red[256], unsigned char green[256], unsigned char blue[256] ) {
}
/*
** GLimp_Shutdown
**
** This routine does all OS specific shutdown procedures for the OpenGL
** subsystem. Under OpenGL this means NULLing out the current DC and
** HGLRC, deleting the rendering context, and releasing the DC acquired
** for the window. The state structure is also nulled out.
**
*/
void GLimp_Shutdown( void ) {
memset( &glConfig, 0, sizeof( glConfig ) );
memset( &glState, 0, sizeof( glState ) );
QGL_Shutdown();
}
/*
** GLimp_LogComment
*/
void GLimp_LogComment( char *comment ) {
}
/*
** GLW_StartDriverAndSetMode
*/
// bk001204 - prototype needed
int GLW_SetMode( const char *drivername, int mode, qboolean fullscreen );
static qboolean GLW_StartDriverAndSetMode( const char *drivername,
int mode,
qboolean fullscreen ) {
rserr_t err;
// don't ever bother going into fullscreen with a voodoo card
#if 1 // JDC: I reenabled this
if ( Q_stristr( drivername, "Voodoo" ) ) {
ri.Cvar_Set( "r_fullscreen", "0" );
r_fullscreen->modified = qfalse;
fullscreen = qfalse;
}
#endif
err = GLW_SetMode( drivername, mode, fullscreen );
switch ( err )
{
case RSERR_INVALID_FULLSCREEN:
ri.Printf( PRINT_ALL, "...WARNING: fullscreen unavailable in this mode\n" );
return qfalse;
case RSERR_INVALID_MODE:
ri.Printf( PRINT_ALL, "...WARNING: could not set the given mode (%d)\n", mode );
return qfalse;
default:
break;
}
return qtrue;
}
void RTCWVR_GetScreenRes(int *width, int *height);
/*
** GLW_InitExtensions
*/
static void GLW_InitExtensions( void ) {
if ( !r_allowExtensions->integer ) {
ri.Printf( PRINT_ALL, "*** IGNORING OPENGL EXTENSIONS ***\n" );
return;
}
ri.Printf( PRINT_ALL, "Initializing OpenGL extensions\n" );
#ifndef HAVE_GLES
// GL_S3_s3tc
if ( Q_stristr( glConfig.extensions_string, "GL_S3_s3tc" ) ) {
if ( r_ext_compressed_textures->value ) {
glConfig.textureCompression = TC_S3TC;
ri.Printf( PRINT_ALL, "...using GL_S3_s3tc\n" );
} else
{
glConfig.textureCompression = TC_NONE;
ri.Printf( PRINT_ALL, "...ignoring GL_S3_s3tc\n" );
}
} else
#endif
{
glConfig.textureCompression = TC_NONE;
ri.Printf( PRINT_ALL, "...GL_S3_s3tc not found\n" );
}
// GL_EXT_texture_env_add
#ifdef HAVE_GLES
glConfig.textureEnvAddAvailable = qtrue;
ri.Printf( PRINT_ALL, "...using GL_EXT_texture_env_add\n" );
#else
glConfig.textureEnvAddAvailable = qfalse;
if ( Q_stristr( glConfig.extensions_string, "EXT_texture_env_add" ) ) {
if ( r_ext_texture_env_add->integer ) {
glConfig.textureEnvAddAvailable = qtrue;
ri.Printf( PRINT_ALL, "...using GL_EXT_texture_env_add\n" );
} else
{
glConfig.textureEnvAddAvailable = qfalse;
ri.Printf( PRINT_ALL, "...ignoring GL_EXT_texture_env_add\n" );
}
} else
{
ri.Printf( PRINT_ALL, "...GL_EXT_texture_env_add not found\n" );
}
#endif
// GL_ARB_multitexture
qglMultiTexCoord2fARB = NULL;
qglActiveTextureARB = NULL;
qglClientActiveTextureARB = NULL;
#ifdef HAVE_GLES
qglGetIntegerv( GL_MAX_TEXTURE_UNITS, &glConfig.maxActiveTextures );
//ri.Printf( PRINT_ALL, "...not using GL_ARB_multitexture, %i texture units\n", glConfig.maxActiveTextures );
//glConfig.maxActiveTextures=4;
qglMultiTexCoord2fARB = myglMultiTexCoord2f;
qglActiveTextureARB = glActiveTexture;
qglClientActiveTextureARB = glClientActiveTexture;
if ( glConfig.maxActiveTextures > 1 )
{
ri.Printf( PRINT_ALL, "...using GL_ARB_multitexture (%i texture units)\n", glConfig.maxActiveTextures );
}
else
{
qglMultiTexCoord2fARB = NULL;
qglActiveTextureARB = NULL;
qglClientActiveTextureARB = NULL;
ri.Printf( PRINT_ALL, "...not using GL_ARB_multitexture, < 2 texture units\n" );
}
#else
if ( Q_stristr( glConfig.extensions_string, "GL_ARB_multitexture" ) ) {
if ( r_ext_multitexture->value ) {
qglMultiTexCoord2fARB = ( PFNGLMULTITEXCOORD2FARBPROC ) dlsym( glw_state.OpenGLLib, "glMultiTexCoord2fARB" );
qglActiveTextureARB = ( PFNGLACTIVETEXTUREARBPROC ) dlsym( glw_state.OpenGLLib, "glActiveTextureARB" );
qglClientActiveTextureARB = ( PFNGLCLIENTACTIVETEXTUREARBPROC ) dlsym( glw_state.OpenGLLib, "glClientActiveTextureARB" );
if ( qglActiveTextureARB ) {
qglGetIntegerv( GL_MAX_ACTIVE_TEXTURES_ARB, &glConfig.maxActiveTextures );
if ( glConfig.maxActiveTextures > 1 ) {
ri.Printf( PRINT_ALL, "...using GL_ARB_multitexture\n" );
} else
{
qglMultiTexCoord2fARB = NULL;
qglActiveTextureARB = NULL;
qglClientActiveTextureARB = NULL;
ri.Printf( PRINT_ALL, "...not using GL_ARB_multitexture, < 2 texture units\n" );
}
}
} else
{
ri.Printf( PRINT_ALL, "...ignoring GL_ARB_multitexture\n" );
}
} else
{
ri.Printf( PRINT_ALL, "...GL_ARB_multitexture not found\n" );
}
#endif
// GL_EXT_compiled_vertex_array
#ifndef HAVE_GLES
if ( Q_stristr( glConfig.extensions_string, "GL_EXT_compiled_vertex_array" ) ) {
if ( r_ext_compiled_vertex_array->value ) {
ri.Printf( PRINT_ALL, "...using GL_EXT_compiled_vertex_array\n" );
qglLockArraysEXT = ( void ( APIENTRY * )( int, int ) )dlsym( glw_state.OpenGLLib, "glLockArraysEXT" );
qglUnlockArraysEXT = ( void ( APIENTRY * )( void ) )dlsym( glw_state.OpenGLLib, "glUnlockArraysEXT" );
if ( !qglLockArraysEXT || !qglUnlockArraysEXT ) {
ri.Error( ERR_FATAL, "bad getprocaddress" );
}
} else
{
ri.Printf( PRINT_ALL, "...ignoring GL_EXT_compiled_vertex_array\n" );
}
} else
#endif
{
ri.Printf( PRINT_ALL, "...GL_EXT_compiled_vertex_array not found\n" );
}
// GL_NV_fog_distance
#ifndef HAVE_GLES
if ( Q_stristr( glConfig.extensions_string, "GL_NV_fog_distance" ) ) {
if ( r_ext_NV_fog_dist->integer ) {
glConfig.NVFogAvailable = qtrue;
ri.Printf( PRINT_ALL, "...using GL_NV_fog_distance\n" );
} else {
ri.Printf( PRINT_ALL, "...ignoring GL_NV_fog_distance\n" );
ri.Cvar_Set( "r_ext_NV_fog_dist", "0" );
}
} else
#endif
{
ri.Printf( PRINT_ALL, "...GL_NV_fog_distance not found\n" );
ri.Cvar_Set( "r_ext_NV_fog_dist", "0" );
}
}
static void GLW_InitGamma() {
glConfig.deviceSupportsGamma = qfalse;
}
/*
** GLW_LoadOpenGL
**
** GLimp_win.c internal function that that attempts to load and use
** a specific OpenGL DLL.
*/
static qboolean GLW_LoadOpenGL( const char *name ) {
qboolean fullscreen;
ri.Printf( PRINT_ALL, "...loading %s: ", name );
#ifndef HAVE_GLES
// disable the 3Dfx splash screen and set gamma
// we do this all the time, but it shouldn't hurt anything
// on non-3Dfx stuff
putenv( "FX_GLIDE_NO_SPLASH=0" );
// Mesa VooDoo hacks
putenv( "MESA_GLX_FX=fullscreen\n" );
#endif
// load the QGL layer
if ( QGL_Init( name ) ) {
#ifdef PANDORA
fullscreen = 1;
#else
fullscreen = r_fullscreen->integer;
#endif
// create the window and set up the context
if ( !GLW_StartDriverAndSetMode( name, r_mode->integer, fullscreen ) ) {
if ( r_mode->integer != 3 ) {
if ( !GLW_StartDriverAndSetMode( name, 3, fullscreen ) ) {
goto fail;
}
} else {
goto fail;
}
}
return qtrue;
} else
{
ri.Printf( PRINT_ALL, "failed\n" );
}
fail:
QGL_Shutdown();
return qfalse;
}
/*
** GLimp_Init
**
** This routine is responsible for initializing the OS specific portions
** of OpenGL.
*/
void GLimp_Init( void ) {
qboolean attemptedlibGL = qfalse;
qboolean attempted3Dfx = qfalse;
qboolean success = qfalse;
char buf[1024];
cvar_t *lastValidRenderer = ri.Cvar_Get( "r_lastValidRenderer", "(uninitialized)", CVAR_ARCHIVE );
// cvar_t *cv; // bk001204 - unused
r_allowSoftwareGL = ri.Cvar_Get( "r_allowSoftwareGL", "0", CVAR_LATCH );
r_previousglDriver = ri.Cvar_Get( "r_previousglDriver", "", CVAR_ROM );
InitSig();
// Hack here so that if the UI
if ( *r_previousglDriver->string ) {
// The UI changed it on us, hack it back
// This means the renderer can't be changed on the fly
ri.Cvar_Set( "r_glDriver", r_previousglDriver->string );
}
int android_screen_width;
int android_screen_height;
RTCWVR_GetScreenRes(&android_screen_width, &android_screen_height);
glConfig.vidWidth = android_screen_width;
glConfig.vidHeight = android_screen_height;
glConfig.colorBits = 32;
glConfig.depthBits = 16;
glConfig.stencilBits = 8;
// Save it in case the UI stomps it
ri.Cvar_Set( "r_previousglDriver", r_glDriver->string );
// This values force the UI to disable driver selection
glConfig.driverType = GLDRV_ICD;
glConfig.hardwareType = GLHW_GENERIC;
// get our config strings
Q_strncpyz( glConfig.vendor_string, qglGetString( GL_VENDOR ), sizeof( glConfig.vendor_string ) );
Q_strncpyz( glConfig.renderer_string, qglGetString( GL_RENDERER ), sizeof( glConfig.renderer_string ) );
if ( *glConfig.renderer_string && glConfig.renderer_string[strlen( glConfig.renderer_string ) - 1] == '\n' ) {
glConfig.renderer_string[strlen( glConfig.renderer_string ) - 1] = 0;
}
Q_strncpyz( glConfig.version_string, qglGetString( GL_VERSION ), sizeof( glConfig.version_string ) );
Q_strncpyz( glConfig.extensions_string, qglGetString( GL_EXTENSIONS ), sizeof( glConfig.extensions_string ) );
//
// chipset specific configuration
//
strcpy( buf, glConfig.renderer_string );
strlwr( buf );
//
// NOTE: if changing cvars, do it within this block. This allows them
// to be overridden when testing driver fixes, etc. but only sets
// them to their default state when the hardware is first installed/run.
//
/*if ( Q_stricmp( lastValidRenderer->string, glConfig.renderer_string ) ) {
glConfig.hardwareType = GLHW_GENERIC;
ri.Cvar_Set( "r_textureMode", "GL_LINEAR_MIPMAP_LINEAR" );
// VOODOO GRAPHICS w/ 2MB
if ( Q_stristr( buf, "voodoo graphics/1 tmu/2 mb" ) ) {
ri.Cvar_Set( "r_picmip", "2" );
ri.Cvar_Get( "r_picmip", "1", CVAR_ARCHIVE | CVAR_LATCH );
} else
{
ri.Cvar_Set( "r_picmip", "1" );
if ( Q_stristr( buf, "rage 128" ) || Q_stristr( buf, "rage128" ) ) {
ri.Cvar_Set( "r_finish", "0" );
}
// Savage3D and Savage4 should always have trilinear enabled
else if ( Q_stristr( buf, "savage3d" ) || Q_stristr( buf, "s3 savage4" ) ) {
ri.Cvar_Set( "r_texturemode", "GL_LINEAR_MIPMAP_LINEAR" );
}
}
}*/
//
// this is where hardware specific workarounds that should be
// detected/initialized every startup should go.
//
if ( Q_stristr( buf, "banshee" ) || Q_stristr( buf, "Voodoo_Graphics" ) ) {
glConfig.hardwareType = GLHW_3DFX_2D3D;
} else if ( Q_stristr( buf, "rage pro" ) || Q_stristr( buf, "RagePro" ) ) {
glConfig.hardwareType = GLHW_RAGEPRO;
} else if ( Q_stristr( buf, "permedia2" ) ) {
glConfig.hardwareType = GLHW_PERMEDIA2;
} else if ( Q_stristr( buf, "riva 128" ) ) {
glConfig.hardwareType = GLHW_RIVA128;
} else if ( Q_stristr( buf, "riva tnt " ) ) {
}
ri.Cvar_Set( "r_lastValidRenderer", glConfig.renderer_string );
//TEST!!!
//ri.Cvar_Set( "r_picmip", "0" );
//ri.Cvar_Set( "r_texturemode", "GL_LINEAR_MIPMAP_LINEAR" );
//!!!!
// initialize extensions
GLW_InitExtensions();
GLW_InitGamma();
InitSig();
return;
}
void RTCWVR_submitFrame();
//int androidSwapped = 1; //If loading, then draw frame does not return, so detect this
/*
** GLimp_EndFrame
**
** Responsible for doing a swapbuffers and possibly for other stuff
** as yet to be determined. Probably better not to make this a GLimp
** function and instead do a call to GLimp_SwapBuffers.
*/
void GLimp_EndFrame( void ) {
// check logging
//QGL_EnableLogging( (qboolean)r_logFile->integer ); // bk001205 - was ->value
// if (!androidSwapped)
// eglSwapBuffers( eglGetCurrentDisplay(), eglGetCurrentSurface( EGL_DRAW ) );
//androidSwapped = 0;
RTCWVR_submitFrame();
}
#ifdef SMP
/*
===========================================================
SMP acceleration
===========================================================
*/
sem_t renderCommandsEvent;
sem_t renderCompletedEvent;
sem_t renderActiveEvent;
void ( *glimpRenderThread )( void );
void *GLimp_RenderThreadWrapper( void *stub ) {
glimpRenderThread();
return NULL;
}
/*
=======================
GLimp_SpawnRenderThread
=======================
*/
pthread_t renderThreadHandle;
qboolean GLimp_SpawnRenderThread( void ( *function )( void ) ) {
sem_init( &renderCommandsEvent, 0, 0 );
sem_init( &renderCompletedEvent, 0, 0 );
sem_init( &renderActiveEvent, 0, 0 );
glimpRenderThread = function;
if ( pthread_create( &renderThreadHandle, NULL,
GLimp_RenderThreadWrapper, NULL ) ) {
return qfalse;
}
return qtrue;
}
static void *smpData;
//static int glXErrors; // bk001204 - unused
void *GLimp_RendererSleep( void ) {
void *data;
// after this, the front end can exit GLimp_FrontEndSleep
sem_post( &renderCompletedEvent );
sem_wait( &renderCommandsEvent );
data = smpData;
// after this, the main thread can exit GLimp_WakeRenderer
sem_post( &renderActiveEvent );
return data;
}
void GLimp_FrontEndSleep( void ) {
sem_wait( &renderCompletedEvent );
}
void GLimp_WakeRenderer( void *data ) {
smpData = data;
// after this, the renderer can continue through GLimp_RendererSleep
sem_post( &renderCommandsEvent );
sem_wait( &renderActiveEvent );
}
#else
void GLimp_RenderThreadWrapper( void *stub ) {}
qboolean GLimp_SpawnRenderThread( void ( *function )( void ) ) {
return qfalse;
}
void *GLimp_RendererSleep( void ) {
return NULL;
}
void GLimp_FrontEndSleep( void ) {}
void GLimp_WakeRenderer( void *data ) {}
#endif
/*****************************************************************************/
/* MOUSE */
/*****************************************************************************/
void IN_Init( void *windowData ) {
// mouse variables
in_mouse = Cvar_Get( "in_mouse", "1", CVAR_ARCHIVE );
in_dgamouse = Cvar_Get( "in_dgamouse", "1", CVAR_ARCHIVE );
}
void IN_Shutdown( void ) {
}
/*
void IN_Frame( void ) {
if ( cls.keyCatchers & KEYCATCH_CONSOLE ) {
// temporarily deactivate if not in the game and
// running on the desktop
// voodoo always counts as full screen
if ( Cvar_VariableValue( "r_fullscreen" ) == 0
&& strcmp( Cvar_VariableString( "r_glDriver" ), _3DFX_DRIVER_NAME ) ) {
IN_DeactivateMouse();
return;
}
}
IN_ActivateMouse();
}
*/
void IN_Activate( void ) {
}
// bk001130 - cvs1.17 joystick code (mkv) was here, no linux_joystick.c
void Sys_SendKeyEvents( void ) {
// XEvent event; // bk001204 - unused
//HandleEvents();
}
// bk010216 - added stubs for non-Linux UNIXes here
// FIXME - use NO_JOYSTICK or something else generic
#if defined( __FreeBSD__ ) // rb010123
void IN_StartupJoystick( void ) {}
void IN_JoyMove( void ) {}
#endif

View file

@ -0,0 +1,57 @@
/*
===========================================================================
Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
RTCW SP Source Code 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.
RTCW SP Source Code 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 RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
// linux_local.h: Linux-specific Quake3 header file
void Sys_QueEvent( int time, sysEventType_t type, int value, int value2, int ptrLength, void *ptr );
qboolean Sys_GetPacket( netadr_t *net_from, msg_t *net_message );
void Sys_SendKeyEvents( void );
// Input subsystem
void IN_Init( void *windowData );
void IN_Frame( void );
void IN_Shutdown( void );
void IN_JoyMove( void );
void IN_StartupJoystick( void );
// GL subsystem
qboolean QGL_Init( const char *dllname );
void QGL_EnableLogging( qboolean enable );
void QGL_Shutdown( void );
// bk001130 - win32
// void IN_JoystickCommands (void);
char *strlwr( char *s );

View file

@ -35,6 +35,10 @@ void ( * qglUnlockArraysEXT) ( void );
void GLimp_EndFrame( void ) {
}
void GLimp_BindFramebuffer(int buffer) {
}
void GLimp_Init( void ) {
}

View file

@ -159,6 +159,8 @@ IMPLEMENTATION SPECIFIC FUNCTIONS
void GLimp_Init( qboolean fixedFunction );
void GLimp_Shutdown( void );
void GLimp_EndFrame( void );
void GLimp_BindFramebuffer(int buffer);
void GLimp_LogComment( char *comment );
void GLimp_Minimize(void);

View file

@ -937,6 +937,10 @@ const void *RB_DrawBuffer( const void *data ) {
cmd = (const drawBufferCommand_t *)data;
// finish any 2D drawing if needed
if(tess.numIndexes)
RB_EndSurface();
qglDrawBuffer( cmd->buffer );
// clear screen for debugging
@ -1098,6 +1102,25 @@ const void *RB_SwapBuffers( const void *data ) {
return (const void *)(cmd + 1);
}
/*
====================
RB_SwitchEye
====================
*/
const void* RB_SwitchEye( const void* data ) {
const switchEyeCommand_t *cmd = data;
// finish any 2D drawing if needed
if(tess.numIndexes)
RB_EndSurface();
GLimp_BindFramebuffer(cmd->eye);
tr.refdef.stereoFrame = cmd->stereoFrame;
return (const void*)(cmd + 1);
}
/*
====================
RB_ExecuteRenderCommands
@ -1139,8 +1162,15 @@ void RB_ExecuteRenderCommands( const void *data ) {
case RC_CLEARDEPTH:
data = RB_ClearDepth(data);
break;
case RC_SWITCH_EYE:
data = RB_SwitchEye(data);
break;
case RC_END_OF_LIST:
default:
// finish any 2D drawing if needed
if(tess.numIndexes)
RB_EndSurface();
// stop rendering
t2 = ri.Milliseconds ();
backEnd.pc.msec = t2 - t1;

View file

@ -365,15 +365,24 @@ void RE_BeginFrame( stereoFrame_t stereoFrame ) {
}
if (glConfig.stereoEnabled) {
if( !(cmd = R_GetCommandBuffer(sizeof(*cmd))) )
return;
cmd->commandId = RC_DRAW_BUFFER;
if ( stereoFrame == STEREO_LEFT ) {
cmd->buffer = (int)GL_BACK_LEFT;
if (tr.vrParms.valid == qtrue) {
switchEyeCommand_t* sec;
if (!(sec = R_GetCommandBuffer(sizeof(*sec))))
return;
sec->commandId = RC_SWITCH_EYE;
sec->eye = tr.vrParms.renderBufferL;
sec->stereoFrame = stereoFrame;
}
} else if ( stereoFrame == STEREO_RIGHT ) {
cmd->buffer = (int)GL_BACK_RIGHT;
if (tr.vrParms.valid == qtrue) {
switchEyeCommand_t* sec;
if (!(sec = R_GetCommandBuffer(sizeof(*sec))))
return;
sec->commandId = RC_SWITCH_EYE;
sec->eye = tr.vrParms.renderBufferR;
sec->stereoFrame = stereoFrame;
}
} else {
ri.Error( ERR_FATAL, "RE_BeginFrame: Stereo is enabled, but stereoFrame was %i", stereoFrame );
}
@ -485,6 +494,25 @@ void RE_EndFrame( int *frontEndMsec, int *backEndMsec ) {
backEnd.pc.msec = 0;
}
//#if __ANDROID__
void R_Mat4Transpose( const float in[4][4], float* out ) {
int i, j;
for (i = 0; i < 4; ++i) {
for (j = 0; j < 4; ++j) {
out[i * 4 + j] = in[j][i];
}
}
}
void RE_SetVRHeadsetParms( const ovrMatrix4f *projectionMatrix,
int renderBufferL, int renderBufferR ) {
R_Mat4Transpose(projectionMatrix->M, tr.vrParms.projection);
tr.vrParms.renderBufferL = renderBufferL;
tr.vrParms.renderBufferR = renderBufferR;
tr.vrParms.valid = qtrue;
}
//#endif
/*
=============
RE_TakeVideoFrame

View file

@ -70,6 +70,7 @@ cvar_t *r_measureOverdraw;
cvar_t *r_inGameVideo;
cvar_t *r_fastsky;
cvar_t *vr_thirdPersonSpectator;
cvar_t *r_drawSun;
cvar_t *r_dynamiclight;
cvar_t *r_dlightBacks;
@ -177,6 +178,7 @@ int max_polyverts;
** setting variables, checking GL constants, and reporting the gfx system config
** to the user.
*/
void VR_ReInitRenderer();
static void InitOpenGL( void )
{
//
@ -209,6 +211,8 @@ static void InitOpenGL( void )
// set default state
GL_SetDefaultState();
VR_ReInitRenderer();
}
/*
@ -1039,7 +1043,7 @@ void R_Register( void )
ri.Cvar_CheckRange( r_ext_multisample, 0, 4, qtrue );
r_overBrightBits = ri.Cvar_Get ("r_overBrightBits", "1", CVAR_ARCHIVE | CVAR_LATCH );
r_ignorehwgamma = ri.Cvar_Get( "r_ignorehwgamma", "0", CVAR_ARCHIVE | CVAR_LATCH);
r_mode = ri.Cvar_Get( "r_mode", "3", CVAR_ARCHIVE | CVAR_LATCH );
r_mode = ri.Cvar_Get( "r_mode", "-2", CVAR_ARCHIVE | CVAR_LATCH );
r_fullscreen = ri.Cvar_Get( "r_fullscreen", "1", CVAR_ARCHIVE );
r_noborder = ri.Cvar_Get("r_noborder", "0", CVAR_ARCHIVE | CVAR_LATCH);
r_customwidth = ri.Cvar_Get( "r_customwidth", "1600", CVAR_ARCHIVE | CVAR_LATCH );
@ -1076,6 +1080,7 @@ void R_Register( void )
r_stereoSeparation = ri.Cvar_Get( "r_stereoSeparation", "64", CVAR_ARCHIVE );
r_ignoreGLErrors = ri.Cvar_Get( "r_ignoreGLErrors", "1", CVAR_ARCHIVE );
r_fastsky = ri.Cvar_Get( "r_fastsky", "0", CVAR_ARCHIVE );
vr_thirdPersonSpectator = ri.Cvar_Get( "vr_thirdPersonSpectator", "0", CVAR_TEMP );
r_inGameVideo = ri.Cvar_Get( "r_inGameVideo", "1", CVAR_ARCHIVE );
r_drawSun = ri.Cvar_Get( "r_drawSun", "0", CVAR_ARCHIVE );
r_dynamiclight = ri.Cvar_Get( "r_dynamiclight", "0", CVAR_ARCHIVE );
@ -1124,7 +1129,7 @@ void R_Register( void )
r_norefresh = ri.Cvar_Get ("r_norefresh", "0", CVAR_CHEAT);
r_drawentities = ri.Cvar_Get ("r_drawentities", "1", CVAR_CHEAT );
r_ignore = ri.Cvar_Get( "r_ignore", "1", CVAR_CHEAT );
r_nocull = ri.Cvar_Get ("r_nocull", "0", CVAR_CHEAT);
r_nocull = ri.Cvar_Get ("r_nocull", "1", CVAR_CHEAT);
r_novis = ri.Cvar_Get ("r_novis", "0", CVAR_CHEAT);
r_showcluster = ri.Cvar_Get ("r_showcluster", "0", CVAR_CHEAT);
r_speeds = ri.Cvar_Get ("r_speeds", "0", CVAR_CHEAT);
@ -1359,6 +1364,10 @@ refexport_t *GetRefAPI ( int apiVersion, refimport_t *rimp ) {
re.BeginFrame = RE_BeginFrame;
re.EndFrame = RE_EndFrame;
#if __ANDROID__
re.SetVRHeadsetParms = RE_SetVRHeadsetParms;
#endif
re.MarkFragments = R_MarkFragments;
re.LerpTag = R_LerpTag;
re.ModelBounds = R_ModelBounds;

View file

@ -469,6 +469,13 @@ typedef struct {
stereoFrame_t stereoFrame;
} viewParms_t;
typedef struct {
qboolean valid;
float projection[16];
int renderBufferL;
int renderBufferR;
int renderBufferOriginal;
} vrParms_t;
/*
==============================================================================
@ -927,6 +934,7 @@ typedef struct {
model_t *currentModel;
viewParms_t viewParms;
vrParms_t vrParms;
float identityLight; // 1.0 / ( 1 << overbrightBits )
int identityLightByte; // identityLight * 255
@ -1548,6 +1556,12 @@ typedef struct
int commandId;
} clearDepthCommand_t;
typedef struct {
int commandId;
int eye;
stereoFrame_t stereoFrame;
} switchEyeCommand_t;
typedef enum {
RC_END_OF_LIST,
RC_SET_COLOR,
@ -1558,7 +1572,8 @@ typedef enum {
RC_SCREENSHOT,
RC_VIDEOFRAME,
RC_COLORMASK,
RC_CLEARDEPTH
RC_CLEARDEPTH,
RC_SWITCH_EYE
} renderCommand_t;
@ -1597,6 +1612,10 @@ void RE_StretchPic ( float x, float y, float w, float h,
float s1, float t1, float s2, float t2, qhandle_t hShader );
void RE_BeginFrame( stereoFrame_t stereoFrame );
void RE_EndFrame( int *frontEndMsec, int *backEndMsec );
#if __ANDROID__
void RE_SetVRHeadsetParms( const ovrMatrix4f *projectionMatrix,
int renderBufferL, int renderBufferR );
#endif
void RE_SaveJPG(char * filename, int quality, int image_width, int image_height,
unsigned char *image_buffer, int padding);
size_t RE_SaveJPGToBuffer(byte *buffer, size_t bufSize, int quality,

View file

@ -446,62 +446,38 @@ static void R_SetFarClip( void )
=================
R_SetupFrustum
Set up the culling frustum planes for the current view using the results we got from computing the first two rows of
the projection matrix.
Setup that culling frustum planes for the current view
=================
*/
void R_SetupFrustum (viewParms_t *dest, float xmin, float xmax, float ymax, float zProj, float stereoSep)
{
vec3_t ofsorigin;
float oppleg, adjleg, length;
void R_SetupFrustum( void ) {
int i;
float xs, xc;
float ang;
if(stereoSep == 0 && xmin == -xmax)
{
// symmetric case can be simplified
VectorCopy(dest->or.origin, ofsorigin);
ang = tr.viewParms.fovX / 180 * M_PI * 0.5f;
xs = sinf( ang );
xc = cosf( ang );
length = sqrt(xmax * xmax + zProj * zProj);
oppleg = xmax / length;
adjleg = zProj / length;
VectorScale( tr.viewParms.or.axis[0], xs, tr.viewParms.frustum[0].normal );
VectorMA( tr.viewParms.frustum[0].normal, xc, tr.viewParms.or.axis[1], tr.viewParms.frustum[0].normal );
VectorScale(dest->or.axis[0], oppleg, dest->frustum[0].normal);
VectorMA(dest->frustum[0].normal, adjleg, dest->or.axis[1], dest->frustum[0].normal);
VectorScale( tr.viewParms.or.axis[0], xs, tr.viewParms.frustum[1].normal );
VectorMA( tr.viewParms.frustum[1].normal, -xc, tr.viewParms.or.axis[1], tr.viewParms.frustum[1].normal );
VectorScale(dest->or.axis[0], oppleg, dest->frustum[1].normal);
VectorMA(dest->frustum[1].normal, -adjleg, dest->or.axis[1], dest->frustum[1].normal);
}
else
{
// In stereo rendering, due to the modification of the projection matrix, dest->or.origin is not the
// actual origin that we're rendering so offset the tip of the view pyramid.
VectorMA(dest->or.origin, stereoSep, dest->or.axis[1], ofsorigin);
oppleg = xmax + stereoSep;
length = sqrt(oppleg * oppleg + zProj * zProj);
VectorScale(dest->or.axis[0], oppleg / length, dest->frustum[0].normal);
VectorMA(dest->frustum[0].normal, zProj / length, dest->or.axis[1], dest->frustum[0].normal);
ang = tr.viewParms.fovY / 180 * M_PI * 0.5f;
xs = sin( ang );
xc = cos( ang );
oppleg = xmin + stereoSep;
length = sqrt(oppleg * oppleg + zProj * zProj);
VectorScale(dest->or.axis[0], -oppleg / length, dest->frustum[1].normal);
VectorMA(dest->frustum[1].normal, -zProj / length, dest->or.axis[1], dest->frustum[1].normal);
}
VectorScale( tr.viewParms.or.axis[0], xs, tr.viewParms.frustum[2].normal );
VectorMA( tr.viewParms.frustum[2].normal, xc, tr.viewParms.or.axis[2], tr.viewParms.frustum[2].normal );
length = sqrt(ymax * ymax + zProj * zProj);
oppleg = ymax / length;
adjleg = zProj / length;
VectorScale(dest->or.axis[0], oppleg, dest->frustum[2].normal);
VectorMA(dest->frustum[2].normal, adjleg, dest->or.axis[2], dest->frustum[2].normal);
VectorScale(dest->or.axis[0], oppleg, dest->frustum[3].normal);
VectorMA(dest->frustum[3].normal, -adjleg, dest->or.axis[2], dest->frustum[3].normal);
VectorScale( tr.viewParms.or.axis[0], xs, tr.viewParms.frustum[3].normal );
VectorMA( tr.viewParms.frustum[3].normal, -xc, tr.viewParms.or.axis[2], tr.viewParms.frustum[3].normal );
for (i=0 ; i<4 ; i++) {
dest->frustum[i].type = PLANE_NON_AXIAL;
dest->frustum[i].dist = DotProduct (ofsorigin, dest->frustum[i].normal);
SetPlaneSignbits( &dest->frustum[i] );
tr.viewParms.frustum[i].type = PLANE_NON_AXIAL;
tr.viewParms.frustum[i].dist = DotProduct( tr.viewParms.or.origin, tr.viewParms.frustum[i].normal );
SetPlaneSignbits( &tr.viewParms.frustum[i] );
}
}
@ -515,21 +491,6 @@ void R_SetupProjection(viewParms_t *dest, float zProj, qboolean computeFrustum)
float xmin, xmax, ymin, ymax;
float width, height, stereoSep = r_stereoSeparation->value;
/*
* offset the view origin of the viewer for stereo rendering
* by setting the projection matrix appropriately.
*/
if(stereoSep != 0)
{
if(dest->stereoFrame == STEREO_LEFT)
stereoSep = zProj / stereoSep;
else if(dest->stereoFrame == STEREO_RIGHT)
stereoSep = zProj / -stereoSep;
else
stereoSep = 0;
}
ymax = zProj * tan(dest->fovY * M_PI / 360.0f);
ymin = -ymax;
@ -538,25 +499,49 @@ void R_SetupProjection(viewParms_t *dest, float zProj, qboolean computeFrustum)
width = xmax - xmin;
height = ymax - ymin;
dest->projectionMatrix[0] = 2 * zProj / width;
dest->projectionMatrix[4] = 0;
dest->projectionMatrix[8] = (xmax + xmin + 2 * stereoSep) / width;
dest->projectionMatrix[12] = 2 * zProj * stereoSep / width;
dest->projectionMatrix[1] = 0;
dest->projectionMatrix[5] = 2 * zProj / height;
dest->projectionMatrix[9] = ( ymax + ymin ) / height; // normally 0
dest->projectionMatrix[13] = 0;
if (tr.vrParms.valid) {
/* if (dest->stereoFrame == STEREO_LEFT) {
memcpy(&dest->projectionMatrix, &tr.vrParms.projectionL, sizeof(dest->projectionMatrix));
}
else */
{
memcpy(&dest->projectionMatrix, &tr.vrParms.projection, sizeof(dest->projectionMatrix));
}
} else {
/*
* offset the view origin of the viewer for stereo rendering
* by setting the projection matrix appropriately.
*/
if(stereoSep != 0)
{
if(dest->stereoFrame == STEREO_LEFT)
stereoSep = zProj / stereoSep;
else if(dest->stereoFrame == STEREO_RIGHT)
stereoSep = zProj / -stereoSep;
else
stereoSep = 0;
}
dest->projectionMatrix[3] = 0;
dest->projectionMatrix[7] = 0;
dest->projectionMatrix[11] = -1;
dest->projectionMatrix[15] = 0;
dest->projectionMatrix[0] = 2 * zProj / width;
dest->projectionMatrix[4] = 0;
dest->projectionMatrix[8] = (xmax + xmin + 2 * stereoSep) / width;
dest->projectionMatrix[12] = 2 * zProj * stereoSep / width;
dest->projectionMatrix[1] = 0;
dest->projectionMatrix[5] = 2 * zProj / height;
dest->projectionMatrix[9] = ( ymax + ymin ) / height; // normally 0
dest->projectionMatrix[13] = 0;
dest->projectionMatrix[3] = 0;
dest->projectionMatrix[7] = 0;
dest->projectionMatrix[11] = -1;
dest->projectionMatrix[15] = 0;
}
// Now that we have all the data for the projection matrix we can also setup the view frustum.
if(computeFrustum)
R_SetupFrustum(dest, xmin, xmax, ymax, zProj, stereoSep);
R_SetupFrustum( );//dest, xmin, xmax, ymax, zProj, zFar, stereoSep);
}
/*
@ -569,15 +554,19 @@ Sets the z-component transformation part in the projection matrix
void R_SetupProjectionZ(viewParms_t *dest)
{
float zNear, zFar, depth;
zNear = r_znear->value;
zFar = dest->zFar;
depth = zFar - zNear;
dest->projectionMatrix[2] = 0;
dest->projectionMatrix[6] = 0;
dest->projectionMatrix[10] = -( zFar + zNear ) / depth;
dest->projectionMatrix[14] = -2 * zFar * zNear / depth;
zNear = r_znear->value;
zFar = dest->zFar;
depth = zFar - zNear;
if (!tr.vrParms.valid)
{
dest->projectionMatrix[2] = 0;
dest->projectionMatrix[6] = 0;
dest->projectionMatrix[10] = -(zFar + zNear) / depth;
dest->projectionMatrix[14] = -2 * zFar * zNear / depth;
}
}
/*

View file

@ -62,11 +62,12 @@ static ovrJava engine_get_ovrJava() {
}
int main(int argc, char* argv[]) {
ovrJava java = engine_get_ovrJava();
engine_t* engine = nullptr;
engine = VR_Init(java);
//sleep(30);
sleep(30);
//First set up resolution cached values
int width, height;

View file

@ -190,6 +190,7 @@ public class MainActivity extends SDLActivity // implements KeyEvent.Callback
public static native void nativeCreate(MainActivity thisObject);
static {
System.loadLibrary("gl4es");
System.loadLibrary("main");
}

View file

@ -2,10 +2,12 @@
setlocal
set BUILD_TYPE=release
set KEYSTORE=
set KEYSTORE_PASS=
set VERSION=0.21.1
set BUILD_TYPE=debug
set VERSION=0.27.1
@REM Define the following environment variables to sign a release build
@REM set KEYSTORE=
@REM set KEYSTORE_PASS=
set ANDROID_SDK_ROOT=%AppData%\..\Local\Android\Sdk
set adb="%ANDROID_SDK_ROOT%\platform-tools\adb.exe"