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