platform/android: rewrite egl part to separate not android-specific file

This commit is contained in:
mittorn
2023-10-26 04:52:41 +03:00
committed by Alibek Omarov
parent 34aab39f9b
commit c2e14eb3a3
4 changed files with 542 additions and 203 deletions

View File

@@ -7,18 +7,14 @@
#include "vid_common.h"
#include <android/native_window.h>
#include <android/native_window_jni.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include "eglutil.h"
static struct vid_android_s
{
int gl_attribs[REF_GL_ATTRIBUTES_COUNT];
qboolean gl_attribs_set[REF_GL_ATTRIBUTES_COUNT];
EGLint gl_api;
qboolean gles1;
void *libgles1, *libgles2;
qboolean has_context;
ANativeWindow* window;
qboolean nativeegl;
} vid_android;
static struct nw_s
@@ -51,43 +47,6 @@ static dllfunc_t android_funcs[] =
#undef NW_FF
dll_info_t android_info = { "libandroid.so", android_funcs, false };
static struct egl_s
{
EGLSurface (*GetCurrentSurface)(EGLint readdraw);
EGLDisplay (*GetCurrentDisplay)(void);
EGLint (*GetError)(void);
EGLBoolean (*SwapBuffers)(EGLDisplay dpy, EGLSurface surface);
EGLBoolean (*SwapInterval)(EGLDisplay dpy, EGLint interval);
void *(*GetProcAddress)(const char *procname);
} egl;
#undef GetProcAddress
#define EGL_FF(x) {"egl"#x, (void*)&egl.x}
static dllfunc_t egl_funcs[] =
{
EGL_FF(SwapInterval),
EGL_FF(SwapBuffers),
EGL_FF(GetError),
EGL_FF(GetCurrentDisplay),
EGL_FF(GetCurrentSurface),
EGL_FF(GetProcAddress),
{ NULL, NULL }
};
#undef EGL_FF
dll_info_t egl_info = { "libEGL.so", egl_funcs, false };
static struct nativeegl_s
{
qboolean valid;
void *window;
EGLDisplay dpy;
EGLSurface surface;
EGLContext context;
EGLConfig cfg;
EGLint numCfg;
const char *extensions;
} negl;
convar_t *cv_vid_scale;
convar_t *cv_vid_rotate;
@@ -98,8 +57,8 @@ Android_SwapInterval
*/
static void Android_SwapInterval( int interval )
{
if( negl.valid )
egl.SwapInterval( negl.dpy, interval );
if( vid_android.nativeegl && eglstate.valid )
egl.SwapInterval( eglstate.dpy, interval );
}
/*
@@ -143,9 +102,9 @@ Update screen. Use native EGL if possible
*/
void GL_SwapBuffers( void )
{
if( negl.valid )
if( vid_android.nativeegl && eglstate.valid )
{
egl.SwapBuffers( negl.dpy, negl.surface );
egl.SwapBuffers( eglstate.dpy, eglstate.surface );
}
else
{
@@ -162,9 +121,9 @@ Check if we may use native EGL without jni calls
*/
void Android_UpdateSurface( qboolean active )
{
negl.valid = false;
vid_android.nativeegl = false;
if( nw.release )
if( glw_state.software || eglstate.valid )
{
if( vid_android.window && !active )
{
@@ -174,16 +133,28 @@ void Android_UpdateSurface( qboolean active )
if( active )
{
EGLint format = WINDOW_FORMAT_RGB_565;
jobject surf;
if( vid_android.window )
nw.release( vid_android.window );
surf = (*jni.env)->CallStaticObjectMethod(jni.env, jni.actcls, jni.getSurface);
Con_Printf("s %p\n", surf);
Con_DPrintf("Surface handle %p\n", surf);
vid_android.window = nw.fromSurface(jni.env, surf);
Con_Printf("w %p\n", vid_android.window);
nw.setBuffersGeometry(vid_android.window, 0, 0, WINDOW_FORMAT_RGB_565 );
Con_DPrintf("NativeWindow %p\n", vid_android.window);
if( eglstate.valid )
egl.GetConfigAttrib( eglstate.dpy, eglstate.cfg, EGL_NATIVE_VISUAL_ID, &format );
nw.setBuffersGeometry(vid_android.window, 0, 0, format );
(*jni.env)->DeleteLocalRef( jni.env, surf );
}
if( Sys_CheckParm( "-egl" ))
{
EGL_UpdateSurface( vid_android.window );
vid_android.nativeegl = true;
}
return;
}
@@ -199,30 +170,7 @@ void Android_UpdateSurface( qboolean active )
if( !Sys_CheckParm("-nativeegl") || !active )
return; // enabled by user
if( !egl.GetCurrentDisplay )
return;
negl.dpy = egl.GetCurrentDisplay();
if( negl.dpy == EGL_NO_DISPLAY )
return;
negl.surface = egl.GetCurrentSurface(EGL_DRAW);
if( negl.surface == EGL_NO_SURFACE )
return;
// now check if swapBuffers does not give error
if( egl.SwapBuffers( negl.dpy, negl.surface ) == EGL_FALSE )
return;
// double check
if( egl.GetError() != EGL_SUCCESS )
return;
__android_log_print( ANDROID_LOG_VERBOSE, "Xash", "native EGL enabled" );
negl.valid = true;
vid_android.nativeegl = EGL_ImportContext();
}
/*
@@ -272,6 +220,8 @@ qboolean R_Init_Video( const int type )
VID_StartupGamma();
Sys_LoadLibrary( &android_info );
switch( type )
{
case REF_SOFTWARE:
@@ -279,7 +229,7 @@ qboolean R_Init_Video( const int type )
break;
case REF_GL:
glw_state.software = false;
Sys_LoadLibrary( &egl_info );
EGL_LoadLibrary();
if( !glw_state.safe && Sys_GetParmFromCmdLine( "-safegl", buf ) )
glw_state.safe = bound( SAFE_NO, Q_atoi( buf ), SAFE_DONTCARE );
@@ -295,7 +245,6 @@ qboolean R_Init_Video( const int type )
uint arg;
// Con_Reportf( S_ERROR "Native software mode isn't supported on Android yet! :(\n" );
// return false;
Sys_LoadLibrary( &android_info );
Android_UpdateSurface( true );
if( !SW_CreateBuffer( jni.width, jni.height, &arg, &arg, &arg, &arg, &arg ) )
return false;
@@ -332,109 +281,34 @@ void R_Free_Video( void )
// R_FreeVideoModes();
Sys_FreeLibrary( &android_info );
Sys_FreeLibrary( &egl_info );
vid_android.has_context = false;
ref.dllFuncs.GL_ClearExtensions();
}
#define COPY_ATTR_IF_SET( refattr, attr ) \
if( vid_android.gl_attribs_set[refattr] ) \
{ \
attribs[i++] = attr; \
attribs[i++] = vid_android.gl_attribs[refattr]; \
}
static size_t VID_GenerateConfig( EGLint *attribs, size_t size )
void *Android_GetWindow( void )
{
size_t i = 0;
EGLint format;
memset( attribs, 0, size * sizeof( EGLint ) );
vid_android.gles1 = false;
memset( vid_android.gl_attribs, 0, sizeof( vid_android.gl_attribs ));
memset( vid_android.gl_attribs_set, 0, sizeof( vid_android.gl_attribs_set ));
// refdll can request some attributes
ref.dllFuncs.GL_SetupAttributes( glw_state.safe );
COPY_ATTR_IF_SET( REF_GL_RED_SIZE, EGL_RED_SIZE );
COPY_ATTR_IF_SET( REF_GL_GREEN_SIZE, EGL_GREEN_SIZE );
COPY_ATTR_IF_SET( REF_GL_BLUE_SIZE, EGL_BLUE_SIZE );
COPY_ATTR_IF_SET( REF_GL_ALPHA_SIZE, EGL_ALPHA_SIZE );
COPY_ATTR_IF_SET( REF_GL_DEPTH_SIZE, EGL_DEPTH_SIZE );
COPY_ATTR_IF_SET( REF_GL_STENCIL_SIZE, EGL_STENCIL_SIZE );
COPY_ATTR_IF_SET( REF_GL_MULTISAMPLEBUFFERS, EGL_SAMPLE_BUFFERS );
COPY_ATTR_IF_SET( REF_GL_MULTISAMPLESAMPLES, EGL_SAMPLES );
if( vid_android.gl_attribs_set[REF_GL_ACCELERATED_VISUAL] )
if( !vid_android.window )
{
attribs[i++] = EGL_CONFIG_CAVEAT;
attribs[i++] = vid_android.gl_attribs[REF_GL_ACCELERATED_VISUAL] ? EGL_NONE : EGL_DONT_CARE;
return NULL;
}
// BigGL support
attribs[i++] = EGL_RENDERABLE_TYPE;
vid_android.gl_api = EGL_OPENGL_ES_API;
if( vid_android.gl_attribs_set[REF_GL_CONTEXT_PROFILE_MASK] &&
!( vid_android.gl_attribs[REF_GL_CONTEXT_PROFILE_MASK] & REF_GL_CONTEXT_PROFILE_ES ))
if( !egl.GetConfigAttrib( eglstate.dpy, eglstate.cfg, EGL_NATIVE_VISUAL_ID, &format) )
{
attribs[i++] = EGL_OPENGL_BIT;
vid_android.gl_api = EGL_OPENGL_API;
}
else if( vid_android.gl_attribs_set[REF_GL_CONTEXT_MAJOR_VERSION] &&
vid_android.gl_attribs[REF_GL_CONTEXT_MAJOR_VERSION] >= 2 )
{
attribs[i++] = EGL_OPENGL_ES2_BIT;
}
else
{
i--; // erase EGL_RENDERABLE_TYPE
vid_android.gles1 = true;
Con_Reportf( S_ERROR "eglGetConfigAttrib(VISUAL_ID) returned error: 0x%x\n", egl.GetError() );
return NULL;
}
attribs[i++] = EGL_NONE;
if( nw.setBuffersGeometry( vid_android.window, 0, 0, format ) )
{
Con_Reportf( S_ERROR "ANativeWindow_setBuffersGeometry returned error\n" );
return NULL;
}
return i;
return vid_android.window;
}
static size_t VID_GenerateContextConfig( EGLint *attribs, size_t size )
{
size_t i = 0;
memset( attribs, 0, size * sizeof( EGLint ));
/*if( Q_strcmp( negl.extensions, " EGL_KHR_create_context ") )
{
if( vid_android.gl_attribs_set[REF_GL_CONTEXT_FLAGS] )
{
attribs[i++] = 0x30FC; // EGL_CONTEXT_FLAGS_KHR
attribs[i++] = vid_android.gl_attribs[REF_GL_CONTEXT_FLAGS] & ((REF_GL_CONTEXT_ROBUST_ACCESS_FLAG << 1) - 1);
}
if( vid_android.gl_attribs_set[REF_GL_CONTEXT_PROFILE_MASK] )
{
int val = vid_android.gl_attribs[REF_GL_CONTEXT_PROFILE_MASK];
if( val & ( (REF_GL_CONTEXT_PROFILE_COMPATIBILITY << 1) - 1 ) )
{
attribs[i++] = 0x30FD; // EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR;
attribs[i++] = val;
}
}
COPY_ATTR_IF_SET( REF_GL_CONTEXT_MAJOR_VERSION, EGL_CONTEXT_CLIENT_VERSION );
COPY_ATTR_IF_SET( REF_GL_CONTEXT_MINOR_VERSION, 0x30FB );
}
else*/
{
// without extension we can set only major version
COPY_ATTR_IF_SET( REF_GL_CONTEXT_MAJOR_VERSION, EGL_CONTEXT_CLIENT_VERSION );
}
attribs[i++] = EGL_NONE;
return i;
}
qboolean VID_SetMode( void )
{
@@ -444,14 +318,25 @@ qboolean VID_SetMode( void )
const size_t attribsSize = ARRAYSIZE( nAttribs );
size_t s1, s2;
if( vid_android.has_context )
// create context on egl side by user request
if( !vid_android.has_context && Sys_CheckParm("-egl") )
{
vid_android.has_context = vid_android.nativeegl = EGL_CreateContext();
if( vid_android.has_context )
Android_UpdateSurface( true );
else
return false;
}
if( vid_android.has_context || glw_state.software )
{
R_ChangeDisplaySettings( 0, 0, WINDOW_MODE_WINDOWED ); // width and height are ignored anyway
return true;
}
s1 = VID_GenerateConfig(nAttribs, attribsSize);
s2 = VID_GenerateContextConfig(nContextAttribs, attribsSize);
s1 = EGL_GenerateConfig(nAttribs, attribsSize);
s2 = EGL_GenerateContextConfig(nContextAttribs, attribsSize);
attribs = (*jni.env)->NewIntArray( jni.env, s1 );
contextAttribs = (*jni.env)->NewIntArray( jni.env, s2 );
@@ -461,8 +346,6 @@ qboolean VID_SetMode( void )
R_ChangeDisplaySettings( 0, 0, WINDOW_MODE_WINDOWED ); // width and height are ignored anyway
if( glw_state.software )
return true;
if( (*jni.env)->CallStaticBooleanMethod( jni.env, jni.actcls, jni.createGLContext, attribs, contextAttribs ) )
{
@@ -512,18 +395,16 @@ rserr_t R_ChangeDisplaySettings( int width, int height, window_mode_t window_m
int GL_SetAttribute( int attr, int val )
{
if( attr < 0 || attr >= REF_GL_ATTRIBUTES_COUNT )
return -1;
vid_android.gl_attribs[attr] = val;
vid_android.gl_attribs_set[attr] = true;
return 0;
return EGL_SetAttribute( attr, val );
}
int GL_GetAttribute( int attr, int *val )
{
EGLBoolean ret;
if( eglstate.valid )
return EGL_GetAttribute( attr, val );
if( attr < 0 || attr >= REF_GL_ATTRIBUTES_COUNT )
return -1;
@@ -570,29 +451,7 @@ vidmode_t* R_GetVideoMode( int num )
void* GL_GetProcAddress( const char *name ) // RenderAPI requirement
{
void *gles;
void *addr;
if( vid_android.gles1 )
{
if( !vid_android.libgles1 )
vid_android.libgles1 = dlopen("libGLESv1_CM.so", RTLD_NOW);
gles = vid_android.libgles1;
}
else
{
if( !vid_android.libgles2 )
vid_android.libgles2 = dlopen("libGLESv2.so", RTLD_NOW);
gles = vid_android.libgles2;
}
if( gles && ( addr = dlsym(gles, name ) ) )
return addr;
if( !egl.GetProcAddress )
return NULL;
return egl.GetProcAddress( name );
return EGL_GetProcAddress( name );
}
void GL_UpdateSwapInterval( void )
@@ -652,7 +511,7 @@ qboolean SW_CreateBuffer( int width, int height, uint *stride, uint *bpp, uint *
if( jni.height < buffer.height )
jni.width = buffer.height;
VID_SetMode();
Android_UpdateSurface( 1 );
Android_UpdateSurface( true );
return false;
}
if( buffer.format != WINDOW_FORMAT_RGB_565 )
@@ -669,4 +528,4 @@ qboolean SW_CreateBuffer( int width, int height, uint *stride, uint *bpp, uint *
*b = (((1 << 5) - 1) << (0));
return true;
}
#endif
#endif