SkData* Request::getJsonBatchList(int n) { SkCanvas* canvas = this->getCanvas(); SkASSERT(fGPUEnabled); // TODO if this is inefficient we could add a method to GrAuditTrail which takes // a Json::Value and is only compiled in this file Json::Value parsedFromString; #if SK_SUPPORT_GPU GrRenderTarget* rt = canvas->internal_private_accessTopLayerRenderTarget(); SkASSERT(rt); GrContext* ctx = rt->getContext(); SkASSERT(ctx); GrAuditTrail* at = ctx->getAuditTrail(); GrAuditTrail::AutoManageBatchList enable(at); fDebugCanvas->drawTo(canvas, n); Json::Reader reader; SkDEBUGCODE(bool parsingSuccessful = )reader.parse(at->toJson(true).c_str(), parsedFromString); SkASSERT(parsingSuccessful); #endif SkDynamicMemoryWStream stream; stream.writeText(Json::FastWriter().write(parsedFromString).c_str()); return stream.copyToData(); }
Json::Value SkDebugCanvas::toJSON(UrlDataManager& urlDataManager, int n, SkCanvas* canvas) { this->drawAndCollectBatches(n, canvas); // now collect json #if SK_SUPPORT_GPU GrAuditTrail* at = this->getAuditTrail(canvas); #endif Json::Value result = Json::Value(Json::objectValue); result[SKDEBUGCANVAS_ATTRIBUTE_VERSION] = Json::Value(SKDEBUGCANVAS_VERSION); Json::Value commands = Json::Value(Json::arrayValue); for (int i = 0; i < this->getSize() && i <= n; i++) { commands[i] = this->getDrawCommandAt(i)->toJSON(urlDataManager); #if SK_SUPPORT_GPU if (at) { // TODO if this is inefficient we could add a method to GrAuditTrail which takes // a Json::Value and is only compiled in this file Json::Value parsedFromString; Json::Reader reader; SkAssertResult(reader.parse(at->toJson(i).c_str(), parsedFromString)); commands[i][SKDEBUGCANVAS_ATTRIBUTE_AUDITTRAIL] = parsedFromString; } #endif } this->cleanupAuditTrail(canvas); result[SKDEBUGCANVAS_ATTRIBUTE_COMMANDS] = commands; return result; }
void SkDebugCanvas::cleanupAuditTrail(SkCanvas* canvas) { GrAuditTrail* at = this->getAuditTrail(canvas); if (at) { #if SK_SUPPORT_GPU GrAuditTrail::AutoEnable ae(at); at->fullReset(); #endif } }
Json::Value SkDebugCanvas::toJSONBatchList(int n, SkCanvas* canvas) { this->drawAndCollectBatches(n, canvas); Json::Value parsedFromString; #if SK_SUPPORT_GPU GrAuditTrail* at = this->getAuditTrail(canvas); if (at) { GrAuditTrail::AutoManageBatchList enable(at); Json::Reader reader; SkAssertResult(reader.parse(at->toJson().c_str(), parsedFromString)); } #endif this->cleanupAuditTrail(canvas); return parsedFromString; }
void SkDebugCanvas::drawTo(SkCanvas* canvas, int index, int m) { SkASSERT(!fCommandVector.isEmpty()); SkASSERT(index < fCommandVector.count()); int saveCount = canvas->save(); SkRect windowRect = SkRect::MakeWH(SkIntToScalar(canvas->getBaseLayerSize().width()), SkIntToScalar(canvas->getBaseLayerSize().height())); bool pathOpsMode = getAllowSimplifyClip(); canvas->setAllowSimplifyClip(pathOpsMode); canvas->clear(SK_ColorWHITE); canvas->resetMatrix(); if (!windowRect.isEmpty()) { canvas->clipRect(windowRect, SkRegion::kReplace_Op); } this->applyUserTransform(canvas); if (fPaintFilterCanvas) { fPaintFilterCanvas->addCanvas(canvas); canvas = fPaintFilterCanvas.get(); } if (fMegaVizMode) { this->markActiveCommands(index); } #if SK_SUPPORT_GPU // If we have a GPU backend we can also visualize the batching information GrAuditTrail* at = nullptr; if (fDrawGpuBatchBounds || m != -1) { at = this->getAuditTrail(canvas); } #endif for (int i = 0; i <= index; i++) { if (i == index && fFilter) { canvas->clear(0xAAFFFFFF); } #if SK_SUPPORT_GPU // We need to flush any pending operations, or they might batch with commands below. // Previous operations were not registered with the audit trail when they were // created, so if we allow them to combine, the audit trail will fail to find them. canvas->flush(); GrAuditTrail::AutoCollectBatches* acb = nullptr; if (at) { acb = new GrAuditTrail::AutoCollectBatches(at, i); } #endif if (fCommandVector[i]->isVisible()) { if (fMegaVizMode && fCommandVector[i]->active()) { // "active" commands execute their visualization behaviors: // All active saveLayers get replaced with saves so all draws go to the // visible canvas. // All active culls draw their cull box fCommandVector[i]->vizExecute(canvas); } else { fCommandVector[i]->setUserMatrix(fUserMatrix); fCommandVector[i]->execute(canvas); } } #if SK_SUPPORT_GPU if (at && acb) { delete acb; } #endif } if (SkColorGetA(fClipVizColor) != 0) { canvas->save(); #define LARGE_COORD 1000000000 canvas->clipRect(SkRect::MakeLTRB(-LARGE_COORD, -LARGE_COORD, LARGE_COORD, LARGE_COORD), SkRegion::kReverseDifference_Op); SkPaint clipPaint; clipPaint.setColor(fClipVizColor); canvas->drawPaint(clipPaint); canvas->restore(); } if (fMegaVizMode) { canvas->save(); // nuke the CTM canvas->resetMatrix(); // turn off clipping if (!windowRect.isEmpty()) { SkRect r = windowRect; r.outset(SK_Scalar1, SK_Scalar1); canvas->clipRect(r, SkRegion::kReplace_Op); } // visualize existing clips SkDebugClipVisitor visitor(canvas); canvas->replayClips(&visitor); canvas->restore(); } if (pathOpsMode) { this->resetClipStackData(); const SkClipStack* clipStack = canvas->getClipStack(); SkClipStack::Iter iter(*clipStack, SkClipStack::Iter::kBottom_IterStart); const SkClipStack::Element* element; SkPath devPath; while ((element = iter.next())) { SkClipStack::Element::Type type = element->getType(); SkPath operand; if (type != SkClipStack::Element::kEmpty_Type) { element->asPath(&operand); } SkRegion::Op elementOp = element->getOp(); this->addClipStackData(devPath, operand, elementOp); if (elementOp == SkRegion::kReplace_Op) { devPath = operand; } else { Op(devPath, operand, (SkPathOp) elementOp, &devPath); } } this->lastClipStackData(devPath); } fMatrix = canvas->getTotalMatrix(); if (!canvas->getClipDeviceBounds(&fClip)) { fClip.setEmpty(); } canvas->restoreToCount(saveCount); if (fPaintFilterCanvas) { fPaintFilterCanvas->removeAll(); } #if SK_SUPPORT_GPU // draw any batches if required and issue a full reset onto GrAuditTrail if (at) { // just in case there is global reordering, we flush the canvas before querying // GrAuditTrail GrAuditTrail::AutoEnable ae(at); canvas->flush(); // we pick three colorblind-safe colors, 75% alpha static const SkColor kTotalBounds = SkColorSetARGB(0xC0, 0x6A, 0x3D, 0x9A); static const SkColor kOpBatchBounds = SkColorSetARGB(0xC0, 0xE3, 0x1A, 0x1C); static const SkColor kOtherBatchBounds = SkColorSetARGB(0xC0, 0xFF, 0x7F, 0x00); // get the render target of the top device so we can ignore batches drawn offscreen SkBaseDevice* bd = canvas->getDevice_just_for_deprecated_compatibility_testing(); SkGpuDevice* gbd = reinterpret_cast<SkGpuDevice*>(bd); uint32_t rtID = gbd->accessRenderTarget()->getUniqueID(); // get the bounding boxes to draw SkTArray<GrAuditTrail::BatchInfo> childrenBounds; if (m == -1) { at->getBoundsByClientID(&childrenBounds, index); } else { // the client wants us to draw the mth batch at->getBoundsByBatchListID(&childrenBounds.push_back(), m); } SkPaint paint; paint.setStyle(SkPaint::kStroke_Style); paint.setStrokeWidth(1); for (int i = 0; i < childrenBounds.count(); i++) { if (childrenBounds[i].fRenderTargetUniqueID != rtID) { // offscreen draw, ignore for now continue; } paint.setColor(kTotalBounds); canvas->drawRect(childrenBounds[i].fBounds, paint); for (int j = 0; j < childrenBounds[i].fBatches.count(); j++) { const GrAuditTrail::BatchInfo::Batch& batch = childrenBounds[i].fBatches[j]; if (batch.fClientID != index) { paint.setColor(kOtherBatchBounds); } else { paint.setColor(kOpBatchBounds); } canvas->drawRect(batch.fBounds, paint); } } } #endif this->cleanupAuditTrail(canvas); }