1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2018 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "tools/DDLTileHelper.h" 9cb93a386Sopenharmony_ci 10cb93a386Sopenharmony_ci#include "include/core/SkCanvas.h" 11cb93a386Sopenharmony_ci#include "include/core/SkDeferredDisplayListRecorder.h" 12cb93a386Sopenharmony_ci#include "include/core/SkPicture.h" 13cb93a386Sopenharmony_ci#include "include/core/SkSurface.h" 14cb93a386Sopenharmony_ci#include "include/core/SkSurfaceCharacterization.h" 15cb93a386Sopenharmony_ci#include "include/gpu/GrDirectContext.h" 16cb93a386Sopenharmony_ci#include "src/core/SkDeferredDisplayListPriv.h" 17cb93a386Sopenharmony_ci#include "src/core/SkTaskGroup.h" 18cb93a386Sopenharmony_ci#include "src/gpu/GrDirectContextPriv.h" 19cb93a386Sopenharmony_ci#include "src/image/SkImage_Gpu.h" 20cb93a386Sopenharmony_ci#include "tools/DDLPromiseImageHelper.h" 21cb93a386Sopenharmony_ci 22cb93a386Sopenharmony_civoid DDLTileHelper::TileData::init(int id, 23cb93a386Sopenharmony_ci GrDirectContext* direct, 24cb93a386Sopenharmony_ci const SkSurfaceCharacterization& dstSurfaceCharacterization, 25cb93a386Sopenharmony_ci const SkIRect& clip, 26cb93a386Sopenharmony_ci const SkIRect& paddingOutsets) { 27cb93a386Sopenharmony_ci fID = id; 28cb93a386Sopenharmony_ci fClip = clip; 29cb93a386Sopenharmony_ci fPaddingOutsets = paddingOutsets; 30cb93a386Sopenharmony_ci 31cb93a386Sopenharmony_ci fPlaybackChar = dstSurfaceCharacterization.createResized(this->paddedRectSize().width(), 32cb93a386Sopenharmony_ci this->paddedRectSize().height()); 33cb93a386Sopenharmony_ci SkASSERT(fPlaybackChar.isValid()); 34cb93a386Sopenharmony_ci 35cb93a386Sopenharmony_ci SkDEBUGCODE(const GrCaps* caps = direct->priv().caps()); 36cb93a386Sopenharmony_ci SkASSERT(caps->isFormatTexturable(fPlaybackChar.backendFormat(), 37cb93a386Sopenharmony_ci fPlaybackChar.backendFormat().textureType())); 38cb93a386Sopenharmony_ci 39cb93a386Sopenharmony_ci fCallbackContext.reset(new PromiseImageCallbackContext(direct, fPlaybackChar.backendFormat())); 40cb93a386Sopenharmony_ci} 41cb93a386Sopenharmony_ci 42cb93a386Sopenharmony_ciDDLTileHelper::TileData::TileData() {} 43cb93a386Sopenharmony_ciDDLTileHelper::TileData::~TileData() {} 44cb93a386Sopenharmony_ci 45cb93a386Sopenharmony_civoid DDLTileHelper::TileData::createDDL(const SkPicture* picture) { 46cb93a386Sopenharmony_ci SkASSERT(!fDisplayList && picture); 47cb93a386Sopenharmony_ci 48cb93a386Sopenharmony_ci auto recordingChar = fPlaybackChar.createResized(fClip.width(), fClip.height()); 49cb93a386Sopenharmony_ci SkASSERT(recordingChar.isValid()); 50cb93a386Sopenharmony_ci 51cb93a386Sopenharmony_ci SkDeferredDisplayListRecorder recorder(recordingChar); 52cb93a386Sopenharmony_ci 53cb93a386Sopenharmony_ci // DDL TODO: the DDLRecorder's rContext isn't initialized until getCanvas is called. 54cb93a386Sopenharmony_ci // Maybe set it up in the ctor? 55cb93a386Sopenharmony_ci SkCanvas* recordingCanvas = recorder.getCanvas(); 56cb93a386Sopenharmony_ci 57cb93a386Sopenharmony_ci // We always record the DDL in the (0,0) .. (clipWidth, clipHeight) coordinates 58cb93a386Sopenharmony_ci recordingCanvas->clipRect(SkRect::MakeWH(fClip.width(), fClip.height())); 59cb93a386Sopenharmony_ci recordingCanvas->translate(-fClip.fLeft, -fClip.fTop); 60cb93a386Sopenharmony_ci 61cb93a386Sopenharmony_ci // Note: in this use case we only render a picture to the deferred canvas 62cb93a386Sopenharmony_ci // but, more generally, clients will use arbitrary draw calls. 63cb93a386Sopenharmony_ci recordingCanvas->drawPicture(picture); 64cb93a386Sopenharmony_ci 65cb93a386Sopenharmony_ci fDisplayList = recorder.detach(); 66cb93a386Sopenharmony_ci} 67cb93a386Sopenharmony_ci 68cb93a386Sopenharmony_civoid DDLTileHelper::createComposeDDL() { 69cb93a386Sopenharmony_ci SkASSERT(!fComposeDDL); 70cb93a386Sopenharmony_ci 71cb93a386Sopenharmony_ci SkDeferredDisplayListRecorder recorder(fDstCharacterization); 72cb93a386Sopenharmony_ci 73cb93a386Sopenharmony_ci SkCanvas* recordingCanvas = recorder.getCanvas(); 74cb93a386Sopenharmony_ci 75cb93a386Sopenharmony_ci for (int i = 0; i < this->numTiles(); ++i) { 76cb93a386Sopenharmony_ci TileData* tile = &fTiles[i]; 77cb93a386Sopenharmony_ci if (!tile->initialized()) { 78cb93a386Sopenharmony_ci continue; 79cb93a386Sopenharmony_ci } 80cb93a386Sopenharmony_ci 81cb93a386Sopenharmony_ci sk_sp<SkImage> promiseImage = tile->makePromiseImageForDst( 82cb93a386Sopenharmony_ci recordingCanvas->recordingContext()->threadSafeProxy()); 83cb93a386Sopenharmony_ci 84cb93a386Sopenharmony_ci SkRect dstRect = SkRect::Make(tile->clipRect()); 85cb93a386Sopenharmony_ci SkIRect srcRect = tile->clipRect(); 86cb93a386Sopenharmony_ci srcRect.offsetTo(tile->padOffset().x(), tile->padOffset().y()); 87cb93a386Sopenharmony_ci 88cb93a386Sopenharmony_ci SkASSERT(promiseImage->bounds().contains(srcRect)); 89cb93a386Sopenharmony_ci 90cb93a386Sopenharmony_ci recordingCanvas->drawImageRect(promiseImage.get(), SkRect::Make(srcRect), dstRect, 91cb93a386Sopenharmony_ci SkSamplingOptions(), nullptr, 92cb93a386Sopenharmony_ci SkCanvas::kStrict_SrcRectConstraint); 93cb93a386Sopenharmony_ci } 94cb93a386Sopenharmony_ci 95cb93a386Sopenharmony_ci fComposeDDL = recorder.detach(); 96cb93a386Sopenharmony_ci SkASSERT(fComposeDDL); 97cb93a386Sopenharmony_ci} 98cb93a386Sopenharmony_ci 99cb93a386Sopenharmony_civoid DDLTileHelper::TileData::precompile(GrDirectContext* direct) { 100cb93a386Sopenharmony_ci if (!this->initialized()) { 101cb93a386Sopenharmony_ci return; 102cb93a386Sopenharmony_ci } 103cb93a386Sopenharmony_ci 104cb93a386Sopenharmony_ci SkASSERT(fDisplayList); 105cb93a386Sopenharmony_ci 106cb93a386Sopenharmony_ci SkDeferredDisplayList::ProgramIterator iter(direct, fDisplayList.get()); 107cb93a386Sopenharmony_ci for (; !iter.done(); iter.next()) { 108cb93a386Sopenharmony_ci iter.compile(); 109cb93a386Sopenharmony_ci } 110cb93a386Sopenharmony_ci} 111cb93a386Sopenharmony_ci 112cb93a386Sopenharmony_cisk_sp<SkSurface> DDLTileHelper::TileData::makeWrappedTileDest(GrRecordingContext* rContext) { 113cb93a386Sopenharmony_ci SkASSERT(fCallbackContext && fCallbackContext->promiseImageTexture()); 114cb93a386Sopenharmony_ci 115cb93a386Sopenharmony_ci auto promiseImageTexture = fCallbackContext->promiseImageTexture(); 116cb93a386Sopenharmony_ci if (!promiseImageTexture->backendTexture().isValid()) { 117cb93a386Sopenharmony_ci return nullptr; 118cb93a386Sopenharmony_ci } 119cb93a386Sopenharmony_ci 120cb93a386Sopenharmony_ci // Here we are, unfortunately, aliasing the backend texture held by the SkPromiseImageTexture. 121cb93a386Sopenharmony_ci // Both the tile's destination surface and the promise image used to draw the tile will be 122cb93a386Sopenharmony_ci // backed by the same backendTexture - unbeknownst to Ganesh. 123cb93a386Sopenharmony_ci return SkSurface::MakeFromBackendTexture(rContext, 124cb93a386Sopenharmony_ci promiseImageTexture->backendTexture(), 125cb93a386Sopenharmony_ci fPlaybackChar.origin(), 126cb93a386Sopenharmony_ci fPlaybackChar.sampleCount(), 127cb93a386Sopenharmony_ci fPlaybackChar.colorType(), 128cb93a386Sopenharmony_ci fPlaybackChar.refColorSpace(), 129cb93a386Sopenharmony_ci &fPlaybackChar.surfaceProps()); 130cb93a386Sopenharmony_ci} 131cb93a386Sopenharmony_ci 132cb93a386Sopenharmony_civoid DDLTileHelper::TileData::drawSKPDirectly(GrDirectContext* dContext, 133cb93a386Sopenharmony_ci const SkPicture* picture) { 134cb93a386Sopenharmony_ci SkASSERT(!fDisplayList && !fTileSurface && picture); 135cb93a386Sopenharmony_ci 136cb93a386Sopenharmony_ci fTileSurface = this->makeWrappedTileDest(dContext); 137cb93a386Sopenharmony_ci if (fTileSurface) { 138cb93a386Sopenharmony_ci SkCanvas* tileCanvas = fTileSurface->getCanvas(); 139cb93a386Sopenharmony_ci 140cb93a386Sopenharmony_ci SkASSERT(this->padOffset().isZero() && this->paddedRectSize() == fClip.size()); 141cb93a386Sopenharmony_ci tileCanvas->clipRect(SkRect::MakeWH(fClip.width(), fClip.height())); 142cb93a386Sopenharmony_ci tileCanvas->translate(-fClip.fLeft, -fClip.fTop); 143cb93a386Sopenharmony_ci 144cb93a386Sopenharmony_ci tileCanvas->drawPicture(picture); 145cb93a386Sopenharmony_ci 146cb93a386Sopenharmony_ci // We can't snap an image here bc, since we're using wrapped backend textures for the 147cb93a386Sopenharmony_ci // surfaces, that would incur a copy. 148cb93a386Sopenharmony_ci } 149cb93a386Sopenharmony_ci} 150cb93a386Sopenharmony_ci 151cb93a386Sopenharmony_civoid DDLTileHelper::TileData::draw(GrDirectContext* direct) { 152cb93a386Sopenharmony_ci SkASSERT(fDisplayList && !fTileSurface); 153cb93a386Sopenharmony_ci 154cb93a386Sopenharmony_ci fTileSurface = this->makeWrappedTileDest(direct); 155cb93a386Sopenharmony_ci if (fTileSurface) { 156cb93a386Sopenharmony_ci fTileSurface->draw(fDisplayList, this->padOffset().x(), this->padOffset().y()); 157cb93a386Sopenharmony_ci 158cb93a386Sopenharmony_ci // We can't snap an image here bc, since we're using wrapped backend textures for the 159cb93a386Sopenharmony_ci // surfaces, that would incur a copy. 160cb93a386Sopenharmony_ci } 161cb93a386Sopenharmony_ci} 162cb93a386Sopenharmony_ci 163cb93a386Sopenharmony_civoid DDLTileHelper::TileData::reset() { 164cb93a386Sopenharmony_ci // TODO: when DDLs are re-renderable we don't need to do this 165cb93a386Sopenharmony_ci fDisplayList = nullptr; 166cb93a386Sopenharmony_ci 167cb93a386Sopenharmony_ci fTileSurface = nullptr; 168cb93a386Sopenharmony_ci} 169cb93a386Sopenharmony_ci 170cb93a386Sopenharmony_cisk_sp<SkImage> DDLTileHelper::TileData::makePromiseImageForDst( 171cb93a386Sopenharmony_ci sk_sp<GrContextThreadSafeProxy> threadSafeProxy) { 172cb93a386Sopenharmony_ci SkASSERT(fCallbackContext); 173cb93a386Sopenharmony_ci 174cb93a386Sopenharmony_ci // The promise image gets a ref on the promise callback context 175cb93a386Sopenharmony_ci sk_sp<SkImage> promiseImage = 176cb93a386Sopenharmony_ci SkImage::MakePromiseTexture(std::move(threadSafeProxy), 177cb93a386Sopenharmony_ci fCallbackContext->backendFormat(), 178cb93a386Sopenharmony_ci this->paddedRectSize(), 179cb93a386Sopenharmony_ci GrMipmapped::kNo, 180cb93a386Sopenharmony_ci GrSurfaceOrigin::kBottomLeft_GrSurfaceOrigin, 181cb93a386Sopenharmony_ci fPlaybackChar.colorType(), 182cb93a386Sopenharmony_ci kPremul_SkAlphaType, 183cb93a386Sopenharmony_ci fPlaybackChar.refColorSpace(), 184cb93a386Sopenharmony_ci PromiseImageCallbackContext::PromiseImageFulfillProc, 185cb93a386Sopenharmony_ci PromiseImageCallbackContext::PromiseImageReleaseProc, 186cb93a386Sopenharmony_ci (void*)this->refCallbackContext().release()); 187cb93a386Sopenharmony_ci fCallbackContext->wasAddedToImage(); 188cb93a386Sopenharmony_ci 189cb93a386Sopenharmony_ci return promiseImage; 190cb93a386Sopenharmony_ci} 191cb93a386Sopenharmony_ci 192cb93a386Sopenharmony_civoid DDLTileHelper::TileData::CreateBackendTexture(GrDirectContext* direct, TileData* tile) { 193cb93a386Sopenharmony_ci SkASSERT(tile->fCallbackContext && !tile->fCallbackContext->promiseImageTexture()); 194cb93a386Sopenharmony_ci 195cb93a386Sopenharmony_ci const SkSurfaceCharacterization& c = tile->fPlaybackChar; 196cb93a386Sopenharmony_ci GrBackendTexture beTex = direct->createBackendTexture(c.width(), c.height(), c.colorType(), 197cb93a386Sopenharmony_ci GrMipMapped(c.isMipMapped()), 198cb93a386Sopenharmony_ci GrRenderable::kYes); 199cb93a386Sopenharmony_ci tile->fCallbackContext->setBackendTexture(beTex); 200cb93a386Sopenharmony_ci} 201cb93a386Sopenharmony_ci 202cb93a386Sopenharmony_civoid DDLTileHelper::TileData::DeleteBackendTexture(GrDirectContext*, TileData* tile) { 203cb93a386Sopenharmony_ci if (!tile->initialized()) { 204cb93a386Sopenharmony_ci return; 205cb93a386Sopenharmony_ci } 206cb93a386Sopenharmony_ci 207cb93a386Sopenharmony_ci SkASSERT(tile->fCallbackContext); 208cb93a386Sopenharmony_ci 209cb93a386Sopenharmony_ci // TODO: it seems that, on the Linux bots, backend texture creation is failing 210cb93a386Sopenharmony_ci // a lot (skbug.com/10142) 211cb93a386Sopenharmony_ci SkASSERT(!tile->fCallbackContext->promiseImageTexture() || 212cb93a386Sopenharmony_ci tile->fCallbackContext->promiseImageTexture()->backendTexture().isValid()); 213cb93a386Sopenharmony_ci 214cb93a386Sopenharmony_ci tile->fTileSurface = nullptr; 215cb93a386Sopenharmony_ci 216cb93a386Sopenharmony_ci SkASSERT(tile->fCallbackContext->unique()); 217cb93a386Sopenharmony_ci tile->fCallbackContext.reset(); 218cb93a386Sopenharmony_ci} 219cb93a386Sopenharmony_ci 220cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////////////////////////// 221cb93a386Sopenharmony_ci 222cb93a386Sopenharmony_ciDDLTileHelper::DDLTileHelper(GrDirectContext* direct, 223cb93a386Sopenharmony_ci const SkSurfaceCharacterization& dstChar, 224cb93a386Sopenharmony_ci const SkIRect& viewport, 225cb93a386Sopenharmony_ci int numXDivisions, int numYDivisions, 226cb93a386Sopenharmony_ci bool addRandomPaddingToDst) 227cb93a386Sopenharmony_ci : fNumXDivisions(numXDivisions) 228cb93a386Sopenharmony_ci , fNumYDivisions(numYDivisions) 229cb93a386Sopenharmony_ci , fTiles(numXDivisions * numYDivisions) 230cb93a386Sopenharmony_ci , fDstCharacterization(dstChar) { 231cb93a386Sopenharmony_ci SkASSERT(fNumXDivisions > 0 && fNumYDivisions > 0); 232cb93a386Sopenharmony_ci 233cb93a386Sopenharmony_ci int xTileSize = viewport.width()/fNumXDivisions; 234cb93a386Sopenharmony_ci int yTileSize = viewport.height()/fNumYDivisions; 235cb93a386Sopenharmony_ci 236cb93a386Sopenharmony_ci SkRandom rand; 237cb93a386Sopenharmony_ci 238cb93a386Sopenharmony_ci // Create the destination tiles 239cb93a386Sopenharmony_ci for (int y = 0, yOff = 0; y < fNumYDivisions; ++y, yOff += yTileSize) { 240cb93a386Sopenharmony_ci int ySize = (y < fNumYDivisions-1) ? yTileSize : viewport.height()-yOff; 241cb93a386Sopenharmony_ci 242cb93a386Sopenharmony_ci for (int x = 0, xOff = 0; x < fNumXDivisions; ++x, xOff += xTileSize) { 243cb93a386Sopenharmony_ci int xSize = (x < fNumXDivisions-1) ? xTileSize : viewport.width()-xOff; 244cb93a386Sopenharmony_ci 245cb93a386Sopenharmony_ci SkIRect clip = SkIRect::MakeXYWH(xOff, yOff, xSize, ySize); 246cb93a386Sopenharmony_ci 247cb93a386Sopenharmony_ci SkASSERT(viewport.contains(clip)); 248cb93a386Sopenharmony_ci 249cb93a386Sopenharmony_ci static const uint32_t kMaxPad = 64; 250cb93a386Sopenharmony_ci int32_t lPad = addRandomPaddingToDst ? rand.nextRangeU(0, kMaxPad) : 0; 251cb93a386Sopenharmony_ci int32_t tPad = addRandomPaddingToDst ? rand.nextRangeU(0, kMaxPad) : 0; 252cb93a386Sopenharmony_ci int32_t rPad = addRandomPaddingToDst ? rand.nextRangeU(0, kMaxPad) : 0; 253cb93a386Sopenharmony_ci int32_t bPad = addRandomPaddingToDst ? rand.nextRangeU(0, kMaxPad) : 0; 254cb93a386Sopenharmony_ci 255cb93a386Sopenharmony_ci fTiles[y*fNumXDivisions+x].init(y*fNumXDivisions+x, direct, dstChar, clip, 256cb93a386Sopenharmony_ci {lPad, tPad, rPad, bPad}); 257cb93a386Sopenharmony_ci } 258cb93a386Sopenharmony_ci } 259cb93a386Sopenharmony_ci} 260cb93a386Sopenharmony_ci 261cb93a386Sopenharmony_civoid DDLTileHelper::createDDLsInParallel(SkPicture* picture) { 262cb93a386Sopenharmony_ci#if 1 263cb93a386Sopenharmony_ci SkTaskGroup().batch(this->numTiles(), [&](int i) { 264cb93a386Sopenharmony_ci fTiles[i].createDDL(picture); 265cb93a386Sopenharmony_ci }); 266cb93a386Sopenharmony_ci SkTaskGroup().add([this]{ this->createComposeDDL(); }); 267cb93a386Sopenharmony_ci SkTaskGroup().wait(); 268cb93a386Sopenharmony_ci#else 269cb93a386Sopenharmony_ci // Use this code path to debug w/o threads 270cb93a386Sopenharmony_ci for (int i = 0; i < this->numTiles(); ++i) { 271cb93a386Sopenharmony_ci fTiles[i].createDDL(picture); 272cb93a386Sopenharmony_ci } 273cb93a386Sopenharmony_ci this->createComposeDDL(); 274cb93a386Sopenharmony_ci#endif 275cb93a386Sopenharmony_ci} 276cb93a386Sopenharmony_ci 277cb93a386Sopenharmony_ci// On the gpu thread: 278cb93a386Sopenharmony_ci// precompile any programs 279cb93a386Sopenharmony_ci// replay the DDL into a surface to make the tile image 280cb93a386Sopenharmony_ci// compose the tile image into the main canvas 281cb93a386Sopenharmony_cistatic void do_gpu_stuff(GrDirectContext* direct, DDLTileHelper::TileData* tile) { 282cb93a386Sopenharmony_ci 283cb93a386Sopenharmony_ci // TODO: schedule program compilation as their own tasks 284cb93a386Sopenharmony_ci tile->precompile(direct); 285cb93a386Sopenharmony_ci 286cb93a386Sopenharmony_ci tile->draw(direct); 287cb93a386Sopenharmony_ci 288cb93a386Sopenharmony_ci tile->dropDDL(); 289cb93a386Sopenharmony_ci} 290cb93a386Sopenharmony_ci 291cb93a386Sopenharmony_ci// We expect to have more than one recording thread but just one gpu thread 292cb93a386Sopenharmony_civoid DDLTileHelper::kickOffThreadedWork(SkTaskGroup* recordingTaskGroup, 293cb93a386Sopenharmony_ci SkTaskGroup* gpuTaskGroup, 294cb93a386Sopenharmony_ci GrDirectContext* dContext, 295cb93a386Sopenharmony_ci SkPicture* picture) { 296cb93a386Sopenharmony_ci SkASSERT(recordingTaskGroup && gpuTaskGroup && dContext); 297cb93a386Sopenharmony_ci 298cb93a386Sopenharmony_ci for (int i = 0; i < this->numTiles(); ++i) { 299cb93a386Sopenharmony_ci TileData* tile = &fTiles[i]; 300cb93a386Sopenharmony_ci if (!tile->initialized()) { 301cb93a386Sopenharmony_ci continue; 302cb93a386Sopenharmony_ci } 303cb93a386Sopenharmony_ci 304cb93a386Sopenharmony_ci // On a recording thread: 305cb93a386Sopenharmony_ci // generate the tile's DDL 306cb93a386Sopenharmony_ci // schedule gpu-thread processing of the DDL 307cb93a386Sopenharmony_ci // Note: a finer grained approach would be add a scheduling task which would evaluate 308cb93a386Sopenharmony_ci // which DDLs were ready to be rendered based on their prerequisites 309cb93a386Sopenharmony_ci recordingTaskGroup->add([tile, gpuTaskGroup, dContext, picture]() { 310cb93a386Sopenharmony_ci tile->createDDL(picture); 311cb93a386Sopenharmony_ci 312cb93a386Sopenharmony_ci gpuTaskGroup->add([dContext, tile]() { 313cb93a386Sopenharmony_ci do_gpu_stuff(dContext, tile); 314cb93a386Sopenharmony_ci }); 315cb93a386Sopenharmony_ci }); 316cb93a386Sopenharmony_ci } 317cb93a386Sopenharmony_ci 318cb93a386Sopenharmony_ci recordingTaskGroup->add([this] { this->createComposeDDL(); }); 319cb93a386Sopenharmony_ci} 320cb93a386Sopenharmony_ci 321cb93a386Sopenharmony_ci// Only called from skpbench 322cb93a386Sopenharmony_civoid DDLTileHelper::interleaveDDLCreationAndDraw(GrDirectContext* dContext, SkPicture* picture) { 323cb93a386Sopenharmony_ci for (int i = 0; i < this->numTiles(); ++i) { 324cb93a386Sopenharmony_ci fTiles[i].createDDL(picture); 325cb93a386Sopenharmony_ci fTiles[i].draw(dContext); 326cb93a386Sopenharmony_ci } 327cb93a386Sopenharmony_ci} 328cb93a386Sopenharmony_ci 329cb93a386Sopenharmony_ci// Only called from skpbench 330cb93a386Sopenharmony_civoid DDLTileHelper::drawAllTilesDirectly(GrDirectContext* dContext, SkPicture* picture) { 331cb93a386Sopenharmony_ci for (int i = 0; i < this->numTiles(); ++i) { 332cb93a386Sopenharmony_ci fTiles[i].drawSKPDirectly(dContext, picture); 333cb93a386Sopenharmony_ci } 334cb93a386Sopenharmony_ci} 335cb93a386Sopenharmony_ci 336cb93a386Sopenharmony_civoid DDLTileHelper::dropCallbackContexts() { 337cb93a386Sopenharmony_ci for (int i = 0; i < this->numTiles(); ++i) { 338cb93a386Sopenharmony_ci fTiles[i].dropCallbackContext(); 339cb93a386Sopenharmony_ci } 340cb93a386Sopenharmony_ci} 341cb93a386Sopenharmony_ci 342cb93a386Sopenharmony_civoid DDLTileHelper::resetAllTiles() { 343cb93a386Sopenharmony_ci for (int i = 0; i < this->numTiles(); ++i) { 344cb93a386Sopenharmony_ci fTiles[i].reset(); 345cb93a386Sopenharmony_ci } 346cb93a386Sopenharmony_ci fComposeDDL.reset(); 347cb93a386Sopenharmony_ci} 348cb93a386Sopenharmony_ci 349cb93a386Sopenharmony_civoid DDLTileHelper::createBackendTextures(SkTaskGroup* taskGroup, GrDirectContext* direct) { 350cb93a386Sopenharmony_ci 351cb93a386Sopenharmony_ci if (taskGroup) { 352cb93a386Sopenharmony_ci for (int i = 0; i < this->numTiles(); ++i) { 353cb93a386Sopenharmony_ci TileData* tile = &fTiles[i]; 354cb93a386Sopenharmony_ci if (!tile->initialized()) { 355cb93a386Sopenharmony_ci continue; 356cb93a386Sopenharmony_ci } 357cb93a386Sopenharmony_ci 358cb93a386Sopenharmony_ci taskGroup->add([direct, tile]() { TileData::CreateBackendTexture(direct, tile); }); 359cb93a386Sopenharmony_ci } 360cb93a386Sopenharmony_ci } else { 361cb93a386Sopenharmony_ci for (int i = 0; i < this->numTiles(); ++i) { 362cb93a386Sopenharmony_ci TileData::CreateBackendTexture(direct, &fTiles[i]); 363cb93a386Sopenharmony_ci } 364cb93a386Sopenharmony_ci } 365cb93a386Sopenharmony_ci} 366cb93a386Sopenharmony_ci 367cb93a386Sopenharmony_civoid DDLTileHelper::deleteBackendTextures(SkTaskGroup* taskGroup, GrDirectContext* direct) { 368cb93a386Sopenharmony_ci if (taskGroup) { 369cb93a386Sopenharmony_ci for (int i = 0; i < this->numTiles(); ++i) { 370cb93a386Sopenharmony_ci TileData* tile = &fTiles[i]; 371cb93a386Sopenharmony_ci 372cb93a386Sopenharmony_ci taskGroup->add([direct, tile]() { TileData::DeleteBackendTexture(direct, tile); }); 373cb93a386Sopenharmony_ci } 374cb93a386Sopenharmony_ci } else { 375cb93a386Sopenharmony_ci for (int i = 0; i < this->numTiles(); ++i) { 376cb93a386Sopenharmony_ci TileData::DeleteBackendTexture(direct, &fTiles[i]); 377cb93a386Sopenharmony_ci } 378cb93a386Sopenharmony_ci } 379cb93a386Sopenharmony_ci} 380