aboutsummaryrefslogtreecommitdiffhomepage
path: root/dm/DMSrcSink.cpp
diff options
context:
space:
mode:
authorGravatar Robert Phillips <robertphillips@google.com>2018-03-26 20:58:04 +0000
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-03-26 20:58:14 +0000
commitf14e833392ed2bddcccc147a53a78d3b5a4ab769 (patch)
tree531c5dc7e166879aaf421e41c1d91c6143a14b58 /dm/DMSrcSink.cpp
parentbd2e2a0cafb0944255635b95663e1d242064b9c3 (diff)
Revert "Switch DDL rendering to be a Via in DM"
This reverts commit bd2e2a0cafb0944255635b95663e1d242064b9c3. Reason for revert: Build-Debian9-Clang-x86_64-Debug-MSAN In file included from ../../../dm/DMSrcSink.cpp:8: ../../../dm/DMSrcSink.h:548:15: error: private field 'fNumDivisions' is not used [-Werror,-Wunused-private-field] const int fNumDivisions; Original change's description: > Switch DDL rendering to be a Via in DM > > This will let us also render the GMs via DDLs. > > Change-Id: I866a5af66d737473f4760dbc9d45053460c42e6e > Reviewed-on: https://skia-review.googlesource.com/116021 > Commit-Queue: Robert Phillips <robertphillips@google.com> > Reviewed-by: Greg Daniel <egdaniel@google.com> > Reviewed-by: Mike Klein <mtklein@google.com> TBR=egdaniel@google.com,mtklein@google.com,robertphillips@google.com Change-Id: Ice07c25ab29c57b2efb193c03e5504a2ae1a0743 No-Presubmit: true No-Tree-Checks: true No-Try: true Reviewed-on: https://skia-review.googlesource.com/116560 Reviewed-by: Robert Phillips <robertphillips@google.com> Commit-Queue: Robert Phillips <robertphillips@google.com>
Diffstat (limited to 'dm/DMSrcSink.cpp')
-rw-r--r--dm/DMSrcSink.cpp375
1 files changed, 4 insertions, 371 deletions
diff --git a/dm/DMSrcSink.cpp b/dm/DMSrcSink.cpp
index b97e9f64a5..1d8aab1fc1 100644
--- a/dm/DMSrcSink.cpp
+++ b/dm/DMSrcSink.cpp
@@ -1153,6 +1153,8 @@ Name ColorCodecSrc::name() const {
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+static const SkRect kSKPViewport = {0, 0, 1000, 1000};
+
SKPSrc::SKPSrc(Path path) : fPath(path) { }
static sk_sp<SkPicture> read_skp(const char* path, const SkDeserialProcs* procs = nullptr) {
@@ -1175,7 +1177,7 @@ Error SKPSrc::draw(SkCanvas* canvas) const {
return SkStringPrintf("Couldn't read %s.", fPath.c_str());
}
- canvas->clipRect(SkRect::MakeWH(FLAGS_skpViewportSize, FLAGS_skpViewportSize));
+ canvas->clipRect(kSKPViewport);
canvas->drawPicture(pic);
return "";
}
@@ -1195,7 +1197,7 @@ static SkRect get_cull_rect_for_skp(const char* path) {
SkISize SKPSrc::size() const {
SkRect viewport = get_cull_rect_for_skp(fPath.c_str());
- if (!viewport.intersect((SkRect::MakeWH(FLAGS_skpViewportSize, FLAGS_skpViewportSize)))) {
+ if (!viewport.intersect(kSKPViewport)) {
return {0, 0};
}
return viewport.roundOut().size();
@@ -2323,375 +2325,6 @@ Error ViaTiles::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream, SkStri
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-ViaDDL::ViaDDL(int numDivisions, Sink* sink)
- : Via(sink)
- , fNumDivisions(numDivisions) {
-}
-
-// This class consolidates tracking & extraction of the original image data from the sources,
-// the upload of said data to the GPU and the fulfillment of promise images.
-class ViaDDL::PromiseImageHelper {
-public:
- class PromiseImageInfo {
- public:
- int fIndex; // index in the 'fImageInfo' array
- uint32_t fOriginalUniqueID; // original ID for deduping
- SkBitmap fBitmap; // CPU-side cache of the contents
-#if SK_SUPPORT_GPU
- GrBackendTexture fBackendTexture; // GPU-side version
-#endif
- };
-
- PromiseImageHelper() : fLocked(false) { }
-
- // This class will hand out pointers to its PromiseImageInfo. This is just some insurance
- // we won't be moving them around.
- void lock() { fLocked = true; }
-
- bool isValidID(int id) const {
- return id >= 0 && id < fImageInfo.count();
- }
-
- const PromiseImageInfo* getInfo(int id) const {
- SkASSERT(fLocked);
- return &fImageInfo[id];
- }
-
- // returns -1 on failure
- int findOrDefineImage(SkImage* image) {
- int preExistingID = this->findImage(image);
- if (preExistingID >= 0) {
- SkASSERT(this->isValidID(preExistingID));
- return preExistingID;
- }
-
- int newID = this->addImage(image);
- SkASSERT(this->isValidID(newID));
- return newID;
- }
-
- void uploadAllToGPU(GrContext* context) {
-#if SK_SUPPORT_GPU
- GrGpu* gpu = context->contextPriv().getGpu();
- SkASSERT(gpu);
-
- for (int i = 0; i < fImageInfo.count(); ++i) {
- // DDL TODO: how can we tell if we need mipmapping!
- fImageInfo[i].fBackendTexture = gpu->createTestingOnlyBackendTexture(
- fImageInfo[i].fBitmap.getPixels(),
- fImageInfo[i].fBitmap.width(),
- fImageInfo[i].fBitmap.height(),
- fImageInfo[i].fBitmap.colorType(),
- false, GrMipMapped::kNo);
- SkAssertResult(fImageInfo[i].fBackendTexture.isValid());
- }
-#endif
- }
-
- void cleanUpVRAM(GrContext* context) {
-#if SK_SUPPORT_GPU
- GrGpu* gpu = context->contextPriv().getGpu();
- SkASSERT(gpu);
-
- for (int i = 0; i < fImageInfo.count(); ++i) {
- gpu->deleteTestingOnlyBackendTexture(fImageInfo[i].fBackendTexture);
- }
-#endif
- }
-
- static void PromiseImageFulfillProc(void* textureContext, GrBackendTexture* outTexture) {
-#if SK_SUPPORT_GPU
- auto imgInfo = static_cast<const PromiseImageInfo*>(textureContext);
-
- SkASSERT(imgInfo->fBackendTexture.isValid());
- *outTexture = imgInfo->fBackendTexture;
-#endif
- }
-
- static void PromiseImageReleaseProc(void* textureContext) {
- // Do nothing. We free all the backend textures at the end in cleanUpVRAM.
- }
-
- static void PromiseImageDoneProc(void* textureContext) {
- // Do nothing.
- }
-
-private:
- // returns -1 if not found
- int findImage(SkImage* image) const {
- for (int i = 0; i < fImageInfo.count(); ++i) {
- if (fImageInfo[i].fOriginalUniqueID == image->uniqueID()) {
- SkASSERT(fImageInfo[i].fIndex == i);
- SkASSERT(this->isValidID(i) && this->isValidID(fImageInfo[i].fIndex));
- return i;
- }
- }
- return -1;
- }
-
- // returns -1 on failure
- int addImage(SkImage* image) {
- SkASSERT(!fLocked);
-
- sk_sp<SkImage> rasterImage = image->makeRasterImage(); // force decoding of lazy images
-
- SkImageInfo ii = SkImageInfo::Make(rasterImage->width(), rasterImage->height(),
- rasterImage->colorType(), rasterImage->alphaType(),
- rasterImage->refColorSpace());
-
- SkBitmap bm;
- bm.allocPixels(ii);
-
- if (!rasterImage->readPixels(bm.pixmap(), 0, 0)) {
- return -1;
- }
-
- bm.setImmutable();
-
- PromiseImageInfo newImageInfo;
- newImageInfo.fIndex = fImageInfo.count();
- newImageInfo.fOriginalUniqueID = image->uniqueID();
- newImageInfo.fBitmap = bm;
- /* fBackendTexture is filled in by uploadAllToGPU */
-
- fImageInfo.push_back(newImageInfo);
- SkASSERT(newImageInfo.fIndex == fImageInfo.count()-1);
- return fImageInfo.count()-1;
- }
-
- SkTArray<PromiseImageInfo> fImageInfo;
- bool fLocked; // are additions still allowed
-};
-
-// TileData class encapsulates the information and behavior for a single tile/thread in
-// a DDL rendering.
-class ViaDDL::TileData {
-public:
- // Note: we could just pass in surface characterization
- TileData(sk_sp<SkSurface> surf, const SkIRect& clip)
- : fSurface(std::move(surf))
- , fClip(clip) {
- SkAssertResult(fSurface->characterize(&fCharacterization));
- }
-
- // This method operates in parallel
- // In each thread we will reconvert the compressedPictureData into an SkPicture
- // replacing each image-index with a promise image.
- void preprocess(SkData* compressedPictureData, const PromiseImageHelper& helper) {
- 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();
-
- sk_sp<SkPicture> reconstitutedPicture;
-
- {
- PromiseImageCallbackContext callbackCtx = { &helper, &recorder };
-
- SkDeserialProcs procs;
- procs.fImageCtx = &callbackCtx;
- procs.fImageProc = PromiseImageCreator;
-
- reconstitutedPicture = SkPicture::MakeFromData(compressedPictureData, &procs);
- if (!reconstitutedPicture) {
- return;
- }
- }
-
- 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(reconstitutedPicture);
-
- fDisplayList = recorder.detach();
- }
-
- // This method operates serially and replays the recorded DDL into the tile surface.
- void draw() {
- fSurface->draw(fDisplayList.get());
- }
-
- // This method also operates serially and composes the results of replaying the DDL into
- // the final destination surface.
- void 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();
- }
-
-private:
- // This class lets us pass the collected image information and the DDLRecorder to the
- // promise_image_creator callback when reconstituting a deflated SKP for a particular tile
- // (i.e., in a thread).
- class PromiseImageCallbackContext {
- public:
- const PromiseImageHelper* fHelper;
- SkDeferredDisplayListRecorder* fRecorder;
- };
-
- // This generates promise images to replace the indices in the compressed picture. This
- // reconstitution is performed separately in each thread so we end of with multiple
- // promise image referring to the same GrBackendTexture.
- // DDL TODO: Having multiple promise images using the same GrBackendTexture won't work in
- // Vulkan! Move creation of the promise images to the main thread & SkImage.
- static sk_sp<SkImage> PromiseImageCreator(const void* rawData, size_t length, void* ctxIn) {
-#if SK_SUPPORT_GPU
- PromiseImageCallbackContext* ctx = static_cast<PromiseImageCallbackContext*>(ctxIn);
- const PromiseImageHelper* helper = ctx->fHelper;
- SkDeferredDisplayListRecorder* recorder = ctx->fRecorder;
-
- SkASSERT(length == sizeof(int));
-
- const int* indexPtr = static_cast<const int*>(rawData);
- SkASSERT(helper->isValidID(*indexPtr));
-
- const PromiseImageHelper::PromiseImageInfo* curImage = helper->getInfo(*indexPtr);
- SkASSERT(curImage->fIndex == *indexPtr);
-
- GrBackendFormat backendFormat = curImage->fBackendTexture.format();
-
- // DDL TODO: sort out mipmapping
- sk_sp<SkImage> image = recorder->makePromiseTexture(
- backendFormat,
- curImage->fBitmap.width(),
- curImage->fBitmap.height(),
- GrMipMapped::kNo,
- GrSurfaceOrigin::kTopLeft_GrSurfaceOrigin,
- curImage->fBitmap.colorType(),
- curImage->fBitmap.alphaType(),
- curImage->fBitmap.refColorSpace(),
- PromiseImageHelper::PromiseImageFulfillProc,
- PromiseImageHelper::PromiseImageReleaseProc,
- PromiseImageHelper::PromiseImageDoneProc,
- (void*) curImage);
- SkASSERT(image);
- return image;
-#else
- return nullptr;
-#endif
- }
-
- sk_sp<SkSurface> fSurface;
- SkIRect fClip; // in the device space of the dest canvas
- std::unique_ptr<SkDeferredDisplayList> fDisplayList;
- SkSurfaceCharacterization fCharacterization;
-};
-
-Error ViaDDL::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const {
-#if SK_SUPPORT_GPU
- auto size = src.size();
- SkPictureRecorder recorder;
- Error err = src.draw(recorder.beginRecording(SkIntToScalar(size.width()),
- SkIntToScalar(size.height())));
- if (!err.isEmpty()) {
- return err;
- }
- sk_sp<SkPicture> inputPicture(recorder.finishRecordingAsPicture());
-
- // this is our ultimate final drawing area/rect
- SkIRect viewport = SkIRect::MakeWH(size.fWidth, size.fHeight);
-
- PromiseImageHelper helper;
- sk_sp<SkData> compressedPictureData;
-
- // Convert the SkPicture into SkData replacing all the SkImages with an index.
- {
- SkSerialProcs procs;
-
- procs.fImageCtx = &helper;
- procs.fImageProc = [](SkImage* image, void* ctx) -> sk_sp<SkData> {
- auto helper = static_cast<PromiseImageHelper*>(ctx);
-
- int id = helper->findOrDefineImage(image);
- if (id >= 0) {
- SkASSERT(helper->isValidID(id));
- return SkData::MakeWithCopy(&id, sizeof(id));
- }
-
- return nullptr;
- };
-
- compressedPictureData = inputPicture->serialize(&procs);
- if (!compressedPictureData) {
- return SkStringPrintf("ViaDDL: Couldn't deflate SkPicture");
- }
- }
-
- helper.lock(); // after this point no more images should be added to the helper
-
- return draw_to_canvas(fSink.get(), bitmap, stream, log, size,
- [&](SkCanvas* canvas) -> Error {
- GrContext* context = canvas->getGrContext();
- if (!context || !context->contextPriv().getGpu()) {
- return SkStringPrintf("DDLs are GPU only");
- }
-
- helper.uploadAllToGPU(context);
-
- int xTileSize = viewport.width()/fNumDivisions;
- int yTileSize = viewport.height()/fNumDivisions;
-
- SkTArray<TileData> tileData;
- tileData.reserve(fNumDivisions*fNumDivisions);
-
- // First, 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);
-
- tileData.push_back(TileData(canvas->makeSurface(tileII), clip));
- }
- }
-
- // Second, run the cpu pre-processing in threads
- SkTaskGroup().batch(tileData.count(), [&](int i) {
- tileData[i].preprocess(compressedPictureData.get(), helper);
- });
-
- // Third, synchronously render the display lists into the dest tiles
- // TODO: it would be cool to not wait until all the tiles are drawn to begin
- // drawing to the GPU and composing to the final surface
- for (int i = 0; i < tileData.count(); ++i) {
- tileData[i].draw();
- }
-
- // Finally, compose the drawn tiles into the result
- // Note: the separation between the tiles and the final composition better
- // matches Chrome but costs us a copy
- for (int i = 0; i < tileData.count(); ++i) {
- tileData[i].compose(canvas);
- }
-
- // All promise images need to be fulfilled before leaving this method since we
- // are about to delete their backing GrBackendTextures
- // DDL TODO: remove the cleanUpVRAM method and use the release & done
- // callbacks.
- GrGpu* gpu = context->contextPriv().getGpu();
- gpu->testingOnly_flushGpuAndSync();
-
- helper.cleanUpVRAM(context);
- return "";
- });
-#else
- return "";
-#endif
-}
-
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
Error ViaPicture::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const {
auto size = src.size();
return draw_to_canvas(fSink.get(), bitmap, stream, log, size, [&](SkCanvas* canvas) -> Error {