123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501 |
- /*
- * Copyright 2011 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
- #include "include/core/SkTraceMemoryDump.h"
- #include "include/gpu/GrBackendSemaphore.h"
- #include "include/gpu/GrContext.h"
- #include "include/private/SkDeferredDisplayList.h"
- #include "include/private/SkImageInfoPriv.h"
- #include "src/core/SkMakeUnique.h"
- #include "src/core/SkTaskGroup.h"
- #include "src/gpu/GrDrawingManager.h"
- #include "src/gpu/GrGpu.h"
- #include "src/gpu/GrMemoryPool.h"
- #include "src/gpu/GrPathRendererChain.h"
- #include "src/gpu/GrProxyProvider.h"
- #include "src/gpu/GrRenderTargetProxy.h"
- #include "src/gpu/GrResourceCache.h"
- #include "src/gpu/GrResourceProvider.h"
- #include "src/gpu/GrSemaphore.h"
- #include "src/gpu/GrShaderUtils.h"
- #include "src/gpu/GrSoftwarePathRenderer.h"
- #include "src/gpu/GrTracing.h"
- #include "src/gpu/SkGr.h"
- #include "src/gpu/ccpr/GrCoverageCountingPathRenderer.h"
- #include "src/gpu/effects/GrSkSLFP.h"
- #include "src/gpu/text/GrTextBlobCache.h"
- #include "src/gpu/text/GrTextContext.h"
- #include "src/image/SkSurface_Gpu.h"
- #include <atomic>
- #include <unordered_map>
- #define ASSERT_OWNED_PROXY(P) \
- SkASSERT(!(P) || !((P)->peekTexture()) || (P)->peekTexture()->getContext() == this)
- #define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == this)
- #define ASSERT_SINGLE_OWNER \
- SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(this->singleOwner());)
- #define RETURN_IF_ABANDONED if (this->abandoned()) { return; }
- #define RETURN_FALSE_IF_ABANDONED if (this->abandoned()) { return false; }
- #define RETURN_NULL_IF_ABANDONED if (this->abandoned()) { return nullptr; }
- ////////////////////////////////////////////////////////////////////////////////
- GrContext::GrContext(GrBackendApi backend, const GrContextOptions& options, int32_t contextID)
- : INHERITED(backend, options, contextID) {
- fResourceCache = nullptr;
- fResourceProvider = nullptr;
- }
- GrContext::~GrContext() {
- ASSERT_SINGLE_OWNER
- if (this->drawingManager()) {
- this->drawingManager()->cleanup();
- }
- delete fResourceProvider;
- delete fResourceCache;
- }
- bool GrContext::init(sk_sp<const GrCaps> caps, sk_sp<GrSkSLFPFactoryCache> FPFactoryCache) {
- ASSERT_SINGLE_OWNER
- SkASSERT(fThreadSafeProxy); // needs to have been initialized by derived classes
- SkASSERT(this->proxyProvider());
- if (!INHERITED::init(std::move(caps), std::move(FPFactoryCache))) {
- return false;
- }
- SkASSERT(this->caps());
- SkASSERT(this->getGrStrikeCache());
- SkASSERT(this->getTextBlobCache());
- if (fGpu) {
- fResourceCache = new GrResourceCache(this->caps(), this->singleOwner(), this->contextID());
- fResourceProvider = new GrResourceProvider(fGpu.get(), fResourceCache, this->singleOwner());
- }
- if (fResourceCache) {
- fResourceCache->setProxyProvider(this->proxyProvider());
- }
- fDidTestPMConversions = false;
- // DDL TODO: we need to think through how the task group & persistent cache
- // get passed on to/shared between all the DDLRecorders created with this context.
- if (this->options().fExecutor) {
- fTaskGroup = skstd::make_unique<SkTaskGroup>(*this->options().fExecutor);
- }
- fPersistentCache = this->options().fPersistentCache;
- fShaderErrorHandler = this->options().fShaderErrorHandler;
- if (!fShaderErrorHandler) {
- fShaderErrorHandler = GrShaderUtils::DefaultShaderErrorHandler();
- }
- return true;
- }
- sk_sp<GrContextThreadSafeProxy> GrContext::threadSafeProxy() {
- return fThreadSafeProxy;
- }
- //////////////////////////////////////////////////////////////////////////////
- void GrContext::abandonContext() {
- if (this->abandoned()) {
- return;
- }
- INHERITED::abandonContext();
- fResourceProvider->abandon();
- // Need to cleanup the drawing manager first so all the render targets
- // will be released/forgotten before they too are abandoned.
- this->drawingManager()->cleanup();
- // abandon first to so destructors
- // don't try to free the resources in the API.
- fResourceCache->abandonAll();
- fGpu->disconnect(GrGpu::DisconnectType::kAbandon);
- }
- void GrContext::releaseResourcesAndAbandonContext() {
- if (this->abandoned()) {
- return;
- }
- INHERITED::abandonContext();
- fResourceProvider->abandon();
- // Need to cleanup the drawing manager first so all the render targets
- // will be released/forgotten before they too are abandoned.
- this->drawingManager()->cleanup();
- // Release all resources in the backend 3D API.
- fResourceCache->releaseAll();
- fGpu->disconnect(GrGpu::DisconnectType::kCleanup);
- }
- void GrContext::resetGLTextureBindings() {
- if (this->abandoned() || this->backend() != GrBackendApi::kOpenGL) {
- return;
- }
- fGpu->resetTextureBindings();
- }
- void GrContext::resetContext(uint32_t state) {
- ASSERT_SINGLE_OWNER
- fGpu->markContextDirty(state);
- }
- void GrContext::freeGpuResources() {
- ASSERT_SINGLE_OWNER
- // TODO: the glyph cache doesn't hold any GpuResources so this call should not be needed here.
- // Some slack in the GrTextBlob's implementation requires it though. That could be fixed.
- this->getGrStrikeCache()->freeAll();
- this->drawingManager()->freeGpuResources();
- fResourceCache->purgeAllUnlocked();
- }
- void GrContext::purgeUnlockedResources(bool scratchResourcesOnly) {
- ASSERT_SINGLE_OWNER
- fResourceCache->purgeUnlockedResources(scratchResourcesOnly);
- fResourceCache->purgeAsNeeded();
- // The textBlob Cache doesn't actually hold any GPU resource but this is a convenient
- // place to purge stale blobs
- this->getTextBlobCache()->purgeStaleBlobs();
- }
- void GrContext::performDeferredCleanup(std::chrono::milliseconds msNotUsed) {
- TRACE_EVENT0("skia.gpu", TRACE_FUNC);
- ASSERT_SINGLE_OWNER
- auto purgeTime = GrStdSteadyClock::now() - msNotUsed;
- fResourceCache->purgeAsNeeded();
- fResourceCache->purgeResourcesNotUsedSince(purgeTime);
- if (auto ccpr = this->drawingManager()->getCoverageCountingPathRenderer()) {
- ccpr->purgeCacheEntriesOlderThan(this->proxyProvider(), purgeTime);
- }
- // The textBlob Cache doesn't actually hold any GPU resource but this is a convenient
- // place to purge stale blobs
- this->getTextBlobCache()->purgeStaleBlobs();
- }
- void GrContext::purgeUnlockedResources(size_t bytesToPurge, bool preferScratchResources) {
- ASSERT_SINGLE_OWNER
- fResourceCache->purgeUnlockedResources(bytesToPurge, preferScratchResources);
- }
- void GrContext::getResourceCacheUsage(int* resourceCount, size_t* resourceBytes) const {
- ASSERT_SINGLE_OWNER
- if (resourceCount) {
- *resourceCount = fResourceCache->getBudgetedResourceCount();
- }
- if (resourceBytes) {
- *resourceBytes = fResourceCache->getBudgetedResourceBytes();
- }
- }
- size_t GrContext::getResourceCachePurgeableBytes() const {
- ASSERT_SINGLE_OWNER
- return fResourceCache->getPurgeableBytes();
- }
- size_t GrContext::ComputeTextureSize(SkColorType type, int width, int height, GrMipMapped mipMapped,
- bool useNextPow2) {
- int colorSamplesPerPixel = 1;
- return GrSurface::ComputeSize(SkColorType2GrPixelConfig(type), width, height,
- colorSamplesPerPixel, mipMapped, useNextPow2);
- }
- ////////////////////////////////////////////////////////////////////////////////
- int GrContext::maxTextureSize() const { return this->caps()->maxTextureSize(); }
- int GrContext::maxRenderTargetSize() const { return this->caps()->maxRenderTargetSize(); }
- bool GrContext::colorTypeSupportedAsImage(SkColorType colorType) const {
- GrPixelConfig config = SkColorType2GrPixelConfig(colorType);
- return this->caps()->isConfigTexturable(config);
- }
- int GrContext::maxSurfaceSampleCountForColorType(SkColorType colorType) const {
- GrPixelConfig config = SkColorType2GrPixelConfig(colorType);
- return this->caps()->maxRenderTargetSampleCount(config);
- }
- ////////////////////////////////////////////////////////////////////////////////
- bool GrContext::wait(int numSemaphores, const GrBackendSemaphore waitSemaphores[]) {
- if (!fGpu || fGpu->caps()->semaphoreSupport()) {
- return false;
- }
- for (int i = 0; i < numSemaphores; ++i) {
- sk_sp<GrSemaphore> sema = fResourceProvider->wrapBackendSemaphore(
- waitSemaphores[i], GrResourceProvider::SemaphoreWrapType::kWillWait,
- kAdopt_GrWrapOwnership);
- fGpu->waitSemaphore(std::move(sema));
- }
- return true;
- }
- ////////////////////////////////////////////////////////////////////////////////
- GrSemaphoresSubmitted GrContext::flush(const GrFlushInfo& info,
- const GrPrepareForExternalIORequests& externalRequests) {
- ASSERT_SINGLE_OWNER
- if (this->abandoned()) {
- return GrSemaphoresSubmitted::kNo;
- }
- return this->drawingManager()->flush(nullptr, 0, SkSurface::BackendSurfaceAccess::kNoAccess,
- info, externalRequests);
- }
- ////////////////////////////////////////////////////////////////////////////////
- void GrContext::checkAsyncWorkCompletion() {
- if (fGpu) {
- fGpu->checkFinishProcs();
- }
- }
- ////////////////////////////////////////////////////////////////////////////////
- void GrContext::storeVkPipelineCacheData() {
- if (fGpu) {
- fGpu->storeVkPipelineCacheData();
- }
- }
- ////////////////////////////////////////////////////////////////////////////////
- bool GrContext::supportsDistanceFieldText() const {
- return this->caps()->shaderCaps()->supportsDistanceFieldText();
- }
- //////////////////////////////////////////////////////////////////////////////
- // DDL TODO: remove 'maxResources'
- void GrContext::getResourceCacheLimits(int* maxResources, size_t* maxResourceBytes) const {
- ASSERT_SINGLE_OWNER
- if (maxResources) {
- *maxResources = fResourceCache->getMaxResourceCount();
- }
- if (maxResourceBytes) {
- *maxResourceBytes = fResourceCache->getMaxResourceBytes();
- }
- }
- void GrContext::setResourceCacheLimits(int maxResources, size_t maxResourceBytes) {
- ASSERT_SINGLE_OWNER
- fResourceCache->setLimits(maxResources, maxResourceBytes);
- }
- //////////////////////////////////////////////////////////////////////////////
- void GrContext::dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const {
- ASSERT_SINGLE_OWNER
- fResourceCache->dumpMemoryStatistics(traceMemoryDump);
- traceMemoryDump->dumpNumericValue("skia/gr_text_blob_cache", "size", "bytes",
- this->getTextBlobCache()->usedBytes());
- }
- //////////////////////////////////////////////////////////////////////////////
- GrBackendTexture GrContext::createBackendTexture(int width, int height,
- const GrBackendFormat& backendFormat,
- GrMipMapped mipMapped,
- GrRenderable renderable,
- GrProtected isProtected) {
- TRACE_EVENT0("skia.gpu", TRACE_FUNC);
- if (!this->asDirectContext()) {
- return GrBackendTexture();
- }
- if (this->abandoned()) {
- return GrBackendTexture();
- }
- if (!backendFormat.isValid()) {
- return GrBackendTexture();
- }
- return fGpu->createBackendTexture(width, height, backendFormat,
- mipMapped, renderable,
- nullptr, 0, nullptr, isProtected);
- }
- GrBackendTexture GrContext::createBackendTexture(int width, int height,
- SkColorType colorType,
- GrMipMapped mipMapped,
- GrRenderable renderable,
- GrProtected isProtected) {
- if (!this->asDirectContext()) {
- return GrBackendTexture();
- }
- if (this->abandoned()) {
- return GrBackendTexture();
- }
- GrBackendFormat format =
- this->caps()->getBackendFormatFromColorType(SkColorTypeToGrColorType(colorType));
- if (!format.isValid()) {
- return GrBackendTexture();
- }
- return this->createBackendTexture(width, height, format, mipMapped, renderable, isProtected);
- }
- GrBackendTexture GrContext::createBackendTexture(const SkSurfaceCharacterization& c) {
- const GrCaps* caps = this->caps();
- if (!this->asDirectContext() || !c.isValid()) {
- return GrBackendTexture();
- }
- if (this->abandoned()) {
- return GrBackendTexture();
- }
- if (c.usesGLFBO0()) {
- // If we are making the surface we will never use FBO0.
- return GrBackendTexture();
- }
- if (c.vulkanSecondaryCBCompatible()) {
- return {};
- }
- const GrBackendFormat format =
- caps->getBackendFormatFromColorType(SkColorTypeToGrColorType(c.colorType()));
- if (!format.isValid()) {
- return GrBackendTexture();
- }
- if (!SkSurface_Gpu::Valid(caps, format)) {
- return GrBackendTexture();
- }
- GrBackendTexture result = this->createBackendTexture(c.width(), c.height(), format,
- GrMipMapped(c.isMipMapped()),
- GrRenderable::kYes,
- c.isProtected());
- SkASSERT(c.isCompatible(result));
- return result;
- }
- GrBackendTexture GrContext::createBackendTexture(const SkSurfaceCharacterization& c,
- const SkColor4f& color) {
- const GrCaps* caps = this->caps();
- if (!this->asDirectContext() || !c.isValid()) {
- return GrBackendTexture();
- }
- if (this->abandoned()) {
- return GrBackendTexture();
- }
- if (c.usesGLFBO0()) {
- // If we are making the surface we will never use FBO0.
- return GrBackendTexture();
- }
- if (c.vulkanSecondaryCBCompatible()) {
- return {};
- }
- const GrBackendFormat format =
- caps->getBackendFormatFromColorType(SkColorTypeToGrColorType(c.colorType()));
- if (!format.isValid()) {
- return GrBackendTexture();
- }
- if (!SkSurface_Gpu::Valid(caps, format)) {
- return GrBackendTexture();
- }
- GrBackendTexture result = this->createBackendTexture(c.width(), c.height(), format, color,
- GrMipMapped(c.isMipMapped()),
- GrRenderable::kYes,
- c.isProtected());
- SkASSERT(c.isCompatible(result));
- return result;
- }
- GrBackendTexture GrContext::createBackendTexture(int width, int height,
- const GrBackendFormat& backendFormat,
- const SkColor4f& color,
- GrMipMapped mipMapped,
- GrRenderable renderable,
- GrProtected isProtected) {
- TRACE_EVENT0("skia.gpu", TRACE_FUNC);
- if (!this->asDirectContext()) {
- return GrBackendTexture();
- }
- if (this->abandoned()) {
- return GrBackendTexture();
- }
- if (!backendFormat.isValid()) {
- return GrBackendTexture();
- }
- return fGpu->createBackendTexture(width, height, backendFormat,
- mipMapped, renderable,
- nullptr, 0, &color, isProtected);
- }
- GrBackendTexture GrContext::createBackendTexture(int width, int height,
- SkColorType colorType,
- const SkColor4f& color,
- GrMipMapped mipMapped,
- GrRenderable renderable,
- GrProtected isProtected) {
- if (!this->asDirectContext()) {
- return GrBackendTexture();
- }
- if (this->abandoned()) {
- return GrBackendTexture();
- }
- GrColorType ct = SkColorTypeToGrColorType(colorType);
- GrBackendFormat format = this->caps()->getBackendFormatFromColorType(ct);
- if (!format.isValid()) {
- return GrBackendTexture();
- }
- SkColor4f swizzledColor = this->caps()->getOutputSwizzle(format, ct).applyTo(color);
- return this->createBackendTexture(width, height, format, swizzledColor, mipMapped, renderable,
- isProtected);
- }
- void GrContext::deleteBackendTexture(GrBackendTexture backendTex) {
- TRACE_EVENT0("skia.gpu", TRACE_FUNC);
- if (this->abandoned() || !backendTex.isValid()) {
- return;
- }
- fGpu->deleteBackendTexture(backendTex);
- }
|