diff options
author | 2023-10-24 20:43:22 -0400 | |
---|---|---|
committer | 2023-10-27 16:49:22 -0400 | |
commit | 1b152e712159c0b82831a7567ce2f3c49cdc11bf (patch) | |
tree | 74c107d65ae11b92af840bcd985910ed7ec4dc42 /libs | |
parent | 57cca107540d12c63b10ba326483b9acc4fa7b45 (diff) |
Implement automatic SV clipping
Clip SV to its ancestor clipping bounds. This enables
Z-above SurfaceView + scrolling containers to work more naturally
Replaces the hidden API of setEnableSurfaceClipping
Fixes: 298621623
Test: Sample app
Change-Id: Iaa862598e37065677f5ba163a5ac7a6fab2739ea
Diffstat (limited to 'libs')
-rw-r--r-- | libs/hwui/Android.bp | 1 | ||||
-rw-r--r-- | libs/hwui/DamageAccumulator.cpp | 41 | ||||
-rw-r--r-- | libs/hwui/DamageAccumulator.h | 2 | ||||
-rw-r--r-- | libs/hwui/Properties.cpp | 24 | ||||
-rw-r--r-- | libs/hwui/Properties.h | 2 | ||||
-rw-r--r-- | libs/hwui/jni/android_graphics_RenderNode.cpp | 46 |
6 files changed, 103 insertions, 13 deletions
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp index ff1eedb8eacb..da728f90e8e0 100644 --- a/libs/hwui/Android.bp +++ b/libs/hwui/Android.bp @@ -144,6 +144,7 @@ cc_defaults { "libsync", "libui", "aconfig_text_flags_c_lib", + "server_configurable_flags", ], static_libs: [ "libEGL_blobCache", diff --git a/libs/hwui/DamageAccumulator.cpp b/libs/hwui/DamageAccumulator.cpp index a8d170d00ef7..fd276419f5e5 100644 --- a/libs/hwui/DamageAccumulator.cpp +++ b/libs/hwui/DamageAccumulator.cpp @@ -242,6 +242,47 @@ void DamageAccumulator::applyRenderNodeTransform(DirtyStack* frame) { } } +SkRect DamageAccumulator::computeClipAndTransform(const SkRect& bounds, Matrix4* outMatrix) const { + const DirtyStack* frame = mHead; + Matrix4 transform; + SkRect pretransformResult = bounds; + while (true) { + SkRect currentBounds = pretransformResult; + pretransformResult.setEmpty(); + switch (frame->type) { + case TransformRenderNode: { + const RenderProperties& props = frame->renderNode->properties(); + // Perform clipping + if (props.getClipDamageToBounds() && !currentBounds.isEmpty()) { + if (!currentBounds.intersect( + SkRect::MakeIWH(props.getWidth(), props.getHeight()))) { + currentBounds.setEmpty(); + } + } + + // apply all transforms + mapRect(props, currentBounds, &pretransformResult); + frame->renderNode->applyViewPropertyTransforms(transform); + } break; + case TransformMatrix4: + mapRect(frame->matrix4, currentBounds, &pretransformResult); + transform.multiply(*frame->matrix4); + break; + default: + pretransformResult = currentBounds; + break; + } + if (frame->prev == frame) break; + frame = frame->prev; + } + SkRect result; + Matrix4 globalToLocal; + globalToLocal.loadInverse(transform); + mapRect(&globalToLocal, pretransformResult, &result); + *outMatrix = transform; + return result; +} + void DamageAccumulator::dirty(float left, float top, float right, float bottom) { mHead->pendingDirty.join({left, top, right, bottom}); } diff --git a/libs/hwui/DamageAccumulator.h b/libs/hwui/DamageAccumulator.h index c4249af392d3..30bf7063a627 100644 --- a/libs/hwui/DamageAccumulator.h +++ b/libs/hwui/DamageAccumulator.h @@ -61,6 +61,8 @@ public: void computeCurrentTransform(Matrix4* outMatrix) const; + SkRect computeClipAndTransform(const SkRect& bounds, Matrix4* outMatrix) const; + void finish(SkRect* totalDirty); struct StretchResult { diff --git a/libs/hwui/Properties.cpp b/libs/hwui/Properties.cpp index 5e5eb4a51b35..ad600d0bab93 100644 --- a/libs/hwui/Properties.cpp +++ b/libs/hwui/Properties.cpp @@ -20,15 +20,26 @@ #ifdef __ANDROID__ #include "HWUIProperties.sysprop.h" #endif -#include "src/core/SkTraceEventCommon.h" +#include <android-base/properties.h> +#include <cutils/compiler.h> +#include <log/log.h> #include <algorithm> #include <cstdlib> #include <optional> -#include <android-base/properties.h> -#include <cutils/compiler.h> -#include <log/log.h> +#include "src/core/SkTraceEventCommon.h" + +#ifdef __ANDROID__ +#include <com_android_graphics_hwui_flags.h> +namespace hwui_flags = com::android::graphics::hwui::flags; +#else +namespace hwui_flags { +constexpr bool clip_surfaceviews() { + return false; +} +} // namespace hwui_flags +#endif namespace android { namespace uirenderer { @@ -92,6 +103,8 @@ bool Properties::isSystemOrPersistent = false; float Properties::maxHdrHeadroomOn8bit = 5.f; // TODO: Refine this number +bool Properties::clipSurfaceViews = false; + StretchEffectBehavior Properties::stretchEffectBehavior = StretchEffectBehavior::ShaderHWUI; DrawingEnabled Properties::drawingEnabled = DrawingEnabled::NotInitialized; @@ -159,6 +172,9 @@ bool Properties::load() { // call isDrawingEnabled to force loading of the property isDrawingEnabled(); + clipSurfaceViews = + base::GetBoolProperty("debug.hwui.clip_surfaceviews", hwui_flags::clip_surfaceviews()); + return (prevDebugLayersUpdates != debugLayersUpdates) || (prevDebugOverdraw != debugOverdraw); } diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h index bb477449fff0..bca57e9e4678 100644 --- a/libs/hwui/Properties.h +++ b/libs/hwui/Properties.h @@ -325,6 +325,8 @@ public: static float maxHdrHeadroomOn8bit; + static bool clipSurfaceViews; + static StretchEffectBehavior getStretchEffectBehavior() { return stretchEffectBehavior; } diff --git a/libs/hwui/jni/android_graphics_RenderNode.cpp b/libs/hwui/jni/android_graphics_RenderNode.cpp index 2a218a25913d..a1b05c186ec0 100644 --- a/libs/hwui/jni/android_graphics_RenderNode.cpp +++ b/libs/hwui/jni/android_graphics_RenderNode.cpp @@ -568,6 +568,7 @@ static void android_view_RenderNode_forceEndAnimators(JNIEnv* env, jobject clazz struct { jclass clazz; jmethodID callPositionChanged; + jmethodID callPositionChanged2; jmethodID callApplyStretch; jmethodID callPositionLost; } gPositionListener; @@ -589,14 +590,25 @@ static void android_view_RenderNode_requestPositionUpdates(JNIEnv* env, jobject, virtual void onPositionUpdated(RenderNode& node, const TreeInfo& info) override { if (CC_UNLIKELY(!mListener || !info.updateWindowPositions)) return; - Matrix4 transform; - info.damageAccumulator->computeCurrentTransform(&transform); const RenderProperties& props = node.properties(); + const bool enableClip = Properties::clipSurfaceViews; - uirenderer::Rect bounds(props.getWidth(), props.getHeight()); + Matrix4 transform; + SkIRect clipBounds; + if (enableClip) { + uirenderer::Rect initialClipBounds; + props.getClippingRectForFlags(props.getClippingFlags(), &initialClipBounds); + clipBounds = + info.damageAccumulator + ->computeClipAndTransform(initialClipBounds.toSkRect(), &transform) + .roundOut(); + } else { + info.damageAccumulator->computeCurrentTransform(&transform); + } bool useStretchShader = Properties::getStretchEffectBehavior() != StretchEffectBehavior::UniformScale; // Compute the transform bounds first before calculating the stretch + uirenderer::Rect bounds(props.getWidth(), props.getHeight()); transform.mapRect(bounds); bool hasStretch = useStretchShader && info.stretchEffectCount; @@ -614,10 +626,11 @@ static void android_view_RenderNode_requestPositionUpdates(JNIEnv* env, jobject, bounds.roundOut(); } - if (mPreviousPosition == bounds) { + if (mPreviousPosition == bounds && mPreviousClip == clipBounds) { return; } mPreviousPosition = bounds; + mPreviousClip = clipBounds; ATRACE_NAME("Update SurfaceView position"); @@ -629,11 +642,23 @@ static void android_view_RenderNode_requestPositionUpdates(JNIEnv* env, jobject, // In particular if the app removes a view from the view tree before // this callback is dispatched, then we lose the position // information for this frame. - jboolean keepListening = env->CallStaticBooleanMethod( - gPositionListener.clazz, gPositionListener.callPositionChanged, mListener, - static_cast<jlong>(info.canvasContext.getFrameNumber()), - static_cast<jint>(bounds.left), static_cast<jint>(bounds.top), - static_cast<jint>(bounds.right), static_cast<jint>(bounds.bottom)); + jboolean keepListening; + if (!enableClip) { + keepListening = env->CallStaticBooleanMethod( + gPositionListener.clazz, gPositionListener.callPositionChanged, mListener, + static_cast<jlong>(info.canvasContext.getFrameNumber()), + static_cast<jint>(bounds.left), static_cast<jint>(bounds.top), + static_cast<jint>(bounds.right), static_cast<jint>(bounds.bottom)); + } else { + keepListening = env->CallStaticBooleanMethod( + gPositionListener.clazz, gPositionListener.callPositionChanged2, mListener, + static_cast<jlong>(info.canvasContext.getFrameNumber()), + static_cast<jint>(bounds.left), static_cast<jint>(bounds.top), + static_cast<jint>(bounds.right), static_cast<jint>(bounds.bottom), + static_cast<jint>(clipBounds.fLeft), static_cast<jint>(clipBounds.fTop), + static_cast<jint>(clipBounds.fRight), + static_cast<jint>(clipBounds.fBottom)); + } if (!keepListening) { env->DeleteGlobalRef(mListener); mListener = nullptr; @@ -738,6 +763,7 @@ static void android_view_RenderNode_requestPositionUpdates(JNIEnv* env, jobject, JavaVM* mVm; jobject mListener; uirenderer::Rect mPreviousPosition; + uirenderer::Rect mPreviousClip; }; RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr); @@ -866,6 +892,8 @@ int register_android_view_RenderNode(JNIEnv* env) { gPositionListener.clazz = MakeGlobalRefOrDie(env, clazz); gPositionListener.callPositionChanged = GetStaticMethodIDOrDie( env, clazz, "callPositionChanged", "(Ljava/lang/ref/WeakReference;JIIII)Z"); + gPositionListener.callPositionChanged2 = GetStaticMethodIDOrDie( + env, clazz, "callPositionChanged2", "(Ljava/lang/ref/WeakReference;JIIIIIIII)Z"); gPositionListener.callApplyStretch = GetStaticMethodIDOrDie( env, clazz, "callApplyStretch", "(Ljava/lang/ref/WeakReference;JFFFFFFFFFF)Z"); gPositionListener.callPositionLost = GetStaticMethodIDOrDie( |