sk_sp<SkColorSpace> SkImage_Lazy::getColorSpace(GrContext* ctx, SkColorSpace* dstColorSpace) { if (!dstColorSpace) { // In legacy mode, we do no modification to the image's color space or encoding. // Subsequent legacy drawing is likely to ignore the color space, but some clients // may want to know what space the image data is in, so return it. return fInfo.refColorSpace(); } else { CachedFormat format = this->chooseCacheFormat(dstColorSpace, ctx->caps()); SkImageInfo cacheInfo = this->buildCacheInfo(format); return cacheInfo.refColorSpace(); } }
sk_sp<SkImage> SkImage_Lazy::onMakeSubset(const SkIRect& subset) const { SkASSERT(fInfo.bounds().contains(subset)); SkASSERT(fInfo.bounds() != subset); const SkIRect generatorSubset = subset.makeOffset(fOrigin.x(), fOrigin.y()); Validator validator(fSharedGenerator, &generatorSubset, fInfo.refColorSpace()); return validator ? sk_sp<SkImage>(new SkImage_Lazy(&validator)) : nullptr; }
SkTransferFunctionBehavior SkImage_Lazy::getGeneratorBehaviorAndInfo(SkImageInfo* generatorImageInfo) const { if (generatorImageInfo->colorSpace()) { return SkTransferFunctionBehavior::kRespect; } // Only specify an output color space if color conversion can be done on the color type. switch (generatorImageInfo->colorType()) { case kRGBA_8888_SkColorType: case kBGRA_8888_SkColorType: case kRGBA_F16_SkColorType: case kRGB_565_SkColorType: *generatorImageInfo = generatorImageInfo->makeColorSpace(fInfo.refColorSpace()); break; default: break; } return SkTransferFunctionBehavior::kIgnore; }
sk_sp<SkImage> SkImage::MakeTextureFromMipMap(GrContext* ctx, const SkImageInfo& info, const GrMipLevel* texels, int mipLevelCount, SkBudgeted budgeted, SkDestinationSurfaceColorMode colorMode) { SkASSERT(mipLevelCount >= 1); if (!ctx) { return nullptr; } sk_sp<GrTextureProxy> proxy(GrUploadMipMapToTextureProxy(ctx, info, texels, mipLevelCount, colorMode)); if (!proxy) { return nullptr; } SkASSERT(proxy->priv().isExact()); return sk_make_sp<SkImage_Gpu>(ctx, kNeedNewImageUniqueID, info.alphaType(), std::move(proxy), info.refColorSpace(), budgeted); }
std::unique_ptr<SkCrossContextImageData> SkCrossContextImageData::MakeFromEncoded( GrContext* context, sk_sp<SkData> encoded, SkColorSpace* dstColorSpace) { sk_sp<SkImage> codecImage = SkImage::MakeFromEncoded(std::move(encoded)); if (!codecImage) { return nullptr; } // Some backends or drivers don't support (safely) moving resources between contexts if (!context->caps()->crossContextTextureSupport()) { return std::unique_ptr<SkCrossContextImageData>( new SkCrossContextImageData(std::move(codecImage))); } sk_sp<SkImage> textureImage = codecImage->makeTextureImage(context, dstColorSpace); if (!textureImage) { // TODO: Force decode to raster here? Do mip-mapping, like getDeferredTextureImageData? return std::unique_ptr<SkCrossContextImageData>( new SkCrossContextImageData(std::move(codecImage))); } // Crack open the gpu image, extract the backend data, stick it in the SkCCID GrTexture* texture = as_IB(textureImage)->peekTexture(); SkASSERT(texture); GrBackendTextureDesc desc; desc.fFlags = kNone_GrBackendTextureFlag; desc.fOrigin = texture->origin(); desc.fWidth = texture->width(); desc.fHeight = texture->height(); desc.fConfig = texture->config(); desc.fSampleCnt = 0; context->contextPriv().prepareSurfaceForExternalIO(as_IB(textureImage)->peekProxy()); auto textureData = texture->texturePriv().detachBackendTexture(); SkASSERT(textureData); SkImageInfo info = as_IB(textureImage)->onImageInfo(); return std::unique_ptr<SkCrossContextImageData>(new SkCrossContextImageData( desc, std::move(textureData), info.alphaType(), info.refColorSpace())); }
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; }