void QGLWidgetPrivate::recreateEglSurface() { Q_Q(QGLWidget); WId currentId = q->winId(); if (glcx->d_func()->eglSurface != EGL_NO_SURFACE) { if (glcx == QGLContext::currentContext()) glcx->doneCurrent(); eglDestroySurface(glcx->d_func()->eglContext->display(), glcx->d_func()->eglSurface); } glcx->d_func()->eglSurface = QEgl::createSurface(glcx->device(), glcx->d_func()->eglContext->config()); #if !defined(QGL_NO_PRESERVED_SWAP) eglGetError(); // Clear error state first. eglSurfaceAttrib(QEgl::display(), glcx->d_func()->eglSurface, EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED); if (eglGetError() != EGL_SUCCESS) { qWarning("QGLContext: could not enable preserved swap"); } #endif eglSurfaceWindowId = currentId; }
static jboolean android_view_HardwareRenderer_preserveBackBuffer(JNIEnv* env, jobject clazz) { EGLDisplay display = eglGetCurrentDisplay(); EGLSurface surface = eglGetCurrentSurface(EGL_DRAW); eglGetError(); eglSurfaceAttrib(display, surface, EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED); EGLint error = eglGetError(); if (error != EGL_SUCCESS) { RENDERER_LOGD("Could not enable buffer preserved swap behavior (%x)", error); } return error == EGL_SUCCESS; }
/* EGLBoolean eglSurfaceAttrib ( EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value ) */ static jboolean android_eglSurfaceAttrib (JNIEnv *_env, jobject _this, jobject dpy, jobject surface, jint attribute, jint value) { EGLBoolean _returnValue = (EGLBoolean) 0; EGLDisplay dpy_native = (EGLDisplay) fromEGLHandle(_env, egldisplayGetHandleID, dpy); EGLSurface surface_native = (EGLSurface) fromEGLHandle(_env, eglsurfaceGetHandleID, surface); _returnValue = eglSurfaceAttrib( (EGLDisplay)dpy_native, (EGLSurface)surface_native, (EGLint)attribute, (EGLint)value ); return (jboolean)_returnValue; }
void InitializeSurface(DisplaySurface *surface, unsigned int xOrigin, unsigned int yOrigin, unsigned int width, unsigned int height) { //VC VC_RECT_T destinationRect; VC_RECT_T sourceRect; if (xOrigin > displayWidth) xOrigin = 0; if (yOrigin > displayHeight) yOrigin = 0; if (width == 0 || xOrigin + width > displayWidth) width = displayWidth - xOrigin; if (height == 0 || yOrigin + height > displayHeight) height = displayHeight - yOrigin; surface->xOrigin = xOrigin; surface->yOrigin = yOrigin; surface->width = width; surface->height = height; // create an EGL window surface destinationRect.x = xOrigin; destinationRect.y = displayHeight - yOrigin - height; destinationRect.width = width; destinationRect.height = height; sourceRect.x = 0; sourceRect.y = 0; sourceRect.width = width << 16; sourceRect.height = height << 16; dispmanDisplay = vc_dispmanx_display_open( 0 /* LCD */); dispmanUpdate = vc_dispmanx_update_start( 0 ); surface->dispmanWindow.element = vc_dispmanx_element_add (dispmanUpdate, dispmanDisplay, 0/*layer*/, &destinationRect, 0/*src*/, &sourceRect, DISPMANX_PROTECTION_NONE, 0 /*alpha*/, 0/*clamp*/, 0/*transform*/); surface->dispmanWindow.width = width; surface->dispmanWindow.height = height; vc_dispmanx_update_submit_sync(dispmanUpdate); // create the surfrace surface->eglSurface = eglCreateWindowSurface(eglDisplay, eglConfig, &surface->dispmanWindow, NULL ); // connect the context to the surface eglMakeCurrent(eglDisplay, surface->eglSurface, surface->eglSurface, eglContext); // JDO: preserve buffer https://www.khronos.org/registry/egl/sdk/docs/man/html/eglSwapBuffers.xhtml // Slower eglSwapBuffers but allows for partial screen update eglSurfaceAttrib(eglDisplay, surface->eglSurface, EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED); }
/* private native int _eglSurfaceAttrib ( int display , int surface , int attribute , int value ) ; */ KNIEXPORT KNI_RETURNTYPE_INT Java_javax_microedition_khronos_egl_EGL10Impl__1eglSurfaceAttrib() { jint display = KNI_GetParameterAsInt(1); jint surface = KNI_GetParameterAsInt(2); jint attribute = KNI_GetParameterAsInt(3); jint value = KNI_GetParameterAsInt(4); jint returnValue = (jint)eglSurfaceAttrib((EGLDisplay)display, (EGLSurface)surface, (EGLint)attribute, (EGLint)value); #ifdef DEBUG printf("eglSurfaceAttrib(0x%x, 0x%x, %d, %d) = %d\n", display, surface, attribute, value, returnValue); #endif KNI_ReturnInt(returnValue); }
bool CGLContextEGL::SurfaceAttrib() { // for the non-trivial dirty region modes, we need the EGL buffer to be preserved across updates if (g_advancedSettings.m_guiAlgorithmDirtyRegions == DIRTYREGION_SOLVER_COST_REDUCTION || g_advancedSettings.m_guiAlgorithmDirtyRegions == DIRTYREGION_SOLVER_UNION) { if ((m_eglDisplay == EGL_NO_DISPLAY) || (m_eglSurface == EGL_NO_SURFACE)) { return false; } if (!eglSurfaceAttrib(m_eglDisplay, m_eglSurface, EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED)) { CLog::Log(LOGDEBUG, "%s: Could not set EGL_SWAP_BEHAVIOR",__FUNCTION__); } } return true; }
bool EglManager::setPreserveBuffer(EGLSurface surface, bool preserve) { if (mSwapBehavior != SwapBehavior::Preserved) return false; bool preserved = eglSurfaceAttrib(mEglDisplay, surface, EGL_SWAP_BEHAVIOR, preserve ? EGL_BUFFER_PRESERVED : EGL_BUFFER_DESTROYED); if (!preserved) { ALOGW("Failed to set EGL_SWAP_BEHAVIOR on surface %p, error=%s", (void*)surface, eglErrorString()); // Maybe it's already set? EGLint swapBehavior; if (eglQuerySurface(mEglDisplay, surface, EGL_SWAP_BEHAVIOR, &swapBehavior)) { preserved = (swapBehavior == EGL_BUFFER_PRESERVED); } else { ALOGW("Failed to query EGL_SWAP_BEHAVIOR on surface %p, error=%p", (void*)surface, eglErrorString()); } } return preserved; }
bool EglManager::enableDirtyRegions(EGLSurface surface) { if (!mRequestDirtyRegions) return false; if (mCanSetDirtyRegions) { EGLBoolean success; TIME_LOG("eglSurfaceAttrib", success = eglSurfaceAttrib(mEglDisplay, surface, EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED)); if (!success) { ALOGW("Failed to set EGL_SWAP_BEHAVIOR on surface %p, error=%s", (void*) surface, egl_error_str()); return false; } return true; } // Perhaps it is already enabled? EGLint value; EGLBoolean success; TIME_LOG("eglQuerySurface", success = eglQuerySurface(mEglDisplay, surface, EGL_SWAP_BEHAVIOR, &value)); if (!success) { ALOGW("Failed to query EGL_SWAP_BEHAVIOR on surface %p, error=%p", (void*) surface, egl_error_str()); return false; } return value == EGL_BUFFER_PRESERVED; }
bool CEGLWrapper::SurfaceAttrib(EGLDisplay display, EGLSurface surface, EGLint attribute, EGLint value) { if ((display == EGL_NO_DISPLAY) || (surface == EGL_NO_SURFACE)) return false; return eglSurfaceAttrib(display, surface, attribute, value); }
JNIEXPORT jboolean JNICALL Java_org_lwjgl_opengles_EGL_neglSurfaceAttrib(JNIEnv *env, jclass clazz, jlong dpy_ptr, jlong surface_ptr, jint attribute, jint value) { EGLDisplay dpy = (EGLDisplay)(intptr_t)dpy_ptr; EGLSurface surface = (EGLSurface)(intptr_t)surface_ptr; return eglSurfaceAttrib(dpy, surface, attribute, value); }
QEglContext *QVGEGLWindowSurfaceDirect::ensureContext(QWidget *widget) { QSize newSize = windowSurfaceSize(widget); QEglProperties surfaceProps; #if defined(QVG_RECREATE_ON_SIZE_CHANGE) #if !defined(QVG_NO_SINGLE_CONTEXT) if (context && size != newSize) { // The surface size has changed, so we need to recreate it. // We can keep the same context and paint engine. size = newSize; if (isPaintingActive) context->doneCurrent(); context->destroySurface(windowSurface); #if defined(EGL_VG_ALPHA_FORMAT_PRE_BIT) if (isPremultipliedContext(context)) { surfaceProps.setValue (EGL_VG_ALPHA_FORMAT, EGL_VG_ALPHA_FORMAT_PRE); } else { surfaceProps.removeValue(EGL_VG_ALPHA_FORMAT); } #endif windowSurface = context->createSurface(widget, &surfaceProps); isPaintingActive = false; needToSwap = true; } #else if (context && size != newSize) { // The surface size has changed, so we need to recreate // the EGL context for the widget. We also need to recreate // the surface's paint engine if context sharing is not // enabled because we cannot reuse the existing paint objects // in the new context. qt_vg_destroy_paint_engine(engine); engine = 0; context->destroySurface(windowSurface); qt_vg_destroy_context(context, QInternal::Widget); context = 0; windowSurface = EGL_NO_SURFACE; } #endif #endif if (!context) { // Create a new EGL context and bind it to the widget surface. size = newSize; context = qt_vg_create_context(widget, QInternal::Widget); if (!context) return 0; // We want a direct to window rendering surface if possible. #if defined(QVG_DIRECT_TO_WINDOW) surfaceProps.setValue(EGL_RENDER_BUFFER, EGL_SINGLE_BUFFER); #endif #if defined(EGL_VG_ALPHA_FORMAT_PRE_BIT) if (isPremultipliedContext(context)) { surfaceProps.setValue (EGL_VG_ALPHA_FORMAT, EGL_VG_ALPHA_FORMAT_PRE); } else { surfaceProps.removeValue(EGL_VG_ALPHA_FORMAT); } #endif EGLSurface surface = context->createSurface(widget, &surfaceProps); if (surface == EGL_NO_SURFACE) { qt_vg_destroy_context(context, QInternal::Widget); context = 0; return 0; } needToSwap = true; #if defined(QVG_DIRECT_TO_WINDOW) // Did we get a direct to window rendering surface? EGLint buffer = 0; if (eglQueryContext(QEgl::display(), context->context(), EGL_RENDER_BUFFER, &buffer) && buffer == EGL_SINGLE_BUFFER) { needToSwap = false; } #endif windowSurface = surface; isPaintingActive = false; } #if !defined(QVG_NO_PRESERVED_SWAP) // Try to force the surface back buffer to preserve its contents. if (needToSwap) { eglGetError(); // Clear error state first. eglSurfaceAttrib(QEgl::display(), windowSurface, EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED); if (eglGetError() != EGL_SUCCESS) { qWarning("QVG: could not enable preserved swap"); } } #endif return context; }
// Chooses the EGL config and creates the EGL context bool QGLContext::chooseContext(const QGLContext* shareContext) // almost same as in qgl_x11egl.cpp { Q_D(QGLContext); if (!device()) return false; int devType = device()->devType(); if ((devType != QInternal::Widget) && (devType != QInternal::Pbuffer)) { qWarning("WARNING: Creating a QGLContext not supported on device type %d", devType); return false; } // Get the display and initialize it. if (d->eglContext == 0) { d->eglContext = new QEglContext(); d->ownsEglContext = true; d->eglContext->setApi(QEgl::OpenGL); if (d->glFormat.samples() == EGL_DONT_CARE) { // Allow apps to override ability to use multisampling by setting an environment variable. Eg: // qputenv("QT_SYMBIAN_DISABLE_GL_MULTISAMPLE", "1"); // Added to allow camera app to start with limited memory. if (!QSymbianGraphicsSystemEx::hasBCM2727() && !qgetenv("QT_SYMBIAN_DISABLE_GL_MULTISAMPLE").toInt()) { // Most likely we have hw support for multisampling // so let's enable it. d->glFormat.setSampleBuffers(1); d->glFormat.setSamples(4); } else { d->glFormat.setSampleBuffers(0); d->glFormat.setSamples(0); } } // If the device is a widget with WA_TranslucentBackground set, make sure the glFormat // has the alpha channel option set: if (devType == QInternal::Widget) { QWidget* widget = static_cast<QWidget*>(device()); if (widget->testAttribute(Qt::WA_TranslucentBackground)) d->glFormat.setAlpha(true); } // Construct the configuration we need for this surface. QEglProperties configProps; configProps.setDeviceType(devType); configProps.setPaintDeviceFormat(device()); configProps.setRenderableType(QEgl::OpenGL); configProps.setValue(EGL_SURFACE_TYPE, EGL_WINDOW_BIT|EGL_SWAP_BEHAVIOR_PRESERVED_BIT); qt_eglproperties_set_glformat(configProps, d->glFormat); if (!d->eglContext->chooseConfig(configProps, QEgl::BestPixelFormat)) { delete d->eglContext; d->eglContext = 0; return false; } // Create a new context for the configuration. QEglContext* eglSharedContext = shareContext ? shareContext->d_func()->eglContext : 0; if (!d->eglContext->createContext(eglSharedContext)) { delete d->eglContext; d->eglContext = 0; return false; } d->sharing = d->eglContext->isSharing(); if (d->sharing && shareContext) const_cast<QGLContext *>(shareContext)->d_func()->sharing = true; } // Inform the higher layers about the actual format properties qt_glformat_from_eglconfig(d->glFormat, d->eglContext->config()); // Do don't create the EGLSurface for everything. // QWidget - yes, create the EGLSurface and store it in QGLContextPrivate::eglSurface // QGLWidget - yes, create the EGLSurface and store it in QGLContextPrivate::eglSurface // QGLPixelBuffer - no, it creates the surface itself and stores it in QGLPixelBufferPrivate::pbuf if (devType == QInternal::Widget) { if (d->eglSurface != EGL_NO_SURFACE) eglDestroySurface(d->eglContext->display(), d->eglSurface); d->eglSurface = QEgl::createSurface(device(), d->eglContext->config()); eglGetError(); // Clear error state first. #ifdef QGL_NO_PRESERVED_SWAP eglSurfaceAttrib(QEgl::display(), d->eglSurface, EGL_SWAP_BEHAVIOR, EGL_BUFFER_DESTROYED); if (eglGetError() != EGL_SUCCESS) qWarning("QGLContext: could not enable destroyed swap behaviour"); #else eglSurfaceAttrib(QEgl::display(), d->eglSurface, EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED); if (eglGetError() != EGL_SUCCESS) qWarning("QGLContext: could not enable preserved swap behaviour"); #endif setWindowCreated(true); } return true; }
void EglOnXBackend::init() { if (!initRenderingContext()) { setFailed(QStringLiteral("Could not initialize rendering context")); return; } initEGL(); if (!hasGLExtension(QStringLiteral("EGL_KHR_image")) && (!hasGLExtension(QStringLiteral("EGL_KHR_image_base")) || !hasGLExtension(QStringLiteral("EGL_KHR_image_pixmap")))) { setFailed(QStringLiteral("Required support for binding pixmaps to EGLImages not found, disabling compositing")); return; } GLPlatform *glPlatform = GLPlatform::instance(); glPlatform->detect(EglPlatformInterface); if (GLPlatform::instance()->driver() == Driver_Intel) options->setUnredirectFullscreen(false); // bug #252817 options->setGlPreferBufferSwap(options->glPreferBufferSwap()); // resolve autosetting if (options->glPreferBufferSwap() == Options::AutoSwapStrategy) options->setGlPreferBufferSwap('e'); // for unknown drivers - should not happen glPlatform->printResults(); initGL(EglPlatformInterface); if (!hasGLExtension(QStringLiteral("GL_OES_EGL_image"))) { setFailed(QStringLiteral("Required extension GL_OES_EGL_image not found, disabling compositing")); return; } // check for EGL_NV_post_sub_buffer and whether it can be used on the surface if (eglPostSubBufferNV) { if (eglQuerySurface(dpy, surface, EGL_POST_SUB_BUFFER_SUPPORTED_NV, &surfaceHasSubPost) == EGL_FALSE) { EGLint error = eglGetError(); if (error != EGL_SUCCESS && error != EGL_BAD_ATTRIBUTE) { setFailed(QStringLiteral("query surface failed")); return; } else { surfaceHasSubPost = EGL_FALSE; } } } setSupportsBufferAge(false); if (hasGLExtension("EGL_EXT_buffer_age")) { const QByteArray useBufferAge = qgetenv("KWIN_USE_BUFFER_AGE"); if (useBufferAge != "0") setSupportsBufferAge(true); } setSyncsToVBlank(false); setBlocksForRetrace(false); gs_tripleBufferNeedsDetection = false; m_swapProfiler.init(); if (surfaceHasSubPost) { qDebug() << "EGL implementation and surface support eglPostSubBufferNV, let's use it"; if (options->glPreferBufferSwap() != Options::NoSwapEncourage) { // check if swap interval 1 is supported EGLint val; eglGetConfigAttrib(dpy, config, EGL_MAX_SWAP_INTERVAL, &val); if (val >= 1) { if (eglSwapInterval(dpy, 1)) { qDebug() << "Enabled v-sync"; setSyncsToVBlank(true); const QByteArray tripleBuffer = qgetenv("KWIN_TRIPLE_BUFFER"); if (!tripleBuffer.isEmpty()) { setBlocksForRetrace(qstrcmp(tripleBuffer, "0") == 0); gs_tripleBufferUndetected = false; } gs_tripleBufferNeedsDetection = gs_tripleBufferUndetected; } } else { qWarning() << "Cannot enable v-sync as max. swap interval is" << val; } } else { // disable v-sync eglSwapInterval(dpy, 0); } } else { /* In the GLX backend, we fall back to using glCopyPixels if we have no extension providing support for partial screen updates. * However, that does not work in EGL - glCopyPixels with glDrawBuffer(GL_FRONT); does nothing. * Hence we need EGL to preserve the backbuffer for us, so that we can draw the partial updates on it and call * eglSwapBuffers() for each frame. eglSwapBuffers() then does the copy (no page flip possible in this mode), * which means it is slow and not synced to the v-blank. */ qWarning() << "eglPostSubBufferNV not supported, have to enable buffer preservation - which breaks v-sync and performance"; eglSurfaceAttrib(dpy, surface, EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED); } }
void showRenderBuffer() { int i; EGLContext eglContext; EGLDisplay eglDisplay; EGLSurface eglSurface; grs_font *font; JNIEnv *env; jclass clazz; jmethodID method; if (Want_pause) { // Save this in case we need to destroy it later eglContext = eglGetCurrentContext(); eglDisplay = eglGetCurrentDisplay(); eglSurface = eglGetCurrentSurface(EGL_DRAW); // Close digi so another application can use the OpenSL ES objects digi_close_digi(); (*jvm)->GetEnv(jvm, (void **) &env, JNI_VERSION_1_6); clazz = (*env)->FindClass(env, "tuchsen/descent/DescentView"); // Pause this thread method = (*env)->GetMethodID(env, clazz, "pauseRenderThread", "()V"); (*env)->CallVoidMethod(env, Descent_view, method); digi_init_digi(); if (Surface_was_destroyed) { // Purge all texture assets, since the EGL context will be blown away for (i = 0; i < MAX_FONTS; ++i) { font = Gamefonts[i]; glDeleteTextures(font->ft_maxchar - font->ft_minchar, font->ft_ogles_texes); memset(font->ft_ogles_texes, 0, (font->ft_maxchar - font->ft_minchar) * sizeof(GLuint)); } for (i = 0; i < MAX_BITMAP_FILES; ++i) { glDeleteTextures(1, &GameBitmaps[i].bm_ogles_tex_id); GameBitmaps[i].bm_ogles_tex_id = 0; } texmerge_close(); texmerge_init(50); glDeleteTextures(1, &nm_background.bm_ogles_tex_id); nm_background.bm_ogles_tex_id = 0; // Blow away EGL surface and context eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); eglDestroySurface(eglDisplay, eglSurface); eglDestroyContext(eglDisplay, eglContext); eglTerminate(eglDisplay); // Reset EGL context method = (*env)->GetMethodID(env, clazz, "initEgl", "()V"); (*env)->CallVoidMethod(env, Descent_view, method); (*env)->DeleteLocalRef(env, clazz); eglSurfaceAttrib(eglGetCurrentDisplay(), eglGetCurrentSurface(EGL_DRAW), EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Hack to show stuff like menus if (Game_mode != GM_NORMAL || In_screen) { mouse_handler(-1, -1, true); mouse_handler(-1, -1, false); } Surface_was_destroyed = false; } Want_pause = false; } else { draw_buttons(); eglSwapBuffers(eglGetCurrentDisplay(), eglGetCurrentSurface(EGL_READ)); can_save_screen = !can_save_screen; } }
// oglinit sets the display, OpenGL|ES context and screen information // state holds the OGLES model information extern void oglinit(STATE_T * state) { int32_t success = 0; EGLBoolean result; EGLint num_config; static EGL_DISPMANX_WINDOW_T nativewindow; DISPMANX_ELEMENT_HANDLE_T dispman_element; DISPMANX_DISPLAY_HANDLE_T dispman_display; DISPMANX_UPDATE_HANDLE_T dispman_update; VC_RECT_T dst_rect; VC_RECT_T src_rect; static const EGLint attribute_list[] = { EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_ALPHA_SIZE, 8, EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_NONE }; EGLConfig config; // get an EGL display connection state->display = eglGetDisplay(EGL_DEFAULT_DISPLAY); assert(state->display != EGL_NO_DISPLAY); // initialize the EGL display connection result = eglInitialize(state->display, NULL, NULL); assert(EGL_FALSE != result); // bind OpenVG API eglBindAPI(EGL_OPENVG_API); // get an appropriate EGL frame buffer configuration result = eglChooseConfig(state->display, attribute_list, &config, 1, &num_config); assert(EGL_FALSE != result); // create an EGL rendering context state->context = eglCreateContext(state->display, config, EGL_NO_CONTEXT, NULL); assert(state->context != EGL_NO_CONTEXT); // create an EGL window surface success = graphics_get_display_size(0 /* LCD */ , &state->screen_width, &state->screen_height); assert(success >= 0); dst_rect.x = 0; dst_rect.y = 0; dst_rect.width = state->screen_width; dst_rect.height = state->screen_height; src_rect.x = 0; src_rect.y = 0; src_rect.width = state->screen_width << 16; src_rect.height = state->screen_height << 16; dispman_display = vc_dispmanx_display_open(0 /* LCD */ ); dispman_update = vc_dispmanx_update_start(0); dispman_element = vc_dispmanx_element_add(dispman_update, dispman_display, 0 /*layer */ , &dst_rect, 0 /*src */ , &src_rect, DISPMANX_PROTECTION_NONE, 0 /*alpha */ , 0 /*clamp */ , 0 /*transform */ ); nativewindow.element = dispman_element; nativewindow.width = state->screen_width; nativewindow.height = state->screen_height; vc_dispmanx_update_submit_sync(dispman_update); state->surface = eglCreateWindowSurface(state->display, config, &nativewindow, NULL); assert(state->surface != EGL_NO_SURFACE); // preserve the buffers on swap result = eglSurfaceAttrib(state->display, state->surface, EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED); assert(EGL_FALSE != result); // connect the context to the surface result = eglMakeCurrent(state->display, state->surface, state->surface, state->context); assert(EGL_FALSE != result); // set up screen ratio glViewport(0, 0, (GLsizei) state->screen_width, (GLsizei) state->screen_height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); float ratio = (float)state->screen_width / (float)state->screen_height; glFrustumf(-ratio, ratio, -1.0f, 1.0f, 1.0f, 10.0f); }
EGLSurface EglManager::createSurface(EGLNativeWindowType window, bool wideColorGamut) { initialize(); wideColorGamut = wideColorGamut && EglExtensions.glColorSpace && EglExtensions.scRGB && EglExtensions.pixelFormatFloat && EglExtensions.noConfigContext; // The color space we want to use depends on whether linear blending is turned // on and whether the app has requested wide color gamut rendering. When wide // color gamut rendering is off, the app simply renders in the display's native // color gamut. // // When wide gamut rendering is off: // - Blending is done by default in gamma space, which requires using a // linear EGL color space (the GPU uses the color values as is) // - If linear blending is on, we must use the sRGB EGL color space (the // GPU will perform sRGB to linear and linear to SRGB conversions before // and after blending) // // When wide gamut rendering is on we cannot rely on the GPU performing // linear blending for us. We use two different color spaces to tag the // surface appropriately for SurfaceFlinger: // - Gamma blending (default) requires the use of the scRGB-nl color space // - Linear blending requires the use of the scRGB color space // Not all Android targets support the EGL_GL_COLOR_SPACE_KHR extension // We insert to placeholders to set EGL_GL_COLORSPACE_KHR and its value. // According to section 3.4.1 of the EGL specification, the attributes // list is considered empty if the first entry is EGL_NONE EGLint attribs[] = {EGL_NONE, EGL_NONE, EGL_NONE}; if (EglExtensions.glColorSpace) { attribs[0] = EGL_GL_COLORSPACE_KHR; #ifdef ANDROID_ENABLE_LINEAR_BLENDING if (wideColorGamut) { attribs[1] = EGL_GL_COLORSPACE_SCRGB_LINEAR_EXT; } else { attribs[1] = EGL_GL_COLORSPACE_SRGB_KHR; } #else if (wideColorGamut) { attribs[1] = EGL_GL_COLORSPACE_SCRGB_EXT; } else { attribs[1] = EGL_GL_COLORSPACE_LINEAR_KHR; } #endif } EGLSurface surface = eglCreateWindowSurface( mEglDisplay, wideColorGamut ? mEglConfigWideGamut : mEglConfig, window, attribs); LOG_ALWAYS_FATAL_IF(surface == EGL_NO_SURFACE, "Failed to create EGLSurface for window %p, eglErr = %s", (void*)window, eglErrorString()); if (mSwapBehavior != SwapBehavior::Preserved) { LOG_ALWAYS_FATAL_IF(eglSurfaceAttrib(mEglDisplay, surface, EGL_SWAP_BEHAVIOR, EGL_BUFFER_DESTROYED) == EGL_FALSE, "Failed to set swap behavior to destroyed for window %p, eglErr = %s", (void*)window, eglErrorString()); } return surface; }