package org.andengine.opengl.view; import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10; import org.andengine.engine.Engine; import org.andengine.engine.options.RenderOptions; import org.andengine.opengl.util.GLState; import org.andengine.util.debug.Debug; import android.opengl.GLES20; import android.opengl.GLSurfaceView; /** * (c) 2010 Nicolas Gramlich * (c) 2011 Zynga Inc. * * @author Nicolas Gramlich * @since 11:57:29 - 08.03.2010 */ public class EngineRenderer implements GLSurfaceView.Renderer { // =========================================================== // Constants // =========================================================== // =========================================================== // Fields // =========================================================== final Engine mEngine; final ConfigChooser mConfigChooser; final boolean mMultiSampling; final IRendererListener mRendererListener; final GLState mGLState; // =========================================================== // Constructors // =========================================================== public EngineRenderer(final Engine pEngine, final ConfigChooser pConfigChooser, final IRendererListener pRendererListener) { this.mEngine = pEngine; this.mConfigChooser = pConfigChooser; this.mRendererListener = pRendererListener; this.mGLState = new GLState(); this.mMultiSampling = this.mEngine.getEngineOptions().getRenderOptions().isMultiSampling(); } // =========================================================== // Getter & Setter // =========================================================== // =========================================================== // Methods for/from SuperClass/Interfaces // =========================================================== @Override public void onSurfaceCreated(final GL10 pGL, final EGLConfig pEGLConfig) { synchronized(GLState.class) { final RenderOptions renderOptions = this.mEngine.getEngineOptions().getRenderOptions(); this.mGLState.reset(renderOptions, this.mConfigChooser, pEGLConfig); // TODO Check if available and make available through EngineOptions-RenderOptions // GLES20.glEnable(GLES20.GL_POLYGON_SMOOTH); // GLES20.glHint(GLES20.GL_POLYGON_SMOOTH_HINT, GLES20.GL_NICEST); // GLES20.glEnable(GLES20.GL_LINE_SMOOTH); // GLES20.glHint(GLES20.GL_LINE_SMOOTH_HINT, GLES20.GL_NICEST); // GLES20.glEnable(GLES20.GL_POINT_SMOOTH); // GLES20.glHint(GLES20.GL_POINT_SMOOTH_HINT, GLES20.GL_NICEST); this.mGLState.disableDepthTest(); this.mGLState.enableBlend(); this.mGLState.setDitherEnabled(renderOptions.isDithering()); /* Enabling culling doesn't really make sense, because triangles are never drawn 'backwards' on purpose. */ // this.mGLState.enableCulling(); // GLES20.glFrontFace(GLES20.GL_CCW); // GLES20.glCullFace(GLES20.GL_BACK); if(this.mRendererListener != null) { this.mRendererListener.onSurfaceCreated(this.mGLState); } } } @Override public void onSurfaceChanged(final GL10 pGL, final int pWidth, final int pHeight) { this.mEngine.setSurfaceSize(pWidth, pHeight); GLES20.glViewport(0, 0, pWidth, pHeight); this.mGLState.loadProjectionGLMatrixIdentity(); if(this.mRendererListener != null) { this.mRendererListener.onSurfaceChanged(this.mGLState, pWidth, pHeight); } } @Override public void onDrawFrame(final GL10 pGL) { synchronized(GLState.class) { if (this.mMultiSampling && this.mConfigChooser.isCoverageMultiSampling()) { final int GL_COVERAGE_BUFFER_BIT_NV = 0x8000; GLES20.glClear(GL_COVERAGE_BUFFER_BIT_NV); } try { this.mEngine.onDrawFrame(this.mGLState); } catch (final InterruptedException e) { Debug.e("GLThread interrupted!", e); } } } // =========================================================== // Methods // =========================================================== // =========================================================== // Inner and Anonymous Classes // =========================================================== }