SkImage_Gpu.cpp revision a8ac92418807e3d46a45413459e6895160134c1d
15d4ba8869476831ee73b15a052af8003d0a1fa2ereed@google.com/*
25d4ba8869476831ee73b15a052af8003d0a1fa2ereed@google.com * Copyright 2012 Google Inc.
35d4ba8869476831ee73b15a052af8003d0a1fa2ereed@google.com *
45d4ba8869476831ee73b15a052af8003d0a1fa2ereed@google.com * Use of this source code is governed by a BSD-style license that can be
55d4ba8869476831ee73b15a052af8003d0a1fa2ereed@google.com * found in the LICENSE file.
65d4ba8869476831ee73b15a052af8003d0a1fa2ereed@google.com */
75d4ba8869476831ee73b15a052af8003d0a1fa2ereed@google.com
833e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume#include <cstddef>
933e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume#include <cstring>
1033e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume#include <type_traits>
1133e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume
12c5035e70cc3fb290f95fd1c052c637aa0dbaf9earobertphillips#include "SkAutoPixmapStorage.h"
137ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel#include "GrBackendSurface.h"
1413dddce65fd87a8175a209a49f35615735a2886aBrian Osman#include "GrBackendTextureImageGenerator.h"
157e910df7f133e80293117bdd069ed25998d10f8cStan Iliev#include "GrAHardwareBufferImageGenerator.h"
163b66ab6f9fdc6eacdf0ee1921da28751de30c018Brian Osman#include "GrBitmapTextureMaker.h"
17856e9d921462136da8562f8f122d42e114cd4710reed#include "GrCaps.h"
1897b6b0730dcb0feee9224ff04eb3985ca4bd0216robertphillips@google.com#include "GrContext.h"
19e2f7d1899d890c2f08571e1bd6c7fa2c5ea1be0bRobert Phillips#include "GrContextPriv.h"
202c2bc11aea4dfcd7ee2f5859838a2aa0a56939e0Brian Osman#include "GrGpu.h"
213b66ab6f9fdc6eacdf0ee1921da28751de30c018Brian Osman#include "GrImageTextureMaker.h"
221105224f9701e57ec5ce0354d6a380b664f5c638Brian Osman#include "GrRenderTargetContext.h"
2332342f032e1dfd133040324f851f0365f9d4cb51Brian Osman#include "GrResourceProvider.h"
24fe3b51636d4216c4ea6cb74ed0964c1d315ca487Brian Osman#include "GrSemaphore.h"
25e8e54580c3c91fd485187af040af118aa5153261Brian Osman#include "GrTextureAdjuster.h"
26646e4293f06d9de6d44dbfa3c32cdc15a6f5906eRobert Phillips#include "GrTexture.h"
27bc7a4fb06780f9829b4b21470fe6f0503d2297cdRobert Phillips#include "GrTextureProxy.h"
2863954c9944a5eed4527e0ed368f4e501faf2c625Brian Osman#include "effects/GrNonlinearColorSpaceXformEffect.h"
29f267c1efe7de7a8e71404afde6cbf93c3808d267bsalomon#include "effects/GrYUVEffect.h"
30993a4216a6014b9de8f4d8120360c94550dc6761bsalomon#include "SkCanvas.h"
31262a71b7f95ce98ff3dd8dba845afbd724470903reed#include "SkBitmapCache.h"
323b65598bceb65736486db27ed49a56d787032747Brian Osman#include "SkGr.h"
33262a71b7f95ce98ff3dd8dba845afbd724470903reed#include "SkImage_Gpu.h"
347992da32f02f90e0ac9ab6914eb31676b502eb71Brian Osman#include "SkImageCacherator.h"
35cb6266b5aa5bbfd880532f08eec83b0c585e873fMatt Sarett#include "SkImageInfoPriv.h"
36b4da01d8f719f3c43d492e8f62a7e2c861e9ef27ericrk#include "SkMipMap.h"
376f1216ac158e36a3a1cc805e7f899c755c5b98a2reed#include "SkPixelRef.h"
3803dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarett#include "SkReadPixelsRec.h"
39993a4216a6014b9de8f4d8120360c94550dc6761bsalomon
40b726d58efc91c4eefa5cea0881a823ee108db8fdRobert PhillipsSkImage_Gpu::SkImage_Gpu(GrContext* context, uint32_t uniqueID, SkAlphaType at,
41b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips                         sk_sp<GrTextureProxy> proxy,
42b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips                         sk_sp<SkColorSpace> colorSpace, SkBudgeted budgeted)
43b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips    : INHERITED(proxy->width(), proxy->height(), uniqueID)
44b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips    , fContext(context)
45b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips    , fProxy(std::move(proxy))
46b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips    , fAlphaType(at)
47b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips    , fBudgeted(budgeted)
48b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips    , fColorSpace(std::move(colorSpace))
49b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips    , fAddedRasterVersionToCache(false) {
50c9b5f8b1522e72449d704d30ed6aee4fc6211ee8reed}
51cef04f818820e59fb534eb226f967f72497845d3piotaixr
526f1216ac158e36a3a1cc805e7f899c755c5b98a2reedSkImage_Gpu::~SkImage_Gpu() {
536f1216ac158e36a3a1cc805e7f899c755c5b98a2reed    if (fAddedRasterVersionToCache.load()) {
546f1216ac158e36a3a1cc805e7f899c755c5b98a2reed        SkNotifyBitmapGenIDIsStale(this->uniqueID());
556f1216ac158e36a3a1cc805e7f899c755c5b98a2reed    }
566f1216ac158e36a3a1cc805e7f899c755c5b98a2reed}
576f1216ac158e36a3a1cc805e7f899c755c5b98a2reed
58396fcdba14a0101ed43dcc3863585bf50c4ed6ccbrianosmanSkImageInfo SkImage_Gpu::onImageInfo() const {
59396fcdba14a0101ed43dcc3863585bf50c4ed6ccbrianosman    SkColorType ct;
60b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips    if (!GrPixelConfigToColorType(fProxy->config(), &ct)) {
61396fcdba14a0101ed43dcc3863585bf50c4ed6ccbrianosman        ct = kUnknown_SkColorType;
62396fcdba14a0101ed43dcc3863585bf50c4ed6ccbrianosman    }
63b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips    return SkImageInfo::Make(fProxy->width(), fProxy->height(), ct, fAlphaType, fColorSpace);
64396fcdba14a0101ed43dcc3863585bf50c4ed6ccbrianosman}
65396fcdba14a0101ed43dcc3863585bf50c4ed6ccbrianosman
666251771ebc5c4d7c98af3e2f3f2e7b22e490c1d5Brian Osmanbool SkImage_Gpu::getROPixels(SkBitmap* dst, SkColorSpace*, CachingHint chint) const {
676251771ebc5c4d7c98af3e2f3f2e7b22e490c1d5Brian Osman    // The SkColorSpace parameter "dstColorSpace" is really just a hint about how/where the bitmap
686251771ebc5c4d7c98af3e2f3f2e7b22e490c1d5Brian Osman    // will be used. The client doesn't expect that we convert to that color space, it's intended
696251771ebc5c4d7c98af3e2f3f2e7b22e490c1d5Brian Osman    // for codec-backed images, to drive our decoding heuristic. In theory we *could* read directly
706251771ebc5c4d7c98af3e2f3f2e7b22e490c1d5Brian Osman    // into that color space (to save the client some effort in whatever they're about to do), but
716251771ebc5c4d7c98af3e2f3f2e7b22e490c1d5Brian Osman    // that would make our use of the bitmap cache incorrect (or much less efficient, assuming we
726251771ebc5c4d7c98af3e2f3f2e7b22e490c1d5Brian Osman    // rolled the dstColorSpace into the key).
735fa3d6d4b15fd6417de877561f5e4bca422e383cMike Reed    const auto desc = SkBitmapCacheDesc::Make(this);
745fa3d6d4b15fd6417de877561f5e4bca422e383cMike Reed    if (SkBitmapCache::Find(desc, dst)) {
756f1216ac158e36a3a1cc805e7f899c755c5b98a2reed        SkASSERT(dst->getGenerationID() == this->uniqueID());
766f1216ac158e36a3a1cc805e7f899c755c5b98a2reed        SkASSERT(dst->isImmutable());
776f1216ac158e36a3a1cc805e7f899c755c5b98a2reed        SkASSERT(dst->getPixels());
786f1216ac158e36a3a1cc805e7f899c755c5b98a2reed        return true;
796f1216ac158e36a3a1cc805e7f899c755c5b98a2reed    }
806f1216ac158e36a3a1cc805e7f899c755c5b98a2reed
817a542c559a6e584107b94e6254ac3c7f9f24b591Mike Reed    SkBitmapCache::RecPtr rec = nullptr;
827a542c559a6e584107b94e6254ac3c7f9f24b591Mike Reed    SkPixmap pmap;
837a542c559a6e584107b94e6254ac3c7f9f24b591Mike Reed    if (kAllow_CachingHint == chint) {
846251771ebc5c4d7c98af3e2f3f2e7b22e490c1d5Brian Osman        rec = SkBitmapCache::Alloc(desc, this->onImageInfo(), &pmap);
857a542c559a6e584107b94e6254ac3c7f9f24b591Mike Reed        if (!rec) {
867a542c559a6e584107b94e6254ac3c7f9f24b591Mike Reed            return false;
877a542c559a6e584107b94e6254ac3c7f9f24b591Mike Reed        }
887a542c559a6e584107b94e6254ac3c7f9f24b591Mike Reed    } else {
896251771ebc5c4d7c98af3e2f3f2e7b22e490c1d5Brian Osman        if (!dst->tryAllocPixels(this->onImageInfo()) || !dst->peekPixels(&pmap)) {
907a542c559a6e584107b94e6254ac3c7f9f24b591Mike Reed            return false;
917a542c559a6e584107b94e6254ac3c7f9f24b591Mike Reed        }
92b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips    }
93b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips
942084ffa9a3fa7eb3c7e17ec5b55750be9942bafcBrian Salomon    sk_sp<GrSurfaceContext> sContext = fContext->contextPriv().makeWrappedSurfaceContext(
952084ffa9a3fa7eb3c7e17ec5b55750be9942bafcBrian Salomon                                                                                    fProxy,
962084ffa9a3fa7eb3c7e17ec5b55750be9942bafcBrian Salomon                                                                                    fColorSpace);
97b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips    if (!sContext) {
988b26b99c97473f020df4b9d4ba789e074e06ceddreed        return false;
998b26b99c97473f020df4b9d4ba789e074e06ceddreed    }
100b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips
1017a542c559a6e584107b94e6254ac3c7f9f24b591Mike Reed    if (!sContext->readPixels(pmap.info(), pmap.writable_addr(), pmap.rowBytes(), 0, 0)) {
1028b26b99c97473f020df4b9d4ba789e074e06ceddreed        return false;
1038b26b99c97473f020df4b9d4ba789e074e06ceddreed    }
1046f1216ac158e36a3a1cc805e7f899c755c5b98a2reed
1057a542c559a6e584107b94e6254ac3c7f9f24b591Mike Reed    if (rec) {
1067a542c559a6e584107b94e6254ac3c7f9f24b591Mike Reed        SkBitmapCache::Add(std::move(rec), dst);
107095530389d8211895309107a4f74beefacce638creed        fAddedRasterVersionToCache.store(true);
108095530389d8211895309107a4f74beefacce638creed    }
1098b26b99c97473f020df4b9d4ba789e074e06ceddreed    return true;
110ace135453db02cfe83d7c7bbeaa679f98d18fbe2reed@google.com}
111ace135453db02cfe83d7c7bbeaa679f98d18fbe2reed@google.com
112b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillipssk_sp<GrTextureProxy> SkImage_Gpu::asTextureProxyRef(GrContext* context,
113b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips                                                     const GrSamplerParams& params,
114b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips                                                     SkColorSpace* dstColorSpace,
115b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips                                                     sk_sp<SkColorSpace>* texColorSpace,
116b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips                                                     SkScalar scaleAdjust[2]) const {
11730a38ff737c61799b0f36d2e6ba412f7e612f617Robert Phillips    if (context != fContext) {
118b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips        SkASSERT(0);
119b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips        return nullptr;
120b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips    }
121b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips
1227992da32f02f90e0ac9ab6914eb31676b502eb71Brian Osman    if (texColorSpace) {
1237992da32f02f90e0ac9ab6914eb31676b502eb71Brian Osman        *texColorSpace = this->fColorSpace;
1247992da32f02f90e0ac9ab6914eb31676b502eb71Brian Osman    }
125b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips
1263798c86f6885f0b47fb2e659a43b48a4468a97efRobert Phillips    GrTextureAdjuster adjuster(fContext, fProxy, this->alphaType(), this->bounds(),
1277992da32f02f90e0ac9ab6914eb31676b502eb71Brian Osman                               this->uniqueID(), this->fColorSpace.get());
1283798c86f6885f0b47fb2e659a43b48a4468a97efRobert Phillips    return adjuster.refTextureProxySafeForParams(params, nullptr, scaleAdjust);
12985d9178832f4a64c9d80ffb14cb9dab4fe0fa54areed}
13085d9178832f4a64c9d80ffb14cb9dab4fe0fa54areed
1318b26b99c97473f020df4b9d4ba789e074e06ceddreedstatic void apply_premul(const SkImageInfo& info, void* pixels, size_t rowBytes) {
1328b26b99c97473f020df4b9d4ba789e074e06ceddreed    switch (info.colorType()) {
1338b26b99c97473f020df4b9d4ba789e074e06ceddreed        case kRGBA_8888_SkColorType:
1348b26b99c97473f020df4b9d4ba789e074e06ceddreed        case kBGRA_8888_SkColorType:
1358b26b99c97473f020df4b9d4ba789e074e06ceddreed            break;
1368b26b99c97473f020df4b9d4ba789e074e06ceddreed        default:
1378b26b99c97473f020df4b9d4ba789e074e06ceddreed            return; // nothing to do
1388b26b99c97473f020df4b9d4ba789e074e06ceddreed    }
13997b6b0730dcb0feee9224ff04eb3985ca4bd0216robertphillips@google.com
1408b26b99c97473f020df4b9d4ba789e074e06ceddreed    // SkColor is not necesarily RGBA or BGRA, but it is one of them on little-endian,
1418b26b99c97473f020df4b9d4ba789e074e06ceddreed    // and in either case, the alpha-byte is always in the same place, so we can safely call
1428b26b99c97473f020df4b9d4ba789e074e06ceddreed    // SkPreMultiplyColor()
1438b26b99c97473f020df4b9d4ba789e074e06ceddreed    //
1448b26b99c97473f020df4b9d4ba789e074e06ceddreed    SkColor* row = (SkColor*)pixels;
1458b26b99c97473f020df4b9d4ba789e074e06ceddreed    for (int y = 0; y < info.height(); ++y) {
1468b26b99c97473f020df4b9d4ba789e074e06ceddreed        for (int x = 0; x < info.width(); ++x) {
1478b26b99c97473f020df4b9d4ba789e074e06ceddreed            row[x] = SkPreMultiplyColor(row[x]);
1488b26b99c97473f020df4b9d4ba789e074e06ceddreed        }
1495d4ba8869476831ee73b15a052af8003d0a1fa2ereed@google.com    }
1504af267b11964d4a8acdb232ac46094c84d890e88reed}
151fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1520ae6faa34d73ffc7ebec3d13f0473703bade821bRobert PhillipsGrBackendObject SkImage_Gpu::onGetTextureHandle(bool flushPendingGrContextIO,
1530ae6faa34d73ffc7ebec3d13f0473703bade821bRobert Phillips                                                GrSurfaceOrigin* origin) const {
1547ee385e1dc3cd6a47dc8f7297fef6e175eaba224Robert Phillips    SkASSERT(fProxy);
1550ae6faa34d73ffc7ebec3d13f0473703bade821bRobert Phillips
156eee4d6e4e8cc5c4c79f065abcc3ce609f71238f9Robert Phillips    if (!fProxy->instantiate(fContext->resourceProvider())) {
157eee4d6e4e8cc5c4c79f065abcc3ce609f71238f9Robert Phillips        return 0;
158eee4d6e4e8cc5c4c79f065abcc3ce609f71238f9Robert Phillips    }
159eee4d6e4e8cc5c4c79f065abcc3ce609f71238f9Robert Phillips
160eee4d6e4e8cc5c4c79f065abcc3ce609f71238f9Robert Phillips    GrTexture* texture = fProxy->priv().peekTexture();
161eee4d6e4e8cc5c4c79f065abcc3ce609f71238f9Robert Phillips
162eee4d6e4e8cc5c4c79f065abcc3ce609f71238f9Robert Phillips    if (texture) {
1630ae6faa34d73ffc7ebec3d13f0473703bade821bRobert Phillips        if (flushPendingGrContextIO) {
1647ee385e1dc3cd6a47dc8f7297fef6e175eaba224Robert Phillips            fContext->contextPriv().prepareSurfaceForExternalIO(fProxy.get());
1650ae6faa34d73ffc7ebec3d13f0473703bade821bRobert Phillips        }
1660ae6faa34d73ffc7ebec3d13f0473703bade821bRobert Phillips        if (origin) {
1677ee385e1dc3cd6a47dc8f7297fef6e175eaba224Robert Phillips            *origin = fProxy->origin();
1680ae6faa34d73ffc7ebec3d13f0473703bade821bRobert Phillips        }
169eee4d6e4e8cc5c4c79f065abcc3ce609f71238f9Robert Phillips        return texture->getTextureHandle();
1700ae6faa34d73ffc7ebec3d13f0473703bade821bRobert Phillips    }
1710ae6faa34d73ffc7ebec3d13f0473703bade821bRobert Phillips    return 0;
1720ae6faa34d73ffc7ebec3d13f0473703bade821bRobert Phillips}
1730ae6faa34d73ffc7ebec3d13f0473703bade821bRobert Phillips
1740ae6faa34d73ffc7ebec3d13f0473703bade821bRobert PhillipsGrTexture* SkImage_Gpu::onGetTexture() const {
1750ae6faa34d73ffc7ebec3d13f0473703bade821bRobert Phillips    GrTextureProxy* proxy = this->peekProxy();
1760ae6faa34d73ffc7ebec3d13f0473703bade821bRobert Phillips    if (!proxy) {
1770ae6faa34d73ffc7ebec3d13f0473703bade821bRobert Phillips        return nullptr;
1780ae6faa34d73ffc7ebec3d13f0473703bade821bRobert Phillips    }
1790ae6faa34d73ffc7ebec3d13f0473703bade821bRobert Phillips
180eee4d6e4e8cc5c4c79f065abcc3ce609f71238f9Robert Phillips    if (!proxy->instantiate(fContext->resourceProvider())) {
181eee4d6e4e8cc5c4c79f065abcc3ce609f71238f9Robert Phillips        return nullptr;
182eee4d6e4e8cc5c4c79f065abcc3ce609f71238f9Robert Phillips    }
183eee4d6e4e8cc5c4c79f065abcc3ce609f71238f9Robert Phillips
184eee4d6e4e8cc5c4c79f065abcc3ce609f71238f9Robert Phillips    return proxy->priv().peekTexture();
1850ae6faa34d73ffc7ebec3d13f0473703bade821bRobert Phillips}
1860ae6faa34d73ffc7ebec3d13f0473703bade821bRobert Phillips
18703dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarettbool SkImage_Gpu::onReadPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRB,
188095530389d8211895309107a4f74beefacce638creed                               int srcX, int srcY, CachingHint) const {
18903dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarett    if (!SkImageInfoValidConversion(dstInfo, this->onImageInfo())) {
190cb6266b5aa5bbfd880532f08eec83b0c585e873fMatt Sarett        return false;
191cb6266b5aa5bbfd880532f08eec83b0c585e873fMatt Sarett    }
192cb6266b5aa5bbfd880532f08eec83b0c585e873fMatt Sarett
19303dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarett    SkReadPixelsRec rec(dstInfo, dstPixels, dstRB, srcX, srcY);
19403dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarett    if (!rec.trim(this->width(), this->height())) {
19503dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarett        return false;
19603dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarett    }
19703dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarett
198b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips    // TODO: this seems to duplicate code in GrTextureContext::onReadPixels and
199b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips    // GrRenderTargetContext::onReadPixels
2008b26b99c97473f020df4b9d4ba789e074e06ceddreed    uint32_t flags = 0;
20103dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarett    if (kUnpremul_SkAlphaType == rec.fInfo.alphaType() && kPremul_SkAlphaType == fAlphaType) {
2028b26b99c97473f020df4b9d4ba789e074e06ceddreed        // let the GPU perform this transformation for us
203e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillips        flags = GrContextPriv::kUnpremul_PixelOpsFlag;
2048b26b99c97473f020df4b9d4ba789e074e06ceddreed    }
205b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips
206a8ac92418807e3d46a45413459e6895160134c1dBrian Osman    // This hack allows us to call makeNonTextureImage on images with arbitrary color spaces.
207a8ac92418807e3d46a45413459e6895160134c1dBrian Osman    // Otherwise, we'll be unable to create a render target context.
208a8ac92418807e3d46a45413459e6895160134c1dBrian Osman    // TODO: This shouldn't be necessary - we need more robust support for images (and surfaces)
209a8ac92418807e3d46a45413459e6895160134c1dBrian Osman    // with arbitrary color spaces. Unfortunately, this is one spot where we go from image to
210a8ac92418807e3d46a45413459e6895160134c1dBrian Osman    // surface (rather than the opposite), and our lenient image rules break our (currently) more
211a8ac92418807e3d46a45413459e6895160134c1dBrian Osman    // strict surface rules.
212a8ac92418807e3d46a45413459e6895160134c1dBrian Osman    sk_sp<SkColorSpace> surfaceColorSpace = fColorSpace;
213a8ac92418807e3d46a45413459e6895160134c1dBrian Osman    if (!flags && SkColorSpace::Equals(fColorSpace.get(), dstInfo.colorSpace())) {
214a8ac92418807e3d46a45413459e6895160134c1dBrian Osman        surfaceColorSpace = nullptr;
215a8ac92418807e3d46a45413459e6895160134c1dBrian Osman    }
216a8ac92418807e3d46a45413459e6895160134c1dBrian Osman
2172084ffa9a3fa7eb3c7e17ec5b55750be9942bafcBrian Salomon    sk_sp<GrSurfaceContext> sContext = fContext->contextPriv().makeWrappedSurfaceContext(
218a8ac92418807e3d46a45413459e6895160134c1dBrian Osman            fProxy, surfaceColorSpace);
219b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips    if (!sContext) {
220b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips        return false;
221b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips    }
222b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips
223b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips    if (!sContext->readPixels(rec.fInfo, rec.fPixels, rec.fRowBytes, rec.fX, rec.fY, flags)) {
2248b26b99c97473f020df4b9d4ba789e074e06ceddreed        return false;
2258b26b99c97473f020df4b9d4ba789e074e06ceddreed    }
226b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips
2278b26b99c97473f020df4b9d4ba789e074e06ceddreed    // do we have to manually fix-up the alpha channel?
2288b26b99c97473f020df4b9d4ba789e074e06ceddreed    //      src         dst
2298b26b99c97473f020df4b9d4ba789e074e06ceddreed    //      unpremul    premul      fix manually
2308b26b99c97473f020df4b9d4ba789e074e06ceddreed    //      premul      unpremul    done by kUnpremul_PixelOpsFlag
2318b26b99c97473f020df4b9d4ba789e074e06ceddreed    // all other combos need to change.
2328b26b99c97473f020df4b9d4ba789e074e06ceddreed    //
2338b26b99c97473f020df4b9d4ba789e074e06ceddreed    // Should this be handled by Ganesh? todo:?
2348b26b99c97473f020df4b9d4ba789e074e06ceddreed    //
23503dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarett    if (kPremul_SkAlphaType == rec.fInfo.alphaType() && kUnpremul_SkAlphaType == fAlphaType) {
23603dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarett        apply_premul(rec.fInfo, rec.fPixels, rec.fRowBytes);
2378b26b99c97473f020df4b9d4ba789e074e06ceddreed    }
2388b26b99c97473f020df4b9d4ba789e074e06ceddreed    return true;
2395d4ba8869476831ee73b15a052af8003d0a1fa2ereed@google.com}
2404af267b11964d4a8acdb232ac46094c84d890e88reed
2417fb4f8bd031eda87e1da9bc0f749968c0e872e6freedsk_sp<SkImage> SkImage_Gpu::onMakeSubset(const SkIRect& subset) const {
24263e7973d1f01bd03216659b9d2267f83a752c8fbBrian Salomon    GrSurfaceDesc desc;
24316d8ec66cdce2f30ce89b87066d3ac7a244c460dRobert Phillips    desc.fOrigin = fProxy->origin();
2447b6945bc4e639d7cc4a49b84d492690f8e865566reed    desc.fWidth = subset.width();
2457b6945bc4e639d7cc4a49b84d492690f8e865566reed    desc.fHeight = subset.height();
24616d8ec66cdce2f30ce89b87066d3ac7a244c460dRobert Phillips    desc.fConfig = fProxy->config();
2477b6945bc4e639d7cc4a49b84d492690f8e865566reed
248b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips    sk_sp<GrSurfaceContext> sContext(fContext->contextPriv().makeDeferredSurfaceContext(
249e2f7d1899d890c2f08571e1bd6c7fa2c5ea1be0bRobert Phillips                                                                        desc,
250e2f7d1899d890c2f08571e1bd6c7fa2c5ea1be0bRobert Phillips                                                                        SkBackingFit::kExact,
251e2f7d1899d890c2f08571e1bd6c7fa2c5ea1be0bRobert Phillips                                                                        fBudgeted));
252e2f7d1899d890c2f08571e1bd6c7fa2c5ea1be0bRobert Phillips    if (!sContext) {
253e2f7d1899d890c2f08571e1bd6c7fa2c5ea1be0bRobert Phillips        return nullptr;
254e2f7d1899d890c2f08571e1bd6c7fa2c5ea1be0bRobert Phillips    }
255e2f7d1899d890c2f08571e1bd6c7fa2c5ea1be0bRobert Phillips
256b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips    if (!sContext->copy(fProxy.get(), subset, SkIPoint::Make(0, 0))) {
257e2f7d1899d890c2f08571e1bd6c7fa2c5ea1be0bRobert Phillips        return nullptr;
258e2f7d1899d890c2f08571e1bd6c7fa2c5ea1be0bRobert Phillips    }
259e2f7d1899d890c2f08571e1bd6c7fa2c5ea1be0bRobert Phillips
260b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips    // MDB: this call is okay bc we know 'sContext' was kExact
261b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips    return sk_make_sp<SkImage_Gpu>(fContext, kNeedNewImageUniqueID,
262b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips                                   fAlphaType, sContext->asTextureProxyRef(),
263e2f7d1899d890c2f08571e1bd6c7fa2c5ea1be0bRobert Phillips                                   fColorSpace, fBudgeted);
2647b6945bc4e639d7cc4a49b84d492690f8e865566reed}
2657b6945bc4e639d7cc4a49b84d492690f8e865566reed
2668b26b99c97473f020df4b9d4ba789e074e06ceddreed///////////////////////////////////////////////////////////////////////////////////////////////////
2678b26b99c97473f020df4b9d4ba789e074e06ceddreed
2687ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Danielstatic sk_sp<SkImage> new_wrapped_texture_common(GrContext* ctx,
2697ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel                                                 const GrBackendTexture& backendTex,
2707ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel                                                 GrSurfaceOrigin origin,
271dddbe380b0e6b690041a4e020aefe57f1b21691abrianosman                                                 SkAlphaType at, sk_sp<SkColorSpace> colorSpace,
272dddbe380b0e6b690041a4e020aefe57f1b21691abrianosman                                                 GrWrapOwnership ownership,
2737fb4f8bd031eda87e1da9bc0f749968c0e872e6freed                                                 SkImage::TextureReleaseProc releaseProc,
2747fb4f8bd031eda87e1da9bc0f749968c0e872e6freed                                                 SkImage::ReleaseContext releaseCtx) {
2757ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel    if (backendTex.width() <= 0 || backendTex.height() <= 0) {
27696fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
2778b26b99c97473f020df4b9d4ba789e074e06ceddreed    }
2780ae6faa34d73ffc7ebec3d13f0473703bade821bRobert Phillips
279b0e93a22bbfad05bb834e33387880ece56e0f6d2Robert Phillips    sk_sp<GrTexture> tex = ctx->resourceProvider()->wrapBackendTexture(backendTex, ownership);
2808b26b99c97473f020df4b9d4ba789e074e06ceddreed    if (!tex) {
28196fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
2828b26b99c97473f020df4b9d4ba789e074e06ceddreed    }
283de49988bc24977f97bb1da8c17ceee5432fcc8e7reed    if (releaseProc) {
284de49988bc24977f97bb1da8c17ceee5432fcc8e7reed        tex->setRelease(releaseProc, releaseCtx);
285de49988bc24977f97bb1da8c17ceee5432fcc8e7reed    }
286de49988bc24977f97bb1da8c17ceee5432fcc8e7reed
28785d34b2e841d99dab914111fe2eaa4db99345e1eBrian Osman    const SkBudgeted budgeted = SkBudgeted::kNo;
288066f020bb6cb9dbb12b977fcddd93982201777feRobert Phillips    sk_sp<GrTextureProxy> proxy(GrSurfaceProxy::MakeWrapped(std::move(tex), origin));
2890ae6faa34d73ffc7ebec3d13f0473703bade821bRobert Phillips    return sk_make_sp<SkImage_Gpu>(ctx, kNeedNewImageUniqueID,
2900ae6faa34d73ffc7ebec3d13f0473703bade821bRobert Phillips                                   at, std::move(proxy), std::move(colorSpace), budgeted);
2916dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon}
2926dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon
2939440345a81d6c2372ac0aed937080f3da67439ddGreg Danielsk_sp<SkImage> SkImage::MakeFromTexture(GrContext* ctx,
2949440345a81d6c2372ac0aed937080f3da67439ddGreg Daniel                                        const GrBackendTexture& tex, GrSurfaceOrigin origin,
2959440345a81d6c2372ac0aed937080f3da67439ddGreg Daniel                                        SkAlphaType at, sk_sp<SkColorSpace> cs,
2969440345a81d6c2372ac0aed937080f3da67439ddGreg Daniel                                        TextureReleaseProc releaseP, ReleaseContext releaseC) {
2977ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel    return new_wrapped_texture_common(ctx, tex, origin, at, std::move(cs), kBorrow_GrWrapOwnership,
2987ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel                                      releaseP, releaseC);
2999440345a81d6c2372ac0aed937080f3da67439ddGreg Daniel}
3009440345a81d6c2372ac0aed937080f3da67439ddGreg Daniel
3019440345a81d6c2372ac0aed937080f3da67439ddGreg Danielsk_sp<SkImage> SkImage::MakeFromAdoptedTexture(GrContext* ctx,
3029440345a81d6c2372ac0aed937080f3da67439ddGreg Daniel                                               const GrBackendTexture& tex, GrSurfaceOrigin origin,
3039440345a81d6c2372ac0aed937080f3da67439ddGreg Daniel                                               SkAlphaType at, sk_sp<SkColorSpace> cs) {
3047ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel    return new_wrapped_texture_common(ctx, tex, origin, at, std::move(cs), kAdopt_GrWrapOwnership,
3057ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel                                      nullptr, nullptr);
3067ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel}
3077ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel
3087ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Danielstatic GrBackendTexture make_backend_texture_from_handle(GrBackend backend,
3097ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel                                                         int width, int height,
3107ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel                                                         GrPixelConfig config,
3117ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel                                                         GrBackendObject handle) {
3128fe24272fa6d2fa9eb2458221ed9852d6ec16f56Brian Salomon    switch (backend) {
3138fe24272fa6d2fa9eb2458221ed9852d6ec16f56Brian Salomon        case kOpenGL_GrBackend: {
3148fe24272fa6d2fa9eb2458221ed9852d6ec16f56Brian Salomon            const GrGLTextureInfo* glInfo = (const GrGLTextureInfo*)(handle);
3158fe24272fa6d2fa9eb2458221ed9852d6ec16f56Brian Salomon            return GrBackendTexture(width, height, config, *glInfo);
3168fe24272fa6d2fa9eb2458221ed9852d6ec16f56Brian Salomon        }
317d20b5c489b5709a4d251c0cc68d584ea4514594eMike Reed#ifdef SK_VULKAN
3188fe24272fa6d2fa9eb2458221ed9852d6ec16f56Brian Salomon        case kVulkan_GrBackend: {
3198fe24272fa6d2fa9eb2458221ed9852d6ec16f56Brian Salomon            const GrVkImageInfo* vkInfo = (const GrVkImageInfo*)(handle);
3208fe24272fa6d2fa9eb2458221ed9852d6ec16f56Brian Salomon            return GrBackendTexture(width, height, *vkInfo);
3218fe24272fa6d2fa9eb2458221ed9852d6ec16f56Brian Salomon        }
322fcd5fddb0264d062a461435618ad54a29ff80fc0Robert Phillips#endif
3238fe24272fa6d2fa9eb2458221ed9852d6ec16f56Brian Salomon        case kMock_GrBackend: {
3248fe24272fa6d2fa9eb2458221ed9852d6ec16f56Brian Salomon            const GrMockTextureInfo* mockInfo = (const GrMockTextureInfo*)(handle);
3258fe24272fa6d2fa9eb2458221ed9852d6ec16f56Brian Salomon            return GrBackendTexture(width, height, config, *mockInfo);
3268fe24272fa6d2fa9eb2458221ed9852d6ec16f56Brian Salomon        }
3278fe24272fa6d2fa9eb2458221ed9852d6ec16f56Brian Salomon        default:
3288fe24272fa6d2fa9eb2458221ed9852d6ec16f56Brian Salomon            return GrBackendTexture();
3298fe24272fa6d2fa9eb2458221ed9852d6ec16f56Brian Salomon    }
3309440345a81d6c2372ac0aed937080f3da67439ddGreg Daniel}
3319440345a81d6c2372ac0aed937080f3da67439ddGreg Daniel
332b445a57e6c36cce86580b618701b5af708a6f271jbaumanstatic sk_sp<SkImage> make_from_yuv_textures_copy(GrContext* ctx, SkYUVColorSpace colorSpace,
333b445a57e6c36cce86580b618701b5af708a6f271jbauman                                                  bool nv12,
334b445a57e6c36cce86580b618701b5af708a6f271jbauman                                                  const GrBackendObject yuvTextureHandles[],
335b445a57e6c36cce86580b618701b5af708a6f271jbauman                                                  const SkISize yuvSizes[],
336dddbe380b0e6b690041a4e020aefe57f1b21691abrianosman                                                  GrSurfaceOrigin origin,
337dddbe380b0e6b690041a4e020aefe57f1b21691abrianosman                                                  sk_sp<SkColorSpace> imageColorSpace) {
3385ec26ae9bfca635ccc98283aad5deda11519d826bsalomon    const SkBudgeted budgeted = SkBudgeted::kYes;
339993a4216a6014b9de8f4d8120360c94550dc6761bsalomon
340b445a57e6c36cce86580b618701b5af708a6f271jbauman    if (yuvSizes[0].fWidth <= 0 || yuvSizes[0].fHeight <= 0 || yuvSizes[1].fWidth <= 0 ||
341b445a57e6c36cce86580b618701b5af708a6f271jbauman        yuvSizes[1].fHeight <= 0) {
342b445a57e6c36cce86580b618701b5af708a6f271jbauman        return nullptr;
343b445a57e6c36cce86580b618701b5af708a6f271jbauman    }
344b445a57e6c36cce86580b618701b5af708a6f271jbauman    if (!nv12 && (yuvSizes[2].fWidth <= 0 || yuvSizes[2].fHeight <= 0)) {
34596fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
346993a4216a6014b9de8f4d8120360c94550dc6761bsalomon    }
347b445a57e6c36cce86580b618701b5af708a6f271jbauman
348b445a57e6c36cce86580b618701b5af708a6f271jbauman    const GrPixelConfig kConfig = nv12 ? kRGBA_8888_GrPixelConfig : kAlpha_8_GrPixelConfig;
349b445a57e6c36cce86580b618701b5af708a6f271jbauman
3507ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel    GrBackend backend = ctx->contextPriv().getBackend();
3517ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel    GrBackendTexture yTex = make_backend_texture_from_handle(backend,
3527ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel                                                             yuvSizes[0].fWidth,
3537ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel                                                             yuvSizes[0].fHeight,
3547ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel                                                             kConfig,
3557ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel                                                             yuvTextureHandles[0]);
3567ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel    GrBackendTexture uTex = make_backend_texture_from_handle(backend,
3577ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel                                                             yuvSizes[1].fWidth,
3587ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel                                                             yuvSizes[1].fHeight,
3597ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel                                                             kConfig,
3607ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel                                                             yuvTextureHandles[1]);
3617ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel
3627ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel    sk_sp<GrTextureProxy> yProxy = GrSurfaceProxy::MakeWrappedBackend(ctx, yTex, origin);
3637ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel    sk_sp<GrTextureProxy> uProxy = GrSurfaceProxy::MakeWrappedBackend(ctx, uTex, origin);
3647ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel    sk_sp<GrTextureProxy> vProxy;
365bc7a4fb06780f9829b4b21470fe6f0503d2297cdRobert Phillips
366b445a57e6c36cce86580b618701b5af708a6f271jbauman    if (nv12) {
367bc7a4fb06780f9829b4b21470fe6f0503d2297cdRobert Phillips        vProxy = uProxy;
368b445a57e6c36cce86580b618701b5af708a6f271jbauman    } else {
3697ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel        GrBackendTexture vTex = make_backend_texture_from_handle(backend,
3707ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel                                                                 yuvSizes[2].fWidth,
3717ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel                                                                 yuvSizes[2].fHeight,
3727ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel                                                                 kConfig,
3737ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel                                                                 yuvTextureHandles[2]);
3747ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel        vProxy = GrSurfaceProxy::MakeWrappedBackend(ctx, vTex, origin);
375b445a57e6c36cce86580b618701b5af708a6f271jbauman    }
376bc7a4fb06780f9829b4b21470fe6f0503d2297cdRobert Phillips    if (!yProxy || !uProxy || !vProxy) {
37796fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
378993a4216a6014b9de8f4d8120360c94550dc6761bsalomon    }
379993a4216a6014b9de8f4d8120360c94550dc6761bsalomon
380d4c741e3d0e0fa633399691c47f76b6c7841ee83robertphillips    const int width = yuvSizes[0].fWidth;
381d4c741e3d0e0fa633399691c47f76b6c7841ee83robertphillips    const int height = yuvSizes[0].fHeight;
382d4c741e3d0e0fa633399691c47f76b6c7841ee83robertphillips
383993a4216a6014b9de8f4d8120360c94550dc6761bsalomon    // Needs to be a render target in order to draw to it for the yuv->rgb conversion.
384dd3b3f41829d32d7eaf3eb4903570d49c2ba9ff8Robert Phillips    sk_sp<GrRenderTargetContext> renderTargetContext(ctx->makeDeferredRenderTargetContext(
3851105224f9701e57ec5ce0354d6a380b664f5c638Brian Osman                                                                         SkBackingFit::kExact,
3861105224f9701e57ec5ce0354d6a380b664f5c638Brian Osman                                                                         width, height,
3871105224f9701e57ec5ce0354d6a380b664f5c638Brian Osman                                                                         kRGBA_8888_GrPixelConfig,
3881105224f9701e57ec5ce0354d6a380b664f5c638Brian Osman                                                                         std::move(imageColorSpace),
3891105224f9701e57ec5ce0354d6a380b664f5c638Brian Osman                                                                         0,
3901105224f9701e57ec5ce0354d6a380b664f5c638Brian Osman                                                                         origin));
3911105224f9701e57ec5ce0354d6a380b664f5c638Brian Osman    if (!renderTargetContext) {
39296fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
393993a4216a6014b9de8f4d8120360c94550dc6761bsalomon    }
394993a4216a6014b9de8f4d8120360c94550dc6761bsalomon
395993a4216a6014b9de8f4d8120360c94550dc6761bsalomon    GrPaint paint;
3967d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed    paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
397fbcef6eb8abad142daf45418516550f7635b4a52Robert Phillips    paint.addColorFragmentProcessor(GrYUVEffect::MakeYUVToRGB(yProxy, uProxy, vProxy,
398fbcef6eb8abad142daf45418516550f7635b4a52Robert Phillips                                                              yuvSizes, colorSpace, nv12));
399993a4216a6014b9de8f4d8120360c94550dc6761bsalomon
400b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips    const SkRect rect = SkRect::MakeIWH(width, height);
401c9a3706f1ee38c331610ec1e872d9a658566c397robertphillips
40282f44319159bb98dcacdbbec7ea643dde5ed024bBrian Salomon    renderTargetContext->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(), rect);
403e60ad620fe236ce4c1e85a31bd53ed0c848da8c3Robert Phillips
4047ee385e1dc3cd6a47dc8f7297fef6e175eaba224Robert Phillips    if (!renderTargetContext->asSurfaceProxy()) {
405e60ad620fe236ce4c1e85a31bd53ed0c848da8c3Robert Phillips        return nullptr;
406e60ad620fe236ce4c1e85a31bd53ed0c848da8c3Robert Phillips    }
4077ee385e1dc3cd6a47dc8f7297fef6e175eaba224Robert Phillips    ctx->contextPriv().flushSurfaceWrites(renderTargetContext->asSurfaceProxy());
408b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips
409b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips    // MDB: this call is okay bc we know 'renderTargetContext' was exact
410b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips    return sk_make_sp<SkImage_Gpu>(ctx, kNeedNewImageUniqueID,
411b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips                                   kOpaque_SkAlphaType, renderTargetContext->asTextureProxyRef(),
41275a475cf2e7c66eb58b6b8b1441deb5911e53181Robert Phillips                                   renderTargetContext->refColorSpace(), budgeted);
413993a4216a6014b9de8f4d8120360c94550dc6761bsalomon}
4145617900063f69754de62b8b12d32f6e36df14104reed
415b445a57e6c36cce86580b618701b5af708a6f271jbaumansk_sp<SkImage> SkImage::MakeFromYUVTexturesCopy(GrContext* ctx, SkYUVColorSpace colorSpace,
416b445a57e6c36cce86580b618701b5af708a6f271jbauman                                                const GrBackendObject yuvTextureHandles[3],
417dddbe380b0e6b690041a4e020aefe57f1b21691abrianosman                                                const SkISize yuvSizes[3], GrSurfaceOrigin origin,
418dddbe380b0e6b690041a4e020aefe57f1b21691abrianosman                                                sk_sp<SkColorSpace> imageColorSpace) {
419dddbe380b0e6b690041a4e020aefe57f1b21691abrianosman    return make_from_yuv_textures_copy(ctx, colorSpace, false, yuvTextureHandles, yuvSizes, origin,
420dddbe380b0e6b690041a4e020aefe57f1b21691abrianosman                                       std::move(imageColorSpace));
421b445a57e6c36cce86580b618701b5af708a6f271jbauman}
422b445a57e6c36cce86580b618701b5af708a6f271jbauman
423b445a57e6c36cce86580b618701b5af708a6f271jbaumansk_sp<SkImage> SkImage::MakeFromNV12TexturesCopy(GrContext* ctx, SkYUVColorSpace colorSpace,
424b445a57e6c36cce86580b618701b5af708a6f271jbauman                                                 const GrBackendObject yuvTextureHandles[2],
425b445a57e6c36cce86580b618701b5af708a6f271jbauman                                                 const SkISize yuvSizes[2],
426dddbe380b0e6b690041a4e020aefe57f1b21691abrianosman                                                 GrSurfaceOrigin origin,
427dddbe380b0e6b690041a4e020aefe57f1b21691abrianosman                                                 sk_sp<SkColorSpace> imageColorSpace) {
428dddbe380b0e6b690041a4e020aefe57f1b21691abrianosman    return make_from_yuv_textures_copy(ctx, colorSpace, true, yuvTextureHandles, yuvSizes, origin,
429dddbe380b0e6b690041a4e020aefe57f1b21691abrianosman                                       std::move(imageColorSpace));
430b445a57e6c36cce86580b618701b5af708a6f271jbauman}
431b445a57e6c36cce86580b618701b5af708a6f271jbauman
4323798c86f6885f0b47fb2e659a43b48a4468a97efRobert Phillipsstatic sk_sp<SkImage> create_image_from_maker(GrContext* context, GrTextureMaker* maker,
4333798c86f6885f0b47fb2e659a43b48a4468a97efRobert Phillips                                              SkAlphaType at, uint32_t id,
434041f7dfc577822f1e97721a865f86a9a02660cf9Brian Osman                                              SkColorSpace* dstColorSpace) {
435041f7dfc577822f1e97721a865f86a9a02660cf9Brian Osman    sk_sp<SkColorSpace> texColorSpace;
4363798c86f6885f0b47fb2e659a43b48a4468a97efRobert Phillips    sk_sp<GrTextureProxy> proxy(maker->refTextureProxyForParams(GrSamplerParams::ClampNoFilter(),
4373798c86f6885f0b47fb2e659a43b48a4468a97efRobert Phillips                                                                dstColorSpace,
4383798c86f6885f0b47fb2e659a43b48a4468a97efRobert Phillips                                                                &texColorSpace, nullptr));
4393798c86f6885f0b47fb2e659a43b48a4468a97efRobert Phillips    if (!proxy) {
440041f7dfc577822f1e97721a865f86a9a02660cf9Brian Osman        return nullptr;
441041f7dfc577822f1e97721a865f86a9a02660cf9Brian Osman    }
4423798c86f6885f0b47fb2e659a43b48a4468a97efRobert Phillips    return sk_make_sp<SkImage_Gpu>(context, id, at,
4433798c86f6885f0b47fb2e659a43b48a4468a97efRobert Phillips                                   std::move(proxy), std::move(texColorSpace), SkBudgeted::kNo);
444041f7dfc577822f1e97721a865f86a9a02660cf9Brian Osman}
445041f7dfc577822f1e97721a865f86a9a02660cf9Brian Osman
4462c2bc11aea4dfcd7ee2f5859838a2aa0a56939e0Brian Osmansk_sp<SkImage> SkImage::makeTextureImage(GrContext* context, SkColorSpace* dstColorSpace) const {
447041f7dfc577822f1e97721a865f86a9a02660cf9Brian Osman    if (!context) {
448041f7dfc577822f1e97721a865f86a9a02660cf9Brian Osman        return nullptr;
449041f7dfc577822f1e97721a865f86a9a02660cf9Brian Osman    }
4508744405448b9402e1368aebd321c4f555543301aRobert Phillips    if (GrContext* incumbent = as_IB(this)->context()) {
4518744405448b9402e1368aebd321c4f555543301aRobert Phillips        return incumbent == context ? sk_ref_sp(const_cast<SkImage*>(this)) : nullptr;
452041f7dfc577822f1e97721a865f86a9a02660cf9Brian Osman    }
453041f7dfc577822f1e97721a865f86a9a02660cf9Brian Osman
454df7e075c74110fcfebdc49ca503684162e118af5Brian Osman    if (this->isLazyGenerated()) {
455df7e075c74110fcfebdc49ca503684162e118af5Brian Osman        GrImageTextureMaker maker(context, this, kDisallow_CachingHint);
4560ae6faa34d73ffc7ebec3d13f0473703bade821bRobert Phillips        return create_image_from_maker(context, &maker, this->alphaType(),
4570ae6faa34d73ffc7ebec3d13f0473703bade821bRobert Phillips                                       this->uniqueID(), dstColorSpace);
458041f7dfc577822f1e97721a865f86a9a02660cf9Brian Osman    }
459041f7dfc577822f1e97721a865f86a9a02660cf9Brian Osman
460041f7dfc577822f1e97721a865f86a9a02660cf9Brian Osman    if (const SkBitmap* bmp = as_IB(this)->onPeekBitmap()) {
461041f7dfc577822f1e97721a865f86a9a02660cf9Brian Osman        GrBitmapTextureMaker maker(context, *bmp);
4620ae6faa34d73ffc7ebec3d13f0473703bade821bRobert Phillips        return create_image_from_maker(context, &maker, this->alphaType(),
4630ae6faa34d73ffc7ebec3d13f0473703bade821bRobert Phillips                                       this->uniqueID(), dstColorSpace);
464041f7dfc577822f1e97721a865f86a9a02660cf9Brian Osman    }
465041f7dfc577822f1e97721a865f86a9a02660cf9Brian Osman    return nullptr;
466041f7dfc577822f1e97721a865f86a9a02660cf9Brian Osman}
467041f7dfc577822f1e97721a865f86a9a02660cf9Brian Osman
46813dddce65fd87a8175a209a49f35615735a2886aBrian Osmansk_sp<SkImage> SkImage::MakeCrossContextFromEncoded(GrContext* context, sk_sp<SkData> encoded,
46913dddce65fd87a8175a209a49f35615735a2886aBrian Osman                                                    bool buildMips, SkColorSpace* dstColorSpace) {
47013dddce65fd87a8175a209a49f35615735a2886aBrian Osman    sk_sp<SkImage> codecImage = SkImage::MakeFromEncoded(std::move(encoded));
47113dddce65fd87a8175a209a49f35615735a2886aBrian Osman    if (!codecImage) {
47213dddce65fd87a8175a209a49f35615735a2886aBrian Osman        return nullptr;
47313dddce65fd87a8175a209a49f35615735a2886aBrian Osman    }
47413dddce65fd87a8175a209a49f35615735a2886aBrian Osman
47513dddce65fd87a8175a209a49f35615735a2886aBrian Osman    // Some backends or drivers don't support (safely) moving resources between contexts
47613dddce65fd87a8175a209a49f35615735a2886aBrian Osman    if (!context || !context->caps()->crossContextTextureSupport()) {
47713dddce65fd87a8175a209a49f35615735a2886aBrian Osman        return codecImage;
47813dddce65fd87a8175a209a49f35615735a2886aBrian Osman    }
47913dddce65fd87a8175a209a49f35615735a2886aBrian Osman
48013dddce65fd87a8175a209a49f35615735a2886aBrian Osman    // Turn the codec image into a GrTextureProxy
48113dddce65fd87a8175a209a49f35615735a2886aBrian Osman    GrImageTextureMaker maker(context, codecImage.get(), kDisallow_CachingHint);
48213dddce65fd87a8175a209a49f35615735a2886aBrian Osman    sk_sp<SkColorSpace> texColorSpace;
48313dddce65fd87a8175a209a49f35615735a2886aBrian Osman    GrSamplerParams params(SkShader::kClamp_TileMode,
48413dddce65fd87a8175a209a49f35615735a2886aBrian Osman                           buildMips ? GrSamplerParams::kMipMap_FilterMode
48513dddce65fd87a8175a209a49f35615735a2886aBrian Osman                                     : GrSamplerParams::kBilerp_FilterMode);
48613dddce65fd87a8175a209a49f35615735a2886aBrian Osman    sk_sp<GrTextureProxy> proxy(maker.refTextureProxyForParams(params, dstColorSpace,
48713dddce65fd87a8175a209a49f35615735a2886aBrian Osman                                                               &texColorSpace, nullptr));
48813dddce65fd87a8175a209a49f35615735a2886aBrian Osman    if (!proxy) {
48913dddce65fd87a8175a209a49f35615735a2886aBrian Osman        return codecImage;
49013dddce65fd87a8175a209a49f35615735a2886aBrian Osman    }
49113dddce65fd87a8175a209a49f35615735a2886aBrian Osman
492eee4d6e4e8cc5c4c79f065abcc3ce609f71238f9Robert Phillips    if (!proxy->instantiate(context->resourceProvider())) {
49313dddce65fd87a8175a209a49f35615735a2886aBrian Osman        return codecImage;
49413dddce65fd87a8175a209a49f35615735a2886aBrian Osman    }
495eee4d6e4e8cc5c4c79f065abcc3ce609f71238f9Robert Phillips    sk_sp<GrTexture> texture = sk_ref_sp(proxy->priv().peekTexture());
49613dddce65fd87a8175a209a49f35615735a2886aBrian Osman
49713dddce65fd87a8175a209a49f35615735a2886aBrian Osman    // Flush any writes or uploads
49813dddce65fd87a8175a209a49f35615735a2886aBrian Osman    context->contextPriv().prepareSurfaceForExternalIO(proxy.get());
49913dddce65fd87a8175a209a49f35615735a2886aBrian Osman
50013dddce65fd87a8175a209a49f35615735a2886aBrian Osman    sk_sp<GrSemaphore> sema = context->getGpu()->prepareTextureForCrossContextUsage(texture.get());
50113dddce65fd87a8175a209a49f35615735a2886aBrian Osman
502b0e93a22bbfad05bb834e33387880ece56e0f6d2Robert Phillips    auto gen = GrBackendTextureImageGenerator::Make(std::move(texture), proxy->origin(),
50316d8ec66cdce2f30ce89b87066d3ac7a244c460dRobert Phillips                                                    std::move(sema), codecImage->alphaType(),
50413dddce65fd87a8175a209a49f35615735a2886aBrian Osman                                                    std::move(texColorSpace));
50513dddce65fd87a8175a209a49f35615735a2886aBrian Osman    return SkImage::MakeFromGenerator(std::move(gen));
50613dddce65fd87a8175a209a49f35615735a2886aBrian Osman}
50713dddce65fd87a8175a209a49f35615735a2886aBrian Osman
5087a86987815be3af78fe3801d4f347ebb0c63141aDerek Sollenberger#if defined(SK_BUILD_FOR_ANDROID) && __ANDROID_API__ >= 26
5097e910df7f133e80293117bdd069ed25998d10f8cStan Ilievsk_sp<SkImage> SkImage::MakeFromAHardwareBuffer(AHardwareBuffer* graphicBuffer, SkAlphaType at,
5107e910df7f133e80293117bdd069ed25998d10f8cStan Iliev                                               sk_sp<SkColorSpace> cs) {
5117e910df7f133e80293117bdd069ed25998d10f8cStan Iliev    auto gen = GrAHardwareBufferImageGenerator::Make(graphicBuffer, at, cs);
5127e910df7f133e80293117bdd069ed25998d10f8cStan Iliev    return SkImage::MakeFromGenerator(std::move(gen));
5137e910df7f133e80293117bdd069ed25998d10f8cStan Iliev}
5147e910df7f133e80293117bdd069ed25998d10f8cStan Iliev#endif
5157e910df7f133e80293117bdd069ed25998d10f8cStan Iliev
516634b43008025d039f3f2f1f6c01e8044ffbb901fbsalomonsk_sp<SkImage> SkImage::makeNonTextureImage() const {
517396fcdba14a0101ed43dcc3863585bf50c4ed6ccbrianosman    if (!this->isTextureBacked()) {
518634b43008025d039f3f2f1f6c01e8044ffbb901fbsalomon        return sk_ref_sp(const_cast<SkImage*>(this));
519634b43008025d039f3f2f1f6c01e8044ffbb901fbsalomon    }
520396fcdba14a0101ed43dcc3863585bf50c4ed6ccbrianosman    SkImageInfo info = as_IB(this)->onImageInfo();
521634b43008025d039f3f2f1f6c01e8044ffbb901fbsalomon    size_t rowBytes = info.minRowBytes();
522634b43008025d039f3f2f1f6c01e8044ffbb901fbsalomon    size_t size = info.getSafeSize(rowBytes);
523634b43008025d039f3f2f1f6c01e8044ffbb901fbsalomon    auto data = SkData::MakeUninitialized(size);
524634b43008025d039f3f2f1f6c01e8044ffbb901fbsalomon    if (!data) {
525634b43008025d039f3f2f1f6c01e8044ffbb901fbsalomon        return nullptr;
526634b43008025d039f3f2f1f6c01e8044ffbb901fbsalomon    }
527634b43008025d039f3f2f1f6c01e8044ffbb901fbsalomon    SkPixmap pm(info, data->writable_data(), rowBytes);
528634b43008025d039f3f2f1f6c01e8044ffbb901fbsalomon    if (!this->readPixels(pm, 0, 0, kDisallow_CachingHint)) {
529634b43008025d039f3f2f1f6c01e8044ffbb901fbsalomon        return nullptr;
530634b43008025d039f3f2f1f6c01e8044ffbb901fbsalomon    }
531634b43008025d039f3f2f1f6c01e8044ffbb901fbsalomon    return MakeRasterData(info, data, rowBytes);
532634b43008025d039f3f2f1f6c01e8044ffbb901fbsalomon}
533634b43008025d039f3f2f1f6c01e8044ffbb901fbsalomon
5345617900063f69754de62b8b12d32f6e36df14104reed///////////////////////////////////////////////////////////////////////////////////////////////////
5355617900063f69754de62b8b12d32f6e36df14104reed
5364d516a6903d83414b5615ca9388b52064da6990cbsalomonnamespace {
5374d516a6903d83414b5615ca9388b52064da6990cbsalomonstruct MipMapLevelData {
5384d516a6903d83414b5615ca9388b52064da6990cbsalomon    void* fPixelData;
5394d516a6903d83414b5615ca9388b52064da6990cbsalomon    size_t fRowBytes;
54041b952c296e343eeabb07d52b6a55ba7565a286bbsalomon};
54141b952c296e343eeabb07d52b6a55ba7565a286bbsalomon
5424d516a6903d83414b5615ca9388b52064da6990cbsalomonstruct DeferredTextureImage {
5437b8400dad2f82dcc6ed3c7cc1707ebaf85f04840Brian Osman    uint32_t                      fContextUniqueID;
5447b8400dad2f82dcc6ed3c7cc1707ebaf85f04840Brian Osman    // Right now, the destination color mode is only considered when generating mipmaps
5457b8400dad2f82dcc6ed3c7cc1707ebaf85f04840Brian Osman    SkDestinationSurfaceColorMode fColorMode;
5464d516a6903d83414b5615ca9388b52064da6990cbsalomon    // We don't store a SkImageInfo because it contains a ref-counted SkColorSpace.
5477b8400dad2f82dcc6ed3c7cc1707ebaf85f04840Brian Osman    int                           fWidth;
5487b8400dad2f82dcc6ed3c7cc1707ebaf85f04840Brian Osman    int                           fHeight;
5497b8400dad2f82dcc6ed3c7cc1707ebaf85f04840Brian Osman    SkColorType                   fColorType;
5507b8400dad2f82dcc6ed3c7cc1707ebaf85f04840Brian Osman    SkAlphaType                   fAlphaType;
5517b8400dad2f82dcc6ed3c7cc1707ebaf85f04840Brian Osman    void*                         fColorSpace;
5527b8400dad2f82dcc6ed3c7cc1707ebaf85f04840Brian Osman    size_t                        fColorSpaceSize;
5537b8400dad2f82dcc6ed3c7cc1707ebaf85f04840Brian Osman    int                           fMipMapLevelCount;
5544d516a6903d83414b5615ca9388b52064da6990cbsalomon    // The fMipMapLevelData array may contain more than 1 element.
5554d516a6903d83414b5615ca9388b52064da6990cbsalomon    // It contains fMipMapLevelCount elements.
5564d516a6903d83414b5615ca9388b52064da6990cbsalomon    // That means this struct's size is not known at compile-time.
5577b8400dad2f82dcc6ed3c7cc1707ebaf85f04840Brian Osman    MipMapLevelData               fMipMapLevelData[1];
5584d516a6903d83414b5615ca9388b52064da6990cbsalomon};
5594d516a6903d83414b5615ca9388b52064da6990cbsalomon}  // anonymous namespace
5604d516a6903d83414b5615ca9388b52064da6990cbsalomon
56133e0cb5e7f9926b96db209c825f1eeca7c15bb16cblumestatic bool should_use_mip_maps(const SkImage::DeferredTextureImageUsageParams & param) {
562a422d706b1a92e71c6f940de3ed3d0b84a13eb1bEric Karl    // There is a bug in the mipmap pre-generation logic in use in getDeferredTextureImageData.
563a422d706b1a92e71c6f940de3ed3d0b84a13eb1bEric Karl    // This can cause runaway memory leaks, so we are disabling this path until we can
564a422d706b1a92e71c6f940de3ed3d0b84a13eb1bEric Karl    // investigate further. crbug.com/669775
565a422d706b1a92e71c6f940de3ed3d0b84a13eb1bEric Karl    return false;
56633e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume}
56733e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume
56833e0cb5e7f9926b96db209c825f1eeca7c15bb16cblumenamespace {
56933e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume
57033e0cb5e7f9926b96db209c825f1eeca7c15bb16cblumeclass DTIBufferFiller
57133e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume{
57233e0cb5e7f9926b96db209c825f1eeca7c15bb16cblumepublic:
573921bc678a7b81de31b4e672326ed2f37ffb66b10cblume    explicit DTIBufferFiller(char* bufferAsCharPtr)
574921bc678a7b81de31b4e672326ed2f37ffb66b10cblume        : bufferAsCharPtr_(bufferAsCharPtr) {}
57533e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume
57633e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume    void fillMember(const void* source, size_t memberOffset, size_t size) {
577921bc678a7b81de31b4e672326ed2f37ffb66b10cblume        memcpy(bufferAsCharPtr_ + memberOffset, source, size);
57833e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume    }
57933e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume
58033e0cb5e7f9926b96db209c825f1eeca7c15bb16cblumeprivate:
58133e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume
582921bc678a7b81de31b4e672326ed2f37ffb66b10cblume    char* bufferAsCharPtr_;
58333e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume};
58433e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume}
58533e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume
58633e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume#define FILL_MEMBER(bufferFiller, member, source) \
58733e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume    bufferFiller.fillMember(source, \
58833e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume               offsetof(DeferredTextureImage, member), \
58933e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume               sizeof(DeferredTextureImage::member));
59033e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume
5917a8c84c6c92565842aeea27d4971fbd78d523f7aEric Karlstatic bool SupportsColorSpace(SkColorType colorType) {
5927a8c84c6c92565842aeea27d4971fbd78d523f7aEric Karl    switch (colorType) {
5937a8c84c6c92565842aeea27d4971fbd78d523f7aEric Karl        case kRGBA_8888_SkColorType:
5947a8c84c6c92565842aeea27d4971fbd78d523f7aEric Karl        case kBGRA_8888_SkColorType:
5957a8c84c6c92565842aeea27d4971fbd78d523f7aEric Karl        case kRGBA_F16_SkColorType:
5967a8c84c6c92565842aeea27d4971fbd78d523f7aEric Karl            return true;
5977a8c84c6c92565842aeea27d4971fbd78d523f7aEric Karl        default:
5987a8c84c6c92565842aeea27d4971fbd78d523f7aEric Karl            return false;
5997a8c84c6c92565842aeea27d4971fbd78d523f7aEric Karl    }
6007a8c84c6c92565842aeea27d4971fbd78d523f7aEric Karl}
6017a8c84c6c92565842aeea27d4971fbd78d523f7aEric Karl
60241b952c296e343eeabb07d52b6a55ba7565a286bbsalomonsize_t SkImage::getDeferredTextureImageData(const GrContextThreadSafeProxy& proxy,
603b4da01d8f719f3c43d492e8f62a7e2c861e9ef27ericrk                                            const DeferredTextureImageUsageParams params[],
60433e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume                                            int paramCnt, void* buffer,
6057a8c84c6c92565842aeea27d4971fbd78d523f7aEric Karl                                            SkColorSpace* dstColorSpace,
6067a8c84c6c92565842aeea27d4971fbd78d523f7aEric Karl                                            SkColorType dstColorType) const {
6077f1d020bbfde245281fac88ff09b55366155be16Mike Reed    // Some quick-rejects where is makes no sense to return CPU data
6087f1d020bbfde245281fac88ff09b55366155be16Mike Reed    //  e.g.
6097f1d020bbfde245281fac88ff09b55366155be16Mike Reed    //      - texture backed
6107f1d020bbfde245281fac88ff09b55366155be16Mike Reed    //      - picture backed
6117f1d020bbfde245281fac88ff09b55366155be16Mike Reed    //
6127f1d020bbfde245281fac88ff09b55366155be16Mike Reed    if (this->isTextureBacked()) {
6137f1d020bbfde245281fac88ff09b55366155be16Mike Reed        return 0;
6147f1d020bbfde245281fac88ff09b55366155be16Mike Reed    }
6157f1d020bbfde245281fac88ff09b55366155be16Mike Reed    if (as_IB(this)->onCanLazyGenerateOnGPU()) {
6167f1d020bbfde245281fac88ff09b55366155be16Mike Reed        return 0;
6177f1d020bbfde245281fac88ff09b55366155be16Mike Reed    }
6187f1d020bbfde245281fac88ff09b55366155be16Mike Reed
6197a8c84c6c92565842aeea27d4971fbd78d523f7aEric Karl    bool supportsColorSpace = SupportsColorSpace(dstColorType);
6207a8c84c6c92565842aeea27d4971fbd78d523f7aEric Karl    // Quick reject if the caller requests a color space with an unsupported color type.
6217a8c84c6c92565842aeea27d4971fbd78d523f7aEric Karl    if (SkToBool(dstColorSpace) && !supportsColorSpace) {
6227a8c84c6c92565842aeea27d4971fbd78d523f7aEric Karl        return 0;
6237a8c84c6c92565842aeea27d4971fbd78d523f7aEric Karl    }
6247a8c84c6c92565842aeea27d4971fbd78d523f7aEric Karl
625b4da01d8f719f3c43d492e8f62a7e2c861e9ef27ericrk    // Extract relevant min/max values from the params array.
626b4da01d8f719f3c43d492e8f62a7e2c861e9ef27ericrk    int lowestPreScaleMipLevel = params[0].fPreScaleMipLevel;
627b4da01d8f719f3c43d492e8f62a7e2c861e9ef27ericrk    SkFilterQuality highestFilterQuality = params[0].fQuality;
62833e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume    bool useMipMaps = should_use_mip_maps(params[0]);
629b4da01d8f719f3c43d492e8f62a7e2c861e9ef27ericrk    for (int i = 1; i < paramCnt; ++i) {
630b4da01d8f719f3c43d492e8f62a7e2c861e9ef27ericrk        if (lowestPreScaleMipLevel > params[i].fPreScaleMipLevel)
631b4da01d8f719f3c43d492e8f62a7e2c861e9ef27ericrk            lowestPreScaleMipLevel = params[i].fPreScaleMipLevel;
632b4da01d8f719f3c43d492e8f62a7e2c861e9ef27ericrk        if (highestFilterQuality < params[i].fQuality)
633b4da01d8f719f3c43d492e8f62a7e2c861e9ef27ericrk            highestFilterQuality = params[i].fQuality;
63433e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume        useMipMaps |= should_use_mip_maps(params[i]);
635b4da01d8f719f3c43d492e8f62a7e2c861e9ef27ericrk    }
636b4da01d8f719f3c43d492e8f62a7e2c861e9ef27ericrk
63741b952c296e343eeabb07d52b6a55ba7565a286bbsalomon    const bool fillMode = SkToBool(buffer);
63841b952c296e343eeabb07d52b6a55ba7565a286bbsalomon    if (fillMode && !SkIsAlign8(reinterpret_cast<intptr_t>(buffer))) {
63941b952c296e343eeabb07d52b6a55ba7565a286bbsalomon        return 0;
64041b952c296e343eeabb07d52b6a55ba7565a286bbsalomon    }
64141b952c296e343eeabb07d52b6a55ba7565a286bbsalomon
642b4da01d8f719f3c43d492e8f62a7e2c861e9ef27ericrk    // Calculate scaling parameters.
643b4da01d8f719f3c43d492e8f62a7e2c861e9ef27ericrk    bool isScaled = lowestPreScaleMipLevel != 0;
644b4da01d8f719f3c43d492e8f62a7e2c861e9ef27ericrk
645b4da01d8f719f3c43d492e8f62a7e2c861e9ef27ericrk    SkISize scaledSize;
646b4da01d8f719f3c43d492e8f62a7e2c861e9ef27ericrk    if (isScaled) {
647b4da01d8f719f3c43d492e8f62a7e2c861e9ef27ericrk        // SkMipMap::ComputeLevelSize takes an index into an SkMipMap. SkMipMaps don't contain the
648b4da01d8f719f3c43d492e8f62a7e2c861e9ef27ericrk        // base level, so to get an SkMipMap index we must subtract one from the GL MipMap level.
649b4da01d8f719f3c43d492e8f62a7e2c861e9ef27ericrk        scaledSize = SkMipMap::ComputeLevelSize(this->width(), this->height(),
650b4da01d8f719f3c43d492e8f62a7e2c861e9ef27ericrk                                                lowestPreScaleMipLevel - 1);
651b4da01d8f719f3c43d492e8f62a7e2c861e9ef27ericrk    } else {
652b4da01d8f719f3c43d492e8f62a7e2c861e9ef27ericrk        scaledSize = SkISize::Make(this->width(), this->height());
653b4da01d8f719f3c43d492e8f62a7e2c861e9ef27ericrk    }
654b4da01d8f719f3c43d492e8f62a7e2c861e9ef27ericrk
655b4da01d8f719f3c43d492e8f62a7e2c861e9ef27ericrk    // We never want to scale at higher than SW medium quality, as SW medium matches GPU high.
656b4da01d8f719f3c43d492e8f62a7e2c861e9ef27ericrk    SkFilterQuality scaleFilterQuality = highestFilterQuality;
657b4da01d8f719f3c43d492e8f62a7e2c861e9ef27ericrk    if (scaleFilterQuality > kMedium_SkFilterQuality) {
658b4da01d8f719f3c43d492e8f62a7e2c861e9ef27ericrk        scaleFilterQuality = kMedium_SkFilterQuality;
659b4da01d8f719f3c43d492e8f62a7e2c861e9ef27ericrk    }
660b4da01d8f719f3c43d492e8f62a7e2c861e9ef27ericrk
661c429baf7a28205a19975cfbb60db1b7bfc9c61faericrk    const int maxTextureSize = proxy.fCaps->maxTextureSize();
662b4da01d8f719f3c43d492e8f62a7e2c861e9ef27ericrk    if (scaledSize.width() > maxTextureSize || scaledSize.height() > maxTextureSize) {
663c429baf7a28205a19975cfbb60db1b7bfc9c61faericrk        return 0;
664c429baf7a28205a19975cfbb60db1b7bfc9c61faericrk    }
665c429baf7a28205a19975cfbb60db1b7bfc9c61faericrk
66641b952c296e343eeabb07d52b6a55ba7565a286bbsalomon    SkAutoPixmapStorage pixmap;
66741b952c296e343eeabb07d52b6a55ba7565a286bbsalomon    SkImageInfo info;
66841b952c296e343eeabb07d52b6a55ba7565a286bbsalomon    size_t pixelSize = 0;
669086a427b0cee3862f25c492fc5082ff24105dc53Mike Reed    if (!isScaled && this->peekPixels(&pixmap) && pixmap.info().colorType() == dstColorType) {
67041b952c296e343eeabb07d52b6a55ba7565a286bbsalomon        info = pixmap.info();
67141b952c296e343eeabb07d52b6a55ba7565a286bbsalomon        pixelSize = SkAlign8(pixmap.getSafeSize());
672ade76e9236788120d8a1a4a7a252d8f66b8b9b02Matt Sarett        if (!dstColorSpace) {
673ade76e9236788120d8a1a4a7a252d8f66b8b9b02Matt Sarett            pixmap.setColorSpace(nullptr);
674ade76e9236788120d8a1a4a7a252d8f66b8b9b02Matt Sarett            info = info.makeColorSpace(nullptr);
675ade76e9236788120d8a1a4a7a252d8f66b8b9b02Matt Sarett        }
67641b952c296e343eeabb07d52b6a55ba7565a286bbsalomon    } else {
6777f1d020bbfde245281fac88ff09b55366155be16Mike Reed        if (!this->isLazyGenerated() && !this->peekPixels(nullptr)) {
67841b952c296e343eeabb07d52b6a55ba7565a286bbsalomon            return 0;
67941b952c296e343eeabb07d52b6a55ba7565a286bbsalomon        }
6807992da32f02f90e0ac9ab6914eb31676b502eb71Brian Osman        if (SkImageCacherator* cacher = as_IB(this)->peekCacherator()) {
6817992da32f02f90e0ac9ab6914eb31676b502eb71Brian Osman            // Generator backed image. Tweak info to trigger correct kind of decode.
6827992da32f02f90e0ac9ab6914eb31676b502eb71Brian Osman            SkImageCacherator::CachedFormat cacheFormat = cacher->chooseCacheFormat(
68361624f0c716b576706659750d87b6956f4c15722Brian Osman                dstColorSpace, proxy.fCaps.get());
6847992da32f02f90e0ac9ab6914eb31676b502eb71Brian Osman            info = cacher->buildCacheInfo(cacheFormat).makeWH(scaledSize.width(),
6857992da32f02f90e0ac9ab6914eb31676b502eb71Brian Osman                                                              scaledSize.height());
6867992da32f02f90e0ac9ab6914eb31676b502eb71Brian Osman        } else {
6877992da32f02f90e0ac9ab6914eb31676b502eb71Brian Osman            info = as_IB(this)->onImageInfo().makeWH(scaledSize.width(), scaledSize.height());
688ade76e9236788120d8a1a4a7a252d8f66b8b9b02Matt Sarett            if (!dstColorSpace) {
689ade76e9236788120d8a1a4a7a252d8f66b8b9b02Matt Sarett                info = info.makeColorSpace(nullptr);
690ade76e9236788120d8a1a4a7a252d8f66b8b9b02Matt Sarett            }
6917992da32f02f90e0ac9ab6914eb31676b502eb71Brian Osman        }
6927a8c84c6c92565842aeea27d4971fbd78d523f7aEric Karl        // Force color type to be the requested type.
6937a8c84c6c92565842aeea27d4971fbd78d523f7aEric Karl        info = info.makeColorType(dstColorType);
69441b952c296e343eeabb07d52b6a55ba7565a286bbsalomon        pixelSize = SkAlign8(SkAutoPixmapStorage::AllocSize(info, nullptr));
69541b952c296e343eeabb07d52b6a55ba7565a286bbsalomon        if (fillMode) {
6967a8c84c6c92565842aeea27d4971fbd78d523f7aEric Karl            // Always decode to N32 and convert to the requested type if necessary.
6977a8c84c6c92565842aeea27d4971fbd78d523f7aEric Karl            SkImageInfo decodeInfo = info.makeColorType(kN32_SkColorType);
6987a8c84c6c92565842aeea27d4971fbd78d523f7aEric Karl            SkAutoPixmapStorage decodePixmap;
6997a8c84c6c92565842aeea27d4971fbd78d523f7aEric Karl            decodePixmap.alloc(decodeInfo);
7007a8c84c6c92565842aeea27d4971fbd78d523f7aEric Karl
701b4da01d8f719f3c43d492e8f62a7e2c861e9ef27ericrk            if (isScaled) {
7027a8c84c6c92565842aeea27d4971fbd78d523f7aEric Karl                if (!this->scalePixels(decodePixmap, scaleFilterQuality,
703b4da01d8f719f3c43d492e8f62a7e2c861e9ef27ericrk                                       SkImage::kDisallow_CachingHint)) {
704b4da01d8f719f3c43d492e8f62a7e2c861e9ef27ericrk                    return 0;
705b4da01d8f719f3c43d492e8f62a7e2c861e9ef27ericrk                }
706b4da01d8f719f3c43d492e8f62a7e2c861e9ef27ericrk            } else {
7077a8c84c6c92565842aeea27d4971fbd78d523f7aEric Karl                if (!this->readPixels(decodePixmap, 0, 0, SkImage::kDisallow_CachingHint)) {
708b4da01d8f719f3c43d492e8f62a7e2c861e9ef27ericrk                    return 0;
709b4da01d8f719f3c43d492e8f62a7e2c861e9ef27ericrk                }
71041b952c296e343eeabb07d52b6a55ba7565a286bbsalomon            }
7117a8c84c6c92565842aeea27d4971fbd78d523f7aEric Karl
7127a8c84c6c92565842aeea27d4971fbd78d523f7aEric Karl            if (decodeInfo.colorType() != info.colorType()) {
7137a8c84c6c92565842aeea27d4971fbd78d523f7aEric Karl                pixmap.alloc(info);
7147a8c84c6c92565842aeea27d4971fbd78d523f7aEric Karl                // Convert and copy the decoded pixmap to the target pixmap.
7157a8c84c6c92565842aeea27d4971fbd78d523f7aEric Karl                decodePixmap.readPixels(pixmap.info(), pixmap.writable_addr(), pixmap.rowBytes(), 0,
7167a8c84c6c92565842aeea27d4971fbd78d523f7aEric Karl                                        0);
7177a8c84c6c92565842aeea27d4971fbd78d523f7aEric Karl            } else {
7187a8c84c6c92565842aeea27d4971fbd78d523f7aEric Karl                pixmap = std::move(decodePixmap);
7197a8c84c6c92565842aeea27d4971fbd78d523f7aEric Karl            }
72041b952c296e343eeabb07d52b6a55ba7565a286bbsalomon        }
72141b952c296e343eeabb07d52b6a55ba7565a286bbsalomon    }
7222c05280a0f792fc94c879e29011312a57532786bcblume    int mipMapLevelCount = 1;
72333e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume    if (useMipMaps) {
72433e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume        // SkMipMap only deals with the mipmap levels it generates, which does
72533e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume        // not include the base level.
72633e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume        // That means it generates and holds levels 1-x instead of 0-x.
72733e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume        // So the total mipmap level count is 1 more than what
72833e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume        // SkMipMap::ComputeLevelCount returns.
72933e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume        mipMapLevelCount = SkMipMap::ComputeLevelCount(scaledSize.width(), scaledSize.height()) + 1;
73033e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume
73133e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume        // We already initialized pixelSize to the size of the base level.
73233e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume        // SkMipMap will generate the extra mipmap levels. Their sizes need to
73333e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume        // be added to the total.
73433e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume        // Index 0 here does not refer to the base mipmap level -- it is
73533e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume        // SkMipMap's first generated mipmap level (level 1).
73633e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume        for (int currentMipMapLevelIndex = mipMapLevelCount - 2; currentMipMapLevelIndex >= 0;
73733e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume             currentMipMapLevelIndex--) {
73833e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume            SkISize mipSize = SkMipMap::ComputeLevelSize(scaledSize.width(), scaledSize.height(),
73933e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume                                                         currentMipMapLevelIndex);
74032b5e70178acda2ce1548cce1740841e7d30344abrianosman            SkImageInfo mipInfo = info.makeWH(mipSize.fWidth, mipSize.fHeight);
74133e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume            pixelSize += SkAlign8(SkAutoPixmapStorage::AllocSize(mipInfo, nullptr));
74233e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume        }
74333e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume    }
74441b952c296e343eeabb07d52b6a55ba7565a286bbsalomon    size_t size = 0;
74541b952c296e343eeabb07d52b6a55ba7565a286bbsalomon    size_t dtiSize = SkAlign8(sizeof(DeferredTextureImage));
74641b952c296e343eeabb07d52b6a55ba7565a286bbsalomon    size += dtiSize;
74733e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume    size += (mipMapLevelCount - 1) * sizeof(MipMapLevelData);
74833e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume    // We subtract 1 because DeferredTextureImage already includes the base
74933e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume    // level in its size
75041b952c296e343eeabb07d52b6a55ba7565a286bbsalomon    size_t pixelOffset = size;
75141b952c296e343eeabb07d52b6a55ba7565a286bbsalomon    size += pixelSize;
7524d516a6903d83414b5615ca9388b52064da6990cbsalomon    size_t colorSpaceOffset = 0;
7534d516a6903d83414b5615ca9388b52064da6990cbsalomon    size_t colorSpaceSize = 0;
75484c9cb7bd8f4c2b0cd4a378995ebbd8524efa390Matt Sarett    SkColorSpaceTransferFn fn;
7554d516a6903d83414b5615ca9388b52064da6990cbsalomon    if (info.colorSpace()) {
756ade76e9236788120d8a1a4a7a252d8f66b8b9b02Matt Sarett        SkASSERT(dstColorSpace);
7577a8c84c6c92565842aeea27d4971fbd78d523f7aEric Karl        SkASSERT(supportsColorSpace);
7584d516a6903d83414b5615ca9388b52064da6990cbsalomon        colorSpaceOffset = size;
7594d516a6903d83414b5615ca9388b52064da6990cbsalomon        colorSpaceSize = info.colorSpace()->writeToMemory(nullptr);
7604d516a6903d83414b5615ca9388b52064da6990cbsalomon        size += colorSpaceSize;
7617a8c84c6c92565842aeea27d4971fbd78d523f7aEric Karl    } else if (supportsColorSpace && this->colorSpace() && this->colorSpace()->isNumericalTransferFn(&fn)) {
76284c9cb7bd8f4c2b0cd4a378995ebbd8524efa390Matt Sarett        // In legacy mode, preserve the color space tag on the SkImage.  This is only
76384c9cb7bd8f4c2b0cd4a378995ebbd8524efa390Matt Sarett        // supported if the color space has a parametric transfer function.
76484c9cb7bd8f4c2b0cd4a378995ebbd8524efa390Matt Sarett        SkASSERT(!dstColorSpace);
76584c9cb7bd8f4c2b0cd4a378995ebbd8524efa390Matt Sarett        colorSpaceOffset = size;
76684c9cb7bd8f4c2b0cd4a378995ebbd8524efa390Matt Sarett        colorSpaceSize = this->colorSpace()->writeToMemory(nullptr);
76784c9cb7bd8f4c2b0cd4a378995ebbd8524efa390Matt Sarett        size += colorSpaceSize;
7684d516a6903d83414b5615ca9388b52064da6990cbsalomon    }
76941b952c296e343eeabb07d52b6a55ba7565a286bbsalomon    if (!fillMode) {
77041b952c296e343eeabb07d52b6a55ba7565a286bbsalomon        return size;
77141b952c296e343eeabb07d52b6a55ba7565a286bbsalomon    }
772921bc678a7b81de31b4e672326ed2f37ffb66b10cblume    char* bufferAsCharPtr = reinterpret_cast<char*>(buffer);
773921bc678a7b81de31b4e672326ed2f37ffb66b10cblume    char* pixelsAsCharPtr = bufferAsCharPtr + pixelOffset;
774921bc678a7b81de31b4e672326ed2f37ffb66b10cblume    void* pixels = pixelsAsCharPtr;
77541b952c296e343eeabb07d52b6a55ba7565a286bbsalomon
776921bc678a7b81de31b4e672326ed2f37ffb66b10cblume    memcpy(reinterpret_cast<void*>(SkAlign8(reinterpret_cast<uintptr_t>(pixelsAsCharPtr))),
777921bc678a7b81de31b4e672326ed2f37ffb66b10cblume                                   pixmap.addr(), pixmap.getSafeSize());
77841b952c296e343eeabb07d52b6a55ba7565a286bbsalomon
7796c15cc7e9d65981ec0363a050d2248f96e21a5daBrian Osman    // If the context has sRGB support, and we're intending to render to a surface with an attached
7806c15cc7e9d65981ec0363a050d2248f96e21a5daBrian Osman    // color space, and the image has an sRGB-like color space attached, then use our gamma (sRGB)
7816c15cc7e9d65981ec0363a050d2248f96e21a5daBrian Osman    // aware mip-mapping.
7827b8400dad2f82dcc6ed3c7cc1707ebaf85f04840Brian Osman    SkDestinationSurfaceColorMode colorMode = SkDestinationSurfaceColorMode::kLegacy;
7836c15cc7e9d65981ec0363a050d2248f96e21a5daBrian Osman    if (proxy.fCaps->srgbSupport() && SkToBool(dstColorSpace) &&
7846c15cc7e9d65981ec0363a050d2248f96e21a5daBrian Osman        info.colorSpace() && info.colorSpace()->gammaCloseToSRGB()) {
7857a8c84c6c92565842aeea27d4971fbd78d523f7aEric Karl        SkASSERT(supportsColorSpace);
7867b8400dad2f82dcc6ed3c7cc1707ebaf85f04840Brian Osman        colorMode = SkDestinationSurfaceColorMode::kGammaAndColorSpaceAware;
7876c15cc7e9d65981ec0363a050d2248f96e21a5daBrian Osman    }
7886c15cc7e9d65981ec0363a050d2248f96e21a5daBrian Osman
78941b952c296e343eeabb07d52b6a55ba7565a286bbsalomon    SkASSERT(info == pixmap.info());
79041b952c296e343eeabb07d52b6a55ba7565a286bbsalomon    size_t rowBytes = pixmap.rowBytes();
79133e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume    static_assert(std::is_standard_layout<DeferredTextureImage>::value,
79233e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume                  "offsetof, which we use below, requires the type have standard layout");
793921bc678a7b81de31b4e672326ed2f37ffb66b10cblume    auto dtiBufferFiller = DTIBufferFiller{bufferAsCharPtr};
7947b8400dad2f82dcc6ed3c7cc1707ebaf85f04840Brian Osman    FILL_MEMBER(dtiBufferFiller, fColorMode, &colorMode);
79533e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume    FILL_MEMBER(dtiBufferFiller, fContextUniqueID, &proxy.fContextUniqueID);
79633e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume    int width = info.width();
79733e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume    FILL_MEMBER(dtiBufferFiller, fWidth, &width);
79833e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume    int height = info.height();
79933e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume    FILL_MEMBER(dtiBufferFiller, fHeight, &height);
80033e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume    SkColorType colorType = info.colorType();
80133e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume    FILL_MEMBER(dtiBufferFiller, fColorType, &colorType);
80233e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume    SkAlphaType alphaType = info.alphaType();
80333e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume    FILL_MEMBER(dtiBufferFiller, fAlphaType, &alphaType);
80433e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume    FILL_MEMBER(dtiBufferFiller, fMipMapLevelCount, &mipMapLevelCount);
805921bc678a7b81de31b4e672326ed2f37ffb66b10cblume    memcpy(bufferAsCharPtr + offsetof(DeferredTextureImage, fMipMapLevelData[0].fPixelData),
80633e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume           &pixels, sizeof(pixels));
807921bc678a7b81de31b4e672326ed2f37ffb66b10cblume    memcpy(bufferAsCharPtr + offsetof(DeferredTextureImage, fMipMapLevelData[0].fRowBytes),
80833e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume           &rowBytes, sizeof(rowBytes));
8094d516a6903d83414b5615ca9388b52064da6990cbsalomon    if (colorSpaceSize) {
810921bc678a7b81de31b4e672326ed2f37ffb66b10cblume        void* colorSpace = bufferAsCharPtr + colorSpaceOffset;
81133e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume        FILL_MEMBER(dtiBufferFiller, fColorSpace, &colorSpace);
81233e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume        FILL_MEMBER(dtiBufferFiller, fColorSpaceSize, &colorSpaceSize);
81384c9cb7bd8f4c2b0cd4a378995ebbd8524efa390Matt Sarett        if (info.colorSpace()) {
81484c9cb7bd8f4c2b0cd4a378995ebbd8524efa390Matt Sarett            info.colorSpace()->writeToMemory(bufferAsCharPtr + colorSpaceOffset);
81584c9cb7bd8f4c2b0cd4a378995ebbd8524efa390Matt Sarett        } else {
81684c9cb7bd8f4c2b0cd4a378995ebbd8524efa390Matt Sarett            SkASSERT(this->colorSpace() && this->colorSpace()->isNumericalTransferFn(&fn));
81784c9cb7bd8f4c2b0cd4a378995ebbd8524efa390Matt Sarett            SkASSERT(!dstColorSpace);
81884c9cb7bd8f4c2b0cd4a378995ebbd8524efa390Matt Sarett            this->colorSpace()->writeToMemory(bufferAsCharPtr + colorSpaceOffset);
81984c9cb7bd8f4c2b0cd4a378995ebbd8524efa390Matt Sarett        }
8204d516a6903d83414b5615ca9388b52064da6990cbsalomon    } else {
821921bc678a7b81de31b4e672326ed2f37ffb66b10cblume        memset(bufferAsCharPtr + offsetof(DeferredTextureImage, fColorSpace),
82233e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume               0, sizeof(DeferredTextureImage::fColorSpace));
823921bc678a7b81de31b4e672326ed2f37ffb66b10cblume        memset(bufferAsCharPtr + offsetof(DeferredTextureImage, fColorSpaceSize),
82433e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume               0, sizeof(DeferredTextureImage::fColorSpaceSize));
82533e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume    }
82633e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume
82733e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume    // Fill in the mipmap levels if they exist
828921bc678a7b81de31b4e672326ed2f37ffb66b10cblume    char* mipLevelPtr = pixelsAsCharPtr + SkAlign8(pixmap.getSafeSize());
82933e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume
83033e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume    if (useMipMaps) {
83194ddf54a6da1b4c65beaf1a32ac1718959b0709ccblume        static_assert(std::is_standard_layout<MipMapLevelData>::value,
83294ddf54a6da1b4c65beaf1a32ac1718959b0709ccblume                      "offsetof, which we use below, requires the type have a standard layout");
83333e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume
8347b8400dad2f82dcc6ed3c7cc1707ebaf85f04840Brian Osman        std::unique_ptr<SkMipMap> mipmaps(SkMipMap::Build(pixmap, colorMode, nullptr));
83533e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume        // SkMipMap holds only the mipmap levels it generates.
83633e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume        // A programmer can use the data they provided to SkMipMap::Build as level 0.
83733e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume        // So the SkMipMap provides levels 1-x but it stores them in its own
83833e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume        // range 0-(x-1).
83933e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume        for (int generatedMipLevelIndex = 0; generatedMipLevelIndex < mipMapLevelCount - 1;
84033e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume             generatedMipLevelIndex++) {
84133e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume            SkMipMap::Level mipLevel;
84233e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume            mipmaps->getLevel(generatedMipLevelIndex, &mipLevel);
84333e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume
84433e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume            // Make sure the mipmap data is after the start of the buffer
845921bc678a7b81de31b4e672326ed2f37ffb66b10cblume            SkASSERT(mipLevelPtr > bufferAsCharPtr);
84633e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume            // Make sure the mipmap data starts before the end of the buffer
847921bc678a7b81de31b4e672326ed2f37ffb66b10cblume            SkASSERT(mipLevelPtr < bufferAsCharPtr + pixelOffset + pixelSize);
84833e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume            // Make sure the mipmap data ends before the end of the buffer
84912f752723b31bb015ded118bfa466c2f1e9b2905cblume            SkASSERT(mipLevelPtr + mipLevel.fPixmap.getSafeSize() <=
850921bc678a7b81de31b4e672326ed2f37ffb66b10cblume                     bufferAsCharPtr + pixelOffset + pixelSize);
85133e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume
85233e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume            // getSafeSize includes rowbyte padding except for the last row,
85333e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume            // right?
85433e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume
855921bc678a7b81de31b4e672326ed2f37ffb66b10cblume            memcpy(mipLevelPtr, mipLevel.fPixmap.addr(), mipLevel.fPixmap.getSafeSize());
85633e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume
857921bc678a7b81de31b4e672326ed2f37ffb66b10cblume            memcpy(bufferAsCharPtr + offsetof(DeferredTextureImage, fMipMapLevelData) +
858921bc678a7b81de31b4e672326ed2f37ffb66b10cblume                   sizeof(MipMapLevelData) * (generatedMipLevelIndex + 1) +
859921bc678a7b81de31b4e672326ed2f37ffb66b10cblume                   offsetof(MipMapLevelData, fPixelData), &mipLevelPtr, sizeof(void*));
86033e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume            size_t rowBytes = mipLevel.fPixmap.rowBytes();
861921bc678a7b81de31b4e672326ed2f37ffb66b10cblume            memcpy(bufferAsCharPtr + offsetof(DeferredTextureImage, fMipMapLevelData) +
862921bc678a7b81de31b4e672326ed2f37ffb66b10cblume                   sizeof(MipMapLevelData) * (generatedMipLevelIndex + 1) +
863921bc678a7b81de31b4e672326ed2f37ffb66b10cblume                   offsetof(MipMapLevelData, fRowBytes), &rowBytes, sizeof(rowBytes));
86433e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume
86533e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume            mipLevelPtr += SkAlign8(mipLevel.fPixmap.getSafeSize());
86633e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume        }
8674d516a6903d83414b5615ca9388b52064da6990cbsalomon    }
86841b952c296e343eeabb07d52b6a55ba7565a286bbsalomon    return size;
86941b952c296e343eeabb07d52b6a55ba7565a286bbsalomon}
87041b952c296e343eeabb07d52b6a55ba7565a286bbsalomon
87141b952c296e343eeabb07d52b6a55ba7565a286bbsalomonsk_sp<SkImage> SkImage::MakeFromDeferredTextureImageData(GrContext* context, const void* data,
87241b952c296e343eeabb07d52b6a55ba7565a286bbsalomon                                                         SkBudgeted budgeted) {
87341b952c296e343eeabb07d52b6a55ba7565a286bbsalomon    if (!data) {
87441b952c296e343eeabb07d52b6a55ba7565a286bbsalomon        return nullptr;
87541b952c296e343eeabb07d52b6a55ba7565a286bbsalomon    }
87641b952c296e343eeabb07d52b6a55ba7565a286bbsalomon    const DeferredTextureImage* dti = reinterpret_cast<const DeferredTextureImage*>(data);
87741b952c296e343eeabb07d52b6a55ba7565a286bbsalomon
878228482a709690135da4d67879fcc13885e9882e0Brian Salomon    if (!context || context->uniqueID() != dti->fContextUniqueID || context->abandoned()) {
87941b952c296e343eeabb07d52b6a55ba7565a286bbsalomon        return nullptr;
88041b952c296e343eeabb07d52b6a55ba7565a286bbsalomon    }
88133e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume    int mipLevelCount = dti->fMipMapLevelCount;
88233e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume    SkASSERT(mipLevelCount >= 1);
8834d516a6903d83414b5615ca9388b52064da6990cbsalomon    sk_sp<SkColorSpace> colorSpace;
8844d516a6903d83414b5615ca9388b52064da6990cbsalomon    if (dti->fColorSpaceSize) {
8854d516a6903d83414b5615ca9388b52064da6990cbsalomon        colorSpace = SkColorSpace::Deserialize(dti->fColorSpace, dti->fColorSpaceSize);
88641b952c296e343eeabb07d52b6a55ba7565a286bbsalomon    }
8874d516a6903d83414b5615ca9388b52064da6990cbsalomon    SkImageInfo info = SkImageInfo::Make(dti->fWidth, dti->fHeight,
8884d516a6903d83414b5615ca9388b52064da6990cbsalomon                                         dti->fColorType, dti->fAlphaType, colorSpace);
889b92234a3210bce532f103d71002f4e04d336a182Brian Osman    if (mipLevelCount == 1) {
890b92234a3210bce532f103d71002f4e04d336a182Brian Osman        SkPixmap pixmap;
891b92234a3210bce532f103d71002f4e04d336a182Brian Osman        pixmap.reset(info, dti->fMipMapLevelData[0].fPixelData, dti->fMipMapLevelData[0].fRowBytes);
89284c9cb7bd8f4c2b0cd4a378995ebbd8524efa390Matt Sarett
893dedac85b4f08546e92143d96c13b753cb1b80e23Matt Sarett        // Pass nullptr for the |dstColorSpace|.  This opts in to more lenient color space
894dedac85b4f08546e92143d96c13b753cb1b80e23Matt Sarett        // verification.  This is ok because we've already verified the color space in
895dedac85b4f08546e92143d96c13b753cb1b80e23Matt Sarett        // getDeferredTextureImageData().
896dedac85b4f08546e92143d96c13b753cb1b80e23Matt Sarett        sk_sp<GrTextureProxy> proxy(GrUploadPixmapToTextureProxy(
897dedac85b4f08546e92143d96c13b753cb1b80e23Matt Sarett                context->resourceProvider(), pixmap, budgeted, nullptr));
898ed182d7c9020a0a533ada3e601183f34e4da7504Brian Osman        if (!proxy) {
899ed182d7c9020a0a533ada3e601183f34e4da7504Brian Osman            return nullptr;
900ed182d7c9020a0a533ada3e601183f34e4da7504Brian Osman        }
901ed182d7c9020a0a533ada3e601183f34e4da7504Brian Osman        return sk_make_sp<SkImage_Gpu>(context, kNeedNewImageUniqueID, pixmap.alphaType(),
902ed182d7c9020a0a533ada3e601183f34e4da7504Brian Osman                                       std::move(proxy), std::move(colorSpace), budgeted);
903b92234a3210bce532f103d71002f4e04d336a182Brian Osman    } else {
904b92234a3210bce532f103d71002f4e04d336a182Brian Osman        std::unique_ptr<GrMipLevel[]> texels(new GrMipLevel[mipLevelCount]);
905b92234a3210bce532f103d71002f4e04d336a182Brian Osman        for (int i = 0; i < mipLevelCount; i++) {
906b92234a3210bce532f103d71002f4e04d336a182Brian Osman            texels[i].fPixels = dti->fMipMapLevelData[i].fPixelData;
907b92234a3210bce532f103d71002f4e04d336a182Brian Osman            texels[i].fRowBytes = dti->fMipMapLevelData[i].fRowBytes;
908b92234a3210bce532f103d71002f4e04d336a182Brian Osman        }
9098ccbbb455c6ef194920c47e846b95b50f5017138Brian Osman
910b92234a3210bce532f103d71002f4e04d336a182Brian Osman        return SkImage::MakeTextureFromMipMap(context, info, texels.get(),
911b92234a3210bce532f103d71002f4e04d336a182Brian Osman                                              mipLevelCount, SkBudgeted::kYes,
912b92234a3210bce532f103d71002f4e04d336a182Brian Osman                                              dti->fColorMode);
913b92234a3210bce532f103d71002f4e04d336a182Brian Osman    }
91441b952c296e343eeabb07d52b6a55ba7565a286bbsalomon}
91541b952c296e343eeabb07d52b6a55ba7565a286bbsalomon
91641b952c296e343eeabb07d52b6a55ba7565a286bbsalomon///////////////////////////////////////////////////////////////////////////////////////////////////
91741b952c296e343eeabb07d52b6a55ba7565a286bbsalomon
918186d2d430ba248fea1e00669154b95252ac9a486cblumesk_sp<SkImage> SkImage::MakeTextureFromMipMap(GrContext* ctx, const SkImageInfo& info,
919590533f066035a48df9f78395a80314b559f4714Robert Phillips                                              const GrMipLevel texels[], int mipLevelCount,
92033e0cb5e7f9926b96db209c825f1eeca7c15bb16cblume                                              SkBudgeted budgeted,
9217b8400dad2f82dcc6ed3c7cc1707ebaf85f04840Brian Osman                                              SkDestinationSurfaceColorMode colorMode) {
9221119dc366e15ef737d05d3a087410ea40c508101Robert Phillips    SkASSERT(mipLevelCount >= 1);
923186d2d430ba248fea1e00669154b95252ac9a486cblume    if (!ctx) {
924186d2d430ba248fea1e00669154b95252ac9a486cblume        return nullptr;
925186d2d430ba248fea1e00669154b95252ac9a486cblume    }
9260ae6faa34d73ffc7ebec3d13f0473703bade821bRobert Phillips    sk_sp<GrTextureProxy> proxy(GrUploadMipMapToTextureProxy(ctx, info, texels, mipLevelCount,
9270ae6faa34d73ffc7ebec3d13f0473703bade821bRobert Phillips                                                             colorMode));
9280ae6faa34d73ffc7ebec3d13f0473703bade821bRobert Phillips    if (!proxy) {
929186d2d430ba248fea1e00669154b95252ac9a486cblume        return nullptr;
930186d2d430ba248fea1e00669154b95252ac9a486cblume    }
9310ae6faa34d73ffc7ebec3d13f0473703bade821bRobert Phillips
9320ae6faa34d73ffc7ebec3d13f0473703bade821bRobert Phillips    SkASSERT(proxy->priv().isExact());
9330ae6faa34d73ffc7ebec3d13f0473703bade821bRobert Phillips    return sk_make_sp<SkImage_Gpu>(ctx, kNeedNewImageUniqueID,
9340ae6faa34d73ffc7ebec3d13f0473703bade821bRobert Phillips                                   info.alphaType(), std::move(proxy),
9350ae6faa34d73ffc7ebec3d13f0473703bade821bRobert Phillips                                   info.refColorSpace(), budgeted);
936186d2d430ba248fea1e00669154b95252ac9a486cblume}
93763954c9944a5eed4527e0ed368f4e501faf2c625Brian Osman
938d3df9ec874b2668111b36ce0993d860b4f88c765Matt Sarettsk_sp<SkImage> SkImage_Gpu::onMakeColorSpace(sk_sp<SkColorSpace> target, SkColorType,
9399f3dcb3f760274d42e28095fd3cf0f484168d996Matt Sarett                                             SkTransferFunctionBehavior premulBehavior) const {
9409f3dcb3f760274d42e28095fd3cf0f484168d996Matt Sarett    if (SkTransferFunctionBehavior::kRespect == premulBehavior) {
9419f3dcb3f760274d42e28095fd3cf0f484168d996Matt Sarett        // TODO: Implement this.
9429f3dcb3f760274d42e28095fd3cf0f484168d996Matt Sarett        return nullptr;
9439f3dcb3f760274d42e28095fd3cf0f484168d996Matt Sarett    }
9449f3dcb3f760274d42e28095fd3cf0f484168d996Matt Sarett
945d3df9ec874b2668111b36ce0993d860b4f88c765Matt Sarett    sk_sp<SkColorSpace> srcSpace = fColorSpace;
946d3df9ec874b2668111b36ce0993d860b4f88c765Matt Sarett    if (!fColorSpace) {
947d3df9ec874b2668111b36ce0993d860b4f88c765Matt Sarett        if (target->isSRGB()) {
948d3df9ec874b2668111b36ce0993d860b4f88c765Matt Sarett            return sk_ref_sp(const_cast<SkImage*>((SkImage*)this));
949d3df9ec874b2668111b36ce0993d860b4f88c765Matt Sarett        }
950d3df9ec874b2668111b36ce0993d860b4f88c765Matt Sarett
951d3df9ec874b2668111b36ce0993d860b4f88c765Matt Sarett        srcSpace = SkColorSpace::MakeSRGB();
952d3df9ec874b2668111b36ce0993d860b4f88c765Matt Sarett    }
953d3df9ec874b2668111b36ce0993d860b4f88c765Matt Sarett
954d3df9ec874b2668111b36ce0993d860b4f88c765Matt Sarett    auto xform = GrNonlinearColorSpaceXformEffect::Make(srcSpace.get(), target.get());
95563954c9944a5eed4527e0ed368f4e501faf2c625Brian Osman    if (!xform) {
95663954c9944a5eed4527e0ed368f4e501faf2c625Brian Osman        return sk_ref_sp(const_cast<SkImage_Gpu*>(this));
95763954c9944a5eed4527e0ed368f4e501faf2c625Brian Osman    }
95863954c9944a5eed4527e0ed368f4e501faf2c625Brian Osman
959dd3b3f41829d32d7eaf3eb4903570d49c2ba9ff8Robert Phillips    sk_sp<GrRenderTargetContext> renderTargetContext(fContext->makeDeferredRenderTargetContext(
96063954c9944a5eed4527e0ed368f4e501faf2c625Brian Osman        SkBackingFit::kExact, this->width(), this->height(), kRGBA_8888_GrPixelConfig, nullptr));
96163954c9944a5eed4527e0ed368f4e501faf2c625Brian Osman    if (!renderTargetContext) {
96263954c9944a5eed4527e0ed368f4e501faf2c625Brian Osman        return nullptr;
96363954c9944a5eed4527e0ed368f4e501faf2c625Brian Osman    }
96463954c9944a5eed4527e0ed368f4e501faf2c625Brian Osman
96563954c9944a5eed4527e0ed368f4e501faf2c625Brian Osman    GrPaint paint;
96663954c9944a5eed4527e0ed368f4e501faf2c625Brian Osman    paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
967fbcef6eb8abad142daf45418516550f7635b4a52Robert Phillips    paint.addColorTextureProcessor(fProxy, nullptr, SkMatrix::I());
96863954c9944a5eed4527e0ed368f4e501faf2c625Brian Osman    paint.addColorFragmentProcessor(std::move(xform));
96963954c9944a5eed4527e0ed368f4e501faf2c625Brian Osman
97063954c9944a5eed4527e0ed368f4e501faf2c625Brian Osman    const SkRect rect = SkRect::MakeIWH(this->width(), this->height());
97163954c9944a5eed4527e0ed368f4e501faf2c625Brian Osman
97263954c9944a5eed4527e0ed368f4e501faf2c625Brian Osman    renderTargetContext->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(), rect);
97363954c9944a5eed4527e0ed368f4e501faf2c625Brian Osman
9747ee385e1dc3cd6a47dc8f7297fef6e175eaba224Robert Phillips    if (!renderTargetContext->asTextureProxy()) {
97563954c9944a5eed4527e0ed368f4e501faf2c625Brian Osman        return nullptr;
97663954c9944a5eed4527e0ed368f4e501faf2c625Brian Osman    }
97763954c9944a5eed4527e0ed368f4e501faf2c625Brian Osman
97863954c9944a5eed4527e0ed368f4e501faf2c625Brian Osman    // MDB: this call is okay bc we know 'renderTargetContext' was exact
97963954c9944a5eed4527e0ed368f4e501faf2c625Brian Osman    return sk_make_sp<SkImage_Gpu>(fContext, kNeedNewImageUniqueID,
98063954c9944a5eed4527e0ed368f4e501faf2c625Brian Osman                                   fAlphaType, renderTargetContext->asTextureProxyRef(),
981d3df9ec874b2668111b36ce0993d860b4f88c765Matt Sarett                                   std::move(target), fBudgeted);
98263954c9944a5eed4527e0ed368f4e501faf2c625Brian Osman
98363954c9944a5eed4527e0ed368f4e501faf2c625Brian Osman}
9845bbd076c52a6cebff4a2d63edd027b0f31624287Brian Osman
9855bbd076c52a6cebff4a2d63edd027b0f31624287Brian Osmanbool SkImage_Gpu::onIsValid(GrContext* context) const {
9865bbd076c52a6cebff4a2d63edd027b0f31624287Brian Osman    // The base class has already checked that context isn't abandoned (if it's not nullptr)
9875bbd076c52a6cebff4a2d63edd027b0f31624287Brian Osman    if (fContext->abandoned()) {
9885bbd076c52a6cebff4a2d63edd027b0f31624287Brian Osman        return false;
9895bbd076c52a6cebff4a2d63edd027b0f31624287Brian Osman    }
9905bbd076c52a6cebff4a2d63edd027b0f31624287Brian Osman
9915bbd076c52a6cebff4a2d63edd027b0f31624287Brian Osman    if (context && context != fContext) {
9925bbd076c52a6cebff4a2d63edd027b0f31624287Brian Osman        return false;
9935bbd076c52a6cebff4a2d63edd027b0f31624287Brian Osman    }
9945bbd076c52a6cebff4a2d63edd027b0f31624287Brian Osman
9955bbd076c52a6cebff4a2d63edd027b0f31624287Brian Osman    return true;
9965bbd076c52a6cebff4a2d63edd027b0f31624287Brian Osman}
997