blob: 623c54eab02de962bda31ff02da4d8d81dc82035 [file] [log] [blame]
reed@google.com5d4ba882012-07-31 15:45:27 +00001/*
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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "include/core/SkCanvas.h"
9#include "include/core/SkSurfaceCharacterization.h"
10#include "include/gpu/GrBackendSurface.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050011#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"
Brian Salomon201cdbb2019-08-14 17:00:30 -040020#include "src/gpu/GrRenderTarget.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050021#include "src/gpu/GrRenderTargetContextPriv.h"
22#include "src/gpu/GrRenderTargetProxyPriv.h"
23#include "src/gpu/SkGpuDevice.h"
24#include "src/image/SkImage_Base.h"
25#include "src/image/SkImage_Gpu.h"
26#include "src/image/SkSurface_Base.h"
27#include "src/image/SkSurface_Gpu.h"
reed@google.com5d4ba882012-07-31 15:45:27 +000028
reedf037e0b2014-10-30 11:34:15 -070029#if SK_SUPPORT_GPU
30
robertphillips24e91282016-04-29 06:46:36 -070031SkSurface_Gpu::SkSurface_Gpu(sk_sp<SkGpuDevice> device)
bsalomonafe30052015-01-16 07:32:33 -080032 : INHERITED(device->width(), device->height(), &device->surfaceProps())
robertphillips24e91282016-04-29 06:46:36 -070033 , fDevice(std::move(device)) {
Robert Phillips0ae6faa2017-03-21 16:22:00 -040034 SkASSERT(fDevice->accessRenderTargetContext()->asSurfaceProxy()->priv().isExact());
robertphillips@google.com97b6b072012-10-31 14:48:39 +000035}
reed@google.com5d4ba882012-07-31 15:45:27 +000036
robertphillips@google.com97b6b072012-10-31 14:48:39 +000037SkSurface_Gpu::~SkSurface_Gpu() {
reed@google.com5d4ba882012-07-31 15:45:27 +000038}
39
joshualitt81793412015-07-08 12:54:04 -070040static GrRenderTarget* prepare_rt_for_external_access(SkSurface_Gpu* surface,
41 SkSurface::BackendHandleAccess access) {
reedfa5e68e2015-06-29 07:37:01 -070042 switch (access) {
joshualitt81793412015-07-08 12:54:04 -070043 case SkSurface::kFlushRead_BackendHandleAccess:
reedfa5e68e2015-06-29 07:37:01 -070044 break;
joshualitt81793412015-07-08 12:54:04 -070045 case SkSurface::kFlushWrite_BackendHandleAccess:
46 case SkSurface::kDiscardWrite_BackendHandleAccess:
reed884200e2015-06-29 09:00:20 -070047 // for now we don't special-case on Discard, but we may in the future.
joshualitt81793412015-07-08 12:54:04 -070048 surface->notifyContentWillChange(SkSurface::kRetain_ContentChangeMode);
reedfa5e68e2015-06-29 07:37:01 -070049 break;
reedfa5e68e2015-06-29 07:37:01 -070050 }
fmalitae2639082015-08-06 07:04:51 -070051
52 // Grab the render target *after* firing notifications, as it may get switched if CoW kicks in.
Greg Daniele6bfb7d2019-04-17 15:26:11 -040053 surface->getDevice()->flush(SkSurface::BackendSurfaceAccess::kNoAccess, GrFlushInfo());
Brian Osman11052242016-10-27 14:47:55 -040054 GrRenderTargetContext* rtc = surface->getDevice()->accessRenderTargetContext();
55 return rtc->accessRenderTarget();
joshualitt81793412015-07-08 12:54:04 -070056}
57
Robert Phillips8caf85f2018-04-05 09:30:38 -040058GrBackendTexture SkSurface_Gpu::onGetBackendTexture(BackendHandleAccess access) {
59 GrRenderTarget* rt = prepare_rt_for_external_access(this, access);
60 if (!rt) {
61 return GrBackendTexture(); // invalid
62 }
63 GrTexture* texture = rt->asTexture();
64 if (texture) {
65 return texture->getBackendTexture();
66 }
67 return GrBackendTexture(); // invalid
68}
69
70GrBackendRenderTarget SkSurface_Gpu::onGetBackendRenderTarget(BackendHandleAccess access) {
71 GrRenderTarget* rt = prepare_rt_for_external_access(this, access);
72 if (!rt) {
73 return GrBackendRenderTarget(); // invalid
74 }
75
76 return rt->getBackendRenderTarget();
77}
78
Hal Canary363a3f82018-10-04 11:04:48 -040079SkCanvas* SkSurface_Gpu::onNewCanvas() { return new SkCanvas(fDevice); }
reed@google.com5d4ba882012-07-31 15:45:27 +000080
reede8f30622016-03-23 18:59:25 -070081sk_sp<SkSurface> SkSurface_Gpu::onNewSurface(const SkImageInfo& info) {
Chris Dalton6ce447a2019-06-23 18:07:38 -060082 int sampleCount = fDevice->accessRenderTargetContext()->numSamples();
Brian Osman11052242016-10-27 14:47:55 -040083 GrSurfaceOrigin origin = fDevice->accessRenderTargetContext()->origin();
bsalomonafe30052015-01-16 07:32:33 -080084 // TODO: Make caller specify this (change virtual signature of onNewSurface).
bsalomon5ec26ae2016-02-25 08:33:02 -080085 static const SkBudgeted kBudgeted = SkBudgeted::kNo;
reede8f30622016-03-23 18:59:25 -070086 return SkSurface::MakeRenderTarget(fDevice->context(), kBudgeted, info, sampleCount,
robertphillips7e922762016-07-26 11:38:17 -070087 origin, &this->props());
reed@google.com5d4ba882012-07-31 15:45:27 +000088}
89
Mike Reed114bde82018-11-21 09:12:09 -050090sk_sp<SkImage> SkSurface_Gpu::onNewImageSnapshot(const SkIRect* subset) {
Robert Phillipse2f7d182016-12-15 09:23:05 -050091 GrRenderTargetContext* rtc = fDevice->accessRenderTargetContext();
92 if (!rtc) {
Robert Phillipse60ad622016-11-17 10:22:48 -050093 return nullptr;
94 }
95
Robert Phillipse2f7d182016-12-15 09:23:05 -050096 GrContext* ctx = fDevice->context();
97
Robert Phillips0ae6faa2017-03-21 16:22:00 -040098 if (!rtc->asSurfaceProxy()) {
99 return nullptr;
100 }
101
102 SkBudgeted budgeted = rtc->asSurfaceProxy()->isBudgeted();
103
104 sk_sp<GrTextureProxy> srcProxy = rtc->asTextureProxyRef();
Mike Reed114bde82018-11-21 09:12:09 -0500105
106 if (subset) {
Brian Salomon078e8fa2019-11-22 04:10:18 +0000107 srcProxy = GrSurfaceProxy::Copy(ctx, rtc->asSurfaceProxy(), rtc->colorInfo().colorType(),
108 rtc->mipMapped(), *subset, SkBackingFit::kExact, budgeted);
Mike Reed114bde82018-11-21 09:12:09 -0500109 } else if (!srcProxy || rtc->priv().refsWrappedObjects()) {
110 // If the original render target is a buffer originally created by the client, then we don't
111 // want to ever retarget the SkSurface at another buffer we create. Force a copy now to avoid
112 // copy-on-write.
Robert Phillips81dd3e02017-06-23 11:59:24 -0400113 SkASSERT(rtc->origin() == rtc->asSurfaceProxy()->origin());
Robert Phillipse2f7d182016-12-15 09:23:05 -0500114
Brian Salomon078e8fa2019-11-22 04:10:18 +0000115 srcProxy = GrSurfaceProxy::Copy(ctx, rtc->asSurfaceProxy(), rtc->colorInfo().colorType(),
116 rtc->mipMapped(), SkBackingFit::kExact, budgeted);
bsalomonf47b9a32016-02-22 11:02:58 -0800117 }
Robert Phillipse2f7d182016-12-15 09:23:05 -0500118
reed8b26b992015-05-07 15:36:17 -0700119 const SkImageInfo info = fDevice->imageInfo();
reede8f30622016-03-23 18:59:25 -0700120 sk_sp<SkImage> image;
Robert Phillips0ae6faa2017-03-21 16:22:00 -0400121 if (srcProxy) {
122 // The renderTargetContext coming out of SkGpuDevice should always be exact and the
123 // above copy creates a kExact surfaceContext.
124 SkASSERT(srcProxy->priv().isExact());
Brian Salomon729fc0c2019-09-30 16:33:11 +0000125 image = sk_make_sp<SkImage_Gpu>(sk_ref_sp(ctx), kNeedNewImageUniqueID, info.alphaType(),
126 std::move(srcProxy), info.refColorSpace());
reed8b26b992015-05-07 15:36:17 -0700127 }
reed4af267b2014-11-21 08:46:37 -0800128 return image;
reed@google.com5d4ba882012-07-31 15:45:27 +0000129}
130
Mike Reed4c790bd2018-02-08 14:10:40 -0500131void SkSurface_Gpu::onWritePixels(const SkPixmap& src, int x, int y) {
132 fDevice->writePixels(src, x, y);
133}
134
Brian Salomon9241a6d2019-10-03 13:26:54 -0400135void SkSurface_Gpu::onAsyncRescaleAndReadPixels(const SkImageInfo& info,
136 const SkIRect& srcRect,
Brian Salomon024bd002019-06-11 11:38:16 -0400137 RescaleGamma rescaleGamma,
Brian Salomon031b0ba2019-05-23 11:05:26 -0400138 SkFilterQuality rescaleQuality,
Brian Salomon024bd002019-06-11 11:38:16 -0400139 ReadPixelsCallback callback,
140 ReadPixelsContext context) {
141 auto* rtc = this->fDevice->accessRenderTargetContext();
Brian Salomon031b0ba2019-05-23 11:05:26 -0400142 rtc->asyncRescaleAndReadPixels(info, srcRect, rescaleGamma, rescaleQuality, callback, context);
Brian Salomonab32f652019-05-10 14:24:50 -0400143}
144
Brian Salomon9241a6d2019-10-03 13:26:54 -0400145void SkSurface_Gpu::onAsyncRescaleAndReadPixelsYUV420(SkYUVColorSpace yuvColorSpace,
146 sk_sp<SkColorSpace> dstColorSpace,
147 const SkIRect& srcRect,
148 const SkISize& dstSize,
149 RescaleGamma rescaleGamma,
150 SkFilterQuality rescaleQuality,
151 ReadPixelsCallback callback,
152 ReadPixelsContext context) {
Brian Salomon024bd002019-06-11 11:38:16 -0400153 auto* rtc = this->fDevice->accessRenderTargetContext();
Brian Salomon9241a6d2019-10-03 13:26:54 -0400154 rtc->asyncRescaleAndReadPixelsYUV420(yuvColorSpace,
155 std::move(dstColorSpace),
156 srcRect,
157 dstSize,
158 rescaleGamma,
159 rescaleQuality,
160 callback,
161 context);
Brian Salomon024bd002019-06-11 11:38:16 -0400162}
163
kkinnunenabcfab42015-02-22 22:53:44 -0800164// Create a new render target and, if necessary, copy the contents of the old
165// render target into it. Note that this flushes the SkGpuDevice but
robertphillips@google.com97b6b072012-10-31 14:48:39 +0000166// doesn't force an OpenGL flush.
commit-bot@chromium.orgc4c98702013-04-22 14:28:01 +0000167void SkSurface_Gpu::onCopyOnWrite(ContentChangeMode mode) {
Robert Phillips602b79c2017-06-23 11:26:28 -0400168 GrRenderTargetContext* rtc = fDevice->accessRenderTargetContext();
169
170 // are we sharing our backing proxy with the image? Note this call should never create a new
bsalomoneaaaf0b2015-01-23 08:08:04 -0800171 // image because onCopyOnWrite is only called when there is a cached image.
Robert Phillipsac6b1fa2017-03-20 08:38:50 -0400172 sk_sp<SkImage> image(this->refCachedImage());
bsalomoneaaaf0b2015-01-23 08:08:04 -0800173 SkASSERT(image);
Robert Phillips602b79c2017-06-23 11:26:28 -0400174
175 GrSurfaceProxy* imageProxy = ((SkImage_Base*) image.get())->peekProxy();
176 SkASSERT(imageProxy);
177
178 if (rtc->asSurfaceProxy()->underlyingUniqueID() == imageProxy->underlyingUniqueID()) {
Robert Phillips6de99042017-01-31 11:31:39 -0500179 fDevice->replaceRenderTargetContext(SkSurface::kRetain_ContentChangeMode == mode);
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000180 } else if (kDiscard_ContentChangeMode == mode) {
181 this->SkSurface_Gpu::onDiscard();
robertphillips@google.com97b6b072012-10-31 14:48:39 +0000182 }
reed@google.com5d4ba882012-07-31 15:45:27 +0000183}
184
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000185void SkSurface_Gpu::onDiscard() {
Brian Osman11052242016-10-27 14:47:55 -0400186 fDevice->accessRenderTargetContext()->discard();
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000187}
188
Greg Daniele6bfb7d2019-04-17 15:26:11 -0400189GrSemaphoresSubmitted SkSurface_Gpu::onFlush(BackendSurfaceAccess access,
190 const GrFlushInfo& info) {
191 return fDevice->flush(access, info);
Greg Daniela5cb7812017-06-16 09:45:32 -0400192}
193
Greg Danielc64ee462017-06-15 16:59:49 -0400194bool SkSurface_Gpu::onWait(int numSemaphores, const GrBackendSemaphore* waitSemaphores) {
195 return fDevice->wait(numSemaphores, waitSemaphores);
ericrkf7b8b8a2016-02-24 14:49:51 -0800196}
197
Robert Phillipsbe77a022018-04-03 17:17:05 -0400198bool SkSurface_Gpu::onCharacterize(SkSurfaceCharacterization* characterization) const {
Robert Phillipsad8a43f2017-08-30 12:06:35 -0400199 GrRenderTargetContext* rtc = fDevice->accessRenderTargetContext();
Robert Phillips8def8bf2017-11-30 08:46:03 -0500200 GrContext* ctx = fDevice->context();
Robert Phillipsad8a43f2017-08-30 12:06:35 -0400201
Robert Phillipscf39f372019-09-03 10:29:20 -0400202 size_t maxResourceBytes = ctx->getResourceCacheLimit();
Robert Phillips8d1e67e2017-12-04 13:48:14 -0500203
Robert Phillipse8fabb22018-02-04 14:33:21 -0500204 bool mipmapped = rtc->asTextureProxy() ? GrMipMapped::kYes == rtc->asTextureProxy()->mipMapped()
205 : false;
206
Brian Salomon4bc0c1f2019-09-30 15:12:27 -0400207 SkColorType ct = GrColorTypeToSkColorType(rtc->colorInfo().colorType());
Brian Salomonbd3d8d32019-07-02 09:16:28 -0400208 if (ct == kUnknown_SkColorType) {
Robert Phillipsbe77a022018-04-03 17:17:05 -0400209 return false;
210 }
211
Greg Daniela070ed72018-04-26 16:31:38 -0400212 bool usesGLFBO0 = rtc->asRenderTargetProxy()->rtPriv().glRTFBOIDIs0();
213 // We should never get in the situation where we have a texture render target that is also
214 // backend by FBO 0.
215 SkASSERT(!usesGLFBO0 || !SkToBool(rtc->asTextureProxy()));
216
Robert Phillipsbe77a022018-04-03 17:17:05 -0400217 SkImageInfo ii = SkImageInfo::Make(rtc->width(), rtc->height(), ct, kPremul_SkAlphaType,
Brian Salomon4bc0c1f2019-09-30 15:12:27 -0400218 rtc->colorInfo().refColorSpace());
Robert Phillipsbe77a022018-04-03 17:17:05 -0400219
Robert Phillipsb2adbef2019-07-02 16:33:05 -0400220 GrBackendFormat format = rtc->asSurfaceProxy()->backendFormat();
Robert Phillips8def8bf2017-11-30 08:46:03 -0500221
Robert Phillipsb2adbef2019-07-02 16:33:05 -0400222 characterization->set(ctx->threadSafeProxy(), maxResourceBytes, ii, format,
223 rtc->origin(), rtc->numSamples(),
224 SkSurfaceCharacterization::Textureable(SkToBool(rtc->asTextureProxy())),
225 SkSurfaceCharacterization::MipMapped(mipmapped),
226 SkSurfaceCharacterization::UsesGLFBO0(usesGLFBO0),
227 SkSurfaceCharacterization::VulkanSecondaryCBCompatible(false),
Robert Phillips3cd54322019-07-10 09:28:59 -0400228 GrProtected(rtc->asRenderTargetProxy()->isProtected()),
Robert Phillipsb2adbef2019-07-02 16:33:05 -0400229 this->props());
Robert Phillipsad8a43f2017-08-30 12:06:35 -0400230 return true;
231}
232
Brian Salomonc552eaf2019-03-20 15:45:50 -0400233void SkSurface_Gpu::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) {
234 // If the dst is also GPU we try to not force a new image snapshot (by calling the base class
235 // onDraw) since that may not always perform the copy-on-write optimization.
236 auto tryDraw = [&] {
237 SkASSERT(fDevice->context()->priv().asDirectContext());
238 GrContext* context = fDevice->context();
239 GrContext* canvasContext = canvas->getGrContext();
240 if (!canvasContext) {
241 return false;
242 }
243 if (!canvasContext->priv().asDirectContext() ||
244 canvasContext->priv().contextID() != context->priv().contextID()) {
245 return false;
246 }
247 GrRenderTargetContext* rtc = fDevice->accessRenderTargetContext();
248 if (!rtc) {
249 return false;
250 }
251 sk_sp<GrTextureProxy> srcProxy = rtc->asTextureProxyRef();
252 if (!srcProxy) {
253 return false;
254 }
255 // Possibly we could skip making an image here if SkGpuDevice exposed a lower level way
256 // of drawing a texture proxy.
257 const SkImageInfo info = fDevice->imageInfo();
258 sk_sp<SkImage> image;
Brian Salomon729fc0c2019-09-30 16:33:11 +0000259 image = sk_make_sp<SkImage_Gpu>(sk_ref_sp(context), kNeedNewImageUniqueID, info.alphaType(),
260 std::move(srcProxy), info.refColorSpace());
Brian Salomonc552eaf2019-03-20 15:45:50 -0400261 canvas->drawImage(image, x, y, paint);
262 return true;
263 };
264 if (!tryDraw()) {
265 INHERITED::onDraw(canvas, x, y, paint);
266 }
267}
268
Robert Phillips9907e6e2019-06-25 14:47:04 -0400269bool SkSurface_Gpu::onIsCompatible(const SkSurfaceCharacterization& characterization) const {
Robert Phillipsad8a43f2017-08-30 12:06:35 -0400270 GrRenderTargetContext* rtc = fDevice->accessRenderTargetContext();
Robert Phillips8def8bf2017-11-30 08:46:03 -0500271 GrContext* ctx = fDevice->context();
Robert Phillipsad8a43f2017-08-30 12:06:35 -0400272
Robert Phillipsbe77a022018-04-03 17:17:05 -0400273 if (!characterization.isValid()) {
Robert Phillipsfc711a22018-02-13 17:03:00 -0500274 return false;
275 }
276
Greg Danielb085fa92019-03-05 16:55:12 -0500277 if (characterization.vulkanSecondaryCBCompatible()) {
278 return false;
279 }
280
Robert Phillips8d1e67e2017-12-04 13:48:14 -0500281 // As long as the current state if the context allows for greater or equal resources,
282 // we allow the DDL to be replayed.
Robert Phillipsfc711a22018-02-13 17:03:00 -0500283 // DDL TODO: should we just remove the resource check and ignore the cache limits on playback?
Robert Phillipscf39f372019-09-03 10:29:20 -0400284 size_t maxResourceBytes = ctx->getResourceCacheLimit();
Robert Phillips8d1e67e2017-12-04 13:48:14 -0500285
Robert Phillipsbe77a022018-04-03 17:17:05 -0400286 if (characterization.isTextureable()) {
Robert Phillipse8fabb22018-02-04 14:33:21 -0500287 if (!rtc->asTextureProxy()) {
288 // If the characterization was textureable we require the replay dest to also be
289 // textureable. If the characterized surface wasn't textureable we allow the replay
290 // dest to be textureable.
291 return false;
292 }
293
Robert Phillipsbe77a022018-04-03 17:17:05 -0400294 if (characterization.isMipMapped() &&
295 GrMipMapped::kNo == rtc->asTextureProxy()->mipMapped()) {
Robert Phillipse8fabb22018-02-04 14:33:21 -0500296 // Fail if the DDL's surface was mipmapped but the replay surface is not.
297 // Allow drawing to proceed if the DDL was not mipmapped but the replay surface is.
298 return false;
299 }
300 }
301
Greg Daniela070ed72018-04-26 16:31:38 -0400302 if (characterization.usesGLFBO0() != rtc->asRenderTargetProxy()->rtPriv().glRTFBOIDIs0()) {
303 return false;
304 }
305
Brian Salomon4bc0c1f2019-09-30 15:12:27 -0400306 SkColorType rtcColorType = GrColorTypeToSkColorType(rtc->colorInfo().colorType());
Brian Salomonbd3d8d32019-07-02 09:16:28 -0400307 if (rtcColorType == kUnknown_SkColorType) {
Robert Phillipsbe77a022018-04-03 17:17:05 -0400308 return false;
309 }
310
Robert Phillips3cd54322019-07-10 09:28:59 -0400311 GrProtected isProtected = GrProtected(rtc->asSurfaceProxy()->isProtected());
312
Robert Phillipsfe0963c2019-02-07 13:25:07 -0500313 return characterization.contextInfo() && characterization.contextInfo()->priv().matches(ctx) &&
Robert Phillipsbe77a022018-04-03 17:17:05 -0400314 characterization.cacheMaxResourceBytes() <= maxResourceBytes &&
315 characterization.origin() == rtc->origin() &&
Robert Phillipsb2adbef2019-07-02 16:33:05 -0400316 characterization.backendFormat() == rtc->asSurfaceProxy()->backendFormat() &&
Brian Salomon4bc0c1f2019-09-30 15:12:27 -0400317 characterization.width() == rtc->width() && characterization.height() == rtc->height() &&
Robert Phillipsbe77a022018-04-03 17:17:05 -0400318 characterization.colorType() == rtcColorType &&
Chris Dalton6ce447a2019-06-23 18:07:38 -0600319 characterization.sampleCount() == rtc->numSamples() &&
Brian Salomon4bc0c1f2019-09-30 15:12:27 -0400320 SkColorSpace::Equals(characterization.colorSpace(), rtc->colorInfo().colorSpace()) &&
Robert Phillips3cd54322019-07-10 09:28:59 -0400321 characterization.isProtected() == isProtected &&
Robert Phillipsbe77a022018-04-03 17:17:05 -0400322 characterization.surfaceProps() == rtc->surfaceProps();
Robert Phillipsad8a43f2017-08-30 12:06:35 -0400323}
324
Robert Phillipsd5f9cdd2018-01-31 09:29:48 -0500325bool SkSurface_Gpu::onDraw(const SkDeferredDisplayList* ddl) {
Robert Phillipsfc711a22018-02-13 17:03:00 -0500326 if (!ddl || !this->isCompatible(ddl->characterization())) {
Robert Phillips7ffbcf92017-12-04 12:52:46 -0500327 return false;
Robert Phillipsad8a43f2017-08-30 12:06:35 -0400328 }
329
Robert Phillips62000362018-02-01 09:10:04 -0500330 GrRenderTargetContext* rtc = fDevice->accessRenderTargetContext();
331 GrContext* ctx = fDevice->context();
332
Chris Dalton6b498102019-08-01 14:14:52 -0600333 ctx->priv().copyRenderTasksFromDDL(ddl, rtc->asRenderTargetProxy());
Robert Phillips62000362018-02-01 09:10:04 -0500334 return true;
Robert Phillipsad8a43f2017-08-30 12:06:35 -0400335}
336
337
reed@google.com5d4ba882012-07-31 15:45:27 +0000338///////////////////////////////////////////////////////////////////////////////
339
Robert Phillips9338c602019-02-19 12:52:29 -0500340sk_sp<SkSurface> SkSurface::MakeRenderTarget(GrRecordingContext* context,
Robert Phillips6b6fcc72018-03-30 13:57:00 -0400341 const SkSurfaceCharacterization& c,
342 SkBudgeted budgeted) {
Robert Phillipsbe77a022018-04-03 17:17:05 -0400343 if (!context || !c.isValid()) {
Robert Phillips6b6fcc72018-03-30 13:57:00 -0400344 return nullptr;
345 }
346
Greg Daniela070ed72018-04-26 16:31:38 -0400347 if (c.usesGLFBO0()) {
348 // If we are making the surface we will never use FBO0.
349 return nullptr;
350 }
351
Robert Phillipsc046ff02019-07-01 10:34:03 -0400352 if (c.vulkanSecondaryCBCompatible()) {
353 return nullptr;
354 }
355
Greg Daniel627d0532019-07-08 16:48:14 -0400356 GrColorType grColorType = SkColorTypeToGrColorType(c.colorType());
Robert Phillips6b6fcc72018-03-30 13:57:00 -0400357
Brian Salomonbf6b9792019-08-21 09:38:10 -0400358 auto rtc = context->priv().makeDeferredRenderTargetContext(SkBackingFit::kExact,
359 c.width(),
360 c.height(),
361 grColorType,
362 c.refColorSpace(),
363 c.sampleCount(),
364 GrMipMapped(c.isMipMapped()),
365 c.origin(),
366 &c.surfaceProps(),
367 budgeted,
368 c.isProtected());
Brian Salomon947efe22019-07-16 15:36:11 -0400369 if (!rtc) {
Robert Phillipsbe77a022018-04-03 17:17:05 -0400370 return nullptr;
371 }
372
Robert Phillips9338c602019-02-19 12:52:29 -0500373 // CONTEXT TODO: remove this use of 'backdoor' to create an SkGpuDevice
Brian Salomon947efe22019-07-16 15:36:11 -0400374 sk_sp<SkGpuDevice> device(SkGpuDevice::Make(context->priv().backdoor(), std::move(rtc),
Robert Phillipsbe77a022018-04-03 17:17:05 -0400375 SkGpuDevice::kClear_InitContents));
376 if (!device) {
377 return nullptr;
378 }
379
Robert Phillips9907e6e2019-06-25 14:47:04 -0400380 sk_sp<SkSurface> result = sk_make_sp<SkSurface_Gpu>(std::move(device));
Robert Phillipsbe77a022018-04-03 17:17:05 -0400381#ifdef SK_DEBUG
Robert Phillips9907e6e2019-06-25 14:47:04 -0400382 if (result) {
383 SkASSERT(result->isCompatible(c));
Robert Phillipsbe77a022018-04-03 17:17:05 -0400384 }
385#endif
386
Robert Phillips9907e6e2019-06-25 14:47:04 -0400387 return result;
Robert Phillips6b6fcc72018-03-30 13:57:00 -0400388}
389
Robert Phillips62221e72019-07-24 15:07:38 -0400390static bool validate_backend_texture(const GrCaps* caps, const GrBackendTexture& tex,
391 int sampleCnt, GrColorType grCT,
Robert Phillips02dc0302019-07-02 17:58:27 -0400392 bool texturable) {
393 if (!tex.isValid()) {
394 return false;
395 }
396
397 GrBackendFormat backendFormat = tex.getBackendFormat();
398 if (!backendFormat.isValid()) {
399 return false;
400 }
Robert Phillips1cd1ed82019-07-23 13:21:01 -0400401
Robert Phillips62221e72019-07-24 15:07:38 -0400402 if (!caps->areColorTypeAndFormatCompatible(grCT, backendFormat)) {
Robert Phillips02dc0302019-07-02 17:58:27 -0400403 return false;
404 }
405
Greg Daniel6fa62e22019-08-07 15:52:37 -0400406 if (!caps->isFormatAsColorTypeRenderable(grCT, backendFormat, sampleCnt)) {
Robert Phillips02dc0302019-07-02 17:58:27 -0400407 return false;
408 }
409
Greg Daniel7bfc9132019-08-14 14:23:53 -0400410 if (texturable && !caps->isFormatTexturable(backendFormat)) {
Robert Phillips02dc0302019-07-02 17:58:27 -0400411 return false;
412 }
Robert Phillips62221e72019-07-24 15:07:38 -0400413
Robert Phillips02dc0302019-07-02 17:58:27 -0400414 return true;
415}
416
417sk_sp<SkSurface> SkSurface::MakeFromBackendTexture(GrContext* context,
418 const SkSurfaceCharacterization& c,
419 const GrBackendTexture& backendTexture,
420 TextureReleaseProc textureReleaseProc,
421 ReleaseContext releaseContext) {
422 if (!context || !c.isValid()) {
423 return nullptr;
424 }
425
426 if (c.usesGLFBO0()) {
427 // If we are making the surface we will never use FBO0.
428 return nullptr;
429 }
430
431 if (!c.isCompatible(backendTexture)) {
432 return nullptr;
433 }
434
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400435 GrColorType grCT = SkColorTypeAndFormatToGrColorType(context->priv().caps(), c.colorType(),
436 backendTexture.getBackendFormat());
Greg Daniele877dce2019-07-11 10:52:43 -0400437 if (grCT == GrColorType::kUnknown) {
438 return nullptr;
439 }
Greg Daniel5c96db82019-07-09 14:06:58 -0400440
Robert Phillips62221e72019-07-24 15:07:38 -0400441 if (!validate_backend_texture(context->priv().caps(), backendTexture,
Greg Daniel5c96db82019-07-09 14:06:58 -0400442 c.sampleCount(), grCT, true)) {
Robert Phillips02dc0302019-07-02 17:58:27 -0400443 return nullptr;
444 }
445
Brian Salomonbf6b9792019-08-21 09:38:10 -0400446 auto rtc = context->priv().makeBackendTextureRenderTargetContext(
447 backendTexture, c.origin(), c.sampleCount(), grCT, c.refColorSpace(), &c.surfaceProps(),
448 textureReleaseProc, releaseContext);
Robert Phillips02dc0302019-07-02 17:58:27 -0400449 if (!rtc) {
450 return nullptr;
451 }
452
Brian Salomonbf6b9792019-08-21 09:38:10 -0400453 auto device = SkGpuDevice::Make(context, std::move(rtc), SkGpuDevice::kUninit_InitContents);
Robert Phillips02dc0302019-07-02 17:58:27 -0400454 if (!device) {
455 return nullptr;
456 }
457
458 sk_sp<SkSurface> result = sk_make_sp<SkSurface_Gpu>(std::move(device));
459#ifdef SK_DEBUG
460 if (result) {
461 SkASSERT(result->isCompatible(c));
462 }
463#endif
464
465 return result;
466}
467
reede8f30622016-03-23 18:59:25 -0700468sk_sp<SkSurface> SkSurface::MakeRenderTarget(GrContext* ctx, SkBudgeted budgeted,
469 const SkImageInfo& info, int sampleCount,
Greg Daniele252f082017-10-23 16:05:23 -0400470 GrSurfaceOrigin origin, const SkSurfaceProps* props,
471 bool shouldCreateWithMips) {
Greg Danielf47069c2017-10-24 11:57:01 -0400472 if (!ctx) {
473 return nullptr;
474 }
Brian Salomonbdecacf2018-02-02 20:32:49 -0500475 sampleCount = SkTMax(1, sampleCount);
Greg Daniele252f082017-10-23 16:05:23 -0400476 GrMipMapped mipMapped = shouldCreateWithMips ? GrMipMapped::kYes : GrMipMapped::kNo;
477
Robert Phillips9da87e02019-02-04 13:26:26 -0500478 if (!ctx->priv().caps()->mipMapSupport()) {
Greg Danielf47069c2017-10-24 11:57:01 -0400479 mipMapped = GrMipMapped::kNo;
480 }
481
robertphillips24e91282016-04-29 06:46:36 -0700482 sk_sp<SkGpuDevice> device(SkGpuDevice::Make(
Greg Daniele252f082017-10-23 16:05:23 -0400483 ctx, budgeted, info, sampleCount, origin, props, mipMapped,
484 SkGpuDevice::kClear_InitContents));
bsalomonafe30052015-01-16 07:32:33 -0800485 if (!device) {
halcanary96fcdcc2015-08-27 07:41:13 -0700486 return nullptr;
reed@google.com5d4ba882012-07-31 15:45:27 +0000487 }
robertphillips24e91282016-04-29 06:46:36 -0700488 return sk_make_sp<SkSurface_Gpu>(std::move(device));
reed@google.com5d4ba882012-07-31 15:45:27 +0000489}
reedf037e0b2014-10-30 11:34:15 -0700490
Brian Salomonbf6b9792019-08-21 09:38:10 -0400491sk_sp<SkSurface> SkSurface_Gpu::MakeWrappedRenderTarget(
492 GrContext* context, std::unique_ptr<GrRenderTargetContext> rtc) {
Robert Phillipsd5f9cdd2018-01-31 09:29:48 -0500493 if (!context) {
494 return nullptr;
495 }
496
Brian Salomonbf6b9792019-08-21 09:38:10 -0400497 auto device = SkGpuDevice::Make(context, std::move(rtc), SkGpuDevice::kUninit_InitContents);
Robert Phillipsd5f9cdd2018-01-31 09:29:48 -0500498 if (!device) {
499 return nullptr;
500 }
501
502 return sk_make_sp<SkSurface_Gpu>(std::move(device));
503}
504
Greg Danielfaa095e2017-12-19 13:15:02 -0500505sk_sp<SkSurface> SkSurface::MakeFromBackendTexture(GrContext* context, const GrBackendTexture& tex,
506 GrSurfaceOrigin origin, int sampleCnt,
507 SkColorType colorType,
508 sk_sp<SkColorSpace> colorSpace,
Greg Daniel8ce79912019-02-05 10:08:43 -0500509 const SkSurfaceProps* props,
510 SkSurface::TextureReleaseProc textureReleaseProc,
511 SkSurface::ReleaseContext releaseContext) {
Greg Danielfaa095e2017-12-19 13:15:02 -0500512 if (!context) {
513 return nullptr;
514 }
Brian Salomonbdecacf2018-02-02 20:32:49 -0500515 sampleCnt = SkTMax(1, sampleCnt);
Greg Daniele877dce2019-07-11 10:52:43 -0400516
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400517 GrColorType grColorType = SkColorTypeAndFormatToGrColorType(context->priv().caps(), colorType,
518 tex.getBackendFormat());
Greg Daniele877dce2019-07-11 10:52:43 -0400519 if (grColorType == GrColorType::kUnknown) {
520 return nullptr;
521 }
522
Robert Phillips62221e72019-07-24 15:07:38 -0400523 if (!validate_backend_texture(context->priv().caps(), tex, sampleCnt, grColorType, true)) {
Brian Salomon53706772018-03-19 14:18:08 -0400524 return nullptr;
525 }
Brian Salomon53706772018-03-19 14:18:08 -0400526
Brian Salomonbf6b9792019-08-21 09:38:10 -0400527 auto rtc = context->priv().makeBackendTextureRenderTargetContext(
528 tex, origin, sampleCnt, grColorType, std::move(colorSpace), props, textureReleaseProc,
529 releaseContext);
Brian Salomon53706772018-03-19 14:18:08 -0400530 if (!rtc) {
531 return nullptr;
532 }
533
Brian Salomonbf6b9792019-08-21 09:38:10 -0400534 auto device = SkGpuDevice::Make(context, std::move(rtc), SkGpuDevice::kUninit_InitContents);
Brian Salomon53706772018-03-19 14:18:08 -0400535 if (!device) {
536 return nullptr;
537 }
538 return sk_make_sp<SkSurface_Gpu>(std::move(device));
Greg Danielfaa095e2017-12-19 13:15:02 -0500539}
540
Brian Salomonaad83152019-05-24 10:16:35 -0400541bool SkSurface_Gpu::onReplaceBackendTexture(const GrBackendTexture& backendTexture,
542 GrSurfaceOrigin origin, TextureReleaseProc releaseProc,
543 ReleaseContext releaseContext) {
544 auto context = this->fDevice->context();
545 if (context->abandoned()) {
546 return false;
547 }
548 if (!backendTexture.isValid()) {
549 return false;
550 }
551 if (backendTexture.width() != this->width() || backendTexture.height() != this->height()) {
552 return false;
553 }
554 auto* oldRTC = fDevice->accessRenderTargetContext();
555 auto oldProxy = sk_ref_sp(oldRTC->asTextureProxy());
556 if (!oldProxy) {
557 return false;
558 }
559 auto* oldTexture = oldProxy->peekTexture();
560 if (!oldTexture) {
561 return false;
562 }
563 if (!oldTexture->resourcePriv().refsWrappedObjects()) {
564 return false;
565 }
566 if (oldTexture->backendFormat() != backendTexture.getBackendFormat()) {
567 return false;
568 }
569 if (oldTexture->getBackendTexture().isSameTexture(backendTexture)) {
570 return false;
571 }
572 SkASSERT(oldTexture->asRenderTarget());
Chris Dalton6ce447a2019-06-23 18:07:38 -0600573 int sampleCnt = oldTexture->asRenderTarget()->numSamples();
Greg Daniel5c96db82019-07-09 14:06:58 -0400574 GrColorType grColorType = SkColorTypeToGrColorType(this->getCanvas()->imageInfo().colorType());
Brian Salomon4bc0c1f2019-09-30 15:12:27 -0400575 auto colorSpace = sk_ref_sp(oldRTC->colorInfo().colorSpace());
Robert Phillips62221e72019-07-24 15:07:38 -0400576 if (!validate_backend_texture(context->priv().caps(), backendTexture,
577 sampleCnt, grColorType, true)) {
Brian Salomonaad83152019-05-24 10:16:35 -0400578 return false;
579 }
Brian Salomon4bc0c1f2019-09-30 15:12:27 -0400580 auto rtc =
581 context->priv().makeBackendTextureRenderTargetContext(backendTexture,
582 origin,
583 sampleCnt,
584 oldRTC->colorInfo().colorType(),
585 std::move(colorSpace),
586 &this->props(),
587 releaseProc,
588 releaseContext);
Brian Salomonaad83152019-05-24 10:16:35 -0400589 if (!rtc) {
590 return false;
591 }
592 fDevice->replaceRenderTargetContext(std::move(rtc), true);
593 return true;
594}
595
Robert Phillips1cd1ed82019-07-23 13:21:01 -0400596bool validate_backend_render_target(const GrCaps* caps, const GrBackendRenderTarget& rt,
Robert Phillips62221e72019-07-24 15:07:38 -0400597 GrColorType grCT) {
Robert Phillips1cd1ed82019-07-23 13:21:01 -0400598 if (!caps->areColorTypeAndFormatCompatible(grCT, rt.getBackendFormat())) {
599 return false;
600 }
601
Greg Daniel900583a2019-08-06 12:05:31 -0400602 if (!caps->isFormatAsColorTypeRenderable(grCT, rt.getBackendFormat(), rt.sampleCnt())) {
Greg Danielfaa095e2017-12-19 13:15:02 -0500603 return false;
604 }
Greg Danielfaa095e2017-12-19 13:15:02 -0500605 return true;
606}
607
608sk_sp<SkSurface> SkSurface::MakeFromBackendRenderTarget(GrContext* context,
609 const GrBackendRenderTarget& rt,
610 GrSurfaceOrigin origin,
611 SkColorType colorType,
612 sk_sp<SkColorSpace> colorSpace,
Greg Daniel8ce79912019-02-05 10:08:43 -0500613 const SkSurfaceProps* props,
614 SkSurface::RenderTargetReleaseProc relProc,
615 SkSurface::ReleaseContext releaseContext) {
Greg Danielfaa095e2017-12-19 13:15:02 -0500616 if (!context) {
617 return nullptr;
618 }
Brian Salomon49edccd2018-03-23 15:31:32 -0400619
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400620 GrColorType grColorType = SkColorTypeAndFormatToGrColorType(context->priv().caps(), colorType,
621 rt.getBackendFormat());
Greg Daniele877dce2019-07-11 10:52:43 -0400622 if (grColorType == GrColorType::kUnknown) {
623 return nullptr;
624 }
625
Robert Phillips62221e72019-07-24 15:07:38 -0400626 if (!validate_backend_render_target(context->priv().caps(), rt, grColorType)) {
Brian Salomon49edccd2018-03-23 15:31:32 -0400627 return nullptr;
628 }
629
Brian Salomonbf6b9792019-08-21 09:38:10 -0400630 auto rtc = context->priv().makeBackendRenderTargetRenderTargetContext(
631 rt, origin, grColorType, std::move(colorSpace), props, relProc, releaseContext);
Brian Salomon49edccd2018-03-23 15:31:32 -0400632 if (!rtc) {
633 return nullptr;
634 }
635
Brian Salomonbf6b9792019-08-21 09:38:10 -0400636 auto device = SkGpuDevice::Make(context, std::move(rtc), SkGpuDevice::kUninit_InitContents);
Brian Salomon49edccd2018-03-23 15:31:32 -0400637 if (!device) {
638 return nullptr;
639 }
640
641 return sk_make_sp<SkSurface_Gpu>(std::move(device));
Greg Danielfaa095e2017-12-19 13:15:02 -0500642}
643
reede8f30622016-03-23 18:59:25 -0700644sk_sp<SkSurface> SkSurface::MakeFromBackendTextureAsRenderTarget(GrContext* context,
Greg Daniel7ef28f32017-04-20 16:41:55 +0000645 const GrBackendTexture& tex,
646 GrSurfaceOrigin origin,
647 int sampleCnt,
Brian Salomoncb884702018-03-19 14:01:21 -0400648 SkColorType colorType,
Greg Daniel7ef28f32017-04-20 16:41:55 +0000649 sk_sp<SkColorSpace> colorSpace,
650 const SkSurfaceProps* props) {
651 if (!context) {
652 return nullptr;
653 }
Justin Novosad21a99d42018-07-17 16:53:43 -0400654
Brian Salomonbdecacf2018-02-02 20:32:49 -0500655 sampleCnt = SkTMax(1, sampleCnt);
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400656 GrColorType grColorType = SkColorTypeAndFormatToGrColorType(context->priv().caps(), colorType,
657 tex.getBackendFormat());
Greg Daniele877dce2019-07-11 10:52:43 -0400658 if (grColorType == GrColorType::kUnknown) {
659 return nullptr;
660 }
Robert Phillips62221e72019-07-24 15:07:38 -0400661 if (!validate_backend_texture(context->priv().caps(), tex, sampleCnt, grColorType, false)) {
Justin Novosad21a99d42018-07-17 16:53:43 -0400662 return nullptr;
663 }
664
Brian Salomonbf6b9792019-08-21 09:38:10 -0400665 auto rtc = context->priv().makeBackendTextureAsRenderTargetRenderTargetContext(
666 tex, origin, sampleCnt, grColorType, std::move(colorSpace), props);
Brian Osman11052242016-10-27 14:47:55 -0400667 if (!rtc) {
ericrkf7b8b8a2016-02-24 14:49:51 -0800668 return nullptr;
669 }
robertphillips15c42ca2016-08-04 08:45:02 -0700670
Brian Salomonbf6b9792019-08-21 09:38:10 -0400671 auto device = SkGpuDevice::Make(context, std::move(rtc), SkGpuDevice::kUninit_InitContents);
ericrkf7b8b8a2016-02-24 14:49:51 -0800672 if (!device) {
673 return nullptr;
674 }
robertphillips24e91282016-04-29 06:46:36 -0700675 return sk_make_sp<SkSurface_Gpu>(std::move(device));
ericrkf7b8b8a2016-02-24 14:49:51 -0800676}
677
Greg Daniel173464d2019-02-06 15:30:34 -0500678#if defined(SK_BUILD_FOR_ANDROID) && __ANDROID_API__ >= 26
679sk_sp<SkSurface> SkSurface::MakeFromAHardwareBuffer(GrContext* context,
680 AHardwareBuffer* hardwareBuffer,
681 GrSurfaceOrigin origin,
682 sk_sp<SkColorSpace> colorSpace,
683 const SkSurfaceProps* surfaceProps) {
684 AHardwareBuffer_Desc bufferDesc;
685 AHardwareBuffer_describe(hardwareBuffer, &bufferDesc);
686
687 if (!SkToBool(bufferDesc.usage & AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT)) {
688 return nullptr;
689 }
690
691 bool isTextureable = SkToBool(bufferDesc.usage & AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE);
692 bool isProtectedContent = SkToBool(bufferDesc.usage & AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT);
693
694 // We currently don't support protected content
695 if (isProtectedContent) {
Emircan Uysaler23ca4e72019-06-24 10:53:09 -0400696 SkDebugf("We currently don't support protected content on android\n");
Greg Daniel173464d2019-02-06 15:30:34 -0500697 return nullptr;
698 }
699
700 GrBackendFormat backendFormat = GrAHardwareBufferUtils::GetBackendFormat(context,
701 hardwareBuffer,
702 bufferDesc.format,
703 true);
704 if (!backendFormat.isValid()) {
705 return nullptr;
706 }
707
708 if (isTextureable) {
709 GrAHardwareBufferUtils::DeleteImageProc deleteImageProc = nullptr;
Stan Ilieva56b04a2019-08-01 14:22:34 -0400710 GrAHardwareBufferUtils::UpdateImageProc updateImageProc = nullptr;
711 GrAHardwareBufferUtils::TexImageCtx deleteImageCtx = nullptr;
Greg Daniel173464d2019-02-06 15:30:34 -0500712
713 GrBackendTexture backendTexture =
714 GrAHardwareBufferUtils::MakeBackendTexture(context, hardwareBuffer,
715 bufferDesc.width, bufferDesc.height,
Stan Ilieva56b04a2019-08-01 14:22:34 -0400716 &deleteImageProc, &updateImageProc,
717 &deleteImageCtx, isProtectedContent,
718 backendFormat, true);
Greg Daniel173464d2019-02-06 15:30:34 -0500719 if (!backendTexture.isValid()) {
720 return nullptr;
721 }
722
723 SkColorType colorType =
724 GrAHardwareBufferUtils::GetSkColorTypeFromBufferFormat(bufferDesc.format);
725
Greg Danielb6c15ba2019-03-04 13:08:25 -0500726 sk_sp<SkSurface> surface = SkSurface::MakeFromBackendTexture(context, backendTexture,
727 origin, 0, colorType, std::move(colorSpace), surfaceProps, deleteImageProc,
728 deleteImageCtx);
729
730 if (!surface) {
731 SkASSERT(deleteImageProc);
732 deleteImageProc(deleteImageCtx);
733 }
734 return surface;
Greg Daniel173464d2019-02-06 15:30:34 -0500735 } else {
736 return nullptr;
737 }
738}
739#endif
740
reedf037e0b2014-10-30 11:34:15 -0700741#endif