Ch10 Listings
satya - Friday, June 12, 2009 10:49:22 PM
Listing 10-1. Example of glDrawElements
glDrawElements(
// type of shape
GL10.GL_TRIANGLE_STRIP,
// Number of indices
3,
// How big each index is
GL10.GL_UNSIGNED_SHORT,
// buffer containing the 3 indices
mIndexBuffer);
satya - Friday, June 12, 2009 10:53:32 PM
Listing 10-2. Sample Code to Get an EGL Context
//Ask for an implementation of EGL10
EGL10 mEgl = (EGL10) EGLContext.getEGL();
//get the default display
EGLDisplay mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
//initialize the display
int[] version = new int[2];
mEgl.eglInitialize(mEglDisplay, version);
//config spec
int[] configSpec = {
EGL10.EGL_DEPTH_SIZE, 0,
EGL10.EGL_NONE
};
EGLConfig[] configs = new EGLConfig[1];
int[] num_config = new int[1];
mEgl.eglChooseConfig(mEglDisplay, configSpec, configs, 1,
num_config);
mEglConfig = configs[0];
//Create EGL Context
mEglContext = mEgl.eglCreateContext(mEglDisplay, mEglConfig,
EGL10.EGL_NO_CONTEXT, null);
satya - Friday, June 12, 2009 10:56:21 PM
Listing 10-3. Getting a Reference to the OpenGL ES Interface
android.view.SurfaceHolder holder = surfaceView.getHolder();
// mEgl points to an EGL context interface EGL10
mEglSurface = mEgl.eglCreateWindowSurface(mEglDisplay,
mEglConfig, holder, null);
mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
mEglContext);
GL gl = mEgl.getGL();
satya - Friday, June 12, 2009 10:57:42 PM
Listing 10-4. Associating and Disassociating the Window Surface
mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE,
EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);
mEgl.eglDestroySurface(mEglDisplay, mEglSurface);
satya - Friday, June 12, 2009 10:59:01 PM
Listing 10-5. Closing Out OpenGL ES Resources
//Destroy surface
mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE,
EGL10.EGL_NO_SURFACE,
EGL10.EGL_NO_CONTEXT);
mEgl.eglDestroySurface(mEglDisplay, mEglSurface);
//Destroy context
mEgl.eglDestroyContext(mEglDisplay, mEglContext);
//Disassociate display
mEgl.eglTerminate(mEglDisplay);
satya - Friday, June 12, 2009 11:02:50 PM
Listing 10-6. Code for the OpenGLTestHarnessActivity Class
// filename: OpenGLTestHarnessActivity.java
public class OpenGLTestHarnessActivity extends Activity
{
private OpenGLTestHarness mTestHarness;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mTestHarness = new OpenGLTestHarness(this);
mTestHarness.setRenderer(new SimpleTriangleRenderer(this));
setContentView(mTestHarness);
}
@Override
protected void onResume() {
super.onResume();
mTestHarness.onResume();
}
@Override
protected void onPause() {
super.onPause();
mTestHarness.onPause();
}
}
satya - Friday, June 12, 2009 11:06:29 PM
Listing 10-7. The OpenGLTestHarness Class
// filename: OpenGLTestHarness.java
public class OpenGLTestHarness extends SurfaceView
implements SurfaceHolder.Callback
{
public static final Semaphore sEglSemaphore = new Semaphore(1);
public boolean mSizeChanged = true;
public SurfaceHolder mHolder;
private OpenGLDrawingThread mGLThread;
public OpenGLTestHarness(Context context) {
super(context);
init();
}
public OpenGLTestHarness(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
mHolder = getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_GPU);
}
public SurfaceHolder getSurfaceHolder() {
return mHolder;
}
public void setRenderer(Renderer renderer) {
mGLThread = new OpenGLDrawingThread(this,renderer);
mGLThread.start();
}
public void surfaceCreated(SurfaceHolder holder) {
mGLThread.surfaceCreated();
}
public void surfaceDestroyed(SurfaceHolder holder) {
mGLThread.surfaceDestroyed();
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
mGLThread.onWindowResize(w, h);
}
public void onPause() {
mGLThread.onPause();
}
public void onResume() {
mGLThread.onResume();
}
@Override public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
mGLThread.onWindowFocusChanged(hasFocus);
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
mGLThread.requestExitAndWait();
}
}
satya - Friday, June 12, 2009 11:21:34 PM
Listing 10-8. The OpenGLDrawingThread Class
// filename: OpenGLDrawingThread.java
class OpenGLDrawingThread extends Thread
{
private boolean mDone, mPaused, mHasFocus;
private boolean mHasSurface, mContextLost, mSizeChanged;
private int mWidth,mHeight;
private Renderer mRenderer;
private EglHelper mEglHelper;
private OpenGLTestHarness pSv = null;
OpenGLDrawingThread(OpenGLTestHarness sv, Renderer renderer) {
super();
mDone = false; mWidth = 0; mHeight = 0;
mRenderer = renderer; mSizeChanged = false;
setName("GLThread");
pSv = sv;
}
@Override
public void run() {
try {
try {
OpenGLTestHarness.sEglSemaphore.acquire();
} catch (InterruptedException e) {
return;
}
guardedRun();
} catch (InterruptedException e) {
// fall thru and exit normally
} finally {
OpenGLTestHarness.sEglSemaphore.release();
}
}
private void guardedRun() throws InterruptedException {
mEglHelper = new EglHelper();
int[] configSpec = mRenderer.getConfigSpec();
mEglHelper.start(configSpec);
GL10 gl = null;
boolean tellRendererSurfaceCreated = true;
boolean tellRendererSurfaceChanged = true;
while (!mDone)
{
int w, h;
boolean changed;
boolean needStart = false;
synchronized (this) {
if (mPaused) {
Log.d("x", "Paused");
mEglHelper.finish();
needStart = true;
}
if(needToWait()) {
while (needToWait()) {
wait();
Log.d("x", "woke up from wait");
}
}
if (mDone) {
break;
}
changed = pSv.mSizeChanged;
w = mWidth;
h = mHeight;
pSv.mSizeChanged = false;
this.mSizeChanged = false;
}
if (needStart) {
Log.d("x", "Need to start");
mEglHelper.start(configSpec);
tellRendererSurfaceCreated = true;
changed = true;
}
if (changed) {
Log.d("x", "Change");
gl = (GL10) mEglHelper.createSurface(pSv.mHolder);
tellRendererSurfaceChanged = true;
}
if (tellRendererSurfaceCreated) {
Log.d("x", "Render Surface created");
mRenderer.surfaceCreated(gl);
tellRendererSurfaceCreated = false;
}
if (tellRendererSurfaceChanged) {
Log.d("x", "Render Surface changed");
mRenderer.sizeChanged(gl, w, h);
tellRendererSurfaceChanged = false;
}
if ((w > 0) && (h > 0)) {
Log.d("x", "Drawing frame now");
mRenderer.drawFrame(gl);
mEglHelper.swap();
}
}
mEglHelper.finish();
}
private boolean needToWait() {
return ((!mSizeChanged) || mPaused || (! mHasFocus) || (! mHasSurface)
|| mContextLost)
&& (! mDone);
}
public void surfaceCreated() {
synchronized(this) {
mHasSurface = true;
mContextLost = false;
notify();
}
}
public void surfaceDestroyed() {
synchronized(this) {
mHasSurface = false;
notify();
}
}
public void onPause() {
synchronized (this) {
mPaused = true;
}
}
public void onResume() {
synchronized (this) {
mPaused = false;
notify();
}
}
public void onWindowFocusChanged(boolean hasFocus) {
synchronized (this) {
mHasFocus = hasFocus;
if (mHasFocus == true) {
notify();
}
}
}
public void onWindowResize(int w, int h) {
synchronized (this) {
mWidth = w;
mHeight = h;
pSv.mSizeChanged = true;
this.mSizeChanged = true;
Log.d("x","window size changed. w, h:" + w + "," + h);
if (w > 0)
{
notify();
}
}
}
public void requestExitAndWait()
{
synchronized(this) {
mDone = true;
notify();
}
try {
join();
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
}
satya - Friday, June 12, 2009 11:29:52 PM
Listing 10-9. The EglHelper Class
//filename: EglHelper.java
public class EglHelper
{
EGL10 mEgl; EGLDisplay mEglDisplay; EGLSurface mEglSurface;
EGLConfig mEglConfig; EGLContext mEglContext;
public EglHelper(){}
public void start(int[] configSpec)
{
mEgl = (EGL10) EGLContext.getEGL();
mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
int[] version = new int[2];
mEgl.eglInitialize(mEglDisplay, version);
EGLConfig[] configs = new EGLConfig[1];
int[] num_config = new int[1];
mEgl.eglChooseConfig(mEglDisplay, configSpec, configs, 1,
num_config);
mEglConfig = configs[0];
mEglContext = mEgl.eglCreateContext(mEglDisplay, mEglConfig,
EGL10.EGL_NO_CONTEXT, null);
mEglSurface = null;
}
public GL createSurface(SurfaceHolder holder) {
if (mEglSurface != null) {
mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE,
EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);
mEgl.eglDestroySurface(mEglDisplay, mEglSurface);
}
mEglSurface = mEgl.eglCreateWindowSurface(mEglDisplay,
mEglConfig, holder, null);
mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
mEglContext);
GL gl = mEglContext.getGL();
return gl;
}
public boolean swap() {
mEgl.eglSwapBuffers(mEglDisplay, mEglSurface);
return mEgl.eglGetError() != EGL11.EGL_CONTEXT_LOST;
}
public void finish() {
if (mEglSurface != null) {
mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE,
EGL10.EGL_NO_SURFACE,
EGL10.EGL_NO_CONTEXT);
mEgl.eglDestroySurface(mEglDisplay, mEglSurface);
mEglSurface = null;
}
if (mEglContext != null) {
mEgl.eglDestroyContext(mEglDisplay, mEglContext);
mEglContext = null;
}
if (mEglDisplay != null) {
mEgl.eglTerminate(mEglDisplay);
mEglDisplay = null;
}
}
}
satya - Friday, June 12, 2009 11:32:20 PM
Listing 10-10. The Methods of the Renderer Protocol
//filename: Renderer.java
public interface Renderer
{
int[] getConfigSpec();
void surfaceCreated(GL10 gl);
void sizeChanged(GL10 gl, int width, int height);
void drawFrame(GL10 gl);
}
satya - Friday, June 12, 2009 11:37:36 PM
Listing 10-11. The AbstractRenderer Class
//filename: AbstractRenderer.java
public abstract class AbstractRenderer implements Renderer
{
public int[] getConfigSpec() {
int[] configSpec = {
EGL10.EGL_DEPTH_SIZE, 0,
EGL10.EGL_NONE
};
return configSpec;
}
public void surfaceCreated(GL10 gl) {
gl.glDisable(GL10.GL_DITHER);
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT,
GL10.GL_FASTEST);
gl.glClearColor(.5f, .5f, .5f, 1);
gl.glShadeModel(GL10.GL_SMOOTH);
gl.glEnable(GL10.GL_DEPTH_TEST);
}
public void sizeChanged(GL10 gl, int w, int h) {
gl.glViewport(0, 0, w, h);
float ratio = (float) w / h;
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity();
gl.glFrustumf(-ratio, ratio, -1, 1, 3, 7);
}
public void drawFrame(GL10 gl)
{
gl.glDisable(GL10.GL_DITHER);
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
GLU.gluLookAt(gl, 0, 0, -5, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
draw(gl);
}
protected abstract void draw(GL10 gl);
}
satya - Friday, June 12, 2009 11:41:25 PM
Listing 10-12. Drawing a Simple Triangle
//filename: SimpleTriangleRenderer.java
public class SimpleTriangleRenderer extends AbstractRenderer
{
//Number of points or vertices we want to use
private final static int VERTS = 3;
//A raw native buffer to hold the point coordinates
private FloatBuffer mFVertexBuffer;
//A raw native buffer to hold indices
//allowing a reuse of points.
private ShortBuffer mIndexBuffer;
public SimpleTriangleRenderer(Context context)
{
ByteBuffer vbb = ByteBuffer.allocateDirect(VERTS * 3 * 4);
vbb.order(ByteOrder.nativeOrder());
mFVertexBuffer = vbb.asFloatBuffer();
ByteBuffer ibb = ByteBuffer.allocateDirect(VERTS * 2);
ibb.order(ByteOrder.nativeOrder());
mIndexBuffer = ibb.asShortBuffer();
float[] coords = {
-0.5f, -0.5f, 0, // (x1,y1,z1)
0.5f, -0.5f, 0,
0.0f, 0.5f, 0
};
for (int i = 0; i < VERTS; i++) {
for(int j = 0; j < 3; j++) {
mFVertexBuffer.put(coords[i*3+j]);
}
}
short[] myIndecesArray = {0,1,2};
for (int i=0;i<3;i++)
{
mIndexBuffer.put(myIndecesArray[i]);
}
mFVertexBuffer.position(0);
mIndexBuffer.position(0);
}
//overridden method
protected void draw(GL10 gl)
{
gl.glColor4f(1.0f, 0, 0, 0.5f);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mFVertexBuffer);
gl.glDrawElements(GL10.GL_TRIANGLES, VERTS,
GL10.GL_UNSIGNED_SHORT, mIndexBuffer);
}
}
satya - Friday, June 12, 2009 11:45:07 PM
Listing 10-13. The SimpleTriangleRenderer2 Class
//filename: SimpleTriangleRenderer2.java
public class SimpleTriangleRenderer2 extends AbstractRenderer
{
private final static int VERTS = 4;
private FloatBuffer mFVertexBuffer;
private ShortBuffer mIndexBuffer;
public SimpleTriangleRenderer2(Context context)
{
ByteBuffer vbb = ByteBuffer.allocateDirect(VERTS * 3 * 4);
vbb.order(ByteOrder.nativeOrder());
mFVertexBuffer = vbb.asFloatBuffer();
ByteBuffer ibb = ByteBuffer.allocateDirect(6 * 2);
ibb.order(ByteOrder.nativeOrder());
mIndexBuffer = ibb.asShortBuffer();
float[] coords = {
-1.0f, -1.0f, 0, // (x1,y1,z1)
1.0f, -1.0f, 0,
0.0f, 1.0f, 0,
1.0f, 1.0f, 0
};
for (int i = 0; i < VERTS; i++) {
for(int j = 0; j < 3; j++) {
mFVertexBuffer.put(coords[i*3+j]);
}
}
short[] myIndecesArray = {0,1,2, 0,2,3};
for (int i=0;i<6;i++)
{
mIndexBuffer.put(myIndecesArray[i]);
}
mFVertexBuffer.position(0);
mIndexBuffer.position(0);
}
protected void draw(GL10 gl)
{
gl.glColor4f(1.0f, 0, 0, 0.5f);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mFVertexBuffer);
gl.glDrawElements(GL10.GL_TRIANGLES, 6, GL10.GL_UNSIGNED_SHORT,
mIndexBuffer);
}
}