blob: 048b87fc4e87861beda8810d795a7a5ab5f5a683 [file] [log] [blame]
bsalomoned0bcad2015-05-04 10:36:42 -07001/*
2 * Copyright 2015 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
8#include "GrResourceProvider.h"
9
Greg Daniela5cb7812017-06-16 09:45:32 -040010#include "GrBackendSemaphore.h"
cdalton397536c2016-03-25 12:15:03 -070011#include "GrBuffer.h"
robertphillips5fa7f302016-07-21 09:21:04 -070012#include "GrCaps.h"
Robert Phillips26c90e02017-03-14 14:39:29 -040013#include "GrContext.h"
Robert Phillipse78b7252017-04-06 07:59:41 -040014#include "GrContextPriv.h"
bsalomoned0bcad2015-05-04 10:36:42 -070015#include "GrGpu.h"
Robert Phillips67d52cf2017-06-05 13:38:13 -040016#include "GrPath.h"
kkinnunencabe20c2015-06-01 01:37:26 -070017#include "GrPathRendering.h"
egdanielec00d942015-09-14 12:56:10 -070018#include "GrRenderTargetPriv.h"
bsalomoned0bcad2015-05-04 10:36:42 -070019#include "GrResourceCache.h"
20#include "GrResourceKey.h"
Greg Danield85f97d2017-03-07 13:37:21 -050021#include "GrSemaphore.h"
egdanielec00d942015-09-14 12:56:10 -070022#include "GrStencilAttachment.h"
Brian Osman32342f02017-03-04 08:12:46 -050023#include "GrTexturePriv.h"
24#include "../private/GrSingleOwner.h"
Robert Phillips45fdae12017-04-17 12:57:27 -040025#include "SkGr.h"
halcanary4dbbd042016-06-07 17:21:10 -070026#include "SkMathPriv.h"
bsalomoned0bcad2015-05-04 10:36:42 -070027
28GR_DECLARE_STATIC_UNIQUE_KEY(gQuadIndexBufferKey);
29
Robert Phillips1bfece82017-06-01 13:56:52 -040030const uint32_t GrResourceProvider::kMinScratchTextureSize = 16;
Brian Osman32342f02017-03-04 08:12:46 -050031
32#define ASSERT_SINGLE_OWNER \
33 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fSingleOwner);)
34
joshualitt6d0872d2016-01-11 08:27:48 -080035GrResourceProvider::GrResourceProvider(GrGpu* gpu, GrResourceCache* cache, GrSingleOwner* owner)
Brian Osman32342f02017-03-04 08:12:46 -050036 : fCache(cache)
37 , fGpu(gpu)
38#ifdef SK_DEBUG
39 , fSingleOwner(owner)
40#endif
41 {
Robert Phillips26c90e02017-03-14 14:39:29 -040042 fCaps = sk_ref_sp(fGpu->caps());
43
bsalomoned0bcad2015-05-04 10:36:42 -070044 GR_DEFINE_STATIC_UNIQUE_KEY(gQuadIndexBufferKey);
45 fQuadIndexBufferKey = gQuadIndexBufferKey;
46}
47
Brian Salomond34edf32017-05-19 15:45:48 -040048bool validate_desc(const GrSurfaceDesc& desc, const GrCaps& caps, int levelCount = 0) {
49 if (desc.fWidth <= 0 || desc.fHeight <= 0) {
50 return false;
51 }
52 if (!caps.isConfigTexturable(desc.fConfig)) {
53 return false;
54 }
55 if (desc.fFlags & kRenderTarget_GrSurfaceFlag) {
56 if (!caps.isConfigRenderable(desc.fConfig, desc.fSampleCnt > 0)) {
57 return false;
58 }
59 } else {
60 if (desc.fSampleCnt) {
61 return false;
62 }
63 }
Brian Osman48c99192017-06-02 08:45:06 -040064 if (levelCount > 1 && (GrPixelConfigIsSint(desc.fConfig) || !caps.mipMapSupport())) {
Brian Salomond34edf32017-05-19 15:45:48 -040065 return false;
66 }
67 return true;
68}
69
Robert Phillips8e8c7552017-07-10 12:06:05 -040070sk_sp<GrTexture> GrResourceProvider::createTexture(const GrSurfaceDesc& desc, SkBudgeted budgeted,
Robert Phillips590533f2017-07-11 14:22:35 -040071 const GrMipLevel texels[], int mipLevelCount,
Robert Phillips8e8c7552017-07-10 12:06:05 -040072 SkDestinationSurfaceColorMode mipColorMode) {
Brian Osman32342f02017-03-04 08:12:46 -050073 ASSERT_SINGLE_OWNER
74
Robert Phillips7f1b4f82017-11-28 07:38:39 -050075 SkASSERT(mipLevelCount > 0);
Robert Phillips1119dc32017-04-11 12:54:57 -040076
Brian Osman32342f02017-03-04 08:12:46 -050077 if (this->isAbandoned()) {
78 return nullptr;
79 }
Robert Phillips1119dc32017-04-11 12:54:57 -040080
Robert Phillips590533f2017-07-11 14:22:35 -040081 if (!validate_desc(desc, *fCaps, mipLevelCount)) {
Brian Osman32342f02017-03-04 08:12:46 -050082 return nullptr;
83 }
Brian Osman32342f02017-03-04 08:12:46 -050084
Robert Phillips590533f2017-07-11 14:22:35 -040085 sk_sp<GrTexture> tex(fGpu->createTexture(desc, budgeted, texels, mipLevelCount));
Robert Phillipse78b7252017-04-06 07:59:41 -040086 if (tex) {
87 tex->texturePriv().setMipColorMode(mipColorMode);
Robert Phillipsa4c41b32017-03-15 13:02:45 -040088 }
Robert Phillipse78b7252017-04-06 07:59:41 -040089
Robert Phillips8e8c7552017-07-10 12:06:05 -040090 return tex;
Brian Osman32342f02017-03-04 08:12:46 -050091}
92
Robert Phillips45fdae12017-04-17 12:57:27 -040093sk_sp<GrTexture> GrResourceProvider::getExactScratch(const GrSurfaceDesc& desc,
Greg Daniel21918232017-09-08 14:46:23 -040094 SkBudgeted budgeted, uint32_t flags) {
Robert Phillips45fdae12017-04-17 12:57:27 -040095 sk_sp<GrTexture> tex(this->refScratchTexture(desc, flags));
96 if (tex && SkBudgeted::kNo == budgeted) {
97 tex->resourcePriv().makeUnbudgeted();
98 }
99
100 return tex;
101}
102
103static bool make_info(int w, int h, GrPixelConfig config, SkImageInfo* ii) {
104 SkColorType colorType;
105 if (!GrPixelConfigToColorType(config, &colorType)) {
106 return false;
107 }
108
109 *ii = SkImageInfo::Make(w, h, colorType, kUnknown_SkAlphaType, nullptr);
110 return true;
111}
112
Robert Phillips1afd4cd2018-01-08 13:40:32 -0500113sk_sp<GrTexture> GrResourceProvider::createTexture(const GrSurfaceDesc& desc,
114 SkBudgeted budgeted,
115 const GrMipLevel& mipLevel) {
Robert Phillips774831a2017-04-20 10:19:33 -0400116 ASSERT_SINGLE_OWNER
117
118 if (this->isAbandoned()) {
119 return nullptr;
120 }
121
Robert Phillips45fdae12017-04-17 12:57:27 -0400122 if (!mipLevel.fPixels) {
123 return nullptr;
124 }
125
Brian Salomond34edf32017-05-19 15:45:48 -0400126 if (!validate_desc(desc, *fCaps)) {
127 return nullptr;
128 }
129
Robert Phillips45fdae12017-04-17 12:57:27 -0400130 GrContext* context = fGpu->getContext();
131
Robert Phillips92de6312017-05-23 07:43:48 -0400132 SkImageInfo srcInfo;
Robert Phillips45fdae12017-04-17 12:57:27 -0400133
Robert Phillips92de6312017-05-23 07:43:48 -0400134 if (make_info(desc.fWidth, desc.fHeight, desc.fConfig, &srcInfo)) {
Greg Daniel21918232017-09-08 14:46:23 -0400135 sk_sp<GrTexture> tex = this->getExactScratch(desc, budgeted, 0);
Robert Phillips1afd4cd2018-01-08 13:40:32 -0500136 sk_sp<GrTextureProxy> proxy = GrSurfaceProxy::MakeWrapped(tex, desc.fOrigin);
Robert Phillipsfe50d962017-06-01 10:22:03 -0400137 if (proxy) {
138 sk_sp<GrSurfaceContext> sContext =
139 context->contextPriv().makeWrappedSurfaceContext(std::move(proxy), nullptr);
140 if (sContext) {
141 if (sContext->writePixels(srcInfo, mipLevel.fPixels, mipLevel.fRowBytes, 0, 0)) {
Robert Phillips1afd4cd2018-01-08 13:40:32 -0500142 SkASSERT(sContext->asTextureProxy()->priv().peekTexture() == tex.get());
143 return tex;
Robert Phillipsfe50d962017-06-01 10:22:03 -0400144 }
Robert Phillips45fdae12017-04-17 12:57:27 -0400145 }
146 }
147 }
148
Robert Phillips1afd4cd2018-01-08 13:40:32 -0500149 return fGpu->createTexture(desc, budgeted, &mipLevel, 1);
Robert Phillips45fdae12017-04-17 12:57:27 -0400150}
151
Robert Phillipse78b7252017-04-06 07:59:41 -0400152sk_sp<GrTexture> GrResourceProvider::createTexture(const GrSurfaceDesc& desc, SkBudgeted budgeted,
153 uint32_t flags) {
154 ASSERT_SINGLE_OWNER
155
156 if (this->isAbandoned()) {
157 return nullptr;
Brian Osman32342f02017-03-04 08:12:46 -0500158 }
Robert Phillipse78b7252017-04-06 07:59:41 -0400159
Brian Salomond34edf32017-05-19 15:45:48 -0400160 if (!validate_desc(desc, *fCaps)) {
Robert Phillipse78b7252017-04-06 07:59:41 -0400161 return nullptr;
162 }
163
Greg Daniel21918232017-09-08 14:46:23 -0400164 sk_sp<GrTexture> tex = this->getExactScratch(desc, budgeted, flags);
Robert Phillips92de6312017-05-23 07:43:48 -0400165 if (tex) {
166 return tex;
Robert Phillipse78b7252017-04-06 07:59:41 -0400167 }
168
Robert Phillips67d52cf2017-06-05 13:38:13 -0400169 return fGpu->createTexture(desc, budgeted);
Brian Osman32342f02017-03-04 08:12:46 -0500170}
171
Robert Phillips67d52cf2017-06-05 13:38:13 -0400172sk_sp<GrTexture> GrResourceProvider::createApproxTexture(const GrSurfaceDesc& desc,
173 uint32_t flags) {
Brian Osman32342f02017-03-04 08:12:46 -0500174 ASSERT_SINGLE_OWNER
175 SkASSERT(0 == flags || kNoPendingIO_Flag == flags);
Brian Osman32342f02017-03-04 08:12:46 -0500176
Brian Osman32342f02017-03-04 08:12:46 -0500177 if (this->isAbandoned()) {
178 return nullptr;
179 }
Robert Phillips1119dc32017-04-11 12:54:57 -0400180
Brian Salomond34edf32017-05-19 15:45:48 -0400181 if (!validate_desc(desc, *fCaps)) {
182 return nullptr;
183 }
184
Greg Daniel6b60b6e2017-09-26 16:37:12 -0400185 if (auto tex = this->refScratchTexture(desc, flags)) {
186 return tex;
187 }
188
Greg Daniel29bf84f2017-09-25 12:25:12 -0400189 SkTCopyOnFirstWrite<GrSurfaceDesc> copyDesc(desc);
190
191 // bin by pow2 with a reasonable min
192 if (!SkToBool(desc.fFlags & kPerformInitialClear_GrSurfaceFlag) &&
193 (fGpu->caps()->reuseScratchTextures() || (desc.fFlags & kRenderTarget_GrSurfaceFlag))) {
194 GrSurfaceDesc* wdesc = copyDesc.writable();
195 wdesc->fWidth = SkTMax(kMinScratchTextureSize, GrNextPow2(desc.fWidth));
196 wdesc->fHeight = SkTMax(kMinScratchTextureSize, GrNextPow2(desc.fHeight));
197 }
198
199 if (auto tex = this->refScratchTexture(*copyDesc, flags)) {
200 return tex;
201 }
202
203 return fGpu->createTexture(*copyDesc, SkBudgeted::kYes);
Brian Osman32342f02017-03-04 08:12:46 -0500204}
205
Greg Daniel29bf84f2017-09-25 12:25:12 -0400206sk_sp<GrTexture> GrResourceProvider::refScratchTexture(const GrSurfaceDesc& desc,
Greg Daniel21918232017-09-08 14:46:23 -0400207 uint32_t flags) {
Brian Osman32342f02017-03-04 08:12:46 -0500208 ASSERT_SINGLE_OWNER
209 SkASSERT(!this->isAbandoned());
Greg Daniel29bf84f2017-09-25 12:25:12 -0400210 SkASSERT(validate_desc(desc, *fCaps));
Brian Osman32342f02017-03-04 08:12:46 -0500211
Brian Salomond17b4a62017-05-23 16:53:47 -0400212 // We could make initial clears work with scratch textures but it is a rare case so we just opt
213 // to fall back to making a new texture.
Greg Daniel29bf84f2017-09-25 12:25:12 -0400214 if (!SkToBool(desc.fFlags & kPerformInitialClear_GrSurfaceFlag) &&
215 (fGpu->caps()->reuseScratchTextures() || (desc.fFlags & kRenderTarget_GrSurfaceFlag))) {
Brian Osman32342f02017-03-04 08:12:46 -0500216
217 GrScratchKey key;
Greg Daniel29bf84f2017-09-25 12:25:12 -0400218 GrTexturePriv::ComputeScratchKey(desc, &key);
Brian Osman32342f02017-03-04 08:12:46 -0500219 uint32_t scratchFlags = 0;
220 if (kNoPendingIO_Flag & flags) {
221 scratchFlags = GrResourceCache::kRequireNoPendingIO_ScratchFlag;
Greg Daniel29bf84f2017-09-25 12:25:12 -0400222 } else if (!(desc.fFlags & kRenderTarget_GrSurfaceFlag)) {
Brian Osman32342f02017-03-04 08:12:46 -0500223 // If it is not a render target then it will most likely be populated by
224 // writePixels() which will trigger a flush if the texture has pending IO.
225 scratchFlags = GrResourceCache::kPreferNoPendingIO_ScratchFlag;
226 }
227 GrGpuResource* resource = fCache->findAndRefScratchResource(key,
Greg Daniel29bf84f2017-09-25 12:25:12 -0400228 GrSurface::WorstCaseSize(desc),
229 scratchFlags);
Brian Osman32342f02017-03-04 08:12:46 -0500230 if (resource) {
231 GrSurface* surface = static_cast<GrSurface*>(resource);
Robert Phillips67d52cf2017-06-05 13:38:13 -0400232 return sk_sp<GrTexture>(surface->asTexture());
Brian Osman32342f02017-03-04 08:12:46 -0500233 }
234 }
235
Brian Osman32342f02017-03-04 08:12:46 -0500236 return nullptr;
237}
238
Greg Daniel7ef28f32017-04-20 16:41:55 +0000239sk_sp<GrTexture> GrResourceProvider::wrapBackendTexture(const GrBackendTexture& tex,
Brian Osman32342f02017-03-04 08:12:46 -0500240 GrWrapOwnership ownership) {
241 ASSERT_SINGLE_OWNER
242 if (this->isAbandoned()) {
243 return nullptr;
244 }
Robert Phillipsb0e93a22017-08-29 08:26:54 -0400245 return fGpu->wrapBackendTexture(tex, ownership);
Brian Salomond17f6582017-07-19 18:28:58 -0400246}
247
248sk_sp<GrTexture> GrResourceProvider::wrapRenderableBackendTexture(const GrBackendTexture& tex,
Brian Salomond17f6582017-07-19 18:28:58 -0400249 int sampleCnt,
250 GrWrapOwnership ownership) {
251 ASSERT_SINGLE_OWNER
252 if (this->isAbandoned()) {
253 return nullptr;
254 }
Robert Phillipsb0e93a22017-08-29 08:26:54 -0400255 return fGpu->wrapRenderableBackendTexture(tex, sampleCnt, ownership);
Brian Osman32342f02017-03-04 08:12:46 -0500256}
257
258sk_sp<GrRenderTarget> GrResourceProvider::wrapBackendRenderTarget(
Robert Phillipsb0e93a22017-08-29 08:26:54 -0400259 const GrBackendRenderTarget& backendRT)
Brian Osman32342f02017-03-04 08:12:46 -0500260{
261 ASSERT_SINGLE_OWNER
Robert Phillipsb0e93a22017-08-29 08:26:54 -0400262 return this->isAbandoned() ? nullptr : fGpu->wrapBackendRenderTarget(backendRT);
Brian Osman32342f02017-03-04 08:12:46 -0500263}
264
265void GrResourceProvider::assignUniqueKeyToResource(const GrUniqueKey& key,
266 GrGpuResource* resource) {
267 ASSERT_SINGLE_OWNER
268 if (this->isAbandoned() || !resource) {
269 return;
270 }
271 resource->resourcePriv().setUniqueKey(key);
272}
273
Brian Salomond28a79d2017-10-16 13:01:07 -0400274sk_sp<GrGpuResource> GrResourceProvider::findResourceByUniqueKey(const GrUniqueKey& key) {
Brian Osman32342f02017-03-04 08:12:46 -0500275 ASSERT_SINGLE_OWNER
Brian Salomond28a79d2017-10-16 13:01:07 -0400276 return this->isAbandoned() ? nullptr
277 : sk_sp<GrGpuResource>(fCache->findAndRefUniqueResource(key));
Brian Osman32342f02017-03-04 08:12:46 -0500278}
279
Chris Dalton5d2de082017-12-19 10:40:23 -0700280sk_sp<const GrBuffer> GrResourceProvider::findOrMakeStaticBuffer(GrBufferType intendedType,
281 size_t size,
282 const void* data,
283 const GrUniqueKey& key) {
284 if (auto buffer = this->findByUniqueKey<GrBuffer>(key)) {
285 return buffer;
286 }
287 if (auto buffer = this->createBuffer(size, intendedType, kStatic_GrAccessPattern, 0,
288 data)) {
289 // We shouldn't bin and/or cachestatic buffers.
290 SkASSERT(buffer->sizeInBytes() == size);
291 SkASSERT(!buffer->resourcePriv().getScratchKey().isValid());
292 SkASSERT(!buffer->resourcePriv().hasPendingIO_debugOnly());
293 buffer->resourcePriv().setUniqueKey(key);
294 return sk_sp<const GrBuffer>(buffer);
295 }
296 return nullptr;
297}
298
Brian Salomond28a79d2017-10-16 13:01:07 -0400299sk_sp<const GrBuffer> GrResourceProvider::createPatternedIndexBuffer(const uint16_t* pattern,
300 int patternSize,
301 int reps,
302 int vertCount,
303 const GrUniqueKey& key) {
bsalomoned0bcad2015-05-04 10:36:42 -0700304 size_t bufferSize = patternSize * reps * sizeof(uint16_t);
305
Brian Salomon09d994e2016-12-21 11:14:46 -0500306 // This is typically used in GrMeshDrawOps, so we assume kNoPendingIO.
Brian Salomon7f56d3d2017-10-09 13:02:49 -0400307 sk_sp<GrBuffer> buffer(this->createBuffer(bufferSize, kIndex_GrBufferType,
308 kStatic_GrAccessPattern, kNoPendingIO_Flag));
bsalomoned0bcad2015-05-04 10:36:42 -0700309 if (!buffer) {
halcanary96fcdcc2015-08-27 07:41:13 -0700310 return nullptr;
bsalomoned0bcad2015-05-04 10:36:42 -0700311 }
Brian Salomon7f56d3d2017-10-09 13:02:49 -0400312 uint16_t* data = (uint16_t*) buffer->map();
313 SkAutoTArray<uint16_t> temp;
314 if (!data) {
315 temp.reset(reps * patternSize);
316 data = temp.get();
317 }
bsalomoned0bcad2015-05-04 10:36:42 -0700318 for (int i = 0; i < reps; ++i) {
319 int baseIdx = i * patternSize;
320 uint16_t baseVert = (uint16_t)(i * vertCount);
321 for (int j = 0; j < patternSize; ++j) {
322 data[baseIdx+j] = baseVert + pattern[j];
323 }
324 }
Brian Salomon7f56d3d2017-10-09 13:02:49 -0400325 if (temp.get()) {
326 if (!buffer->updateData(data, bufferSize)) {
327 return nullptr;
328 }
329 } else {
330 buffer->unmap();
bsalomoned0bcad2015-05-04 10:36:42 -0700331 }
Brian Salomon7f56d3d2017-10-09 13:02:49 -0400332 this->assignUniqueKeyToResource(key, buffer.get());
Brian Salomond28a79d2017-10-16 13:01:07 -0400333 return std::move(buffer);
bsalomoned0bcad2015-05-04 10:36:42 -0700334}
335
Brian Salomon34169692017-08-28 15:32:01 -0400336static constexpr int kMaxQuads = 1 << 12; // max possible: (1 << 14) - 1;
337
Brian Salomond28a79d2017-10-16 13:01:07 -0400338sk_sp<const GrBuffer> GrResourceProvider::createQuadIndexBuffer() {
bsalomoned0bcad2015-05-04 10:36:42 -0700339 GR_STATIC_ASSERT(4 * kMaxQuads <= 65535);
Brian Salomon57caa662017-10-18 12:21:05 +0000340 static const uint16_t kPattern[] = { 0, 1, 2, 2, 1, 3 };
Chris Daltonff926502017-05-03 14:36:54 -0400341 return this->createPatternedIndexBuffer(kPattern, 6, kMaxQuads, 4, fQuadIndexBufferKey);
bsalomoned0bcad2015-05-04 10:36:42 -0700342}
343
Brian Salomon34169692017-08-28 15:32:01 -0400344int GrResourceProvider::QuadCountOfQuadBuffer() { return kMaxQuads; }
345
Robert Phillips67d52cf2017-06-05 13:38:13 -0400346sk_sp<GrPath> GrResourceProvider::createPath(const SkPath& path, const GrStyle& style) {
Robert Phillips0f171812017-09-21 14:25:31 -0400347 if (this->isAbandoned()) {
348 return nullptr;
349 }
350
bsalomon706f08f2015-05-22 07:35:58 -0700351 SkASSERT(this->gpu()->pathRendering());
bsalomon6663acf2016-05-10 09:14:17 -0700352 return this->gpu()->pathRendering()->createPath(path, style);
bsalomon706f08f2015-05-22 07:35:58 -0700353}
354
Robert Phillips67d52cf2017-06-05 13:38:13 -0400355sk_sp<GrPathRange> GrResourceProvider::createPathRange(GrPathRange::PathGenerator* gen,
356 const GrStyle& style) {
Robert Phillips0f171812017-09-21 14:25:31 -0400357 if (this->isAbandoned()) {
358 return nullptr;
359 }
360
bsalomon706f08f2015-05-22 07:35:58 -0700361 SkASSERT(this->gpu()->pathRendering());
bsalomon6663acf2016-05-10 09:14:17 -0700362 return this->gpu()->pathRendering()->createPathRange(gen, style);
bsalomon706f08f2015-05-22 07:35:58 -0700363}
364
Robert Phillips67d52cf2017-06-05 13:38:13 -0400365sk_sp<GrPathRange> GrResourceProvider::createGlyphs(const SkTypeface* tf,
366 const SkScalerContextEffects& effects,
367 const SkDescriptor* desc,
368 const GrStyle& style) {
bsalomon706f08f2015-05-22 07:35:58 -0700369
370 SkASSERT(this->gpu()->pathRendering());
bsalomon6663acf2016-05-10 09:14:17 -0700371 return this->gpu()->pathRendering()->createGlyphs(tf, effects, desc, style);
bsalomon706f08f2015-05-22 07:35:58 -0700372}
373
cdaltone2e71c22016-04-07 18:13:29 -0700374GrBuffer* GrResourceProvider::createBuffer(size_t size, GrBufferType intendedType,
cdalton1bf3e712016-04-19 10:00:02 -0700375 GrAccessPattern accessPattern, uint32_t flags,
376 const void* data) {
robertphillips1b8e1b52015-06-24 06:54:10 -0700377 if (this->isAbandoned()) {
halcanary96fcdcc2015-08-27 07:41:13 -0700378 return nullptr;
robertphillips1b8e1b52015-06-24 06:54:10 -0700379 }
cdaltond37fe762016-04-21 07:41:50 -0700380 if (kDynamic_GrAccessPattern != accessPattern) {
381 return this->gpu()->createBuffer(size, intendedType, accessPattern, data);
382 }
csmartdalton485a1202016-07-13 10:16:32 -0700383 if (!(flags & kRequireGpuMemory_Flag) &&
384 this->gpu()->caps()->preferClientSideDynamicBuffers() &&
385 GrBufferTypeIsVertexOrIndex(intendedType) &&
386 kDynamic_GrAccessPattern == accessPattern) {
387 return GrBuffer::CreateCPUBacked(this->gpu(), size, intendedType, data);
388 }
robertphillips1b8e1b52015-06-24 06:54:10 -0700389
cdaltond37fe762016-04-21 07:41:50 -0700390 // bin by pow2 with a reasonable min
Robert Phillips9e380472016-10-28 12:15:03 -0400391 static const size_t MIN_SIZE = 1 << 12;
392 size_t allocSize = SkTMax(MIN_SIZE, GrNextSizePow2(size));
robertphillips1b8e1b52015-06-24 06:54:10 -0700393
cdaltond37fe762016-04-21 07:41:50 -0700394 GrScratchKey key;
csmartdalton485a1202016-07-13 10:16:32 -0700395 GrBuffer::ComputeScratchKeyForDynamicVBO(allocSize, intendedType, &key);
cdaltond37fe762016-04-21 07:41:50 -0700396 uint32_t scratchFlags = 0;
397 if (flags & kNoPendingIO_Flag) {
398 scratchFlags = GrResourceCache::kRequireNoPendingIO_ScratchFlag;
399 } else {
400 scratchFlags = GrResourceCache::kPreferNoPendingIO_ScratchFlag;
401 }
402 GrBuffer* buffer = static_cast<GrBuffer*>(
403 this->cache()->findAndRefScratchResource(key, allocSize, scratchFlags));
404 if (!buffer) {
405 buffer = this->gpu()->createBuffer(allocSize, intendedType, kDynamic_GrAccessPattern);
406 if (!buffer) {
407 return nullptr;
robertphillips1b8e1b52015-06-24 06:54:10 -0700408 }
409 }
cdaltond37fe762016-04-21 07:41:50 -0700410 if (data) {
411 buffer->updateData(data, size);
412 }
csmartdalton485a1202016-07-13 10:16:32 -0700413 SkASSERT(!buffer->isCPUBacked()); // We should only cache real VBOs.
cdaltond37fe762016-04-21 07:41:50 -0700414 return buffer;
jvanverth17aa0472016-01-05 10:41:27 -0800415}
416
Robert Phillipsc0192e32017-09-21 12:00:26 -0400417bool GrResourceProvider::attachStencilAttachment(GrRenderTarget* rt) {
egdanielec00d942015-09-14 12:56:10 -0700418 SkASSERT(rt);
419 if (rt->renderTargetPriv().getStencilAttachment()) {
Robert Phillipsc0192e32017-09-21 12:00:26 -0400420 return true;
egdanielec00d942015-09-14 12:56:10 -0700421 }
422
423 if (!rt->wasDestroyed() && rt->canAttemptStencilAttachment()) {
424 GrUniqueKey sbKey;
425
426 int width = rt->width();
427 int height = rt->height();
428#if 0
429 if (this->caps()->oversizedStencilSupport()) {
430 width = SkNextPow2(width);
431 height = SkNextPow2(height);
432 }
433#endif
Robert Phillipscb2e2352017-08-30 16:44:40 -0400434 SkDEBUGCODE(bool newStencil = false;)
egdanielec00d942015-09-14 12:56:10 -0700435 GrStencilAttachment::ComputeSharedStencilAttachmentKey(width, height,
436 rt->numStencilSamples(), &sbKey);
Brian Salomond28a79d2017-10-16 13:01:07 -0400437 auto stencil = this->findByUniqueKey<GrStencilAttachment>(sbKey);
egdanielec00d942015-09-14 12:56:10 -0700438 if (!stencil) {
439 // Need to try and create a new stencil
Brian Salomond28a79d2017-10-16 13:01:07 -0400440 stencil.reset(this->gpu()->createStencilAttachmentForRenderTarget(rt, width, height));
egdanielec00d942015-09-14 12:56:10 -0700441 if (stencil) {
Brian Salomond28a79d2017-10-16 13:01:07 -0400442 this->assignUniqueKeyToResource(sbKey, stencil.get());
Robert Phillipscb2e2352017-08-30 16:44:40 -0400443 SkDEBUGCODE(newStencil = true;)
egdanielec00d942015-09-14 12:56:10 -0700444 }
445 }
Brian Salomond28a79d2017-10-16 13:01:07 -0400446 if (rt->renderTargetPriv().attachStencilAttachment(std::move(stencil))) {
Robert Phillips95214472017-08-08 18:00:03 -0400447#ifdef SK_DEBUG
448 // Fill the SB with an inappropriate value. opLists that use the
449 // SB should clear it properly.
Robert Phillipscb2e2352017-08-30 16:44:40 -0400450 if (newStencil) {
Brian Salomond28a79d2017-10-16 13:01:07 -0400451 SkASSERT(rt->renderTargetPriv().getStencilAttachment()->isDirty());
Robert Phillipscb2e2352017-08-30 16:44:40 -0400452 this->gpu()->clearStencil(rt, 0xFFFF);
Brian Salomond28a79d2017-10-16 13:01:07 -0400453 SkASSERT(rt->renderTargetPriv().getStencilAttachment()->isDirty());
Robert Phillipscb2e2352017-08-30 16:44:40 -0400454 }
Robert Phillips95214472017-08-08 18:00:03 -0400455#endif
egdanielec00d942015-09-14 12:56:10 -0700456 }
457 }
Robert Phillipsc0192e32017-09-21 12:00:26 -0400458 return SkToBool(rt->renderTargetPriv().getStencilAttachment());
egdanielec00d942015-09-14 12:56:10 -0700459}
460
bungeman6bd52842016-10-27 09:30:08 -0700461sk_sp<GrRenderTarget> GrResourceProvider::wrapBackendTextureAsRenderTarget(
Robert Phillipsb0e93a22017-08-29 08:26:54 -0400462 const GrBackendTexture& tex, int sampleCnt)
bungeman6bd52842016-10-27 09:30:08 -0700463{
ericrkf7b8b8a2016-02-24 14:49:51 -0800464 if (this->isAbandoned()) {
465 return nullptr;
466 }
Robert Phillipsb0e93a22017-08-29 08:26:54 -0400467 return this->gpu()->wrapBackendTextureAsRenderTarget(tex, sampleCnt);
ericrkf7b8b8a2016-02-24 14:49:51 -0800468}
Greg Danield85f97d2017-03-07 13:37:21 -0500469
Greg Daniela5cb7812017-06-16 09:45:32 -0400470sk_sp<GrSemaphore> SK_WARN_UNUSED_RESULT GrResourceProvider::makeSemaphore(bool isOwned) {
471 return fGpu->makeSemaphore(isOwned);
472}
473
474sk_sp<GrSemaphore> GrResourceProvider::wrapBackendSemaphore(const GrBackendSemaphore& semaphore,
Greg Daniel17b7c052018-01-09 13:55:33 -0500475 SemaphoreWrapType wrapType,
Greg Daniela5cb7812017-06-16 09:45:32 -0400476 GrWrapOwnership ownership) {
477 ASSERT_SINGLE_OWNER
Greg Daniel17b7c052018-01-09 13:55:33 -0500478 return this->isAbandoned() ? nullptr : fGpu->wrapBackendSemaphore(semaphore,
479 wrapType,
480 ownership);
Greg Danield85f97d2017-03-07 13:37:21 -0500481}
482
483void GrResourceProvider::takeOwnershipOfSemaphore(sk_sp<GrSemaphore> semaphore) {
484 semaphore->resetGpu(fGpu);
485}
486
487void GrResourceProvider::releaseOwnershipOfSemaphore(sk_sp<GrSemaphore> semaphore) {
488 semaphore->resetGpu(nullptr);
489}