diff options
-rw-r--r-- | api/current.txt | 3 | ||||
-rw-r--r-- | api/system-current.txt | 3 | ||||
-rw-r--r-- | api/test-current.txt | 3 | ||||
-rw-r--r-- | core/java/android/view/SurfaceHolder.java | 27 | ||||
-rw-r--r-- | core/java/android/view/SurfaceView.java | 16 | ||||
-rw-r--r-- | core/java/android/view/ViewRootImpl.java | 31 | ||||
-rw-r--r-- | core/java/com/android/internal/view/BaseSurfaceHolder.java | 2 | ||||
-rw-r--r-- | core/java/com/android/internal/view/SurfaceCallbackHelper.java | 77 | ||||
-rw-r--r-- | opengl/java/android/opengl/GLSurfaceView.java | 41 |
9 files changed, 157 insertions, 46 deletions
diff --git a/api/current.txt b/api/current.txt index ec16f5a5f56b..196b5f2483fb 100644 --- a/api/current.txt +++ b/api/current.txt @@ -28553,7 +28553,7 @@ package android.opengl { method public void surfaceChanged(android.view.SurfaceHolder, int, int, int); method public void surfaceCreated(android.view.SurfaceHolder); method public void surfaceDestroyed(android.view.SurfaceHolder); - method public void surfaceRedrawNeeded(android.view.SurfaceHolder); + method public deprecated void surfaceRedrawNeeded(android.view.SurfaceHolder); field public static final int DEBUG_CHECK_GL_ERROR = 1; // 0x1 field public static final int DEBUG_LOG_GL_CALLS = 2; // 0x2 field public static final int RENDERMODE_CONTINUOUSLY = 1; // 0x1 @@ -43035,6 +43035,7 @@ package android.view { public static abstract interface SurfaceHolder.Callback2 implements android.view.SurfaceHolder.Callback { method public abstract void surfaceRedrawNeeded(android.view.SurfaceHolder); + method public default void surfaceRedrawNeededAsync(android.view.SurfaceHolder, java.lang.Runnable); } public class SurfaceView extends android.view.View { diff --git a/api/system-current.txt b/api/system-current.txt index 4bba111f9392..5a1f88019ad4 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -31091,7 +31091,7 @@ package android.opengl { method public void surfaceChanged(android.view.SurfaceHolder, int, int, int); method public void surfaceCreated(android.view.SurfaceHolder); method public void surfaceDestroyed(android.view.SurfaceHolder); - method public void surfaceRedrawNeeded(android.view.SurfaceHolder); + method public deprecated void surfaceRedrawNeeded(android.view.SurfaceHolder); field public static final int DEBUG_CHECK_GL_ERROR = 1; // 0x1 field public static final int DEBUG_LOG_GL_CALLS = 2; // 0x2 field public static final int RENDERMODE_CONTINUOUSLY = 1; // 0x1 @@ -46227,6 +46227,7 @@ package android.view { public static abstract interface SurfaceHolder.Callback2 implements android.view.SurfaceHolder.Callback { method public abstract void surfaceRedrawNeeded(android.view.SurfaceHolder); + method public default void surfaceRedrawNeededAsync(android.view.SurfaceHolder, java.lang.Runnable); } public class SurfaceView extends android.view.View { diff --git a/api/test-current.txt b/api/test-current.txt index d4fb027bcb4d..e67f2ced13b1 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -28640,7 +28640,7 @@ package android.opengl { method public void surfaceChanged(android.view.SurfaceHolder, int, int, int); method public void surfaceCreated(android.view.SurfaceHolder); method public void surfaceDestroyed(android.view.SurfaceHolder); - method public void surfaceRedrawNeeded(android.view.SurfaceHolder); + method public deprecated void surfaceRedrawNeeded(android.view.SurfaceHolder); field public static final int DEBUG_CHECK_GL_ERROR = 1; // 0x1 field public static final int DEBUG_LOG_GL_CALLS = 2; // 0x2 field public static final int RENDERMODE_CONTINUOUSLY = 1; // 0x1 @@ -43324,6 +43324,7 @@ package android.view { public static abstract interface SurfaceHolder.Callback2 implements android.view.SurfaceHolder.Callback { method public abstract void surfaceRedrawNeeded(android.view.SurfaceHolder); + method public default void surfaceRedrawNeededAsync(android.view.SurfaceHolder, java.lang.Runnable); } public class SurfaceView extends android.view.View { diff --git a/core/java/android/view/SurfaceHolder.java b/core/java/android/view/SurfaceHolder.java index a3e8312c0a64..2fd2e966dc38 100644 --- a/core/java/android/view/SurfaceHolder.java +++ b/core/java/android/view/SurfaceHolder.java @@ -116,9 +116,34 @@ public interface SurfaceHolder { * size before it has been correctly drawn that way). This will * typically be preceeded by a call to {@link #surfaceChanged}. * + * As of O, {@link #surfaceRedrawNeededAsync} may be implemented + * to provide a non-blocking implementation. If {@link #surfaceRedrawNeededAsync} + * is not implemented, then this will be called instead. + * * @param holder The SurfaceHolder whose surface has changed. */ - public void surfaceRedrawNeeded(SurfaceHolder holder); + void surfaceRedrawNeeded(SurfaceHolder holder); + + /** + * An alternative to surfaceRedrawNeeded where it is not required to block + * until the redraw is complete. You should initiate the redraw, and return, + * later invoking drawingFinished when your redraw is complete. + * + * This can be useful to avoid blocking your main application thread on rendering. + * + * As of O, if this is implemented {@link #surfaceRedrawNeeded} will not be called. + * However it is still recommended to implement {@link #surfaceRedrawNeeded} for + * compatibility with older versions of the platform. + * + * @param holder The SurfaceHolder which needs redrawing. + * @param drawingFinished A runnable to signal completion. This may be invoked + * from any thread. + * + */ + default void surfaceRedrawNeededAsync(SurfaceHolder holder, Runnable drawingFinished) { + surfaceRedrawNeeded(holder); + drawingFinished.run(); + } } /** diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java index d46910c2139c..018be866cd8b 100644 --- a/core/java/android/view/SurfaceView.java +++ b/core/java/android/view/SurfaceView.java @@ -33,6 +33,7 @@ import android.util.AttributeSet; import android.util.Log; import com.android.internal.view.BaseIWindow; +import com.android.internal.view.SurfaceCallbackHelper; import java.lang.ref.WeakReference; import java.util.ArrayList; @@ -639,21 +640,13 @@ public class SurfaceView extends View { if (callbacks == null) { callbacks = getSurfaceCallbacks(); } - for (SurfaceHolder.Callback c : callbacks) { - if (c instanceof SurfaceHolder.Callback2) { - ((SurfaceHolder.Callback2)c).surfaceRedrawNeeded( - mSurfaceHolder); - } - } + SurfaceCallbackHelper sch = + new SurfaceCallbackHelper(mSession, mWindow); + sch.dispatchSurfaceRedrawNeededAsync(mSurfaceHolder, callbacks); } } } finally { mIsCreating = false; - if (redrawNeeded) { - if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " " - + "finishedDrawing"); - mSession.finishDrawing(mWindow); - } mSession.performDeferredDestroy(mWindow); } } catch (RemoteException ex) { @@ -876,7 +869,6 @@ public class SurfaceView extends View { } private final SurfaceHolder mSurfaceHolder = new SurfaceHolder() { - private static final String LOG_TAG = "SurfaceHolder"; @Override diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 4f2020311ff4..69464fc06e8f 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -93,6 +93,7 @@ import com.android.internal.os.SomeArgs; import com.android.internal.policy.PhoneFallbackEventHandler; import com.android.internal.view.BaseSurfaceHolder; import com.android.internal.view.RootViewSurfaceTaker; +import com.android.internal.view.SurfaceCallbackHelper; import java.io.FileDescriptor; import java.io.IOException; @@ -525,11 +526,17 @@ public final class ViewRootImpl implements ViewParent, */ public void notifyChildRebuilt() { if (mView instanceof RootViewSurfaceTaker) { + if (mSurfaceHolderCallback != null) { + mSurfaceHolder.removeCallback(mSurfaceHolderCallback); + } + mSurfaceHolderCallback = ((RootViewSurfaceTaker)mView).willYouTakeTheSurface(); + if (mSurfaceHolderCallback != null) { mSurfaceHolder = new TakenSurfaceHolder(); mSurfaceHolder.setFormat(PixelFormat.UNKNOWN); + mSurfaceHolder.addCallback(mSurfaceHolderCallback); } else { mSurfaceHolder = null; } @@ -578,6 +585,7 @@ public final class ViewRootImpl implements ViewParent, if (mSurfaceHolderCallback != null) { mSurfaceHolder = new TakenSurfaceHolder(); mSurfaceHolder.setFormat(PixelFormat.UNKNOWN); + mSurfaceHolder.addCallback(mSurfaceHolderCallback); } } @@ -1954,7 +1962,6 @@ public final class ViewRootImpl implements ViewParent, mSurfaceHolder.ungetCallbacks(); mIsCreating = true; - mSurfaceHolderCallback.surfaceCreated(mSurfaceHolder); SurfaceHolder.Callback callbacks[] = mSurfaceHolder.getCallbacks(); if (callbacks != null) { for (SurfaceHolder.Callback c : callbacks) { @@ -1964,8 +1971,6 @@ public final class ViewRootImpl implements ViewParent, surfaceChanged = true; } if (surfaceChanged || surfaceGenerationId != mSurface.getGenerationId()) { - mSurfaceHolderCallback.surfaceChanged(mSurfaceHolder, - lp.format, mWidth, mHeight); SurfaceHolder.Callback callbacks[] = mSurfaceHolder.getCallbacks(); if (callbacks != null) { for (SurfaceHolder.Callback c : callbacks) { @@ -1978,7 +1983,6 @@ public final class ViewRootImpl implements ViewParent, } else if (hadSurface) { mSurfaceHolder.ungetCallbacks(); SurfaceHolder.Callback callbacks[] = mSurfaceHolder.getCallbacks(); - mSurfaceHolderCallback.surfaceDestroyed(mSurfaceHolder); if (callbacks != null) { for (SurfaceHolder.Callback c : callbacks) { c.surfaceDestroyed(mSurfaceHolder); @@ -2643,21 +2647,18 @@ public final class ViewRootImpl implements ViewParent, if (LOCAL_LOGV) { Log.v(mTag, "FINISHED DRAWING: " + mWindowAttributes.getTitle()); } + if (mSurfaceHolder != null && mSurface.isValid()) { - mSurfaceHolderCallback.surfaceRedrawNeeded(mSurfaceHolder); + SurfaceCallbackHelper sch = new SurfaceCallbackHelper(mWindowSession, mWindow); SurfaceHolder.Callback callbacks[] = mSurfaceHolder.getCallbacks(); - if (callbacks != null) { - for (SurfaceHolder.Callback c : callbacks) { - if (c instanceof SurfaceHolder.Callback2) { - ((SurfaceHolder.Callback2)c).surfaceRedrawNeeded(mSurfaceHolder); - } - } + + sch.dispatchSurfaceRedrawNeededAsync(mSurfaceHolder, callbacks); + } else { + try { + mWindowSession.finishDrawing(mWindow); + } catch (RemoteException e) { } } - try { - mWindowSession.finishDrawing(mWindow); - } catch (RemoteException e) { - } } } diff --git a/core/java/com/android/internal/view/BaseSurfaceHolder.java b/core/java/com/android/internal/view/BaseSurfaceHolder.java index b41ef297a5be..32ce0fe1282b 100644 --- a/core/java/com/android/internal/view/BaseSurfaceHolder.java +++ b/core/java/com/android/internal/view/BaseSurfaceHolder.java @@ -86,7 +86,7 @@ public abstract class BaseSurfaceHolder implements SurfaceHolder { mCallbacks.remove(callback); } } - + public SurfaceHolder.Callback[] getCallbacks() { if (mHaveGottenCallbacks) { return mGottenCallbacks; diff --git a/core/java/com/android/internal/view/SurfaceCallbackHelper.java b/core/java/com/android/internal/view/SurfaceCallbackHelper.java new file mode 100644 index 000000000000..5b6a82cf1c43 --- /dev/null +++ b/core/java/com/android/internal/view/SurfaceCallbackHelper.java @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2016 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.internal.view; + +import android.os.RemoteException; +import android.view.IWindow; +import android.view.IWindowSession; +import android.view.Surface; +import android.view.SurfaceHolder; + +public class SurfaceCallbackHelper { + IWindowSession mSession; + IWindow.Stub mWindow; + + int mFinishDrawingCollected = 0; + int mFinishDrawingExpected = 0; + + private Runnable mFinishDrawingRunnable = new Runnable() { + @Override + public void run() { + synchronized (SurfaceCallbackHelper.this) { + mFinishDrawingCollected++; + if (mFinishDrawingCollected < mFinishDrawingExpected) { + return; + } + try { + mSession.finishDrawing(mWindow); + } catch (RemoteException e) { + } + } + } + }; + + public SurfaceCallbackHelper(IWindowSession session, + IWindow.Stub window) { + mSession = session; + mWindow = window; + } + + public void dispatchSurfaceRedrawNeededAsync(SurfaceHolder holder, SurfaceHolder.Callback callbacks[]) { + if (callbacks == null || callbacks.length == 0) { + try { + mSession.finishDrawing(mWindow); + } catch (RemoteException e) { + } + return; + } + + synchronized (this) { + mFinishDrawingExpected = callbacks.length; + mFinishDrawingCollected = 0; + } + + for (SurfaceHolder.Callback c : callbacks) { + if (c instanceof SurfaceHolder.Callback2) { + ((SurfaceHolder.Callback2) c).surfaceRedrawNeededAsync( + holder, mFinishDrawingRunnable); + } else { + mFinishDrawingRunnable.run(); + } + } + } +}
\ No newline at end of file diff --git a/opengl/java/android/opengl/GLSurfaceView.java b/opengl/java/android/opengl/GLSurfaceView.java index 4154ef02772b..329514c0b7fc 100644 --- a/opengl/java/android/opengl/GLSurfaceView.java +++ b/opengl/java/android/opengl/GLSurfaceView.java @@ -542,16 +542,27 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback } /** - * This method is part of the SurfaceHolder.Callback interface, and is + * This method is part of the SurfaceHolder.Callback2 interface, and is * not normally called or subclassed by clients of GLSurfaceView. */ @Override - public void surfaceRedrawNeeded(SurfaceHolder holder) { + public void surfaceRedrawNeededAsync(SurfaceHolder holder, Runnable finishDrawing) { if (mGLThread != null) { - mGLThread.requestRenderAndWait(); + mGLThread.requestRenderAndNotify(finishDrawing); } } + /** + * This method is part of the SurfaceHolder.Callback2 interface, and is + * not normally called or subclassed by clients of GLSurfaceView. + */ + @Deprecated + @Override + public void surfaceRedrawNeeded(SurfaceHolder holder) { + // Since we are part of the framework we know only surfaceRedrawNeededAsync + // will be called. + } + /** * Pause the rendering thread, optionally tearing down the EGL context @@ -1305,6 +1316,7 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback int w = 0; int h = 0; Runnable event = null; + Runnable finishDrawingRunnable = null; while (true) { synchronized (sGLThreadManager) { @@ -1400,6 +1412,11 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback sGLThreadManager.notifyAll(); } + if (mFinishDrawingRunnable != null) { + finishDrawingRunnable = mFinishDrawingRunnable; + mFinishDrawingRunnable = null; + } + // Ready to draw? if (readyToDraw()) { @@ -1453,7 +1470,6 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback break; } } - // By design, this is the only place in a GLThread thread where we wait(). if (LOG_THREADS) { Log.i("GLThread", "waiting tid=" + getId() @@ -1546,6 +1562,10 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback try { Trace.traceBegin(Trace.TRACE_TAG_VIEW, "onDrawFrame"); view.mRenderer.onDrawFrame(gl); + if (finishDrawingRunnable != null) { + finishDrawingRunnable.run(); + finishDrawingRunnable = null; + } } finally { Trace.traceEnd(Trace.TRACE_TAG_VIEW); } @@ -1625,7 +1645,7 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback } } - public void requestRenderAndWait() { + public void requestRenderAndNotify(Runnable finishDrawing) { synchronized(sGLThreadManager) { // If we are already on the GL thread, this means a client callback // has caused reentrancy, for example via updating the SurfaceView parameters. @@ -1638,17 +1658,9 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback mWantRenderNotification = true; mRequestRender = true; mRenderComplete = false; + mFinishDrawingRunnable = finishDrawing; sGLThreadManager.notifyAll(); - - while (!mExited && !mPaused && !mRenderComplete && ableToDraw()) { - try { - sGLThreadManager.wait(); - } catch (InterruptedException ex) { - Thread.currentThread().interrupt(); - } - } - } } @@ -1821,6 +1833,7 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback private boolean mRenderComplete; private ArrayList<Runnable> mEventQueue = new ArrayList<Runnable>(); private boolean mSizeChanged = true; + private Runnable mFinishDrawingRunnable = null; // End of member variables protected by the sGLThreadManager monitor. |