1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2019 Google LLC 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 "src/gpu/GrRenderTask.h" 9cb93a386Sopenharmony_ci 10cb93a386Sopenharmony_ci#include "src/gpu/GrAttachment.h" 11cb93a386Sopenharmony_ci#include "src/gpu/GrRenderTarget.h" 12cb93a386Sopenharmony_ci#include "src/gpu/GrTextureProxyPriv.h" 13cb93a386Sopenharmony_ci#include "src/gpu/GrTextureResolveRenderTask.h" 14cb93a386Sopenharmony_ci 15cb93a386Sopenharmony_ciuint32_t GrRenderTask::CreateUniqueID() { 16cb93a386Sopenharmony_ci static std::atomic<uint32_t> nextID{1}; 17cb93a386Sopenharmony_ci uint32_t id; 18cb93a386Sopenharmony_ci do { 19cb93a386Sopenharmony_ci id = nextID.fetch_add(1, std::memory_order_relaxed); 20cb93a386Sopenharmony_ci } while (id == SK_InvalidUniqueID); 21cb93a386Sopenharmony_ci return id; 22cb93a386Sopenharmony_ci} 23cb93a386Sopenharmony_ci 24cb93a386Sopenharmony_ciGrRenderTask::GrRenderTask() 25cb93a386Sopenharmony_ci : fUniqueID(CreateUniqueID()) 26cb93a386Sopenharmony_ci , fFlags(0) { 27cb93a386Sopenharmony_ci} 28cb93a386Sopenharmony_ci 29cb93a386Sopenharmony_civoid GrRenderTask::disown(GrDrawingManager* drawingMgr) { 30cb93a386Sopenharmony_ci SkASSERT(!fDrawingMgr || drawingMgr == fDrawingMgr); 31cb93a386Sopenharmony_ci SkASSERT(this->isClosed()); 32cb93a386Sopenharmony_ci if (this->isSetFlag(kDisowned_Flag)) { 33cb93a386Sopenharmony_ci return; 34cb93a386Sopenharmony_ci } 35cb93a386Sopenharmony_ci SkDEBUGCODE(fDrawingMgr = nullptr); 36cb93a386Sopenharmony_ci this->setFlag(kDisowned_Flag); 37cb93a386Sopenharmony_ci 38cb93a386Sopenharmony_ci for (const sk_sp<GrSurfaceProxy>& target : fTargets) { 39cb93a386Sopenharmony_ci if (this == drawingMgr->getLastRenderTask(target.get())) { 40cb93a386Sopenharmony_ci drawingMgr->setLastRenderTask(target.get(), nullptr); 41cb93a386Sopenharmony_ci } 42cb93a386Sopenharmony_ci } 43cb93a386Sopenharmony_ci} 44cb93a386Sopenharmony_ci 45cb93a386Sopenharmony_civoid GrRenderTask::makeSkippable() { 46cb93a386Sopenharmony_ci SkASSERT(this->isClosed()); 47cb93a386Sopenharmony_ci if (!this->isSkippable()) { 48cb93a386Sopenharmony_ci this->setFlag(kSkippable_Flag); 49cb93a386Sopenharmony_ci this->onMakeSkippable(); 50cb93a386Sopenharmony_ci } 51cb93a386Sopenharmony_ci} 52cb93a386Sopenharmony_ci 53cb93a386Sopenharmony_ci#ifdef SK_DEBUG 54cb93a386Sopenharmony_ciGrRenderTask::~GrRenderTask() { 55cb93a386Sopenharmony_ci SkASSERT(this->isSetFlag(kDisowned_Flag)); 56cb93a386Sopenharmony_ci} 57cb93a386Sopenharmony_ci 58cb93a386Sopenharmony_cibool GrRenderTask::deferredProxiesAreInstantiated() const { 59cb93a386Sopenharmony_ci for (int i = 0; i < fDeferredProxies.count(); ++i) { 60cb93a386Sopenharmony_ci if (!fDeferredProxies[i]->isInstantiated()) { 61cb93a386Sopenharmony_ci return false; 62cb93a386Sopenharmony_ci } 63cb93a386Sopenharmony_ci } 64cb93a386Sopenharmony_ci 65cb93a386Sopenharmony_ci return true; 66cb93a386Sopenharmony_ci} 67cb93a386Sopenharmony_ci#endif 68cb93a386Sopenharmony_ci 69cb93a386Sopenharmony_civoid GrRenderTask::makeClosed(GrRecordingContext* rContext) { 70cb93a386Sopenharmony_ci if (this->isClosed()) { 71cb93a386Sopenharmony_ci return; 72cb93a386Sopenharmony_ci } 73cb93a386Sopenharmony_ci 74cb93a386Sopenharmony_ci SkIRect targetUpdateBounds; 75cb93a386Sopenharmony_ci if (ExpectedOutcome::kTargetDirty == this->onMakeClosed(rContext, &targetUpdateBounds)) { 76cb93a386Sopenharmony_ci GrSurfaceProxy* proxy = this->target(0); 77cb93a386Sopenharmony_ci if (proxy->requiresManualMSAAResolve()) { 78cb93a386Sopenharmony_ci SkASSERT(this->target(0)->asRenderTargetProxy()); 79cb93a386Sopenharmony_ci this->target(0)->asRenderTargetProxy()->markMSAADirty(targetUpdateBounds); 80cb93a386Sopenharmony_ci } 81cb93a386Sopenharmony_ci GrTextureProxy* textureProxy = this->target(0)->asTextureProxy(); 82cb93a386Sopenharmony_ci if (textureProxy && GrMipmapped::kYes == textureProxy->mipmapped()) { 83cb93a386Sopenharmony_ci textureProxy->markMipmapsDirty(); 84cb93a386Sopenharmony_ci } 85cb93a386Sopenharmony_ci } 86cb93a386Sopenharmony_ci 87cb93a386Sopenharmony_ci if (fTextureResolveTask) { 88cb93a386Sopenharmony_ci this->addDependency(fTextureResolveTask); 89cb93a386Sopenharmony_ci fTextureResolveTask->makeClosed(rContext); 90cb93a386Sopenharmony_ci fTextureResolveTask = nullptr; 91cb93a386Sopenharmony_ci } 92cb93a386Sopenharmony_ci 93cb93a386Sopenharmony_ci this->setFlag(kClosed_Flag); 94cb93a386Sopenharmony_ci} 95cb93a386Sopenharmony_ci 96cb93a386Sopenharmony_civoid GrRenderTask::prepare(GrOpFlushState* flushState) { 97cb93a386Sopenharmony_ci for (int i = 0; i < fDeferredProxies.count(); ++i) { 98cb93a386Sopenharmony_ci fDeferredProxies[i]->texPriv().scheduleUpload(flushState); 99cb93a386Sopenharmony_ci } 100cb93a386Sopenharmony_ci 101cb93a386Sopenharmony_ci this->onPrepare(flushState); 102cb93a386Sopenharmony_ci} 103cb93a386Sopenharmony_ci 104cb93a386Sopenharmony_ci// Add a GrRenderTask-based dependency 105cb93a386Sopenharmony_civoid GrRenderTask::addDependency(GrRenderTask* dependedOn) { 106cb93a386Sopenharmony_ci SkASSERT(!dependedOn->dependsOn(this)); // loops are bad 107cb93a386Sopenharmony_ci SkASSERT(!this->dependsOn(dependedOn)); // caller should weed out duplicates 108cb93a386Sopenharmony_ci 109cb93a386Sopenharmony_ci fDependencies.push_back(dependedOn); 110cb93a386Sopenharmony_ci dependedOn->addDependent(this); 111cb93a386Sopenharmony_ci 112cb93a386Sopenharmony_ci SkDEBUGCODE(this->validate()); 113cb93a386Sopenharmony_ci} 114cb93a386Sopenharmony_ci 115cb93a386Sopenharmony_civoid GrRenderTask::addDependenciesFromOtherTask(GrRenderTask* otherTask) { 116cb93a386Sopenharmony_ci SkASSERT(otherTask); 117cb93a386Sopenharmony_ci for (GrRenderTask* task : otherTask->fDependencies) { 118cb93a386Sopenharmony_ci // The task should not be adding a dependency to itself. 119cb93a386Sopenharmony_ci SkASSERT(task != this); 120cb93a386Sopenharmony_ci if (!this->dependsOn(task)) { 121cb93a386Sopenharmony_ci this->addDependency(task); 122cb93a386Sopenharmony_ci } 123cb93a386Sopenharmony_ci } 124cb93a386Sopenharmony_ci} 125cb93a386Sopenharmony_ci 126cb93a386Sopenharmony_ci// Convert from a GrSurface-based dependency to a GrRenderTask one 127cb93a386Sopenharmony_civoid GrRenderTask::addDependency(GrDrawingManager* drawingMgr, GrSurfaceProxy* dependedOn, 128cb93a386Sopenharmony_ci GrMipmapped mipMapped, 129cb93a386Sopenharmony_ci GrTextureResolveManager textureResolveManager, 130cb93a386Sopenharmony_ci const GrCaps& caps) { 131cb93a386Sopenharmony_ci // If it is still receiving dependencies, this GrRenderTask shouldn't be closed 132cb93a386Sopenharmony_ci SkASSERT(!this->isClosed()); 133cb93a386Sopenharmony_ci 134cb93a386Sopenharmony_ci GrRenderTask* dependedOnTask = drawingMgr->getLastRenderTask(dependedOn); 135cb93a386Sopenharmony_ci 136cb93a386Sopenharmony_ci if (dependedOnTask == this) { 137cb93a386Sopenharmony_ci // self-read - presumably for dst reads. We don't need to do anything in this case. The 138cb93a386Sopenharmony_ci // XferProcessor will detect what is happening and insert a texture barrier. 139cb93a386Sopenharmony_ci SkASSERT(GrMipmapped::kNo == mipMapped); 140cb93a386Sopenharmony_ci // We should never attempt a self-read on a surface that has a separate MSAA renderbuffer. 141cb93a386Sopenharmony_ci SkASSERT(!dependedOn->requiresManualMSAAResolve()); 142cb93a386Sopenharmony_ci SkASSERT(!dependedOn->asTextureProxy() || 143cb93a386Sopenharmony_ci !dependedOn->asTextureProxy()->texPriv().isDeferred()); 144cb93a386Sopenharmony_ci return; 145cb93a386Sopenharmony_ci } 146cb93a386Sopenharmony_ci 147cb93a386Sopenharmony_ci if (dependedOnTask) { 148cb93a386Sopenharmony_ci if (this->dependsOn(dependedOnTask) || fTextureResolveTask == dependedOnTask) { 149cb93a386Sopenharmony_ci return; // don't add duplicate dependencies 150cb93a386Sopenharmony_ci } 151cb93a386Sopenharmony_ci 152cb93a386Sopenharmony_ci if (!dependedOnTask->isSetFlag(kAtlas_Flag)) { 153cb93a386Sopenharmony_ci // We are closing 'dependedOnTask' here bc the current contents of it are what 'this' 154cb93a386Sopenharmony_ci // renderTask depends on. We need a break in 'dependedOnTask' so that the usage of 155cb93a386Sopenharmony_ci // that state has a chance to execute. 156cb93a386Sopenharmony_ci dependedOnTask->makeClosed(drawingMgr->getContext()); 157cb93a386Sopenharmony_ci } 158cb93a386Sopenharmony_ci } 159cb93a386Sopenharmony_ci 160cb93a386Sopenharmony_ci auto resolveFlags = GrSurfaceProxy::ResolveFlags::kNone; 161cb93a386Sopenharmony_ci 162cb93a386Sopenharmony_ci if (dependedOn->requiresManualMSAAResolve()) { 163cb93a386Sopenharmony_ci auto* renderTargetProxy = dependedOn->asRenderTargetProxy(); 164cb93a386Sopenharmony_ci SkASSERT(renderTargetProxy); 165cb93a386Sopenharmony_ci if (renderTargetProxy->isMSAADirty()) { 166cb93a386Sopenharmony_ci resolveFlags |= GrSurfaceProxy::ResolveFlags::kMSAA; 167cb93a386Sopenharmony_ci } 168cb93a386Sopenharmony_ci } 169cb93a386Sopenharmony_ci 170cb93a386Sopenharmony_ci GrTextureProxy* textureProxy = dependedOn->asTextureProxy(); 171cb93a386Sopenharmony_ci if (GrMipmapped::kYes == mipMapped) { 172cb93a386Sopenharmony_ci SkASSERT(textureProxy); 173cb93a386Sopenharmony_ci if (GrMipmapped::kYes != textureProxy->mipmapped()) { 174cb93a386Sopenharmony_ci // There are some cases where we might be given a non-mipmapped texture with a mipmap 175cb93a386Sopenharmony_ci // filter. See skbug.com/7094. 176cb93a386Sopenharmony_ci mipMapped = GrMipmapped::kNo; 177cb93a386Sopenharmony_ci } else if (textureProxy->mipmapsAreDirty()) { 178cb93a386Sopenharmony_ci resolveFlags |= GrSurfaceProxy::ResolveFlags::kMipMaps; 179cb93a386Sopenharmony_ci } 180cb93a386Sopenharmony_ci } 181cb93a386Sopenharmony_ci 182cb93a386Sopenharmony_ci // Does this proxy have msaa to resolve and/or mipmaps to regenerate? 183cb93a386Sopenharmony_ci if (GrSurfaceProxy::ResolveFlags::kNone != resolveFlags) { 184cb93a386Sopenharmony_ci if (!fTextureResolveTask) { 185cb93a386Sopenharmony_ci fTextureResolveTask = textureResolveManager.newTextureResolveRenderTask(caps); 186cb93a386Sopenharmony_ci } 187cb93a386Sopenharmony_ci fTextureResolveTask->addProxy(drawingMgr, sk_ref_sp(dependedOn), resolveFlags, caps); 188cb93a386Sopenharmony_ci 189cb93a386Sopenharmony_ci // addProxy() should have closed the texture proxy's previous task. 190cb93a386Sopenharmony_ci SkASSERT(!dependedOnTask || dependedOnTask->isClosed()); 191cb93a386Sopenharmony_ci SkASSERT(drawingMgr->getLastRenderTask(dependedOn) == fTextureResolveTask); 192cb93a386Sopenharmony_ci 193cb93a386Sopenharmony_ci#ifdef SK_DEBUG 194cb93a386Sopenharmony_ci // addProxy() should have called addDependency (in this instance, recursively) on 195cb93a386Sopenharmony_ci // fTextureResolveTask. 196cb93a386Sopenharmony_ci if (dependedOnTask) { 197cb93a386Sopenharmony_ci SkASSERT(fTextureResolveTask->dependsOn(dependedOnTask)); 198cb93a386Sopenharmony_ci } 199cb93a386Sopenharmony_ci if (textureProxy && textureProxy->texPriv().isDeferred()) { 200cb93a386Sopenharmony_ci SkASSERT(fTextureResolveTask->fDeferredProxies.back() == textureProxy); 201cb93a386Sopenharmony_ci } 202cb93a386Sopenharmony_ci 203cb93a386Sopenharmony_ci // The GrTextureResolveRenderTask factory should have also marked the proxy clean, set the 204cb93a386Sopenharmony_ci // last renderTask on the textureProxy to textureResolveTask, and closed textureResolveTask. 205cb93a386Sopenharmony_ci if (GrRenderTargetProxy* renderTargetProxy = dependedOn->asRenderTargetProxy()) { 206cb93a386Sopenharmony_ci SkASSERT(!renderTargetProxy->isMSAADirty()); 207cb93a386Sopenharmony_ci } 208cb93a386Sopenharmony_ci if (textureProxy) { 209cb93a386Sopenharmony_ci SkASSERT(!textureProxy->mipmapsAreDirty()); 210cb93a386Sopenharmony_ci } 211cb93a386Sopenharmony_ci SkASSERT(drawingMgr->getLastRenderTask(dependedOn) == fTextureResolveTask); 212cb93a386Sopenharmony_ci#endif 213cb93a386Sopenharmony_ci return; 214cb93a386Sopenharmony_ci } 215cb93a386Sopenharmony_ci 216cb93a386Sopenharmony_ci if (textureProxy && textureProxy->texPriv().isDeferred()) { 217cb93a386Sopenharmony_ci fDeferredProxies.push_back(textureProxy); 218cb93a386Sopenharmony_ci } 219cb93a386Sopenharmony_ci 220cb93a386Sopenharmony_ci if (dependedOnTask) { 221cb93a386Sopenharmony_ci this->addDependency(dependedOnTask); 222cb93a386Sopenharmony_ci } 223cb93a386Sopenharmony_ci} 224cb93a386Sopenharmony_ci 225cb93a386Sopenharmony_civoid GrRenderTask::replaceDependency(const GrRenderTask* toReplace, GrRenderTask* replaceWith) { 226cb93a386Sopenharmony_ci for (auto& target : fDependencies) { 227cb93a386Sopenharmony_ci if (target == toReplace) { 228cb93a386Sopenharmony_ci target = replaceWith; 229cb93a386Sopenharmony_ci replaceWith->fDependents.push_back(this); 230cb93a386Sopenharmony_ci break; 231cb93a386Sopenharmony_ci } 232cb93a386Sopenharmony_ci } 233cb93a386Sopenharmony_ci} 234cb93a386Sopenharmony_ci 235cb93a386Sopenharmony_civoid GrRenderTask::replaceDependent(const GrRenderTask* toReplace, GrRenderTask* replaceWith) { 236cb93a386Sopenharmony_ci for (auto& target : fDependents) { 237cb93a386Sopenharmony_ci if (target == toReplace) { 238cb93a386Sopenharmony_ci target = replaceWith; 239cb93a386Sopenharmony_ci replaceWith->fDependencies.push_back(this); 240cb93a386Sopenharmony_ci break; 241cb93a386Sopenharmony_ci } 242cb93a386Sopenharmony_ci } 243cb93a386Sopenharmony_ci} 244cb93a386Sopenharmony_ci 245cb93a386Sopenharmony_cibool GrRenderTask::dependsOn(const GrRenderTask* dependedOn) const { 246cb93a386Sopenharmony_ci for (int i = 0; i < fDependencies.count(); ++i) { 247cb93a386Sopenharmony_ci if (fDependencies[i] == dependedOn) { 248cb93a386Sopenharmony_ci return true; 249cb93a386Sopenharmony_ci } 250cb93a386Sopenharmony_ci } 251cb93a386Sopenharmony_ci 252cb93a386Sopenharmony_ci return false; 253cb93a386Sopenharmony_ci} 254cb93a386Sopenharmony_ci 255cb93a386Sopenharmony_ci 256cb93a386Sopenharmony_civoid GrRenderTask::addDependent(GrRenderTask* dependent) { 257cb93a386Sopenharmony_ci fDependents.push_back(dependent); 258cb93a386Sopenharmony_ci} 259cb93a386Sopenharmony_ci 260cb93a386Sopenharmony_ci#ifdef SK_DEBUG 261cb93a386Sopenharmony_cibool GrRenderTask::isDependent(const GrRenderTask* dependent) const { 262cb93a386Sopenharmony_ci for (int i = 0; i < fDependents.count(); ++i) { 263cb93a386Sopenharmony_ci if (fDependents[i] == dependent) { 264cb93a386Sopenharmony_ci return true; 265cb93a386Sopenharmony_ci } 266cb93a386Sopenharmony_ci } 267cb93a386Sopenharmony_ci 268cb93a386Sopenharmony_ci return false; 269cb93a386Sopenharmony_ci} 270cb93a386Sopenharmony_ci 271cb93a386Sopenharmony_civoid GrRenderTask::validate() const { 272cb93a386Sopenharmony_ci // TODO: check for loops and duplicates 273cb93a386Sopenharmony_ci 274cb93a386Sopenharmony_ci for (int i = 0; i < fDependencies.count(); ++i) { 275cb93a386Sopenharmony_ci SkASSERT(fDependencies[i]->isDependent(this)); 276cb93a386Sopenharmony_ci } 277cb93a386Sopenharmony_ci} 278cb93a386Sopenharmony_ci#endif 279cb93a386Sopenharmony_ci 280cb93a386Sopenharmony_cibool GrRenderTask::isInstantiated() const { 281cb93a386Sopenharmony_ci for (const sk_sp<GrSurfaceProxy>& target : fTargets) { 282cb93a386Sopenharmony_ci GrSurfaceProxy* proxy = target.get(); 283cb93a386Sopenharmony_ci if (!proxy->isInstantiated()) { 284cb93a386Sopenharmony_ci return false; 285cb93a386Sopenharmony_ci } 286cb93a386Sopenharmony_ci 287cb93a386Sopenharmony_ci GrSurface* surface = proxy->peekSurface(); 288cb93a386Sopenharmony_ci if (surface->wasDestroyed()) { 289cb93a386Sopenharmony_ci return false; 290cb93a386Sopenharmony_ci } 291cb93a386Sopenharmony_ci } 292cb93a386Sopenharmony_ci 293cb93a386Sopenharmony_ci return true; 294cb93a386Sopenharmony_ci} 295cb93a386Sopenharmony_ci 296cb93a386Sopenharmony_civoid GrRenderTask::addTarget(GrDrawingManager* drawingMgr, sk_sp<GrSurfaceProxy> proxy) { 297cb93a386Sopenharmony_ci SkASSERT(proxy); 298cb93a386Sopenharmony_ci SkASSERT(!this->isClosed()); 299cb93a386Sopenharmony_ci SkASSERT(!fDrawingMgr || drawingMgr == fDrawingMgr); 300cb93a386Sopenharmony_ci SkDEBUGCODE(fDrawingMgr = drawingMgr); 301cb93a386Sopenharmony_ci drawingMgr->setLastRenderTask(proxy.get(), this); 302cb93a386Sopenharmony_ci proxy->isUsedAsTaskTarget(); 303cb93a386Sopenharmony_ci fTargets.emplace_back(std::move(proxy)); 304cb93a386Sopenharmony_ci} 305cb93a386Sopenharmony_ci 306cb93a386Sopenharmony_ci#if GR_TEST_UTILS 307cb93a386Sopenharmony_civoid GrRenderTask::dump(const SkString& label, 308cb93a386Sopenharmony_ci SkString indent, 309cb93a386Sopenharmony_ci bool printDependencies, 310cb93a386Sopenharmony_ci bool close) const { 311cb93a386Sopenharmony_ci SkDebugf("%s%s --------------------------------------------------------------\n", 312cb93a386Sopenharmony_ci indent.c_str(), 313cb93a386Sopenharmony_ci label.c_str()); 314cb93a386Sopenharmony_ci SkDebugf("%s%s task - renderTaskID: %d\n", indent.c_str(), this->name(), fUniqueID); 315cb93a386Sopenharmony_ci 316cb93a386Sopenharmony_ci if (!fTargets.empty()) { 317cb93a386Sopenharmony_ci SkDebugf("%sTargets: \n", indent.c_str()); 318cb93a386Sopenharmony_ci for (const sk_sp<GrSurfaceProxy>& target : fTargets) { 319cb93a386Sopenharmony_ci SkASSERT(target); 320cb93a386Sopenharmony_ci SkString proxyStr = target->dump(); 321cb93a386Sopenharmony_ci SkDebugf("%s%s\n", indent.c_str(), proxyStr.c_str()); 322cb93a386Sopenharmony_ci } 323cb93a386Sopenharmony_ci } 324cb93a386Sopenharmony_ci 325cb93a386Sopenharmony_ci if (printDependencies) { 326cb93a386Sopenharmony_ci SkDebugf("%sI rely On (%d): ", indent.c_str(), fDependencies.count()); 327cb93a386Sopenharmony_ci for (int i = 0; i < fDependencies.count(); ++i) { 328cb93a386Sopenharmony_ci SkDebugf("%d, ", fDependencies[i]->fUniqueID); 329cb93a386Sopenharmony_ci } 330cb93a386Sopenharmony_ci SkDebugf("\n"); 331cb93a386Sopenharmony_ci 332cb93a386Sopenharmony_ci SkDebugf("%s(%d) Rely On Me: ", indent.c_str(), fDependents.count()); 333cb93a386Sopenharmony_ci for (int i = 0; i < fDependents.count(); ++i) { 334cb93a386Sopenharmony_ci SkDebugf("%d, ", fDependents[i]->fUniqueID); 335cb93a386Sopenharmony_ci } 336cb93a386Sopenharmony_ci SkDebugf("\n"); 337cb93a386Sopenharmony_ci } 338cb93a386Sopenharmony_ci 339cb93a386Sopenharmony_ci if (close) { 340cb93a386Sopenharmony_ci SkDebugf("%s--------------------------------------------------------------\n\n", 341cb93a386Sopenharmony_ci indent.c_str()); 342cb93a386Sopenharmony_ci } 343cb93a386Sopenharmony_ci} 344cb93a386Sopenharmony_ci#endif 345