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" 220bd24dc41f2351d84f5fce32130668a5792d134bRobert Phillips#include "GrProxyProvider.h" 231105224f9701e57ec5ce0354d6a380b664f5c638Brian Osman#include "GrRenderTargetContext.h" 2432342f032e1dfd133040324f851f0365f9d4cb51Brian Osman#include "GrResourceProvider.h" 25fe3b51636d4216c4ea6cb74ed0964c1d315ca487Brian Osman#include "GrSemaphore.h" 26914a36b248ffb538874483d86759254838866dd7Eric Karl#include "GrSurfacePriv.h" 27e8e54580c3c91fd485187af040af118aa5153261Brian Osman#include "GrTextureAdjuster.h" 28646e4293f06d9de6d44dbfa3c32cdc15a6f5906eRobert Phillips#include "GrTexture.h" 29914a36b248ffb538874483d86759254838866dd7Eric Karl#include "GrTexturePriv.h" 30bc7a4fb06780f9829b4b21470fe6f0503d2297cdRobert Phillips#include "GrTextureProxy.h" 3163954c9944a5eed4527e0ed368f4e501faf2c625Brian Osman#include "effects/GrNonlinearColorSpaceXformEffect.h" 327461a4abe06ffdfbb62a479a71b14895a637bba9Ethan Nicholas#include "effects/GrYUVtoRGBEffect.h" 33993a4216a6014b9de8f4d8120360c94550dc6761bsalomon#include "SkCanvas.h" 34262a71b7f95ce98ff3dd8dba845afbd724470903reed#include "SkBitmapCache.h" 353b65598bceb65736486db27ed49a56d787032747Brian Osman#include "SkGr.h" 36262a71b7f95ce98ff3dd8dba845afbd724470903reed#include "SkImage_Gpu.h" 377992da32f02f90e0ac9ab6914eb31676b502eb71Brian Osman#include "SkImageCacherator.h" 38cb6266b5aa5bbfd880532f08eec83b0c585e873fMatt Sarett#include "SkImageInfoPriv.h" 39b4da01d8f719f3c43d492e8f62a7e2c861e9ef27ericrk#include "SkMipMap.h" 406f1216ac158e36a3a1cc805e7f899c755c5b98a2reed#include "SkPixelRef.h" 4103dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarett#include "SkReadPixelsRec.h" 42bc54fadf610b8d17165735d55de431a47fde9349Greg Daniel#include "SkTraceEvent.h" 43993a4216a6014b9de8f4d8120360c94550dc6761bsalomon 44b726d58efc91c4eefa5cea0881a823ee108db8fdRobert PhillipsSkImage_Gpu::SkImage_Gpu(GrContext* context, uint32_t uniqueID, SkAlphaType at, 45b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips sk_sp<GrTextureProxy> proxy, 46b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips sk_sp<SkColorSpace> colorSpace, SkBudgeted budgeted) 47a108c92ae5868ca99759a872edddb377f31ad1beRobert Phillips : INHERITED(proxy->worstCaseWidth(), proxy->worstCaseHeight(), uniqueID) 48b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips , fContext(context) 49b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips , fProxy(std::move(proxy)) 50b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips , fAlphaType(at) 51b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips , fBudgeted(budgeted) 52b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips , fColorSpace(std::move(colorSpace)) 53b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips , fAddedRasterVersionToCache(false) { 54c9b5f8b1522e72449d704d30ed6aee4fc6211ee8reed} 55cef04f818820e59fb534eb226f967f72497845d3piotaixr 566f1216ac158e36a3a1cc805e7f899c755c5b98a2reedSkImage_Gpu::~SkImage_Gpu() { 576f1216ac158e36a3a1cc805e7f899c755c5b98a2reed if (fAddedRasterVersionToCache.load()) { 586f1216ac158e36a3a1cc805e7f899c755c5b98a2reed SkNotifyBitmapGenIDIsStale(this->uniqueID()); 596f1216ac158e36a3a1cc805e7f899c755c5b98a2reed } 606f1216ac158e36a3a1cc805e7f899c755c5b98a2reed} 616f1216ac158e36a3a1cc805e7f899c755c5b98a2reed 62396fcdba14a0101ed43dcc3863585bf50c4ed6ccbrianosmanSkImageInfo SkImage_Gpu::onImageInfo() const { 63396fcdba14a0101ed43dcc3863585bf50c4ed6ccbrianosman SkColorType ct; 64b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips if (!GrPixelConfigToColorType(fProxy->config(), &ct)) { 65396fcdba14a0101ed43dcc3863585bf50c4ed6ccbrianosman ct = kUnknown_SkColorType; 66396fcdba14a0101ed43dcc3863585bf50c4ed6ccbrianosman } 67b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips return SkImageInfo::Make(fProxy->width(), fProxy->height(), ct, fAlphaType, fColorSpace); 68396fcdba14a0101ed43dcc3863585bf50c4ed6ccbrianosman} 69396fcdba14a0101ed43dcc3863585bf50c4ed6ccbrianosman 706251771ebc5c4d7c98af3e2f3f2e7b22e490c1d5Brian Osmanbool SkImage_Gpu::getROPixels(SkBitmap* dst, SkColorSpace*, CachingHint chint) const { 716251771ebc5c4d7c98af3e2f3f2e7b22e490c1d5Brian Osman // The SkColorSpace parameter "dstColorSpace" is really just a hint about how/where the bitmap 726251771ebc5c4d7c98af3e2f3f2e7b22e490c1d5Brian Osman // will be used. The client doesn't expect that we convert to that color space, it's intended 736251771ebc5c4d7c98af3e2f3f2e7b22e490c1d5Brian Osman // for codec-backed images, to drive our decoding heuristic. In theory we *could* read directly 746251771ebc5c4d7c98af3e2f3f2e7b22e490c1d5Brian Osman // into that color space (to save the client some effort in whatever they're about to do), but 756251771ebc5c4d7c98af3e2f3f2e7b22e490c1d5Brian Osman // that would make our use of the bitmap cache incorrect (or much less efficient, assuming we 766251771ebc5c4d7c98af3e2f3f2e7b22e490c1d5Brian Osman // rolled the dstColorSpace into the key). 775fa3d6d4b15fd6417de877561f5e4bca422e383cMike Reed const auto desc = SkBitmapCacheDesc::Make(this); 785fa3d6d4b15fd6417de877561f5e4bca422e383cMike Reed if (SkBitmapCache::Find(desc, dst)) { 796f1216ac158e36a3a1cc805e7f899c755c5b98a2reed SkASSERT(dst->getGenerationID() == this->uniqueID()); 806f1216ac158e36a3a1cc805e7f899c755c5b98a2reed SkASSERT(dst->isImmutable()); 816f1216ac158e36a3a1cc805e7f899c755c5b98a2reed SkASSERT(dst->getPixels()); 826f1216ac158e36a3a1cc805e7f899c755c5b98a2reed return true; 836f1216ac158e36a3a1cc805e7f899c755c5b98a2reed } 846f1216ac158e36a3a1cc805e7f899c755c5b98a2reed 857a542c559a6e584107b94e6254ac3c7f9f24b591Mike Reed SkBitmapCache::RecPtr rec = nullptr; 867a542c559a6e584107b94e6254ac3c7f9f24b591Mike Reed SkPixmap pmap; 877a542c559a6e584107b94e6254ac3c7f9f24b591Mike Reed if (kAllow_CachingHint == chint) { 886251771ebc5c4d7c98af3e2f3f2e7b22e490c1d5Brian Osman rec = SkBitmapCache::Alloc(desc, this->onImageInfo(), &pmap); 897a542c559a6e584107b94e6254ac3c7f9f24b591Mike Reed if (!rec) { 907a542c559a6e584107b94e6254ac3c7f9f24b591Mike Reed return false; 917a542c559a6e584107b94e6254ac3c7f9f24b591Mike Reed } 927a542c559a6e584107b94e6254ac3c7f9f24b591Mike Reed } else { 936251771ebc5c4d7c98af3e2f3f2e7b22e490c1d5Brian Osman if (!dst->tryAllocPixels(this->onImageInfo()) || !dst->peekPixels(&pmap)) { 947a542c559a6e584107b94e6254ac3c7f9f24b591Mike Reed return false; 957a542c559a6e584107b94e6254ac3c7f9f24b591Mike Reed } 96b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips } 97b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips 982084ffa9a3fa7eb3c7e17ec5b55750be9942bafcBrian Salomon sk_sp<GrSurfaceContext> sContext = fContext->contextPriv().makeWrappedSurfaceContext( 992084ffa9a3fa7eb3c7e17ec5b55750be9942bafcBrian Salomon fProxy, 1002084ffa9a3fa7eb3c7e17ec5b55750be9942bafcBrian Salomon fColorSpace); 101b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips if (!sContext) { 1028b26b99c97473f020df4b9d4ba789e074e06ceddreed return false; 1038b26b99c97473f020df4b9d4ba789e074e06ceddreed } 104b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips 1057a542c559a6e584107b94e6254ac3c7f9f24b591Mike Reed if (!sContext->readPixels(pmap.info(), pmap.writable_addr(), pmap.rowBytes(), 0, 0)) { 1068b26b99c97473f020df4b9d4ba789e074e06ceddreed return false; 1078b26b99c97473f020df4b9d4ba789e074e06ceddreed } 1086f1216ac158e36a3a1cc805e7f899c755c5b98a2reed 1097a542c559a6e584107b94e6254ac3c7f9f24b591Mike Reed if (rec) { 1107a542c559a6e584107b94e6254ac3c7f9f24b591Mike Reed SkBitmapCache::Add(std::move(rec), dst); 111095530389d8211895309107a4f74beefacce638creed fAddedRasterVersionToCache.store(true); 112095530389d8211895309107a4f74beefacce638creed } 1138b26b99c97473f020df4b9d4ba789e074e06ceddreed return true; 114ace135453db02cfe83d7c7bbeaa679f98d18fbe2reed@google.com} 115ace135453db02cfe83d7c7bbeaa679f98d18fbe2reed@google.com 116b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillipssk_sp<GrTextureProxy> SkImage_Gpu::asTextureProxyRef(GrContext* context, 1172bbdcc44c63974f29f3743bb58d929601a3f65c6Brian Salomon const GrSamplerState& params, 118b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips SkColorSpace* dstColorSpace, 119b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips sk_sp<SkColorSpace>* texColorSpace, 120b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips SkScalar scaleAdjust[2]) const { 12130a38ff737c61799b0f36d2e6ba412f7e612f617Robert Phillips if (context != fContext) { 122b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips SkASSERT(0); 123b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips return nullptr; 124b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips } 125b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips 126c77085d2e0a3ff7e908a7164ac6224ea10686739Greg Daniel GrTextureAdjuster adjuster(fContext, fProxy, this->alphaType(), this->uniqueID(), 127c77085d2e0a3ff7e908a7164ac6224ea10686739Greg Daniel this->fColorSpace.get()); 12838784599f39026f54aa56b3c6e34afc15e00abd6Leon Scroggins III return adjuster.refTextureProxyForParams(params, dstColorSpace, texColorSpace, 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 } 1499708af826cab6f7194aa852922e53cccbc7fd0a3Brian Salomon row = (SkColor*)((char*)(row) + rowBytes); 1505d4ba8869476831ee73b15a052af8003d0a1fa2ereed@google.com } 1514af267b11964d4a8acdb232ac46094c84d890e88reed} 152fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1530ae6faa34d73ffc7ebec3d13f0473703bade821bRobert PhillipsGrBackendObject SkImage_Gpu::onGetTextureHandle(bool flushPendingGrContextIO, 1540ae6faa34d73ffc7ebec3d13f0473703bade821bRobert Phillips GrSurfaceOrigin* origin) const { 1557ee385e1dc3cd6a47dc8f7297fef6e175eaba224Robert Phillips SkASSERT(fProxy); 1560ae6faa34d73ffc7ebec3d13f0473703bade821bRobert Phillips 157f2336e4500769bc0ff6a208289d757581b0ea91aGreg Daniel if (!fContext->contextPriv().resourceProvider() && !fProxy->priv().isInstantiated()) { 158f2336e4500769bc0ff6a208289d757581b0ea91aGreg Daniel // This image was created with a DDL context and cannot be instantiated. Thus we return 0 159f2336e4500769bc0ff6a208289d757581b0ea91aGreg Daniel // here which is considered invalid for all backends. 160f2336e4500769bc0ff6a208289d757581b0ea91aGreg Daniel return 0; 161f2336e4500769bc0ff6a208289d757581b0ea91aGreg Daniel } 162f2336e4500769bc0ff6a208289d757581b0ea91aGreg Daniel 163f2336e4500769bc0ff6a208289d757581b0ea91aGreg Daniel if (GrSurfaceProxy::LazyState::kNot != fProxy->lazyInstantiationState()) { 164f2336e4500769bc0ff6a208289d757581b0ea91aGreg Daniel SkASSERT(fContext->contextPriv().resourceProvider()); 165f2336e4500769bc0ff6a208289d757581b0ea91aGreg Daniel fProxy->priv().doLazyInstantiation(fContext->contextPriv().resourceProvider()); 166f2336e4500769bc0ff6a208289d757581b0ea91aGreg Daniel if (!fProxy->priv().isInstantiated()) { 167f2336e4500769bc0ff6a208289d757581b0ea91aGreg Daniel // We failed to instantiate the lazy proxy. Thus we return 0 here which is considered 168f2336e4500769bc0ff6a208289d757581b0ea91aGreg Daniel // invalid for all backends. 169f2336e4500769bc0ff6a208289d757581b0ea91aGreg Daniel return 0; 170f2336e4500769bc0ff6a208289d757581b0ea91aGreg Daniel } 171f2336e4500769bc0ff6a208289d757581b0ea91aGreg Daniel } 172f2336e4500769bc0ff6a208289d757581b0ea91aGreg Daniel 1736be756b673b823881e90a2ef68c12b640ddde549Robert Phillips if (!fProxy->instantiate(fContext->contextPriv().resourceProvider())) { 174eee4d6e4e8cc5c4c79f065abcc3ce609f71238f9Robert Phillips return 0; 175eee4d6e4e8cc5c4c79f065abcc3ce609f71238f9Robert Phillips } 176eee4d6e4e8cc5c4c79f065abcc3ce609f71238f9Robert Phillips 177eee4d6e4e8cc5c4c79f065abcc3ce609f71238f9Robert Phillips GrTexture* texture = fProxy->priv().peekTexture(); 178eee4d6e4e8cc5c4c79f065abcc3ce609f71238f9Robert Phillips 179eee4d6e4e8cc5c4c79f065abcc3ce609f71238f9Robert Phillips if (texture) { 1800ae6faa34d73ffc7ebec3d13f0473703bade821bRobert Phillips if (flushPendingGrContextIO) { 1817ee385e1dc3cd6a47dc8f7297fef6e175eaba224Robert Phillips fContext->contextPriv().prepareSurfaceForExternalIO(fProxy.get()); 1820ae6faa34d73ffc7ebec3d13f0473703bade821bRobert Phillips } 1830ae6faa34d73ffc7ebec3d13f0473703bade821bRobert Phillips if (origin) { 1847ee385e1dc3cd6a47dc8f7297fef6e175eaba224Robert Phillips *origin = fProxy->origin(); 1850ae6faa34d73ffc7ebec3d13f0473703bade821bRobert Phillips } 186eee4d6e4e8cc5c4c79f065abcc3ce609f71238f9Robert Phillips return texture->getTextureHandle(); 1870ae6faa34d73ffc7ebec3d13f0473703bade821bRobert Phillips } 1880ae6faa34d73ffc7ebec3d13f0473703bade821bRobert Phillips return 0; 1890ae6faa34d73ffc7ebec3d13f0473703bade821bRobert Phillips} 1900ae6faa34d73ffc7ebec3d13f0473703bade821bRobert Phillips 1910ae6faa34d73ffc7ebec3d13f0473703bade821bRobert PhillipsGrTexture* SkImage_Gpu::onGetTexture() const { 1920ae6faa34d73ffc7ebec3d13f0473703bade821bRobert Phillips GrTextureProxy* proxy = this->peekProxy(); 1930ae6faa34d73ffc7ebec3d13f0473703bade821bRobert Phillips if (!proxy) { 1940ae6faa34d73ffc7ebec3d13f0473703bade821bRobert Phillips return nullptr; 1950ae6faa34d73ffc7ebec3d13f0473703bade821bRobert Phillips } 1960ae6faa34d73ffc7ebec3d13f0473703bade821bRobert Phillips 1976be756b673b823881e90a2ef68c12b640ddde549Robert Phillips if (!proxy->instantiate(fContext->contextPriv().resourceProvider())) { 198eee4d6e4e8cc5c4c79f065abcc3ce609f71238f9Robert Phillips return nullptr; 199eee4d6e4e8cc5c4c79f065abcc3ce609f71238f9Robert Phillips } 200eee4d6e4e8cc5c4c79f065abcc3ce609f71238f9Robert Phillips 201eee4d6e4e8cc5c4c79f065abcc3ce609f71238f9Robert Phillips return proxy->priv().peekTexture(); 2020ae6faa34d73ffc7ebec3d13f0473703bade821bRobert Phillips} 2030ae6faa34d73ffc7ebec3d13f0473703bade821bRobert Phillips 20403dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarettbool SkImage_Gpu::onReadPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRB, 205095530389d8211895309107a4f74beefacce638creed int srcX, int srcY, CachingHint) const { 20603dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarett if (!SkImageInfoValidConversion(dstInfo, this->onImageInfo())) { 207cb6266b5aa5bbfd880532f08eec83b0c585e873fMatt Sarett return false; 208cb6266b5aa5bbfd880532f08eec83b0c585e873fMatt Sarett } 209cb6266b5aa5bbfd880532f08eec83b0c585e873fMatt Sarett 21003dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarett SkReadPixelsRec rec(dstInfo, dstPixels, dstRB, srcX, srcY); 21103dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarett if (!rec.trim(this->width(), this->height())) { 21203dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarett return false; 21303dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarett } 21403dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarett 215b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips // TODO: this seems to duplicate code in GrTextureContext::onReadPixels and 216b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips // GrRenderTargetContext::onReadPixels 2178b26b99c97473f020df4b9d4ba789e074e06ceddreed uint32_t flags = 0; 21803dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarett if (kUnpremul_SkAlphaType == rec.fInfo.alphaType() && kPremul_SkAlphaType == fAlphaType) { 2198b26b99c97473f020df4b9d4ba789e074e06ceddreed // let the GPU perform this transformation for us 220e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillips flags = GrContextPriv::kUnpremul_PixelOpsFlag; 2218b26b99c97473f020df4b9d4ba789e074e06ceddreed } 222b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips 223a8ac92418807e3d46a45413459e6895160134c1dBrian Osman // This hack allows us to call makeNonTextureImage on images with arbitrary color spaces. 224a8ac92418807e3d46a45413459e6895160134c1dBrian Osman // Otherwise, we'll be unable to create a render target context. 225a8ac92418807e3d46a45413459e6895160134c1dBrian Osman // TODO: This shouldn't be necessary - we need more robust support for images (and surfaces) 226a8ac92418807e3d46a45413459e6895160134c1dBrian Osman // with arbitrary color spaces. Unfortunately, this is one spot where we go from image to 227a8ac92418807e3d46a45413459e6895160134c1dBrian Osman // surface (rather than the opposite), and our lenient image rules break our (currently) more 228a8ac92418807e3d46a45413459e6895160134c1dBrian Osman // strict surface rules. 229366093f2124c38fa5c590c9ed2d1811817fed8eeBrian Salomon // GrSurfaceContext::readPixels does not make use of the context's color space. However, we 230366093f2124c38fa5c590c9ed2d1811817fed8eeBrian Salomon // don't allow creating a surface context for a sRGB GrPixelConfig unless the color space has 231366093f2124c38fa5c590c9ed2d1811817fed8eeBrian Salomon // sRGB gamma. So we choose null for non-SRGB GrPixelConfigs and sRGB for sRGB GrPixelConfigs. 232a8ac92418807e3d46a45413459e6895160134c1dBrian Osman sk_sp<SkColorSpace> surfaceColorSpace = fColorSpace; 23398e38e2ac5e91eb288eaeceb5b0f36f9b2dd412aMike Klein if (!flags) { 23498e38e2ac5e91eb288eaeceb5b0f36f9b2dd412aMike Klein if (!dstInfo.colorSpace() || 235366093f2124c38fa5c590c9ed2d1811817fed8eeBrian Salomon SkColorSpace::Equals(fColorSpace.get(), dstInfo.colorSpace())) { 236366093f2124c38fa5c590c9ed2d1811817fed8eeBrian Salomon if (GrPixelConfigIsSRGB(fProxy->config())) { 237366093f2124c38fa5c590c9ed2d1811817fed8eeBrian Salomon surfaceColorSpace = SkColorSpace::MakeSRGB(); 238366093f2124c38fa5c590c9ed2d1811817fed8eeBrian Salomon } else { 239366093f2124c38fa5c590c9ed2d1811817fed8eeBrian Salomon surfaceColorSpace = nullptr; 240366093f2124c38fa5c590c9ed2d1811817fed8eeBrian Salomon } 24198e38e2ac5e91eb288eaeceb5b0f36f9b2dd412aMike Klein } 242a8ac92418807e3d46a45413459e6895160134c1dBrian Osman } 243a8ac92418807e3d46a45413459e6895160134c1dBrian Osman 2442084ffa9a3fa7eb3c7e17ec5b55750be9942bafcBrian Salomon sk_sp<GrSurfaceContext> sContext = fContext->contextPriv().makeWrappedSurfaceContext( 245a8ac92418807e3d46a45413459e6895160134c1dBrian Osman fProxy, surfaceColorSpace); 246b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips if (!sContext) { 247b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips return false; 248b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips } 249b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips 250b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips if (!sContext->readPixels(rec.fInfo, rec.fPixels, rec.fRowBytes, rec.fX, rec.fY, flags)) { 2518b26b99c97473f020df4b9d4ba789e074e06ceddreed return false; 2528b26b99c97473f020df4b9d4ba789e074e06ceddreed } 253b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips 2548b26b99c97473f020df4b9d4ba789e074e06ceddreed // do we have to manually fix-up the alpha channel? 2558b26b99c97473f020df4b9d4ba789e074e06ceddreed // src dst 2568b26b99c97473f020df4b9d4ba789e074e06ceddreed // unpremul premul fix manually 2578b26b99c97473f020df4b9d4ba789e074e06ceddreed // premul unpremul done by kUnpremul_PixelOpsFlag 2588b26b99c97473f020df4b9d4ba789e074e06ceddreed // all other combos need to change. 2598b26b99c97473f020df4b9d4ba789e074e06ceddreed // 2608b26b99c97473f020df4b9d4ba789e074e06ceddreed // Should this be handled by Ganesh? todo:? 2618b26b99c97473f020df4b9d4ba789e074e06ceddreed // 26203dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarett if (kPremul_SkAlphaType == rec.fInfo.alphaType() && kUnpremul_SkAlphaType == fAlphaType) { 26303dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarett apply_premul(rec.fInfo, rec.fPixels, rec.fRowBytes); 2648b26b99c97473f020df4b9d4ba789e074e06ceddreed } 2658b26b99c97473f020df4b9d4ba789e074e06ceddreed return true; 2665d4ba8869476831ee73b15a052af8003d0a1fa2ereed@google.com} 2674af267b11964d4a8acdb232ac46094c84d890e88reed 2687fb4f8bd031eda87e1da9bc0f749968c0e872e6freedsk_sp<SkImage> SkImage_Gpu::onMakeSubset(const SkIRect& subset) const { 26963e7973d1f01bd03216659b9d2267f83a752c8fbBrian Salomon GrSurfaceDesc desc; 27016d8ec66cdce2f30ce89b87066d3ac7a244c460dRobert Phillips desc.fOrigin = fProxy->origin(); 2717b6945bc4e639d7cc4a49b84d492690f8e865566reed desc.fWidth = subset.width(); 2727b6945bc4e639d7cc4a49b84d492690f8e865566reed desc.fHeight = subset.height(); 27316d8ec66cdce2f30ce89b87066d3ac7a244c460dRobert Phillips desc.fConfig = fProxy->config(); 2747b6945bc4e639d7cc4a49b84d492690f8e865566reed 275b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips sk_sp<GrSurfaceContext> sContext(fContext->contextPriv().makeDeferredSurfaceContext( 276e2f7d1899d890c2f08571e1bd6c7fa2c5ea1be0bRobert Phillips desc, 27765c7f662ba4ec1c78dc5fc67b184ee9c7b614f55Greg Daniel GrMipMapped::kNo, 278e2f7d1899d890c2f08571e1bd6c7fa2c5ea1be0bRobert Phillips SkBackingFit::kExact, 279e2f7d1899d890c2f08571e1bd6c7fa2c5ea1be0bRobert Phillips fBudgeted)); 280e2f7d1899d890c2f08571e1bd6c7fa2c5ea1be0bRobert Phillips if (!sContext) { 281e2f7d1899d890c2f08571e1bd6c7fa2c5ea1be0bRobert Phillips return nullptr; 282e2f7d1899d890c2f08571e1bd6c7fa2c5ea1be0bRobert Phillips } 283e2f7d1899d890c2f08571e1bd6c7fa2c5ea1be0bRobert Phillips 284b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips if (!sContext->copy(fProxy.get(), subset, SkIPoint::Make(0, 0))) { 285e2f7d1899d890c2f08571e1bd6c7fa2c5ea1be0bRobert Phillips return nullptr; 286e2f7d1899d890c2f08571e1bd6c7fa2c5ea1be0bRobert Phillips } 287e2f7d1899d890c2f08571e1bd6c7fa2c5ea1be0bRobert Phillips 288b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips // MDB: this call is okay bc we know 'sContext' was kExact 289b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips return sk_make_sp<SkImage_Gpu>(fContext, kNeedNewImageUniqueID, 290b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips fAlphaType, sContext->asTextureProxyRef(), 291e2f7d1899d890c2f08571e1bd6c7fa2c5ea1be0bRobert Phillips fColorSpace, fBudgeted); 2927b6945bc4e639d7cc4a49b84d492690f8e865566reed} 2937b6945bc4e639d7cc4a49b84d492690f8e865566reed 2948b26b99c97473f020df4b9d4ba789e074e06ceddreed/////////////////////////////////////////////////////////////////////////////////////////////////// 2958b26b99c97473f020df4b9d4ba789e074e06ceddreed 2967ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Danielstatic sk_sp<SkImage> new_wrapped_texture_common(GrContext* ctx, 2977ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel const GrBackendTexture& backendTex, 2987ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel GrSurfaceOrigin origin, 299dddbe380b0e6b690041a4e020aefe57f1b21691abrianosman SkAlphaType at, sk_sp<SkColorSpace> colorSpace, 300dddbe380b0e6b690041a4e020aefe57f1b21691abrianosman GrWrapOwnership ownership, 3017fb4f8bd031eda87e1da9bc0f749968c0e872e6freed SkImage::TextureReleaseProc releaseProc, 3027fb4f8bd031eda87e1da9bc0f749968c0e872e6freed SkImage::ReleaseContext releaseCtx) { 3037ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel if (backendTex.width() <= 0 || backendTex.height() <= 0) { 30496fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 3058b26b99c97473f020df4b9d4ba789e074e06ceddreed } 3060ae6faa34d73ffc7ebec3d13f0473703bade821bRobert Phillips 307adbe1328789071d1f742023edd93b6948eed9470Robert Phillips GrProxyProvider* proxyProvider = ctx->contextPriv().proxyProvider(); 308adbe1328789071d1f742023edd93b6948eed9470Robert Phillips sk_sp<GrTextureProxy> proxy = proxyProvider->createWrappedTextureProxy( 309adbe1328789071d1f742023edd93b6948eed9470Robert Phillips backendTex, origin, ownership, releaseProc, releaseCtx); 310adbe1328789071d1f742023edd93b6948eed9470Robert Phillips if (!proxy) { 311e201ebc995151adbe0e15cd88d7277d41c40ddbfRobert Phillips return nullptr; 312e201ebc995151adbe0e15cd88d7277d41c40ddbfRobert Phillips } 3130bd24dc41f2351d84f5fce32130668a5792d134bRobert Phillips 3140ae6faa34d73ffc7ebec3d13f0473703bade821bRobert Phillips return sk_make_sp<SkImage_Gpu>(ctx, kNeedNewImageUniqueID, 3150bd24dc41f2351d84f5fce32130668a5792d134bRobert Phillips at, std::move(proxy), std::move(colorSpace), SkBudgeted::kNo); 3166dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon} 3176dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon 3189440345a81d6c2372ac0aed937080f3da67439ddGreg Danielsk_sp<SkImage> SkImage::MakeFromTexture(GrContext* ctx, 3199440345a81d6c2372ac0aed937080f3da67439ddGreg Daniel const GrBackendTexture& tex, GrSurfaceOrigin origin, 3209440345a81d6c2372ac0aed937080f3da67439ddGreg Daniel SkAlphaType at, sk_sp<SkColorSpace> cs, 3219440345a81d6c2372ac0aed937080f3da67439ddGreg Daniel TextureReleaseProc releaseP, ReleaseContext releaseC) { 322faa095e9842b924c20de84dce1bcc1adad7fe2e4Greg Daniel if (!ctx) { 323faa095e9842b924c20de84dce1bcc1adad7fe2e4Greg Daniel return nullptr; 324faa095e9842b924c20de84dce1bcc1adad7fe2e4Greg Daniel } 3257ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel return new_wrapped_texture_common(ctx, tex, origin, at, std::move(cs), kBorrow_GrWrapOwnership, 3267ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel releaseP, releaseC); 3279440345a81d6c2372ac0aed937080f3da67439ddGreg Daniel} 3289440345a81d6c2372ac0aed937080f3da67439ddGreg Daniel 329faa095e9842b924c20de84dce1bcc1adad7fe2e4Greg Danielbool validate_backend_texture(GrContext* ctx, const GrBackendTexture& tex, GrPixelConfig* config, 330f5d8758f29390fd5c135df12bc8a5e196854eda2Greg Daniel SkColorType ct, SkAlphaType at, sk_sp<SkColorSpace> cs) { 331f5d8758f29390fd5c135df12bc8a5e196854eda2Greg Daniel // TODO: Create a SkImageColorInfo struct for color, alpha, and color space so we don't need to 332f5d8758f29390fd5c135df12bc8a5e196854eda2Greg Daniel // create a fake image info here. 333f5d8758f29390fd5c135df12bc8a5e196854eda2Greg Daniel SkImageInfo info = SkImageInfo::Make(1, 1, ct, at, cs); 334f5d8758f29390fd5c135df12bc8a5e196854eda2Greg Daniel if (!SkImageInfoIsValidAllowNumericalCS(info)) { 335f5d8758f29390fd5c135df12bc8a5e196854eda2Greg Daniel return false; 336f5d8758f29390fd5c135df12bc8a5e196854eda2Greg Daniel } 337f5d8758f29390fd5c135df12bc8a5e196854eda2Greg Daniel 338faa095e9842b924c20de84dce1bcc1adad7fe2e4Greg Daniel return ctx->caps()->validateBackendTexture(tex, ct, config); 339f5d8758f29390fd5c135df12bc8a5e196854eda2Greg Daniel} 340f5d8758f29390fd5c135df12bc8a5e196854eda2Greg Daniel 341f5d8758f29390fd5c135df12bc8a5e196854eda2Greg Danielsk_sp<SkImage> SkImage::MakeFromTexture(GrContext* ctx, 342f5d8758f29390fd5c135df12bc8a5e196854eda2Greg Daniel const GrBackendTexture& tex, GrSurfaceOrigin origin, 343f5d8758f29390fd5c135df12bc8a5e196854eda2Greg Daniel SkColorType ct, SkAlphaType at, sk_sp<SkColorSpace> cs, 344f5d8758f29390fd5c135df12bc8a5e196854eda2Greg Daniel TextureReleaseProc releaseP, ReleaseContext releaseC) { 345faa095e9842b924c20de84dce1bcc1adad7fe2e4Greg Daniel if (!ctx) { 346faa095e9842b924c20de84dce1bcc1adad7fe2e4Greg Daniel return nullptr; 347faa095e9842b924c20de84dce1bcc1adad7fe2e4Greg Daniel } 348f5d8758f29390fd5c135df12bc8a5e196854eda2Greg Daniel GrBackendTexture texCopy = tex; 349faa095e9842b924c20de84dce1bcc1adad7fe2e4Greg Daniel if (!validate_backend_texture(ctx, texCopy, &texCopy.fConfig, ct, at, cs)) { 350f5d8758f29390fd5c135df12bc8a5e196854eda2Greg Daniel return nullptr; 351f5d8758f29390fd5c135df12bc8a5e196854eda2Greg Daniel } 352f5d8758f29390fd5c135df12bc8a5e196854eda2Greg Daniel return MakeFromTexture(ctx, texCopy, origin, at, cs, releaseP, releaseC); 353f5d8758f29390fd5c135df12bc8a5e196854eda2Greg Daniel} 354f5d8758f29390fd5c135df12bc8a5e196854eda2Greg Daniel 3559440345a81d6c2372ac0aed937080f3da67439ddGreg Danielsk_sp<SkImage> SkImage::MakeFromAdoptedTexture(GrContext* ctx, 3569440345a81d6c2372ac0aed937080f3da67439ddGreg Daniel const GrBackendTexture& tex, GrSurfaceOrigin origin, 3579440345a81d6c2372ac0aed937080f3da67439ddGreg Daniel SkAlphaType at, sk_sp<SkColorSpace> cs) { 358f2336e4500769bc0ff6a208289d757581b0ea91aGreg Daniel if (!ctx->contextPriv().resourceProvider()) { 359f2336e4500769bc0ff6a208289d757581b0ea91aGreg Daniel // We have a DDL context and we don't support adopted textures for them. 360f2336e4500769bc0ff6a208289d757581b0ea91aGreg Daniel return nullptr; 361f2336e4500769bc0ff6a208289d757581b0ea91aGreg Daniel } 3627ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel return new_wrapped_texture_common(ctx, tex, origin, at, std::move(cs), kAdopt_GrWrapOwnership, 3637ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel nullptr, nullptr); 3647ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel} 3657ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel 366f5d8758f29390fd5c135df12bc8a5e196854eda2Greg Danielsk_sp<SkImage> SkImage::MakeFromAdoptedTexture(GrContext* ctx, 367f5d8758f29390fd5c135df12bc8a5e196854eda2Greg Daniel const GrBackendTexture& tex, GrSurfaceOrigin origin, 368f5d8758f29390fd5c135df12bc8a5e196854eda2Greg Daniel SkColorType ct, SkAlphaType at, 369f5d8758f29390fd5c135df12bc8a5e196854eda2Greg Daniel sk_sp<SkColorSpace> cs) { 370f5d8758f29390fd5c135df12bc8a5e196854eda2Greg Daniel GrBackendTexture texCopy = tex; 371faa095e9842b924c20de84dce1bcc1adad7fe2e4Greg Daniel if (!validate_backend_texture(ctx, texCopy, &texCopy.fConfig, ct, at, cs)) { 372f5d8758f29390fd5c135df12bc8a5e196854eda2Greg Daniel return nullptr; 373f5d8758f29390fd5c135df12bc8a5e196854eda2Greg Daniel } 374f5d8758f29390fd5c135df12bc8a5e196854eda2Greg Daniel return MakeFromAdoptedTexture(ctx, texCopy, origin, at, cs); 375f5d8758f29390fd5c135df12bc8a5e196854eda2Greg Daniel} 376f5d8758f29390fd5c135df12bc8a5e196854eda2Greg Daniel 3777ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Danielstatic GrBackendTexture make_backend_texture_from_handle(GrBackend backend, 3787ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel int width, int height, 3797ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel GrPixelConfig config, 3807ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel GrBackendObject handle) { 3818fe24272fa6d2fa9eb2458221ed9852d6ec16f56Brian Salomon switch (backend) { 3828fe24272fa6d2fa9eb2458221ed9852d6ec16f56Brian Salomon case kOpenGL_GrBackend: { 3838fe24272fa6d2fa9eb2458221ed9852d6ec16f56Brian Salomon const GrGLTextureInfo* glInfo = (const GrGLTextureInfo*)(handle); 3848fe24272fa6d2fa9eb2458221ed9852d6ec16f56Brian Salomon return GrBackendTexture(width, height, config, *glInfo); 3858fe24272fa6d2fa9eb2458221ed9852d6ec16f56Brian Salomon } 386d20b5c489b5709a4d251c0cc68d584ea4514594eMike Reed#ifdef SK_VULKAN 3878fe24272fa6d2fa9eb2458221ed9852d6ec16f56Brian Salomon case kVulkan_GrBackend: { 3888fe24272fa6d2fa9eb2458221ed9852d6ec16f56Brian Salomon const GrVkImageInfo* vkInfo = (const GrVkImageInfo*)(handle); 3898fe24272fa6d2fa9eb2458221ed9852d6ec16f56Brian Salomon return GrBackendTexture(width, height, *vkInfo); 3908fe24272fa6d2fa9eb2458221ed9852d6ec16f56Brian Salomon } 391fcd5fddb0264d062a461435618ad54a29ff80fc0Robert Phillips#endif 3928fe24272fa6d2fa9eb2458221ed9852d6ec16f56Brian Salomon case kMock_GrBackend: { 3938fe24272fa6d2fa9eb2458221ed9852d6ec16f56Brian Salomon const GrMockTextureInfo* mockInfo = (const GrMockTextureInfo*)(handle); 3948fe24272fa6d2fa9eb2458221ed9852d6ec16f56Brian Salomon return GrBackendTexture(width, height, config, *mockInfo); 3958fe24272fa6d2fa9eb2458221ed9852d6ec16f56Brian Salomon } 3968fe24272fa6d2fa9eb2458221ed9852d6ec16f56Brian Salomon default: 3978fe24272fa6d2fa9eb2458221ed9852d6ec16f56Brian Salomon return GrBackendTexture(); 3988fe24272fa6d2fa9eb2458221ed9852d6ec16f56Brian Salomon } 3999440345a81d6c2372ac0aed937080f3da67439ddGreg Daniel} 4009440345a81d6c2372ac0aed937080f3da67439ddGreg Daniel 401c25db637532cd10dde7855d868c0d033e96f61f2Robert Phillipsstatic bool are_yuv_sizes_valid(const SkISize yuvSizes[], bool nv12) { 402c25db637532cd10dde7855d868c0d033e96f61f2Robert Phillips if (yuvSizes[0].fWidth <= 0 || yuvSizes[0].fHeight <= 0 || 403c25db637532cd10dde7855d868c0d033e96f61f2Robert Phillips yuvSizes[1].fWidth <= 0 || yuvSizes[1].fHeight <= 0) { 404c25db637532cd10dde7855d868c0d033e96f61f2Robert Phillips return false; 405c25db637532cd10dde7855d868c0d033e96f61f2Robert Phillips } 406c25db637532cd10dde7855d868c0d033e96f61f2Robert Phillips if (!nv12 && (yuvSizes[2].fWidth <= 0 || yuvSizes[2].fHeight <= 0)) { 407c25db637532cd10dde7855d868c0d033e96f61f2Robert Phillips return false; 408c25db637532cd10dde7855d868c0d033e96f61f2Robert Phillips } 409c25db637532cd10dde7855d868c0d033e96f61f2Robert Phillips 410c25db637532cd10dde7855d868c0d033e96f61f2Robert Phillips return true; 411c25db637532cd10dde7855d868c0d033e96f61f2Robert Phillips} 412c25db637532cd10dde7855d868c0d033e96f61f2Robert Phillips 413b445a57e6c36cce86580b618701b5af708a6f271jbaumanstatic sk_sp<SkImage> make_from_yuv_textures_copy(GrContext* ctx, SkYUVColorSpace colorSpace, 414b445a57e6c36cce86580b618701b5af708a6f271jbauman bool nv12, 415c25db637532cd10dde7855d868c0d033e96f61f2Robert Phillips const GrBackendTexture yuvBackendTextures[], 416b445a57e6c36cce86580b618701b5af708a6f271jbauman const SkISize yuvSizes[], 417dddbe380b0e6b690041a4e020aefe57f1b21691abrianosman GrSurfaceOrigin origin, 418dddbe380b0e6b690041a4e020aefe57f1b21691abrianosman sk_sp<SkColorSpace> imageColorSpace) { 4190bd24dc41f2351d84f5fce32130668a5792d134bRobert Phillips GrProxyProvider* proxyProvider = ctx->contextPriv().proxyProvider(); 4200bd24dc41f2351d84f5fce32130668a5792d134bRobert Phillips 421c25db637532cd10dde7855d868c0d033e96f61f2Robert Phillips if (!are_yuv_sizes_valid(yuvSizes, nv12)) { 42296fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 423993a4216a6014b9de8f4d8120360c94550dc6761bsalomon } 424b445a57e6c36cce86580b618701b5af708a6f271jbauman 4250bd24dc41f2351d84f5fce32130668a5792d134bRobert Phillips sk_sp<GrTextureProxy> yProxy = proxyProvider->createWrappedTextureProxy(yuvBackendTextures[0], 4260bd24dc41f2351d84f5fce32130668a5792d134bRobert Phillips origin); 4270bd24dc41f2351d84f5fce32130668a5792d134bRobert Phillips sk_sp<GrTextureProxy> uProxy = proxyProvider->createWrappedTextureProxy(yuvBackendTextures[1], 4280bd24dc41f2351d84f5fce32130668a5792d134bRobert Phillips origin); 4297ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel sk_sp<GrTextureProxy> vProxy; 430bc7a4fb06780f9829b4b21470fe6f0503d2297cdRobert Phillips 431b445a57e6c36cce86580b618701b5af708a6f271jbauman if (nv12) { 432bc7a4fb06780f9829b4b21470fe6f0503d2297cdRobert Phillips vProxy = uProxy; 433b445a57e6c36cce86580b618701b5af708a6f271jbauman } else { 4340bd24dc41f2351d84f5fce32130668a5792d134bRobert Phillips vProxy = proxyProvider->createWrappedTextureProxy(yuvBackendTextures[2], origin); 435b445a57e6c36cce86580b618701b5af708a6f271jbauman } 436bc7a4fb06780f9829b4b21470fe6f0503d2297cdRobert Phillips if (!yProxy || !uProxy || !vProxy) { 43796fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 438993a4216a6014b9de8f4d8120360c94550dc6761bsalomon } 439993a4216a6014b9de8f4d8120360c94550dc6761bsalomon 440d4c741e3d0e0fa633399691c47f76b6c7841ee83robertphillips const int width = yuvSizes[0].fWidth; 441d4c741e3d0e0fa633399691c47f76b6c7841ee83robertphillips const int height = yuvSizes[0].fHeight; 442d4c741e3d0e0fa633399691c47f76b6c7841ee83robertphillips 443993a4216a6014b9de8f4d8120360c94550dc6761bsalomon // Needs to be a render target in order to draw to it for the yuv->rgb conversion. 444dd3b3f41829d32d7eaf3eb4903570d49c2ba9ff8Robert Phillips sk_sp<GrRenderTargetContext> renderTargetContext(ctx->makeDeferredRenderTargetContext( 445bdecacfbe47bc7211336bb847bb33c00ef85ea3eBrian Salomon SkBackingFit::kExact, width, height, kRGBA_8888_GrPixelConfig, 446bdecacfbe47bc7211336bb847bb33c00ef85ea3eBrian Salomon std::move(imageColorSpace), 1, GrMipMapped::kNo, origin)); 4471105224f9701e57ec5ce0354d6a380b664f5c638Brian Osman if (!renderTargetContext) { 44896fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 449993a4216a6014b9de8f4d8120360c94550dc6761bsalomon } 450993a4216a6014b9de8f4d8120360c94550dc6761bsalomon 451993a4216a6014b9de8f4d8120360c94550dc6761bsalomon GrPaint paint; 4527d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed paint.setPorterDuffXPFactory(SkBlendMode::kSrc); 4537461a4abe06ffdfbb62a479a71b14895a637bba9Ethan Nicholas paint.addColorFragmentProcessor(GrYUVtoRGBEffect::Make(yProxy, uProxy, vProxy, 4547461a4abe06ffdfbb62a479a71b14895a637bba9Ethan Nicholas yuvSizes, colorSpace, nv12)); 455993a4216a6014b9de8f4d8120360c94550dc6761bsalomon 456b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips const SkRect rect = SkRect::MakeIWH(width, height); 457c9a3706f1ee38c331610ec1e872d9a658566c397robertphillips 45882f44319159bb98dcacdbbec7ea643dde5ed024bBrian Salomon renderTargetContext->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(), rect); 459e60ad620fe236ce4c1e85a31bd53ed0c848da8c3Robert Phillips 4607ee385e1dc3cd6a47dc8f7297fef6e175eaba224Robert Phillips if (!renderTargetContext->asSurfaceProxy()) { 461e60ad620fe236ce4c1e85a31bd53ed0c848da8c3Robert Phillips return nullptr; 462e60ad620fe236ce4c1e85a31bd53ed0c848da8c3Robert Phillips } 4637ee385e1dc3cd6a47dc8f7297fef6e175eaba224Robert Phillips ctx->contextPriv().flushSurfaceWrites(renderTargetContext->asSurfaceProxy()); 464b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips 465b726d58efc91c4eefa5cea0881a823ee108db8fdRobert Phillips // MDB: this call is okay bc we know 'renderTargetContext' was exact 466f3569f0f6d312570c7344b345f8b3a03a892f751Brian Salomon return sk_make_sp<SkImage_Gpu>(ctx, kNeedNewImageUniqueID, kOpaque_SkAlphaType, 467f3569f0f6d312570c7344b345f8b3a03a892f751Brian Salomon renderTargetContext->asTextureProxyRef(), 468c25db637532cd10dde7855d868c0d033e96f61f2Robert Phillips renderTargetContext->colorSpaceInfo().refColorSpace(), 469c25db637532cd10dde7855d868c0d033e96f61f2Robert Phillips SkBudgeted::kYes); 470c25db637532cd10dde7855d868c0d033e96f61f2Robert Phillips} 471c25db637532cd10dde7855d868c0d033e96f61f2Robert Phillips 472c25db637532cd10dde7855d868c0d033e96f61f2Robert Phillipsstatic sk_sp<SkImage> make_from_yuv_objects_copy(GrContext* ctx, SkYUVColorSpace colorSpace, 473c25db637532cd10dde7855d868c0d033e96f61f2Robert Phillips bool nv12, 474c25db637532cd10dde7855d868c0d033e96f61f2Robert Phillips const GrBackendObject yuvTextureHandles[], 475c25db637532cd10dde7855d868c0d033e96f61f2Robert Phillips const SkISize yuvSizes[], 476c25db637532cd10dde7855d868c0d033e96f61f2Robert Phillips GrSurfaceOrigin origin, 477c25db637532cd10dde7855d868c0d033e96f61f2Robert Phillips sk_sp<SkColorSpace> imageColorSpace) { 478c25db637532cd10dde7855d868c0d033e96f61f2Robert Phillips if (!are_yuv_sizes_valid(yuvSizes, nv12)) { 479c25db637532cd10dde7855d868c0d033e96f61f2Robert Phillips return nullptr; 480c25db637532cd10dde7855d868c0d033e96f61f2Robert Phillips } 481c25db637532cd10dde7855d868c0d033e96f61f2Robert Phillips 482c25db637532cd10dde7855d868c0d033e96f61f2Robert Phillips GrBackendTexture backendTextures[3]; 483c25db637532cd10dde7855d868c0d033e96f61f2Robert Phillips 484c25db637532cd10dde7855d868c0d033e96f61f2Robert Phillips const GrPixelConfig kConfig = nv12 ? kRGBA_8888_GrPixelConfig : kAlpha_8_GrPixelConfig; 485c25db637532cd10dde7855d868c0d033e96f61f2Robert Phillips 486c25db637532cd10dde7855d868c0d033e96f61f2Robert Phillips GrBackend backend = ctx->contextPriv().getBackend(); 487c25db637532cd10dde7855d868c0d033e96f61f2Robert Phillips backendTextures[0] = make_backend_texture_from_handle(backend, 488c25db637532cd10dde7855d868c0d033e96f61f2Robert Phillips yuvSizes[0].fWidth, 489c25db637532cd10dde7855d868c0d033e96f61f2Robert Phillips yuvSizes[0].fHeight, 490c25db637532cd10dde7855d868c0d033e96f61f2Robert Phillips kConfig, 491c25db637532cd10dde7855d868c0d033e96f61f2Robert Phillips yuvTextureHandles[0]); 492c25db637532cd10dde7855d868c0d033e96f61f2Robert Phillips backendTextures[1] = make_backend_texture_from_handle(backend, 493c25db637532cd10dde7855d868c0d033e96f61f2Robert Phillips yuvSizes[1].fWidth, 494c25db637532cd10dde7855d868c0d033e96f61f2Robert Phillips yuvSizes[1].fHeight, 495c25db637532cd10dde7855d868c0d033e96f61f2Robert Phillips kConfig, 496c25db637532cd10dde7855d868c0d033e96f61f2Robert Phillips yuvTextureHandles[1]); 497c25db637532cd10dde7855d868c0d033e96f61f2Robert Phillips 498c25db637532cd10dde7855d868c0d033e96f61f2Robert Phillips if (!nv12) { 499c25db637532cd10dde7855d868c0d033e96f61f2Robert Phillips backendTextures[2] = make_backend_texture_from_handle(backend, 500c25db637532cd10dde7855d868c0d033e96f61f2Robert Phillips yuvSizes[2].fWidth, 501c25db637532cd10dde7855d868c0d033e96f61f2Robert Phillips yuvSizes[2].fHeight, 502c25db637532cd10dde7855d868c0d033e96f61f2Robert Phillips kConfig, 503c25db637532cd10dde7855d868c0d033e96f61f2Robert Phillips yuvTextureHandles[2]); 504c25db637532cd10dde7855d868c0d033e96f61f2Robert Phillips } 505c25db637532cd10dde7855d868c0d033e96f61f2Robert Phillips 506c25db637532cd10dde7855d868c0d033e96f61f2Robert Phillips return make_from_yuv_textures_copy(ctx, colorSpace, nv12, 507c25db637532cd10dde7855d868c0d033e96f61f2Robert Phillips backendTextures, yuvSizes, origin, 508c25db637532cd10dde7855d868c0d033e96f61f2Robert Phillips std::move(imageColorSpace)); 509993a4216a6014b9de8f4d8120360c94550dc6761bsalomon} 5105617900063f69754de62b8b12d32f6e36df14104reed 511b445a57e6c36cce86580b618701b5af708a6f271jbaumansk_sp<SkImage> SkImage::MakeFromYUVTexturesCopy(GrContext* ctx, SkYUVColorSpace colorSpace, 512b445a57e6c36cce86580b618701b5af708a6f271jbauman const GrBackendObject yuvTextureHandles[3], 513dddbe380b0e6b690041a4e020aefe57f1b21691abrianosman const SkISize yuvSizes[3], GrSurfaceOrigin origin, 514dddbe380b0e6b690041a4e020aefe57f1b21691abrianosman sk_sp<SkColorSpace> imageColorSpace) { 515c25db637532cd10dde7855d868c0d033e96f61f2Robert Phillips return make_from_yuv_objects_copy(ctx, colorSpace, false, yuvTextureHandles, yuvSizes, origin, 516c25db637532cd10dde7855d868c0d033e96f61f2Robert Phillips std::move(imageColorSpace)); 517b445a57e6c36cce86580b618701b5af708a6f271jbauman} 518b445a57e6c36cce86580b618701b5af708a6f271jbauman 519b445a57e6c36cce86580b618701b5af708a6f271jbaumansk_sp<SkImage> SkImage::MakeFromNV12TexturesCopy(GrContext* ctx, SkYUVColorSpace colorSpace, 520b445a57e6c36cce86580b618701b5af708a6f271jbauman const GrBackendObject yuvTextureHandles[2], 521b445a57e6c36cce86580b618701b5af708a6f271jbauman const SkISize yuvSizes[2], 522dddbe380b0e6b690041a4e020aefe57f1b21691abrianosman GrSurfaceOrigin origin, 523dddbe380b0e6b690041a4e020aefe57f1b21691abrianosman sk_sp<SkColorSpace> imageColorSpace) { 524c25db637532cd10dde7855d868c0d033e96f61f2Robert Phillips return make_from_yuv_objects_copy(ctx, colorSpace, true, yuvTextureHandles, yuvSizes, origin, 525c25db637532cd10dde7855d868c0d033e96f61f2Robert Phillips std::move(imageColorSpace)); 526c25db637532cd10dde7855d868c0d033e96f61f2Robert Phillips} 527c25db637532cd10dde7855d868c0d033e96f61f2Robert Phillips 528c25db637532cd10dde7855d868c0d033e96f61f2Robert Phillipssk_sp<SkImage> SkImage::MakeFromYUVTexturesCopy(GrContext* ctx, SkYUVColorSpace colorSpace, 529c25db637532cd10dde7855d868c0d033e96f61f2Robert Phillips const GrBackendTexture yuvBackendTextures[3], 530c25db637532cd10dde7855d868c0d033e96f61f2Robert Phillips const SkISize yuvSizes[3], GrSurfaceOrigin origin, 531c25db637532cd10dde7855d868c0d033e96f61f2Robert Phillips sk_sp<SkColorSpace> imageColorSpace) { 532c25db637532cd10dde7855d868c0d033e96f61f2Robert Phillips return make_from_yuv_textures_copy(ctx, colorSpace, false, yuvBackendTextures, yuvSizes, origin, 533c25db637532cd10dde7855d868c0d033e96f61f2Robert Phillips std::move(imageColorSpace)); 534c25db637532cd10dde7855d868c0d033e96f61f2Robert Phillips} 535c25db637532cd10dde7855d868c0d033e96f61f2Robert Phillips 536c25db637532cd10dde7855d868c0d033e96f61f2Robert Phillipssk_sp<SkImage> SkImage::MakeFromNV12TexturesCopy(GrContext* ctx, SkYUVColorSpace colorSpace, 537c25db637532cd10dde7855d868c0d033e96f61f2Robert Phillips const GrBackendTexture yuvBackendTextures[2], 538c25db637532cd10dde7855d868c0d033e96f61f2Robert Phillips const SkISize yuvSizes[2], 539c25db637532cd10dde7855d868c0d033e96f61f2Robert Phillips GrSurfaceOrigin origin, 540c25db637532cd10dde7855d868c0d033e96f61f2Robert Phillips sk_sp<SkColorSpace> imageColorSpace) { 541c25db637532cd10dde7855d868c0d033e96f61f2Robert Phillips return make_from_yuv_textures_copy(ctx, colorSpace, true, yuvBackendTextures, yuvSizes, origin, 542dddbe380b0e6b690041a4e020aefe57f1b21691abrianosman std::move(imageColorSpace)); 543b445a57e6c36cce86580b618701b5af708a6f271jbauman} 544b445a57e6c36cce86580b618701b5af708a6f271jbauman 5453798c86f6885f0b47fb2e659a43b48a4468a97efRobert Phillipsstatic sk_sp<SkImage> create_image_from_maker(GrContext* context, GrTextureMaker* maker, 5463798c86f6885f0b47fb2e659a43b48a4468a97efRobert Phillips SkAlphaType at, uint32_t id, 547041f7dfc577822f1e97721a865f86a9a02660cf9Brian Osman SkColorSpace* dstColorSpace) { 548041f7dfc577822f1e97721a865f86a9a02660cf9Brian Osman sk_sp<SkColorSpace> texColorSpace; 5492bbdcc44c63974f29f3743bb58d929601a3f65c6Brian Salomon sk_sp<GrTextureProxy> proxy(maker->refTextureProxyForParams( 5502bbdcc44c63974f29f3743bb58d929601a3f65c6Brian Salomon GrSamplerState::ClampNearest(), dstColorSpace, &texColorSpace, nullptr)); 5513798c86f6885f0b47fb2e659a43b48a4468a97efRobert Phillips if (!proxy) { 552041f7dfc577822f1e97721a865f86a9a02660cf9Brian Osman return nullptr; 553041f7dfc577822f1e97721a865f86a9a02660cf9Brian Osman } 5543798c86f6885f0b47fb2e659a43b48a4468a97efRobert Phillips return sk_make_sp<SkImage_Gpu>(context, id, at, 5553798c86f6885f0b47fb2e659a43b48a4468a97efRobert Phillips std::move(proxy), std::move(texColorSpace), SkBudgeted::kNo); 556041f7dfc577822f1e97721a865f86a9a02660cf9Brian Osman} 557041f7dfc577822f1e97721a865f86a9a02660cf9Brian Osman 5582c2bc11aea4dfcd7ee2f5859838a2aa0a56939e0Brian Osmansk_sp<SkImage> SkImage::makeTextureImage(GrContext* context, SkColorSpace* dstColorSpace) const { 559041f7dfc577822f1e97721a865f86a9a02660cf9Brian Osman if (!context) { 560041f7dfc577822f1e97721a865f86a9a02660cf9Brian Osman return nullptr; 561041f7dfc577822f1e97721a865f86a9a02660cf9Brian Osman } 5628744405448b9402e1368aebd321c4f555543301aRobert Phillips if (GrContext* incumbent = as_IB(this)->context()) { 5638744405448b9402e1368aebd321c4f555543301aRobert Phillips return incumbent == context ? sk_ref_sp(const_cast<SkImage*>(this)) : nullptr; 564041f7dfc577822f1e97721a865f86a9a02660cf9Brian Osman } 565041f7dfc577822f1e97721a865f86a9a02660cf9Brian Osman 566df7e075c74110fcfebdc49ca503684162e118af5Brian Osman if (this->isLazyGenerated()) { 567df7e075c74110fcfebdc49ca503684162e118af5Brian Osman GrImageTextureMaker maker(context, this, kDisallow_CachingHint); 5680ae6faa34d73ffc7ebec3d13f0473703bade821bRobert Phillips return create_image_from_maker(context, &maker, this->alphaType(), 5690ae6faa34d73ffc7ebec3d13f0473703bade821bRobert Phillips this->uniqueID(), dstColorSpace); 570041f7dfc577822f1e97721a865f86a9a02660cf9Brian Osman } 571041f7dfc577822f1e97721a865f86a9a02660cf9Brian Osman 572041f7dfc577822f1e97721a865f86a9a02660cf9Brian Osman if (const SkBitmap* bmp = as_IB(this)->onPeekBitmap()) { 573041f7dfc577822f1e97721a865f86a9a02660cf9Brian Osman GrBitmapTextureMaker maker(context, *bmp); 5740ae6faa34d73ffc7ebec3d13f0473703bade821bRobert Phillips return create_image_from_maker(context, &maker, this->alphaType(), 5750ae6faa34d73ffc7ebec3d13f0473703bade821bRobert Phillips this->uniqueID(), dstColorSpace); 576041f7dfc577822f1e97721a865f86a9a02660cf9Brian Osman } 577041f7dfc577822f1e97721a865f86a9a02660cf9Brian Osman return nullptr; 578041f7dfc577822f1e97721a865f86a9a02660cf9Brian Osman} 579041f7dfc577822f1e97721a865f86a9a02660cf9Brian Osman 58013dddce65fd87a8175a209a49f35615735a2886aBrian Osmansk_sp<SkImage> SkImage::MakeCrossContextFromEncoded(GrContext* context, sk_sp<SkData> encoded, 58113dddce65fd87a8175a209a49f35615735a2886aBrian Osman bool buildMips, SkColorSpace* dstColorSpace) { 58213dddce65fd87a8175a209a49f35615735a2886aBrian Osman sk_sp<SkImage> codecImage = SkImage::MakeFromEncoded(std::move(encoded)); 58313dddce65fd87a8175a209a49f35615735a2886aBrian Osman if (!codecImage) { 58413dddce65fd87a8175a209a49f35615735a2886aBrian Osman return nullptr; 58513dddce65fd87a8175a209a49f35615735a2886aBrian Osman } 58613dddce65fd87a8175a209a49f35615735a2886aBrian Osman 58713dddce65fd87a8175a209a49f35615735a2886aBrian Osman // Some backends or drivers don't support (safely) moving resources between contexts 58813dddce65fd87a8175a209a49f35615735a2886aBrian Osman if (!context || !context->caps()->crossContextTextureSupport()) { 58913dddce65fd87a8175a209a49f35615735a2886aBrian Osman return codecImage; 59013dddce65fd87a8175a209a49f35615735a2886aBrian Osman } 59113dddce65fd87a8175a209a49f35615735a2886aBrian Osman 59213dddce65fd87a8175a209a49f35615735a2886aBrian Osman // Turn the codec image into a GrTextureProxy 59313dddce65fd87a8175a209a49f35615735a2886aBrian Osman GrImageTextureMaker maker(context, codecImage.get(), kDisallow_CachingHint); 59413dddce65fd87a8175a209a49f35615735a2886aBrian Osman sk_sp<SkColorSpace> texColorSpace; 5952bbdcc44c63974f29f3743bb58d929601a3f65c6Brian Salomon GrSamplerState samplerState( 5962bbdcc44c63974f29f3743bb58d929601a3f65c6Brian Salomon GrSamplerState::WrapMode::kClamp, 5972bbdcc44c63974f29f3743bb58d929601a3f65c6Brian Salomon buildMips ? GrSamplerState::Filter::kMipMap : GrSamplerState::Filter::kBilerp); 5982bbdcc44c63974f29f3743bb58d929601a3f65c6Brian Salomon sk_sp<GrTextureProxy> proxy( 5992bbdcc44c63974f29f3743bb58d929601a3f65c6Brian Salomon maker.refTextureProxyForParams(samplerState, dstColorSpace, &texColorSpace, nullptr)); 60013dddce65fd87a8175a209a49f35615735a2886aBrian Osman if (!proxy) { 60113dddce65fd87a8175a209a49f35615735a2886aBrian Osman return codecImage; 60213dddce65fd87a8175a209a49f35615735a2886aBrian Osman } 60313dddce65fd87a8175a209a49f35615735a2886aBrian Osman 6046be756b673b823881e90a2ef68c12b640ddde549Robert Phillips if (!proxy->instantiate(context->contextPriv().resourceProvider())) { 60513dddce65fd87a8175a209a49f35615735a2886aBrian Osman return codecImage; 60613dddce65fd87a8175a209a49f35615735a2886aBrian Osman } 607eee4d6e4e8cc5c4c79f065abcc3ce609f71238f9Robert Phillips sk_sp<GrTexture> texture = sk_ref_sp(proxy->priv().peekTexture()); 60813dddce65fd87a8175a209a49f35615735a2886aBrian Osman 60913dddce65fd87a8175a209a49f35615735a2886aBrian Osman // Flush any writes or uploads 61013dddce65fd87a8175a209a49f35615735a2886aBrian Osman context->contextPriv().prepareSurfaceForExternalIO(proxy.get()); 61113dddce65fd87a8175a209a49f35615735a2886aBrian Osman 612f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips GrGpu* gpu = context->contextPriv().getGpu(); 613f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips sk_sp<GrSemaphore> sema = gpu->prepareTextureForCrossContextUsage(texture.get()); 61413dddce65fd87a8175a209a49f35615735a2886aBrian Osman 615b0e93a22bbfad05bb834e33387880ece56e0f6d2Robert Phillips auto gen = GrBackendTextureImageGenerator::Make(std::move(texture), proxy->origin(), 61616d8ec66cdce2f30ce89b87066d3ac7a244c460dRobert Phillips std::move(sema), codecImage->alphaType(), 61713dddce65fd87a8175a209a49f35615735a2886aBrian Osman std::move(texColorSpace)); 61813dddce65fd87a8175a209a49f35615735a2886aBrian Osman return SkImage::MakeFromGenerator(std::move(gen)); 61913dddce65fd87a8175a209a49f35615735a2886aBrian Osman} 62013dddce65fd87a8175a209a49f35615735a2886aBrian Osman 62163bc48d09323a62c8c67237fc66ad6ec7105e973Brian Osmansk_sp<SkImage> SkImage::MakeCrossContextFromPixmap(GrContext* context, const SkPixmap& pixmap, 62263bc48d09323a62c8c67237fc66ad6ec7105e973Brian Osman bool buildMips, SkColorSpace* dstColorSpace) { 62363bc48d09323a62c8c67237fc66ad6ec7105e973Brian Osman // Some backends or drivers don't support (safely) moving resources between contexts 62463bc48d09323a62c8c67237fc66ad6ec7105e973Brian Osman if (!context || !context->caps()->crossContextTextureSupport()) { 62563bc48d09323a62c8c67237fc66ad6ec7105e973Brian Osman return SkImage::MakeRasterCopy(pixmap); 62663bc48d09323a62c8c67237fc66ad6ec7105e973Brian Osman } 62763bc48d09323a62c8c67237fc66ad6ec7105e973Brian Osman 6289e788116c17406ed655127770148de6f33e262c7Greg Daniel // If we don't have access to the resource provider and gpu (i.e. in a DDL context) we will not 6299e788116c17406ed655127770148de6f33e262c7Greg Daniel // be able to make everything needed for a GPU CrossContext image. Thus return a raster copy 6309e788116c17406ed655127770148de6f33e262c7Greg Daniel // instead. 6319e788116c17406ed655127770148de6f33e262c7Greg Daniel if (!context->contextPriv().resourceProvider()) { 6329e788116c17406ed655127770148de6f33e262c7Greg Daniel return SkImage::MakeRasterCopy(pixmap); 6339e788116c17406ed655127770148de6f33e262c7Greg Daniel } 6349e788116c17406ed655127770148de6f33e262c7Greg Daniel 6350bd24dc41f2351d84f5fce32130668a5792d134bRobert Phillips GrProxyProvider* proxyProvider = context->contextPriv().proxyProvider(); 63663bc48d09323a62c8c67237fc66ad6ec7105e973Brian Osman // Turn the pixmap into a GrTextureProxy 63763bc48d09323a62c8c67237fc66ad6ec7105e973Brian Osman sk_sp<GrTextureProxy> proxy; 63863bc48d09323a62c8c67237fc66ad6ec7105e973Brian Osman if (buildMips) { 63963bc48d09323a62c8c67237fc66ad6ec7105e973Brian Osman SkBitmap bmp; 64063bc48d09323a62c8c67237fc66ad6ec7105e973Brian Osman bmp.installPixels(pixmap); 641a4ead65e2c80b6e649f31e28e8fa116aca83fad4Greg Daniel proxy = proxyProvider->createMipMapProxyFromBitmap(bmp, dstColorSpace); 64263bc48d09323a62c8c67237fc66ad6ec7105e973Brian Osman } else { 643bc54fadf610b8d17165735d55de431a47fde9349Greg Daniel SkDestinationSurfaceColorMode colorMode = dstColorSpace 644bc54fadf610b8d17165735d55de431a47fde9349Greg Daniel ? SkDestinationSurfaceColorMode::kGammaAndColorSpaceAware 645bc54fadf610b8d17165735d55de431a47fde9349Greg Daniel : SkDestinationSurfaceColorMode::kLegacy; 646bc54fadf610b8d17165735d55de431a47fde9349Greg Daniel 647bc54fadf610b8d17165735d55de431a47fde9349Greg Daniel if (SkImageInfoIsValid(pixmap.info(), colorMode)) { 648bc54fadf610b8d17165735d55de431a47fde9349Greg Daniel ATRACE_ANDROID_FRAMEWORK("Upload Texture [%ux%u]", pixmap.width(), pixmap.height()); 649bc54fadf610b8d17165735d55de431a47fde9349Greg Daniel GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(pixmap.info(), *proxyProvider->caps()); 650bc54fadf610b8d17165735d55de431a47fde9349Greg Daniel proxy = proxyProvider->createTextureProxy(desc, SkBudgeted::kYes, pixmap.addr(), 651bc54fadf610b8d17165735d55de431a47fde9349Greg Daniel pixmap.rowBytes()); 652bc54fadf610b8d17165735d55de431a47fde9349Greg Daniel } 65363bc48d09323a62c8c67237fc66ad6ec7105e973Brian Osman } 65463bc48d09323a62c8c67237fc66ad6ec7105e973Brian Osman 65563bc48d09323a62c8c67237fc66ad6ec7105e973Brian Osman if (!proxy) { 65663bc48d09323a62c8c67237fc66ad6ec7105e973Brian Osman return SkImage::MakeRasterCopy(pixmap); 65763bc48d09323a62c8c67237fc66ad6ec7105e973Brian Osman } 65863bc48d09323a62c8c67237fc66ad6ec7105e973Brian Osman 65963bc48d09323a62c8c67237fc66ad6ec7105e973Brian Osman sk_sp<GrTexture> texture = sk_ref_sp(proxy->priv().peekTexture()); 66063bc48d09323a62c8c67237fc66ad6ec7105e973Brian Osman 66163bc48d09323a62c8c67237fc66ad6ec7105e973Brian Osman // Flush any writes or uploads 66263bc48d09323a62c8c67237fc66ad6ec7105e973Brian Osman context->contextPriv().prepareSurfaceForExternalIO(proxy.get()); 663f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips GrGpu* gpu = context->contextPriv().getGpu(); 66463bc48d09323a62c8c67237fc66ad6ec7105e973Brian Osman 665f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips sk_sp<GrSemaphore> sema = gpu->prepareTextureForCrossContextUsage(texture.get()); 66663bc48d09323a62c8c67237fc66ad6ec7105e973Brian Osman 66763bc48d09323a62c8c67237fc66ad6ec7105e973Brian Osman auto gen = GrBackendTextureImageGenerator::Make(std::move(texture), proxy->origin(), 66863bc48d09323a62c8c67237fc66ad6ec7105e973Brian Osman std::move(sema), pixmap.alphaType(), 66963bc48d09323a62c8c67237fc66ad6ec7105e973Brian Osman pixmap.info().refColorSpace()); 67063bc48d09323a62c8c67237fc66ad6ec7105e973Brian Osman return SkImage::MakeFromGenerator(std::move(gen)); 67163bc48d09323a62c8c67237fc66ad6ec7105e973Brian Osman} 67263bc48d09323a62c8c67237fc66ad6ec7105e973Brian Osman 6737a86987815be3af78fe3801d4f347ebb0c63141aDerek Sollenberger#if defined(SK_BUILD_FOR_ANDROID) && __ANDROID_API__ >= 26 6747e910df7f133e80293117bdd069ed25998d10f8cStan Ilievsk_sp<SkImage> SkImage::MakeFromAHardwareBuffer(AHardwareBuffer* graphicBuffer, SkAlphaType at, 6757e910df7f133e80293117bdd069ed25998d10f8cStan Iliev sk_sp<SkColorSpace> cs) { 6767e910df7f133e80293117bdd069ed25998d10f8cStan Iliev auto gen = GrAHardwareBufferImageGenerator::Make(graphicBuffer, at, cs); 6777e910df7f133e80293117bdd069ed25998d10f8cStan Iliev return SkImage::MakeFromGenerator(std::move(gen)); 6787e910df7f133e80293117bdd069ed25998d10f8cStan Iliev} 6797e910df7f133e80293117bdd069ed25998d10f8cStan Iliev#endif 6807e910df7f133e80293117bdd069ed25998d10f8cStan Iliev 6815617900063f69754de62b8b12d32f6e36df14104reed/////////////////////////////////////////////////////////////////////////////////////////////////// 6825617900063f69754de62b8b12d32f6e36df14104reed 683914a36b248ffb538874483d86759254838866dd7Eric Karlbool SkImage::MakeBackendTextureFromSkImage(GrContext* ctx, 684914a36b248ffb538874483d86759254838866dd7Eric Karl sk_sp<SkImage> image, 685914a36b248ffb538874483d86759254838866dd7Eric Karl GrBackendTexture* backendTexture, 686914a36b248ffb538874483d86759254838866dd7Eric Karl BackendTextureReleaseProc* releaseProc) { 687914a36b248ffb538874483d86759254838866dd7Eric Karl if (!image || !ctx || !backendTexture || !releaseProc) { 688914a36b248ffb538874483d86759254838866dd7Eric Karl return false; 689914a36b248ffb538874483d86759254838866dd7Eric Karl } 690914a36b248ffb538874483d86759254838866dd7Eric Karl 691914a36b248ffb538874483d86759254838866dd7Eric Karl // Ensure we have a texture backed image. 692914a36b248ffb538874483d86759254838866dd7Eric Karl if (!image->isTextureBacked()) { 693914a36b248ffb538874483d86759254838866dd7Eric Karl image = image->makeTextureImage(ctx, nullptr); 694914a36b248ffb538874483d86759254838866dd7Eric Karl if (!image) { 695914a36b248ffb538874483d86759254838866dd7Eric Karl return false; 696914a36b248ffb538874483d86759254838866dd7Eric Karl } 697914a36b248ffb538874483d86759254838866dd7Eric Karl } 698914a36b248ffb538874483d86759254838866dd7Eric Karl GrTexture* texture = image->getTexture(); 69936591e5ffe263fcab5c43456d7328da2bf9addb1Eric Karl if (!texture) { 70036591e5ffe263fcab5c43456d7328da2bf9addb1Eric Karl // In context-loss cases, we may not have a texture. 70136591e5ffe263fcab5c43456d7328da2bf9addb1Eric Karl return false; 70236591e5ffe263fcab5c43456d7328da2bf9addb1Eric Karl } 703914a36b248ffb538874483d86759254838866dd7Eric Karl 704914a36b248ffb538874483d86759254838866dd7Eric Karl // If the image's context doesn't match the provided context, fail. 705914a36b248ffb538874483d86759254838866dd7Eric Karl if (texture->getContext() != ctx) { 706914a36b248ffb538874483d86759254838866dd7Eric Karl return false; 707914a36b248ffb538874483d86759254838866dd7Eric Karl } 708914a36b248ffb538874483d86759254838866dd7Eric Karl 709914a36b248ffb538874483d86759254838866dd7Eric Karl // Flush any pending IO on the texture. 710914a36b248ffb538874483d86759254838866dd7Eric Karl ctx->contextPriv().prepareSurfaceForExternalIO(as_IB(image)->peekProxy()); 711914a36b248ffb538874483d86759254838866dd7Eric Karl SkASSERT(!texture->surfacePriv().hasPendingIO()); 712914a36b248ffb538874483d86759254838866dd7Eric Karl 713914a36b248ffb538874483d86759254838866dd7Eric Karl // We must make a copy of the image if the image is not unique, if the GrTexture owned by the 714914a36b248ffb538874483d86759254838866dd7Eric Karl // image is not unique, or if the texture wraps an external object. 715914a36b248ffb538874483d86759254838866dd7Eric Karl if (!image->unique() || !texture->surfacePriv().hasUniqueRef() || 716914a36b248ffb538874483d86759254838866dd7Eric Karl texture->resourcePriv().refsWrappedObjects()) { 717914a36b248ffb538874483d86759254838866dd7Eric Karl // onMakeSubset will always copy the image. 718914a36b248ffb538874483d86759254838866dd7Eric Karl image = as_IB(image)->onMakeSubset(image->bounds()); 719914a36b248ffb538874483d86759254838866dd7Eric Karl if (!image) { 720914a36b248ffb538874483d86759254838866dd7Eric Karl return false; 721914a36b248ffb538874483d86759254838866dd7Eric Karl } 722914a36b248ffb538874483d86759254838866dd7Eric Karl 723914a36b248ffb538874483d86759254838866dd7Eric Karl texture = image->getTexture(); 72436591e5ffe263fcab5c43456d7328da2bf9addb1Eric Karl if (!texture) { 72536591e5ffe263fcab5c43456d7328da2bf9addb1Eric Karl return false; 72636591e5ffe263fcab5c43456d7328da2bf9addb1Eric Karl } 727914a36b248ffb538874483d86759254838866dd7Eric Karl 728914a36b248ffb538874483d86759254838866dd7Eric Karl // Flush to ensure that the copy is completed before we return the texture. 729914a36b248ffb538874483d86759254838866dd7Eric Karl ctx->contextPriv().prepareSurfaceForExternalIO(as_IB(image)->peekProxy()); 730914a36b248ffb538874483d86759254838866dd7Eric Karl SkASSERT(!texture->surfacePriv().hasPendingIO()); 731914a36b248ffb538874483d86759254838866dd7Eric Karl } 732914a36b248ffb538874483d86759254838866dd7Eric Karl 733914a36b248ffb538874483d86759254838866dd7Eric Karl SkASSERT(!texture->resourcePriv().refsWrappedObjects()); 734914a36b248ffb538874483d86759254838866dd7Eric Karl SkASSERT(texture->surfacePriv().hasUniqueRef()); 735914a36b248ffb538874483d86759254838866dd7Eric Karl SkASSERT(image->unique()); 736914a36b248ffb538874483d86759254838866dd7Eric Karl 737914a36b248ffb538874483d86759254838866dd7Eric Karl // Take a reference to the GrTexture and release the image. 738914a36b248ffb538874483d86759254838866dd7Eric Karl sk_sp<GrTexture> textureRef(SkSafeRef(texture)); 739914a36b248ffb538874483d86759254838866dd7Eric Karl image = nullptr; 740914a36b248ffb538874483d86759254838866dd7Eric Karl 741914a36b248ffb538874483d86759254838866dd7Eric Karl // Steal the backend texture from the GrTexture, releasing the GrTexture in the process. 742914a36b248ffb538874483d86759254838866dd7Eric Karl return GrTexture::StealBackendTexture(std::move(textureRef), backendTexture, releaseProc); 743914a36b248ffb538874483d86759254838866dd7Eric Karl} 744914a36b248ffb538874483d86759254838866dd7Eric Karl 745914a36b248ffb538874483d86759254838866dd7Eric Karl/////////////////////////////////////////////////////////////////////////////////////////////////// 746914a36b248ffb538874483d86759254838866dd7Eric Karl 747d3df9ec874b2668111b36ce0993d860b4f88c765Matt Sarettsk_sp<SkImage> SkImage_Gpu::onMakeColorSpace(sk_sp<SkColorSpace> target, SkColorType, 7489f3dcb3f760274d42e28095fd3cf0f484168d996Matt Sarett SkTransferFunctionBehavior premulBehavior) const { 7499f3dcb3f760274d42e28095fd3cf0f484168d996Matt Sarett if (SkTransferFunctionBehavior::kRespect == premulBehavior) { 7509f3dcb3f760274d42e28095fd3cf0f484168d996Matt Sarett // TODO: Implement this. 7519f3dcb3f760274d42e28095fd3cf0f484168d996Matt Sarett return nullptr; 7529f3dcb3f760274d42e28095fd3cf0f484168d996Matt Sarett } 7539f3dcb3f760274d42e28095fd3cf0f484168d996Matt Sarett 754d3df9ec874b2668111b36ce0993d860b4f88c765Matt Sarett sk_sp<SkColorSpace> srcSpace = fColorSpace; 755d3df9ec874b2668111b36ce0993d860b4f88c765Matt Sarett if (!fColorSpace) { 756d3df9ec874b2668111b36ce0993d860b4f88c765Matt Sarett if (target->isSRGB()) { 757d3df9ec874b2668111b36ce0993d860b4f88c765Matt Sarett return sk_ref_sp(const_cast<SkImage*>((SkImage*)this)); 758d3df9ec874b2668111b36ce0993d860b4f88c765Matt Sarett } 759d3df9ec874b2668111b36ce0993d860b4f88c765Matt Sarett 760d3df9ec874b2668111b36ce0993d860b4f88c765Matt Sarett srcSpace = SkColorSpace::MakeSRGB(); 761d3df9ec874b2668111b36ce0993d860b4f88c765Matt Sarett } 762d3df9ec874b2668111b36ce0993d860b4f88c765Matt Sarett 763d3df9ec874b2668111b36ce0993d860b4f88c765Matt Sarett auto xform = GrNonlinearColorSpaceXformEffect::Make(srcSpace.get(), target.get()); 76463954c9944a5eed4527e0ed368f4e501faf2c625Brian Osman if (!xform) { 76563954c9944a5eed4527e0ed368f4e501faf2c625Brian Osman return sk_ref_sp(const_cast<SkImage_Gpu*>(this)); 76663954c9944a5eed4527e0ed368f4e501faf2c625Brian Osman } 76763954c9944a5eed4527e0ed368f4e501faf2c625Brian Osman 768dd3b3f41829d32d7eaf3eb4903570d49c2ba9ff8Robert Phillips sk_sp<GrRenderTargetContext> renderTargetContext(fContext->makeDeferredRenderTargetContext( 76963954c9944a5eed4527e0ed368f4e501faf2c625Brian Osman SkBackingFit::kExact, this->width(), this->height(), kRGBA_8888_GrPixelConfig, nullptr)); 77063954c9944a5eed4527e0ed368f4e501faf2c625Brian Osman if (!renderTargetContext) { 77163954c9944a5eed4527e0ed368f4e501faf2c625Brian Osman return nullptr; 77263954c9944a5eed4527e0ed368f4e501faf2c625Brian Osman } 77363954c9944a5eed4527e0ed368f4e501faf2c625Brian Osman 77463954c9944a5eed4527e0ed368f4e501faf2c625Brian Osman GrPaint paint; 77563954c9944a5eed4527e0ed368f4e501faf2c625Brian Osman paint.setPorterDuffXPFactory(SkBlendMode::kSrc); 7762240be96d97b5ac0886381d74a21f1e2a0928f55Brian Osman paint.addColorTextureProcessor(fProxy, SkMatrix::I()); 77763954c9944a5eed4527e0ed368f4e501faf2c625Brian Osman paint.addColorFragmentProcessor(std::move(xform)); 77863954c9944a5eed4527e0ed368f4e501faf2c625Brian Osman 77963954c9944a5eed4527e0ed368f4e501faf2c625Brian Osman const SkRect rect = SkRect::MakeIWH(this->width(), this->height()); 78063954c9944a5eed4527e0ed368f4e501faf2c625Brian Osman 78163954c9944a5eed4527e0ed368f4e501faf2c625Brian Osman renderTargetContext->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(), rect); 78263954c9944a5eed4527e0ed368f4e501faf2c625Brian Osman 7837ee385e1dc3cd6a47dc8f7297fef6e175eaba224Robert Phillips if (!renderTargetContext->asTextureProxy()) { 78463954c9944a5eed4527e0ed368f4e501faf2c625Brian Osman return nullptr; 78563954c9944a5eed4527e0ed368f4e501faf2c625Brian Osman } 78663954c9944a5eed4527e0ed368f4e501faf2c625Brian Osman 78763954c9944a5eed4527e0ed368f4e501faf2c625Brian Osman // MDB: this call is okay bc we know 'renderTargetContext' was exact 78863954c9944a5eed4527e0ed368f4e501faf2c625Brian Osman return sk_make_sp<SkImage_Gpu>(fContext, kNeedNewImageUniqueID, 78963954c9944a5eed4527e0ed368f4e501faf2c625Brian Osman fAlphaType, renderTargetContext->asTextureProxyRef(), 790d3df9ec874b2668111b36ce0993d860b4f88c765Matt Sarett std::move(target), fBudgeted); 79163954c9944a5eed4527e0ed368f4e501faf2c625Brian Osman 79263954c9944a5eed4527e0ed368f4e501faf2c625Brian Osman} 7935bbd076c52a6cebff4a2d63edd027b0f31624287Brian Osman 7945bbd076c52a6cebff4a2d63edd027b0f31624287Brian Osmanbool SkImage_Gpu::onIsValid(GrContext* context) const { 7955bbd076c52a6cebff4a2d63edd027b0f31624287Brian Osman // The base class has already checked that context isn't abandoned (if it's not nullptr) 7965bbd076c52a6cebff4a2d63edd027b0f31624287Brian Osman if (fContext->abandoned()) { 7975bbd076c52a6cebff4a2d63edd027b0f31624287Brian Osman return false; 7985bbd076c52a6cebff4a2d63edd027b0f31624287Brian Osman } 7995bbd076c52a6cebff4a2d63edd027b0f31624287Brian Osman 8005bbd076c52a6cebff4a2d63edd027b0f31624287Brian Osman if (context && context != fContext) { 8015bbd076c52a6cebff4a2d63edd027b0f31624287Brian Osman return false; 8025bbd076c52a6cebff4a2d63edd027b0f31624287Brian Osman } 8035bbd076c52a6cebff4a2d63edd027b0f31624287Brian Osman 8045bbd076c52a6cebff4a2d63edd027b0f31624287Brian Osman return true; 8055bbd076c52a6cebff4a2d63edd027b0f31624287Brian Osman} 806