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