SkSurface_Gpu.cpp 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813
  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 "include/core/SkCanvas.h"
  8. #include "include/core/SkSurfaceCharacterization.h"
  9. #include "include/gpu/GrBackendSurface.h"
  10. #include "include/gpu/GrRenderTarget.h"
  11. #include "include/gpu/GrTexture.h"
  12. #include "include/private/GrRecordingContext.h"
  13. #include "include/private/SkDeferredDisplayList.h"
  14. #include "src/core/SkImagePriv.h"
  15. #include "src/gpu/GrAHardwareBufferUtils.h"
  16. #include "src/gpu/GrCaps.h"
  17. #include "src/gpu/GrContextPriv.h"
  18. #include "src/gpu/GrContextThreadSafeProxyPriv.h"
  19. #include "src/gpu/GrRecordingContextPriv.h"
  20. #include "src/gpu/GrRenderTargetContextPriv.h"
  21. #include "src/gpu/GrRenderTargetProxyPriv.h"
  22. #include "src/gpu/SkGpuDevice.h"
  23. #include "src/image/SkImage_Base.h"
  24. #include "src/image/SkImage_Gpu.h"
  25. #include "src/image/SkSurface_Base.h"
  26. #include "src/image/SkSurface_Gpu.h"
  27. #if SK_SUPPORT_GPU
  28. SkSurface_Gpu::SkSurface_Gpu(sk_sp<SkGpuDevice> device)
  29. : INHERITED(device->width(), device->height(), &device->surfaceProps())
  30. , fDevice(std::move(device)) {
  31. SkASSERT(fDevice->accessRenderTargetContext()->asSurfaceProxy()->priv().isExact());
  32. }
  33. SkSurface_Gpu::~SkSurface_Gpu() {
  34. }
  35. static GrRenderTarget* prepare_rt_for_external_access(SkSurface_Gpu* surface,
  36. SkSurface::BackendHandleAccess access) {
  37. switch (access) {
  38. case SkSurface::kFlushRead_BackendHandleAccess:
  39. break;
  40. case SkSurface::kFlushWrite_BackendHandleAccess:
  41. case SkSurface::kDiscardWrite_BackendHandleAccess:
  42. // for now we don't special-case on Discard, but we may in the future.
  43. surface->notifyContentWillChange(SkSurface::kRetain_ContentChangeMode);
  44. break;
  45. }
  46. // Grab the render target *after* firing notifications, as it may get switched if CoW kicks in.
  47. surface->getDevice()->flush(SkSurface::BackendSurfaceAccess::kNoAccess, GrFlushInfo());
  48. GrRenderTargetContext* rtc = surface->getDevice()->accessRenderTargetContext();
  49. return rtc->accessRenderTarget();
  50. }
  51. GrBackendTexture SkSurface_Gpu::onGetBackendTexture(BackendHandleAccess access) {
  52. GrRenderTarget* rt = prepare_rt_for_external_access(this, access);
  53. if (!rt) {
  54. return GrBackendTexture(); // invalid
  55. }
  56. GrTexture* texture = rt->asTexture();
  57. if (texture) {
  58. return texture->getBackendTexture();
  59. }
  60. return GrBackendTexture(); // invalid
  61. }
  62. GrBackendRenderTarget SkSurface_Gpu::onGetBackendRenderTarget(BackendHandleAccess access) {
  63. GrRenderTarget* rt = prepare_rt_for_external_access(this, access);
  64. if (!rt) {
  65. return GrBackendRenderTarget(); // invalid
  66. }
  67. return rt->getBackendRenderTarget();
  68. }
  69. SkCanvas* SkSurface_Gpu::onNewCanvas() { return new SkCanvas(fDevice); }
  70. sk_sp<SkSurface> SkSurface_Gpu::onNewSurface(const SkImageInfo& info) {
  71. int sampleCount = fDevice->accessRenderTargetContext()->numSamples();
  72. GrSurfaceOrigin origin = fDevice->accessRenderTargetContext()->origin();
  73. // TODO: Make caller specify this (change virtual signature of onNewSurface).
  74. static const SkBudgeted kBudgeted = SkBudgeted::kNo;
  75. return SkSurface::MakeRenderTarget(fDevice->context(), kBudgeted, info, sampleCount,
  76. origin, &this->props());
  77. }
  78. sk_sp<SkImage> SkSurface_Gpu::onNewImageSnapshot(const SkIRect* subset) {
  79. GrRenderTargetContext* rtc = fDevice->accessRenderTargetContext();
  80. if (!rtc) {
  81. return nullptr;
  82. }
  83. GrContext* ctx = fDevice->context();
  84. if (!rtc->asSurfaceProxy()) {
  85. return nullptr;
  86. }
  87. SkBudgeted budgeted = rtc->asSurfaceProxy()->isBudgeted();
  88. sk_sp<GrTextureProxy> srcProxy = rtc->asTextureProxyRef();
  89. if (subset) {
  90. srcProxy = GrSurfaceProxy::Copy(ctx, rtc->asSurfaceProxy(), rtc->mipMapped(), *subset,
  91. SkBackingFit::kExact, budgeted);
  92. } else if (!srcProxy || rtc->priv().refsWrappedObjects()) {
  93. // If the original render target is a buffer originally created by the client, then we don't
  94. // want to ever retarget the SkSurface at another buffer we create. Force a copy now to avoid
  95. // copy-on-write.
  96. SkASSERT(rtc->origin() == rtc->asSurfaceProxy()->origin());
  97. srcProxy = GrSurfaceProxy::Copy(ctx, rtc->asSurfaceProxy(), rtc->mipMapped(),
  98. SkBackingFit::kExact, budgeted);
  99. }
  100. const SkImageInfo info = fDevice->imageInfo();
  101. sk_sp<SkImage> image;
  102. if (srcProxy) {
  103. // The renderTargetContext coming out of SkGpuDevice should always be exact and the
  104. // above copy creates a kExact surfaceContext.
  105. SkASSERT(srcProxy->priv().isExact());
  106. image = sk_make_sp<SkImage_Gpu>(sk_ref_sp(ctx), kNeedNewImageUniqueID, info.alphaType(),
  107. std::move(srcProxy), info.refColorSpace());
  108. }
  109. return image;
  110. }
  111. void SkSurface_Gpu::onWritePixels(const SkPixmap& src, int x, int y) {
  112. fDevice->writePixels(src, x, y);
  113. }
  114. void SkSurface_Gpu::onAsyncRescaleAndReadPixels(const SkImageInfo& info, const SkIRect& srcRect,
  115. RescaleGamma rescaleGamma,
  116. SkFilterQuality rescaleQuality,
  117. ReadPixelsCallback callback,
  118. ReadPixelsContext context) {
  119. auto* rtc = this->fDevice->accessRenderTargetContext();
  120. rtc->asyncRescaleAndReadPixels(info, srcRect, rescaleGamma, rescaleQuality, callback, context);
  121. }
  122. void SkSurface_Gpu::onAsyncRescaleAndReadPixelsYUV420(
  123. SkYUVColorSpace yuvColorSpace, sk_sp<SkColorSpace> dstColorSpace, const SkIRect& srcRect,
  124. int dstW, int dstH, RescaleGamma rescaleGamma, SkFilterQuality rescaleQuality,
  125. ReadPixelsCallbackYUV420 callback, ReadPixelsContext context) {
  126. auto* rtc = this->fDevice->accessRenderTargetContext();
  127. rtc->asyncRescaleAndReadPixelsYUV420(yuvColorSpace, std::move(dstColorSpace), srcRect, dstW,
  128. dstH, rescaleGamma, rescaleQuality, callback, context);
  129. }
  130. // Create a new render target and, if necessary, copy the contents of the old
  131. // render target into it. Note that this flushes the SkGpuDevice but
  132. // doesn't force an OpenGL flush.
  133. void SkSurface_Gpu::onCopyOnWrite(ContentChangeMode mode) {
  134. GrRenderTargetContext* rtc = fDevice->accessRenderTargetContext();
  135. // are we sharing our backing proxy with the image? Note this call should never create a new
  136. // image because onCopyOnWrite is only called when there is a cached image.
  137. sk_sp<SkImage> image(this->refCachedImage());
  138. SkASSERT(image);
  139. GrSurfaceProxy* imageProxy = ((SkImage_Base*) image.get())->peekProxy();
  140. SkASSERT(imageProxy);
  141. if (rtc->asSurfaceProxy()->underlyingUniqueID() == imageProxy->underlyingUniqueID()) {
  142. fDevice->replaceRenderTargetContext(SkSurface::kRetain_ContentChangeMode == mode);
  143. } else if (kDiscard_ContentChangeMode == mode) {
  144. this->SkSurface_Gpu::onDiscard();
  145. }
  146. }
  147. void SkSurface_Gpu::onDiscard() {
  148. fDevice->accessRenderTargetContext()->discard();
  149. }
  150. GrSemaphoresSubmitted SkSurface_Gpu::onFlush(BackendSurfaceAccess access,
  151. const GrFlushInfo& info) {
  152. return fDevice->flush(access, info);
  153. }
  154. bool SkSurface_Gpu::onWait(int numSemaphores, const GrBackendSemaphore* waitSemaphores) {
  155. return fDevice->wait(numSemaphores, waitSemaphores);
  156. }
  157. bool SkSurface_Gpu::onCharacterize(SkSurfaceCharacterization* characterization) const {
  158. GrRenderTargetContext* rtc = fDevice->accessRenderTargetContext();
  159. GrContext* ctx = fDevice->context();
  160. int maxResourceCount;
  161. size_t maxResourceBytes;
  162. ctx->getResourceCacheLimits(&maxResourceCount, &maxResourceBytes);
  163. bool mipmapped = rtc->asTextureProxy() ? GrMipMapped::kYes == rtc->asTextureProxy()->mipMapped()
  164. : false;
  165. SkColorType ct = GrColorTypeToSkColorType(rtc->colorSpaceInfo().colorType());
  166. if (ct == kUnknown_SkColorType) {
  167. return false;
  168. }
  169. bool usesGLFBO0 = rtc->asRenderTargetProxy()->rtPriv().glRTFBOIDIs0();
  170. // We should never get in the situation where we have a texture render target that is also
  171. // backend by FBO 0.
  172. SkASSERT(!usesGLFBO0 || !SkToBool(rtc->asTextureProxy()));
  173. SkImageInfo ii = SkImageInfo::Make(rtc->width(), rtc->height(), ct, kPremul_SkAlphaType,
  174. rtc->colorSpaceInfo().refColorSpace());
  175. GrBackendFormat format = rtc->asSurfaceProxy()->backendFormat();
  176. characterization->set(ctx->threadSafeProxy(), maxResourceBytes, ii, format,
  177. rtc->origin(), rtc->numSamples(),
  178. SkSurfaceCharacterization::Textureable(SkToBool(rtc->asTextureProxy())),
  179. SkSurfaceCharacterization::MipMapped(mipmapped),
  180. SkSurfaceCharacterization::UsesGLFBO0(usesGLFBO0),
  181. SkSurfaceCharacterization::VulkanSecondaryCBCompatible(false),
  182. GrProtected(rtc->asRenderTargetProxy()->isProtected()),
  183. this->props());
  184. return true;
  185. }
  186. void SkSurface_Gpu::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) {
  187. // If the dst is also GPU we try to not force a new image snapshot (by calling the base class
  188. // onDraw) since that may not always perform the copy-on-write optimization.
  189. auto tryDraw = [&] {
  190. SkASSERT(fDevice->context()->priv().asDirectContext());
  191. GrContext* context = fDevice->context();
  192. GrContext* canvasContext = canvas->getGrContext();
  193. if (!canvasContext) {
  194. return false;
  195. }
  196. if (!canvasContext->priv().asDirectContext() ||
  197. canvasContext->priv().contextID() != context->priv().contextID()) {
  198. return false;
  199. }
  200. GrRenderTargetContext* rtc = fDevice->accessRenderTargetContext();
  201. if (!rtc) {
  202. return false;
  203. }
  204. sk_sp<GrTextureProxy> srcProxy = rtc->asTextureProxyRef();
  205. if (!srcProxy) {
  206. return false;
  207. }
  208. // Possibly we could skip making an image here if SkGpuDevice exposed a lower level way
  209. // of drawing a texture proxy.
  210. const SkImageInfo info = fDevice->imageInfo();
  211. sk_sp<SkImage> image;
  212. image = sk_make_sp<SkImage_Gpu>(sk_ref_sp(context), kNeedNewImageUniqueID, info.alphaType(),
  213. std::move(srcProxy), info.refColorSpace());
  214. canvas->drawImage(image, x, y, paint);
  215. return true;
  216. };
  217. if (!tryDraw()) {
  218. INHERITED::onDraw(canvas, x, y, paint);
  219. }
  220. }
  221. bool SkSurface_Gpu::onIsCompatible(const SkSurfaceCharacterization& characterization) const {
  222. GrRenderTargetContext* rtc = fDevice->accessRenderTargetContext();
  223. GrContext* ctx = fDevice->context();
  224. if (!characterization.isValid()) {
  225. return false;
  226. }
  227. if (characterization.vulkanSecondaryCBCompatible()) {
  228. return false;
  229. }
  230. // As long as the current state if the context allows for greater or equal resources,
  231. // we allow the DDL to be replayed.
  232. // DDL TODO: should we just remove the resource check and ignore the cache limits on playback?
  233. int maxResourceCount;
  234. size_t maxResourceBytes;
  235. ctx->getResourceCacheLimits(&maxResourceCount, &maxResourceBytes);
  236. if (characterization.isTextureable()) {
  237. if (!rtc->asTextureProxy()) {
  238. // If the characterization was textureable we require the replay dest to also be
  239. // textureable. If the characterized surface wasn't textureable we allow the replay
  240. // dest to be textureable.
  241. return false;
  242. }
  243. if (characterization.isMipMapped() &&
  244. GrMipMapped::kNo == rtc->asTextureProxy()->mipMapped()) {
  245. // Fail if the DDL's surface was mipmapped but the replay surface is not.
  246. // Allow drawing to proceed if the DDL was not mipmapped but the replay surface is.
  247. return false;
  248. }
  249. }
  250. if (characterization.usesGLFBO0() != rtc->asRenderTargetProxy()->rtPriv().glRTFBOIDIs0()) {
  251. return false;
  252. }
  253. SkColorType rtcColorType = GrColorTypeToSkColorType(rtc->colorSpaceInfo().colorType());
  254. if (rtcColorType == kUnknown_SkColorType) {
  255. return false;
  256. }
  257. GrProtected isProtected = GrProtected(rtc->asSurfaceProxy()->isProtected());
  258. return characterization.contextInfo() && characterization.contextInfo()->priv().matches(ctx) &&
  259. characterization.cacheMaxResourceBytes() <= maxResourceBytes &&
  260. characterization.origin() == rtc->origin() &&
  261. characterization.backendFormat() == rtc->asSurfaceProxy()->backendFormat() &&
  262. characterization.width() == rtc->width() &&
  263. characterization.height() == rtc->height() &&
  264. characterization.colorType() == rtcColorType &&
  265. characterization.sampleCount() == rtc->numSamples() &&
  266. SkColorSpace::Equals(characterization.colorSpace(),
  267. rtc->colorSpaceInfo().colorSpace()) &&
  268. characterization.isProtected() == isProtected &&
  269. characterization.surfaceProps() == rtc->surfaceProps();
  270. }
  271. bool SkSurface_Gpu::onDraw(const SkDeferredDisplayList* ddl) {
  272. if (!ddl || !this->isCompatible(ddl->characterization())) {
  273. return false;
  274. }
  275. GrRenderTargetContext* rtc = fDevice->accessRenderTargetContext();
  276. GrContext* ctx = fDevice->context();
  277. ctx->priv().copyOpListsFromDDL(ddl, rtc->asRenderTargetProxy());
  278. return true;
  279. }
  280. ///////////////////////////////////////////////////////////////////////////////
  281. bool SkSurface_Gpu::Valid(const GrCaps* caps, const GrBackendFormat& format) {
  282. if (caps->isFormatSRGB(format)) {
  283. return caps->srgbSupport();
  284. }
  285. return true;
  286. }
  287. sk_sp<SkSurface> SkSurface::MakeRenderTarget(GrRecordingContext* context,
  288. const SkSurfaceCharacterization& c,
  289. SkBudgeted budgeted) {
  290. if (!context || !c.isValid()) {
  291. return nullptr;
  292. }
  293. const GrCaps* caps = context->priv().caps();
  294. if (c.usesGLFBO0()) {
  295. // If we are making the surface we will never use FBO0.
  296. return nullptr;
  297. }
  298. if (c.vulkanSecondaryCBCompatible()) {
  299. return nullptr;
  300. }
  301. if (!SkSurface_Gpu::Valid(caps, c.backendFormat())) {
  302. return nullptr;
  303. }
  304. GrColorType grColorType = SkColorTypeToGrColorType(c.colorType());
  305. sk_sp<GrRenderTargetContext> rtc(context->priv().makeDeferredRenderTargetContext(
  306. SkBackingFit::kExact,
  307. c.width(),
  308. c.height(),
  309. grColorType,
  310. c.refColorSpace(),
  311. c.sampleCount(),
  312. GrMipMapped(c.isMipMapped()),
  313. c.origin(),
  314. &c.surfaceProps(),
  315. budgeted,
  316. c.isProtected()));
  317. if (!rtc) {
  318. return nullptr;
  319. }
  320. // CONTEXT TODO: remove this use of 'backdoor' to create an SkGpuDevice
  321. sk_sp<SkGpuDevice> device(SkGpuDevice::Make(context->priv().backdoor(), std::move(rtc),
  322. c.width(), c.height(),
  323. SkGpuDevice::kClear_InitContents));
  324. if (!device) {
  325. return nullptr;
  326. }
  327. sk_sp<SkSurface> result = sk_make_sp<SkSurface_Gpu>(std::move(device));
  328. #ifdef SK_DEBUG
  329. if (result) {
  330. SkASSERT(result->isCompatible(c));
  331. }
  332. #endif
  333. return result;
  334. }
  335. static bool validate_backend_texture(GrContext* ctx, const GrBackendTexture& tex,
  336. GrPixelConfig* config, int sampleCnt, GrColorType grCT,
  337. bool texturable) {
  338. if (!tex.isValid()) {
  339. return false;
  340. }
  341. GrBackendFormat backendFormat = tex.getBackendFormat();
  342. if (!backendFormat.isValid()) {
  343. return false;
  344. }
  345. if (!ctx->priv().caps()->areColorTypeAndFormatCompatible(grCT, backendFormat)) {
  346. return false;
  347. }
  348. *config = ctx->priv().caps()->getConfigFromBackendFormat(backendFormat, grCT);
  349. if (*config == kUnknown_GrPixelConfig) {
  350. return false;
  351. }
  352. // We don't require that the client gave us an exact valid sample cnt. However, it must be
  353. // less than the max supported sample count and 1 if MSAA is unsupported for the color type.
  354. if (!ctx->priv().caps()->getRenderTargetSampleCount(sampleCnt, grCT, backendFormat)) {
  355. return false;
  356. }
  357. if (texturable && !ctx->priv().caps()->isFormatTexturable(grCT, backendFormat)) {
  358. return false;
  359. }
  360. return true;
  361. }
  362. sk_sp<SkSurface> SkSurface::MakeFromBackendTexture(GrContext* context,
  363. const SkSurfaceCharacterization& c,
  364. const GrBackendTexture& backendTexture,
  365. TextureReleaseProc textureReleaseProc,
  366. ReleaseContext releaseContext) {
  367. if (!context || !c.isValid()) {
  368. return nullptr;
  369. }
  370. if (c.usesGLFBO0()) {
  371. // If we are making the surface we will never use FBO0.
  372. return nullptr;
  373. }
  374. if (!c.isCompatible(backendTexture)) {
  375. return nullptr;
  376. }
  377. GrColorType grCT = SkColorTypeAndFormatToGrColorType(context->priv().caps(), c.colorType(),
  378. backendTexture.getBackendFormat());
  379. if (grCT == GrColorType::kUnknown) {
  380. return nullptr;
  381. }
  382. GrBackendTexture texCopy = backendTexture;
  383. if (!validate_backend_texture(context, texCopy, &texCopy.fConfig,
  384. c.sampleCount(), grCT, true)) {
  385. return nullptr;
  386. }
  387. if (!SkSurface_Gpu::Valid(context->priv().caps(), texCopy.getBackendFormat())) {
  388. return nullptr;
  389. }
  390. sk_sp<GrRenderTargetContext> rtc(context->priv().makeBackendTextureRenderTargetContext(
  391. texCopy, c.origin(), c.sampleCount(), grCT,
  392. c.refColorSpace(), &c.surfaceProps(), textureReleaseProc, releaseContext));
  393. if (!rtc) {
  394. return nullptr;
  395. }
  396. sk_sp<SkGpuDevice> device(SkGpuDevice::Make(context, std::move(rtc),
  397. texCopy.width(), texCopy.height(),
  398. SkGpuDevice::kUninit_InitContents));
  399. if (!device) {
  400. return nullptr;
  401. }
  402. sk_sp<SkSurface> result = sk_make_sp<SkSurface_Gpu>(std::move(device));
  403. #ifdef SK_DEBUG
  404. if (result) {
  405. SkASSERT(result->isCompatible(c));
  406. }
  407. #endif
  408. return result;
  409. }
  410. sk_sp<SkSurface> SkSurface::MakeRenderTarget(GrContext* ctx, SkBudgeted budgeted,
  411. const SkImageInfo& info, int sampleCount,
  412. GrSurfaceOrigin origin, const SkSurfaceProps* props,
  413. bool shouldCreateWithMips) {
  414. if (!ctx) {
  415. return nullptr;
  416. }
  417. sampleCount = SkTMax(1, sampleCount);
  418. GrMipMapped mipMapped = shouldCreateWithMips ? GrMipMapped::kYes : GrMipMapped::kNo;
  419. if (!ctx->priv().caps()->mipMapSupport()) {
  420. mipMapped = GrMipMapped::kNo;
  421. }
  422. sk_sp<SkGpuDevice> device(SkGpuDevice::Make(
  423. ctx, budgeted, info, sampleCount, origin, props, mipMapped,
  424. SkGpuDevice::kClear_InitContents));
  425. if (!device) {
  426. return nullptr;
  427. }
  428. return sk_make_sp<SkSurface_Gpu>(std::move(device));
  429. }
  430. sk_sp<SkSurface> SkSurface_Gpu::MakeWrappedRenderTarget(GrContext* context,
  431. sk_sp<GrRenderTargetContext> rtc) {
  432. if (!context) {
  433. return nullptr;
  434. }
  435. int w = rtc->width();
  436. int h = rtc->height();
  437. sk_sp<SkGpuDevice> device(
  438. SkGpuDevice::Make(context, std::move(rtc), w, h, SkGpuDevice::kUninit_InitContents));
  439. if (!device) {
  440. return nullptr;
  441. }
  442. return sk_make_sp<SkSurface_Gpu>(std::move(device));
  443. }
  444. sk_sp<SkSurface> SkSurface::MakeFromBackendTexture(GrContext* context, const GrBackendTexture& tex,
  445. GrSurfaceOrigin origin, int sampleCnt,
  446. SkColorType colorType,
  447. sk_sp<SkColorSpace> colorSpace,
  448. const SkSurfaceProps* props,
  449. SkSurface::TextureReleaseProc textureReleaseProc,
  450. SkSurface::ReleaseContext releaseContext) {
  451. if (!context) {
  452. return nullptr;
  453. }
  454. sampleCnt = SkTMax(1, sampleCnt);
  455. GrColorType grColorType = SkColorTypeAndFormatToGrColorType(context->priv().caps(), colorType,
  456. tex.getBackendFormat());
  457. if (grColorType == GrColorType::kUnknown) {
  458. return nullptr;
  459. }
  460. GrBackendTexture texCopy = tex;
  461. if (!validate_backend_texture(context, texCopy, &texCopy.fConfig, sampleCnt, grColorType,
  462. true)) {
  463. return nullptr;
  464. }
  465. if (!context) {
  466. return nullptr;
  467. }
  468. if (!SkSurface_Gpu::Valid(context->priv().caps(), texCopy.getBackendFormat())) {
  469. return nullptr;
  470. }
  471. sk_sp<GrRenderTargetContext> rtc(context->priv().makeBackendTextureRenderTargetContext(
  472. texCopy, origin, sampleCnt, grColorType, std::move(colorSpace), props,
  473. textureReleaseProc, releaseContext));
  474. if (!rtc) {
  475. return nullptr;
  476. }
  477. sk_sp<SkGpuDevice> device(SkGpuDevice::Make(context, std::move(rtc), texCopy.width(),
  478. texCopy.height(),
  479. SkGpuDevice::kUninit_InitContents));
  480. if (!device) {
  481. return nullptr;
  482. }
  483. return sk_make_sp<SkSurface_Gpu>(std::move(device));
  484. }
  485. bool SkSurface_Gpu::onReplaceBackendTexture(const GrBackendTexture& backendTexture,
  486. GrSurfaceOrigin origin, TextureReleaseProc releaseProc,
  487. ReleaseContext releaseContext) {
  488. auto context = this->fDevice->context();
  489. if (context->abandoned()) {
  490. return false;
  491. }
  492. if (!backendTexture.isValid()) {
  493. return false;
  494. }
  495. if (backendTexture.width() != this->width() || backendTexture.height() != this->height()) {
  496. return false;
  497. }
  498. auto* oldRTC = fDevice->accessRenderTargetContext();
  499. auto oldProxy = sk_ref_sp(oldRTC->asTextureProxy());
  500. if (!oldProxy) {
  501. return false;
  502. }
  503. auto* oldTexture = oldProxy->peekTexture();
  504. if (!oldTexture) {
  505. return false;
  506. }
  507. if (!oldTexture->resourcePriv().refsWrappedObjects()) {
  508. return false;
  509. }
  510. if (oldTexture->backendFormat() != backendTexture.getBackendFormat()) {
  511. return false;
  512. }
  513. if (oldTexture->getBackendTexture().isSameTexture(backendTexture)) {
  514. return false;
  515. }
  516. SkASSERT(oldTexture->asRenderTarget());
  517. int sampleCnt = oldTexture->asRenderTarget()->numSamples();
  518. GrBackendTexture texCopy = backendTexture;
  519. GrColorType grColorType = SkColorTypeToGrColorType(this->getCanvas()->imageInfo().colorType());
  520. auto colorSpace = sk_ref_sp(oldRTC->colorSpaceInfo().colorSpace());
  521. if (!validate_backend_texture(context, texCopy, &texCopy.fConfig, sampleCnt, grColorType,
  522. true)) {
  523. return false;
  524. }
  525. sk_sp<GrRenderTargetContext> rtc(context->priv().makeBackendTextureRenderTargetContext(
  526. texCopy,
  527. origin,
  528. sampleCnt,
  529. oldRTC->colorSpaceInfo().colorType(),
  530. std::move(colorSpace),
  531. &this->props(),
  532. releaseProc,
  533. releaseContext));
  534. if (!rtc) {
  535. return false;
  536. }
  537. fDevice->replaceRenderTargetContext(std::move(rtc), true);
  538. return true;
  539. }
  540. bool validate_backend_render_target(const GrCaps* caps, const GrBackendRenderTarget& rt,
  541. GrPixelConfig* config, GrColorType grCT) {
  542. if (!caps->areColorTypeAndFormatCompatible(grCT, rt.getBackendFormat())) {
  543. return false;
  544. }
  545. *config = caps->validateBackendRenderTarget(rt, grCT);
  546. if (*config == kUnknown_GrPixelConfig) {
  547. return false;
  548. }
  549. if (rt.sampleCnt() > 1) {
  550. if (caps->maxRenderTargetSampleCount(grCT, rt.getBackendFormat()) <= 1) {
  551. return false;
  552. }
  553. } else if (!caps->isFormatRenderable(grCT, rt.getBackendFormat())) {
  554. return false;
  555. }
  556. return true;
  557. }
  558. sk_sp<SkSurface> SkSurface::MakeFromBackendRenderTarget(GrContext* context,
  559. const GrBackendRenderTarget& rt,
  560. GrSurfaceOrigin origin,
  561. SkColorType colorType,
  562. sk_sp<SkColorSpace> colorSpace,
  563. const SkSurfaceProps* props,
  564. SkSurface::RenderTargetReleaseProc relProc,
  565. SkSurface::ReleaseContext releaseContext) {
  566. if (!context) {
  567. return nullptr;
  568. }
  569. GrColorType grColorType = SkColorTypeAndFormatToGrColorType(context->priv().caps(), colorType,
  570. rt.getBackendFormat());
  571. if (grColorType == GrColorType::kUnknown) {
  572. return nullptr;
  573. }
  574. GrBackendRenderTarget rtCopy = rt;
  575. if (!validate_backend_render_target(context->priv().caps(), rtCopy,
  576. &rtCopy.fConfig, grColorType)) {
  577. return nullptr;
  578. }
  579. if (!SkSurface_Gpu::Valid(context->priv().caps(), rtCopy.getBackendFormat())) {
  580. return nullptr;
  581. }
  582. if (!context) {
  583. return nullptr;
  584. }
  585. sk_sp<GrRenderTargetContext> rtc(context->priv().makeBackendRenderTargetRenderTargetContext(
  586. rtCopy, origin, grColorType, std::move(colorSpace), props, relProc, releaseContext));
  587. if (!rtc) {
  588. return nullptr;
  589. }
  590. sk_sp<SkGpuDevice> device(SkGpuDevice::Make(context, std::move(rtc), rtCopy.width(),
  591. rtCopy.height(),
  592. SkGpuDevice::kUninit_InitContents));
  593. if (!device) {
  594. return nullptr;
  595. }
  596. return sk_make_sp<SkSurface_Gpu>(std::move(device));
  597. }
  598. sk_sp<SkSurface> SkSurface::MakeFromBackendTextureAsRenderTarget(GrContext* context,
  599. const GrBackendTexture& tex,
  600. GrSurfaceOrigin origin,
  601. int sampleCnt,
  602. SkColorType colorType,
  603. sk_sp<SkColorSpace> colorSpace,
  604. const SkSurfaceProps* props) {
  605. if (!context) {
  606. return nullptr;
  607. }
  608. sampleCnt = SkTMax(1, sampleCnt);
  609. GrColorType grColorType = SkColorTypeAndFormatToGrColorType(context->priv().caps(), colorType,
  610. tex.getBackendFormat());
  611. if (grColorType == GrColorType::kUnknown) {
  612. return nullptr;
  613. }
  614. GrBackendTexture texCopy = tex;
  615. if (!validate_backend_texture(context, texCopy, &texCopy.fConfig,
  616. sampleCnt, grColorType, false)) {
  617. return nullptr;
  618. }
  619. if (!SkSurface_Gpu::Valid(context->priv().caps(), texCopy.getBackendFormat())) {
  620. return nullptr;
  621. }
  622. sk_sp<GrRenderTargetContext> rtc(
  623. context->priv().makeBackendTextureAsRenderTargetRenderTargetContext(
  624. texCopy,
  625. origin,
  626. sampleCnt,
  627. grColorType,
  628. std::move(colorSpace),
  629. props));
  630. if (!rtc) {
  631. return nullptr;
  632. }
  633. sk_sp<SkGpuDevice> device(SkGpuDevice::Make(context, std::move(rtc), tex.width(), tex.height(),
  634. SkGpuDevice::kUninit_InitContents));
  635. if (!device) {
  636. return nullptr;
  637. }
  638. return sk_make_sp<SkSurface_Gpu>(std::move(device));
  639. }
  640. #if defined(SK_BUILD_FOR_ANDROID) && __ANDROID_API__ >= 26
  641. sk_sp<SkSurface> SkSurface::MakeFromAHardwareBuffer(GrContext* context,
  642. AHardwareBuffer* hardwareBuffer,
  643. GrSurfaceOrigin origin,
  644. sk_sp<SkColorSpace> colorSpace,
  645. const SkSurfaceProps* surfaceProps) {
  646. AHardwareBuffer_Desc bufferDesc;
  647. AHardwareBuffer_describe(hardwareBuffer, &bufferDesc);
  648. if (!SkToBool(bufferDesc.usage & AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT)) {
  649. return nullptr;
  650. }
  651. bool isTextureable = SkToBool(bufferDesc.usage & AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE);
  652. bool isProtectedContent = SkToBool(bufferDesc.usage & AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT);
  653. // We currently don't support protected content
  654. if (isProtectedContent) {
  655. SkDebugf("We currently don't support protected content on android\n");
  656. return nullptr;
  657. }
  658. GrBackendFormat backendFormat = GrAHardwareBufferUtils::GetBackendFormat(context,
  659. hardwareBuffer,
  660. bufferDesc.format,
  661. true);
  662. if (!backendFormat.isValid()) {
  663. return nullptr;
  664. }
  665. if (isTextureable) {
  666. GrAHardwareBufferUtils::DeleteImageProc deleteImageProc = nullptr;
  667. GrAHardwareBufferUtils::DeleteImageCtx deleteImageCtx = nullptr;
  668. GrBackendTexture backendTexture =
  669. GrAHardwareBufferUtils::MakeBackendTexture(context, hardwareBuffer,
  670. bufferDesc.width, bufferDesc.height,
  671. &deleteImageProc, &deleteImageCtx,
  672. isProtectedContent, backendFormat,
  673. true);
  674. if (!backendTexture.isValid()) {
  675. return nullptr;
  676. }
  677. SkColorType colorType =
  678. GrAHardwareBufferUtils::GetSkColorTypeFromBufferFormat(bufferDesc.format);
  679. sk_sp<SkSurface> surface = SkSurface::MakeFromBackendTexture(context, backendTexture,
  680. origin, 0, colorType, std::move(colorSpace), surfaceProps, deleteImageProc,
  681. deleteImageCtx);
  682. if (!surface) {
  683. SkASSERT(deleteImageProc);
  684. deleteImageProc(deleteImageCtx);
  685. }
  686. return surface;
  687. } else {
  688. return nullptr;
  689. }
  690. }
  691. #endif
  692. #endif