blob: 0418670dbb89a829866301c59326ff70e5747bcd [file] [log] [blame]
/*
* Copyright 2019 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "include/gpu/GrRecordingContext.h"
#include "include/gpu/GrContextThreadSafeProxy.h"
#include "src/core/SkArenaAlloc.h"
#include "src/gpu/GrAuditTrail.h"
#include "src/gpu/GrCaps.h"
#include "src/gpu/GrContextThreadSafeProxyPriv.h"
#include "src/gpu/GrDrawingManager.h"
#include "src/gpu/GrMemoryPool.h"
#include "src/gpu/GrProgramDesc.h"
#include "src/gpu/GrProxyProvider.h"
#include "src/gpu/GrRecordingContextPriv.h"
#include "src/gpu/SkGr.h"
#include "src/gpu/SurfaceContext.h"
#include "src/gpu/effects/GrSkSLFP.h"
#include "src/gpu/text/GrTextBlob.h"
#include "src/gpu/text/GrTextBlobCache.h"
#if SK_GPU_V1
#include "src/gpu/ops/AtlasTextOp.h"
#endif
GrRecordingContext::ProgramData::ProgramData(std::unique_ptr<const GrProgramDesc> desc,
const GrProgramInfo* info)
: fDesc(std::move(desc))
, fInfo(info) {
}
GrRecordingContext::ProgramData::ProgramData(ProgramData&& other)
: fDesc(std::move(other.fDesc))
, fInfo(other.fInfo) {
}
GrRecordingContext::ProgramData::~ProgramData() = default;
GrRecordingContext::GrRecordingContext(sk_sp<GrContextThreadSafeProxy> proxy, bool ddlRecording)
: INHERITED(std::move(proxy))
, fAuditTrail(new GrAuditTrail())
, fArenas(ddlRecording) {
fProxyProvider = std::make_unique<GrProxyProvider>(this);
}
GrRecordingContext::~GrRecordingContext() {
#if SK_GPU_V1
skgpu::v1::AtlasTextOp::ClearCache();
#endif
}
int GrRecordingContext::maxSurfaceSampleCountForColorType(SkColorType colorType) const {
GrBackendFormat format =
this->caps()->getDefaultBackendFormat(SkColorTypeToGrColorType(colorType),
GrRenderable::kYes);
return this->caps()->maxRenderTargetSampleCount(format);
}
bool GrRecordingContext::init() {
if (!INHERITED::init()) {
return false;
}
#if SK_GPU_V1
skgpu::v1::PathRendererChain::Options prcOptions;
prcOptions.fAllowPathMaskCaching = this->options().fAllowPathMaskCaching;
#if GR_TEST_UTILS
prcOptions.fGpuPathRenderers = this->options().fGpuPathRenderers;
#endif
// FIXME: Once this is removed from Chrome and Android, rename to fEnable"".
if (this->options().fDisableDistanceFieldPaths) {
prcOptions.fGpuPathRenderers &= ~GpuPathRenderers::kSmall;
}
#endif
bool reduceOpsTaskSplitting = true;
if (this->caps()->avoidReorderingRenderTasks()) {
reduceOpsTaskSplitting = false;
} else if (GrContextOptions::Enable::kYes == this->options().fReduceOpsTaskSplitting) {
reduceOpsTaskSplitting = true;
} else if (GrContextOptions::Enable::kNo == this->options().fReduceOpsTaskSplitting) {
reduceOpsTaskSplitting = false;
}
fDrawingManager.reset(new GrDrawingManager(this,
#if SK_GPU_V1
prcOptions,
#endif
reduceOpsTaskSplitting));
return true;
}
void GrRecordingContext::abandonContext() {
INHERITED::abandonContext();
this->destroyDrawingManager();
}
GrDrawingManager* GrRecordingContext::drawingManager() {
return fDrawingManager.get();
}
void GrRecordingContext::destroyDrawingManager() {
fDrawingManager.reset();
}
GrRecordingContext::Arenas::Arenas(SkArenaAlloc* recordTimeAllocator,
GrSubRunAllocator* subRunAllocator)
: fRecordTimeAllocator(recordTimeAllocator)
, fRecordTimeSubRunAllocator(subRunAllocator) {
// OwnedArenas should instantiate these before passing the bare pointer off to this struct.
SkASSERT(subRunAllocator);
}
// Must be defined here so that std::unique_ptr can see the sizes of the various pools, otherwise
// it can't generate a default destructor for them.
GrRecordingContext::OwnedArenas::OwnedArenas(bool ddlRecording) : fDDLRecording(ddlRecording) {}
GrRecordingContext::OwnedArenas::~OwnedArenas() {}
GrRecordingContext::OwnedArenas& GrRecordingContext::OwnedArenas::operator=(OwnedArenas&& a) {
fDDLRecording = a.fDDLRecording;
fRecordTimeAllocator = std::move(a.fRecordTimeAllocator);
fRecordTimeSubRunAllocator = std::move(a.fRecordTimeSubRunAllocator);
return *this;
}
GrRecordingContext::Arenas GrRecordingContext::OwnedArenas::get() {
if (!fRecordTimeAllocator && fDDLRecording) {
// TODO: empirically determine a better number for SkArenaAlloc's firstHeapAllocation param
fRecordTimeAllocator = std::make_unique<SkArenaAlloc>(1024);
}
if (!fRecordTimeSubRunAllocator) {
fRecordTimeSubRunAllocator = std::make_unique<GrSubRunAllocator>();
}
return {fRecordTimeAllocator.get(), fRecordTimeSubRunAllocator.get()};
}
GrRecordingContext::OwnedArenas&& GrRecordingContext::detachArenas() {
return std::move(fArenas);
}
GrTextBlobCache* GrRecordingContext::getTextBlobCache() {
return fThreadSafeProxy->priv().getTextBlobCache();
}
const GrTextBlobCache* GrRecordingContext::getTextBlobCache() const {
return fThreadSafeProxy->priv().getTextBlobCache();
}
GrThreadSafeCache* GrRecordingContext::threadSafeCache() {
return fThreadSafeProxy->priv().threadSafeCache();
}
const GrThreadSafeCache* GrRecordingContext::threadSafeCache() const {
return fThreadSafeProxy->priv().threadSafeCache();
}
void GrRecordingContext::addOnFlushCallbackObject(GrOnFlushCallbackObject* onFlushCBObject) {
this->drawingManager()->addOnFlushCallbackObject(onFlushCBObject);
}
////////////////////////////////////////////////////////////////////////////////
int GrRecordingContext::maxTextureSize() const { return this->caps()->maxTextureSize(); }
int GrRecordingContext::maxRenderTargetSize() const { return this->caps()->maxRenderTargetSize(); }
bool GrRecordingContext::colorTypeSupportedAsImage(SkColorType colorType) const {
GrBackendFormat format =
this->caps()->getDefaultBackendFormat(SkColorTypeToGrColorType(colorType),
GrRenderable::kNo);
return format.isValid();
}
///////////////////////////////////////////////////////////////////////////////////////////////////
#ifdef SK_ENABLE_DUMP_GPU
#include "src/utils/SkJSONWriter.h"
void GrRecordingContext::dumpJSON(SkJSONWriter* writer) const {
writer->beginObject();
#if GR_GPU_STATS
writer->appendS32("path_masks_generated", this->stats()->numPathMasksGenerated());
writer->appendS32("path_mask_cache_hits", this->stats()->numPathMaskCacheHits());
#endif
writer->endObject();
}
#else
void GrRecordingContext::dumpJSON(SkJSONWriter*) const { }
#endif
#if GR_TEST_UTILS
#if GR_GPU_STATS
void GrRecordingContext::Stats::dump(SkString* out) const {
out->appendf("Num Path Masks Generated: %d\n", fNumPathMasksGenerated);
out->appendf("Num Path Mask Cache Hits: %d\n", fNumPathMaskCacheHits);
}
void GrRecordingContext::Stats::dumpKeyValuePairs(SkTArray<SkString>* keys,
SkTArray<double>* values) const {
keys->push_back(SkString("path_masks_generated"));
values->push_back(fNumPathMasksGenerated);
keys->push_back(SkString("path_mask_cache_hits"));
values->push_back(fNumPathMaskCacheHits);
}
void GrRecordingContext::DMSAAStats::dumpKeyValuePairs(SkTArray<SkString>* keys,
SkTArray<double>* values) const {
keys->push_back(SkString("dmsaa_render_passes"));
values->push_back(fNumRenderPasses);
keys->push_back(SkString("dmsaa_multisample_render_passes"));
values->push_back(fNumMultisampleRenderPasses);
for (const auto& [name, count] : fTriggerCounts) {
keys->push_back(SkStringPrintf("dmsaa_trigger_%s", name.c_str()));
values->push_back(count);
}
}
void GrRecordingContext::DMSAAStats::dump() const {
SkDebugf("DMSAA Render Passes: %d\n", fNumRenderPasses);
SkDebugf("DMSAA Multisample Render Passes: %d\n", fNumMultisampleRenderPasses);
if (!fTriggerCounts.empty()) {
SkDebugf("DMSAA Triggers:\n");
for (const auto& [name, count] : fTriggerCounts) {
SkDebugf(" %s: %d\n", name.c_str(), count);
}
}
}
void GrRecordingContext::DMSAAStats::merge(const DMSAAStats& stats) {
fNumRenderPasses += stats.fNumRenderPasses;
fNumMultisampleRenderPasses += stats.fNumMultisampleRenderPasses;
for (const auto& [name, count] : stats.fTriggerCounts) {
fTriggerCounts[name] += count;
}
}
#endif // GR_GPU_STATS
#endif // GR_TEST_UTILS