Example #1
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();
Example #2
sk_sp<SkImage> SkImage_Lazy::onMakeSubset(const SkIRect& subset) const {
    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;
Example #3
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());
    return SkTransferFunctionBehavior::kIgnore;
Example #4
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,
    if (!proxy) {
        return nullptr;

    return sk_make_sp<SkImage_Gpu>(ctx, kNeedNewImageUniqueID,
                                   info.alphaType(), std::move(proxy),
                                   info.refColorSpace(), budgeted);
Example #5
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();

    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;

    auto textureData = texture->texturePriv().detachBackendTexture();

    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.
        image = sk_make_sp<SkImage_Gpu>(ctx, kNeedNewImageUniqueID,
                                        info.alphaType(), std::move(srcProxy),
                                        info.refColorSpace(), budgeted);
    return image;