blob: a6958e5440b4a86580253b4bbc0510c5461d5cf7 [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
cdalton397536c2016-03-25 12:15:03 -070010#include "GrBuffer.h"
robertphillips5fa7f302016-07-21 09:21:04 -070011#include "GrCaps.h"
bsalomoned0bcad2015-05-04 10:36:42 -070012#include "GrGpu.h"
kkinnunencabe20c2015-06-01 01:37:26 -070013#include "GrPathRendering.h"
egdanielec00d942015-09-14 12:56:10 -070014#include "GrRenderTarget.h"
15#include "GrRenderTargetPriv.h"
bsalomoned0bcad2015-05-04 10:36:42 -070016#include "GrResourceCache.h"
17#include "GrResourceKey.h"
egdanielec00d942015-09-14 12:56:10 -070018#include "GrStencilAttachment.h"
halcanary4dbbd042016-06-07 17:21:10 -070019#include "SkMathPriv.h"
bsalomoned0bcad2015-05-04 10:36:42 -070020
21GR_DECLARE_STATIC_UNIQUE_KEY(gQuadIndexBufferKey);
22
joshualitt6d0872d2016-01-11 08:27:48 -080023GrResourceProvider::GrResourceProvider(GrGpu* gpu, GrResourceCache* cache, GrSingleOwner* owner)
24 : INHERITED(gpu, cache, owner) {
bsalomoned0bcad2015-05-04 10:36:42 -070025 GR_DEFINE_STATIC_UNIQUE_KEY(gQuadIndexBufferKey);
26 fQuadIndexBufferKey = gQuadIndexBufferKey;
27}
28
cdalton397536c2016-03-25 12:15:03 -070029const GrBuffer* GrResourceProvider::createInstancedIndexBuffer(const uint16_t* pattern,
30 int patternSize,
31 int reps,
32 int vertCount,
33 const GrUniqueKey& key) {
bsalomoned0bcad2015-05-04 10:36:42 -070034 size_t bufferSize = patternSize * reps * sizeof(uint16_t);
35
bsalomoneae62002015-07-31 13:59:30 -070036 // This is typically used in GrBatchs, so we assume kNoPendingIO.
cdaltone2e71c22016-04-07 18:13:29 -070037 GrBuffer* buffer = this->createBuffer(bufferSize, kIndex_GrBufferType, kStatic_GrAccessPattern,
cdalton397536c2016-03-25 12:15:03 -070038 kNoPendingIO_Flag);
bsalomoned0bcad2015-05-04 10:36:42 -070039 if (!buffer) {
halcanary96fcdcc2015-08-27 07:41:13 -070040 return nullptr;
bsalomoned0bcad2015-05-04 10:36:42 -070041 }
42 uint16_t* data = (uint16_t*) buffer->map();
halcanary96fcdcc2015-08-27 07:41:13 -070043 bool useTempData = (nullptr == data);
bsalomoned0bcad2015-05-04 10:36:42 -070044 if (useTempData) {
halcanary385fe4d2015-08-26 13:07:48 -070045 data = new uint16_t[reps * patternSize];
bsalomoned0bcad2015-05-04 10:36:42 -070046 }
47 for (int i = 0; i < reps; ++i) {
48 int baseIdx = i * patternSize;
49 uint16_t baseVert = (uint16_t)(i * vertCount);
50 for (int j = 0; j < patternSize; ++j) {
51 data[baseIdx+j] = baseVert + pattern[j];
52 }
53 }
54 if (useTempData) {
55 if (!buffer->updateData(data, bufferSize)) {
56 buffer->unref();
halcanary96fcdcc2015-08-27 07:41:13 -070057 return nullptr;
bsalomoned0bcad2015-05-04 10:36:42 -070058 }
halcanary385fe4d2015-08-26 13:07:48 -070059 delete[] data;
bsalomoned0bcad2015-05-04 10:36:42 -070060 } else {
61 buffer->unmap();
62 }
63 this->assignUniqueKeyToResource(key, buffer);
64 return buffer;
65}
66
cdalton397536c2016-03-25 12:15:03 -070067const GrBuffer* GrResourceProvider::createQuadIndexBuffer() {
bsalomoned0bcad2015-05-04 10:36:42 -070068 static const int kMaxQuads = 1 << 12; // max possible: (1 << 14) - 1;
69 GR_STATIC_ASSERT(4 * kMaxQuads <= 65535);
70 static const uint16_t kPattern[] = { 0, 1, 2, 0, 2, 3 };
71
72 return this->createInstancedIndexBuffer(kPattern, 6, kMaxQuads, 4, fQuadIndexBufferKey);
73}
74
bsalomon6663acf2016-05-10 09:14:17 -070075GrPath* GrResourceProvider::createPath(const SkPath& path, const GrStyle& style) {
bsalomon706f08f2015-05-22 07:35:58 -070076 SkASSERT(this->gpu()->pathRendering());
bsalomon6663acf2016-05-10 09:14:17 -070077 return this->gpu()->pathRendering()->createPath(path, style);
bsalomon706f08f2015-05-22 07:35:58 -070078}
79
80GrPathRange* GrResourceProvider::createPathRange(GrPathRange::PathGenerator* gen,
bsalomon6663acf2016-05-10 09:14:17 -070081 const GrStyle& style) {
bsalomon706f08f2015-05-22 07:35:58 -070082 SkASSERT(this->gpu()->pathRendering());
bsalomon6663acf2016-05-10 09:14:17 -070083 return this->gpu()->pathRendering()->createPathRange(gen, style);
bsalomon706f08f2015-05-22 07:35:58 -070084}
85
reeda9322c22016-04-12 06:47:05 -070086GrPathRange* GrResourceProvider::createGlyphs(const SkTypeface* tf,
87 const SkScalerContextEffects& effects,
88 const SkDescriptor* desc,
bsalomon6663acf2016-05-10 09:14:17 -070089 const GrStyle& style) {
bsalomon706f08f2015-05-22 07:35:58 -070090
91 SkASSERT(this->gpu()->pathRendering());
bsalomon6663acf2016-05-10 09:14:17 -070092 return this->gpu()->pathRendering()->createGlyphs(tf, effects, desc, style);
bsalomon706f08f2015-05-22 07:35:58 -070093}
94
cdaltone2e71c22016-04-07 18:13:29 -070095GrBuffer* GrResourceProvider::createBuffer(size_t size, GrBufferType intendedType,
cdalton1bf3e712016-04-19 10:00:02 -070096 GrAccessPattern accessPattern, uint32_t flags,
97 const void* data) {
robertphillips1b8e1b52015-06-24 06:54:10 -070098 if (this->isAbandoned()) {
halcanary96fcdcc2015-08-27 07:41:13 -070099 return nullptr;
robertphillips1b8e1b52015-06-24 06:54:10 -0700100 }
cdaltond37fe762016-04-21 07:41:50 -0700101 if (kDynamic_GrAccessPattern != accessPattern) {
102 return this->gpu()->createBuffer(size, intendedType, accessPattern, data);
103 }
csmartdalton485a1202016-07-13 10:16:32 -0700104 if (!(flags & kRequireGpuMemory_Flag) &&
105 this->gpu()->caps()->preferClientSideDynamicBuffers() &&
106 GrBufferTypeIsVertexOrIndex(intendedType) &&
107 kDynamic_GrAccessPattern == accessPattern) {
108 return GrBuffer::CreateCPUBacked(this->gpu(), size, intendedType, data);
109 }
robertphillips1b8e1b52015-06-24 06:54:10 -0700110
cdaltond37fe762016-04-21 07:41:50 -0700111 // bin by pow2 with a reasonable min
Robert Phillips9e380472016-10-28 12:15:03 -0400112 static const size_t MIN_SIZE = 1 << 12;
113 size_t allocSize = SkTMax(MIN_SIZE, GrNextSizePow2(size));
robertphillips1b8e1b52015-06-24 06:54:10 -0700114
cdaltond37fe762016-04-21 07:41:50 -0700115 GrScratchKey key;
csmartdalton485a1202016-07-13 10:16:32 -0700116 GrBuffer::ComputeScratchKeyForDynamicVBO(allocSize, intendedType, &key);
cdaltond37fe762016-04-21 07:41:50 -0700117 uint32_t scratchFlags = 0;
118 if (flags & kNoPendingIO_Flag) {
119 scratchFlags = GrResourceCache::kRequireNoPendingIO_ScratchFlag;
120 } else {
121 scratchFlags = GrResourceCache::kPreferNoPendingIO_ScratchFlag;
122 }
123 GrBuffer* buffer = static_cast<GrBuffer*>(
124 this->cache()->findAndRefScratchResource(key, allocSize, scratchFlags));
125 if (!buffer) {
126 buffer = this->gpu()->createBuffer(allocSize, intendedType, kDynamic_GrAccessPattern);
127 if (!buffer) {
128 return nullptr;
robertphillips1b8e1b52015-06-24 06:54:10 -0700129 }
130 }
cdaltond37fe762016-04-21 07:41:50 -0700131 if (data) {
132 buffer->updateData(data, size);
133 }
csmartdalton485a1202016-07-13 10:16:32 -0700134 SkASSERT(!buffer->isCPUBacked()); // We should only cache real VBOs.
cdaltond37fe762016-04-21 07:41:50 -0700135 return buffer;
jvanverth17aa0472016-01-05 10:41:27 -0800136}
137
joshualittb356cbc2015-08-05 06:36:39 -0700138GrBatchAtlas* GrResourceProvider::createAtlas(GrPixelConfig config,
139 int width, int height,
140 int numPlotsX, int numPlotsY,
141 GrBatchAtlas::EvictionFunc func, void* data) {
142 GrSurfaceDesc desc;
143 desc.fFlags = kNone_GrSurfaceFlags;
144 desc.fWidth = width;
145 desc.fHeight = height;
146 desc.fConfig = config;
147
148 // We don't want to flush the context so we claim we're in the middle of flushing so as to
149 // guarantee we do not recieve a texture with pending IO
halcanary6950de62015-11-07 05:29:00 -0800150 // TODO: Determine how to avoid having to do this. (https://bug.skia.org/4156)
joshualittb356cbc2015-08-05 06:36:39 -0700151 static const uint32_t kFlags = GrResourceProvider::kNoPendingIO_Flag;
152 GrTexture* texture = this->createApproxTexture(desc, kFlags);
153 if (!texture) {
halcanary96fcdcc2015-08-27 07:41:13 -0700154 return nullptr;
joshualittb356cbc2015-08-05 06:36:39 -0700155 }
jvanverthc3d706f2016-04-20 10:33:27 -0700156 GrBatchAtlas* atlas = new GrBatchAtlas(texture, numPlotsX, numPlotsY);
joshualitt8377e802015-11-05 07:14:56 -0800157 atlas->registerEvictionCallback(func, data);
158 return atlas;
joshualittb356cbc2015-08-05 06:36:39 -0700159}
egdanielec00d942015-09-14 12:56:10 -0700160
161GrStencilAttachment* GrResourceProvider::attachStencilAttachment(GrRenderTarget* rt) {
162 SkASSERT(rt);
163 if (rt->renderTargetPriv().getStencilAttachment()) {
164 return rt->renderTargetPriv().getStencilAttachment();
165 }
166
167 if (!rt->wasDestroyed() && rt->canAttemptStencilAttachment()) {
168 GrUniqueKey sbKey;
169
170 int width = rt->width();
171 int height = rt->height();
172#if 0
173 if (this->caps()->oversizedStencilSupport()) {
174 width = SkNextPow2(width);
175 height = SkNextPow2(height);
176 }
177#endif
178 bool newStencil = false;
179 GrStencilAttachment::ComputeSharedStencilAttachmentKey(width, height,
180 rt->numStencilSamples(), &sbKey);
181 GrStencilAttachment* stencil = static_cast<GrStencilAttachment*>(
182 this->findAndRefResourceByUniqueKey(sbKey));
183 if (!stencil) {
184 // Need to try and create a new stencil
185 stencil = this->gpu()->createStencilAttachmentForRenderTarget(rt, width, height);
186 if (stencil) {
187 stencil->resourcePriv().setUniqueKey(sbKey);
188 newStencil = true;
189 }
190 }
191 if (rt->renderTargetPriv().attachStencilAttachment(stencil)) {
192 if (newStencil) {
193 // Right now we're clearing the stencil attachment here after it is
bsalomon7ea33f52015-11-22 14:51:00 -0800194 // attached to a RT for the first time. When we start matching
egdanielec00d942015-09-14 12:56:10 -0700195 // stencil buffers with smaller color targets this will no longer
196 // be correct because it won't be guaranteed to clear the entire
197 // sb.
198 // We used to clear down in the GL subclass using a special purpose
199 // FBO. But iOS doesn't allow a stencil-only FBO. It reports unsupported
200 // FBO status.
201 this->gpu()->clearStencil(rt);
202 }
203 }
204 }
205 return rt->renderTargetPriv().getStencilAttachment();
206}
207
bungeman6bd52842016-10-27 09:30:08 -0700208sk_sp<GrRenderTarget> GrResourceProvider::wrapBackendTextureAsRenderTarget(
209 const GrBackendTextureDesc& desc)
210{
ericrkf7b8b8a2016-02-24 14:49:51 -0800211 if (this->isAbandoned()) {
212 return nullptr;
213 }
kkinnunen49c4c222016-04-01 04:50:37 -0700214 return this->gpu()->wrapBackendTextureAsRenderTarget(desc);
ericrkf7b8b8a2016-02-24 14:49:51 -0800215}