1 /*
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 "src/gpu/GrOpFlushState.h"
9
10 #include "include/gpu/GrDirectContext.h"
11 #include "src/core/SkConvertPixels.h"
12 #include "src/gpu/GrDataUtils.h"
13 #include "src/gpu/GrDirectContextPriv.h"
14 #include "src/gpu/GrDrawOpAtlas.h"
15 #include "src/gpu/GrGpu.h"
16 #include "src/gpu/GrImageInfo.h"
17 #include "src/gpu/GrProgramInfo.h"
18 #include "src/gpu/GrResourceProvider.h"
19 #include "src/gpu/GrTexture.h"
20
21 //////////////////////////////////////////////////////////////////////////////
22
GrOpFlushState(GrGpu * gpu,GrResourceProvider * resourceProvider,GrTokenTracker * tokenTracker,sk_sp<GrBufferAllocPool::CpuBufferCache> cpuBufferCache)23 GrOpFlushState::GrOpFlushState(GrGpu* gpu, GrResourceProvider* resourceProvider,
24 GrTokenTracker* tokenTracker,
25 sk_sp<GrBufferAllocPool::CpuBufferCache> cpuBufferCache)
26 : fVertexPool(gpu, cpuBufferCache)
27 , fIndexPool(gpu, cpuBufferCache)
28 , fDrawIndirectPool(gpu, std::move(cpuBufferCache))
29 , fGpu(gpu)
30 , fResourceProvider(resourceProvider)
31 , fTokenTracker(tokenTracker) {}
32
caps() const33 const GrCaps& GrOpFlushState::caps() const {
34 return *fGpu->caps();
35 }
36
threadSafeCache() const37 GrThreadSafeCache* GrOpFlushState::threadSafeCache() const {
38 return fGpu->getContext()->priv().threadSafeCache();
39 }
40
executeDrawsAndUploadsForMeshDrawOp(const GrOp * op,const SkRect & chainBounds,const GrPipeline * pipeline,const GrUserStencilSettings * userStencilSettings)41 void GrOpFlushState::executeDrawsAndUploadsForMeshDrawOp(
42 const GrOp* op, const SkRect& chainBounds, const GrPipeline* pipeline,
43 const GrUserStencilSettings* userStencilSettings) {
44 SkASSERT(this->opsRenderPass());
45
46 while (fCurrDraw != fDraws.end() && fCurrDraw->fOp == op) {
47 GrDeferredUploadToken drawToken = fTokenTracker->nextTokenToFlush();
48 while (fCurrUpload != fInlineUploads.end() &&
49 fCurrUpload->fUploadBeforeToken == drawToken) {
50 this->opsRenderPass()->inlineUpload(this, fCurrUpload->fUpload);
51 ++fCurrUpload;
52 }
53
54 GrProgramInfo programInfo(this->caps(),
55 this->writeView(),
56 this->usesMSAASurface(),
57 pipeline,
58 userStencilSettings,
59 fCurrDraw->fGeometryProcessor,
60 fCurrDraw->fPrimitiveType,
61 0,
62 this->renderPassBarriers(),
63 this->colorLoadOp());
64
65 this->bindPipelineAndScissorClip(programInfo, chainBounds);
66 this->bindTextures(programInfo.geomProc(), fCurrDraw->fGeomProcProxies,
67 programInfo.pipeline());
68 for (int i = 0; i < fCurrDraw->fMeshCnt; ++i) {
69 this->drawMesh(fCurrDraw->fMeshes[i]);
70 }
71
72 fTokenTracker->flushToken();
73 ++fCurrDraw;
74 }
75 }
76
preExecuteDraws()77 void GrOpFlushState::preExecuteDraws() {
78 fVertexPool.unmap();
79 fIndexPool.unmap();
80 fDrawIndirectPool.unmap();
81 for (auto& upload : fASAPUploads) {
82 this->doUpload(upload);
83 }
84 // Setup execution iterators.
85 fCurrDraw = fDraws.begin();
86 fCurrUpload = fInlineUploads.begin();
87 }
88
reset()89 void GrOpFlushState::reset() {
90 SkASSERT(fCurrDraw == fDraws.end());
91 SkASSERT(fCurrUpload == fInlineUploads.end());
92 fVertexPool.reset();
93 fIndexPool.reset();
94 fDrawIndirectPool.reset();
95 fArena.reset();
96 fASAPUploads.reset();
97 fInlineUploads.reset();
98 fDraws.reset();
99 fBaseDrawToken = GrDeferredUploadToken::AlreadyFlushedToken();
100 }
101
doUpload(GrDeferredTextureUploadFn & upload,bool shouldPrepareSurfaceForSampling)102 void GrOpFlushState::doUpload(GrDeferredTextureUploadFn& upload,
103 bool shouldPrepareSurfaceForSampling) {
104 GrDeferredTextureUploadWritePixelsFn wp = [this, shouldPrepareSurfaceForSampling](
105 GrTextureProxy* dstProxy,
106 SkIRect rect,
107 GrColorType colorType,
108 const void* buffer,
109 size_t rowBytes) {
110 GrSurface* dstSurface = dstProxy->peekSurface();
111 if (!fGpu->caps()->surfaceSupportsWritePixels(dstSurface)) {
112 return false;
113 }
114 GrCaps::SupportedWrite supportedWrite = fGpu->caps()->supportedWritePixelsColorType(
115 colorType, dstSurface->backendFormat(), colorType);
116 size_t tightRB = rect.width()*GrColorTypeBytesPerPixel(supportedWrite.fColorType);
117 SkASSERT(rowBytes >= tightRB);
118 std::unique_ptr<char[]> tmpPixels;
119 if (supportedWrite.fColorType != colorType ||
120 (!fGpu->caps()->writePixelsRowBytesSupport() && rowBytes != tightRB)) {
121 tmpPixels.reset(new char[rect.height()*tightRB]);
122 // Use kUnknown to ensure no alpha type conversions or clamping occur.
123 static constexpr auto kAT = kUnknown_SkAlphaType;
124 GrImageInfo srcInfo(colorType, kAT, nullptr, rect.size());
125 GrImageInfo tmpInfo(supportedWrite.fColorType, kAT, nullptr, rect.size());
126 if (!GrConvertPixels( GrPixmap(tmpInfo, tmpPixels.get(), tightRB ),
127 GrCPixmap(srcInfo, buffer, rowBytes))) {
128 return false;
129 }
130 rowBytes = tightRB;
131 buffer = tmpPixels.get();
132 }
133 return this->fGpu->writePixels(dstSurface,
134 rect,
135 colorType,
136 supportedWrite.fColorType,
137 buffer,
138 rowBytes,
139 shouldPrepareSurfaceForSampling);
140 };
141 upload(wp);
142 }
143
addInlineUpload(GrDeferredTextureUploadFn && upload)144 GrDeferredUploadToken GrOpFlushState::addInlineUpload(GrDeferredTextureUploadFn&& upload) {
145 return fInlineUploads.append(&fArena, std::move(upload), fTokenTracker->nextDrawToken())
146 .fUploadBeforeToken;
147 }
148
addASAPUpload(GrDeferredTextureUploadFn && upload)149 GrDeferredUploadToken GrOpFlushState::addASAPUpload(GrDeferredTextureUploadFn&& upload) {
150 fASAPUploads.append(&fArena, std::move(upload));
151 return fTokenTracker->nextTokenToFlush();
152 }
153
recordDraw(const GrGeometryProcessor * geomProc,const GrSimpleMesh meshes[],int meshCnt,const GrSurfaceProxy * const geomProcProxies[],GrPrimitiveType primitiveType)154 void GrOpFlushState::recordDraw(
155 const GrGeometryProcessor* geomProc,
156 const GrSimpleMesh meshes[],
157 int meshCnt,
158 const GrSurfaceProxy* const geomProcProxies[],
159 GrPrimitiveType primitiveType) {
160 SkASSERT(fOpArgs);
161 SkDEBUGCODE(fOpArgs->validate());
162 bool firstDraw = fDraws.begin() == fDraws.end();
163 auto& draw = fDraws.append(&fArena);
164 GrDeferredUploadToken token = fTokenTracker->issueDrawToken();
165 for (int i = 0; i < geomProc->numTextureSamplers(); ++i) {
166 SkASSERT(geomProcProxies && geomProcProxies[i]);
167 geomProcProxies[i]->ref();
168 }
169 draw.fGeometryProcessor = geomProc;
170 draw.fGeomProcProxies = geomProcProxies;
171 draw.fMeshes = meshes;
172 draw.fMeshCnt = meshCnt;
173 draw.fOp = fOpArgs->op();
174 draw.fPrimitiveType = primitiveType;
175 if (firstDraw) {
176 fBaseDrawToken = token;
177 }
178 }
179
makeVertexSpace(size_t vertexSize,int vertexCount,sk_sp<const GrBuffer> * buffer,int * startVertex)180 void* GrOpFlushState::makeVertexSpace(size_t vertexSize, int vertexCount,
181 sk_sp<const GrBuffer>* buffer, int* startVertex) {
182 return fVertexPool.makeSpace(vertexSize, vertexCount, buffer, startVertex);
183 }
184
makeIndexSpace(int indexCount,sk_sp<const GrBuffer> * buffer,int * startIndex)185 uint16_t* GrOpFlushState::makeIndexSpace(int indexCount, sk_sp<const GrBuffer>* buffer,
186 int* startIndex) {
187 return reinterpret_cast<uint16_t*>(fIndexPool.makeSpace(indexCount, buffer, startIndex));
188 }
189
makeVertexSpaceAtLeast(size_t vertexSize,int minVertexCount,int fallbackVertexCount,sk_sp<const GrBuffer> * buffer,int * startVertex,int * actualVertexCount)190 void* GrOpFlushState::makeVertexSpaceAtLeast(size_t vertexSize, int minVertexCount,
191 int fallbackVertexCount, sk_sp<const GrBuffer>* buffer,
192 int* startVertex, int* actualVertexCount) {
193 return fVertexPool.makeSpaceAtLeast(vertexSize, minVertexCount, fallbackVertexCount, buffer,
194 startVertex, actualVertexCount);
195 }
196
makeIndexSpaceAtLeast(int minIndexCount,int fallbackIndexCount,sk_sp<const GrBuffer> * buffer,int * startIndex,int * actualIndexCount)197 uint16_t* GrOpFlushState::makeIndexSpaceAtLeast(int minIndexCount, int fallbackIndexCount,
198 sk_sp<const GrBuffer>* buffer, int* startIndex,
199 int* actualIndexCount) {
200 return reinterpret_cast<uint16_t*>(fIndexPool.makeSpaceAtLeast(
201 minIndexCount, fallbackIndexCount, buffer, startIndex, actualIndexCount));
202 }
203
putBackIndices(int indexCount)204 void GrOpFlushState::putBackIndices(int indexCount) {
205 fIndexPool.putBack(indexCount * sizeof(uint16_t));
206 }
207
putBackVertices(int vertices,size_t vertexStride)208 void GrOpFlushState::putBackVertices(int vertices, size_t vertexStride) {
209 fVertexPool.putBack(vertices * vertexStride);
210 }
211
detachAppliedClip()212 GrAppliedClip GrOpFlushState::detachAppliedClip() {
213 return fOpArgs->appliedClip() ? std::move(*fOpArgs->appliedClip()) : GrAppliedClip::Disabled();
214 }
215
strikeCache() const216 GrStrikeCache* GrOpFlushState::strikeCache() const {
217 return fGpu->getContext()->priv().getGrStrikeCache();
218 }
219
atlasManager() const220 GrAtlasManager* GrOpFlushState::atlasManager() const {
221 return fGpu->getContext()->priv().getAtlasManager();
222 }
223
smallPathAtlasManager() const224 skgpu::v1::SmallPathAtlasMgr* GrOpFlushState::smallPathAtlasManager() const {
225 return fGpu->getContext()->priv().getSmallPathAtlasMgr();
226 }
227
drawMesh(const GrSimpleMesh & mesh)228 void GrOpFlushState::drawMesh(const GrSimpleMesh& mesh) {
229 SkASSERT(mesh.fIsInitialized);
230 if (!mesh.fIndexBuffer) {
231 this->bindBuffers(nullptr, nullptr, mesh.fVertexBuffer);
232 this->draw(mesh.fVertexCount, mesh.fBaseVertex);
233 } else {
234 this->bindBuffers(mesh.fIndexBuffer, nullptr, mesh.fVertexBuffer, mesh.fPrimitiveRestart);
235 if (0 == mesh.fPatternRepeatCount) {
236 this->drawIndexed(mesh.fIndexCount, mesh.fBaseIndex, mesh.fMinIndexValue,
237 mesh.fMaxIndexValue, mesh.fBaseVertex);
238 } else {
239 this->drawIndexPattern(mesh.fIndexCount, mesh.fPatternRepeatCount,
240 mesh.fMaxPatternRepetitionsInIndexBuffer, mesh.fVertexCount,
241 mesh.fBaseVertex);
242 }
243 }
244 }
245
246 //////////////////////////////////////////////////////////////////////////////
247
~Draw()248 GrOpFlushState::Draw::~Draw() {
249 for (int i = 0; i < fGeometryProcessor->numTextureSamplers(); ++i) {
250 SkASSERT(fGeomProcProxies && fGeomProcProxies[i]);
251 fGeomProcProxies[i]->unref();
252 }
253 }
254