From f14e833392ed2bddcccc147a53a78d3b5a4ab769 Mon Sep 17 00:00:00 2001 From: Robert Phillips Date: Mon, 26 Mar 2018 20:58:04 +0000 Subject: 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 > Reviewed-by: Greg Daniel > Reviewed-by: Mike Klein 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 Commit-Queue: Robert Phillips --- dm/DMSrcSink.cpp | 375 +------------------------------------------------------ 1 file changed, 4 insertions(+), 371 deletions(-) (limited to 'dm/DMSrcSink.cpp') 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 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(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 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 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 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 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 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 PromiseImageCreator(const void* rawData, size_t length, void* ctxIn) { -#if SK_SUPPORT_GPU - PromiseImageCallbackContext* ctx = static_cast(ctxIn); - const PromiseImageHelper* helper = ctx->fHelper; - SkDeferredDisplayListRecorder* recorder = ctx->fRecorder; - - SkASSERT(length == sizeof(int)); - - const int* indexPtr = static_cast(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 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 fSurface; - SkIRect fClip; // in the device space of the dest canvas - std::unique_ptr 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 inputPicture(recorder.finishRecordingAsPicture()); - - // this is our ultimate final drawing area/rect - SkIRect viewport = SkIRect::MakeWH(size.fWidth, size.fHeight); - - PromiseImageHelper helper; - sk_sp 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 { - auto helper = static_cast(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.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 { -- cgit v1.2.3