Prevent EndLayerOps when Begin was rejected
am: 3c53ec51ef
Change-Id: I075b68a1b7bdee4cbebd734748dd485ff6cd67b3
This commit is contained in:
@ -149,50 +149,53 @@ int RecordingCanvas::saveLayer(float left, float top, float right, float bottom,
|
|||||||
|
|
||||||
// Map visible bounds back to layer space, and intersect with parameter bounds
|
// Map visible bounds back to layer space, and intersect with parameter bounds
|
||||||
Rect layerBounds = visibleBounds;
|
Rect layerBounds = visibleBounds;
|
||||||
Matrix4 inverse;
|
if (CC_LIKELY(!layerBounds.isEmpty())) {
|
||||||
inverse.loadInverse(*previous.transform);
|
// if non-empty, can safely map by the inverse transform
|
||||||
inverse.mapRect(layerBounds);
|
Matrix4 inverse;
|
||||||
layerBounds.doIntersect(unmappedBounds);
|
inverse.loadInverse(*previous.transform);
|
||||||
|
inverse.mapRect(layerBounds);
|
||||||
|
layerBounds.doIntersect(unmappedBounds);
|
||||||
|
}
|
||||||
|
|
||||||
int saveValue = mState.save((int) flags);
|
int saveValue = mState.save((int) flags);
|
||||||
Snapshot& snapshot = *mState.writableSnapshot();
|
Snapshot& snapshot = *mState.writableSnapshot();
|
||||||
|
|
||||||
// layerBounds is in original bounds space, but clipped by current recording clip
|
// layerBounds is in original bounds space, but clipped by current recording clip
|
||||||
if (layerBounds.isEmpty() || unmappedBounds.isEmpty()) {
|
if (!layerBounds.isEmpty() && !unmappedBounds.isEmpty()) {
|
||||||
// Don't bother recording layer, since it's been rejected
|
|
||||||
if (CC_LIKELY(clippedLayer)) {
|
if (CC_LIKELY(clippedLayer)) {
|
||||||
snapshot.resetClip(0, 0, 0, 0);
|
auto previousClip = getRecordedClip(); // capture before new snapshot clip has changed
|
||||||
|
if (addOp(alloc().create_trivial<BeginLayerOp>(
|
||||||
|
unmappedBounds,
|
||||||
|
*previous.transform, // transform to *draw* with
|
||||||
|
previousClip, // clip to *draw* with
|
||||||
|
refPaint(paint))) >= 0) {
|
||||||
|
snapshot.flags |= Snapshot::kFlagIsLayer | Snapshot::kFlagIsFboLayer;
|
||||||
|
snapshot.initializeViewport(unmappedBounds.getWidth(), unmappedBounds.getHeight());
|
||||||
|
snapshot.transform->loadTranslate(-unmappedBounds.left, -unmappedBounds.top, 0.0f);
|
||||||
|
|
||||||
|
Rect clip = layerBounds;
|
||||||
|
clip.translate(-unmappedBounds.left, -unmappedBounds.top);
|
||||||
|
snapshot.resetClip(clip.left, clip.top, clip.right, clip.bottom);
|
||||||
|
snapshot.roundRectClipState = nullptr;
|
||||||
|
return saveValue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (addOp(alloc().create_trivial<BeginUnclippedLayerOp>(
|
||||||
|
unmappedBounds,
|
||||||
|
*mState.currentSnapshot()->transform,
|
||||||
|
getRecordedClip(),
|
||||||
|
refPaint(paint))) >= 0) {
|
||||||
|
snapshot.flags |= Snapshot::kFlagIsLayer;
|
||||||
|
return saveValue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return saveValue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Layer not needed, so skip recording it...
|
||||||
if (CC_LIKELY(clippedLayer)) {
|
if (CC_LIKELY(clippedLayer)) {
|
||||||
auto previousClip = getRecordedClip(); // note: done before new snapshot's clip has changed
|
// ... and set empty clip to reject inner content, if possible
|
||||||
|
snapshot.resetClip(0, 0, 0, 0);
|
||||||
snapshot.flags |= Snapshot::kFlagIsLayer | Snapshot::kFlagIsFboLayer;
|
|
||||||
snapshot.initializeViewport(unmappedBounds.getWidth(), unmappedBounds.getHeight());
|
|
||||||
snapshot.transform->loadTranslate(-unmappedBounds.left, -unmappedBounds.top, 0.0f);
|
|
||||||
|
|
||||||
Rect clip = layerBounds;
|
|
||||||
clip.translate(-unmappedBounds.left, -unmappedBounds.top);
|
|
||||||
snapshot.resetClip(clip.left, clip.top, clip.right, clip.bottom);
|
|
||||||
snapshot.roundRectClipState = nullptr;
|
|
||||||
|
|
||||||
addOp(alloc().create_trivial<BeginLayerOp>(
|
|
||||||
unmappedBounds,
|
|
||||||
*previous.transform, // transform to *draw* with
|
|
||||||
previousClip, // clip to *draw* with
|
|
||||||
refPaint(paint)));
|
|
||||||
} else {
|
|
||||||
snapshot.flags |= Snapshot::kFlagIsLayer;
|
|
||||||
|
|
||||||
addOp(alloc().create_trivial<BeginUnclippedLayerOp>(
|
|
||||||
unmappedBounds,
|
|
||||||
*mState.currentSnapshot()->transform,
|
|
||||||
getRecordedClip(),
|
|
||||||
refPaint(paint)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return saveValue;
|
return saveValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -619,7 +622,7 @@ void RecordingCanvas::callDrawGLFunction(Functor* functor,
|
|||||||
functor));
|
functor));
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t RecordingCanvas::addOp(RecordedOp* op) {
|
int RecordingCanvas::addOp(RecordedOp* op) {
|
||||||
// skip op with empty clip
|
// skip op with empty clip
|
||||||
if (op->localClip && op->localClip->rect.isEmpty()) {
|
if (op->localClip && op->localClip->rect.isEmpty()) {
|
||||||
// NOTE: this rejection happens after op construction/content ref-ing, so content ref'd
|
// NOTE: this rejection happens after op construction/content ref-ing, so content ref'd
|
||||||
|
@ -208,7 +208,7 @@ private:
|
|||||||
void drawSimpleRects(const float* rects, int vertexCount, const SkPaint* paint);
|
void drawSimpleRects(const float* rects, int vertexCount, const SkPaint* paint);
|
||||||
|
|
||||||
|
|
||||||
size_t addOp(RecordedOp* op);
|
int addOp(RecordedOp* op);
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// lazy object copy
|
// lazy object copy
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
@ -545,6 +545,21 @@ TEST(RecordingCanvas, saveLayer_rotateClipped) {
|
|||||||
EXPECT_EQ(3, count);
|
EXPECT_EQ(3, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(RecordingCanvas, saveLayer_rejectBegin) {
|
||||||
|
auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [](RecordingCanvas& canvas) {
|
||||||
|
canvas.save(SaveFlags::MatrixClip);
|
||||||
|
canvas.translate(0, -20); // avoid identity case
|
||||||
|
// empty clip rect should force layer + contents to be rejected
|
||||||
|
canvas.clipRect(0, -20, 200, -20, SkRegion::kIntersect_Op);
|
||||||
|
canvas.saveLayerAlpha(0, 0, 200, 200, 128, SaveFlags::ClipToLayer);
|
||||||
|
canvas.drawRect(0, 0, 200, 200, SkPaint());
|
||||||
|
canvas.restore();
|
||||||
|
canvas.restore();
|
||||||
|
});
|
||||||
|
|
||||||
|
ASSERT_EQ(0u, dl->getOps().size()) << "Begin/Rect/End should all be rejected.";
|
||||||
|
}
|
||||||
|
|
||||||
TEST(RecordingCanvas, drawRenderNode_rejection) {
|
TEST(RecordingCanvas, drawRenderNode_rejection) {
|
||||||
auto child = TestUtils::createNode(50, 50, 150, 150,
|
auto child = TestUtils::createNode(50, 50, 150, 150,
|
||||||
[](RenderProperties& props, RecordingCanvas& canvas) {
|
[](RenderProperties& props, RecordingCanvas& canvas) {
|
||||||
|
Reference in New Issue
Block a user