/** * Recreates and selects the surface for the newly created window, or selects a dummy buffer when there's no window. */ static void GLimp_EGL_UpdateWindowSurface( void ) { EGLNativeWindowType window = glw_state.window; EGLContext context = qeglGetCurrentContext(); if( context == EGL_NO_CONTEXT ) return; if( glw_state.surface != EGL_NO_SURFACE ) { qeglMakeCurrent( glw_state.display, glw_state.noWindowPbuffer, glw_state.noWindowPbuffer, context ); qeglDestroySurface( glw_state.display, glw_state.surface ); glw_state.surface = EGL_NO_SURFACE; } if( !window ) return; #ifdef __ANDROID__ ANativeWindow_setBuffersGeometry( window, glConfig.width, glConfig.height, glw_state.format ); #endif glw_state.surface = qeglCreateWindowSurface( glw_state.display, glw_state.config, window, NULL ); if( glw_state.surface == EGL_NO_SURFACE ) { ri.Com_Printf( "GLimp_EGL_UpdateWindowSurface() - GLimp_EGL_CreateWindowSurface failed\n" ); return; } qeglMakeCurrent( glw_state.display, glw_state.surface, glw_state.surface, context ); qeglSwapInterval( glw_state.display, glw_state.swapInterval ); }
/** * 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_Shutdown ** ** This routine does all OS specific shutdown procedures for the OpenGL ** subsystem. The state structure is also nulled out. ** */ void GLimp_Shutdown( void ) { if( glw_state.windowMutex ) ri.Mutex_Destroy( &glw_state.windowMutex ); if( glw_state.context != EGL_NO_CONTEXT ) { qeglMakeCurrent( glw_state.display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT ); qeglDestroyContext( glw_state.display, glw_state.context ); glw_state.context = EGL_NO_CONTEXT; } if( glw_state.surface != EGL_NO_SURFACE ) { qeglDestroySurface( glw_state.display, glw_state.surface ); glw_state.surface = EGL_NO_SURFACE; } if( glw_state.noWindowPbuffer != EGL_NO_SURFACE ) { qeglDestroySurface( glw_state.display, glw_state.noWindowPbuffer ); glw_state.noWindowPbuffer = EGL_NO_SURFACE; } if( glw_state.mainThreadPbuffer != EGL_NO_SURFACE ) { qeglDestroySurface( glw_state.display, glw_state.mainThreadPbuffer ); glw_state.mainThreadPbuffer = EGL_NO_SURFACE; } if( glw_state.display != EGL_NO_DISPLAY ) { qeglTerminate( glw_state.display ); glw_state.display = EGL_NO_DISPLAY; } }
/* ** GLimp_EnableMultithreadedRendering */ void GLimp_EnableMultithreadedRendering( bool enable ) { EGLSurface surface; if( glw_state.multithreadedRendering == enable ) return; glw_state.multithreadedRendering = enable; if( enable ) { surface = glw_state.mainThreadPbuffer; } else { if( glw_state.windowChanged ) { glw_state.windowChanged = false; GLimp_EGL_UpdateWindowSurface(); } surface = ( glw_state.surface != EGL_NO_SURFACE ? glw_state.surface : glw_state.noWindowPbuffer ); } qeglMakeCurrent( glw_state.display, surface, surface, glw_state.context ); }
/* ** 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 ) { if( glw_state.context != EGL_NO_CONTEXT ) { qeglMakeCurrent( glw_state.display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT ); qeglDestroyContext( glw_state.display, glw_state.context ); glw_state.context = EGL_NO_CONTEXT; } if( glw_state.surface != EGL_NO_SURFACE ) { qeglDestroySurface( glw_state.display, glw_state.surface ); glw_state.surface = EGL_NO_SURFACE; } if( glw_state.pbufferSurface != EGL_NO_SURFACE ) { qeglDestroySurface( glw_state.display, glw_state.pbufferSurface ); glw_state.surface = EGL_NO_SURFACE; } if( glw_state.display != EGL_NO_DISPLAY ) { qeglTerminate( glw_state.display ); glw_state.display = EGL_NO_DISPLAY; } }
/* ** GLimp_SharedContext_MakeCurrent */ bool GLimp_SharedContext_MakeCurrent( void *context, void *surface ) { return qeglMakeCurrent( glw_state.display, surface, surface, context ) ? true : false; }
/* ** GLimp_InitGL */ static bool GLimp_InitGL( void ) { int format; EGLConfig config; const int contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; EGLSurface surface; glw_state.display = qeglGetDisplay( EGL_DEFAULT_DISPLAY ); if( glw_state.display == EGL_NO_DISPLAY ) { ri.Com_Printf( "GLimp_InitGL() - eglGetDisplay failed\n" ); return false; } if( !qeglInitialize( glw_state.display, NULL, NULL ) ) { ri.Com_Printf( "GLimp_InitGL() - eglInitialize failed\n" ); return false; } GLimp_EGL_ChooseConfig(); if( !glw_state.config ) { ri.Com_Printf( "GLimp_InitGL() - GLimp_EGL_ChooseConfig failed\n" ); return false; } if ( !qeglGetConfigAttrib( glw_state.display, glw_state.config, EGL_NATIVE_VISUAL_ID, &glw_state.format ) ) { ri.Com_Printf( "GLimp_InitGL() - eglGetConfigAttrib failed\n" ); return false; } glw_state.mainThreadPbuffer = GLimp_EGL_CreatePbufferSurface(); if( glw_state.mainThreadPbuffer == EGL_NO_SURFACE ) { ri.Com_Printf( "GLimp_InitGL() - GLimp_EGL_CreatePbufferSurface for mainThreadPbuffer failed\n" ); return false; } glw_state.noWindowPbuffer = GLimp_EGL_CreatePbufferSurface(); if( glw_state.noWindowPbuffer == EGL_NO_SURFACE ) { ri.Com_Printf( "GLimp_InitGL() - GLimp_EGL_CreatePbufferSurface for noWindowPbuffer failed\n" ); return false; } glw_state.context = qeglCreateContext( glw_state.display, glw_state.config, EGL_NO_CONTEXT, contextAttribs ); if( glw_state.context == EGL_NO_CONTEXT ) { ri.Com_Printf( "GLimp_InitGL() - eglCreateContext failed\n" ); return false; } glw_state.windowMutex = ri.Mutex_Create(); glw_state.swapInterval = 1; // Default swap interval for new surfaces // GLimp_EGL_UpdateWindowSurface attaches the surface to the current context, so make one current to initialize qeglMakeCurrent( glw_state.display, glw_state.noWindowPbuffer, glw_state.noWindowPbuffer, glw_state.context ); GLimp_EGL_UpdateWindowSurface(); return true; }