skia2/tools/DDLTileHelper.cpp
Robert Phillips 7a3197bae3 Revert "Fix bug in GM's DDL drawing mode"
This reverts commit 06f69eb296.

Reason for revert: SKPBench dying

Original change's description:
> Fix bug in GM's DDL drawing mode
> 
> Due to how we were constructing the promise images we weren't hitting this before.
> 
> It is possible, when re-inflating the images of an SKP, that a draw occurs to create an image subset. When this occurs it is crucial that the generated opList be added to the appropriate drawing manager (so that it gets copied into the DDL).
> 
> This CL gets rid of the prior hack. It does have the (minor) downside that the SkDDLRecorders are now all created outside of their thread silos.
> 
> Change-Id: Ic6b23a8b68c0d4fe25dd8588c6e2ab65f9f238cf
> Reviewed-on: https://skia-review.googlesource.com/157080
> Reviewed-by: Greg Daniel <egdaniel@google.com>
> Commit-Queue: Robert Phillips <robertphillips@google.com>

TBR=egdaniel@google.com,robertphillips@google.com

Change-Id: Ia52094ce0e356b77b025a7352f2cc728df77d259
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Reviewed-on: https://skia-review.googlesource.com/157223
Reviewed-by: Robert Phillips <robertphillips@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
2018-09-26 21:18:28 +00:00

162 lines
5.2 KiB
C++

/*
* Copyright 2018 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "DDLTileHelper.h"
#include "DDLPromiseImageHelper.h"
#include "SkCanvas.h"
#include "SkDeferredDisplayListRecorder.h"
#include "SkImage_Gpu.h"
#include "SkPicture.h"
#include "SkSurface.h"
#include "SkSurfaceCharacterization.h"
#include "SkTaskGroup.h"
DDLTileHelper::TileData::TileData(sk_sp<SkSurface> s, const SkIRect& clip)
: fSurface(std::move(s))
, fClip(clip) {
SkAssertResult(fSurface->characterize(&fCharacterization));
}
void DDLTileHelper::TileData::createTileSpecificSKP(SkData* compressedPictureData,
const DDLPromiseImageHelper& helper) {
SkASSERT(!fReconstitutedPicture);
// This is bending the DDLRecorder contract! The promise images in the SKP should be
// created by the same recorder used to create the matching DDL.
SkDeferredDisplayListRecorder recorder(fCharacterization);
fReconstitutedPicture = helper.reinflateSKP(&recorder, compressedPictureData, &fPromiseImages);
}
void DDLTileHelper::TileData::createDDL() {
SkASSERT(fReconstitutedPicture);
SkASSERT(!fDisplayList);
SkDeferredDisplayListRecorder recorder(fCharacterization);
// DDL TODO: the DDLRecorder's GrContext isn't initialized until getCanvas is called.
// Maybe set it up in the ctor?
SkCanvas* subCanvas = recorder.getCanvas();
// Because we cheated in createTileSpecificSKP and used the wrong DDLRecorder, the GrContext's
// stored in fReconstitutedPicture's promise images are incorrect. Patch them with the correct
// one now.
for (int i = 0; i < fPromiseImages.count(); ++i) {
GrContext* newContext = subCanvas->getGrContext();
if (fPromiseImages[i]->isTextureBacked()) {
SkImage_Gpu* gpuImage = (SkImage_Gpu*) fPromiseImages[i].get();
gpuImage->resetContext(sk_ref_sp(newContext));
}
}
subCanvas->clipRect(SkRect::MakeWH(fClip.width(), fClip.height()));
subCanvas->translate(-fClip.fLeft, -fClip.fTop);
// Note: in this use case we only render a picture to the deferred canvas
// but, more generally, clients will use arbitrary draw calls.
subCanvas->drawPicture(fReconstitutedPicture);
fDisplayList = recorder.detach();
}
void DDLTileHelper::TileData::draw() {
SkASSERT(fDisplayList);
fSurface->draw(fDisplayList.get());
}
void DDLTileHelper::TileData::compose(SkCanvas* dst) {
sk_sp<SkImage> img = fSurface->makeImageSnapshot();
dst->save();
dst->clipRect(SkRect::Make(fClip));
dst->drawImage(std::move(img), fClip.fLeft, fClip.fTop);
dst->restore();
}
void DDLTileHelper::TileData::reset() {
// TODO: when DDLs are re-renderable we don't need to do this
fDisplayList = nullptr;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
DDLTileHelper::DDLTileHelper(SkCanvas* canvas, const SkIRect& viewport, int numDivisions)
: fNumDivisions(numDivisions) {
SkASSERT(fNumDivisions > 0);
fTiles.reserve(fNumDivisions*fNumDivisions);
int xTileSize = viewport.width()/fNumDivisions;
int yTileSize = viewport.height()/fNumDivisions;
// Create the destination tiles
for (int y = 0, yOff = 0; y < fNumDivisions; ++y, yOff += yTileSize) {
int ySize = (y < fNumDivisions-1) ? yTileSize : viewport.height()-yOff;
for (int x = 0, xOff = 0; x < fNumDivisions; ++x, xOff += xTileSize) {
int xSize = (x < fNumDivisions-1) ? xTileSize : viewport.width()-xOff;
SkIRect clip = SkIRect::MakeXYWH(xOff, yOff, xSize, ySize);
SkASSERT(viewport.contains(clip));
SkImageInfo tileII = SkImageInfo::MakeN32Premul(xSize, ySize);
sk_sp<SkSurface> tileSurface = canvas->makeSurface(tileII);
// TODO: this is here to deal w/ a resource allocator bug (skbug.com/8007). If all
// the DDLs are flushed at the same time (w/o the composition draws) the allocator
// feels free to reuse the backing GrSurfaces!
tileSurface->flush();
fTiles.push_back(TileData(std::move(tileSurface), clip));
}
}
}
void DDLTileHelper::createSKPPerTile(SkData* compressedPictureData,
const DDLPromiseImageHelper& helper) {
for (int i = 0; i < fTiles.count(); ++i) {
fTiles[i].createTileSpecificSKP(compressedPictureData, helper);
}
}
void DDLTileHelper::createDDLsInParallel() {
#if 1
SkTaskGroup().batch(fTiles.count(), [&](int i) { fTiles[i].createDDL(); });
SkTaskGroup().wait();
#else
// Use this code path to debug w/o threads
for (int i = 0; i < fTiles.count(); ++i) {
fTiles[i].createDDL();
}
#endif
}
void DDLTileHelper::drawAllTilesAndFlush(GrContext* context, bool flush) {
for (int i = 0; i < fTiles.count(); ++i) {
fTiles[i].draw();
}
if (flush) {
context->flush();
}
}
void DDLTileHelper::composeAllTiles(SkCanvas* dstCanvas) {
for (int i = 0; i < fTiles.count(); ++i) {
fTiles[i].compose(dstCanvas);
}
}
void DDLTileHelper::resetAllTiles() {
for (int i = 0; i < fTiles.count(); ++i) {
fTiles[i].reset();
}
}