1f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin/* 2f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Copyright (C) 2010 The Android Open Source Project 3f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * 4f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Licensed under the Apache License, Version 2.0 (the "License"); 5f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * you may not use this file except in compliance with the License. 6f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * You may obtain a copy of the License at 7f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * 8f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * http://www.apache.org/licenses/LICENSE-2.0 9f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * 10f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Unless required by applicable law or agreed to in writing, software 11f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * distributed under the License is distributed on an "AS IS" BASIS, 12f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * See the License for the specific language governing permissions and 14f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * limitations under the License. 15f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin */ 16f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 17f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linpackage com.android.gallery3d.ui; 18f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 197a5e1e771ae58241f3a2be36f23025f282032261Owen Linimport android.annotation.TargetApi; 20f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.content.Context; 21bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Changimport android.graphics.Matrix; 22f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.graphics.PixelFormat; 23f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.opengl.GLSurfaceView; 24df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Linimport android.os.Build; 25f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.os.Process; 26f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.os.SystemClock; 27f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.util.AttributeSet; 28f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.view.MotionEvent; 2979cf902f4cc602774e90bc2040f0029978becb61Owen Linimport android.view.SurfaceHolder; 30edada7ca2b7c70c5459cbe488c1a16cc186f2bf0Chih-Chung Changimport android.view.View; 31f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 32edada7ca2b7c70c5459cbe488c1a16cc186f2bf0Chih-Chung Changimport com.android.gallery3d.R; 332b3ee0ea07246b859a5b75d8a6102a7cce7ec838Owen Linimport com.android.gallery3d.anim.CanvasAnimation; 347a5e1e771ae58241f3a2be36f23025f282032261Owen Linimport com.android.gallery3d.common.ApiHelper; 352b3ee0ea07246b859a5b75d8a6102a7cce7ec838Owen Linimport com.android.gallery3d.common.Utils; 36a4eae1abb4f2547dfbda84301ee764ce35464881John Reckimport com.android.gallery3d.glrenderer.BasicTexture; 37a4eae1abb4f2547dfbda84301ee764ce35464881John Reckimport com.android.gallery3d.glrenderer.GLCanvas; 3850b33abe053ccab7be3d1bca2328e792507963d4George Mountimport com.android.gallery3d.glrenderer.GLES11Canvas; 3950b33abe053ccab7be3d1bca2328e792507963d4George Mountimport com.android.gallery3d.glrenderer.GLES20Canvas; 40a4eae1abb4f2547dfbda84301ee764ce35464881John Reckimport com.android.gallery3d.glrenderer.UploadedTexture; 412b3ee0ea07246b859a5b75d8a6102a7cce7ec838Owen Linimport com.android.gallery3d.util.GalleryUtils; 428fedc27c552424cc5d8e72783bd53f38538190e9Ahbong Changimport com.android.gallery3d.util.MotionEventHelper; 432b3ee0ea07246b859a5b75d8a6102a7cce7ec838Owen Linimport com.android.gallery3d.util.Profile; 442b3ee0ea07246b859a5b75d8a6102a7cce7ec838Owen Lin 45d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Linimport java.util.ArrayDeque; 46f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport java.util.ArrayList; 471ade1266d8e13830e3b07c1ebd8c95f4e859e129Chih-Chung Changimport java.util.concurrent.locks.Condition; 48f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport java.util.concurrent.locks.ReentrantLock; 492b3ee0ea07246b859a5b75d8a6102a7cce7ec838Owen Lin 50f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport javax.microedition.khronos.egl.EGLConfig; 51f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport javax.microedition.khronos.opengles.GL10; 52f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport javax.microedition.khronos.opengles.GL11; 53f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 54f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin// The root component of all <code>GLView</code>s. The rendering is done in GL 55f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin// thread while the event handling is done in the main thread. To synchronize 56f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin// the two threads, the entry points of this package need to synchronize on the 57f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin// <code>GLRootView</code> instance unless it can be proved that the rendering 58f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin// thread won't access the same thing as the method. The entry points include: 59f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin// (1) The public methods of HeadUpDisplay 60f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin// (2) The public methods of CameraHeadUpDisplay 61f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin// (3) The overridden methods in GLRootView. 62f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linpublic class GLRootView extends GLSurfaceView 63f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin implements GLSurfaceView.Renderer, GLRoot { 64f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static final String TAG = "GLRootView"; 65f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 66f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static final boolean DEBUG_FPS = false; 67f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private int mFrameCount = 0; 68f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private long mFrameCountingStart = 0; 69f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 70f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static final boolean DEBUG_INVALIDATE = false; 71f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private int mInvalidateColor = 0; 72f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 73f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static final boolean DEBUG_DRAWING_STAT = false; 74f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 753d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang private static final boolean DEBUG_PROFILE = false; 767d19f7f4281f232b9dceee4a5df390c03e2bd16bChih-Chung Chang private static final boolean DEBUG_PROFILE_SLOW_ONLY = false; 773d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang 78f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static final int FLAG_INITIALIZED = 1; 79f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static final int FLAG_NEED_LAYOUT = 2; 80f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 81f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private GL11 mGL; 827b83fb8e3a8978b33a6b9bfc56d85fe2c1a9cf06Chih-Chung Chang private GLCanvas mCanvas; 83f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private GLView mContentView; 84f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 852ef46ed28b28b355d7f3f1432c7b1196b832a859Chih-Chung Chang private OrientationSource mOrientationSource; 86bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang // mCompensation is the difference between the UI orientation on GLCanvas 87bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang // and the framework orientation. See OrientationManager for details. 88bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang private int mCompensation; 89bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang // mCompensationMatrix maps the coordinates of touch events. It is kept sync 90bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang // with mCompensation. 91bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang private Matrix mCompensationMatrix = new Matrix(); 922ef46ed28b28b355d7f3f1432c7b1196b832a859Chih-Chung Chang private int mDisplayRotation; 932ef46ed28b28b355d7f3f1432c7b1196b832a859Chih-Chung Chang 94f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private int mFlags = FLAG_NEED_LAYOUT; 95f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private volatile boolean mRenderRequested = false; 96f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 97f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private final ArrayList<CanvasAnimation> mAnimations = 98f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin new ArrayList<CanvasAnimation>(); 99f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 100d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin private final ArrayDeque<OnGLIdleListener> mIdleListeners = 101d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin new ArrayDeque<OnGLIdleListener>(); 102f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 103f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private final IdleRunner mIdleRunner = new IdleRunner(); 104f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 105f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private final ReentrantLock mRenderLock = new ReentrantLock(); 1061ade1266d8e13830e3b07c1ebd8c95f4e859e129Chih-Chung Chang private final Condition mFreezeCondition = 1071ade1266d8e13830e3b07c1ebd8c95f4e859e129Chih-Chung Chang mRenderLock.newCondition(); 1081ade1266d8e13830e3b07c1ebd8c95f4e859e129Chih-Chung Chang private boolean mFreeze; 109f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 110f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private long mLastDrawFinishTime; 111f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private boolean mInDownState = false; 112edada7ca2b7c70c5459cbe488c1a16cc186f2bf0Chih-Chung Chang private boolean mFirstDraw = true; 113f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 114f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public GLRootView(Context context) { 115f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin this(context, null); 116f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 117f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 118f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public GLRootView(Context context, AttributeSet attrs) { 119f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin super(context, attrs); 120f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mFlags |= FLAG_INITIALIZED; 121f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin setBackgroundDrawable(null); 12250b33abe053ccab7be3d1bca2328e792507963d4George Mount setEGLContextClientVersion(ApiHelper.HAS_GLES20_REQUIRED ? 2 : 1); 123ac94740cd673a016542d803c8600633c99b7427eGeorge Mount if (ApiHelper.USE_888_PIXEL_FORMAT) { 124ac94740cd673a016542d803c8600633c99b7427eGeorge Mount setEGLConfigChooser(8, 8, 8, 0, 0, 0); 125ac94740cd673a016542d803c8600633c99b7427eGeorge Mount } else { 126ac94740cd673a016542d803c8600633c99b7427eGeorge Mount setEGLConfigChooser(5, 6, 5, 0, 0, 0); 127ac94740cd673a016542d803c8600633c99b7427eGeorge Mount } 128f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin setRenderer(this); 1292e1771b997ab6966411b2c612562c538ae3e325dPin Ting if (ApiHelper.USE_888_PIXEL_FORMAT) { 1302e1771b997ab6966411b2c612562c538ae3e325dPin Ting getHolder().setFormat(PixelFormat.RGB_888); 1312e1771b997ab6966411b2c612562c538ae3e325dPin Ting } else { 1322e1771b997ab6966411b2c612562c538ae3e325dPin Ting getHolder().setFormat(PixelFormat.RGB_565); 1332e1771b997ab6966411b2c612562c538ae3e325dPin Ting } 134f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 135f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // Uncomment this to enable gl error check. 13649affdc4e274098a34e4eb2dbe4a89a750f1ba7fOwen Lin // setDebugFlags(DEBUG_CHECK_GL_ERROR); 137f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 138f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 139f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin @Override 140f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void registerLaunchedAnimation(CanvasAnimation animation) { 141f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // Register the newly launched animation so that we can set the start 142f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // time more precisely. (Usually, it takes much longer for first 143f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // rendering, so we set the animation start time as the time we 144f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // complete rendering) 145f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mAnimations.add(animation); 146f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 147f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 148f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin @Override 149f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void addOnGLIdleListener(OnGLIdleListener listener) { 150f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin synchronized (mIdleListeners) { 151f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mIdleListeners.addLast(listener); 152f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mIdleRunner.enable(); 153f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 154f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 155f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 156f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin @Override 157f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void setContentPane(GLView content) { 158f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (mContentView == content) return; 159f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (mContentView != null) { 160f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (mInDownState) { 161f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin long now = SystemClock.uptimeMillis(); 162f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin MotionEvent cancelEvent = MotionEvent.obtain( 163f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin now, now, MotionEvent.ACTION_CANCEL, 0, 0, 0); 164f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mContentView.dispatchTouchEvent(cancelEvent); 165f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin cancelEvent.recycle(); 166f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mInDownState = false; 167f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 168f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mContentView.detachFromRoot(); 169f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin BasicTexture.yieldAllTextures(); 170f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 171f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mContentView = content; 172f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (content != null) { 173f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin content.attachToRoot(this); 174f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin requestLayoutContentPane(); 175f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 176f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 177f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 178f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin @Override 17971c177759c7aa10082c8fdf909b701cf0047beadAngus Kong public void requestRenderForced() { 18071c177759c7aa10082c8fdf909b701cf0047beadAngus Kong superRequestRender(); 18171c177759c7aa10082c8fdf909b701cf0047beadAngus Kong } 18271c177759c7aa10082c8fdf909b701cf0047beadAngus Kong 18371c177759c7aa10082c8fdf909b701cf0047beadAngus Kong @Override 184f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void requestRender() { 185f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (DEBUG_INVALIDATE) { 186f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin StackTraceElement e = Thread.currentThread().getStackTrace()[4]; 187f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin String caller = e.getFileName() + ":" + e.getLineNumber() + " "; 188f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Log.d(TAG, "invalidate: " + caller); 189f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 190f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (mRenderRequested) return; 191f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mRenderRequested = true; 192b75f5defe8ace12b8b563e713f7175863ab5713dJohn Reck if (ApiHelper.HAS_POST_ON_ANIMATION) { 193b75f5defe8ace12b8b563e713f7175863ab5713dJohn Reck postOnAnimation(mRequestRenderOnAnimationFrame); 194b75f5defe8ace12b8b563e713f7175863ab5713dJohn Reck } else { 195b75f5defe8ace12b8b563e713f7175863ab5713dJohn Reck super.requestRender(); 196b75f5defe8ace12b8b563e713f7175863ab5713dJohn Reck } 197b75f5defe8ace12b8b563e713f7175863ab5713dJohn Reck } 198b75f5defe8ace12b8b563e713f7175863ab5713dJohn Reck 199b75f5defe8ace12b8b563e713f7175863ab5713dJohn Reck private Runnable mRequestRenderOnAnimationFrame = new Runnable() { 200b75f5defe8ace12b8b563e713f7175863ab5713dJohn Reck @Override 201b75f5defe8ace12b8b563e713f7175863ab5713dJohn Reck public void run() { 202b75f5defe8ace12b8b563e713f7175863ab5713dJohn Reck superRequestRender(); 203b75f5defe8ace12b8b563e713f7175863ab5713dJohn Reck } 204b75f5defe8ace12b8b563e713f7175863ab5713dJohn Reck }; 205b75f5defe8ace12b8b563e713f7175863ab5713dJohn Reck 206b75f5defe8ace12b8b563e713f7175863ab5713dJohn Reck private void superRequestRender() { 207f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin super.requestRender(); 208f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 209f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 210f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin @Override 211f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void requestLayoutContentPane() { 212f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mRenderLock.lock(); 213f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin try { 214f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (mContentView == null || (mFlags & FLAG_NEED_LAYOUT) != 0) return; 215f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 216f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // "View" system will invoke onLayout() for initialization(bug ?), we 217f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // have to ignore it since the GLThread is not ready yet. 218f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if ((mFlags & FLAG_INITIALIZED) == 0) return; 219f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 220f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mFlags |= FLAG_NEED_LAYOUT; 221f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin requestRender(); 222f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } finally { 223f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mRenderLock.unlock(); 224f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 225f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 226f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 227f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private void layoutContentPane() { 228f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mFlags &= ~FLAG_NEED_LAYOUT; 229bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang 230bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang int w = getWidth(); 231bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang int h = getHeight(); 2322ef46ed28b28b355d7f3f1432c7b1196b832a859Chih-Chung Chang int displayRotation = 0; 2332ef46ed28b28b355d7f3f1432c7b1196b832a859Chih-Chung Chang int compensation = 0; 2342ef46ed28b28b355d7f3f1432c7b1196b832a859Chih-Chung Chang 2352ef46ed28b28b355d7f3f1432c7b1196b832a859Chih-Chung Chang // Get the new orientation values 2362ef46ed28b28b355d7f3f1432c7b1196b832a859Chih-Chung Chang if (mOrientationSource != null) { 2372ef46ed28b28b355d7f3f1432c7b1196b832a859Chih-Chung Chang displayRotation = mOrientationSource.getDisplayRotation(); 2382ef46ed28b28b355d7f3f1432c7b1196b832a859Chih-Chung Chang compensation = mOrientationSource.getCompensation(); 2392ef46ed28b28b355d7f3f1432c7b1196b832a859Chih-Chung Chang } else { 2402ef46ed28b28b355d7f3f1432c7b1196b832a859Chih-Chung Chang displayRotation = 0; 2412ef46ed28b28b355d7f3f1432c7b1196b832a859Chih-Chung Chang compensation = 0; 2422ef46ed28b28b355d7f3f1432c7b1196b832a859Chih-Chung Chang } 243bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang 2442ef46ed28b28b355d7f3f1432c7b1196b832a859Chih-Chung Chang if (mCompensation != compensation) { 2452ef46ed28b28b355d7f3f1432c7b1196b832a859Chih-Chung Chang mCompensation = compensation; 246bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang if (mCompensation % 180 != 0) { 247bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang mCompensationMatrix.setRotate(mCompensation); 248bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang // move center to origin before rotation 249bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang mCompensationMatrix.preTranslate(-w / 2, -h / 2); 250bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang // align with the new origin after rotation 251bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang mCompensationMatrix.postTranslate(h / 2, w / 2); 252bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang } else { 253bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang mCompensationMatrix.setRotate(mCompensation, w / 2, h / 2); 254bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang } 255bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang } 2562ef46ed28b28b355d7f3f1432c7b1196b832a859Chih-Chung Chang mDisplayRotation = displayRotation; 257bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang 258bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang // Do the actual layout. 259bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang if (mCompensation % 180 != 0) { 260bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang int tmp = w; 261bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang w = h; 262bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang h = tmp; 263bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang } 264bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang Log.i(TAG, "layout content pane " + w + "x" + h 265bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang + " (compensation " + mCompensation + ")"); 266bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang if (mContentView != null && w != 0 && h != 0) { 267bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang mContentView.layout(0, 0, w, h); 268f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 269f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // Uncomment this to dump the view hierarchy. 270f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin //mContentView.dumpTree(""); 271f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 272f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 273f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin @Override 274f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin protected void onLayout( 275f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin boolean changed, int left, int top, int right, int bottom) { 276f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (changed) requestLayoutContentPane(); 277f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 278f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 279f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin /** 280f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Called when the context is created, possibly after automatic destruction. 281f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin */ 282f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // This is a GLSurfaceView.Renderer callback 283f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin @Override 284f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void onSurfaceCreated(GL10 gl1, EGLConfig config) { 285f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin GL11 gl = (GL11) gl1; 286f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (mGL != null) { 287f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // The GL Object has changed 288f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Log.i(TAG, "GLObject has changed from " + mGL + " to " + gl); 289f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 29037c605949219b8bf54c165c34d6405f5f2989f50Owen Lin mRenderLock.lock(); 29137c605949219b8bf54c165c34d6405f5f2989f50Owen Lin try { 29237c605949219b8bf54c165c34d6405f5f2989f50Owen Lin mGL = gl; 29350b33abe053ccab7be3d1bca2328e792507963d4George Mount mCanvas = ApiHelper.HAS_GLES20_REQUIRED ? new GLES20Canvas() : new GLES11Canvas(gl); 29437c605949219b8bf54c165c34d6405f5f2989f50Owen Lin BasicTexture.invalidateAllTextures(); 29537c605949219b8bf54c165c34d6405f5f2989f50Owen Lin } finally { 29637c605949219b8bf54c165c34d6405f5f2989f50Owen Lin mRenderLock.unlock(); 29737c605949219b8bf54c165c34d6405f5f2989f50Owen Lin } 29837c605949219b8bf54c165c34d6405f5f2989f50Owen Lin 2993d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang if (DEBUG_FPS || DEBUG_PROFILE) { 300f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY); 3013d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang } else { 3023d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY); 303f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 304f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 305f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 306f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin /** 307f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Called when the OpenGL surface is recreated without destroying the 308f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * context. 309f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin */ 310f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // This is a GLSurfaceView.Renderer callback 311f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin @Override 312f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void onSurfaceChanged(GL10 gl1, int width, int height) { 313f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Log.i(TAG, "onSurfaceChanged: " + width + "x" + height 314f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin + ", gl10: " + gl1.toString()); 315f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Process.setThreadPriority(Process.THREAD_PRIORITY_DISPLAY); 316f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin GalleryUtils.setRenderThread(); 3173d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang if (DEBUG_PROFILE) { 3183d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang Log.d(TAG, "Start profiling"); 3193d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang Profile.enable(20); // take a sample every 20ms 3203d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang } 321f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin GL11 gl = (GL11) gl1; 322f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Utils.assertTrue(mGL == gl); 323f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 324f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mCanvas.setSize(width, height); 325f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 326f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 327f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private void outputFps() { 328f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin long now = System.nanoTime(); 329f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (mFrameCountingStart == 0) { 330f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mFrameCountingStart = now; 331f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } else if ((now - mFrameCountingStart) > 1000000000) { 332f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Log.d(TAG, "fps: " + (double) mFrameCount 333f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * 1000000000 / (now - mFrameCountingStart)); 334f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mFrameCountingStart = now; 335f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mFrameCount = 0; 336f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 337f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin ++mFrameCount; 338f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 339f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 340f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin @Override 341f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void onDrawFrame(GL10 gl) { 342cb05834cedb8223fc59456afcd62fa7448f2b3b8Chih-Chung Chang AnimationTime.update(); 3433d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang long t0; 3447d19f7f4281f232b9dceee4a5df390c03e2bd16bChih-Chung Chang if (DEBUG_PROFILE_SLOW_ONLY) { 3453d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang Profile.hold(); 3463d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang t0 = System.nanoTime(); 3473d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang } 348f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mRenderLock.lock(); 3491ade1266d8e13830e3b07c1ebd8c95f4e859e129Chih-Chung Chang 3501ade1266d8e13830e3b07c1ebd8c95f4e859e129Chih-Chung Chang while (mFreeze) { 3511ade1266d8e13830e3b07c1ebd8c95f4e859e129Chih-Chung Chang mFreezeCondition.awaitUninterruptibly(); 3521ade1266d8e13830e3b07c1ebd8c95f4e859e129Chih-Chung Chang } 3531ade1266d8e13830e3b07c1ebd8c95f4e859e129Chih-Chung Chang 354f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin try { 355f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin onDrawFrameLocked(gl); 356f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } finally { 357f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mRenderLock.unlock(); 358f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 359d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin 360edada7ca2b7c70c5459cbe488c1a16cc186f2bf0Chih-Chung Chang // We put a black cover View in front of the SurfaceView and hide it 361edada7ca2b7c70c5459cbe488c1a16cc186f2bf0Chih-Chung Chang // after the first draw. This prevents the SurfaceView being transparent 362edada7ca2b7c70c5459cbe488c1a16cc186f2bf0Chih-Chung Chang // before the first draw. 363edada7ca2b7c70c5459cbe488c1a16cc186f2bf0Chih-Chung Chang if (mFirstDraw) { 364edada7ca2b7c70c5459cbe488c1a16cc186f2bf0Chih-Chung Chang mFirstDraw = false; 365edada7ca2b7c70c5459cbe488c1a16cc186f2bf0Chih-Chung Chang post(new Runnable() { 366ca7d9bfb42c1d5037bcecdde30eb836755140b03The Android Open Source Project @Override 367edada7ca2b7c70c5459cbe488c1a16cc186f2bf0Chih-Chung Chang public void run() { 368edada7ca2b7c70c5459cbe488c1a16cc186f2bf0Chih-Chung Chang View root = getRootView(); 369edada7ca2b7c70c5459cbe488c1a16cc186f2bf0Chih-Chung Chang View cover = root.findViewById(R.id.gl_root_cover); 370edada7ca2b7c70c5459cbe488c1a16cc186f2bf0Chih-Chung Chang cover.setVisibility(GONE); 371edada7ca2b7c70c5459cbe488c1a16cc186f2bf0Chih-Chung Chang } 372edada7ca2b7c70c5459cbe488c1a16cc186f2bf0Chih-Chung Chang }); 373edada7ca2b7c70c5459cbe488c1a16cc186f2bf0Chih-Chung Chang } 374edada7ca2b7c70c5459cbe488c1a16cc186f2bf0Chih-Chung Chang 3757d19f7f4281f232b9dceee4a5df390c03e2bd16bChih-Chung Chang if (DEBUG_PROFILE_SLOW_ONLY) { 3763d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang long t = System.nanoTime(); 3773d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang long durationInMs = (t - mLastDrawFinishTime) / 1000000; 3783d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang long durationDrawInMs = (t - t0) / 1000000; 3793d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang mLastDrawFinishTime = t; 3803d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang 3813d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang if (durationInMs > 34) { // 34ms -> we skipped at least 2 frames 3823d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang Log.v(TAG, "----- SLOW (" + durationDrawInMs + "/" + 3833d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang durationInMs + ") -----"); 3843d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang Profile.commit(); 3853d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang } else { 3863d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang Profile.drop(); 387f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 388f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 389f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 390f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 391f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private void onDrawFrameLocked(GL10 gl) { 392f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (DEBUG_FPS) outputFps(); 393f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 394f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // release the unbound textures and deleted buffers. 395f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mCanvas.deleteRecycledResources(); 396f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 397f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // reset texture upload limit 398f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin UploadedTexture.resetUploadLimit(); 399f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 400f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mRenderRequested = false; 401f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 402695e1aa059cbc2cb2988f6beb0fee8ff7952b229John Reck if ((mOrientationSource != null 403695e1aa059cbc2cb2988f6beb0fee8ff7952b229John Reck && mDisplayRotation != mOrientationSource.getDisplayRotation()) 404695e1aa059cbc2cb2988f6beb0fee8ff7952b229John Reck || (mFlags & FLAG_NEED_LAYOUT) != 0) { 405695e1aa059cbc2cb2988f6beb0fee8ff7952b229John Reck layoutContentPane(); 406695e1aa059cbc2cb2988f6beb0fee8ff7952b229John Reck } 407f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 408bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang mCanvas.save(GLCanvas.SAVE_FLAG_ALL); 409bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang rotateCanvas(-mCompensation); 410f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (mContentView != null) { 411f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mContentView.render(mCanvas); 4126adf13c2aeee89735df1b7c12670a026e5087161John Reck } else { 4136adf13c2aeee89735df1b7c12670a026e5087161John Reck // Make sure we always draw something to prevent displaying garbage 4146adf13c2aeee89735df1b7c12670a026e5087161John Reck mCanvas.clearBuffer(); 415f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 416bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang mCanvas.restore(); 417f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 418f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (!mAnimations.isEmpty()) { 4197d19f7f4281f232b9dceee4a5df390c03e2bd16bChih-Chung Chang long now = AnimationTime.get(); 420f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin for (int i = 0, n = mAnimations.size(); i < n; i++) { 421f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mAnimations.get(i).setStartTime(now); 422f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 423f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mAnimations.clear(); 424f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 425f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 426f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (UploadedTexture.uploadLimitReached()) { 427f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin requestRender(); 428f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 429f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 430f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin synchronized (mIdleListeners) { 431d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin if (!mIdleListeners.isEmpty()) mIdleRunner.enable(); 432f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 433f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 434f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (DEBUG_INVALIDATE) { 435f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mCanvas.fillRect(10, 10, 5, 5, mInvalidateColor); 436f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mInvalidateColor = ~mInvalidateColor; 437f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 438f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 439f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (DEBUG_DRAWING_STAT) { 440f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mCanvas.dumpStatisticsAndClear(); 441f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 442f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 443f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 444bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang private void rotateCanvas(int degrees) { 445bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang if (degrees == 0) return; 446bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang int w = getWidth(); 447bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang int h = getHeight(); 448bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang int cx = w / 2; 449bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang int cy = h / 2; 450bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang mCanvas.translate(cx, cy); 451bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang mCanvas.rotate(degrees, 0, 0, 1); 452bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang if (degrees % 180 != 0) { 453bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang mCanvas.translate(-cy, -cx); 454bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang } else { 455bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang mCanvas.translate(-cx, -cy); 456bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang } 457bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang } 458bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang 459f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin @Override 460f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public boolean dispatchTouchEvent(MotionEvent event) { 461bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang if (!isEnabled()) return false; 462bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang 463f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int action = event.getAction(); 464f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (action == MotionEvent.ACTION_CANCEL 465f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin || action == MotionEvent.ACTION_UP) { 466f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mInDownState = false; 467f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } else if (!mInDownState && action != MotionEvent.ACTION_DOWN) { 468f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return false; 469f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 470bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang 471bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang if (mCompensation != 0) { 4728fedc27c552424cc5d8e72783bd53f38538190e9Ahbong Chang event = MotionEventHelper.transformEvent(event, mCompensationMatrix); 473bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang } 474bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang 475f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mRenderLock.lock(); 476f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin try { 477f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // If this has been detached from root, we don't need to handle event 478f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin boolean handled = mContentView != null 479f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin && mContentView.dispatchTouchEvent(event); 480f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (action == MotionEvent.ACTION_DOWN && handled) { 481f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mInDownState = true; 482f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 483f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return handled; 484f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } finally { 485f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mRenderLock.unlock(); 486f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 487f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 488f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 489f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private class IdleRunner implements Runnable { 490f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // true if the idle runner is in the queue 491f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private boolean mActive = false; 492f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 493f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin @Override 494f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void run() { 495f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin OnGLIdleListener listener; 496f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin synchronized (mIdleListeners) { 497f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mActive = false; 498f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (mIdleListeners.isEmpty()) return; 499f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin listener = mIdleListeners.removeFirst(); 500f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 501f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mRenderLock.lock(); 5025515801ddea6953e95b2c41a9434bb1fe489e08aOwen Lin boolean keepInQueue; 503f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin try { 5045515801ddea6953e95b2c41a9434bb1fe489e08aOwen Lin keepInQueue = listener.onGLIdle(mCanvas, mRenderRequested); 505f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } finally { 506f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mRenderLock.unlock(); 507f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 508f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin synchronized (mIdleListeners) { 5095515801ddea6953e95b2c41a9434bb1fe489e08aOwen Lin if (keepInQueue) mIdleListeners.addLast(listener); 5105515801ddea6953e95b2c41a9434bb1fe489e08aOwen Lin if (!mRenderRequested && !mIdleListeners.isEmpty()) enable(); 511f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 512f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 513f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 514f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void enable() { 515f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // Who gets the flag can add it to the queue 516f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (mActive) return; 517f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mActive = true; 518f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin queueEvent(this); 519f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 520f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 521f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 522f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin @Override 523f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void lockRenderThread() { 524f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mRenderLock.lock(); 525f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 526f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 527f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin @Override 528f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void unlockRenderThread() { 529f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mRenderLock.unlock(); 530f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 5313d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang 5323d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang @Override 5333d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang public void onPause() { 53479cf902f4cc602774e90bc2040f0029978becb61Owen Lin unfreeze(); 5353d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang super.onPause(); 5363d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang if (DEBUG_PROFILE) { 5373d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang Log.d(TAG, "Stop profiling"); 5383d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang Profile.disableAll(); 5393d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang Profile.dumpToFile("/sdcard/gallery.prof"); 5403d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang Profile.reset(); 5413d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang } 5423d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang } 543bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang 544bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang @Override 5452ef46ed28b28b355d7f3f1432c7b1196b832a859Chih-Chung Chang public void setOrientationSource(OrientationSource source) { 5462ef46ed28b28b355d7f3f1432c7b1196b832a859Chih-Chung Chang mOrientationSource = source; 5472ef46ed28b28b355d7f3f1432c7b1196b832a859Chih-Chung Chang } 5482ef46ed28b28b355d7f3f1432c7b1196b832a859Chih-Chung Chang 5492ef46ed28b28b355d7f3f1432c7b1196b832a859Chih-Chung Chang @Override 5502ef46ed28b28b355d7f3f1432c7b1196b832a859Chih-Chung Chang public int getDisplayRotation() { 5512ef46ed28b28b355d7f3f1432c7b1196b832a859Chih-Chung Chang return mDisplayRotation; 5522ef46ed28b28b355d7f3f1432c7b1196b832a859Chih-Chung Chang } 5532ef46ed28b28b355d7f3f1432c7b1196b832a859Chih-Chung Chang 5542ef46ed28b28b355d7f3f1432c7b1196b832a859Chih-Chung Chang @Override 5552ef46ed28b28b355d7f3f1432c7b1196b832a859Chih-Chung Chang public int getCompensation() { 5562ef46ed28b28b355d7f3f1432c7b1196b832a859Chih-Chung Chang return mCompensation; 5572ef46ed28b28b355d7f3f1432c7b1196b832a859Chih-Chung Chang } 5582ef46ed28b28b355d7f3f1432c7b1196b832a859Chih-Chung Chang 5592ef46ed28b28b355d7f3f1432c7b1196b832a859Chih-Chung Chang @Override 5602ef46ed28b28b355d7f3f1432c7b1196b832a859Chih-Chung Chang public Matrix getCompensationMatrix() { 5612ef46ed28b28b355d7f3f1432c7b1196b832a859Chih-Chung Chang return mCompensationMatrix; 562bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang } 5631ade1266d8e13830e3b07c1ebd8c95f4e859e129Chih-Chung Chang 5641ade1266d8e13830e3b07c1ebd8c95f4e859e129Chih-Chung Chang @Override 5651ade1266d8e13830e3b07c1ebd8c95f4e859e129Chih-Chung Chang public void freeze() { 5661ade1266d8e13830e3b07c1ebd8c95f4e859e129Chih-Chung Chang mRenderLock.lock(); 5671ade1266d8e13830e3b07c1ebd8c95f4e859e129Chih-Chung Chang mFreeze = true; 5681ade1266d8e13830e3b07c1ebd8c95f4e859e129Chih-Chung Chang mRenderLock.unlock(); 5691ade1266d8e13830e3b07c1ebd8c95f4e859e129Chih-Chung Chang } 5701ade1266d8e13830e3b07c1ebd8c95f4e859e129Chih-Chung Chang 5711ade1266d8e13830e3b07c1ebd8c95f4e859e129Chih-Chung Chang @Override 5721ade1266d8e13830e3b07c1ebd8c95f4e859e129Chih-Chung Chang public void unfreeze() { 5731ade1266d8e13830e3b07c1ebd8c95f4e859e129Chih-Chung Chang mRenderLock.lock(); 5741ade1266d8e13830e3b07c1ebd8c95f4e859e129Chih-Chung Chang mFreeze = false; 5751ade1266d8e13830e3b07c1ebd8c95f4e859e129Chih-Chung Chang mFreezeCondition.signalAll(); 5761ade1266d8e13830e3b07c1ebd8c95f4e859e129Chih-Chung Chang mRenderLock.unlock(); 5771ade1266d8e13830e3b07c1ebd8c95f4e859e129Chih-Chung Chang } 57879cf902f4cc602774e90bc2040f0029978becb61Owen Lin 5790b2486cff0c1b951c54325596256b986307f7f3aChih-Chung Chang @Override 580df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin @TargetApi(Build.VERSION_CODES.JELLY_BEAN) 5810b2486cff0c1b951c54325596256b986307f7f3aChih-Chung Chang public void setLightsOutMode(boolean enabled) { 582b0774a3bfb24d8515fc3ddf152fabf82f0ff67e5Yuli Huang if (!ApiHelper.HAS_SET_SYSTEM_UI_VISIBILITY) return; 583b0774a3bfb24d8515fc3ddf152fabf82f0ff67e5Yuli Huang 5847a5e1e771ae58241f3a2be36f23025f282032261Owen Lin int flags = 0; 5857a5e1e771ae58241f3a2be36f23025f282032261Owen Lin if (enabled) { 586ca7d9bfb42c1d5037bcecdde30eb836755140b03The Android Open Source Project flags = STATUS_BAR_HIDDEN; 5877a5e1e771ae58241f3a2be36f23025f282032261Owen Lin if (ApiHelper.HAS_VIEW_SYSTEM_UI_FLAG_LAYOUT_STABLE) { 5887a5e1e771ae58241f3a2be36f23025f282032261Owen Lin flags |= (SYSTEM_UI_FLAG_FULLSCREEN | SYSTEM_UI_FLAG_LAYOUT_STABLE); 5897a5e1e771ae58241f3a2be36f23025f282032261Owen Lin } 5907a5e1e771ae58241f3a2be36f23025f282032261Owen Lin } 5910b2486cff0c1b951c54325596256b986307f7f3aChih-Chung Chang setSystemUiVisibility(flags); 5920b2486cff0c1b951c54325596256b986307f7f3aChih-Chung Chang } 5930b2486cff0c1b951c54325596256b986307f7f3aChih-Chung Chang 59479cf902f4cc602774e90bc2040f0029978becb61Owen Lin // We need to unfreeze in the following methods and in onPause(). 59579cf902f4cc602774e90bc2040f0029978becb61Owen Lin // These methods will wait on GLThread. If we have freezed the GLRootView, 59679cf902f4cc602774e90bc2040f0029978becb61Owen Lin // the GLThread will wait on main thread to call unfreeze and cause dead 59779cf902f4cc602774e90bc2040f0029978becb61Owen Lin // lock. 59879cf902f4cc602774e90bc2040f0029978becb61Owen Lin @Override 59979cf902f4cc602774e90bc2040f0029978becb61Owen Lin public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { 60079cf902f4cc602774e90bc2040f0029978becb61Owen Lin unfreeze(); 60179cf902f4cc602774e90bc2040f0029978becb61Owen Lin super.surfaceChanged(holder, format, w, h); 60279cf902f4cc602774e90bc2040f0029978becb61Owen Lin } 60379cf902f4cc602774e90bc2040f0029978becb61Owen Lin 60479cf902f4cc602774e90bc2040f0029978becb61Owen Lin @Override 60579cf902f4cc602774e90bc2040f0029978becb61Owen Lin public void surfaceCreated(SurfaceHolder holder) { 60679cf902f4cc602774e90bc2040f0029978becb61Owen Lin unfreeze(); 60779cf902f4cc602774e90bc2040f0029978becb61Owen Lin super.surfaceCreated(holder); 60879cf902f4cc602774e90bc2040f0029978becb61Owen Lin } 60979cf902f4cc602774e90bc2040f0029978becb61Owen Lin 61079cf902f4cc602774e90bc2040f0029978becb61Owen Lin @Override 61179cf902f4cc602774e90bc2040f0029978becb61Owen Lin public void surfaceDestroyed(SurfaceHolder holder) { 61279cf902f4cc602774e90bc2040f0029978becb61Owen Lin unfreeze(); 61379cf902f4cc602774e90bc2040f0029978becb61Owen Lin super.surfaceDestroyed(holder); 61479cf902f4cc602774e90bc2040f0029978becb61Owen Lin } 61579cf902f4cc602774e90bc2040f0029978becb61Owen Lin 61679cf902f4cc602774e90bc2040f0029978becb61Owen Lin @Override 61779cf902f4cc602774e90bc2040f0029978becb61Owen Lin protected void onDetachedFromWindow() { 61879cf902f4cc602774e90bc2040f0029978becb61Owen Lin unfreeze(); 61979cf902f4cc602774e90bc2040f0029978becb61Owen Lin super.onDetachedFromWindow(); 62079cf902f4cc602774e90bc2040f0029978becb61Owen Lin } 62179cf902f4cc602774e90bc2040f0029978becb61Owen Lin 62279cf902f4cc602774e90bc2040f0029978becb61Owen Lin @Override 62379cf902f4cc602774e90bc2040f0029978becb61Owen Lin protected void finalize() throws Throwable { 62479cf902f4cc602774e90bc2040f0029978becb61Owen Lin try { 62579cf902f4cc602774e90bc2040f0029978becb61Owen Lin unfreeze(); 62679cf902f4cc602774e90bc2040f0029978becb61Owen Lin } finally { 62779cf902f4cc602774e90bc2040f0029978becb61Owen Lin super.finalize(); 62879cf902f4cc602774e90bc2040f0029978becb61Owen Lin } 62979cf902f4cc602774e90bc2040f0029978becb61Owen Lin } 630f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin} 631