Exemplo n.º 1
0
void EglOnXBackend::present()
{
    if (lastDamage().isEmpty())
        return;

    const QRegion displayRegion(0, 0, displayWidth(), displayHeight());
    const bool fullRepaint = supportsBufferAge() || (lastDamage() == displayRegion);

    if (fullRepaint || !surfaceHasSubPost) {
        if (gs_tripleBufferNeedsDetection) {
            eglWaitGL();
            m_swapProfiler.begin();
        }
        // the entire screen changed, or we cannot do partial updates (which implies we enabled surface preservation)
        eglSwapBuffers(dpy, surface);
        if (gs_tripleBufferNeedsDetection) {
            eglWaitGL();
            if (char result = m_swapProfiler.end()) {
                gs_tripleBufferUndetected = gs_tripleBufferNeedsDetection = false;
                if (result == 'd' && GLPlatform::instance()->driver() == Driver_NVidia) {
                    // TODO this is a workaround, we should get __GL_YIELD set before libGL checks it
                    if (qstrcmp(qgetenv("__GL_YIELD"), "USLEEP")) {
                        options->setGlPreferBufferSwap(0);
                        eglSwapInterval(dpy, 0);
                        qWarning() << "\nIt seems you are using the nvidia driver without triple buffering\n"
                                          "You must export __GL_YIELD=\"USLEEP\" to prevent large CPU overhead on synced swaps\n"
                                          "Preferably, enable the TripleBuffer Option in the xorg.conf Device\n"
                                          "For this reason, the tearing prevention has been disabled.\n"
                                          "See https://bugs.kde.org/show_bug.cgi?id=322060\n";
                    }
                }
                setBlocksForRetrace(result == 'd');
            }
        }
        if (supportsBufferAge()) {
            eglQuerySurface(dpy, surface, EGL_BUFFER_AGE_EXT, &m_bufferAge);
        }
    } else {
        // a part of the screen changed, and we can use eglPostSubBufferNV to copy the updated area
        foreach (const QRect & r, lastDamage().rects()) {
            eglPostSubBufferNV(dpy, surface, r.left(), displayHeight() - r.bottom() - 1, r.width(), r.height());
        }
    }

    setLastDamage(QRegion());
    if (!supportsBufferAge()) {
        eglWaitGL();
        xcb_flush(connection());
    }
}
/* EGLBoolean eglWaitGL ( void ) */
static jboolean
android_eglWaitGL
  (JNIEnv *_env, jobject _this) {
    EGLBoolean _returnValue = (EGLBoolean) 0;
    _returnValue = eglWaitGL();
    return (jboolean)_returnValue;
}
Exemplo n.º 3
0
/*!***********************************************************************
 @Function		ApiRenderComplete
 @description	Perform API operations required after a frame has finished (e.g., flipping).
*************************************************************************/
void PVRShellInit::ApiRenderComplete()
{
	bool bRes;

	if(m_pShell->m_pShellData->bNeedPixmap)
	{
		/*
			"Clients rendering to single buffered surfaces (e.g. pixmap surfaces)
			should call eglWaitGL before accessing the native pixmap from the client."
		*/
		eglWaitGL();

		// Pixmap support: Copy the rendered pixmap to the display
		if(m_pShell->m_pShellData->bNeedPixmapDisableCopy)
		{
			bRes = true;
		}
		else
		{
			bRes = OsPixmapCopy();
		}
	}
	else
	{
		if(m_pShell->m_pShellData->bNoShellSwapBuffer)
			return;

		bRes = (eglSwapBuffers (m_EGLDisplay, m_EGLWindow) == EGL_TRUE);
	}

	if(!bRes)
	{
		// check for context loss
#ifdef EGL_VERSION_1_3
		if(eglGetError() == EGL_CONTEXT_LOST)
#else
		if((eglGetError() == EGL_CONTEXT_LOST_IMG) && m_bPowerManagementSupported)
#endif
		{
			m_pShell->ReleaseView();

			OsDoReleaseAPI();
			if(ApiInitAPI())
			{
				m_pShell->InitView();
			}
		}
		else
		{
			if(m_pShell->m_pShellData->bNeedPixmap)
				m_pShell->PVRShellOutputDebug("failed to copy pixmap\n");
			else
				m_pShell->PVRShellOutputDebug("eglSwapBuffers failed\n");
		}
	}
}
Exemplo n.º 4
0
/*  private native int _eglWaitGL ( ) ; */
KNIEXPORT KNI_RETURNTYPE_INT
Java_javax_microedition_khronos_egl_EGL10Impl__1eglWaitGL() {

    jint returnValue = (jint)eglWaitGL();
#ifdef DEBUG
    printf("eglWaitGL() = %d\n", returnValue);
#endif

    KNI_ReturnInt(returnValue);
}
Exemplo n.º 5
0
//swapping buffers
void common_eglswapbuffers(
			struct globalStruct *globals,
						   EGLDisplay eglDisplay, 
						   EGLSurface eglSurface
						   )
{
	if(globals->inSurfaceType == SGXPERF_SURFACE_TYPE_WINDOW)
		eglSwapBuffers(eglDisplay, eglSurface);
	else if(globals->inSurfaceType == SGXPERF_SURFACE_TYPE_PIXMAP_16 || globals->inSurfaceType == SGXPERF_SURFACE_TYPE_PIXMAP_32)
		eglWaitGL();
}
Exemplo n.º 6
0
static void     _egl_beg        (s52engine *engine)
{
    // On Android, Blit x10 slower whitout
    if (EGL_FALSE == eglWaitGL()) {
        g_print("_egl_beg(): eglWaitGL() failed. [0x%x]\n", eglGetError());
        return;
    }

    if (EGL_FALSE == eglMakeCurrent(engine->eglDisplay, engine->eglSurface, engine->eglSurface, engine->eglContext)) {
        g_print("_egl_beg(): eglMakeCurrent() failed. [0x%x]\n", eglGetError());
    }

    return;
}
Exemplo n.º 7
0
void EGLXTransportSurfaceClient::destroy()
{
    GLTransportSurfaceClient::destroy();

    if (m_eglImage) {
        m_eglImage->destroy();
        m_eglImage = nullptr;
    }

    eglWaitGL();

    if (m_image) {
        XDestroyImage(m_image);
        m_image = 0;
    }
}
Exemplo n.º 8
0
// Wait for client OpenGL/OpenVG operations to complete before
// using native rendering operations.
void QEglContext::waitClient()
{
#ifdef EGL_OPENGL_ES_API
    if (apiType == OpenGL) {
        eglBindAPI(EGL_OPENGL_ES_API);
        eglWaitClient();
    }
#else
    if (apiType == OpenGL)
        eglWaitGL();
#endif
#ifdef EGL_OPENVG_API
    if (apiType == OpenVG) {
        eglBindAPI(EGL_OPENVG_API);
        eglWaitClient();
    }
#endif
}
Exemplo n.º 9
0
int
PND_gl_swapwindow(_THIS, SDL_Window * window)
{
    SDL_VideoData *phdata = (SDL_VideoData *) _this->driverdata;
    SDL_WindowData *wdata = (SDL_WindowData *) window->driverdata;

    if (phdata->egl_initialized != SDL_TRUE) {
        return SDL_SetError("PND: GLES initialization failed, no OpenGL ES support");
    }

    /* Many applications do not uses glFinish(), so we call it for them */
    glFinish();

    /* Wait until OpenGL ES rendering is completed */
    eglWaitGL();

    eglSwapBuffers(phdata->egl_display, wdata->gles_surface);
    return 0;
}
Exemplo n.º 10
0
void EGLTextureFromPixmap::destroy()
{
    eglWaitNative(EGL_CORE_NATIVE_ENGINE);

    if (m_surface != EGL_NO_SURFACE)
        eglReleaseTexImage(EGLHelper::eglDisplay(), m_surface, EGL_BACK_BUFFER);

    if (m_eglImage) {
        EGLHelper::destroyEGLImage(m_eglImage);
        m_eglImage = 0;
    }

    if (m_surface != EGL_NO_SURFACE) {
        eglDestroySurface(EGLHelper::eglDisplay(), m_surface);
        m_surface = EGL_NO_SURFACE;
    }

    eglWaitGL();
}
Exemplo n.º 11
0
static void
clutter_backend_egl_redraw (ClutterBackend *backend,
                            ClutterStage   *stage)
{
    ClutterBackendEGL  *backend_egl = CLUTTER_BACKEND_EGL (backend);
    ClutterStageEGL    *stage_egl;
    ClutterStageWindow *impl;

    impl = _clutter_stage_get_window (stage);
    if (!impl)
        return;

    g_assert (CLUTTER_IS_STAGE_EGL (impl));
    stage_egl = CLUTTER_STAGE_EGL (impl);

    eglWaitNative (EGL_CORE_NATIVE_ENGINE);
    clutter_actor_paint (CLUTTER_ACTOR (stage));
    cogl_flush ();
    eglWaitGL();
    eglSwapBuffers (backend_egl->edpy,  stage_egl->egl_surface);
}
Exemplo n.º 12
0
EGLBoolean eglWaitClient()
{
    return eglWaitGL();
}
static jboolean jni_eglWaitGL(JNIEnv *_env, jobject _this) {
    return EglBoolToJBool(eglWaitGL());
}
Exemplo n.º 14
0
PyObject *egl_swapbuffers(PyObject *self, PyObject *args) {
    eglWaitGL();
    eglSwapBuffers(display, surface);
    Py_INCREF(Py_None);
    return Py_None;
}
Exemplo n.º 15
0
static int test_transparentalpha(display_t * disp)
{
   int32_t           surfattr[] = {
                        gconfig_TRANSPARENT_ALPHA, 1,
                        gconfig_BITS_BUFFER, 32, gconfig_NONE
                     };
   windowconfig_t    winattr[]  = {
                        windowconfig_INIT_TITLE("test-graphic-window"),
                        windowconfig_INIT_SIZE(100, 100),
                        windowconfig_INIT_POS(50, 100),
                        windowconfig_INIT_NONE
                     };
   window_t    top      = window_FREE;
   window_t    bottom   = window_FREE;
   gconfig_t   gconf = gconfig_FREE;
   uint32_t    snr      = defaultscreennr_display(disp);
   EGLContext  eglcontext = EGL_NO_CONTEXT;

   // prepare
   TEST(0 == init_gconfig(&gconf, disp, surfattr));
   eglcontext = eglCreateContext(gl_display(disp), gl_gconfig(&gconf), EGL_NO_CONTEXT, 0);
   TEST(EGL_NO_CONTEXT != eglcontext);

   // TEST init_window: gconfig_TRANSPARENT_ALPHA: draw overlay on top of bottom
   TEST(0 == init_window(&top, disp, snr, 0, &gconf, winattr));
   TEST(0 == init_window(&bottom, disp, snr, 0, &gconf, winattr));

   // TEST swapbuffer_window: bottom window opaque color
   TEST(0 == show_x11window(os_window(&bottom)));
   WAITFOR(disp, os_window(&bottom)->state == x11window_state_SHOWN);
   TEST(EGL_TRUE == eglMakeCurrent(gl_display(disp), (void*)gl_window(&bottom), (void*)gl_window(&bottom), eglcontext));
   glClearColor(1, 0, 0, 1);
   glClear(GL_COLOR_BUFFER_BIT);
   TEST(0 == swapbuffer_window(&bottom, disp));
   eglWaitGL();
   // red color
   TEST(0 == compare_color(os_window(&bottom), 100, 100, 1, 0, 0));

   // TEST swapbuffer_window: top window with transparent value
   TEST(0 == show_x11window(os_window(&top)));
   WAITFOR(disp, os_window(&top)->state == x11window_state_SHOWN);
   TEST(EGL_TRUE == eglMakeCurrent(gl_display(disp), (void*)gl_window(&top), (void*)gl_window(&top), eglcontext));
   glClearColor(0, 0, 1, 0); // transparent blue
   glClear(GL_COLOR_BUFFER_BIT);
   TEST(0 == swapbuffer_window(&top, disp));
   eglWaitGL();
   // resulting color is the combination of red and blue
   TEST(0 == compare_color(os_window(&bottom), 100, 100, 1, 0, 1));

   // unprepare
	TEST(EGL_TRUE == eglMakeCurrent(gl_display(disp), EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
	TEST(EGL_TRUE == eglDestroyContext(gl_display(disp), eglcontext));
   TEST(0 == free_gconfig(&gconf));
   TEST(0 == free_window(&bottom));
   TEST(0 == free_window(&top));
   WAITFOR(disp, false);
   eglReleaseThread();

   return 0;
ONERR:
   eglMakeCurrent(gl_display(disp), EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
   if (eglcontext != EGL_NO_CONTEXT) eglDestroyContext(gl_display(disp), eglcontext);
   (void) free_gconfig(&gconf);
   (void) free_window(&top);
   (void) free_window(&bottom);
   return EINVAL;
}
Exemplo n.º 16
0
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR pCmdLine, int nCmdShow)
{
   int i;

   // Windows variables
   HWND hWnd=0;
   HDC  hDC=0;

   // EGL variables
   EGLDisplay eglDisplay=0;
   EGLConfig  eglConfig=0;
   EGLSurface eglSurface=0;
   EGLContext eglContext=0;
   NativeWindowType eglWindow=0;
   EGLint pi32ConfigAttribs[128];
   unsigned int nWidth;
   unsigned int nHeight;
   ATOM registerClass;
   RECT sRect;
   EGLint iMajorVersion, iMinorVersion;
   int iConfigs;

   /*
      Step 0 - Create a NativeWindowType that we can use for OpenGL ES output
   */

   // Register the windows class
   WNDCLASS sWC;

   sWC.style=CS_HREDRAW | CS_VREDRAW;
   sWC.lpfnWndProc=WndProc;
   sWC.cbClsExtra=0;
   sWC.cbWndExtra=0;
   sWC.hInstance=hInstance;
   sWC.hIcon=0;
   sWC.hCursor=0;
   sWC.lpszMenuName=0;
   sWC.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);
   sWC.lpszClassName=WINDOW_CLASS;

   nWidth=WINDOW_WIDTH;
   nHeight=WINDOW_HEIGHT;

   registerClass=RegisterClass(&sWC);
   if (!registerClass)
   {
      MessageBox(0, _T("Failed to register the window class"), _T("Error"), MB_OK | MB_ICONEXCLAMATION);
   }

   // Create the eglWindow
   SetRect(&sRect, 0, 0, nWidth, nHeight);
   AdjustWindowRectEx(&sRect, WS_CAPTION | WS_SYSMENU, 0, 0);
   hWnd=CreateWindow(WINDOW_CLASS, _T("GLU ES Tesselation test"), WS_VISIBLE | WS_SYSMENU, 0, 0, nWidth, nHeight, NULL, NULL, hInstance, NULL);
   eglWindow=hWnd;

   // Get the associated device context
   hDC=GetDC(hWnd);
   if (!hDC)
   {
      MessageBox(0, _T("Failed to create the device context"), _T("Error"), MB_OK|MB_ICONEXCLAMATION);
      goto cleanup;
   }

   /*
      Step 1 - Get the default display.
      EGL uses the concept of a "display" which in most environments
      corresponds to a single physical screen. Since we usually want
      to draw to the main screen or only have a single screen to begin
      with, we let EGL pick the default display.
      Querying other displays is platform specific.
   */
   eglDisplay=eglGetDisplay((NativeDisplayType)hDC);

   if(eglDisplay==EGL_NO_DISPLAY)
   {
      eglDisplay=eglGetDisplay((NativeDisplayType)EGL_DEFAULT_DISPLAY);
   }

   /*
      Step 2 - Initialize EGL.
      EGL has to be initialized with the display obtained in the
      previous step. We cannot use other EGL functions except
      eglGetDisplay and eglGetError before eglInitialize has been
      called.
      If we're not interested in the EGL version number we can just
      pass NULL for the second and third parameters.
   */

   if (!eglInitialize(eglDisplay, &iMajorVersion, &iMinorVersion))
   {
      MessageBox(0, _T("eglInitialize() failed."), _T("Error"), MB_OK | MB_ICONEXCLAMATION);
      goto cleanup;
   }

   /*
      Step 3 - Specify the required configuration attributes.
      An EGL "configuration" describes the pixel format and type of
      surfaces that can be used for drawing.
      For now we just want to use a 16 bit RGB surface that is a
      Window surface, i.e. it will be visible on screen. The list
      has to contain key/value pairs, terminated with EGL_NONE.
   */
   i=0;

   pi32ConfigAttribs[i++]=EGL_RED_SIZE;
   pi32ConfigAttribs[i++]=5;
   pi32ConfigAttribs[i++]=EGL_GREEN_SIZE;
   pi32ConfigAttribs[i++]=6;
   pi32ConfigAttribs[i++]=EGL_BLUE_SIZE;
   pi32ConfigAttribs[i++]=5;
   pi32ConfigAttribs[i++]=EGL_ALPHA_SIZE;
   pi32ConfigAttribs[i++]=0;
   pi32ConfigAttribs[i++]=EGL_DEPTH_SIZE;
   pi32ConfigAttribs[i++]=16;
   pi32ConfigAttribs[i++]=EGL_SURFACE_TYPE;
   pi32ConfigAttribs[i++]=EGL_WINDOW_BIT;
   pi32ConfigAttribs[i++]=EGL_NONE;

   /*
      Step 4 - Find a config that matches all requirements.
      eglChooseConfig provides a list of all available configurations
      that meet or exceed the requirements given as the second
      argument. In most cases we just want the first config that meets
      all criteria, so we can limit the number of configs returned to 1.
   */
   if (!eglChooseConfig(eglDisplay, pi32ConfigAttribs, &eglConfig, 1, &iConfigs) || (iConfigs != 1))
   {
      MessageBox(0, _T("eglChooseConfig() failed."), _T("Error"), MB_OK|MB_ICONEXCLAMATION);
      goto cleanup;
   }

   /*
      Step 5 - Create a surface to draw to.
      Use the config picked in the previous step and the native window
      handle when available to create a window surface. A window surface
      is one that will be visible on screen inside the native display (or
      fullscreen if there is no windowing system).
      Pixmaps and pbuffers are surfaces which only exist in off-screen
      memory.
   */
   eglSurface=eglCreateWindowSurface(eglDisplay, eglConfig, eglWindow, NULL);

   if (eglSurface==EGL_NO_SURFACE)
   {
      eglGetError(); // Clear error
      eglSurface=eglCreateWindowSurface(eglDisplay, eglConfig, NULL, NULL);
   }

   if (!TestEGLError(hWnd, "eglCreateWindowSurface"))
   {
      goto cleanup;
   }

   /*
      Step 6 - Create a context.
      EGL has to create a context for OpenGL ES. Our OpenGL ES resources
      like textures will only be valid inside this context
      (or shared contexts)
   */
   eglContext=eglCreateContext(eglDisplay, eglConfig, NULL, NULL);
   if (!TestEGLError(hWnd, "eglCreateContext"))
   {
      goto cleanup;
   }

   /*
      Step 7 - Bind the context to the current thread and use our
      window surface for drawing and reading.
      Contexts are bound to a thread. This means you don't have to
      worry about other threads and processes interfering with your
      OpenGL ES application.
      We need to specify a surface that will be the target of all
      subsequent drawing operations, and one that will be the source
      of read operations. They can be the same surface.
   */
   eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext);
   if (!TestEGLError(hWnd, "eglMakeCurrent"))
   {
      goto cleanup;
   }

   /* Initialize scene */
   init_scene(WINDOW_WIDTH, WINDOW_HEIGHT);

   /* Render stuff */
   do {
      MSG msg;

	  render_scene();
      glFinish();
      eglWaitGL();
      eglSwapBuffers(eglDisplay, eglSurface);
	  if (done)
	  {
         break;
	  }

      PeekMessage(&msg, hWnd, 0, 0, PM_REMOVE);
      TranslateMessage(&msg);
      DispatchMessage(&msg);

   } while(1);


   /*
      Step 8 - Terminate OpenGL ES and destroy the window (if present).
      eglTerminate takes care of destroying any context or surface created
      with this display, so we don't need to call eglDestroySurface or
      eglDestroyContext here.
   */
cleanup:
   eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
   eglTerminate(eglDisplay);

   /*
      Step 9 - Destroy the eglWindow.
      Again, this is platform specific and delegated to a separate function.
   */

   // Release the device context
   if (hDC)
   {
      ReleaseDC(hWnd, hDC);
   }

   // Destroy the eglWindow
   if (hWnd)
   {
      DestroyWindow(hWnd);
   }

   return 0;
}
static jboolean jni_eglWaitGL(JNIEnv *_env, jobject _this) {
    return eglWaitGL();
}
Exemplo n.º 18
0
JNIEXPORT jboolean JNICALL Java_org_lwjgl_opengles_EGL_eglWaitGL(JNIEnv *env, jclass clazz) {
    return eglWaitGL();
}
Exemplo n.º 19
0
int main(int argc, char** argv)
{
    gf_3d_target_t      target;
    gf_display_t        gf_disp;
    EGLConfig           config;
    EGLContext          econtext;
    EGLint              num_config;
    gf_dev_info_t       info;
    gf_layer_info_t     linfo;
    gf_display_info_t   disp_info;
    GLuint              width, height;
    GLuint              it;

    /* initialize the graphics device */
    if (gf_dev_attach(&gfdev, NULL, &info)!=GF_ERR_OK)
    {
        perror("gf_dev_attach()");
        return -1;
    }

    /* Setup the layer we will use */
    if (gf_display_attach(&gf_disp, gfdev, 0, &disp_info)!=GF_ERR_OK)
    {
        fprintf(stderr, "gf_display_attach() failed\n");
        return -1;
    }

    width=disp_info.xres;
    height=disp_info.yres;

    layer_idx=disp_info.main_layer_index;

    /* get an EGL display connection */
    display=eglGetDisplay(gfdev);
    if (display==EGL_NO_DISPLAY)
    {
        fprintf(stderr, "eglGetDisplay() failed\n");
        return -1;
    }

    if (gf_layer_attach(&layer, gf_disp, layer_idx, 0)!=GF_ERR_OK)
    {
        fprintf(stderr, "gf_layer_attach() failed\n");
        return -1;
    }

    /* initialize the EGL display connection */
    if (eglInitialize(display, NULL, NULL)!=EGL_TRUE)
    {
        fprintf(stderr, "eglInitialize: error 0x%x\n", eglGetError());
        return -1;
    }

    for (it=0;; it++)
    {
        /* Walk through all possible pixel formats for this layer */
        if (gf_layer_query(layer, it, &linfo)==-1)
        {
            fprintf(stderr, "Couldn't find a compatible frame "
                    "buffer configuration on layer %d\n", layer_idx);
            return -1;
        }

        /*
         * We want the color buffer format to match the layer format,
         * so request the layer format through EGL_NATIVE_VISUAL_ID.
         */
        attribute_list[1]=linfo.format;

        /* Look for a compatible EGL frame buffer configuration */
        if (eglChooseConfig(display, attribute_list, &config, 1, &num_config)==EGL_TRUE)
        {
            if (num_config>0)
            {
                break;
            }
        }
    }

    /* create a 3D rendering target */
    if (gf_3d_target_create(&target, layer, NULL, 0, width, height, linfo.format)!=GF_ERR_OK)
    {
        fprintf(stderr, "Unable to create rendering target\n");
        return -1;
    }

    gf_layer_set_src_viewport(layer, 0, 0, width-1, height-1);
    gf_layer_set_dst_viewport(layer, 0, 0, width-1, height-1);
    gf_layer_enable(layer);

    /*
     * The layer settings haven't taken effect yet since we haven't
     * called gf_layer_update() yet.  This is exactly what we want,
     * since we haven't supplied a valid surface to display yet.
     * Later, the OpenGL ES library calls will call gf_layer_update()
     * internally, when  displaying the rendered 3D content.
     */

    /* create an EGL rendering context */
    econtext=eglCreateContext(display, config, EGL_NO_CONTEXT, NULL);
    if (econtext==EGL_NO_CONTEXT)
    {
        fprintf(stderr, "Create context failed: 0x%x\n", eglGetError());
        return -1;
    }

    /* create an EGL window surface */
    surface=eglCreateWindowSurface(display, config, target, NULL);
    if (surface==EGL_NO_SURFACE)
    {
        fprintf(stderr, "Create surface failed: 0x%x\n", eglGetError());
        return -1;
    }

    /* connect the context to the surface */
    if (eglMakeCurrent(display, surface, surface, econtext)==EGL_FALSE)
    {
        fprintf(stderr, "Make current failed: 0x%x\n", eglGetError());
        return -1;
    }

    init_scene(width, height);

    do {
        render_scene();
        glFinish();
        eglWaitGL();
        eglSwapBuffers(display, surface);
    } while(1);

    return 0;
}