/* ** qglGetGLWExtensionsString */ static const char *_qglGetGLWExtensionsStringInit( void ) { int major = 0, minor = 0; if( !qglXQueryVersion || !qglXQueryVersion( x11display.dpy, &major, &minor ) || !( minor > 0 || major > 1 ) ) { qglXQueryExtensionsString = NULL; } qglGetGLWExtensionsString = _qglGetGLWExtensionsString; return qglGetGLWExtensionsString(); }
/** * Recreates and selects the surface for the newly created window, or selects a dummy buffer when there's no window. */ static void GLimp_Android_UpdateWindowSurface( void ) { ANativeWindow *window = glw_state.window; if( glw_state.surface != EGL_NO_SURFACE ) { qeglDestroySurface( glw_state.display, glw_state.surface ); glw_state.surface = EGL_NO_SURFACE; } if( !window ) { qeglMakeCurrent( glw_state.display, glw_state.pbufferSurface, glw_state.pbufferSurface, glw_state.context ); return; } ANativeWindow_setBuffersGeometry( window, glConfig.width, glConfig.height, glw_state.format ); if( glConfig.stereoEnabled ) { const char *extensions = qglGetGLWExtensionsString(); if( extensions && strstr( extensions, "EGL_EXT_multiview_window" ) ) { int attribs[] = { EGL_MULTIVIEW_VIEW_COUNT_EXT, 2, EGL_NONE }; glw_state.surface = qeglCreateWindowSurface( glw_state.display, glw_state.config, glw_state.window, attribs ); } } if( glw_state.surface == EGL_NO_SURFACE ) // Try to create a non-stereo surface. { glConfig.stereoEnabled = false; glw_state.surface = qeglCreateWindowSurface( glw_state.display, glw_state.config, glw_state.window, NULL ); } if( glw_state.surface == EGL_NO_SURFACE ) { ri.Com_Printf( "GLimp_Android_UpdateWindowSurface() - GLimp_Android_CreateWindowSurface failed\n" ); return; } if( !qeglMakeCurrent( glw_state.display, glw_state.surface, glw_state.surface, glw_state.context ) ) { ri.Com_Printf( "GLimp_Android_UpdateWindowSurface() - eglMakeCurrent failed\n" ); qeglDestroySurface( glw_state.display, glw_state.surface ); glw_state.surface = EGL_NO_SURFACE; return; } qeglSwapInterval( glw_state.display, glw_state.swapInterval ); }
/* ** GLimp_Android_ChooseConfig */ static void GLimp_Android_ChooseConfig( void ) { int colorSizes[] = { 8, 4 }, colorSize; int depthSizes[] = { 24, 16, 16 }, depthSize, firstDepthSize = 0; bool depthEncodingSupported = false; int depthEncodings[] = { EGL_DONT_CARE, EGL_DEPTH_ENCODING_NONLINEAR_NV, EGL_DONT_CARE }, depthEncoding; int maxStencilSize = ( ( r_stencilbits->integer >= 8 ) ? 8 : 0 ), stencilSize; int minSwapIntervals[] = { #ifndef PUBLIC_BUILD // Vsync cannot be normally turned off on Android, so the setting must not be available to the user. 0, #endif EGL_DONT_CARE }; int minSwapInterval; const char *extensions = qglGetGLWExtensionsString(); int i, j, k; if( !( ri.Cvar_Get( "gl_ext_depth24", "1", CVAR_ARCHIVE|CVAR_LATCH_VIDEO )->integer ) ) firstDepthSize = 1; if( extensions && strstr( extensions, "EGL_NV_depth_nonlinear" ) && ri.Cvar_Get( "gl_ext_depth_nonlinear", "1", CVAR_ARCHIVE|CVAR_LATCH_VIDEO )->integer ) { depthEncodingSupported = true; } for( i = 0; i < sizeof( colorSizes ) / sizeof( colorSizes[0] ); i++ ) { colorSize = colorSizes[i]; for( j = firstDepthSize; j < sizeof( depthSizes ) / sizeof( depthSizes[0] ); j++ ) { depthEncoding = depthEncodings[j]; if( ( depthEncoding != EGL_DONT_CARE ) && !depthEncodingSupported ) continue; depthSize = depthSizes[j]; for( stencilSize = maxStencilSize; stencilSize >= 0; stencilSize -= 8 ) { for( k = 0; k < sizeof( minSwapIntervals ) / sizeof( minSwapIntervals[0] ); k++ ) { EGLConfig config = GLimp_Android_ChooseVisual( colorSize, depthSize, depthEncoding, stencilSize, minSwapIntervals[k] ); if( config ) { glw_state.config = config; #ifdef PUBLIC_BUILD minSwapInterval = 1; #else qeglGetConfigAttrib( glw_state.display, glw_state.config, EGL_MIN_SWAP_INTERVAL, &minSwapInterval ); #endif ri.Com_Printf( "Got colorbits %i, depthbits %i%s, stencilbits %i" #ifndef PUBLIC_BUILD ", min swap interval %i" #endif "\n" , colorSize * 4, depthSize , ( depthEncoding == EGL_DEPTH_ENCODING_NONLINEAR_NV ) ? " (non-linear)" : "" , stencilSize #ifndef PUBLIC_BUILD , minSwapInterval #endif ); glConfig.stencilBits = stencilSize; ri.Cvar_ForceSet( "r_swapinterval_min", ( minSwapInterval > 0 ) ? "1" : "0" ); return; } } } } } }