Update DDL testing harness to support drawing DDL w/ integer offsets

This isn't hooked up anywhere but breaks up the omnibus CL.

Change-Id: I15c200e57450e7cc8ee95a3f7969926d0eb8487f
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/333129
Commit-Queue: Robert Phillips <robertphillips@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
This commit is contained in:
Robert Phillips 2020-11-10 08:30:50 -05:00 committed by Skia Commit-Bot
parent e96c19e902
commit 0c0884991d
9 changed files with 70 additions and 29 deletions

View File

@ -1814,7 +1814,8 @@ Result GPUDDLSink::ddlDraw(const Src& src,
// one. About all it can be consistently used for is GrCaps access and 'defaultBackendFormat'
// calls.
constexpr int kNumDivisions = 3;
DDLTileHelper tiles(gpuThreadCtx, dstCharacterization, viewport, kNumDivisions);
DDLTileHelper tiles(gpuThreadCtx, dstCharacterization, viewport, kNumDivisions,
/* addRandomPaddingToDst */ false);
tiles.createBackendTextures(gpuTaskGroup, gpuThreadCtx);
@ -2268,7 +2269,8 @@ Result ViaDDL::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream, SkStrin
canvas->clear(SK_ColorTRANSPARENT);
}
// First, create all the tiles (including their individual dest surfaces)
DDLTileHelper tiles(direct, dstCharacterization, viewport, fNumDivisions);
DDLTileHelper tiles(direct, dstCharacterization, viewport, fNumDivisions,
/* addRandomPaddingToDst */ false);
tiles.createBackendTextures(nullptr, direct);

View File

@ -1007,18 +1007,25 @@ public:
*/
bool characterize(SkSurfaceCharacterization* characterization) const;
/** Draws deferred display list created using SkDeferredDisplayListRecorder.
Has no effect and returns false if SkSurfaceCharacterization stored in
deferredDisplayList is not compatible with SkSurface.
/** Draws the deferred display list created via a SkDeferredDisplayListRecorder.
If the deferred display list is not compatible with this SkSurface, the draw is skipped
and false is return.
raster surface returns false.
The xOffset and yOffset parameters are experimental and, if not both zero, will cause
the draw to be ignored.
When implemented, if xOffset or yOffset are non-zero, the DDL will be drawn offset by that
amount into the surface.
@param deferredDisplayList drawing commands
@param xOffset x-offset at which to draw the DDL
@param yOffset y-offset at which to draw the DDL
@return false if deferredDisplayList is not compatible
example: https://fiddle.skia.org/c/@Surface_draw_2
*/
bool draw(sk_sp<const SkDeferredDisplayList> deferredDisplayList);
bool draw(sk_sp<const SkDeferredDisplayList> deferredDisplayList,
int xOffset = 0,
int yOffset = 0);
protected:
SkSurface(int width, int height, const SkSurfaceProps* surfaceProps);

View File

@ -338,8 +338,12 @@ bool SkSurface::isCompatible(const SkSurfaceCharacterization& characterization)
return asConstSB(this)->onIsCompatible(characterization);
}
bool SkSurface::draw(sk_sp<const SkDeferredDisplayList> ddl) {
return asSB(this)->onDraw(std::move(ddl));
bool SkSurface::draw(sk_sp<const SkDeferredDisplayList> ddl, int xOffset, int yOffset) {
if (xOffset != 0 || yOffset != 0) {
return false; // the offsets currently aren't supported
}
return asSB(this)->onDraw(std::move(ddl), xOffset, yOffset);
}
//////////////////////////////////////////////////////////////////////////////////////

View File

@ -125,7 +125,9 @@ public:
virtual bool onCharacterize(SkSurfaceCharacterization*) const { return false; }
virtual bool onIsCompatible(const SkSurfaceCharacterization&) const { return false; }
virtual bool onDraw(sk_sp<const SkDeferredDisplayList>) { return false; }
virtual bool onDraw(sk_sp<const SkDeferredDisplayList>, int xOffset, int yOffset) {
return false;
}
inline SkCanvas* getCachedCanvas();
inline sk_sp<SkImage> refCachedImage();

View File

@ -355,7 +355,7 @@ bool SkSurface_Gpu::onIsCompatible(const SkSurfaceCharacterization& characteriza
characterization.surfaceProps() == rtc->surfaceProps();
}
bool SkSurface_Gpu::onDraw(sk_sp<const SkDeferredDisplayList> ddl) {
bool SkSurface_Gpu::onDraw(sk_sp<const SkDeferredDisplayList> ddl, int xOffset, int yOffset) {
if (!ddl || !this->isCompatible(ddl->characterization())) {
return false;
}

View File

@ -58,7 +58,7 @@ public:
bool onCharacterize(SkSurfaceCharacterization*) const override;
bool onIsCompatible(const SkSurfaceCharacterization&) const override;
void onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) override;
bool onDraw(sk_sp<const SkDeferredDisplayList>) override;
bool onDraw(sk_sp<const SkDeferredDisplayList>, int xOffset, int yOffset) override;
SkGpuDevice* getDevice() { return fDevice.get(); }

View File

@ -22,11 +22,14 @@
void DDLTileHelper::TileData::init(int id,
GrDirectContext* direct,
const SkSurfaceCharacterization& dstSurfaceCharacterization,
const SkIRect& clip) {
const SkIRect& clip,
const SkIRect& paddingOutsets) {
fID = id;
fClip = clip;
fPaddingOutsets = paddingOutsets;
fCharacterization = dstSurfaceCharacterization.createResized(clip.width(), clip.height());
fCharacterization = dstSurfaceCharacterization.createResized(this->paddedRectSize().width(),
this->paddedRectSize().height());
SkASSERT(fCharacterization.isValid());
GrBackendFormat backendFormat = direct->defaultBackendFormat(fCharacterization.colorType(),
@ -78,6 +81,7 @@ void DDLTileHelper::TileData::createDDL() {
}
}
// We always record the DDL in the (0,0) .. (clipWidth, clipHeight) coordinates
recordingCanvas->clipRect(SkRect::MakeWH(fClip.width(), fClip.height()));
recordingCanvas->translate(-fClip.fLeft, -fClip.fTop);
@ -98,14 +102,15 @@ void DDLTileHelper::createComposeDDL() {
for (int i = 0; i < this->numTiles(); ++i) {
TileData* tile = &fTiles[i];
sk_sp<SkImage> promiseImage = tile->makePromiseImage(&recorder);
sk_sp<SkImage> promiseImage = tile->makePromiseImageForDst(&recorder);
SkIRect clipRect = tile->clipRect();
SkRect dstRect = SkRect::Make(tile->clipRect());
SkIRect srcRect = tile->clipRect();
srcRect.offsetTo(tile->padOffset().x(), tile->padOffset().y());
SkASSERT(clipRect.width() == promiseImage->width() &&
clipRect.height() == promiseImage->height());
SkASSERT(promiseImage->bounds().contains(srcRect));
recordingCanvas->drawImage(promiseImage, clipRect.fLeft, clipRect.fTop);
recordingCanvas->drawImageRect(promiseImage.get(), srcRect, dstRect, nullptr);
}
fComposeDDL = recorder.detach();
@ -148,6 +153,7 @@ void DDLTileHelper::TileData::drawSKPDirectly(GrRecordingContext* context) {
if (fTileSurface) {
SkCanvas* tileCanvas = fTileSurface->getCanvas();
SkASSERT(this->padOffset().isZero() && this->paddedRectSize() == fClip.size());
tileCanvas->clipRect(SkRect::MakeWH(fClip.width(), fClip.height()));
tileCanvas->translate(-fClip.fLeft, -fClip.fTop);
@ -167,7 +173,7 @@ void DDLTileHelper::TileData::draw(GrDirectContext* direct) {
// (maybe in GrDrawingManager::addDDLTarget).
fTileSurface = this->makeWrappedTileDest(direct);
if (fTileSurface) {
fTileSurface->draw(fDisplayList);
fTileSurface->draw(fDisplayList, this->padOffset().x(), this->padOffset().y());
// We can't snap an image here bc, since we're using wrapped backend textures for the
// surfaces, that would incur a copy.
@ -181,14 +187,15 @@ void DDLTileHelper::TileData::reset() {
fTileSurface = nullptr;
}
sk_sp<SkImage> DDLTileHelper::TileData::makePromiseImage(SkDeferredDisplayListRecorder* recorder) {
sk_sp<SkImage> DDLTileHelper::TileData::makePromiseImageForDst(
SkDeferredDisplayListRecorder* recorder) {
SkASSERT(fCallbackContext);
// The promise image gets a ref on the promise callback context
sk_sp<SkImage> promiseImage =
recorder->makePromiseTexture(fCallbackContext->backendFormat(),
fClip.width(),
fClip.height(),
this->paddedRectSize().width(),
this->paddedRectSize().height(),
GrMipmapped::kNo,
GrSurfaceOrigin::kBottomLeft_GrSurfaceOrigin,
fCharacterization.colorType(),
@ -230,7 +237,8 @@ void DDLTileHelper::TileData::DeleteBackendTexture(GrDirectContext*, TileData* t
DDLTileHelper::DDLTileHelper(GrDirectContext* direct,
const SkSurfaceCharacterization& dstChar,
const SkIRect& viewport,
int numDivisions)
int numDivisions,
bool addRandomPaddingToDst)
: fNumDivisions(numDivisions)
, fTiles(numDivisions * numDivisions)
, fDstCharacterization(dstChar) {
@ -239,6 +247,8 @@ DDLTileHelper::DDLTileHelper(GrDirectContext* direct,
int xTileSize = viewport.width()/fNumDivisions;
int yTileSize = viewport.height()/fNumDivisions;
SkRandom rand;
// Create the destination tiles
for (int y = 0, yOff = 0; y < fNumDivisions; ++y, yOff += yTileSize) {
int ySize = (y < fNumDivisions-1) ? yTileSize : viewport.height()-yOff;
@ -250,7 +260,14 @@ DDLTileHelper::DDLTileHelper(GrDirectContext* direct,
SkASSERT(viewport.contains(clip));
fTiles[y*fNumDivisions+x].init(y*fNumDivisions+x, direct, dstChar, clip);
static const uint32_t kMaxPad = 64;
int32_t lPad = addRandomPaddingToDst ? rand.nextRangeU(0, kMaxPad) : 0;
int32_t tPad = addRandomPaddingToDst ? rand.nextRangeU(0, kMaxPad) : 0;
int32_t rPad = addRandomPaddingToDst ? rand.nextRangeU(0, kMaxPad) : 0;
int32_t bPad = addRandomPaddingToDst ? rand.nextRangeU(0, kMaxPad) : 0;
fTiles[y*fNumDivisions+x].init(y*fNumDivisions+x, direct, dstChar, clip,
{lPad, tPad, rPad, bPad});
}
}
}

View File

@ -35,7 +35,8 @@ public:
void init(int id,
GrDirectContext*,
const SkSurfaceCharacterization& dstChar,
const SkIRect& clip);
const SkIRect& clip,
const SkIRect& paddingOutsets);
// Convert the compressedPictureData into an SkPicture replacing each image-index
// with a promise image.
@ -62,10 +63,15 @@ public:
int id() const { return fID; }
SkIRect clipRect() const { return fClip; }
SkISize paddedRectSize() const {
return { fClip.width() + fPaddingOutsets.fLeft + fPaddingOutsets.fRight,
fClip.height() + fPaddingOutsets.fTop + fPaddingOutsets.fBottom };
}
SkIVector padOffset() const { return { fPaddingOutsets.fLeft, fPaddingOutsets.fTop }; }
SkDeferredDisplayList* ddl() { return fDisplayList.get(); }
sk_sp<SkImage> makePromiseImage(SkDeferredDisplayListRecorder*);
sk_sp<SkImage> makePromiseImageForDst(SkDeferredDisplayListRecorder*);
void dropCallbackContext() { fCallbackContext.reset(); }
static void CreateBackendTexture(GrDirectContext*, TileData*);
@ -78,6 +84,7 @@ public:
int fID = -1;
SkIRect fClip; // in the device space of the final SkSurface
SkIRect fPaddingOutsets; // random padding for the output surface
SkSurfaceCharacterization fCharacterization; // characterization for the tile's surface
// The callback context holds (via its SkPromiseImageTexture) the backend texture
@ -99,7 +106,8 @@ public:
DDLTileHelper(GrDirectContext*,
const SkSurfaceCharacterization& dstChar,
const SkIRect& viewport,
int numDivisions);
int numDivisions,
bool addRandomPaddingToDst);
void createSKPPerTile(SkData* compressedPictureData, const DDLPromiseImageHelper&);

View File

@ -269,7 +269,8 @@ static void run_ddl_benchmark(sk_gpu_test::TestContext* testContext, GrDirectCon
promiseImageHelper.uploadAllToGPU(nullptr, context);
DDLTileHelper tiles(context, dstCharacterization, viewport, FLAGS_ddlTilingWidthHeight);
DDLTileHelper tiles(context, dstCharacterization, viewport, FLAGS_ddlTilingWidthHeight,
/* addRandomPaddingToDst */ false);
tiles.createBackendTextures(nullptr, context);