bool SkSurface_Gpu::onCharacterize(SkSurfaceCharacterization* data) const { GrRenderTargetContext* rtc = fDevice->accessRenderTargetContext(); GrContext* ctx = fDevice->context(); int maxResourceCount; size_t maxResourceBytes; ctx->getResourceCacheLimits(&maxResourceCount, &maxResourceBytes); bool mipmapped = rtc->asTextureProxy() ? GrMipMapped::kYes == rtc->asTextureProxy()->mipMapped() : false; data->set(ctx->threadSafeProxy(), maxResourceBytes, rtc->origin(), rtc->width(), rtc->height(), rtc->colorSpaceInfo().config(), rtc->fsaaType(), rtc->numStencilSamples(), SkSurfaceCharacterization::Textureable(SkToBool(rtc->asTextureProxy())), SkSurfaceCharacterization::MipMapped(mipmapped), rtc->colorSpaceInfo().refColorSpace(), this->props()); return true; }
bool SkSurface_Gpu::isCompatible(const SkSurfaceCharacterization& data) const { GrRenderTargetContext* rtc = fDevice->accessRenderTargetContext(); GrContext* ctx = fDevice->context(); if (!data.isValid()) { return false; } // As long as the current state if the context allows for greater or equal resources, // we allow the DDL to be replayed. // DDL TODO: should we just remove the resource check and ignore the cache limits on playback? int maxResourceCount; size_t maxResourceBytes; ctx->getResourceCacheLimits(&maxResourceCount, &maxResourceBytes); if (data.isTextureable()) { if (!rtc->asTextureProxy()) { // If the characterization was textureable we require the replay dest to also be // textureable. If the characterized surface wasn't textureable we allow the replay // dest to be textureable. return false; } if (data.isMipMapped() && GrMipMapped::kNo == rtc->asTextureProxy()->mipMapped()) { // Fail if the DDL's surface was mipmapped but the replay surface is not. // Allow drawing to proceed if the DDL was not mipmapped but the replay surface is. return false; } } return data.contextInfo() && data.contextInfo()->matches(ctx) && data.cacheMaxResourceBytes() <= maxResourceBytes && data.origin() == rtc->origin() && data.width() == rtc->width() && data.height() == rtc->height() && data.config() == rtc->colorSpaceInfo().config() && data.fsaaType() == rtc->fsaaType() && data.stencilCount() == rtc->numStencilSamples() && SkColorSpace::Equals(data.colorSpace(), rtc->colorSpaceInfo().colorSpace()) && data.surfaceProps() == rtc->surfaceProps(); }
sk_sp<SkImage> SkSurface_Gpu::onNewImageSnapshot() { GrRenderTargetContext* rtc = fDevice->accessRenderTargetContext(); if (!rtc) { return nullptr; } GrContext* ctx = fDevice->context(); if (!rtc->asSurfaceProxy()) { return nullptr; } SkBudgeted budgeted = rtc->asSurfaceProxy()->isBudgeted(); sk_sp<GrTextureProxy> srcProxy = rtc->asTextureProxyRef(); // If the original render target is a buffer originally created by the client, then we don't // want to ever retarget the SkSurface at another buffer we create. Force a copy now to avoid // copy-on-write. if (!srcProxy || rtc->priv().refsWrappedObjects()) { SkASSERT(rtc->origin() == rtc->asSurfaceProxy()->origin()); srcProxy = GrSurfaceProxy::Copy(ctx, rtc->asSurfaceProxy(), rtc->mipMapped(), budgeted); } const SkImageInfo info = fDevice->imageInfo(); sk_sp<SkImage> image; if (srcProxy) { // The renderTargetContext coming out of SkGpuDevice should always be exact and the // above copy creates a kExact surfaceContext. SkASSERT(srcProxy->priv().isExact()); image = sk_make_sp<SkImage_Gpu>(ctx, kNeedNewImageUniqueID, info.alphaType(), std::move(srcProxy), info.refColorSpace(), budgeted); } return image; }