RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX


3D Graphics Made Easier with OpenGL ES for BREW : Page 2

Until recently, developers wanting to provide a 3D graphics experience on BREW faced significant challenges: developing or porting your own 3D engine. With the introduction of OpenGL ES for BREW, you now have access to a state-of-the-art 3D rendering platform that’s portable across mobile platforms and devices.

OpenGL ES for BREW Interfaces
Like other BREW components, you gain access to OpenGL ES through BREW extensions. Two extensions comprise support for OpenGL ES: the IGL interface and IEGL interface. The IGL interface provides the actual 3D graphics engine, while the IEGL interface provides the window manager engine. Thus, to get started, it suffices to write:

ISHELL_CreateInstance(pMe->a.m_pIShell, AEECLSID_GL, (void **)&pIGL)
However, this isn't truly portable. While there's nothing in how BREW interfaces are written that prevents porting the extension concept over to other platforms, doing so would be at odds with many other platforms, such as the traditional "function-call-to-a-library" approach of Linux, or the C++ framework used by Symbian. Instead, Qualcomm provides an interface file, GL.c, that contains the actual OpenGL ES interfaces written as C calls to the IGL and IEGL interfaces. While you don't have to use these calls directly, it's better that you do, because your code will be more portable, and match the OpenGL ES specifications and documentation.

Starting with OpenGL ES
As suggested in the last section, you should use the functions in GL.c rather than the native extension interfaces for maximum portability. To do this, you need to initialize the OpenGL ES functions with the extension interfaces you create, typically at application startup:

if( ISHELL_CreateInstance(pMe->a.m_pIShell, AEECLSID_GL, (void **)&pMe->pIGL) != SUCCESS )
  return FALSE;
  // To use the standard OpenGL|ES APIs must call IGL_Init()

if( ISHELL_CreateInstance(pMe->a.m_pIShell, AEECLSID_EGL, (void **)&pMe->pIEGL) != SUCCESS )
  return FALSE;
  // To use the standard EGL APIs must call IEGL_Init()
You will need to keep these interfaces around, because when it's time to clean up, you're responsible for freeing them.

Next, obtain your display bitmap, so you can share the bitmap with the OpenGL ES interfaces:

if( IDISPLAY_GetDeviceBitmap(pMe->a.m_pIDisplay, &pMe->pDDBitmap) != SUCCESS )
  return FALSE;
if( IBITMAP_GetInfo(pMe->pDDBitmap, &pMe->sDDBitmapInfo, sizeof(AEEBitmapInfo)) != SUCCESS )
  return FALSE;
By getting the device bitmap from the display, you can also use OpenGL on other displays on the handset where the manufacturer has enabled external display access through IDisplay.

Finally, it's time to initialize the window manager and graphics engine. This involves setting the main display, window surface, and context for the window manager, followed by specifying various parameters for the graphics engine itself:

EGLConfig cfg;
EGLint ncfg = 1;

pMe->eglDisplay		= EGL_NO_DISPLAY;
pMe->eglSurface		= EGL_NO_SURFACE;
pMe->eglContext		= EGL_NO_CONTEXT;

// Set the display to the main display
pMe->eglDisplay = eglGetDisplay( pMe->a.m_pIDisplay );
if( pMe->eglDisplay == EGL_NO_DISPLAY || 
    eglGetError() != EGL_SUCCESS ) 
  return FALSE;

// Initialize the display
if( eglInitialize( pMe->eglDisplay, NULL, NULL ) == EGL_FALSE || 
    eglGetError() != EGL_SUCCESS )
	return FALSE;
// Get display configuration	
eglGetConfigs( pMe->eglDisplay, &cfg, 1, &ncfg );

// Create the window surface using our display’s bitmap.
if( IBITMAP_QueryInterface(pMe->pDDBitmap,AEECLSID_DIB,(void**)&pDIB)!=SUCCESS)
  return EFAILED;
pMe->eglSurface = eglCreateWindowSurface( pMe->eglDisplay, cfg, pDIB, params );
IDIB_Release( pDIB );
if( pMe->eglSurface == EGL_NO_SURFACE || eglGetError() != EGL_SUCCESS )
  return FALSE;

// Create the context used to render on the new window surface
pMe->eglContext = eglCreateContext( pMe->eglDisplay, cfg, 0, 0 );
if( pMe->eglContext == EGL_NO_CONTEXT || eglGetError() != EGL_SUCCESS )
  return FALSE;
// Make it the current context with the newly-created display and surface.
if( eglMakeCurrent( pMe->eglDisplay, pMe->eglSurface, pMe->eglSurface, pMe->eglContext ) == EGL_FALSE ||
eglGetError() != EGL_SUCCESS )
	return FALSE;
This code is straightforward, but experienced BREW developers should recognize the introduction of new types like EGLint. For portability, you should always use the OpenGL ES types when working with the OpenGL interfaces. These include EGLBoolean and EGLInt for working with the EGL, and GLboolean, GLfixed, GLfloat, Glint, GLshort, GLuint, GLushort, and GLvoid for the graphics engine.

With the window manager set up, it's time to set up the graphics engine. These are values you're likely to change depending on your application, but are reasonable defaults:

// Select smooth shading & depth testing
glShadeModel( GL_SMOOTH );
glEnable( GL_DEPTH_TEST );

// Disable lighting and blending for performance.

// Request nicest perspective correction; use GL_FASTEST for better performance
// Initialize the viewport 
glViewport( 0, 0, pMe->sDDBitmapInfo.cx, pMe->sDDBitmapInfo.cy );
// Initialize the Projection Matrix
glMatrixMode( GL_PROJECTION );
glFrustumx( ITOX(-5),  ITOX(5),
            ITOX(-5),  ITOX(5),
            ITOX(10),  ITOX(100)	);
// Initialize the model view matrix
glMatrixMode( GL_MODELVIEW );
if (glGetError() != GL_NO_ERROR) return FALSE;
return TRUE;
These APIs are all well documented by Khronos, and should be familiar to OpenGL developers. The code begins by enabling smooth shading and depth testing, disabling lighting and blending, and suggesting that perspective correction should use the most accurate means instead of the fastest. Next, the code sets up the viewport, specifying the entire bitmap as obtained from the main display. Finally, the code sets up the projection and model view matrices, beginning each with the identity matrix and applying a transformation to the projection matrix. The use of the ITOX macro converts an integer to the fixed-point representation used by OpenGL—fixed-point math is typically significantly faster than floating-point math on OpenGL ES supported platforms.

Close Icon
Thanks for your registration, follow us on our social networks to keep up-to-date