SkImage_Gpu.cpp 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747
  1. /*
  2. * Copyright 2012 Google Inc.
  3. *
  4. * Use of this source code is governed by a BSD-style license that can be
  5. * found in the LICENSE file.
  6. */
  7. #include <cstddef>
  8. #include <cstring>
  9. #include <type_traits>
  10. #include "include/core/SkCanvas.h"
  11. #include "include/gpu/GrBackendSurface.h"
  12. #include "include/gpu/GrContext.h"
  13. #include "include/gpu/GrTexture.h"
  14. #include "include/private/GrRecordingContext.h"
  15. #include "include/private/SkImageInfoPriv.h"
  16. #include "src/core/SkAutoPixmapStorage.h"
  17. #include "src/core/SkBitmapCache.h"
  18. #include "src/core/SkMipMap.h"
  19. #include "src/core/SkScopeExit.h"
  20. #include "src/core/SkTraceEvent.h"
  21. #include "src/gpu/GrAHardwareBufferImageGenerator.h"
  22. #include "src/gpu/GrAHardwareBufferUtils.h"
  23. #include "src/gpu/GrBackendTextureImageGenerator.h"
  24. #include "src/gpu/GrBitmapTextureMaker.h"
  25. #include "src/gpu/GrCaps.h"
  26. #include "src/gpu/GrClip.h"
  27. #include "src/gpu/GrColorSpaceXform.h"
  28. #include "src/gpu/GrContextPriv.h"
  29. #include "src/gpu/GrDrawingManager.h"
  30. #include "src/gpu/GrGpu.h"
  31. #include "src/gpu/GrImageTextureMaker.h"
  32. #include "src/gpu/GrProxyProvider.h"
  33. #include "src/gpu/GrRecordingContextPriv.h"
  34. #include "src/gpu/GrRenderTargetContext.h"
  35. #include "src/gpu/GrResourceProvider.h"
  36. #include "src/gpu/GrResourceProviderPriv.h"
  37. #include "src/gpu/GrSemaphore.h"
  38. #include "src/gpu/GrSurfacePriv.h"
  39. #include "src/gpu/GrTextureAdjuster.h"
  40. #include "src/gpu/GrTextureContext.h"
  41. #include "src/gpu/GrTexturePriv.h"
  42. #include "src/gpu/GrTextureProxy.h"
  43. #include "src/gpu/GrTextureProxyPriv.h"
  44. #include "src/gpu/SkGr.h"
  45. #include "src/gpu/effects/GrYUVtoRGBEffect.h"
  46. #include "src/gpu/gl/GrGLTexture.h"
  47. #include "src/image/SkImage_Gpu.h"
  48. static SkColorType proxy_color_type(GrTextureProxy* proxy) {
  49. SkColorType colorType;
  50. if (!GrPixelConfigToColorType(proxy->config(), &colorType)) {
  51. colorType = kUnknown_SkColorType;
  52. }
  53. return colorType;
  54. }
  55. SkImage_Gpu::SkImage_Gpu(sk_sp<GrContext> context, uint32_t uniqueID, SkAlphaType at,
  56. sk_sp<GrTextureProxy> proxy, sk_sp<SkColorSpace> colorSpace)
  57. : INHERITED(std::move(context), proxy->worstCaseWidth(), proxy->worstCaseHeight(), uniqueID,
  58. proxy_color_type(proxy.get()), at, colorSpace)
  59. , fProxy(std::move(proxy)) {}
  60. SkImage_Gpu::~SkImage_Gpu() {}
  61. GrSemaphoresSubmitted SkImage_Gpu::onFlush(GrContext* context, const GrFlushInfo& info) {
  62. if (!context || !fContext->priv().matches(context) || fContext->abandoned()) {
  63. return GrSemaphoresSubmitted::kNo;
  64. }
  65. GrSurfaceProxy* p[1] = {fProxy.get()};
  66. return context->priv().flushSurfaces(p, 1, info);
  67. }
  68. sk_sp<SkImage> SkImage_Gpu::onMakeColorTypeAndColorSpace(GrRecordingContext* context,
  69. SkColorType targetCT,
  70. sk_sp<SkColorSpace> targetCS) const {
  71. if (!context || !fContext->priv().matches(context)) {
  72. return nullptr;
  73. }
  74. auto xform = GrColorSpaceXformEffect::Make(this->colorSpace(), this->alphaType(),
  75. targetCS.get(), this->alphaType());
  76. SkASSERT(xform || targetCT != this->colorType());
  77. sk_sp<GrTextureProxy> proxy = this->asTextureProxyRef(context);
  78. sk_sp<GrRenderTargetContext> renderTargetContext(
  79. context->priv().makeDeferredRenderTargetContextWithFallback(
  80. SkBackingFit::kExact, this->width(), this->height(),
  81. SkColorTypeToGrColorType(targetCT), nullptr));
  82. if (!renderTargetContext) {
  83. return nullptr;
  84. }
  85. GrPaint paint;
  86. paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
  87. paint.addColorTextureProcessor(std::move(proxy), SkMatrix::I());
  88. if (xform) {
  89. paint.addColorFragmentProcessor(std::move(xform));
  90. }
  91. renderTargetContext->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(),
  92. SkRect::MakeIWH(this->width(), this->height()));
  93. if (!renderTargetContext->asTextureProxy()) {
  94. return nullptr;
  95. }
  96. // MDB: this call is okay bc we know 'renderTargetContext' was exact
  97. return sk_make_sp<SkImage_Gpu>(fContext, kNeedNewImageUniqueID, this->alphaType(),
  98. renderTargetContext->asTextureProxyRef(), std::move(targetCS));
  99. }
  100. ///////////////////////////////////////////////////////////////////////////////////////////////////
  101. static sk_sp<SkImage> new_wrapped_texture_common(GrContext* ctx,
  102. const GrBackendTexture& backendTex,
  103. GrColorType colorType, GrSurfaceOrigin origin,
  104. SkAlphaType at, sk_sp<SkColorSpace> colorSpace,
  105. GrWrapOwnership ownership,
  106. SkImage::TextureReleaseProc releaseProc,
  107. SkImage::ReleaseContext releaseCtx) {
  108. if (!backendTex.isValid() || backendTex.width() <= 0 || backendTex.height() <= 0) {
  109. return nullptr;
  110. }
  111. GrProxyProvider* proxyProvider = ctx->priv().proxyProvider();
  112. sk_sp<GrTextureProxy> proxy =
  113. proxyProvider->wrapBackendTexture(backendTex, colorType, origin, ownership,
  114. GrWrapCacheable::kNo, kRead_GrIOType,
  115. releaseProc, releaseCtx);
  116. if (!proxy) {
  117. return nullptr;
  118. }
  119. return sk_make_sp<SkImage_Gpu>(sk_ref_sp(ctx), kNeedNewImageUniqueID, at, std::move(proxy),
  120. std::move(colorSpace));
  121. }
  122. sk_sp<SkImage> SkImage::MakeFromTexture(GrContext* ctx,
  123. const GrBackendTexture& tex, GrSurfaceOrigin origin,
  124. SkColorType ct, SkAlphaType at, sk_sp<SkColorSpace> cs,
  125. TextureReleaseProc releaseP, ReleaseContext releaseC) {
  126. if (!ctx) {
  127. return nullptr;
  128. }
  129. GrColorType grColorType = SkColorTypeAndFormatToGrColorType(ctx->priv().caps(), ct,
  130. tex.getBackendFormat());
  131. if (GrColorType::kUnknown == grColorType) {
  132. return nullptr;
  133. }
  134. GrBackendTexture texCopy = tex;
  135. if (!SkImage_GpuBase::ValidateBackendTexture(ctx, texCopy, &texCopy.fConfig, grColorType,
  136. ct, at, cs)) {
  137. return nullptr;
  138. }
  139. return new_wrapped_texture_common(ctx, texCopy, grColorType, origin, at, std::move(cs),
  140. kBorrow_GrWrapOwnership, releaseP, releaseC);
  141. }
  142. sk_sp<SkImage> SkImage::MakeFromAdoptedTexture(GrContext* ctx,
  143. const GrBackendTexture& tex, GrSurfaceOrigin origin,
  144. SkColorType ct, SkAlphaType at,
  145. sk_sp<SkColorSpace> cs) {
  146. if (!ctx || !ctx->priv().resourceProvider()) {
  147. // We have a DDL context and we don't support adopted textures for them.
  148. return nullptr;
  149. }
  150. GrColorType grColorType = SkColorTypeAndFormatToGrColorType(ctx->priv().caps(), ct,
  151. tex.getBackendFormat());
  152. if (GrColorType::kUnknown == grColorType) {
  153. return nullptr;
  154. }
  155. GrBackendTexture texCopy = tex;
  156. if (!SkImage_GpuBase::ValidateBackendTexture(ctx, texCopy, &texCopy.fConfig, grColorType,
  157. ct, at, cs)) {
  158. return nullptr;
  159. }
  160. return new_wrapped_texture_common(ctx, texCopy, grColorType, origin, at, std::move(cs),
  161. kAdopt_GrWrapOwnership, nullptr, nullptr);
  162. }
  163. sk_sp<SkImage> SkImage::MakeFromCompressed(GrContext* context, sk_sp<SkData> data,
  164. int width, int height, CompressionType type) {
  165. GrProxyProvider* proxyProvider = context->priv().proxyProvider();
  166. sk_sp<GrTextureProxy> proxy = proxyProvider->createCompressedTextureProxy(
  167. width, height, SkBudgeted::kYes, type, std::move(data));
  168. if (!proxy) {
  169. return nullptr;
  170. }
  171. return sk_make_sp<SkImage_Gpu>(sk_ref_sp(context), kNeedNewImageUniqueID, kOpaque_SkAlphaType,
  172. std::move(proxy), nullptr);
  173. }
  174. sk_sp<SkImage> SkImage_Gpu::ConvertYUVATexturesToRGB(GrContext* ctx, SkYUVColorSpace yuvColorSpace,
  175. const GrBackendTexture yuvaTextures[],
  176. const SkYUVAIndex yuvaIndices[4], SkISize size,
  177. GrSurfaceOrigin origin,
  178. GrRenderTargetContext* renderTargetContext) {
  179. SkASSERT(renderTargetContext);
  180. int numTextures;
  181. if (!SkYUVAIndex::AreValidIndices(yuvaIndices, &numTextures)) {
  182. return nullptr;
  183. }
  184. sk_sp<GrTextureProxy> tempTextureProxies[4];
  185. if (!SkImage_GpuBase::MakeTempTextureProxies(ctx, yuvaTextures, numTextures, yuvaIndices,
  186. origin, tempTextureProxies)) {
  187. return nullptr;
  188. }
  189. const SkRect rect = SkRect::MakeIWH(size.width(), size.height());
  190. if (!RenderYUVAToRGBA(ctx, renderTargetContext, rect, yuvColorSpace, nullptr,
  191. tempTextureProxies, yuvaIndices)) {
  192. return nullptr;
  193. }
  194. SkAlphaType at = GetAlphaTypeFromYUVAIndices(yuvaIndices);
  195. // MDB: this call is okay bc we know 'renderTargetContext' was exact
  196. return sk_make_sp<SkImage_Gpu>(sk_ref_sp(ctx), kNeedNewImageUniqueID, at,
  197. renderTargetContext->asTextureProxyRef(),
  198. renderTargetContext->colorSpaceInfo().refColorSpace());
  199. }
  200. sk_sp<SkImage> SkImage::MakeFromYUVATexturesCopy(GrContext* ctx,
  201. SkYUVColorSpace yuvColorSpace,
  202. const GrBackendTexture yuvaTextures[],
  203. const SkYUVAIndex yuvaIndices[4],
  204. SkISize imageSize,
  205. GrSurfaceOrigin imageOrigin,
  206. sk_sp<SkColorSpace> imageColorSpace) {
  207. const int width = imageSize.width();
  208. const int height = imageSize.height();
  209. // Needs to create a render target in order to draw to it for the yuv->rgb conversion.
  210. sk_sp<GrRenderTargetContext> renderTargetContext(ctx->priv().makeDeferredRenderTargetContext(
  211. SkBackingFit::kExact, width, height, GrColorType::kRGBA_8888,
  212. std::move(imageColorSpace), 1, GrMipMapped::kNo, imageOrigin));
  213. if (!renderTargetContext) {
  214. return nullptr;
  215. }
  216. return SkImage_Gpu::ConvertYUVATexturesToRGB(ctx, yuvColorSpace, yuvaTextures, yuvaIndices,
  217. imageSize, imageOrigin, renderTargetContext.get());
  218. }
  219. sk_sp<SkImage> SkImage::MakeFromYUVATexturesCopyWithExternalBackend(
  220. GrContext* ctx,
  221. SkYUVColorSpace yuvColorSpace,
  222. const GrBackendTexture yuvaTextures[],
  223. const SkYUVAIndex yuvaIndices[4],
  224. SkISize imageSize,
  225. GrSurfaceOrigin imageOrigin,
  226. const GrBackendTexture& backendTexture,
  227. sk_sp<SkColorSpace> imageColorSpace) {
  228. GrColorType grColorType = SkColorTypeAndFormatToGrColorType(ctx->priv().caps(),
  229. kRGBA_8888_SkColorType,
  230. backendTexture.getBackendFormat());
  231. if (GrColorType::kUnknown == grColorType) {
  232. return nullptr;
  233. }
  234. GrBackendTexture backendTextureCopy = backendTexture;
  235. SkAlphaType at = SkImage_GpuBase::GetAlphaTypeFromYUVAIndices(yuvaIndices);
  236. if (!SkImage_Gpu::ValidateBackendTexture(ctx, backendTextureCopy, &backendTextureCopy.fConfig,
  237. grColorType, kRGBA_8888_SkColorType, at, nullptr)) {
  238. return nullptr;
  239. }
  240. // Needs to create a render target with external texture
  241. // in order to draw to it for the yuv->rgb conversion.
  242. sk_sp<GrRenderTargetContext> renderTargetContext(
  243. ctx->priv().makeBackendTextureRenderTargetContext(backendTextureCopy, imageOrigin, 1,
  244. grColorType,
  245. std::move(imageColorSpace)));
  246. if (!renderTargetContext) {
  247. return nullptr;
  248. }
  249. return SkImage_Gpu::ConvertYUVATexturesToRGB(ctx, yuvColorSpace, yuvaTextures, yuvaIndices,
  250. imageSize, imageOrigin, renderTargetContext.get());
  251. }
  252. sk_sp<SkImage> SkImage::MakeFromYUVTexturesCopy(GrContext* ctx, SkYUVColorSpace yuvColorSpace,
  253. const GrBackendTexture yuvTextures[3],
  254. GrSurfaceOrigin imageOrigin,
  255. sk_sp<SkColorSpace> imageColorSpace) {
  256. // TODO: SkImageSourceChannel input is being ingored right now. Setup correctly in the future.
  257. SkYUVAIndex yuvaIndices[4] = {
  258. SkYUVAIndex{0, SkColorChannel::kR},
  259. SkYUVAIndex{1, SkColorChannel::kR},
  260. SkYUVAIndex{2, SkColorChannel::kR},
  261. SkYUVAIndex{-1, SkColorChannel::kA}};
  262. SkISize size{yuvTextures[0].width(), yuvTextures[0].height()};
  263. return SkImage_Gpu::MakeFromYUVATexturesCopy(ctx, yuvColorSpace, yuvTextures, yuvaIndices,
  264. size, imageOrigin, std::move(imageColorSpace));
  265. }
  266. sk_sp<SkImage> SkImage::MakeFromYUVTexturesCopyWithExternalBackend(
  267. GrContext* ctx, SkYUVColorSpace yuvColorSpace, const GrBackendTexture yuvTextures[3],
  268. GrSurfaceOrigin imageOrigin, const GrBackendTexture& backendTexture,
  269. sk_sp<SkColorSpace> imageColorSpace) {
  270. SkYUVAIndex yuvaIndices[4] = {
  271. SkYUVAIndex{0, SkColorChannel::kR},
  272. SkYUVAIndex{1, SkColorChannel::kR},
  273. SkYUVAIndex{2, SkColorChannel::kR},
  274. SkYUVAIndex{-1, SkColorChannel::kA}};
  275. SkISize size{yuvTextures[0].width(), yuvTextures[0].height()};
  276. return SkImage_Gpu::MakeFromYUVATexturesCopyWithExternalBackend(
  277. ctx, yuvColorSpace, yuvTextures, yuvaIndices, size, imageOrigin, backendTexture,
  278. std::move(imageColorSpace));
  279. }
  280. sk_sp<SkImage> SkImage::MakeFromNV12TexturesCopy(GrContext* ctx, SkYUVColorSpace yuvColorSpace,
  281. const GrBackendTexture nv12Textures[2],
  282. GrSurfaceOrigin imageOrigin,
  283. sk_sp<SkColorSpace> imageColorSpace) {
  284. // TODO: SkImageSourceChannel input is being ingored right now. Setup correctly in the future.
  285. SkYUVAIndex yuvaIndices[4] = {
  286. SkYUVAIndex{0, SkColorChannel::kR},
  287. SkYUVAIndex{1, SkColorChannel::kR},
  288. SkYUVAIndex{1, SkColorChannel::kG},
  289. SkYUVAIndex{-1, SkColorChannel::kA}};
  290. SkISize size{nv12Textures[0].width(), nv12Textures[0].height()};
  291. return SkImage_Gpu::MakeFromYUVATexturesCopy(ctx, yuvColorSpace, nv12Textures, yuvaIndices,
  292. size, imageOrigin, std::move(imageColorSpace));
  293. }
  294. sk_sp<SkImage> SkImage::MakeFromNV12TexturesCopyWithExternalBackend(
  295. GrContext* ctx,
  296. SkYUVColorSpace yuvColorSpace,
  297. const GrBackendTexture nv12Textures[2],
  298. GrSurfaceOrigin imageOrigin,
  299. const GrBackendTexture& backendTexture,
  300. sk_sp<SkColorSpace> imageColorSpace) {
  301. SkYUVAIndex yuvaIndices[4] = {
  302. SkYUVAIndex{0, SkColorChannel::kR},
  303. SkYUVAIndex{1, SkColorChannel::kR},
  304. SkYUVAIndex{1, SkColorChannel::kG},
  305. SkYUVAIndex{-1, SkColorChannel::kA}};
  306. SkISize size{nv12Textures[0].width(), nv12Textures[0].height()};
  307. return SkImage_Gpu::MakeFromYUVATexturesCopyWithExternalBackend(
  308. ctx, yuvColorSpace, nv12Textures, yuvaIndices, size, imageOrigin, backendTexture,
  309. std::move(imageColorSpace));
  310. }
  311. static sk_sp<SkImage> create_image_from_producer(GrContext* context, GrTextureProducer* producer,
  312. SkAlphaType at, uint32_t id,
  313. GrMipMapped mipMapped) {
  314. sk_sp<GrTextureProxy> proxy(producer->refTextureProxy(mipMapped));
  315. if (!proxy) {
  316. return nullptr;
  317. }
  318. return sk_make_sp<SkImage_Gpu>(sk_ref_sp(context), id, at, std::move(proxy),
  319. sk_ref_sp(producer->colorSpace()));
  320. }
  321. sk_sp<SkImage> SkImage::makeTextureImage(GrContext* context, SkColorSpace* dstColorSpace,
  322. GrMipMapped mipMapped) const {
  323. if (!context) {
  324. return nullptr;
  325. }
  326. if (this->isTextureBacked()) {
  327. if (!as_IB(this)->context()->priv().matches(context)) {
  328. return nullptr;
  329. }
  330. sk_sp<GrTextureProxy> proxy = as_IB(this)->asTextureProxyRef(context);
  331. SkASSERT(proxy);
  332. if (GrMipMapped::kNo == mipMapped || proxy->mipMapped() == mipMapped) {
  333. return sk_ref_sp(const_cast<SkImage*>(this));
  334. }
  335. GrTextureAdjuster adjuster(context, std::move(proxy),
  336. SkColorTypeToGrColorType(this->colorType()), this->alphaType(),
  337. this->uniqueID(), this->colorSpace());
  338. return create_image_from_producer(context, &adjuster, this->alphaType(),
  339. this->uniqueID(), mipMapped);
  340. }
  341. if (this->isLazyGenerated()) {
  342. GrImageTextureMaker maker(context, this, kDisallow_CachingHint);
  343. return create_image_from_producer(context, &maker, this->alphaType(),
  344. this->uniqueID(), mipMapped);
  345. }
  346. if (const SkBitmap* bmp = as_IB(this)->onPeekBitmap()) {
  347. GrBitmapTextureMaker maker(context, *bmp);
  348. return create_image_from_producer(context, &maker, this->alphaType(),
  349. this->uniqueID(), mipMapped);
  350. }
  351. return nullptr;
  352. }
  353. ///////////////////////////////////////////////////////////////////////////////////////////////////
  354. sk_sp<SkImage> SkImage_Gpu::MakePromiseTexture(GrContext* context,
  355. const GrBackendFormat& backendFormat,
  356. int width,
  357. int height,
  358. GrMipMapped mipMapped,
  359. GrSurfaceOrigin origin,
  360. SkColorType colorType,
  361. SkAlphaType alphaType,
  362. sk_sp<SkColorSpace> colorSpace,
  363. PromiseImageTextureFulfillProc textureFulfillProc,
  364. PromiseImageTextureReleaseProc textureReleaseProc,
  365. PromiseImageTextureDoneProc textureDoneProc,
  366. PromiseImageTextureContext textureContext,
  367. PromiseImageApiVersion version) {
  368. // The contract here is that if 'promiseDoneProc' is passed in it should always be called,
  369. // even if creation of the SkImage fails. Once we call MakePromiseImageLazyProxy it takes
  370. // responsibility for calling the done proc.
  371. if (!textureDoneProc) {
  372. return nullptr;
  373. }
  374. SkScopeExit callDone([textureDoneProc, textureContext]() { textureDoneProc(textureContext); });
  375. SkImageInfo info = SkImageInfo::Make(width, height, colorType, alphaType, colorSpace);
  376. if (!SkImageInfoIsValid(info)) {
  377. return nullptr;
  378. }
  379. if (!context) {
  380. return nullptr;
  381. }
  382. if (width <= 0 || height <= 0) {
  383. return nullptr;
  384. }
  385. GrColorType grColorType = SkColorTypeAndFormatToGrColorType(context->priv().caps(),
  386. colorType,
  387. backendFormat);
  388. if (GrColorType::kUnknown == grColorType) {
  389. return nullptr;
  390. }
  391. callDone.clear();
  392. auto proxy = MakePromiseImageLazyProxy(context, width, height, origin,
  393. grColorType, backendFormat,
  394. mipMapped, textureFulfillProc, textureReleaseProc,
  395. textureDoneProc, textureContext, version);
  396. if (!proxy) {
  397. return nullptr;
  398. }
  399. return sk_make_sp<SkImage_Gpu>(sk_ref_sp(context), kNeedNewImageUniqueID, alphaType,
  400. std::move(proxy), std::move(colorSpace));
  401. }
  402. ///////////////////////////////////////////////////////////////////////////////////////////////////
  403. sk_sp<SkImage> SkImage::MakeCrossContextFromEncoded(GrContext* context, sk_sp<SkData> encoded,
  404. bool buildMips, SkColorSpace* dstColorSpace,
  405. bool limitToMaxTextureSize) {
  406. sk_sp<SkImage> codecImage = SkImage::MakeFromEncoded(std::move(encoded));
  407. if (!codecImage) {
  408. return nullptr;
  409. }
  410. // Some backends or drivers don't support (safely) moving resources between contexts
  411. if (!context || !context->priv().caps()->crossContextTextureSupport()) {
  412. return codecImage;
  413. }
  414. // If non-power-of-two mipmapping isn't supported, ignore the client's request
  415. if (!context->priv().caps()->mipMapSupport()) {
  416. buildMips = false;
  417. }
  418. auto maxTextureSize = context->priv().caps()->maxTextureSize();
  419. if (limitToMaxTextureSize &&
  420. (codecImage->width() > maxTextureSize || codecImage->height() > maxTextureSize)) {
  421. SkAutoPixmapStorage pmap;
  422. SkImageInfo info = codecImage->imageInfo();
  423. if (!dstColorSpace) {
  424. info = info.makeColorSpace(nullptr);
  425. }
  426. if (!pmap.tryAlloc(info) || !codecImage->readPixels(pmap, 0, 0, kDisallow_CachingHint)) {
  427. return nullptr;
  428. }
  429. return MakeCrossContextFromPixmap(context, pmap, buildMips, dstColorSpace, true);
  430. }
  431. // Turn the codec image into a GrTextureProxy
  432. GrImageTextureMaker maker(context, codecImage.get(), kDisallow_CachingHint);
  433. GrSamplerState samplerState(
  434. GrSamplerState::WrapMode::kClamp,
  435. buildMips ? GrSamplerState::Filter::kMipMap : GrSamplerState::Filter::kBilerp);
  436. SkScalar scaleAdjust[2] = { 1.0f, 1.0f };
  437. sk_sp<GrTextureProxy> proxy(maker.refTextureProxyForParams(samplerState, scaleAdjust));
  438. // Given that we disable mipmaps if non-power-of-two mipmapping isn't supported, we always
  439. // expect the created texture to be unscaled.
  440. SkASSERT(scaleAdjust[0] == 1.0f && scaleAdjust[1] == 1.0f);
  441. if (!proxy) {
  442. return codecImage;
  443. }
  444. // Flush any writes or uploads
  445. context->priv().flushSurface(proxy.get());
  446. if (!proxy->isInstantiated()) {
  447. return codecImage;
  448. }
  449. sk_sp<GrTexture> texture = sk_ref_sp(proxy->peekTexture());
  450. GrGpu* gpu = context->priv().getGpu();
  451. sk_sp<GrSemaphore> sema = gpu->prepareTextureForCrossContextUsage(texture.get());
  452. auto gen = GrBackendTextureImageGenerator::Make(
  453. std::move(texture), proxy->origin(), std::move(sema), codecImage->colorType(),
  454. codecImage->alphaType(), codecImage->refColorSpace());
  455. return SkImage::MakeFromGenerator(std::move(gen));
  456. }
  457. sk_sp<SkImage> SkImage::MakeCrossContextFromPixmap(GrContext* context,
  458. const SkPixmap& originalPixmap, bool buildMips,
  459. SkColorSpace* dstColorSpace,
  460. bool limitToMaxTextureSize) {
  461. // Some backends or drivers don't support (safely) moving resources between contexts
  462. if (!context || !context->priv().caps()->crossContextTextureSupport()) {
  463. return SkImage::MakeRasterCopy(originalPixmap);
  464. }
  465. // If we don't have access to the resource provider and gpu (i.e. in a DDL context) we will not
  466. // be able to make everything needed for a GPU CrossContext image. Thus return a raster copy
  467. // instead.
  468. if (!context->priv().resourceProvider()) {
  469. return SkImage::MakeRasterCopy(originalPixmap);
  470. }
  471. // If non-power-of-two mipmapping isn't supported, ignore the client's request
  472. if (!context->priv().caps()->mipMapSupport()) {
  473. buildMips = false;
  474. }
  475. const SkPixmap* pixmap = &originalPixmap;
  476. SkAutoPixmapStorage resized;
  477. int maxTextureSize = context->priv().caps()->maxTextureSize();
  478. int maxDim = SkTMax(originalPixmap.width(), originalPixmap.height());
  479. if (limitToMaxTextureSize && maxDim > maxTextureSize) {
  480. float scale = static_cast<float>(maxTextureSize) / maxDim;
  481. int newWidth = SkTMin(static_cast<int>(originalPixmap.width() * scale), maxTextureSize);
  482. int newHeight = SkTMin(static_cast<int>(originalPixmap.height() * scale), maxTextureSize);
  483. SkImageInfo info = originalPixmap.info().makeWH(newWidth, newHeight);
  484. if (!resized.tryAlloc(info) || !originalPixmap.scalePixels(resized, kLow_SkFilterQuality)) {
  485. return nullptr;
  486. }
  487. pixmap = &resized;
  488. }
  489. GrProxyProvider* proxyProvider = context->priv().proxyProvider();
  490. // Turn the pixmap into a GrTextureProxy
  491. SkBitmap bmp;
  492. bmp.installPixels(*pixmap);
  493. GrMipMapped mipMapped = buildMips ? GrMipMapped::kYes : GrMipMapped::kNo;
  494. sk_sp<GrTextureProxy> proxy = proxyProvider->createProxyFromBitmap(bmp, mipMapped);
  495. if (!proxy) {
  496. return SkImage::MakeRasterCopy(*pixmap);
  497. }
  498. sk_sp<GrTexture> texture = sk_ref_sp(proxy->peekTexture());
  499. // Flush any writes or uploads
  500. context->priv().flushSurface(proxy.get());
  501. GrGpu* gpu = context->priv().getGpu();
  502. sk_sp<GrSemaphore> sema = gpu->prepareTextureForCrossContextUsage(texture.get());
  503. auto gen = GrBackendTextureImageGenerator::Make(std::move(texture), proxy->origin(),
  504. std::move(sema), pixmap->colorType(),
  505. pixmap->alphaType(),
  506. pixmap->info().refColorSpace());
  507. return SkImage::MakeFromGenerator(std::move(gen));
  508. }
  509. #if defined(SK_BUILD_FOR_ANDROID) && __ANDROID_API__ >= 26
  510. sk_sp<SkImage> SkImage::MakeFromAHardwareBuffer(AHardwareBuffer* graphicBuffer, SkAlphaType at,
  511. sk_sp<SkColorSpace> cs,
  512. GrSurfaceOrigin surfaceOrigin) {
  513. auto gen = GrAHardwareBufferImageGenerator::Make(graphicBuffer, at, cs, surfaceOrigin);
  514. return SkImage::MakeFromGenerator(std::move(gen));
  515. }
  516. sk_sp<SkImage> SkImage::MakeFromAHardwareBufferWithData(GrContext* context,
  517. const SkPixmap& pixmap,
  518. AHardwareBuffer* hardwareBuffer,
  519. GrSurfaceOrigin surfaceOrigin) {
  520. AHardwareBuffer_Desc bufferDesc;
  521. AHardwareBuffer_describe(hardwareBuffer, &bufferDesc);
  522. if (!SkToBool(bufferDesc.usage & AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE)) {
  523. return nullptr;
  524. }
  525. GrBackendFormat backendFormat = GrAHardwareBufferUtils::GetBackendFormat(context,
  526. hardwareBuffer,
  527. bufferDesc.format,
  528. true);
  529. if (!backendFormat.isValid()) {
  530. return nullptr;
  531. }
  532. GrAHardwareBufferUtils::DeleteImageProc deleteImageProc = nullptr;
  533. GrAHardwareBufferUtils::DeleteImageCtx deleteImageCtx = nullptr;
  534. GrBackendTexture backendTexture =
  535. GrAHardwareBufferUtils::MakeBackendTexture(context, hardwareBuffer,
  536. bufferDesc.width, bufferDesc.height,
  537. &deleteImageProc, &deleteImageCtx,
  538. false, backendFormat, true);
  539. if (!backendTexture.isValid()) {
  540. return nullptr;
  541. }
  542. SkASSERT(deleteImageProc);
  543. SkColorType colorType =
  544. GrAHardwareBufferUtils::GetSkColorTypeFromBufferFormat(bufferDesc.format);
  545. GrColorType grColorType = SkColorTypeToGrColorType(colorType);
  546. backendTexture.fConfig = context->priv().caps()->getConfigFromBackendFormat(
  547. backendFormat, grColorType);
  548. GrProxyProvider* proxyProvider = context->priv().proxyProvider();
  549. if (!proxyProvider) {
  550. deleteImageProc(deleteImageCtx);
  551. return nullptr;
  552. }
  553. sk_sp<GrTextureProxy> proxy =
  554. proxyProvider->wrapBackendTexture(backendTexture, grColorType, surfaceOrigin,
  555. kBorrow_GrWrapOwnership, GrWrapCacheable::kNo,
  556. kRW_GrIOType, deleteImageProc, deleteImageCtx);
  557. if (!proxy) {
  558. deleteImageProc(deleteImageCtx);
  559. return nullptr;
  560. }
  561. sk_sp<SkColorSpace> cs = pixmap.refColorSpace();
  562. SkAlphaType at = pixmap.alphaType();
  563. sk_sp<SkImage> image = sk_make_sp<SkImage_Gpu>(sk_ref_sp(context), kNeedNewImageUniqueID, at,
  564. proxy, cs);
  565. if (!image) {
  566. return nullptr;
  567. }
  568. GrDrawingManager* drawingManager = context->priv().drawingManager();
  569. if (!drawingManager) {
  570. return nullptr;
  571. }
  572. sk_sp<GrTextureContext> texContext =
  573. drawingManager->makeTextureContext(proxy, SkColorTypeToGrColorType(pixmap.colorType()),
  574. pixmap.alphaType(), cs);
  575. if (!texContext) {
  576. return nullptr;
  577. }
  578. SkImageInfo srcInfo = SkImageInfo::Make(bufferDesc.width, bufferDesc.height, colorType, at,
  579. std::move(cs));
  580. texContext->writePixels(srcInfo, pixmap.addr(0, 0), pixmap.rowBytes(), {0, 0});
  581. GrFlushInfo info;
  582. info.fFlags = kSyncCpu_GrFlushFlag;
  583. GrSurfaceProxy* p[1] = {proxy.get()};
  584. drawingManager->flush(p, 1, SkSurface::BackendSurfaceAccess::kNoAccess, info,
  585. GrPrepareForExternalIORequests());
  586. return image;
  587. }
  588. #endif
  589. ///////////////////////////////////////////////////////////////////////////////////////////////////
  590. bool SkImage::MakeBackendTextureFromSkImage(GrContext* ctx,
  591. sk_sp<SkImage> image,
  592. GrBackendTexture* backendTexture,
  593. BackendTextureReleaseProc* releaseProc) {
  594. if (!image || !ctx || !backendTexture || !releaseProc) {
  595. return false;
  596. }
  597. // Ensure we have a texture backed image.
  598. if (!image->isTextureBacked()) {
  599. image = image->makeTextureImage(ctx, nullptr);
  600. if (!image) {
  601. return false;
  602. }
  603. }
  604. GrTexture* texture = image->getTexture();
  605. if (!texture) {
  606. // In context-loss cases, we may not have a texture.
  607. return false;
  608. }
  609. // If the image's context doesn't match the provided context, fail.
  610. if (texture->getContext() != ctx) {
  611. return false;
  612. }
  613. // Flush any pending IO on the texture.
  614. ctx->priv().flushSurface(as_IB(image)->peekProxy());
  615. SkASSERT(!texture->surfacePriv().hasPendingIO());
  616. // We must make a copy of the image if the image is not unique, if the GrTexture owned by the
  617. // image is not unique, or if the texture wraps an external object.
  618. if (!image->unique() || !texture->surfacePriv().hasUniqueRef() ||
  619. texture->resourcePriv().refsWrappedObjects()) {
  620. // onMakeSubset will always copy the image.
  621. image = as_IB(image)->onMakeSubset(ctx, image->bounds());
  622. if (!image) {
  623. return false;
  624. }
  625. texture = image->getTexture();
  626. if (!texture) {
  627. return false;
  628. }
  629. // Flush to ensure that the copy is completed before we return the texture.
  630. ctx->priv().flushSurface(as_IB(image)->peekProxy());
  631. SkASSERT(!texture->surfacePriv().hasPendingIO());
  632. }
  633. SkASSERT(!texture->resourcePriv().refsWrappedObjects());
  634. SkASSERT(texture->surfacePriv().hasUniqueRef());
  635. SkASSERT(image->unique());
  636. // Take a reference to the GrTexture and release the image.
  637. sk_sp<GrTexture> textureRef(SkSafeRef(texture));
  638. image = nullptr;
  639. // Steal the backend texture from the GrTexture, releasing the GrTexture in the process.
  640. return GrTexture::StealBackendTexture(std::move(textureRef), backendTexture, releaseProc);
  641. }