GLRootView.java revision edada7ca2b7c70c5459cbe488c1a16cc186f2bf0
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
19f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.content.Context;
20bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Changimport android.graphics.Matrix;
21f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.graphics.PixelFormat;
22f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.opengl.GLSurfaceView;
23f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.os.Process;
24f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.os.SystemClock;
25f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.util.AttributeSet;
26f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.view.MotionEvent;
2779cf902f4cc602774e90bc2040f0029978becb61Owen Linimport android.view.SurfaceHolder;
28edada7ca2b7c70c5459cbe488c1a16cc186f2bf0Chih-Chung Changimport android.view.View;
29f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
30edada7ca2b7c70c5459cbe488c1a16cc186f2bf0Chih-Chung Changimport com.android.gallery3d.R;
312b3ee0ea07246b859a5b75d8a6102a7cce7ec838Owen Linimport com.android.gallery3d.anim.CanvasAnimation;
322b3ee0ea07246b859a5b75d8a6102a7cce7ec838Owen Linimport com.android.gallery3d.common.Utils;
332b3ee0ea07246b859a5b75d8a6102a7cce7ec838Owen Linimport com.android.gallery3d.util.GalleryUtils;
342b3ee0ea07246b859a5b75d8a6102a7cce7ec838Owen Linimport com.android.gallery3d.util.Profile;
352b3ee0ea07246b859a5b75d8a6102a7cce7ec838Owen Lin
36d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Linimport java.util.ArrayDeque;
37f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport java.util.ArrayList;
381ade1266d8e13830e3b07c1ebd8c95f4e859e129Chih-Chung Changimport java.util.concurrent.locks.Condition;
39f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport java.util.concurrent.locks.ReentrantLock;
402b3ee0ea07246b859a5b75d8a6102a7cce7ec838Owen Lin
41f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport javax.microedition.khronos.egl.EGLConfig;
42f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport javax.microedition.khronos.opengles.GL10;
43f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport javax.microedition.khronos.opengles.GL11;
44f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
45f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin// The root component of all <code>GLView</code>s. The rendering is done in GL
46f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin// thread while the event handling is done in the main thread.  To synchronize
47f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin// the two threads, the entry points of this package need to synchronize on the
48f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin// <code>GLRootView</code> instance unless it can be proved that the rendering
49f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin// thread won't access the same thing as the method. The entry points include:
50f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin// (1) The public methods of HeadUpDisplay
51f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin// (2) The public methods of CameraHeadUpDisplay
52f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin// (3) The overridden methods in GLRootView.
53f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linpublic class GLRootView extends GLSurfaceView
54f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        implements GLSurfaceView.Renderer, GLRoot {
55f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private static final String TAG = "GLRootView";
56f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
57f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private static final boolean DEBUG_FPS = false;
58f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private int mFrameCount = 0;
59f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private long mFrameCountingStart = 0;
60f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
61f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private static final boolean DEBUG_INVALIDATE = false;
62f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private int mInvalidateColor = 0;
63f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
64f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private static final boolean DEBUG_DRAWING_STAT = false;
65f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
663d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang    private static final boolean DEBUG_PROFILE = false;
677d19f7f4281f232b9dceee4a5df390c03e2bd16bChih-Chung Chang    private static final boolean DEBUG_PROFILE_SLOW_ONLY = false;
683d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang
69f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private static final int FLAG_INITIALIZED = 1;
70f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private static final int FLAG_NEED_LAYOUT = 2;
71f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
72f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private GL11 mGL;
737b83fb8e3a8978b33a6b9bfc56d85fe2c1a9cf06Chih-Chung Chang    private GLCanvas mCanvas;
74f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private GLView mContentView;
75f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
762ef46ed28b28b355d7f3f1432c7b1196b832a859Chih-Chung Chang    private OrientationSource mOrientationSource;
77bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang    // mCompensation is the difference between the UI orientation on GLCanvas
78bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang    // and the framework orientation. See OrientationManager for details.
79bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang    private int mCompensation;
80bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang    // mCompensationMatrix maps the coordinates of touch events. It is kept sync
81bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang    // with mCompensation.
82bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang    private Matrix mCompensationMatrix = new Matrix();
832ef46ed28b28b355d7f3f1432c7b1196b832a859Chih-Chung Chang    private int mDisplayRotation;
842ef46ed28b28b355d7f3f1432c7b1196b832a859Chih-Chung Chang
85bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang    // The value which will become mCompensation in next layout.
86bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang    private int mPendingCompensation;
87bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang
88f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private int mFlags = FLAG_NEED_LAYOUT;
89f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private volatile boolean mRenderRequested = false;
90f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
91f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private final GalleryEGLConfigChooser mEglConfigChooser =
92f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            new GalleryEGLConfigChooser();
93f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
94f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private final ArrayList<CanvasAnimation> mAnimations =
95f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            new ArrayList<CanvasAnimation>();
96f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
97d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin    private final ArrayDeque<OnGLIdleListener> mIdleListeners =
98d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin            new ArrayDeque<OnGLIdleListener>();
99f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
100f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private final IdleRunner mIdleRunner = new IdleRunner();
101f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
102f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private final ReentrantLock mRenderLock = new ReentrantLock();
1031ade1266d8e13830e3b07c1ebd8c95f4e859e129Chih-Chung Chang    private final Condition mFreezeCondition =
1041ade1266d8e13830e3b07c1ebd8c95f4e859e129Chih-Chung Chang            mRenderLock.newCondition();
1051ade1266d8e13830e3b07c1ebd8c95f4e859e129Chih-Chung Chang    private boolean mFreeze;
106f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
107f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private long mLastDrawFinishTime;
108f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private boolean mInDownState = false;
109edada7ca2b7c70c5459cbe488c1a16cc186f2bf0Chih-Chung Chang    private boolean mFirstDraw = true;
110f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
111f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public GLRootView(Context context) {
112f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        this(context, null);
113f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
114f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
115f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public GLRootView(Context context, AttributeSet attrs) {
116f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        super(context, attrs);
117f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mFlags |= FLAG_INITIALIZED;
118f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        setBackgroundDrawable(null);
119f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        setEGLConfigChooser(mEglConfigChooser);
120f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        setRenderer(this);
121f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        getHolder().setFormat(PixelFormat.RGB_565);
122f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
123f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        // Uncomment this to enable gl error check.
12449affdc4e274098a34e4eb2dbe4a89a750f1ba7fOwen Lin        // setDebugFlags(DEBUG_CHECK_GL_ERROR);
125f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
126f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
127f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    @Override
128f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public void registerLaunchedAnimation(CanvasAnimation animation) {
129f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        // Register the newly launched animation so that we can set the start
130f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        // time more precisely. (Usually, it takes much longer for first
131f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        // rendering, so we set the animation start time as the time we
132f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        // complete rendering)
133f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mAnimations.add(animation);
134f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
135f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
136f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    @Override
137f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public void addOnGLIdleListener(OnGLIdleListener listener) {
138f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        synchronized (mIdleListeners) {
139f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            mIdleListeners.addLast(listener);
140f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            mIdleRunner.enable();
141f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
142f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
143f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
144f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    @Override
145f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public void setContentPane(GLView content) {
146f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        if (mContentView == content) return;
147f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        if (mContentView != null) {
148f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            if (mInDownState) {
149f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                long now = SystemClock.uptimeMillis();
150f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                MotionEvent cancelEvent = MotionEvent.obtain(
151f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                        now, now, MotionEvent.ACTION_CANCEL, 0, 0, 0);
152f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                mContentView.dispatchTouchEvent(cancelEvent);
153f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                cancelEvent.recycle();
154f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                mInDownState = false;
155f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
156f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            mContentView.detachFromRoot();
157f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            BasicTexture.yieldAllTextures();
158f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
159f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mContentView = content;
160f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        if (content != null) {
161f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            content.attachToRoot(this);
162f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            requestLayoutContentPane();
163f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
164f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
165f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
166f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    @Override
167f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public void requestRender() {
168f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        if (DEBUG_INVALIDATE) {
169f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            StackTraceElement e = Thread.currentThread().getStackTrace()[4];
170f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            String caller = e.getFileName() + ":" + e.getLineNumber() + " ";
171f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            Log.d(TAG, "invalidate: " + caller);
172f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
173f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        if (mRenderRequested) return;
174f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mRenderRequested = true;
175f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        super.requestRender();
176f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
177f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
178f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    @Override
179f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public void requestLayoutContentPane() {
180f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mRenderLock.lock();
181f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        try {
182f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            if (mContentView == null || (mFlags & FLAG_NEED_LAYOUT) != 0) return;
183f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
184f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            // "View" system will invoke onLayout() for initialization(bug ?), we
185f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            // have to ignore it since the GLThread is not ready yet.
186f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            if ((mFlags & FLAG_INITIALIZED) == 0) return;
187f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
188f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            mFlags |= FLAG_NEED_LAYOUT;
189f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            requestRender();
190f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        } finally {
191f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            mRenderLock.unlock();
192f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
193f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
194f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
195f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private void layoutContentPane() {
196f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mFlags &= ~FLAG_NEED_LAYOUT;
197bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang
198bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang        int w = getWidth();
199bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang        int h = getHeight();
2002ef46ed28b28b355d7f3f1432c7b1196b832a859Chih-Chung Chang        int displayRotation = 0;
2012ef46ed28b28b355d7f3f1432c7b1196b832a859Chih-Chung Chang        int compensation = 0;
2022ef46ed28b28b355d7f3f1432c7b1196b832a859Chih-Chung Chang
2032ef46ed28b28b355d7f3f1432c7b1196b832a859Chih-Chung Chang        // Get the new orientation values
2042ef46ed28b28b355d7f3f1432c7b1196b832a859Chih-Chung Chang        if (mOrientationSource != null) {
2052ef46ed28b28b355d7f3f1432c7b1196b832a859Chih-Chung Chang            displayRotation = mOrientationSource.getDisplayRotation();
2062ef46ed28b28b355d7f3f1432c7b1196b832a859Chih-Chung Chang            compensation = mOrientationSource.getCompensation();
2072ef46ed28b28b355d7f3f1432c7b1196b832a859Chih-Chung Chang        } else {
2082ef46ed28b28b355d7f3f1432c7b1196b832a859Chih-Chung Chang            displayRotation = 0;
2092ef46ed28b28b355d7f3f1432c7b1196b832a859Chih-Chung Chang            compensation = 0;
2102ef46ed28b28b355d7f3f1432c7b1196b832a859Chih-Chung Chang        }
211bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang
2122ef46ed28b28b355d7f3f1432c7b1196b832a859Chih-Chung Chang        if (mCompensation != compensation) {
2132ef46ed28b28b355d7f3f1432c7b1196b832a859Chih-Chung Chang            mCompensation = compensation;
214bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang            if (mCompensation % 180 != 0) {
215bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang                mCompensationMatrix.setRotate(mCompensation);
216bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang                // move center to origin before rotation
217bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang                mCompensationMatrix.preTranslate(-w / 2, -h / 2);
218bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang                // align with the new origin after rotation
219bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang                mCompensationMatrix.postTranslate(h / 2, w / 2);
220bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang            } else {
221bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang                mCompensationMatrix.setRotate(mCompensation, w / 2, h / 2);
222bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang            }
223bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang        }
2242ef46ed28b28b355d7f3f1432c7b1196b832a859Chih-Chung Chang        mDisplayRotation = displayRotation;
225bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang
226bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang        // Do the actual layout.
227bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang        if (mCompensation % 180 != 0) {
228bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang            int tmp = w;
229bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang            w = h;
230bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang            h = tmp;
231bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang        }
232bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang        Log.i(TAG, "layout content pane " + w + "x" + h
233bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang                + " (compensation " + mCompensation + ")");
234bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang        if (mContentView != null && w != 0 && h != 0) {
235bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang            mContentView.layout(0, 0, w, h);
236f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
237f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        // Uncomment this to dump the view hierarchy.
238f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        //mContentView.dumpTree("");
239f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
240f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
241f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    @Override
242f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    protected void onLayout(
243f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            boolean changed, int left, int top, int right, int bottom) {
244f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        if (changed) requestLayoutContentPane();
245f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
246f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
247f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    /**
248f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin     * Called when the context is created, possibly after automatic destruction.
249f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin     */
250f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    // This is a GLSurfaceView.Renderer callback
251f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    @Override
252f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public void onSurfaceCreated(GL10 gl1, EGLConfig config) {
253f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        GL11 gl = (GL11) gl1;
254f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        if (mGL != null) {
255f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            // The GL Object has changed
256f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            Log.i(TAG, "GLObject has changed from " + mGL + " to " + gl);
257f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
25837c605949219b8bf54c165c34d6405f5f2989f50Owen Lin        mRenderLock.lock();
25937c605949219b8bf54c165c34d6405f5f2989f50Owen Lin        try {
26037c605949219b8bf54c165c34d6405f5f2989f50Owen Lin            mGL = gl;
26137c605949219b8bf54c165c34d6405f5f2989f50Owen Lin            mCanvas = new GLCanvasImpl(gl);
26237c605949219b8bf54c165c34d6405f5f2989f50Owen Lin            BasicTexture.invalidateAllTextures();
26337c605949219b8bf54c165c34d6405f5f2989f50Owen Lin        } finally {
26437c605949219b8bf54c165c34d6405f5f2989f50Owen Lin            mRenderLock.unlock();
26537c605949219b8bf54c165c34d6405f5f2989f50Owen Lin        }
26637c605949219b8bf54c165c34d6405f5f2989f50Owen Lin
2673d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        if (DEBUG_FPS || DEBUG_PROFILE) {
268f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);
2693d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        } else {
2703d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
271f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
272f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
273f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
274f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    /**
275f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin     * Called when the OpenGL surface is recreated without destroying the
276f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin     * context.
277f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin     */
278f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    // This is a GLSurfaceView.Renderer callback
279f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    @Override
280f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public void onSurfaceChanged(GL10 gl1, int width, int height) {
281f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        Log.i(TAG, "onSurfaceChanged: " + width + "x" + height
282f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                + ", gl10: " + gl1.toString());
283f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        Process.setThreadPriority(Process.THREAD_PRIORITY_DISPLAY);
284f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        GalleryUtils.setRenderThread();
2853d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        if (DEBUG_PROFILE) {
2863d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            Log.d(TAG, "Start profiling");
2873d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            Profile.enable(20);  // take a sample every 20ms
2883d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        }
289f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        GL11 gl = (GL11) gl1;
290f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        Utils.assertTrue(mGL == gl);
291f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
292f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mCanvas.setSize(width, height);
293f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
294f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
295f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private void outputFps() {
296f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        long now = System.nanoTime();
297f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        if (mFrameCountingStart == 0) {
298f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            mFrameCountingStart = now;
299f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        } else if ((now - mFrameCountingStart) > 1000000000) {
300f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            Log.d(TAG, "fps: " + (double) mFrameCount
301f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                    * 1000000000 / (now - mFrameCountingStart));
302f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            mFrameCountingStart = now;
303f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            mFrameCount = 0;
304f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
305f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        ++mFrameCount;
306f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
307f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
308f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    @Override
309f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public void onDrawFrame(GL10 gl) {
310cb05834cedb8223fc59456afcd62fa7448f2b3b8Chih-Chung Chang        AnimationTime.update();
3113d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        long t0;
3127d19f7f4281f232b9dceee4a5df390c03e2bd16bChih-Chung Chang        if (DEBUG_PROFILE_SLOW_ONLY) {
3133d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            Profile.hold();
3143d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            t0 = System.nanoTime();
3153d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        }
316f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mRenderLock.lock();
3171ade1266d8e13830e3b07c1ebd8c95f4e859e129Chih-Chung Chang
3181ade1266d8e13830e3b07c1ebd8c95f4e859e129Chih-Chung Chang        while (mFreeze) {
3191ade1266d8e13830e3b07c1ebd8c95f4e859e129Chih-Chung Chang            mFreezeCondition.awaitUninterruptibly();
3201ade1266d8e13830e3b07c1ebd8c95f4e859e129Chih-Chung Chang        }
3211ade1266d8e13830e3b07c1ebd8c95f4e859e129Chih-Chung Chang
322f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        try {
323f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            onDrawFrameLocked(gl);
324f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        } finally {
325f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            mRenderLock.unlock();
326f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
327d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin
328edada7ca2b7c70c5459cbe488c1a16cc186f2bf0Chih-Chung Chang        // We put a black cover View in front of the SurfaceView and hide it
329edada7ca2b7c70c5459cbe488c1a16cc186f2bf0Chih-Chung Chang        // after the first draw. This prevents the SurfaceView being transparent
330edada7ca2b7c70c5459cbe488c1a16cc186f2bf0Chih-Chung Chang        // before the first draw.
331edada7ca2b7c70c5459cbe488c1a16cc186f2bf0Chih-Chung Chang        if (mFirstDraw) {
332edada7ca2b7c70c5459cbe488c1a16cc186f2bf0Chih-Chung Chang            mFirstDraw = false;
333edada7ca2b7c70c5459cbe488c1a16cc186f2bf0Chih-Chung Chang            post(new Runnable() {
334edada7ca2b7c70c5459cbe488c1a16cc186f2bf0Chih-Chung Chang                    public void run() {
335edada7ca2b7c70c5459cbe488c1a16cc186f2bf0Chih-Chung Chang                        View root = getRootView();
336edada7ca2b7c70c5459cbe488c1a16cc186f2bf0Chih-Chung Chang                        View cover = root.findViewById(R.id.gl_root_cover);
337edada7ca2b7c70c5459cbe488c1a16cc186f2bf0Chih-Chung Chang                        cover.setVisibility(GONE);
338edada7ca2b7c70c5459cbe488c1a16cc186f2bf0Chih-Chung Chang                    }
339edada7ca2b7c70c5459cbe488c1a16cc186f2bf0Chih-Chung Chang                });
340edada7ca2b7c70c5459cbe488c1a16cc186f2bf0Chih-Chung Chang        }
341edada7ca2b7c70c5459cbe488c1a16cc186f2bf0Chih-Chung Chang
3427d19f7f4281f232b9dceee4a5df390c03e2bd16bChih-Chung Chang        if (DEBUG_PROFILE_SLOW_ONLY) {
3433d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            long t = System.nanoTime();
3443d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            long durationInMs = (t - mLastDrawFinishTime) / 1000000;
3453d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            long durationDrawInMs = (t - t0) / 1000000;
3463d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            mLastDrawFinishTime = t;
3473d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang
3483d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            if (durationInMs > 34) {  // 34ms -> we skipped at least 2 frames
3493d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang                Log.v(TAG, "----- SLOW (" + durationDrawInMs + "/" +
3503d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang                        durationInMs + ") -----");
3513d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang                Profile.commit();
3523d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            } else {
3533d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang                Profile.drop();
354f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
355f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
356f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
357f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
358f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private void onDrawFrameLocked(GL10 gl) {
359f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        if (DEBUG_FPS) outputFps();
360f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
361f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        // release the unbound textures and deleted buffers.
362f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mCanvas.deleteRecycledResources();
363f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
364f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        // reset texture upload limit
365f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        UploadedTexture.resetUploadLimit();
366f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
367f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mRenderRequested = false;
368f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
369f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        if ((mFlags & FLAG_NEED_LAYOUT) != 0) layoutContentPane();
370f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
371bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang        mCanvas.save(GLCanvas.SAVE_FLAG_ALL);
372bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang        rotateCanvas(-mCompensation);
373f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        if (mContentView != null) {
374f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin           mContentView.render(mCanvas);
375f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
376bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang        mCanvas.restore();
377f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
378f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        if (!mAnimations.isEmpty()) {
3797d19f7f4281f232b9dceee4a5df390c03e2bd16bChih-Chung Chang            long now = AnimationTime.get();
380f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            for (int i = 0, n = mAnimations.size(); i < n; i++) {
381f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                mAnimations.get(i).setStartTime(now);
382f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
383f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            mAnimations.clear();
384f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
385f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
386f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        if (UploadedTexture.uploadLimitReached()) {
387f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            requestRender();
388f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
389f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
390f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        synchronized (mIdleListeners) {
391d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin            if (!mIdleListeners.isEmpty()) mIdleRunner.enable();
392f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
393f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
394f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        if (DEBUG_INVALIDATE) {
395f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            mCanvas.fillRect(10, 10, 5, 5, mInvalidateColor);
396f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            mInvalidateColor = ~mInvalidateColor;
397f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
398f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
399f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        if (DEBUG_DRAWING_STAT) {
400f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            mCanvas.dumpStatisticsAndClear();
401f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
402f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
403f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
404bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang    private void rotateCanvas(int degrees) {
405bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang        if (degrees == 0) return;
406bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang        int w = getWidth();
407bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang        int h = getHeight();
408bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang        int cx = w / 2;
409bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang        int cy = h / 2;
410bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang        mCanvas.translate(cx, cy);
411bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang        mCanvas.rotate(degrees, 0, 0, 1);
412bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang        if (degrees % 180 != 0) {
413bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang            mCanvas.translate(-cy, -cx);
414bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang        } else {
415bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang            mCanvas.translate(-cx, -cy);
416bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang        }
417bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang    }
418bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang
419f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    @Override
420f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public boolean dispatchTouchEvent(MotionEvent event) {
421bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang        if (!isEnabled()) return false;
422bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang
423f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        int action = event.getAction();
424f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        if (action == MotionEvent.ACTION_CANCEL
425f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                || action == MotionEvent.ACTION_UP) {
426f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            mInDownState = false;
427f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        } else if (!mInDownState && action != MotionEvent.ACTION_DOWN) {
428f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            return false;
429f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
430bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang
431bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang        if (mCompensation != 0) {
432bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang            event.transform(mCompensationMatrix);
433bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang        }
434bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang
435f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mRenderLock.lock();
436f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        try {
437f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            // If this has been detached from root, we don't need to handle event
438f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            boolean handled = mContentView != null
439f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                    && mContentView.dispatchTouchEvent(event);
440f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            if (action == MotionEvent.ACTION_DOWN && handled) {
441f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                mInDownState = true;
442f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
443f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            return handled;
444f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        } finally {
445f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            mRenderLock.unlock();
446f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
447f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
448f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
449f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private class IdleRunner implements Runnable {
450f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        // true if the idle runner is in the queue
451f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        private boolean mActive = false;
452f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
453f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        @Override
454f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        public void run() {
455f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            OnGLIdleListener listener;
456f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            synchronized (mIdleListeners) {
457f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                mActive = false;
458f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                if (mIdleListeners.isEmpty()) return;
459f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                listener = mIdleListeners.removeFirst();
460f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
461f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            mRenderLock.lock();
462f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            try {
463d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin                if (!listener.onGLIdle(mCanvas, mRenderRequested)) return;
464f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            } finally {
465f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                mRenderLock.unlock();
466f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
467f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            synchronized (mIdleListeners) {
468f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                mIdleListeners.addLast(listener);
469d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin                if (!mRenderRequested) enable();
470f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
471f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
472f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
473f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        public void enable() {
474f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            // Who gets the flag can add it to the queue
475f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            if (mActive) return;
476f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            mActive = true;
477f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            queueEvent(this);
478f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
479f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
480f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
481f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    @Override
482f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public void lockRenderThread() {
483f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mRenderLock.lock();
484f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
485f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
486f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    @Override
487f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public void unlockRenderThread() {
488f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mRenderLock.unlock();
489f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
4903d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang
4913d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang    @Override
4923d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang    public void onPause() {
49379cf902f4cc602774e90bc2040f0029978becb61Owen Lin        unfreeze();
4943d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        super.onPause();
4953d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        if (DEBUG_PROFILE) {
4963d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            Log.d(TAG, "Stop profiling");
4973d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            Profile.disableAll();
4983d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            Profile.dumpToFile("/sdcard/gallery.prof");
4993d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            Profile.reset();
5003d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        }
5013d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang    }
502bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang
503bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang    @Override
5042ef46ed28b28b355d7f3f1432c7b1196b832a859Chih-Chung Chang    public void setOrientationSource(OrientationSource source) {
5052ef46ed28b28b355d7f3f1432c7b1196b832a859Chih-Chung Chang        mOrientationSource = source;
5062ef46ed28b28b355d7f3f1432c7b1196b832a859Chih-Chung Chang    }
5072ef46ed28b28b355d7f3f1432c7b1196b832a859Chih-Chung Chang
5082ef46ed28b28b355d7f3f1432c7b1196b832a859Chih-Chung Chang    @Override
5092ef46ed28b28b355d7f3f1432c7b1196b832a859Chih-Chung Chang    public int getDisplayRotation() {
5102ef46ed28b28b355d7f3f1432c7b1196b832a859Chih-Chung Chang        return mDisplayRotation;
5112ef46ed28b28b355d7f3f1432c7b1196b832a859Chih-Chung Chang    }
5122ef46ed28b28b355d7f3f1432c7b1196b832a859Chih-Chung Chang
5132ef46ed28b28b355d7f3f1432c7b1196b832a859Chih-Chung Chang    @Override
5142ef46ed28b28b355d7f3f1432c7b1196b832a859Chih-Chung Chang    public int getCompensation() {
5152ef46ed28b28b355d7f3f1432c7b1196b832a859Chih-Chung Chang        return mCompensation;
5162ef46ed28b28b355d7f3f1432c7b1196b832a859Chih-Chung Chang    }
5172ef46ed28b28b355d7f3f1432c7b1196b832a859Chih-Chung Chang
5182ef46ed28b28b355d7f3f1432c7b1196b832a859Chih-Chung Chang    @Override
5192ef46ed28b28b355d7f3f1432c7b1196b832a859Chih-Chung Chang    public Matrix getCompensationMatrix() {
5202ef46ed28b28b355d7f3f1432c7b1196b832a859Chih-Chung Chang        return mCompensationMatrix;
521bd141b5a51c96f6fcaddfa547f0928ce69cf0755Chih-Chung Chang    }
5221ade1266d8e13830e3b07c1ebd8c95f4e859e129Chih-Chung Chang
5231ade1266d8e13830e3b07c1ebd8c95f4e859e129Chih-Chung Chang    @Override
5241ade1266d8e13830e3b07c1ebd8c95f4e859e129Chih-Chung Chang    public void freeze() {
5251ade1266d8e13830e3b07c1ebd8c95f4e859e129Chih-Chung Chang        mRenderLock.lock();
5261ade1266d8e13830e3b07c1ebd8c95f4e859e129Chih-Chung Chang        mFreeze = true;
5271ade1266d8e13830e3b07c1ebd8c95f4e859e129Chih-Chung Chang        mRenderLock.unlock();
5281ade1266d8e13830e3b07c1ebd8c95f4e859e129Chih-Chung Chang    }
5291ade1266d8e13830e3b07c1ebd8c95f4e859e129Chih-Chung Chang
5301ade1266d8e13830e3b07c1ebd8c95f4e859e129Chih-Chung Chang    @Override
5311ade1266d8e13830e3b07c1ebd8c95f4e859e129Chih-Chung Chang    public void unfreeze() {
5321ade1266d8e13830e3b07c1ebd8c95f4e859e129Chih-Chung Chang        mRenderLock.lock();
5331ade1266d8e13830e3b07c1ebd8c95f4e859e129Chih-Chung Chang        mFreeze = false;
5341ade1266d8e13830e3b07c1ebd8c95f4e859e129Chih-Chung Chang        mFreezeCondition.signalAll();
5351ade1266d8e13830e3b07c1ebd8c95f4e859e129Chih-Chung Chang        mRenderLock.unlock();
5361ade1266d8e13830e3b07c1ebd8c95f4e859e129Chih-Chung Chang    }
53779cf902f4cc602774e90bc2040f0029978becb61Owen Lin
5380b2486cff0c1b951c54325596256b986307f7f3aChih-Chung Chang    @Override
5390b2486cff0c1b951c54325596256b986307f7f3aChih-Chung Chang    public void setLightsOutMode(boolean enabled) {
540e919bcff63e898d53869725a979cdfd01ef92b08Chih-Chung Chang        int flags = enabled
541e919bcff63e898d53869725a979cdfd01ef92b08Chih-Chung Chang                ? SYSTEM_UI_FLAG_LOW_PROFILE
542e919bcff63e898d53869725a979cdfd01ef92b08Chih-Chung Chang                | SYSTEM_UI_FLAG_FULLSCREEN
543e919bcff63e898d53869725a979cdfd01ef92b08Chih-Chung Chang                | SYSTEM_UI_FLAG_LAYOUT_STABLE
544e919bcff63e898d53869725a979cdfd01ef92b08Chih-Chung Chang                : 0;
5450b2486cff0c1b951c54325596256b986307f7f3aChih-Chung Chang        setSystemUiVisibility(flags);
5460b2486cff0c1b951c54325596256b986307f7f3aChih-Chung Chang    }
5470b2486cff0c1b951c54325596256b986307f7f3aChih-Chung Chang
54879cf902f4cc602774e90bc2040f0029978becb61Owen Lin    // We need to unfreeze in the following methods and in onPause().
54979cf902f4cc602774e90bc2040f0029978becb61Owen Lin    // These methods will wait on GLThread. If we have freezed the GLRootView,
55079cf902f4cc602774e90bc2040f0029978becb61Owen Lin    // the GLThread will wait on main thread to call unfreeze and cause dead
55179cf902f4cc602774e90bc2040f0029978becb61Owen Lin    // lock.
55279cf902f4cc602774e90bc2040f0029978becb61Owen Lin    @Override
55379cf902f4cc602774e90bc2040f0029978becb61Owen Lin    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
55479cf902f4cc602774e90bc2040f0029978becb61Owen Lin        unfreeze();
55579cf902f4cc602774e90bc2040f0029978becb61Owen Lin        super.surfaceChanged(holder, format, w, h);
55679cf902f4cc602774e90bc2040f0029978becb61Owen Lin    }
55779cf902f4cc602774e90bc2040f0029978becb61Owen Lin
55879cf902f4cc602774e90bc2040f0029978becb61Owen Lin    @Override
55979cf902f4cc602774e90bc2040f0029978becb61Owen Lin    public void surfaceCreated(SurfaceHolder holder) {
56079cf902f4cc602774e90bc2040f0029978becb61Owen Lin        unfreeze();
56179cf902f4cc602774e90bc2040f0029978becb61Owen Lin        super.surfaceCreated(holder);
56279cf902f4cc602774e90bc2040f0029978becb61Owen Lin    }
56379cf902f4cc602774e90bc2040f0029978becb61Owen Lin
56479cf902f4cc602774e90bc2040f0029978becb61Owen Lin    @Override
56579cf902f4cc602774e90bc2040f0029978becb61Owen Lin    public void surfaceDestroyed(SurfaceHolder holder) {
56679cf902f4cc602774e90bc2040f0029978becb61Owen Lin        unfreeze();
56779cf902f4cc602774e90bc2040f0029978becb61Owen Lin        super.surfaceDestroyed(holder);
56879cf902f4cc602774e90bc2040f0029978becb61Owen Lin    }
56979cf902f4cc602774e90bc2040f0029978becb61Owen Lin
57079cf902f4cc602774e90bc2040f0029978becb61Owen Lin    @Override
57179cf902f4cc602774e90bc2040f0029978becb61Owen Lin    protected void onDetachedFromWindow() {
57279cf902f4cc602774e90bc2040f0029978becb61Owen Lin        unfreeze();
57379cf902f4cc602774e90bc2040f0029978becb61Owen Lin        super.onDetachedFromWindow();
57479cf902f4cc602774e90bc2040f0029978becb61Owen Lin    }
57579cf902f4cc602774e90bc2040f0029978becb61Owen Lin
57679cf902f4cc602774e90bc2040f0029978becb61Owen Lin    @Override
57779cf902f4cc602774e90bc2040f0029978becb61Owen Lin    protected void finalize() throws Throwable {
57879cf902f4cc602774e90bc2040f0029978becb61Owen Lin        try {
57979cf902f4cc602774e90bc2040f0029978becb61Owen Lin            unfreeze();
58079cf902f4cc602774e90bc2040f0029978becb61Owen Lin        } finally {
58179cf902f4cc602774e90bc2040f0029978becb61Owen Lin            super.finalize();
58279cf902f4cc602774e90bc2040f0029978becb61Owen Lin        }
58379cf902f4cc602774e90bc2040f0029978becb61Owen Lin    }
584f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin}
585