Esempio n. 1
0
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;
}
Esempio n. 4
0
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);
}
Esempio n. 6
0
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;
}
Esempio n. 8
0
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);
}
Esempio n. 10
0
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;
}
Esempio n. 12
0
// 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;
}
Esempio n. 13
0
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);
    }
}
Esempio n. 14
0
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;
	}
}
Esempio n. 15
0
// 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;
}