1cfd74d65d832137e20e193c960802afba73b5d38sm/* 23c1e67e433728684b5f228c5d4f3e5b1457bb271sm * Copyright (C) 2010 The Android Open Source Project 3cfd74d65d832137e20e193c960802afba73b5d38sm * 4cfd74d65d832137e20e193c960802afba73b5d38sm * Licensed under the Apache License, Version 2.0 (the "License"); 5cfd74d65d832137e20e193c960802afba73b5d38sm * you may not use this file except in compliance with the License. 6cfd74d65d832137e20e193c960802afba73b5d38sm * You may obtain a copy of the License at 7cfd74d65d832137e20e193c960802afba73b5d38sm * 8cfd74d65d832137e20e193c960802afba73b5d38sm * http://www.apache.org/licenses/LICENSE-2.0 9cfd74d65d832137e20e193c960802afba73b5d38sm * 10cfd74d65d832137e20e193c960802afba73b5d38sm * Unless required by applicable law or agreed to in writing, software 11cfd74d65d832137e20e193c960802afba73b5d38sm * distributed under the License is distributed on an "AS IS" BASIS, 12cfd74d65d832137e20e193c960802afba73b5d38sm * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13cfd74d65d832137e20e193c960802afba73b5d38sm * See the License for the specific language governing permissions and 14cfd74d65d832137e20e193c960802afba73b5d38sm * limitations under the License. 15cfd74d65d832137e20e193c960802afba73b5d38sm */ 16cfd74d65d832137e20e193c960802afba73b5d38sm 17cfd74d65d832137e20e193c960802afba73b5d38smpackage com.replica.replicaisland; 18cfd74d65d832137e20e193c960802afba73b5d38sm 19cfd74d65d832137e20e193c960802afba73b5d38smimport android.content.Context; 20cfd74d65d832137e20e193c960802afba73b5d38smimport android.os.Build; 21cfd74d65d832137e20e193c960802afba73b5d38smimport android.os.SystemClock; 22cfd74d65d832137e20e193c960802afba73b5d38sm 23cfd74d65d832137e20e193c960802afba73b5d38smimport javax.microedition.khronos.egl.EGLConfig; 24cfd74d65d832137e20e193c960802afba73b5d38smimport javax.microedition.khronos.opengles.GL10; 25cfd74d65d832137e20e193c960802afba73b5d38sm 26cfd74d65d832137e20e193c960802afba73b5d38smimport com.replica.replicaisland.RenderSystem.RenderElement; 27cfd74d65d832137e20e193c960802afba73b5d38sm 28cfd74d65d832137e20e193c960802afba73b5d38sm/** 29cfd74d65d832137e20e193c960802afba73b5d38sm * GameRenderer the top-level rendering interface for the game engine. It is called by 30cfd74d65d832137e20e193c960802afba73b5d38sm * GLSurfaceView and is responsible for submitting commands to OpenGL. GameRenderer receives a 31cfd74d65d832137e20e193c960802afba73b5d38sm * queue of renderable objects from the thread and uses that to draw the scene every frame. If 32cfd74d65d832137e20e193c960802afba73b5d38sm * no queue is available then no drawing is performed. If the queue is not changed from frame to 33cfd74d65d832137e20e193c960802afba73b5d38sm * frame, the same scene will be redrawn every frame. 34cfd74d65d832137e20e193c960802afba73b5d38sm * The GameRenderer also invokes texture loads when it is activated. 35cfd74d65d832137e20e193c960802afba73b5d38sm */ 36cfd74d65d832137e20e193c960802afba73b5d38smpublic class GameRenderer implements GLSurfaceView.Renderer { 37cfd74d65d832137e20e193c960802afba73b5d38sm private static final int PROFILE_REPORT_DELAY = 3 * 1000; 38cfd74d65d832137e20e193c960802afba73b5d38sm 39cfd74d65d832137e20e193c960802afba73b5d38sm private int mWidth; 40cfd74d65d832137e20e193c960802afba73b5d38sm private int mHeight; 41cfd74d65d832137e20e193c960802afba73b5d38sm private int mHalfWidth; 42cfd74d65d832137e20e193c960802afba73b5d38sm private int mHalfHeight; 43cfd74d65d832137e20e193c960802afba73b5d38sm 44cfd74d65d832137e20e193c960802afba73b5d38sm private float mScaleX; 45cfd74d65d832137e20e193c960802afba73b5d38sm private float mScaleY; 46cfd74d65d832137e20e193c960802afba73b5d38sm private Context mContext; 47cfd74d65d832137e20e193c960802afba73b5d38sm private long mLastTime; 48cfd74d65d832137e20e193c960802afba73b5d38sm private int mProfileFrames; 49cfd74d65d832137e20e193c960802afba73b5d38sm private long mProfileWaitTime; 50cfd74d65d832137e20e193c960802afba73b5d38sm private long mProfileFrameTime; 51cfd74d65d832137e20e193c960802afba73b5d38sm private long mProfileSubmitTime; 52cfd74d65d832137e20e193c960802afba73b5d38sm private int mProfileObjectCount; 53cfd74d65d832137e20e193c960802afba73b5d38sm 54cfd74d65d832137e20e193c960802afba73b5d38sm private ObjectManager mDrawQueue; 55cfd74d65d832137e20e193c960802afba73b5d38sm private boolean mDrawQueueChanged; 56cfd74d65d832137e20e193c960802afba73b5d38sm private Game mGame; 57cfd74d65d832137e20e193c960802afba73b5d38sm private Object mDrawLock; 58cfd74d65d832137e20e193c960802afba73b5d38sm 59cfd74d65d832137e20e193c960802afba73b5d38sm float mCameraX; 60cfd74d65d832137e20e193c960802afba73b5d38sm float mCameraY; 61cfd74d65d832137e20e193c960802afba73b5d38sm 62cfd74d65d832137e20e193c960802afba73b5d38sm boolean mCallbackRequested; 63cfd74d65d832137e20e193c960802afba73b5d38sm 64cfd74d65d832137e20e193c960802afba73b5d38sm public GameRenderer(Context context, Game game, int gameWidth, int gameHeight) { 65cfd74d65d832137e20e193c960802afba73b5d38sm mContext = context; 66cfd74d65d832137e20e193c960802afba73b5d38sm mGame = game; 67cfd74d65d832137e20e193c960802afba73b5d38sm mWidth = gameWidth; 68cfd74d65d832137e20e193c960802afba73b5d38sm mHeight = gameHeight; 69cfd74d65d832137e20e193c960802afba73b5d38sm mHalfWidth = gameWidth / 2; 70cfd74d65d832137e20e193c960802afba73b5d38sm mHalfHeight = gameHeight / 2; 71cfd74d65d832137e20e193c960802afba73b5d38sm mScaleX = 1.0f; 72cfd74d65d832137e20e193c960802afba73b5d38sm mScaleY = 1.0f; 73cfd74d65d832137e20e193c960802afba73b5d38sm mDrawQueueChanged = false; 74cfd74d65d832137e20e193c960802afba73b5d38sm mDrawLock = new Object(); 75cfd74d65d832137e20e193c960802afba73b5d38sm mCameraX = 0.0f; 76cfd74d65d832137e20e193c960802afba73b5d38sm mCameraY = 0.0f; 77cfd74d65d832137e20e193c960802afba73b5d38sm mCallbackRequested = false; 78cfd74d65d832137e20e193c960802afba73b5d38sm } 79cfd74d65d832137e20e193c960802afba73b5d38sm 80cfd74d65d832137e20e193c960802afba73b5d38sm public void onSurfaceCreated(GL10 gl, EGLConfig config) { 81cfd74d65d832137e20e193c960802afba73b5d38sm /* 82cfd74d65d832137e20e193c960802afba73b5d38sm * Some one-time OpenGL initialization can be made here probably based 83cfd74d65d832137e20e193c960802afba73b5d38sm * on features of this particular context 84cfd74d65d832137e20e193c960802afba73b5d38sm */ 85cfd74d65d832137e20e193c960802afba73b5d38sm gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST); 86cfd74d65d832137e20e193c960802afba73b5d38sm 87cfd74d65d832137e20e193c960802afba73b5d38sm gl.glClearColor(0.0f, 0.0f, 0.0f, 1); 88cfd74d65d832137e20e193c960802afba73b5d38sm gl.glShadeModel(GL10.GL_FLAT); 89cfd74d65d832137e20e193c960802afba73b5d38sm gl.glDisable(GL10.GL_DEPTH_TEST); 90cfd74d65d832137e20e193c960802afba73b5d38sm gl.glEnable(GL10.GL_TEXTURE_2D); 91cfd74d65d832137e20e193c960802afba73b5d38sm /* 92cfd74d65d832137e20e193c960802afba73b5d38sm * By default, OpenGL enables features that improve quality but reduce 93cfd74d65d832137e20e193c960802afba73b5d38sm * performance. One might want to tweak that especially on software 94cfd74d65d832137e20e193c960802afba73b5d38sm * renderer. 95cfd74d65d832137e20e193c960802afba73b5d38sm */ 96cfd74d65d832137e20e193c960802afba73b5d38sm gl.glDisable(GL10.GL_DITHER); 97cfd74d65d832137e20e193c960802afba73b5d38sm gl.glDisable(GL10.GL_LIGHTING); 98cfd74d65d832137e20e193c960802afba73b5d38sm 99cfd74d65d832137e20e193c960802afba73b5d38sm gl.glTexEnvx(GL10.GL_TEXTURE_ENV, GL10.GL_TEXTURE_ENV_MODE, GL10.GL_MODULATE); 100cfd74d65d832137e20e193c960802afba73b5d38sm 101cfd74d65d832137e20e193c960802afba73b5d38sm gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); 102cfd74d65d832137e20e193c960802afba73b5d38sm 103cfd74d65d832137e20e193c960802afba73b5d38sm String extensions = gl.glGetString(GL10.GL_EXTENSIONS); 104cfd74d65d832137e20e193c960802afba73b5d38sm String version = gl.glGetString(GL10.GL_VERSION); 1053c1e67e433728684b5f228c5d4f3e5b1457bb271sm String renderer = gl.glGetString(GL10.GL_RENDERER); 1063c1e67e433728684b5f228c5d4f3e5b1457bb271sm boolean isSoftwareRenderer = renderer.contains("PixelFlinger"); 107cfd74d65d832137e20e193c960802afba73b5d38sm boolean isOpenGL10 = version.contains("1.0"); 108cfd74d65d832137e20e193c960802afba73b5d38sm boolean supportsDrawTexture = extensions.contains("draw_texture"); 109cfd74d65d832137e20e193c960802afba73b5d38sm // VBOs are standard in GLES1.1 1103c1e67e433728684b5f228c5d4f3e5b1457bb271sm // No use using VBOs when software renderering, esp. since older versions of the software renderer 1113c1e67e433728684b5f228c5d4f3e5b1457bb271sm // had a crash bug related to freeing VBOs. 1123c1e67e433728684b5f228c5d4f3e5b1457bb271sm boolean supportsVBOs = !isSoftwareRenderer && (!isOpenGL10 || extensions.contains("vertex_buffer_object")); 113cfd74d65d832137e20e193c960802afba73b5d38sm ContextParameters params = BaseObject.sSystemRegistry.contextParameters; 114cfd74d65d832137e20e193c960802afba73b5d38sm params.supportsDrawTexture = supportsDrawTexture; 115cfd74d65d832137e20e193c960802afba73b5d38sm params.supportsVBOs = supportsVBOs; 116cfd74d65d832137e20e193c960802afba73b5d38sm 117cfd74d65d832137e20e193c960802afba73b5d38sm hackBrokenDevices(); 118cfd74d65d832137e20e193c960802afba73b5d38sm 1193c1e67e433728684b5f228c5d4f3e5b1457bb271sm DebugLog.i("Graphics Support", version + " (" + renderer + "): " +(supportsDrawTexture ? "draw texture," : "") + (supportsVBOs ? "vbos" : "")); 120cfd74d65d832137e20e193c960802afba73b5d38sm 121cfd74d65d832137e20e193c960802afba73b5d38sm mGame.onSurfaceCreated(); 122cfd74d65d832137e20e193c960802afba73b5d38sm 123cfd74d65d832137e20e193c960802afba73b5d38sm } 124cfd74d65d832137e20e193c960802afba73b5d38sm 125cfd74d65d832137e20e193c960802afba73b5d38sm private void hackBrokenDevices() { 126cfd74d65d832137e20e193c960802afba73b5d38sm // Some devices are broken. Fix them here. This is pretty much the only 127cfd74d65d832137e20e193c960802afba73b5d38sm // device-specific code in the whole project. Ugh. 128cfd74d65d832137e20e193c960802afba73b5d38sm ContextParameters params = BaseObject.sSystemRegistry.contextParameters; 129cfd74d65d832137e20e193c960802afba73b5d38sm 130cfd74d65d832137e20e193c960802afba73b5d38sm 131cfd74d65d832137e20e193c960802afba73b5d38sm if (Build.PRODUCT.contains("morrison")) { 132cfd74d65d832137e20e193c960802afba73b5d38sm // This is the Motorola Cliq. This device LIES and says it supports 133cfd74d65d832137e20e193c960802afba73b5d38sm // VBOs, which it actually does not (or, more likely, the extensions string 134cfd74d65d832137e20e193c960802afba73b5d38sm // is correct and the GL JNI glue is broken). 135cfd74d65d832137e20e193c960802afba73b5d38sm params.supportsVBOs = false; 136cfd74d65d832137e20e193c960802afba73b5d38sm // TODO: if Motorola fixes this, I should switch to using the fingerprint 137cfd74d65d832137e20e193c960802afba73b5d38sm // (blur/morrison/morrison/morrison:1.5/CUPCAKE/091007:user/ota-rel-keys,release-keys) 138cfd74d65d832137e20e193c960802afba73b5d38sm // instead of the product name so that newer versions use VBOs. 139cfd74d65d832137e20e193c960802afba73b5d38sm } 140cfd74d65d832137e20e193c960802afba73b5d38sm } 141cfd74d65d832137e20e193c960802afba73b5d38sm 142cfd74d65d832137e20e193c960802afba73b5d38sm public void loadTextures(GL10 gl, TextureLibrary library) { 143cfd74d65d832137e20e193c960802afba73b5d38sm if (gl != null) { 144cfd74d65d832137e20e193c960802afba73b5d38sm library.loadAll(mContext, gl); 145cfd74d65d832137e20e193c960802afba73b5d38sm DebugLog.d("AndouKun", "Textures Loaded."); 146cfd74d65d832137e20e193c960802afba73b5d38sm } 147cfd74d65d832137e20e193c960802afba73b5d38sm } 148cfd74d65d832137e20e193c960802afba73b5d38sm 149cfd74d65d832137e20e193c960802afba73b5d38sm public void flushTextures(GL10 gl, TextureLibrary library) { 150cfd74d65d832137e20e193c960802afba73b5d38sm if (gl != null) { 151cfd74d65d832137e20e193c960802afba73b5d38sm library.deleteAll(gl); 152cfd74d65d832137e20e193c960802afba73b5d38sm DebugLog.d("AndouKun", "Textures Unloaded."); 153cfd74d65d832137e20e193c960802afba73b5d38sm } 154cfd74d65d832137e20e193c960802afba73b5d38sm } 155cfd74d65d832137e20e193c960802afba73b5d38sm 156cfd74d65d832137e20e193c960802afba73b5d38sm public void loadBuffers(GL10 gl, BufferLibrary library) { 157cfd74d65d832137e20e193c960802afba73b5d38sm if (gl != null) { 158cfd74d65d832137e20e193c960802afba73b5d38sm library.generateHardwareBuffers(gl); 159cfd74d65d832137e20e193c960802afba73b5d38sm DebugLog.d("AndouKun", "Buffers Created."); 160cfd74d65d832137e20e193c960802afba73b5d38sm } 161cfd74d65d832137e20e193c960802afba73b5d38sm } 162cfd74d65d832137e20e193c960802afba73b5d38sm 163cfd74d65d832137e20e193c960802afba73b5d38sm public void flushBuffers(GL10 gl, BufferLibrary library) { 164cfd74d65d832137e20e193c960802afba73b5d38sm if (gl != null) { 165cfd74d65d832137e20e193c960802afba73b5d38sm library.releaseHardwareBuffers(gl); 166cfd74d65d832137e20e193c960802afba73b5d38sm DebugLog.d("AndouKun", "Buffers Released."); 167cfd74d65d832137e20e193c960802afba73b5d38sm } 168cfd74d65d832137e20e193c960802afba73b5d38sm } 169cfd74d65d832137e20e193c960802afba73b5d38sm 170cfd74d65d832137e20e193c960802afba73b5d38sm public void onSurfaceLost() { 171cfd74d65d832137e20e193c960802afba73b5d38sm mGame.onSurfaceLost(); 172cfd74d65d832137e20e193c960802afba73b5d38sm } 173cfd74d65d832137e20e193c960802afba73b5d38sm 174cfd74d65d832137e20e193c960802afba73b5d38sm public void requestCallback() { 175cfd74d65d832137e20e193c960802afba73b5d38sm mCallbackRequested = true; 176cfd74d65d832137e20e193c960802afba73b5d38sm } 177cfd74d65d832137e20e193c960802afba73b5d38sm 178cfd74d65d832137e20e193c960802afba73b5d38sm /** Draws the scene. Note that the draw queue is locked for the duration of this function. */ 179cfd74d65d832137e20e193c960802afba73b5d38sm public void onDrawFrame(GL10 gl) { 1809d4cc2572d37983607df38b0f4216ed76ac51814sm 181cfd74d65d832137e20e193c960802afba73b5d38sm long time = SystemClock.uptimeMillis(); 182cfd74d65d832137e20e193c960802afba73b5d38sm long time_delta = (time - mLastTime); 183cfd74d65d832137e20e193c960802afba73b5d38sm 184cfd74d65d832137e20e193c960802afba73b5d38sm synchronized(mDrawLock) { 185cfd74d65d832137e20e193c960802afba73b5d38sm if (!mDrawQueueChanged) { 186cfd74d65d832137e20e193c960802afba73b5d38sm while (!mDrawQueueChanged) { 187cfd74d65d832137e20e193c960802afba73b5d38sm try { 188cfd74d65d832137e20e193c960802afba73b5d38sm mDrawLock.wait(); 189cfd74d65d832137e20e193c960802afba73b5d38sm } catch (InterruptedException e) { 190cfd74d65d832137e20e193c960802afba73b5d38sm // No big deal if this wait is interrupted. 191cfd74d65d832137e20e193c960802afba73b5d38sm } 192cfd74d65d832137e20e193c960802afba73b5d38sm } 193cfd74d65d832137e20e193c960802afba73b5d38sm } 194cfd74d65d832137e20e193c960802afba73b5d38sm mDrawQueueChanged = false; 195cfd74d65d832137e20e193c960802afba73b5d38sm } 196cfd74d65d832137e20e193c960802afba73b5d38sm 197cfd74d65d832137e20e193c960802afba73b5d38sm final long wait = SystemClock.uptimeMillis(); 198cfd74d65d832137e20e193c960802afba73b5d38sm 199cfd74d65d832137e20e193c960802afba73b5d38sm if (mCallbackRequested) { 200cfd74d65d832137e20e193c960802afba73b5d38sm mGame.onSurfaceReady(); 201cfd74d65d832137e20e193c960802afba73b5d38sm mCallbackRequested = false; 202cfd74d65d832137e20e193c960802afba73b5d38sm } 203cfd74d65d832137e20e193c960802afba73b5d38sm 204cfd74d65d832137e20e193c960802afba73b5d38sm DrawableBitmap.beginDrawing(gl, mWidth, mHeight); 205cfd74d65d832137e20e193c960802afba73b5d38sm 206cfd74d65d832137e20e193c960802afba73b5d38sm synchronized (this) { 207cfd74d65d832137e20e193c960802afba73b5d38sm if (mDrawQueue != null && mDrawQueue.getObjects().getCount() > 0) { 208cfd74d65d832137e20e193c960802afba73b5d38sm OpenGLSystem.setGL(gl); 209cfd74d65d832137e20e193c960802afba73b5d38sm FixedSizeArray<BaseObject> objects = mDrawQueue.getObjects(); 210cfd74d65d832137e20e193c960802afba73b5d38sm Object[] objectArray = objects.getArray(); 211cfd74d65d832137e20e193c960802afba73b5d38sm final int count = objects.getCount(); 212cfd74d65d832137e20e193c960802afba73b5d38sm final float scaleX = mScaleX; 213cfd74d65d832137e20e193c960802afba73b5d38sm final float scaleY = mScaleY; 214cfd74d65d832137e20e193c960802afba73b5d38sm final float halfWidth = mHalfWidth; 215cfd74d65d832137e20e193c960802afba73b5d38sm final float halfHeight = mHalfHeight; 216cfd74d65d832137e20e193c960802afba73b5d38sm mProfileObjectCount += count; 217cfd74d65d832137e20e193c960802afba73b5d38sm for (int i = 0; i < count; i++) { 218cfd74d65d832137e20e193c960802afba73b5d38sm RenderElement element = (RenderElement)objectArray[i]; 219cfd74d65d832137e20e193c960802afba73b5d38sm float x = element.x; 220cfd74d65d832137e20e193c960802afba73b5d38sm float y = element.y; 221cfd74d65d832137e20e193c960802afba73b5d38sm if (element.cameraRelative) { 222cfd74d65d832137e20e193c960802afba73b5d38sm x = (x - mCameraX) + halfWidth; 223cfd74d65d832137e20e193c960802afba73b5d38sm y = (y - mCameraY) + halfHeight; 224cfd74d65d832137e20e193c960802afba73b5d38sm } 225cfd74d65d832137e20e193c960802afba73b5d38sm element.mDrawable.draw(x, y, scaleX, scaleY); 226cfd74d65d832137e20e193c960802afba73b5d38sm } 227cfd74d65d832137e20e193c960802afba73b5d38sm OpenGLSystem.setGL(null); 228cfd74d65d832137e20e193c960802afba73b5d38sm } else if (mDrawQueue == null) { 229cfd74d65d832137e20e193c960802afba73b5d38sm // If we have no draw queue, clear the screen. If we have a draw queue that 230cfd74d65d832137e20e193c960802afba73b5d38sm // is empty, we'll leave the frame buffer alone. 231cfd74d65d832137e20e193c960802afba73b5d38sm gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); 232cfd74d65d832137e20e193c960802afba73b5d38sm } 233cfd74d65d832137e20e193c960802afba73b5d38sm } 234cfd74d65d832137e20e193c960802afba73b5d38sm 235cfd74d65d832137e20e193c960802afba73b5d38sm DrawableBitmap.endDrawing(gl); 236cfd74d65d832137e20e193c960802afba73b5d38sm 237cfd74d65d832137e20e193c960802afba73b5d38sm long time2 = SystemClock.uptimeMillis(); 238cfd74d65d832137e20e193c960802afba73b5d38sm mLastTime = time2; 239cfd74d65d832137e20e193c960802afba73b5d38sm 240cfd74d65d832137e20e193c960802afba73b5d38sm mProfileFrameTime += time_delta; 241cfd74d65d832137e20e193c960802afba73b5d38sm mProfileSubmitTime += time2 - time; 242cfd74d65d832137e20e193c960802afba73b5d38sm mProfileWaitTime += wait - time; 243cfd74d65d832137e20e193c960802afba73b5d38sm 244cfd74d65d832137e20e193c960802afba73b5d38sm mProfileFrames++; 245cfd74d65d832137e20e193c960802afba73b5d38sm if (mProfileFrameTime > PROFILE_REPORT_DELAY) { 246cfd74d65d832137e20e193c960802afba73b5d38sm final int validFrames = mProfileFrames; 247cfd74d65d832137e20e193c960802afba73b5d38sm final long averageFrameTime = mProfileFrameTime / validFrames; 248cfd74d65d832137e20e193c960802afba73b5d38sm final long averageSubmitTime = mProfileSubmitTime / validFrames; 249cfd74d65d832137e20e193c960802afba73b5d38sm final float averageObjectsPerFrame = (float)mProfileObjectCount / validFrames; 250cfd74d65d832137e20e193c960802afba73b5d38sm final long averageWaitTime = mProfileWaitTime / validFrames; 251cfd74d65d832137e20e193c960802afba73b5d38sm 252cfd74d65d832137e20e193c960802afba73b5d38sm DebugLog.d("Render Profile", 253cfd74d65d832137e20e193c960802afba73b5d38sm "Average Submit: " + averageSubmitTime 254cfd74d65d832137e20e193c960802afba73b5d38sm + " Average Draw: " + averageFrameTime 255cfd74d65d832137e20e193c960802afba73b5d38sm + " Objects/Frame: " + averageObjectsPerFrame 256cfd74d65d832137e20e193c960802afba73b5d38sm + " Wait Time: " + averageWaitTime); 257cfd74d65d832137e20e193c960802afba73b5d38sm 258cfd74d65d832137e20e193c960802afba73b5d38sm mProfileFrameTime = 0; 259cfd74d65d832137e20e193c960802afba73b5d38sm mProfileSubmitTime = 0; 260cfd74d65d832137e20e193c960802afba73b5d38sm mProfileFrames = 0; 261cfd74d65d832137e20e193c960802afba73b5d38sm mProfileObjectCount = 0; 262cfd74d65d832137e20e193c960802afba73b5d38sm } 263cfd74d65d832137e20e193c960802afba73b5d38sm 264cfd74d65d832137e20e193c960802afba73b5d38sm } 265cfd74d65d832137e20e193c960802afba73b5d38sm 266cfd74d65d832137e20e193c960802afba73b5d38sm public void onSurfaceChanged(GL10 gl, int w, int h) { 267cfd74d65d832137e20e193c960802afba73b5d38sm DebugLog.d("AndouKun", "Surface Size Change: " + w + ", " + h); 268cfd74d65d832137e20e193c960802afba73b5d38sm 269cfd74d65d832137e20e193c960802afba73b5d38sm //mWidth = w;0 270cfd74d65d832137e20e193c960802afba73b5d38sm //mHeight = h; 271cfd74d65d832137e20e193c960802afba73b5d38sm // ensure the same aspect ratio as the game 272cfd74d65d832137e20e193c960802afba73b5d38sm float scaleX = (float)w / mWidth; 273cfd74d65d832137e20e193c960802afba73b5d38sm float scaleY = (float)h / mHeight; 274cfd74d65d832137e20e193c960802afba73b5d38sm final int viewportWidth = (int)(mWidth * scaleX); 275cfd74d65d832137e20e193c960802afba73b5d38sm final int viewportHeight = (int)(mHeight * scaleY); 276cfd74d65d832137e20e193c960802afba73b5d38sm gl.glViewport(0, 0, viewportWidth, viewportHeight); 277cfd74d65d832137e20e193c960802afba73b5d38sm mScaleX = scaleX; 278cfd74d65d832137e20e193c960802afba73b5d38sm mScaleY = scaleY; 279cfd74d65d832137e20e193c960802afba73b5d38sm 280cfd74d65d832137e20e193c960802afba73b5d38sm 281cfd74d65d832137e20e193c960802afba73b5d38sm /* 282cfd74d65d832137e20e193c960802afba73b5d38sm * Set our projection matrix. This doesn't have to be done each time we 283cfd74d65d832137e20e193c960802afba73b5d38sm * draw, but usually a new projection needs to be set when the viewport 284cfd74d65d832137e20e193c960802afba73b5d38sm * is resized. 285cfd74d65d832137e20e193c960802afba73b5d38sm */ 286cfd74d65d832137e20e193c960802afba73b5d38sm float ratio = (float) mWidth / mHeight; 287cfd74d65d832137e20e193c960802afba73b5d38sm gl.glMatrixMode(GL10.GL_PROJECTION); 288cfd74d65d832137e20e193c960802afba73b5d38sm gl.glLoadIdentity(); 289cfd74d65d832137e20e193c960802afba73b5d38sm gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10); 290cfd74d65d832137e20e193c960802afba73b5d38sm 291cfd74d65d832137e20e193c960802afba73b5d38sm 292cfd74d65d832137e20e193c960802afba73b5d38sm mGame.onSurfaceReady(); 293cfd74d65d832137e20e193c960802afba73b5d38sm } 294cfd74d65d832137e20e193c960802afba73b5d38sm 295cfd74d65d832137e20e193c960802afba73b5d38sm public synchronized void setDrawQueue(ObjectManager queue, float cameraX, float cameraY) { 296cfd74d65d832137e20e193c960802afba73b5d38sm mDrawQueue = queue; 297cfd74d65d832137e20e193c960802afba73b5d38sm mCameraX = cameraX; 298cfd74d65d832137e20e193c960802afba73b5d38sm mCameraY = cameraY; 299cfd74d65d832137e20e193c960802afba73b5d38sm synchronized(mDrawLock) { 300cfd74d65d832137e20e193c960802afba73b5d38sm mDrawQueueChanged = true; 301cfd74d65d832137e20e193c960802afba73b5d38sm mDrawLock.notify(); 302cfd74d65d832137e20e193c960802afba73b5d38sm } 303cfd74d65d832137e20e193c960802afba73b5d38sm } 304cfd74d65d832137e20e193c960802afba73b5d38sm 305cfd74d65d832137e20e193c960802afba73b5d38sm public synchronized void onPause() { 306cfd74d65d832137e20e193c960802afba73b5d38sm // Stop waiting to avoid deadlock. 307cfd74d65d832137e20e193c960802afba73b5d38sm // TODO: this is a hack. Probably this renderer 308cfd74d65d832137e20e193c960802afba73b5d38sm // should just use GLSurfaceView's non-continuious render 309cfd74d65d832137e20e193c960802afba73b5d38sm // mode. 310cfd74d65d832137e20e193c960802afba73b5d38sm synchronized(mDrawLock) { 311cfd74d65d832137e20e193c960802afba73b5d38sm mDrawQueueChanged = true; 312cfd74d65d832137e20e193c960802afba73b5d38sm mDrawLock.notify(); 313cfd74d65d832137e20e193c960802afba73b5d38sm } 314cfd74d65d832137e20e193c960802afba73b5d38sm } 315cfd74d65d832137e20e193c960802afba73b5d38sm 316cfd74d65d832137e20e193c960802afba73b5d38sm /** 317cfd74d65d832137e20e193c960802afba73b5d38sm * This function blocks while drawFrame() is in progress, and may be used by other threads to 318cfd74d65d832137e20e193c960802afba73b5d38sm * determine when drawing is occurring. 319cfd74d65d832137e20e193c960802afba73b5d38sm */ 320cfd74d65d832137e20e193c960802afba73b5d38sm 321cfd74d65d832137e20e193c960802afba73b5d38sm public synchronized void waitDrawingComplete() { 322cfd74d65d832137e20e193c960802afba73b5d38sm } 323cfd74d65d832137e20e193c960802afba73b5d38sm 324cfd74d65d832137e20e193c960802afba73b5d38sm public void setContext(Context newContext) { 325cfd74d65d832137e20e193c960802afba73b5d38sm mContext = newContext; 326cfd74d65d832137e20e193c960802afba73b5d38sm } 327cfd74d65d832137e20e193c960802afba73b5d38sm 328cfd74d65d832137e20e193c960802afba73b5d38sm 329cfd74d65d832137e20e193c960802afba73b5d38sm} 330