Remove support for deprecated kDontClipToLayer_SaveLayerFlag
This removes the conditional behavior based on #defines, and the private flag definitions. It removes GMs and updates tests that tested the feature. Follow-up CLs will go through and simplify the internals of SkCanvas to take advantage of this support removal. Bug: skia:10986 Change-Id: Id42c9e7d134dd06507fabf6577e7872942ef9077 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/339988 Commit-Queue: Michael Ludwig <michaelludwig@google.com> Reviewed-by: Mike Reed <reed@google.com>
This commit is contained in:
parent
3021795041
commit
e0dee01043
@ -6,6 +6,9 @@ This file includes a list of high level updates for each milestone release.
|
||||
|
||||
Milestone 89
|
||||
------------
|
||||
* Remove support for deprecated kDontClipToLayer_SaveLayerFlag in SkCanvas::SaveLayerRec
|
||||
https://review.skia.org/339988
|
||||
|
||||
* Expose more info in SkCodec::FrameInfo
|
||||
https://review.skia.org/339857
|
||||
|
||||
|
@ -19,65 +19,6 @@
|
||||
#include "src/core/SkCanvasPriv.h"
|
||||
#include "tools/ToolUtils.h"
|
||||
|
||||
static void do_draw(SkCanvas* canvas, const SkRect& r) {
|
||||
SkPaint paint;
|
||||
paint.setBlendMode(SkBlendMode::kSrc);
|
||||
paint.setColor(0x800000FF);
|
||||
canvas->drawRect(r, paint);
|
||||
}
|
||||
|
||||
/**
|
||||
* Exercise SkCanvasPriv::kDontClipToLayer_SaveLayerFlag flag, which does not limit the clip to the
|
||||
* layer's bounds. Thus when a draw occurs, it can (depending on "where" it is) draw into the layer
|
||||
* and/or draw onto the surrounding portions of the canvas, or both.
|
||||
*
|
||||
* This GM has a 100x100 rectangle (r), which its going to draw. However first it creates a layer
|
||||
* with this flag covering 1/2 of the rectangle (upper half). Then it draws the rect in SRC mode.
|
||||
*
|
||||
* The portion of the draw that intersects the layer should see the SRC draw, apply it to the layer
|
||||
* and then during restore, it will SRC_OVER that layer onto the canvas (SRC_OVER since the layer
|
||||
* has no paint, so it gets the default xfermode during restore).
|
||||
*
|
||||
* Note: when we talk about drawing directly into the "canvas", in fact we are drawing into an
|
||||
* "outer" layer we created (filled with red). This is a testing detail, so that our final
|
||||
* output image is itself opaque, otherwise we make it harder to view the GM as a PNG.
|
||||
*
|
||||
* The portion of the draw below the layer draws directly into the canvas. Since it is in SRC mode,
|
||||
* it will write 0x80 to the canvas' alpha, overwriting the "red", which then gets blended with
|
||||
* the GM's white background.
|
||||
*
|
||||
* The portion in the layer, will end up SRC_OVERing the 0x80 layer pixels onto the canvas' red
|
||||
* pixels, making magenta.
|
||||
*
|
||||
* Thus the expected result is the upper half to be magenta 0xFF7F0080, and the lower half to be
|
||||
* light blue 0xFF7F7FFF.
|
||||
*/
|
||||
DEF_SIMPLE_GM(dont_clip_to_layer, canvas, 120, 120) {
|
||||
const SkRect r { 10, 10, 110, 110 };
|
||||
|
||||
// Wrap the entire test inside a red layer, so we don't punch the actual gm's alpha with
|
||||
// kSrc_Mode, which makes it hard to view (we like our GMs to have opaque pixels).
|
||||
canvas->saveLayer(&r, nullptr);
|
||||
canvas->drawColor(SK_ColorRED);
|
||||
|
||||
SkRect r0 = { 20, 20, 100, 55 };
|
||||
SkRect r1 = { 20, 65, 100, 100 };
|
||||
|
||||
SkCanvas::SaveLayerRec rec;
|
||||
rec.fPaint = nullptr;
|
||||
rec.fBounds = &r0;
|
||||
rec.fBackdrop = nullptr;
|
||||
rec.fSaveLayerFlags = SkCanvasPriv::kDontClipToLayer_SaveLayerFlag;
|
||||
canvas->saveLayer(rec);
|
||||
rec.fBounds = &r1;
|
||||
canvas->saveLayer(rec);
|
||||
do_draw(canvas, r);
|
||||
canvas->restore();
|
||||
canvas->restore();
|
||||
|
||||
canvas->restore(); // red-layer
|
||||
}
|
||||
|
||||
/** Draw a 2px border around the target, then red behind the target;
|
||||
set the clip to match the target, then draw >> the target in blue.
|
||||
*/
|
||||
|
@ -42,80 +42,6 @@
|
||||
#include <string.h>
|
||||
#include <initializer_list>
|
||||
|
||||
// This GM tests out the deprecated Android-specific unclipped saveLayer "feature".
|
||||
// In particular, it attempts to compare the performance of unclipped saveLayers with alternatives.
|
||||
|
||||
static void save_layer_unclipped(SkCanvas* canvas,
|
||||
SkScalar l, SkScalar t, SkScalar r, SkScalar b) {
|
||||
SkPaint paint;
|
||||
paint.setAlphaf(0.25f);
|
||||
SkRect rect = SkRect::MakeLTRB(l, t, r, b);
|
||||
canvas->saveLayer({ &rect, &paint, nullptr,
|
||||
(SkCanvas::SaveLayerFlags) SkCanvasPriv::kDontClipToLayer_SaveLayerFlag });
|
||||
}
|
||||
|
||||
static void do_draw(SkCanvas* canvas) {
|
||||
SkPaint paint;
|
||||
paint.setColor(0xFFFF0000);
|
||||
|
||||
for (int i = 0; i < 20; ++i) {
|
||||
canvas->drawRect({ 15, 15, 290, 40 }, paint);
|
||||
canvas->translate(0, 30);
|
||||
}
|
||||
}
|
||||
|
||||
class UnclippedSaveLayerGM : public skiagm::GM {
|
||||
public:
|
||||
UnclippedSaveLayerGM() { this->setBGColor(SK_ColorWHITE); }
|
||||
|
||||
protected:
|
||||
bool runAsBench() const override { return true; }
|
||||
|
||||
SkString onShortName() override {
|
||||
return SkString("savelayer_unclipped");
|
||||
}
|
||||
|
||||
SkISize onISize() override { return SkISize::Make(320, 640); }
|
||||
|
||||
void onDraw(SkCanvas* canvas) override {
|
||||
const SkScalar L = 10;
|
||||
const SkScalar T = 10;
|
||||
const SkScalar R = 310;
|
||||
const SkScalar B = 630;
|
||||
|
||||
canvas->clipRect({ L, T, R, B });
|
||||
|
||||
SkAutoCanvasRestore acr(canvas, true);
|
||||
save_layer_unclipped(canvas, L, T, R, T + 100);
|
||||
save_layer_unclipped(canvas, L, B - 100, R, B);
|
||||
|
||||
do_draw(canvas);
|
||||
}
|
||||
|
||||
private:
|
||||
using INHERITED = skiagm::GM;
|
||||
};
|
||||
DEF_GM(return new UnclippedSaveLayerGM;)
|
||||
|
||||
DEF_SIMPLE_GM(picture_savelayer, canvas, 320, 640) {
|
||||
SkPaint paint1, paint2, paint3;
|
||||
paint1.setAlphaf(0.5f);
|
||||
paint2.setAlphaf(0.25f);
|
||||
paint3.setColor(0xFFFF0000);
|
||||
SkRect rect1{40, 5, 80, 70}, rect2{5, 40, 70, 80}, rect3{10, 10, 70, 70};
|
||||
// In the future, we might also test the clipped case by allowing i = 0
|
||||
for(int i = 1; i < 2; ++i) {
|
||||
canvas->translate(100 * i, 0);
|
||||
auto flag = i ?
|
||||
(SkCanvas::SaveLayerFlags) SkCanvasPriv::kDontClipToLayer_SaveLayerFlag : 0;
|
||||
canvas->saveLayer(SkCanvas::SaveLayerRec(&rect1, &paint1, nullptr, flag));
|
||||
canvas->saveLayer(SkCanvas::SaveLayerRec(&rect2, &paint2, nullptr, flag));
|
||||
canvas->drawRect(rect3, paint3);
|
||||
canvas->restore();
|
||||
canvas->restore();
|
||||
}
|
||||
};
|
||||
|
||||
// Test kInitWithPrevious_SaveLayerFlag by drawing an image, save a layer with the flag, which
|
||||
// should seed the layer with the image (from below). Then we punch a hole in the layer and
|
||||
// restore with kPlus mode, which should show the mandrill super-bright on the outside, but
|
||||
|
@ -82,10 +82,6 @@ class SkVertices;
|
||||
This approach may be deprecated in the future.
|
||||
*/
|
||||
class SK_API SkCanvas {
|
||||
enum PrivateSaveLayerFlags {
|
||||
kDontClipToLayer_PrivateSaveLayerFlag = 1U << 31,
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
/** Allocates raster SkCanvas that will draw directly into pixels.
|
||||
@ -637,10 +633,6 @@ public:
|
||||
1 << 3, //!< experimental: do not use
|
||||
// instead of matching previous layer's colortype, use F16
|
||||
kF16ColorType = 1 << 4,
|
||||
#ifdef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG
|
||||
kDontClipToLayer_Legacy_SaveLayerFlag =
|
||||
kDontClipToLayer_PrivateSaveLayerFlag, //!< deprecated
|
||||
#endif
|
||||
};
|
||||
|
||||
typedef uint32_t SaveLayerFlags;
|
||||
|
@ -1146,30 +1146,27 @@ void SkCanvas::internalSaveLayer(const SaveLayerRec& rec, SaveLayerStrategy stra
|
||||
newDevice.reset(priorDevice->onCreateDevice(createInfo, paint));
|
||||
}
|
||||
|
||||
bool boundsAffectsClip = !(saveLayerFlags & SkCanvasPriv::kDontClipToLayer_SaveLayerFlag);
|
||||
if (!newDevice) {
|
||||
if (modifiedRec) {
|
||||
// In this case there will be no layer in which to stash the matrix so we need to
|
||||
// revert the prior MCRec to its earlier state.
|
||||
modifiedRec->fMatrix = SkM44(stashedMatrix);
|
||||
}
|
||||
if (boundsAffectsClip) {
|
||||
if (strategy == kNoLayer_SaveLayerStrategy) {
|
||||
// replaceClip() serves two purposes here:
|
||||
// 1. When 'ir' is empty, it forces the top level device to reject all subsequent
|
||||
// nested draw calls.
|
||||
// 2. When 'ir' is not empty, this canvas represents a recording canvas, so the
|
||||
// replaceClip() simulates what a new top-level device's canvas would be in
|
||||
// the non-recording scenario. This allows the canvas to report the expanding
|
||||
// effects of image filters on the temporary clip bounds.
|
||||
UPDATE_DEVICE_CLIP(device->replaceClip(ir));
|
||||
} else {
|
||||
// else the layer device failed to be created, so the saveLayer() effectively
|
||||
// becomes just a save(). The clipRegion() explicitly applies the bounds of the
|
||||
// failed layer, without resetting the clip of the prior device that all subsequent
|
||||
// nested draw calls need to respect.
|
||||
UPDATE_DEVICE_CLIP(device->clipRegion(SkRegion(ir), SkClipOp::kIntersect));
|
||||
}
|
||||
if (strategy == kNoLayer_SaveLayerStrategy) {
|
||||
// replaceClip() serves two purposes here:
|
||||
// 1. When 'ir' is empty, it forces the top level device to reject all subsequent
|
||||
// nested draw calls.
|
||||
// 2. When 'ir' is not empty, this canvas represents a recording canvas, so the
|
||||
// replaceClip() simulates what a new top-level device's canvas would be in
|
||||
// the non-recording scenario. This allows the canvas to report the expanding
|
||||
// effects of image filters on the temporary clip bounds.
|
||||
UPDATE_DEVICE_CLIP(device->replaceClip(ir));
|
||||
} else {
|
||||
// else the layer device failed to be created, so the saveLayer() effectively
|
||||
// becomes just a save(). The clipRegion() explicitly applies the bounds of the
|
||||
// failed layer, without resetting the clip of the prior device that all subsequent
|
||||
// nested draw calls need to respect.
|
||||
UPDATE_DEVICE_CLIP(device->clipRegion(SkRegion(ir), SkClipOp::kIntersect));
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -1177,8 +1174,7 @@ void SkCanvas::internalSaveLayer(const SaveLayerRec& rec, SaveLayerStrategy stra
|
||||
newDevice->setMarkerStack(fMarkerStack.get());
|
||||
DeviceCM* layer = new DeviceCM(newDevice, paint, stashedMatrix);
|
||||
|
||||
// only have a "next" if this new layer doesn't affect the clip (rare)
|
||||
layer->fNext = boundsAffectsClip ? nullptr : fMCRec->fTopLayer;
|
||||
layer->fNext = nullptr;
|
||||
fMCRec->fLayer = layer;
|
||||
fMCRec->fTopLayer = layer; // this field is NOT an owner of layer
|
||||
|
||||
@ -1189,17 +1185,6 @@ void SkCanvas::internalSaveLayer(const SaveLayerRec& rec, SaveLayerStrategy stra
|
||||
|
||||
newDevice->setOrigin(fMCRec->fMatrix, ir.fLeft, ir.fTop);
|
||||
newDevice->androidFramework_setDeviceClipRestriction(&fClipRestrictionRect);
|
||||
|
||||
if (layer->fNext) {
|
||||
// need to punch a hole in the previous device, so we don't draw there, given that
|
||||
// the new top-layer will allow drawing to happen "below" it.
|
||||
SkRegion hole(ir);
|
||||
do {
|
||||
layer = layer->fNext;
|
||||
layer->fDevice->clipRegion(hole, SkClipOp::kDifference);
|
||||
} while (layer->fNext);
|
||||
}
|
||||
|
||||
fQuickRejectBounds = qr_clip_bounds(this->computeDeviceClipBounds());
|
||||
}
|
||||
|
||||
|
@ -26,10 +26,6 @@ private:
|
||||
|
||||
class SkCanvasPriv {
|
||||
public:
|
||||
enum {
|
||||
kDontClipToLayer_SaveLayerFlag = SkCanvas::kDontClipToLayer_PrivateSaveLayerFlag,
|
||||
};
|
||||
|
||||
// The lattice has pointers directly into the readbuffer
|
||||
static bool ReadLattice(SkReadBuffer&, SkCanvas::Lattice*);
|
||||
|
||||
@ -39,8 +35,6 @@ public:
|
||||
// storage must be 4-byte aligned
|
||||
static size_t WriteLattice(void* storage, const SkCanvas::Lattice&);
|
||||
|
||||
static SkCanvas::SaveLayerFlags LegacySaveFlagsToSaveLayerFlags(uint32_t legacySaveFlags);
|
||||
|
||||
static int SaveBehind(SkCanvas* canvas, const SkRect* subset) {
|
||||
return canvas->only_axis_aligned_saveBehind(subset);
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ enum DrawType {
|
||||
RESTORE,
|
||||
ROTATE,
|
||||
SAVE,
|
||||
SAVE_LAYER_SAVEFLAGS_DEPRECATED,
|
||||
SAVE_LAYER_SAVEFLAGS_DEPRECATED_2015_REMOVED_12_2020,
|
||||
SCALE,
|
||||
SET_MATRIX,
|
||||
SKEW,
|
||||
|
@ -22,20 +22,6 @@
|
||||
#include "src/core/SkVerticesPriv.h"
|
||||
#include "src/utils/SkPatchUtils.h"
|
||||
|
||||
// matches old SkCanvas::SaveFlags
|
||||
enum LegacySaveFlags {
|
||||
kClipToLayer_LegacySaveFlags = 0x10,
|
||||
};
|
||||
|
||||
SkCanvas::SaveLayerFlags SkCanvasPriv::LegacySaveFlagsToSaveLayerFlags(uint32_t flags) {
|
||||
uint32_t layerFlags = 0;
|
||||
|
||||
if (0 == (flags & kClipToLayer_LegacySaveFlags)) {
|
||||
layerFlags |= kDontClipToLayer_SaveLayerFlag;
|
||||
}
|
||||
return layerFlags;
|
||||
}
|
||||
|
||||
static const SkRect* get_rect_ptr(SkReadBuffer* reader, SkRect* storage) {
|
||||
if (reader->readBool()) {
|
||||
reader->readRect(storage);
|
||||
@ -559,15 +545,6 @@ void SkPicturePlayback::handleOp(SkReadBuffer* reader,
|
||||
}
|
||||
SkCanvasPriv::SaveBehind(canvas, subset);
|
||||
} break;
|
||||
case SAVE_LAYER_SAVEFLAGS_DEPRECATED: {
|
||||
SkRect storage;
|
||||
const SkRect* boundsPtr = get_rect_ptr(reader, &storage);
|
||||
const SkPaint* paint = fPictureData->optionalPaint(reader);
|
||||
auto flags = SkCanvasPriv::LegacySaveFlagsToSaveLayerFlags(reader->readInt());
|
||||
BREAK_ON_READ_ERROR(reader);
|
||||
|
||||
canvas->saveLayer(SkCanvas::SaveLayerRec(boundsPtr, paint, flags));
|
||||
} break;
|
||||
case SAVE_LAYER_SAVELAYERREC: {
|
||||
SkCanvas::SaveLayerRec rec(nullptr, nullptr, nullptr, 0);
|
||||
const uint32_t flatFlags = reader->readInt();
|
||||
|
@ -190,12 +190,6 @@ struct SaveLayerDrawRestoreNooper {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (match->first<SaveLayer>()->saveLayerFlags &
|
||||
SkCanvasPriv::kDontClipToLayer_SaveLayerFlag) {
|
||||
// can't throw away the layer if set
|
||||
return false;
|
||||
}
|
||||
|
||||
// A SaveLayer's bounds field is just a hint, so we should be free to ignore it.
|
||||
SkPaint* layerPaint = match->first<SaveLayer>()->paint;
|
||||
SkPaint* drawPaint = match->second<SkPaint>();
|
||||
|
@ -125,12 +125,6 @@ DEF_TEST(CanvasState_test_complex_layers, reporter) {
|
||||
};
|
||||
|
||||
const int layerAlpha[] = { 255, 255, 0 };
|
||||
const SkCanvas::SaveLayerFlags flags[] = {
|
||||
static_cast<SkCanvas::SaveLayerFlags>(SkCanvasPriv::kDontClipToLayer_SaveLayerFlag),
|
||||
0,
|
||||
static_cast<SkCanvas::SaveLayerFlags>(SkCanvasPriv::kDontClipToLayer_SaveLayerFlag),
|
||||
};
|
||||
REPORTER_ASSERT(reporter, sizeof(layerAlpha) == sizeof(flags));
|
||||
|
||||
bool (*drawFn)(SkCanvasState* state, float l, float t,
|
||||
float r, float b, int32_t s);
|
||||
@ -164,7 +158,7 @@ DEF_TEST(CanvasState_test_complex_layers, reporter) {
|
||||
}
|
||||
|
||||
// draw a rect within the layer's bounds and again outside the layer's bounds
|
||||
canvas->saveLayer(SkCanvas::SaveLayerRec(&rect, paint.getMaybeNull(), flags[k]));
|
||||
canvas->saveLayer(SkCanvas::SaveLayerRec(&rect, paint.getMaybeNull()));
|
||||
|
||||
if (j) {
|
||||
// Capture from the first Skia.
|
||||
@ -225,12 +219,6 @@ DEF_TEST(CanvasState_test_complex_clips, reporter) {
|
||||
SkRegion::kIntersect_Op,
|
||||
SkRegion::kDifference_Op,
|
||||
};
|
||||
const SkCanvas::SaveLayerFlags flags[] = {
|
||||
static_cast<SkCanvas::SaveLayerFlags>(SkCanvasPriv::kDontClipToLayer_SaveLayerFlag),
|
||||
0,
|
||||
static_cast<SkCanvas::SaveLayerFlags>(SkCanvasPriv::kDontClipToLayer_SaveLayerFlag),
|
||||
};
|
||||
REPORTER_ASSERT(reporter, sizeof(clipOps) == sizeof(flags));
|
||||
|
||||
bool (*drawFn)(SkCanvasState* state, int32_t l, int32_t t,
|
||||
int32_t r, int32_t b, int32_t clipOp,
|
||||
@ -261,7 +249,7 @@ DEF_TEST(CanvasState_test_complex_clips, reporter) {
|
||||
paint.setAlpha(128);
|
||||
for (size_t j = 0; j < SK_ARRAY_COUNT(clipOps); ++j) {
|
||||
SkRect layerBounds = SkRect::Make(layerRect);
|
||||
canvas->saveLayer(SkCanvas::SaveLayerRec(&layerBounds, &paint, flags[j]));
|
||||
canvas->saveLayer(SkCanvas::SaveLayerRec(&layerBounds, &paint));
|
||||
|
||||
if (i) {
|
||||
SkCanvasState* state = SkCanvasStateUtils::CaptureCanvasState(canvas);
|
||||
@ -317,10 +305,6 @@ DEF_TEST(CanvasState_test_soft_clips, reporter) {
|
||||
}
|
||||
|
||||
DEF_TEST(CanvasState_test_saveLayer_clip, reporter) {
|
||||
#ifdef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG
|
||||
static_assert(SkCanvas::kDontClipToLayer_Legacy_SaveLayerFlag ==
|
||||
SkCanvasPriv::kDontClipToLayer_SaveLayerFlag, "");
|
||||
#endif
|
||||
const int WIDTH = 100;
|
||||
const int HEIGHT = 100;
|
||||
const int LAYER_WIDTH = 50;
|
||||
@ -333,20 +317,9 @@ DEF_TEST(CanvasState_test_saveLayer_clip, reporter) {
|
||||
SkRect bounds = SkRect::MakeWH(SkIntToScalar(LAYER_WIDTH), SkIntToScalar(LAYER_HEIGHT));
|
||||
canvas.clipRect(SkRect::MakeWH(SkIntToScalar(WIDTH), SkIntToScalar(HEIGHT)));
|
||||
|
||||
SkIRect devClip;
|
||||
// Check that saveLayer without the kClipToLayer_SaveFlag leaves the clip unchanged.
|
||||
canvas.saveLayer(SkCanvas::SaveLayerRec(&bounds, nullptr,
|
||||
(SkCanvas::SaveLayerFlags) SkCanvasPriv::kDontClipToLayer_SaveLayerFlag));
|
||||
devClip = canvas.getDeviceClipBounds();
|
||||
REPORTER_ASSERT(reporter, canvas.isClipRect());
|
||||
REPORTER_ASSERT(reporter, devClip.width() == WIDTH);
|
||||
REPORTER_ASSERT(reporter, devClip.height() == HEIGHT);
|
||||
canvas.restore();
|
||||
|
||||
// Check that saveLayer with the kClipToLayer_SaveFlag sets the clip
|
||||
// stack to the layer bounds.
|
||||
// Check that saveLayer sets the clip stack to the layer bounds.
|
||||
canvas.saveLayer(&bounds, nullptr);
|
||||
devClip = canvas.getDeviceClipBounds();
|
||||
SkIRect devClip = canvas.getDeviceClipBounds();
|
||||
REPORTER_ASSERT(reporter, canvas.isClipRect());
|
||||
REPORTER_ASSERT(reporter, devClip.width() == LAYER_WIDTH);
|
||||
REPORTER_ASSERT(reporter, devClip.height() == LAYER_HEIGHT);
|
||||
|
Loading…
Reference in New Issue
Block a user