diff options
| -rw-r--r-- | core/java/android/view/SurfaceView.java | 13 | ||||
| -rw-r--r-- | graphics/java/android/graphics/BaseCanvas.java | 10 | ||||
| -rw-r--r-- | graphics/java/android/graphics/BaseRecordingCanvas.java | 12 | ||||
| -rw-r--r-- | libs/hwui/Android.bp | 2 | ||||
| -rw-r--r-- | libs/hwui/DisplayList.h | 4 | ||||
| -rw-r--r-- | libs/hwui/RenderNode.cpp | 8 | ||||
| -rw-r--r-- | libs/hwui/RenderNode.h | 5 | ||||
| -rw-r--r-- | libs/hwui/SkiaCanvas.cpp | 8 | ||||
| -rw-r--r-- | libs/hwui/SkiaCanvas.h | 2 | ||||
| -rw-r--r-- | libs/hwui/hwui/Canvas.h | 2 | ||||
| -rw-r--r-- | libs/hwui/jni/android_graphics_Canvas.cpp | 7 | ||||
| -rw-r--r-- | libs/hwui/pipeline/skia/HolePunch.cpp | 21 | ||||
| -rw-r--r-- | libs/hwui/pipeline/skia/HolePunch.h | 30 | ||||
| -rw-r--r-- | libs/hwui/pipeline/skia/RenderNodeDrawable.cpp | 6 | ||||
| -rw-r--r-- | libs/hwui/pipeline/skia/SkiaDisplayList.h | 10 | ||||
| -rw-r--r-- | libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp | 21 | ||||
| -rw-r--r-- | libs/hwui/pipeline/skia/SkiaRecordingCanvas.h | 3 | ||||
| -rw-r--r-- | libs/hwui/pipeline/skia/TransformCanvas.cpp | 43 | ||||
| -rw-r--r-- | libs/hwui/pipeline/skia/TransformCanvas.h | 35 | 
19 files changed, 235 insertions, 7 deletions
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java index 82106b09ca5c..2b96a14b04d4 100644 --- a/core/java/android/view/SurfaceView.java +++ b/core/java/android/view/SurfaceView.java @@ -33,7 +33,6 @@ import android.graphics.Color;  import android.graphics.Matrix;  import android.graphics.Paint;  import android.graphics.PixelFormat; -import android.graphics.PorterDuff;  import android.graphics.Rect;  import android.graphics.Region;  import android.graphics.RenderNode; @@ -670,10 +669,16 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall              if (mClipSurfaceToBounds && mClipBounds != null) {                  mTmpRect.intersect(mClipBounds);              } -            canvas.drawRoundRect(mTmpRect.left, mTmpRect.top, mTmpRect.right, mTmpRect.bottom, -                    mCornerRadius, mCornerRadius, mRoundedViewportPaint); +            canvas.punchHole( +                    mTmpRect.left, +                    mTmpRect.top, +                    mTmpRect.right, +                    mTmpRect.bottom, +                    mCornerRadius, +                    mCornerRadius +            );          } else { -            canvas.drawColor(0, PorterDuff.Mode.CLEAR); +            canvas.punchHole(0f, 0f, getWidth(), getHeight(), 0f, 0f);          }      } diff --git a/graphics/java/android/graphics/BaseCanvas.java b/graphics/java/android/graphics/BaseCanvas.java index 54f9fa81b9b7..a612265793a3 100644 --- a/graphics/java/android/graphics/BaseCanvas.java +++ b/graphics/java/android/graphics/BaseCanvas.java @@ -673,6 +673,13 @@ public abstract class BaseCanvas {      /**       * @hide       */ +    public void punchHole(float left, float top, float right, float bottom, float rx, float ry) { +        nPunchHole(mNativeCanvasWrapper, left, top, right, bottom, rx, ry); +    } + +    /** +     * @hide +     */      public void setHwBitmapsInSwModeEnabled(boolean enabled) {          mAllowHwBitmapsInSwMode = enabled;      } @@ -815,4 +822,7 @@ public abstract class BaseCanvas {      private static native void nDrawTextOnPath(long nativeCanvas, String text, long nativePath,              float hOffset, float vOffset, int flags, long nativePaint); + +    private static native void nPunchHole(long renderer, float left, float top, float right, +            float bottom, float rx, float ry);  } diff --git a/graphics/java/android/graphics/BaseRecordingCanvas.java b/graphics/java/android/graphics/BaseRecordingCanvas.java index a8922e84514a..a998ba870f74 100644 --- a/graphics/java/android/graphics/BaseRecordingCanvas.java +++ b/graphics/java/android/graphics/BaseRecordingCanvas.java @@ -610,6 +610,14 @@ public class BaseRecordingCanvas extends Canvas {                  indices, indexOffset, indexCount, paint.getNativeInstance());      } +    /** +     * @hide +     */ +    @Override +    public void punchHole(float left, float top, float right, float bottom, float rx, float ry) { +        nPunchHole(mNativeCanvasWrapper, left, top, right, bottom, rx, ry); +    } +      @FastNative      private static native void nDrawBitmap(long nativeCanvas, long bitmapHandle, float left,              float top, long nativePaintOrZero, int canvasDensity, int screenDensity, @@ -735,4 +743,8 @@ public class BaseRecordingCanvas extends Canvas {      @FastNative      private static native void nDrawTextOnPath(long nativeCanvas, String text, long nativePath,              float hOffset, float vOffset, int flags, long nativePaint); + +    @FastNative +    private static native void nPunchHole(long renderer, float left, float top, float right, +            float bottom, float rx, float ry);  } diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp index 9b9af6f75aeb..c75b21f739cd 100644 --- a/libs/hwui/Android.bp +++ b/libs/hwui/Android.bp @@ -464,10 +464,12 @@ cc_defaults {          "canvas/CanvasOpBuffer.cpp",          "canvas/CanvasOpRasterizer.cpp",          "effects/StretchEffect.cpp", +        "pipeline/skia/HolePunch.cpp",          "pipeline/skia/SkiaDisplayList.cpp",          "pipeline/skia/SkiaRecordingCanvas.cpp",          "pipeline/skia/RenderNodeDrawable.cpp",          "pipeline/skia/ReorderBarrierDrawables.cpp", +        "pipeline/skia/TransformCanvas.cpp",          "renderthread/Frame.cpp",          "renderthread/RenderTask.cpp",          "renderthread/TimeLord.cpp", diff --git a/libs/hwui/DisplayList.h b/libs/hwui/DisplayList.h index ca5f853066f2..894b479c11db 100644 --- a/libs/hwui/DisplayList.h +++ b/libs/hwui/DisplayList.h @@ -72,6 +72,10 @@ public:          return mImpl && !(mImpl->isEmpty());      } +    [[nodiscard]] bool hasHolePunches() const { +        return mImpl && mImpl->hasHolePunches(); +    } +      [[nodiscard]] bool containsProjectionReceiver() const {          return mImpl && mImpl->containsProjectionReceiver();      } diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp index f5b2675c7fe6..e9eae3d14760 100644 --- a/libs/hwui/RenderNode.cpp +++ b/libs/hwui/RenderNode.cpp @@ -255,15 +255,19 @@ void RenderNode::prepareTreeImpl(TreeObserver& observer, TreeInfo& info, bool fu      if (mDisplayList) {          info.out.hasFunctors |= mDisplayList.hasFunctor(); +        mHasHolePunches = mDisplayList.hasHolePunches();          bool isDirty = mDisplayList.prepareListAndChildren(                  observer, info, childFunctorsNeedLayer, -                [](RenderNode* child, TreeObserver& observer, TreeInfo& info, -                   bool functorsNeedLayer) { +                [this](RenderNode* child, TreeObserver& observer, TreeInfo& info, +                       bool functorsNeedLayer) {                      child->prepareTreeImpl(observer, info, functorsNeedLayer); +                    mHasHolePunches |= child->hasHolePunches();                  });          if (isDirty) {              damageSelf(info);          } +    } else { +        mHasHolePunches = false;      }      pushLayerUpdate(info); diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h index 39ea53b6e3b3..988141fe191d 100644 --- a/libs/hwui/RenderNode.h +++ b/libs/hwui/RenderNode.h @@ -35,6 +35,7 @@  #include "DisplayList.h"  #include "Matrix.h"  #include "RenderProperties.h" +#include "pipeline/skia/HolePunch.h"  #include "pipeline/skia/SkiaDisplayList.h"  #include "pipeline/skia/SkiaLayer.h" @@ -284,6 +285,8 @@ private:      UsageHint mUsageHint = UsageHint::Unknown; +    bool mHasHolePunches; +      // METHODS & FIELDS ONLY USED BY THE SKIA RENDERER  public:      /** @@ -294,6 +297,8 @@ public:          return std::move(mAvailableDisplayList);      } +    bool hasHolePunches() { return mHasHolePunches; } +      /**       * Attach unused displayList to this node for potential future reuse.       */ diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp index 28d2b4cec0e1..4c4a15295690 100644 --- a/libs/hwui/SkiaCanvas.cpp +++ b/libs/hwui/SkiaCanvas.cpp @@ -23,6 +23,7 @@  #include "hwui/MinikinUtils.h"  #include "hwui/PaintFilter.h"  #include "pipeline/skia/AnimatedDrawables.h" +#include "pipeline/skia/HolePunch.h"  #include <SkAndroidFrameworkUtils.h>  #include <SkAnimatedImage.h> @@ -244,6 +245,13 @@ const SkiaCanvas::SaveRec* SkiaCanvas::currentSaveRec() const {      return (rec && rec->saveCount == currentSaveCount) ? rec : nullptr;  } +void SkiaCanvas::punchHole(const SkRRect& rect) { +    SkPaint paint = SkPaint(); +    paint.setColor(0); +    paint.setBlendMode(SkBlendMode::kClear); +    mCanvas->drawRRect(rect, paint); +} +  // ----------------------------------------------------------------------------  // functions to emulate legacy SaveFlags (i.e. independent matrix/clip flags)  // ---------------------------------------------------------------------------- diff --git a/libs/hwui/SkiaCanvas.h b/libs/hwui/SkiaCanvas.h index 9ab2b106dbfa..e0a0be54fb39 100644 --- a/libs/hwui/SkiaCanvas.h +++ b/libs/hwui/SkiaCanvas.h @@ -60,6 +60,8 @@ public:          LOG_ALWAYS_FATAL("SkiaCanvas does not support enableZ");      } +    virtual void punchHole(const SkRRect& rect) override; +      virtual void setBitmap(const SkBitmap& bitmap) override;      virtual bool isOpaque() override; diff --git a/libs/hwui/hwui/Canvas.h b/libs/hwui/hwui/Canvas.h index d1bdb712e911..c1feb767b459 100644 --- a/libs/hwui/hwui/Canvas.h +++ b/libs/hwui/hwui/Canvas.h @@ -155,6 +155,8 @@ public:          LOG_ALWAYS_FATAL("Not supported");      } +    virtual void punchHole(const SkRRect& rect) = 0; +      // ----------------------------------------------------------------------------      // Canvas state operations      // ---------------------------------------------------------------------------- diff --git a/libs/hwui/jni/android_graphics_Canvas.cpp b/libs/hwui/jni/android_graphics_Canvas.cpp index 89fb8bb2a2a0..a611f7ce2d14 100644 --- a/libs/hwui/jni/android_graphics_Canvas.cpp +++ b/libs/hwui/jni/android_graphics_Canvas.cpp @@ -35,6 +35,7 @@  #include "SkGraphics.h"  #include "SkRegion.h"  #include "SkVertices.h" +#include "SkRRect.h"  namespace minikin {  class MeasuredText; @@ -667,6 +668,11 @@ static void setCompatibilityVersion(JNIEnv* env, jobject, jint apiLevel) {      Canvas::setCompatibilityVersion(apiLevel);  } +static void punchHole(JNIEnv* env, jobject, jlong canvasPtr, jfloat left, jfloat top, jfloat right, +        jfloat bottom, jfloat rx, jfloat ry) { +    auto canvas = reinterpret_cast<Canvas*>(canvasPtr); +    canvas->punchHole(SkRRect::MakeRectXY(SkRect::MakeLTRB(left, top, right, bottom), rx, ry)); +}  }; // namespace CanvasJNI @@ -740,6 +746,7 @@ static const JNINativeMethod gDrawMethods[] = {      {"nDrawTextRun","(JLjava/lang/String;IIIIFFZJ)V", (void*) CanvasJNI::drawTextRunString},      {"nDrawTextOnPath","(J[CIIJFFIJ)V", (void*) CanvasJNI::drawTextOnPathChars},      {"nDrawTextOnPath","(JLjava/lang/String;JFFIJ)V", (void*) CanvasJNI::drawTextOnPathString}, +    {"nPunchHole", "(JFFFFFF)V", (void*) CanvasJNI::punchHole}  };  int register_android_graphics_Canvas(JNIEnv* env) { diff --git a/libs/hwui/pipeline/skia/HolePunch.cpp b/libs/hwui/pipeline/skia/HolePunch.cpp new file mode 100644 index 000000000000..2b2bca6df5a3 --- /dev/null +++ b/libs/hwui/pipeline/skia/HolePunch.cpp @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2021 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. + */ +#include "HolePunch.h" +#include <string> + +using namespace android::uirenderer::skiapipeline; + +const std::string HOLE_PUNCH_ANNOTATION = "surface_hole_punch"; diff --git a/libs/hwui/pipeline/skia/HolePunch.h b/libs/hwui/pipeline/skia/HolePunch.h new file mode 100644 index 000000000000..92c6f7721a08 --- /dev/null +++ b/libs/hwui/pipeline/skia/HolePunch.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2021 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. + */ + +#pragma once + +#include <string> +#include "SkRRect.h" + +namespace android { +namespace uirenderer { +namespace skiapipeline { + +const static std::string HOLE_PUNCH_ANNOTATION; + +}  // namespace skiapipeline +}  // namespace uirenderer +}  // namespace android
\ No newline at end of file diff --git a/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp b/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp index cb0ff8d871d4..5627a7e27232 100644 --- a/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp +++ b/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp @@ -18,6 +18,7 @@  #include <SkPaintFilterCanvas.h>  #include "RenderNode.h"  #include "SkiaDisplayList.h" +#include "TransformCanvas.h"  #include "utils/TraceUtils.h"  #include <include/effects/SkImageFilters.h> @@ -256,6 +257,11 @@ void RenderNodeDrawable::drawContent(SkCanvas* canvas) const {                  canvas->drawAnnotation(bounds, String8::format(                      "SurfaceID|%" PRId64, renderNode->uniqueId()).c_str(), nullptr);              } + +            if (renderNode->hasHolePunches()) { +                TransformCanvas transformCanvas(canvas); +                displayList->draw(&transformCanvas); +            }              canvas->drawImageRect(snapshotImage, bounds, bounds, sampling, &paint,                                    SkCanvas::kStrict_SrcRectConstraint); diff --git a/libs/hwui/pipeline/skia/SkiaDisplayList.h b/libs/hwui/pipeline/skia/SkiaDisplayList.h index 1136e58e43d8..90e9bc6a1a28 100644 --- a/libs/hwui/pipeline/skia/SkiaDisplayList.h +++ b/libs/hwui/pipeline/skia/SkiaDisplayList.h @@ -163,7 +163,7 @@ public:  private:      std::vector<Pair<VectorDrawableRoot*, SkMatrix>> mVectorDrawables; - +    bool mHasHolePunches;  public:      void appendVD(VectorDrawableRoot* r) { appendVD(r, SkMatrix::I()); } @@ -171,6 +171,14 @@ public:          mVectorDrawables.push_back(Pair<VectorDrawableRoot*, SkMatrix>(r, mat));      } +    void setHasHolePunches(bool hasHolePunches) { +        mHasHolePunches = hasHolePunches; +    } + +    bool hasHolePunches() { +        return mHasHolePunches; +    } +      std::vector<AnimatedImageDrawable*> mAnimatedImages;      DisplayListData mDisplayList; diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp index 61f9960c4d8d..82814def6962 100644 --- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp +++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp @@ -53,6 +53,27 @@ void SkiaRecordingCanvas::initDisplayList(uirenderer::RenderNode* renderNode, in      mDisplayList->attachRecorder(&mRecorder, SkIRect::MakeWH(width, height));      SkiaCanvas::reset(&mRecorder); +    mDisplayList->setHasHolePunches(false); +} + +void SkiaRecordingCanvas::punchHole(const SkRRect& rect) { +    // Add the marker annotation to allow HWUI to determine where the current +    // clip/transformation should be applied +    SkVector vector = rect.getSimpleRadii(); +    const int dataSize = 2; +    float data[dataSize]; +    data[0] = vector.x(); +    data[1] = vector.y(); +    mRecorder.drawAnnotation(rect.rect(), HOLE_PUNCH_ANNOTATION.c_str(), +                             SkData::MakeWithCopy(data, dataSize)); + +    // Clear the current rect within the layer itself +    SkPaint paint = SkPaint(); +    paint.setColor(0); +    paint.setBlendMode(SkBlendMode::kClear); +    mRecorder.drawRRect(rect, paint); + +    mDisplayList->setHasHolePunches(true);  }  std::unique_ptr<SkiaDisplayList> SkiaRecordingCanvas::finishRecording() { diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h index ff03e0c5f6d6..06f2a27d22a5 100644 --- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h +++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h @@ -15,6 +15,7 @@   */  #pragma once +#include "HolePunch.h"  #include "RecordingCanvas.h"  #include "ReorderBarrierDrawables.h"  #include "SkiaCanvas.h" @@ -43,6 +44,8 @@ public:          initDisplayList(renderNode, width, height);      } +    virtual void punchHole(const SkRRect& rect) override; +      virtual void finishRecording(uirenderer::RenderNode* destination) override;      std::unique_ptr<SkiaDisplayList> finishRecording(); diff --git a/libs/hwui/pipeline/skia/TransformCanvas.cpp b/libs/hwui/pipeline/skia/TransformCanvas.cpp new file mode 100644 index 000000000000..6bfbb0d270b7 --- /dev/null +++ b/libs/hwui/pipeline/skia/TransformCanvas.cpp @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2021 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. + */ +#include "TransformCanvas.h" +#include "HolePunch.h" +#include "SkData.h" +#include "SkDrawable.h" + +using namespace android::uirenderer::skiapipeline; + +void TransformCanvas::onDrawAnnotation(const SkRect& rect, const char* key, SkData* value) { +    if (HOLE_PUNCH_ANNOTATION == key) { +        auto* rectParams = static_cast<const float*>(value->data()); +        float radiusX = rectParams[0]; +        float radiusY = rectParams[1]; +        SkRRect roundRect = SkRRect::MakeRectXY(rect, radiusX, radiusY); + +        SkPaint paint; +        paint.setColor(0); +        paint.setBlendMode(SkBlendMode::kClear); +        mWrappedCanvas->drawRRect(roundRect, paint); +    } +} + +void TransformCanvas::onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) { +    drawable->draw(this, matrix); +} + +bool TransformCanvas::onFilter(SkPaint& paint) const { +    return false; +} diff --git a/libs/hwui/pipeline/skia/TransformCanvas.h b/libs/hwui/pipeline/skia/TransformCanvas.h new file mode 100644 index 000000000000..47f77f107441 --- /dev/null +++ b/libs/hwui/pipeline/skia/TransformCanvas.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2021 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. + */ +#pragma once + +#include <include/core/SkCanvas.h> +#include "SkPaintFilterCanvas.h" + +class TransformCanvas : public SkPaintFilterCanvas { +public: +    TransformCanvas(SkCanvas* target) : SkPaintFilterCanvas(target), mWrappedCanvas(target) {} + +protected: +    bool onFilter(SkPaint& paint) const override; + +protected: +    void onDrawAnnotation(const SkRect& rect, const char* key, SkData* value) override; +    void onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) override; + +private: +    // We don't own the canvas so just maintain a raw pointer to it +    SkCanvas* mWrappedCanvas; +};  |