diff options
Diffstat (limited to 'src/com/android/gallery3d/ui/GLRootView.java')
-rw-r--r-- | src/com/android/gallery3d/ui/GLRootView.java | 630 |
1 files changed, 0 insertions, 630 deletions
diff --git a/src/com/android/gallery3d/ui/GLRootView.java b/src/com/android/gallery3d/ui/GLRootView.java deleted file mode 100644 index dc898d83d..000000000 --- a/src/com/android/gallery3d/ui/GLRootView.java +++ /dev/null @@ -1,630 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.ui; - -import android.annotation.TargetApi; -import android.content.Context; -import android.graphics.Matrix; -import android.graphics.PixelFormat; -import android.opengl.GLSurfaceView; -import android.os.Build; -import android.os.Process; -import android.os.SystemClock; -import android.util.AttributeSet; -import android.view.MotionEvent; -import android.view.SurfaceHolder; -import android.view.View; - -import com.android.gallery3d.R; -import com.android.gallery3d.anim.CanvasAnimation; -import com.android.gallery3d.common.ApiHelper; -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.glrenderer.BasicTexture; -import com.android.gallery3d.glrenderer.GLCanvas; -import com.android.gallery3d.glrenderer.GLES11Canvas; -import com.android.gallery3d.glrenderer.GLES20Canvas; -import com.android.gallery3d.glrenderer.UploadedTexture; -import com.android.gallery3d.util.GalleryUtils; -import com.android.gallery3d.util.MotionEventHelper; -import com.android.gallery3d.util.Profile; - -import java.util.ArrayDeque; -import java.util.ArrayList; -import java.util.concurrent.locks.Condition; -import java.util.concurrent.locks.ReentrantLock; - -import javax.microedition.khronos.egl.EGLConfig; -import javax.microedition.khronos.opengles.GL10; -import javax.microedition.khronos.opengles.GL11; - -// The root component of all <code>GLView</code>s. The rendering is done in GL -// thread while the event handling is done in the main thread. To synchronize -// the two threads, the entry points of this package need to synchronize on the -// <code>GLRootView</code> instance unless it can be proved that the rendering -// thread won't access the same thing as the method. The entry points include: -// (1) The public methods of HeadUpDisplay -// (2) The public methods of CameraHeadUpDisplay -// (3) The overridden methods in GLRootView. -public class GLRootView extends GLSurfaceView - implements GLSurfaceView.Renderer, GLRoot { - private static final String TAG = "GLRootView"; - - private static final boolean DEBUG_FPS = false; - private int mFrameCount = 0; - private long mFrameCountingStart = 0; - - private static final boolean DEBUG_INVALIDATE = false; - private int mInvalidateColor = 0; - - private static final boolean DEBUG_DRAWING_STAT = false; - - private static final boolean DEBUG_PROFILE = false; - private static final boolean DEBUG_PROFILE_SLOW_ONLY = false; - - private static final int FLAG_INITIALIZED = 1; - private static final int FLAG_NEED_LAYOUT = 2; - - private GL11 mGL; - private GLCanvas mCanvas; - private GLView mContentView; - - private OrientationSource mOrientationSource; - // mCompensation is the difference between the UI orientation on GLCanvas - // and the framework orientation. See OrientationManager for details. - private int mCompensation; - // mCompensationMatrix maps the coordinates of touch events. It is kept sync - // with mCompensation. - private Matrix mCompensationMatrix = new Matrix(); - private int mDisplayRotation; - - private int mFlags = FLAG_NEED_LAYOUT; - private volatile boolean mRenderRequested = false; - - private final ArrayList<CanvasAnimation> mAnimations = - new ArrayList<CanvasAnimation>(); - - private final ArrayDeque<OnGLIdleListener> mIdleListeners = - new ArrayDeque<OnGLIdleListener>(); - - private final IdleRunner mIdleRunner = new IdleRunner(); - - private final ReentrantLock mRenderLock = new ReentrantLock(); - private final Condition mFreezeCondition = - mRenderLock.newCondition(); - private boolean mFreeze; - - private long mLastDrawFinishTime; - private boolean mInDownState = false; - private boolean mFirstDraw = true; - - public GLRootView(Context context) { - this(context, null); - } - - public GLRootView(Context context, AttributeSet attrs) { - super(context, attrs); - mFlags |= FLAG_INITIALIZED; - setBackgroundDrawable(null); - setEGLContextClientVersion(ApiHelper.HAS_GLES20_REQUIRED ? 2 : 1); - if (ApiHelper.USE_888_PIXEL_FORMAT) { - setEGLConfigChooser(8, 8, 8, 0, 0, 0); - } else { - setEGLConfigChooser(5, 6, 5, 0, 0, 0); - } - setRenderer(this); - if (ApiHelper.USE_888_PIXEL_FORMAT) { - getHolder().setFormat(PixelFormat.RGB_888); - } else { - getHolder().setFormat(PixelFormat.RGB_565); - } - - // Uncomment this to enable gl error check. - // setDebugFlags(DEBUG_CHECK_GL_ERROR); - } - - @Override - public void registerLaunchedAnimation(CanvasAnimation animation) { - // Register the newly launched animation so that we can set the start - // time more precisely. (Usually, it takes much longer for first - // rendering, so we set the animation start time as the time we - // complete rendering) - mAnimations.add(animation); - } - - @Override - public void addOnGLIdleListener(OnGLIdleListener listener) { - synchronized (mIdleListeners) { - mIdleListeners.addLast(listener); - mIdleRunner.enable(); - } - } - - @Override - public void setContentPane(GLView content) { - if (mContentView == content) return; - if (mContentView != null) { - if (mInDownState) { - long now = SystemClock.uptimeMillis(); - MotionEvent cancelEvent = MotionEvent.obtain( - now, now, MotionEvent.ACTION_CANCEL, 0, 0, 0); - mContentView.dispatchTouchEvent(cancelEvent); - cancelEvent.recycle(); - mInDownState = false; - } - mContentView.detachFromRoot(); - BasicTexture.yieldAllTextures(); - } - mContentView = content; - if (content != null) { - content.attachToRoot(this); - requestLayoutContentPane(); - } - } - - @Override - public void requestRenderForced() { - superRequestRender(); - } - - @Override - public void requestRender() { - if (DEBUG_INVALIDATE) { - StackTraceElement e = Thread.currentThread().getStackTrace()[4]; - String caller = e.getFileName() + ":" + e.getLineNumber() + " "; - Log.d(TAG, "invalidate: " + caller); - } - if (mRenderRequested) return; - mRenderRequested = true; - if (ApiHelper.HAS_POST_ON_ANIMATION) { - postOnAnimation(mRequestRenderOnAnimationFrame); - } else { - super.requestRender(); - } - } - - private Runnable mRequestRenderOnAnimationFrame = new Runnable() { - @Override - public void run() { - superRequestRender(); - } - }; - - private void superRequestRender() { - super.requestRender(); - } - - @Override - public void requestLayoutContentPane() { - mRenderLock.lock(); - try { - if (mContentView == null || (mFlags & FLAG_NEED_LAYOUT) != 0) return; - - // "View" system will invoke onLayout() for initialization(bug ?), we - // have to ignore it since the GLThread is not ready yet. - if ((mFlags & FLAG_INITIALIZED) == 0) return; - - mFlags |= FLAG_NEED_LAYOUT; - requestRender(); - } finally { - mRenderLock.unlock(); - } - } - - private void layoutContentPane() { - mFlags &= ~FLAG_NEED_LAYOUT; - - int w = getWidth(); - int h = getHeight(); - int displayRotation = 0; - int compensation = 0; - - // Get the new orientation values - if (mOrientationSource != null) { - displayRotation = mOrientationSource.getDisplayRotation(); - compensation = mOrientationSource.getCompensation(); - } else { - displayRotation = 0; - compensation = 0; - } - - if (mCompensation != compensation) { - mCompensation = compensation; - if (mCompensation % 180 != 0) { - mCompensationMatrix.setRotate(mCompensation); - // move center to origin before rotation - mCompensationMatrix.preTranslate(-w / 2, -h / 2); - // align with the new origin after rotation - mCompensationMatrix.postTranslate(h / 2, w / 2); - } else { - mCompensationMatrix.setRotate(mCompensation, w / 2, h / 2); - } - } - mDisplayRotation = displayRotation; - - // Do the actual layout. - if (mCompensation % 180 != 0) { - int tmp = w; - w = h; - h = tmp; - } - Log.i(TAG, "layout content pane " + w + "x" + h - + " (compensation " + mCompensation + ")"); - if (mContentView != null && w != 0 && h != 0) { - mContentView.layout(0, 0, w, h); - } - // Uncomment this to dump the view hierarchy. - //mContentView.dumpTree(""); - } - - @Override - protected void onLayout( - boolean changed, int left, int top, int right, int bottom) { - if (changed) requestLayoutContentPane(); - } - - /** - * Called when the context is created, possibly after automatic destruction. - */ - // This is a GLSurfaceView.Renderer callback - @Override - public void onSurfaceCreated(GL10 gl1, EGLConfig config) { - GL11 gl = (GL11) gl1; - if (mGL != null) { - // The GL Object has changed - Log.i(TAG, "GLObject has changed from " + mGL + " to " + gl); - } - mRenderLock.lock(); - try { - mGL = gl; - mCanvas = ApiHelper.HAS_GLES20_REQUIRED ? new GLES20Canvas() : new GLES11Canvas(gl); - BasicTexture.invalidateAllTextures(); - } finally { - mRenderLock.unlock(); - } - - if (DEBUG_FPS || DEBUG_PROFILE) { - setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY); - } else { - setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY); - } - } - - /** - * Called when the OpenGL surface is recreated without destroying the - * context. - */ - // This is a GLSurfaceView.Renderer callback - @Override - public void onSurfaceChanged(GL10 gl1, int width, int height) { - Log.i(TAG, "onSurfaceChanged: " + width + "x" + height - + ", gl10: " + gl1.toString()); - Process.setThreadPriority(Process.THREAD_PRIORITY_DISPLAY); - GalleryUtils.setRenderThread(); - if (DEBUG_PROFILE) { - Log.d(TAG, "Start profiling"); - Profile.enable(20); // take a sample every 20ms - } - GL11 gl = (GL11) gl1; - Utils.assertTrue(mGL == gl); - - mCanvas.setSize(width, height); - } - - private void outputFps() { - long now = System.nanoTime(); - if (mFrameCountingStart == 0) { - mFrameCountingStart = now; - } else if ((now - mFrameCountingStart) > 1000000000) { - Log.d(TAG, "fps: " + (double) mFrameCount - * 1000000000 / (now - mFrameCountingStart)); - mFrameCountingStart = now; - mFrameCount = 0; - } - ++mFrameCount; - } - - @Override - public void onDrawFrame(GL10 gl) { - AnimationTime.update(); - long t0; - if (DEBUG_PROFILE_SLOW_ONLY) { - Profile.hold(); - t0 = System.nanoTime(); - } - mRenderLock.lock(); - - while (mFreeze) { - mFreezeCondition.awaitUninterruptibly(); - } - - try { - onDrawFrameLocked(gl); - } finally { - mRenderLock.unlock(); - } - - // We put a black cover View in front of the SurfaceView and hide it - // after the first draw. This prevents the SurfaceView being transparent - // before the first draw. - if (mFirstDraw) { - mFirstDraw = false; - post(new Runnable() { - @Override - public void run() { - View root = getRootView(); - View cover = root.findViewById(R.id.gl_root_cover); - cover.setVisibility(GONE); - } - }); - } - - if (DEBUG_PROFILE_SLOW_ONLY) { - long t = System.nanoTime(); - long durationInMs = (t - mLastDrawFinishTime) / 1000000; - long durationDrawInMs = (t - t0) / 1000000; - mLastDrawFinishTime = t; - - if (durationInMs > 34) { // 34ms -> we skipped at least 2 frames - Log.v(TAG, "----- SLOW (" + durationDrawInMs + "/" + - durationInMs + ") -----"); - Profile.commit(); - } else { - Profile.drop(); - } - } - } - - private void onDrawFrameLocked(GL10 gl) { - if (DEBUG_FPS) outputFps(); - - // release the unbound textures and deleted buffers. - mCanvas.deleteRecycledResources(); - - // reset texture upload limit - UploadedTexture.resetUploadLimit(); - - mRenderRequested = false; - - if ((mOrientationSource != null - && mDisplayRotation != mOrientationSource.getDisplayRotation()) - || (mFlags & FLAG_NEED_LAYOUT) != 0) { - layoutContentPane(); - } - - mCanvas.save(GLCanvas.SAVE_FLAG_ALL); - rotateCanvas(-mCompensation); - if (mContentView != null) { - mContentView.render(mCanvas); - } else { - // Make sure we always draw something to prevent displaying garbage - mCanvas.clearBuffer(); - } - mCanvas.restore(); - - if (!mAnimations.isEmpty()) { - long now = AnimationTime.get(); - for (int i = 0, n = mAnimations.size(); i < n; i++) { - mAnimations.get(i).setStartTime(now); - } - mAnimations.clear(); - } - - if (UploadedTexture.uploadLimitReached()) { - requestRender(); - } - - synchronized (mIdleListeners) { - if (!mIdleListeners.isEmpty()) mIdleRunner.enable(); - } - - if (DEBUG_INVALIDATE) { - mCanvas.fillRect(10, 10, 5, 5, mInvalidateColor); - mInvalidateColor = ~mInvalidateColor; - } - - if (DEBUG_DRAWING_STAT) { - mCanvas.dumpStatisticsAndClear(); - } - } - - private void rotateCanvas(int degrees) { - if (degrees == 0) return; - int w = getWidth(); - int h = getHeight(); - int cx = w / 2; - int cy = h / 2; - mCanvas.translate(cx, cy); - mCanvas.rotate(degrees, 0, 0, 1); - if (degrees % 180 != 0) { - mCanvas.translate(-cy, -cx); - } else { - mCanvas.translate(-cx, -cy); - } - } - - @Override - public boolean dispatchTouchEvent(MotionEvent event) { - if (!isEnabled()) return false; - - int action = event.getAction(); - if (action == MotionEvent.ACTION_CANCEL - || action == MotionEvent.ACTION_UP) { - mInDownState = false; - } else if (!mInDownState && action != MotionEvent.ACTION_DOWN) { - return false; - } - - if (mCompensation != 0) { - event = MotionEventHelper.transformEvent(event, mCompensationMatrix); - } - - mRenderLock.lock(); - try { - // If this has been detached from root, we don't need to handle event - boolean handled = mContentView != null - && mContentView.dispatchTouchEvent(event); - if (action == MotionEvent.ACTION_DOWN && handled) { - mInDownState = true; - } - return handled; - } finally { - mRenderLock.unlock(); - } - } - - private class IdleRunner implements Runnable { - // true if the idle runner is in the queue - private boolean mActive = false; - - @Override - public void run() { - OnGLIdleListener listener; - synchronized (mIdleListeners) { - mActive = false; - if (mIdleListeners.isEmpty()) return; - listener = mIdleListeners.removeFirst(); - } - mRenderLock.lock(); - boolean keepInQueue; - try { - keepInQueue = listener.onGLIdle(mCanvas, mRenderRequested); - } finally { - mRenderLock.unlock(); - } - synchronized (mIdleListeners) { - if (keepInQueue) mIdleListeners.addLast(listener); - if (!mRenderRequested && !mIdleListeners.isEmpty()) enable(); - } - } - - public void enable() { - // Who gets the flag can add it to the queue - if (mActive) return; - mActive = true; - queueEvent(this); - } - } - - @Override - public void lockRenderThread() { - mRenderLock.lock(); - } - - @Override - public void unlockRenderThread() { - mRenderLock.unlock(); - } - - @Override - public void onPause() { - unfreeze(); - super.onPause(); - if (DEBUG_PROFILE) { - Log.d(TAG, "Stop profiling"); - Profile.disableAll(); - Profile.dumpToFile("/sdcard/gallery.prof"); - Profile.reset(); - } - } - - @Override - public void setOrientationSource(OrientationSource source) { - mOrientationSource = source; - } - - @Override - public int getDisplayRotation() { - return mDisplayRotation; - } - - @Override - public int getCompensation() { - return mCompensation; - } - - @Override - public Matrix getCompensationMatrix() { - return mCompensationMatrix; - } - - @Override - public void freeze() { - mRenderLock.lock(); - mFreeze = true; - mRenderLock.unlock(); - } - - @Override - public void unfreeze() { - mRenderLock.lock(); - mFreeze = false; - mFreezeCondition.signalAll(); - mRenderLock.unlock(); - } - - @Override - @TargetApi(Build.VERSION_CODES.JELLY_BEAN) - public void setLightsOutMode(boolean enabled) { - if (!ApiHelper.HAS_SET_SYSTEM_UI_VISIBILITY) return; - - int flags = 0; - if (enabled) { - flags = STATUS_BAR_HIDDEN; - if (ApiHelper.HAS_VIEW_SYSTEM_UI_FLAG_LAYOUT_STABLE) { - flags |= (SYSTEM_UI_FLAG_FULLSCREEN | SYSTEM_UI_FLAG_LAYOUT_STABLE); - } - } - setSystemUiVisibility(flags); - } - - // We need to unfreeze in the following methods and in onPause(). - // These methods will wait on GLThread. If we have freezed the GLRootView, - // the GLThread will wait on main thread to call unfreeze and cause dead - // lock. - @Override - public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { - unfreeze(); - super.surfaceChanged(holder, format, w, h); - } - - @Override - public void surfaceCreated(SurfaceHolder holder) { - unfreeze(); - super.surfaceCreated(holder); - } - - @Override - public void surfaceDestroyed(SurfaceHolder holder) { - unfreeze(); - super.surfaceDestroyed(holder); - } - - @Override - protected void onDetachedFromWindow() { - unfreeze(); - super.onDetachedFromWindow(); - } - - @Override - protected void finalize() throws Throwable { - try { - unfreeze(); - } finally { - super.finalize(); - } - } -} |