diff options
| -rw-r--r-- | core/java/android/view/SurfaceControl.java | 23 | ||||
| -rw-r--r-- | core/java/android/view/ViewRootImpl.java | 54 | ||||
| -rw-r--r-- | core/java/android/view/WindowManager.java | 7 | ||||
| -rw-r--r-- | core/jni/Android.bp | 1 | ||||
| -rw-r--r-- | core/jni/AndroidRuntime.cpp | 4 | ||||
| -rw-r--r-- | core/jni/android_graphics_BLASTBufferQueue.cpp | 82 | ||||
| -rw-r--r-- | graphics/java/android/graphics/BLASTBufferQueue.java | 67 | ||||
| -rw-r--r-- | services/core/java/com/android/server/wm/WindowSurfaceController.java | 8 |
8 files changed, 238 insertions, 8 deletions
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java index 6637c5b06a1b..8dd475e0c306 100644 --- a/core/java/android/view/SurfaceControl.java +++ b/core/java/android/view/SurfaceControl.java @@ -199,7 +199,10 @@ public final class SurfaceControl implements Parcelable { private final CloseGuard mCloseGuard = CloseGuard.get(); private String mName; - long mNativeObject; // package visibility only for Surface.java access + /** + * @hide + */ + public long mNativeObject; // TODO: Move this to native. private final Object mSizeLock = new Object(); @@ -318,6 +321,11 @@ public final class SurfaceControl implements Parcelable { public static final int FX_SURFACE_CONTAINER = 0x00080000; /** + * @hide + */ + public static final int FX_SURFACE_BLAST = 0x00040000; + + /** * Mask used for FX values above. * * @hide @@ -693,6 +701,14 @@ public final class SurfaceControl implements Parcelable { } /** + * @hide + */ + public Builder setBLASTLayer() { + unsetBufferSize(); + return setFlags(FX_SURFACE_BLAST, FX_SURFACE_MASK); + } + + /** * Indicates whether a 'ContainerLayer' is to be constructed. * * Container layers will not be rendered in any fashion and instead are used @@ -1951,7 +1967,10 @@ public final class SurfaceControl implements Parcelable { public static final NativeAllocationRegistry sRegistry = new NativeAllocationRegistry( Transaction.class.getClassLoader(), nativeGetNativeTransactionFinalizer(), 512); - private long mNativeObject; + /** + * @hide + */ + public long mNativeObject; private final ArrayMap<SurfaceControl, Point> mResizedSurfaces = new ArrayMap<>(); Runnable mFreeNativeResources; diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index cf0698575851..9ddd84f1943c 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -45,6 +45,7 @@ import android.content.res.CompatibilityInfo; import android.content.res.Configuration; import android.content.res.Resources; import android.content.res.TypedArray; +import android.graphics.BLASTBufferQueue; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.FrameInfo; @@ -170,6 +171,8 @@ public final class ViewRootImpl implements ViewParent, */ private static final boolean MT_RENDERER_AVAILABLE = true; + private static final boolean USE_BLAST_BUFFERQUEUE = false; + /** * If set to 2, the view system will switch from using rectangles retrieved from window to * dispatch to the view hierarchy to using {@link InsetsController}, that derives the insets @@ -475,6 +478,9 @@ public final class ViewRootImpl implements ViewParent, @UnsupportedAppUsage public final Surface mSurface = new Surface(); private final SurfaceControl mSurfaceControl = new SurfaceControl(); + private SurfaceControl mBlastSurfaceControl; + + private BLASTBufferQueue mBlastBufferQueue; /** * Transaction object that can be used to synchronize child SurfaceControl changes with @@ -1282,6 +1288,11 @@ public final class ViewRootImpl implements ViewParent, } mWindowAttributes.privateFlags |= compatibleWindowFlag; + if (USE_BLAST_BUFFERQUEUE) { + mWindowAttributes.privateFlags = + WindowManager.LayoutParams.PRIVATE_FLAG_USE_BLAST; + } + if (mWindowAttributes.preservePreviousSurfaceInsets) { // Restore old surface insets. mWindowAttributes.surfaceInsets.set( @@ -1629,6 +1640,29 @@ public final class ViewRootImpl implements ViewParent, return mBoundsLayer; } + Surface getOrCreateBLASTSurface(int width, int height) { + if (mSurfaceControl == null || !mSurfaceControl.isValid()) { + return null; + } + if (mBlastSurfaceControl == null) { + mBlastSurfaceControl = new SurfaceControl.Builder(mSurfaceSession) + .setParent(mSurfaceControl) + .setName("BLAST") + .setBLASTLayer() + .build(); + mBlastBufferQueue = new BLASTBufferQueue( + mBlastSurfaceControl, width, height); + + } + mBlastBufferQueue.update(mSurfaceControl, width, height); + + mTransaction.show(mBlastSurfaceControl) + .reparent(mBlastSurfaceControl, mSurfaceControl) + .apply(); + + return mBlastBufferQueue.getSurface(); + } + private void setBoundsLayerCrop() { // mWinFrame is already adjusted for surface insets. So offset it and use it as // the cropping bounds. @@ -1658,6 +1692,13 @@ public final class ViewRootImpl implements ViewParent, } mSurface.release(); mSurfaceControl.release(); + + if (mBlastBufferQueue != null) { + mTransaction.remove(mBlastSurfaceControl).apply(); + mBlastSurfaceControl = null; + // We should probably add an explicit dispose. + mBlastBufferQueue = null; + } } /** @@ -2413,10 +2454,9 @@ public final class ViewRootImpl implements ViewParent, // will be transparent if (mAttachInfo.mThreadedRenderer != null) { try { - hwInitialized = mAttachInfo.mThreadedRenderer.initialize( - mSurface); + hwInitialized = mAttachInfo.mThreadedRenderer.initialize(mSurface); if (hwInitialized && (host.mPrivateFlags - & View.PFLAG_REQUEST_TRANSPARENT_REGIONS) == 0) { + & View.PFLAG_REQUEST_TRANSPARENT_REGIONS) == 0) { // Don't pre-allocate if transparent regions // are requested as they may not be needed mAttachInfo.mThreadedRenderer.allocateBuffers(); @@ -7139,7 +7179,13 @@ public final class ViewRootImpl implements ViewParent, mPendingStableInsets, mPendingOutsets, mPendingBackDropFrame, mPendingDisplayCutout, mPendingMergedConfiguration, mSurfaceControl, mTempInsets); if (mSurfaceControl.isValid()) { - mSurface.copyFrom(mSurfaceControl); + if (USE_BLAST_BUFFERQUEUE == false) { + mSurface.copyFrom(mSurfaceControl); + } else { + mSurface.transferFrom(getOrCreateBLASTSurface( + (int) (mView.getMeasuredWidth() * appScale + 0.5f), + (int) (mView.getMeasuredHeight() * appScale + 0.5f))); + } } else { destroySurface(); } diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index 001ab6650551..4a6ef987a642 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -1834,6 +1834,13 @@ public interface WindowManager extends ViewManager { public static final int PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC = 0x01000000; /** + * Flag to request creation of a BLAST (Buffer as LayerState) Layer. + * If not specified the client will receive a BufferQueue layer. + * @hide + */ + public static final int PRIVATE_FLAG_USE_BLAST = 0x02000000; + + /** * An internal annotation for flags that can be specified to {@link #softInputMode}. * * @hide diff --git a/core/jni/Android.bp b/core/jni/Android.bp index 0feab7f61918..ce405feb5985 100644 --- a/core/jni/Android.bp +++ b/core/jni/Android.bp @@ -117,6 +117,7 @@ cc_library_shared { "android_view_RenderNodeAnimator.cpp", "android_view_Surface.cpp", "android_view_SurfaceControl.cpp", + "android_graphics_BLASTBufferQueue.cpp", "android_view_SurfaceSession.cpp", "android_view_TextureView.cpp", "android_view_VelocityTracker.cpp", diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp index d476d2d2c35c..3497f920e6a4 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -115,6 +115,7 @@ extern int register_android_util_MemoryIntArray(JNIEnv* env); extern int register_android_content_StringBlock(JNIEnv* env); extern int register_android_content_XmlBlock(JNIEnv* env); extern int register_android_content_res_ApkAssets(JNIEnv* env); +extern int register_android_graphics_BLASTBufferQueue(JNIEnv* env); extern int register_android_view_DisplayEventReceiver(JNIEnv* env); extern int register_android_view_InputApplicationHandle(JNIEnv* env); extern int register_android_view_InputWindowHandle(JNIEnv* env); @@ -1458,10 +1459,9 @@ static const RegJNIRec gRegJNI[] = { REG_JNI(register_android_opengl_jni_GLES31), REG_JNI(register_android_opengl_jni_GLES31Ext), REG_JNI(register_android_opengl_jni_GLES32), - REG_JNI(register_android_graphics_classes), + REG_JNI(register_android_graphics_BLASTBufferQueue), REG_JNI(register_android_graphics_GraphicBuffer), - REG_JNI(register_android_database_CursorWindow), REG_JNI(register_android_database_SQLiteConnection), REG_JNI(register_android_database_SQLiteGlobal), diff --git a/core/jni/android_graphics_BLASTBufferQueue.cpp b/core/jni/android_graphics_BLASTBufferQueue.cpp new file mode 100644 index 000000000000..185e58160adf --- /dev/null +++ b/core/jni/android_graphics_BLASTBufferQueue.cpp @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2019 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. + */ + +#define LOG_TAG "BLASTBufferQueue" + +#include <nativehelper/JNIHelp.h> + +#include <android_runtime/AndroidRuntime.h> +#include <android_runtime/android_view_Surface.h> +#include <utils/Log.h> +#include <utils/RefBase.h> + +#include <gui/BLASTBufferQueue.h> +#include <gui/Surface.h> +#include <gui/SurfaceComposerClient.h> + +namespace android { + +static jlong nativeCreate(JNIEnv* env, jclass clazz, jlong surfaceControl, jlong width, jlong height) { + sp<BLASTBufferQueue> queue = new BLASTBufferQueue( + reinterpret_cast<SurfaceControl*>(surfaceControl), width, height); + queue->incStrong((void*)nativeCreate); + return reinterpret_cast<jlong>(queue.get()); +} + +static void nativeDestroy(JNIEnv* env, jclass clazz, jlong ptr) { + sp<BLASTBufferQueue> queue = reinterpret_cast<BLASTBufferQueue*>(ptr); + queue->decStrong((void*)nativeCreate); +} + +static jobject nativeGetSurface(JNIEnv* env, jclass clazz, jlong ptr) { + sp<BLASTBufferQueue> queue = reinterpret_cast<BLASTBufferQueue*>(ptr); + return android_view_Surface_createFromIGraphicBufferProducer(env, queue->getIGraphicBufferProducer()); +} + +static void nativeSetNextTransaction(JNIEnv* env, jclass clazz, jlong ptr, jlong transactionPtr) { + sp<BLASTBufferQueue> queue = reinterpret_cast<BLASTBufferQueue*>(ptr); + auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionPtr); + queue->setNextTransaction(transaction); +} + +static void nativeUpdate(JNIEnv*env, jclass clazz, jlong ptr, jlong surfaceControl, jlong width, jlong height) { + sp<BLASTBufferQueue> queue = reinterpret_cast<BLASTBufferQueue*>(ptr); + queue->update(reinterpret_cast<SurfaceControl*>(surfaceControl), width, height); +} + +static const JNINativeMethod gMethods[] = { + /* name, signature, funcPtr */ + { "nativeCreate", "(JJJ)J", + (void*)nativeCreate }, + { "nativeGetSurface", "(J)Landroid/view/Surface;", + (void*)nativeGetSurface }, + { "nativeDestroy", "(J)V", + (void*)nativeDestroy }, + { "nativeSetNextTransaction", "(JJ)V", + (void*)nativeSetNextTransaction }, + { "nativeUpdate", "(JJJJ)V", + (void*)nativeUpdate } +}; + +int register_android_graphics_BLASTBufferQueue(JNIEnv* env) { + int res = jniRegisterNativeMethods(env, "android/graphics/BLASTBufferQueue", + gMethods, NELEM(gMethods)); + LOG_ALWAYS_FATAL_IF(res < 0, "Unable to register native methods."); + + return 0; +} + +} // namespace android diff --git a/graphics/java/android/graphics/BLASTBufferQueue.java b/graphics/java/android/graphics/BLASTBufferQueue.java new file mode 100644 index 000000000000..8c6a9371d53b --- /dev/null +++ b/graphics/java/android/graphics/BLASTBufferQueue.java @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2019 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 android.graphics; + +import android.view.Surface; +import android.view.SurfaceControl; + +/** + * @hide + */ +public final class BLASTBufferQueue { + // Note: This field is accessed by native code. + private long mNativeObject; // BLASTBufferQueue* + + private static native long nativeCreate(long surfaceControl, long width, long height); + private static native void nativeDestroy(long ptr); + private static native Surface nativeGetSurface(long ptr); + private static native void nativeSetNextTransaction(long ptr, long transactionPtr); + private static native void nativeUpdate(long ptr, long surfaceControl, long width, long height); + + /** Create a new connection with the surface flinger. */ + public BLASTBufferQueue(SurfaceControl sc, int width, int height) { + mNativeObject = nativeCreate(sc.mNativeObject, width, height); + } + + public void destroy() { + nativeDestroy(mNativeObject); + } + + public Surface getSurface() { + return nativeGetSurface(mNativeObject); + } + + public void setNextTransaction(SurfaceControl.Transaction t) { + nativeSetNextTransaction(mNativeObject, t.mNativeObject); + } + + public void update(SurfaceControl sc, int width, int height) { + nativeUpdate(mNativeObject, sc.mNativeObject, width, height); + } + + @Override + protected void finalize() throws Throwable { + try { + if (mNativeObject != 0) { + nativeDestroy(mNativeObject); + } + } finally { + super.finalize(); + } + } +} + diff --git a/services/core/java/com/android/server/wm/WindowSurfaceController.java b/services/core/java/com/android/server/wm/WindowSurfaceController.java index 7f68c48e473f..0b4ea9927139 100644 --- a/services/core/java/com/android/server/wm/WindowSurfaceController.java +++ b/services/core/java/com/android/server/wm/WindowSurfaceController.java @@ -38,6 +38,7 @@ import android.util.Slog; import android.util.proto.ProtoOutputStream; import android.view.SurfaceControl; import android.view.WindowContentFrameStats; +import android.view.WindowManager; import com.android.server.protolog.common.ProtoLog; @@ -108,6 +109,13 @@ class WindowSurfaceController { .setFlags(flags) .setMetadata(METADATA_WINDOW_TYPE, windowType) .setMetadata(METADATA_OWNER_UID, ownerUid); + + if ((win.getAttrs().privateFlags & + WindowManager.LayoutParams.PRIVATE_FLAG_USE_BLAST) != 0) { + b.setContainerLayer(); + } + + mSurfaceControl = b.build(); Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); } |