summaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
Diffstat (limited to 'libs')
-rw-r--r--libs/hwui/RecordingCanvas.cpp18
-rw-r--r--libs/hwui/RecordingCanvas.h31
-rw-r--r--libs/hwui/RenderProperties.h8
-rw-r--r--libs/hwui/SkiaCanvas.cpp5
-rw-r--r--libs/hwui/pipeline/skia/SkiaDisplayList.cpp1
-rw-r--r--libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp8
-rw-r--r--libs/hwui/private/hwui/DrawVkInfo.h2
-rw-r--r--libs/hwui/renderthread/VulkanManager.cpp12
-rw-r--r--libs/hwui/renderthread/VulkanManager.h2
9 files changed, 71 insertions, 16 deletions
diff --git a/libs/hwui/RecordingCanvas.cpp b/libs/hwui/RecordingCanvas.cpp
index 6dc9d34cc3fd..85947665839a 100644
--- a/libs/hwui/RecordingCanvas.cpp
+++ b/libs/hwui/RecordingCanvas.cpp
@@ -759,6 +759,8 @@ RecordingCanvas::RecordingCanvas() : INHERITED(1, 1), fDL(nullptr) {}
void RecordingCanvas::reset(DisplayListData* dl, const SkIRect& bounds) {
this->resetCanvas(bounds.right(), bounds.bottom());
fDL = dl;
+ mClipMayBeComplex = false;
+ mSaveCount = mComplexSaveCount = 0;
}
sk_sp<SkSurface> RecordingCanvas::onNewSurface(const SkImageInfo&, const SkSurfaceProps&) {
@@ -770,6 +772,7 @@ void RecordingCanvas::onFlush() {
}
void RecordingCanvas::willSave() {
+ mSaveCount++;
fDL->save();
}
SkCanvas::SaveLayerStrategy RecordingCanvas::getSaveLayerStrategy(const SaveLayerRec& rec) {
@@ -778,6 +781,11 @@ SkCanvas::SaveLayerStrategy RecordingCanvas::getSaveLayerStrategy(const SaveLaye
return SkCanvas::kNoLayer_SaveLayerStrategy;
}
void RecordingCanvas::willRestore() {
+ mSaveCount--;
+ if (mSaveCount < mComplexSaveCount) {
+ mClipMayBeComplex = false;
+ mComplexSaveCount = 0;
+ }
fDL->restore();
}
@@ -798,17 +806,27 @@ void RecordingCanvas::didTranslate(SkScalar dx, SkScalar dy) {
void RecordingCanvas::onClipRect(const SkRect& rect, SkClipOp op, ClipEdgeStyle style) {
fDL->clipRect(rect, op, style == kSoft_ClipEdgeStyle);
+ if (!getTotalMatrix().isScaleTranslate()) {
+ setClipMayBeComplex();
+ }
this->INHERITED::onClipRect(rect, op, style);
}
void RecordingCanvas::onClipRRect(const SkRRect& rrect, SkClipOp op, ClipEdgeStyle style) {
+ if (rrect.getType() > SkRRect::kRect_Type || !getTotalMatrix().isScaleTranslate()) {
+ setClipMayBeComplex();
+ }
fDL->clipRRect(rrect, op, style == kSoft_ClipEdgeStyle);
this->INHERITED::onClipRRect(rrect, op, style);
}
void RecordingCanvas::onClipPath(const SkPath& path, SkClipOp op, ClipEdgeStyle style) {
+ setClipMayBeComplex();
fDL->clipPath(path, op, style == kSoft_ClipEdgeStyle);
this->INHERITED::onClipPath(path, op, style);
}
void RecordingCanvas::onClipRegion(const SkRegion& region, SkClipOp op) {
+ if (region.isComplex() || !getTotalMatrix().isScaleTranslate()) {
+ setClipMayBeComplex();
+ }
fDL->clipRegion(region, op);
this->INHERITED::onClipRegion(region, op);
}
diff --git a/libs/hwui/RecordingCanvas.h b/libs/hwui/RecordingCanvas.h
index caaef67f724f..3a76ca1137a5 100644
--- a/libs/hwui/RecordingCanvas.h
+++ b/libs/hwui/RecordingCanvas.h
@@ -203,10 +203,41 @@ public:
void drawVectorDrawable(VectorDrawableRoot* tree);
+ /**
+ * If "isClipMayBeComplex" returns false, it is guaranteed the current clip is a rectangle.
+ * If the return value is true, then clip may or may not be complex (there is no guarantee).
+ */
+ inline bool isClipMayBeComplex() { return mClipMayBeComplex; }
+
private:
typedef SkCanvasVirtualEnforcer<SkNoDrawCanvas> INHERITED;
+ inline void setClipMayBeComplex() {
+ if (!mClipMayBeComplex) {
+ mComplexSaveCount = mSaveCount;
+ mClipMayBeComplex = true;
+ }
+ }
+
DisplayListData* fDL;
+
+ /**
+ * mClipMayBeComplex tracks if the current clip is a rectangle. This flag is used to promote
+ * FunctorDrawable to a layer, if it is clipped by a non-rect.
+ */
+ bool mClipMayBeComplex = false;
+
+ /**
+ * mSaveCount is the current level of our save tree.
+ */
+ int mSaveCount = 0;
+
+ /**
+ * mComplexSaveCount is the first save level, which has a complex clip. Every level below
+ * mComplexSaveCount is assumed to have a complex clip and every level above mComplexSaveCount
+ * is guaranteed to not be complex.
+ */
+ int mComplexSaveCount = 0;
};
} // namespace uirenderer
diff --git a/libs/hwui/RenderProperties.h b/libs/hwui/RenderProperties.h
index ddb7e4e4ce74..e6710cc8f950 100644
--- a/libs/hwui/RenderProperties.h
+++ b/libs/hwui/RenderProperties.h
@@ -151,6 +151,7 @@ public:
// parent may have already dictated that a descendant layer is needed
bool functorsNeedLayer =
ancestorDictatesFunctorsNeedLayer
+ || CC_UNLIKELY(isClipMayBeComplex())
// Round rect clipping forces layer for functors
|| CC_UNLIKELY(getOutline().willRoundRectClip()) ||
@@ -193,6 +194,12 @@ public:
bool isProjectionReceiver() const { return mPrimitiveFields.mProjectionReceiver; }
+ bool setClipMayBeComplex(bool isClipMayBeComplex) {
+ return RP_SET(mPrimitiveFields.mClipMayBeComplex, isClipMayBeComplex);
+ }
+
+ bool isClipMayBeComplex() const { return mPrimitiveFields.mClipMayBeComplex; }
+
bool setStaticMatrix(const SkMatrix* matrix) {
delete mStaticMatrix;
if (matrix) {
@@ -563,6 +570,7 @@ private:
bool mProjectBackwards = false;
bool mProjectionReceiver = false;
bool mAllowForceDark = true;
+ bool mClipMayBeComplex = false;
Rect mClipBounds;
Outline mOutline;
RevealClip mRevealClip;
diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp
index 54a91f4ec06f..f328a5399cbb 100644
--- a/libs/hwui/SkiaCanvas.cpp
+++ b/libs/hwui/SkiaCanvas.cpp
@@ -694,11 +694,8 @@ void SkiaCanvas::drawGlyphs(ReadGlyphFunc glyphFunc, int count, const Paint& pai
paintCopy.setStyle(SkPaint::kFill_Style);
}
- SkRect bounds =
- SkRect::MakeLTRB(boundsLeft + x, boundsTop + y, boundsRight + x, boundsBottom + y);
-
SkTextBlobBuilder builder;
- const SkTextBlobBuilder::RunBuffer& buffer = builder.allocRunPos(font, count, &bounds);
+ const SkTextBlobBuilder::RunBuffer& buffer = builder.allocRunPos(font, count);
glyphFunc(buffer.glyphs, buffer.pos);
sk_sp<SkTextBlob> textBlob(builder.make());
diff --git a/libs/hwui/pipeline/skia/SkiaDisplayList.cpp b/libs/hwui/pipeline/skia/SkiaDisplayList.cpp
index 230065c222a9..29d5ef233338 100644
--- a/libs/hwui/pipeline/skia/SkiaDisplayList.cpp
+++ b/libs/hwui/pipeline/skia/SkiaDisplayList.cpp
@@ -73,7 +73,6 @@ bool SkiaDisplayList::prepareListAndChildren(
RenderNode* childNode = child.getRenderNode();
Matrix4 mat4(child.getRecordedMatrix());
info.damageAccumulator->pushTransform(&mat4);
- // TODO: a layer is needed if the canvas is rotated or has a non-rect clip
info.hasBackwardProjectedNodes = false;
childFn(childNode, observer, info, functorsNeedLayer);
hasBackwardProjectedNodesSubtree |= info.hasBackwardProjectedNodes;
diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
index d54275fe7e19..d9456355cb88 100644
--- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
+++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
@@ -113,6 +113,10 @@ void SkiaRecordingCanvas::drawRenderNode(uirenderer::RenderNode* renderNode) {
// Record the child node. Drawable dtor will be invoked when mChildNodes deque is cleared.
mDisplayList->mChildNodes.emplace_back(renderNode, asSkCanvas(), true, mCurrentBarrier);
auto& renderNodeDrawable = mDisplayList->mChildNodes.back();
+ if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaVulkan) {
+ // Put Vulkan WebViews with non-rectangular clips in a HW layer
+ renderNode->mutateStagingProperties().setClipMayBeComplex(mRecorder.isClipMayBeComplex());
+ }
drawDrawable(&renderNodeDrawable);
// use staging property, since recording on UI thread
@@ -138,10 +142,8 @@ void SkiaRecordingCanvas::callDrawGLFunction(Functor* functor,
void SkiaRecordingCanvas::drawWebViewFunctor(int functor) {
FunctorDrawable* functorDrawable;
if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaVulkan) {
- // TODO(cblume) use VkFunctorDrawable instead of VkInteropFunctorDrawable here when the
- // interop is disabled.
functorDrawable =
- mDisplayList->allocateDrawable<VkInteropFunctorDrawable>(functor, asSkCanvas());
+ mDisplayList->allocateDrawable<VkFunctorDrawable>(functor, asSkCanvas());
} else {
functorDrawable = mDisplayList->allocateDrawable<GLFunctorDrawable>(functor, asSkCanvas());
}
diff --git a/libs/hwui/private/hwui/DrawVkInfo.h b/libs/hwui/private/hwui/DrawVkInfo.h
index abc4dbf9fa1c..fb55f5ca4c93 100644
--- a/libs/hwui/private/hwui/DrawVkInfo.h
+++ b/libs/hwui/private/hwui/DrawVkInfo.h
@@ -29,7 +29,7 @@ struct VkFunctorInitParams {
VkDevice device;
VkQueue queue;
uint32_t graphics_queue_index;
- uint32_t instance_version;
+ uint32_t api_version;
const char* const* enabled_instance_extension_names;
uint32_t enabled_instance_extension_names_length;
const char* const* enabled_device_extension_names;
diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp
index 1e7520216d66..582d51e6af94 100644
--- a/libs/hwui/renderthread/VulkanManager.cpp
+++ b/libs/hwui/renderthread/VulkanManager.cpp
@@ -83,7 +83,6 @@ void VulkanManager::destroy() {
mDevice = VK_NULL_HANDLE;
mPhysicalDevice = VK_NULL_HANDLE;
mInstance = VK_NULL_HANDLE;
- mInstanceVersion = 0u;
mInstanceExtensions.clear();
mDeviceExtensions.clear();
free_features_extensions_structs(mPhysicalDeviceFeatures2);
@@ -100,7 +99,7 @@ bool VulkanManager::setupDevice(GrVkExtensions& grExtensions, VkPhysicalDeviceFe
0, // applicationVersion
"android framework", // pEngineName
0, // engineVerison
- VK_MAKE_VERSION(1, 1, 0), // apiVersion
+ mAPIVersion, // apiVersion
};
{
@@ -377,8 +376,9 @@ void VulkanManager::initialize() {
}
GET_PROC(EnumerateInstanceVersion);
- LOG_ALWAYS_FATAL_IF(mEnumerateInstanceVersion(&mInstanceVersion));
- LOG_ALWAYS_FATAL_IF(mInstanceVersion < VK_MAKE_VERSION(1, 1, 0));
+ uint32_t instanceVersion;
+ LOG_ALWAYS_FATAL_IF(mEnumerateInstanceVersion(&instanceVersion));
+ LOG_ALWAYS_FATAL_IF(instanceVersion < VK_MAKE_VERSION(1, 1, 0));
GrVkExtensions extensions;
LOG_ALWAYS_FATAL_IF(!this->setupDevice(extensions, mPhysicalDeviceFeatures2));
@@ -398,7 +398,7 @@ void VulkanManager::initialize() {
backendContext.fDevice = mDevice;
backendContext.fQueue = mGraphicsQueue;
backendContext.fGraphicsQueueIndex = mGraphicsQueueIndex;
- backendContext.fInstanceVersion = mInstanceVersion;
+ backendContext.fMaxAPIVersion = mAPIVersion;
backendContext.fVkExtensions = &extensions;
backendContext.fDeviceFeatures2 = &mPhysicalDeviceFeatures2;
backendContext.fGetProc = std::move(getProc);
@@ -446,7 +446,7 @@ VkFunctorInitParams VulkanManager::getVkFunctorInitParams() const {
.device = mDevice,
.queue = mGraphicsQueue,
.graphics_queue_index = mGraphicsQueueIndex,
- .instance_version = mInstanceVersion,
+ .api_version = mAPIVersion,
.enabled_instance_extension_names = mInstanceExtensions.data(),
.enabled_instance_extension_names_length =
static_cast<uint32_t>(mInstanceExtensions.size()),
diff --git a/libs/hwui/renderthread/VulkanManager.h b/libs/hwui/renderthread/VulkanManager.h
index abe78efc9174..6426fe2808b7 100644
--- a/libs/hwui/renderthread/VulkanManager.h
+++ b/libs/hwui/renderthread/VulkanManager.h
@@ -246,7 +246,7 @@ private:
VkCommandBuffer mDummyCB = VK_NULL_HANDLE;
// Variables saved to populate VkFunctorInitParams.
- uint32_t mInstanceVersion = 0u;
+ static const uint32_t mAPIVersion = VK_MAKE_VERSION(1, 1, 0);
std::vector<const char*> mInstanceExtensions;
std::vector<const char*> mDeviceExtensions;
VkPhysicalDeviceFeatures2 mPhysicalDeviceFeatures2{};