• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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->writeView(),
55                                   pipeline,
56                                   userStencilSettings,
57                                   fCurrDraw->fGeometryProcessor,
58                                   fCurrDraw->fPrimitiveType,
59                                   0,
60                                   this->renderPassBarriers(),
61                                   this->colorLoadOp());
62 
63         this->bindPipelineAndScissorClip(programInfo, chainBounds);
64         this->bindTextures(programInfo.geomProc(), fCurrDraw->fGeomProcProxies,
65                            programInfo.pipeline());
66         for (int i = 0; i < fCurrDraw->fMeshCnt; ++i) {
67             this->drawMesh(fCurrDraw->fMeshes[i]);
68         }
69 
70         fTokenTracker->flushToken();
71         ++fCurrDraw;
72     }
73 }
74 
preExecuteDraws()75 void GrOpFlushState::preExecuteDraws() {
76     fVertexPool.unmap();
77     fIndexPool.unmap();
78     fDrawIndirectPool.unmap();
79     for (auto& upload : fASAPUploads) {
80         this->doUpload(upload);
81     }
82     // Setup execution iterators.
83     fCurrDraw = fDraws.begin();
84     fCurrUpload = fInlineUploads.begin();
85 }
86 
reset()87 void GrOpFlushState::reset() {
88     SkASSERT(fCurrDraw == fDraws.end());
89     SkASSERT(fCurrUpload == fInlineUploads.end());
90     fVertexPool.reset();
91     fIndexPool.reset();
92     fDrawIndirectPool.reset();
93     fArena.reset();
94     fASAPUploads.reset();
95     fInlineUploads.reset();
96     fDraws.reset();
97     fBaseDrawToken = GrDeferredUploadToken::AlreadyFlushedToken();
98 }
99 
doUpload(GrDeferredTextureUploadFn & upload,bool shouldPrepareSurfaceForSampling)100 void GrOpFlushState::doUpload(GrDeferredTextureUploadFn& upload,
101                               bool shouldPrepareSurfaceForSampling) {
102     GrDeferredTextureUploadWritePixelsFn wp = [this, shouldPrepareSurfaceForSampling](
103             GrTextureProxy* dstProxy, int left, int top, int width, int height,
104             GrColorType colorType, const void* buffer, size_t rowBytes) {
105         GrSurface* dstSurface = dstProxy->peekSurface();
106         if (!fGpu->caps()->surfaceSupportsWritePixels(dstSurface)) {
107             return false;
108         }
109         GrCaps::SupportedWrite supportedWrite = fGpu->caps()->supportedWritePixelsColorType(
110                 colorType, dstSurface->backendFormat(), colorType);
111         size_t tightRB = width * GrColorTypeBytesPerPixel(supportedWrite.fColorType);
112         SkASSERT(rowBytes >= tightRB);
113         std::unique_ptr<char[]> tmpPixels;
114         if (supportedWrite.fColorType != colorType ||
115             (!fGpu->caps()->writePixelsRowBytesSupport() && rowBytes != tightRB)) {
116             tmpPixels.reset(new char[height * tightRB]);
117             // Use kUnknown to ensure no alpha type conversions or clamping occur.
118             static constexpr auto kAT = kUnknown_SkAlphaType;
119             GrImageInfo srcInfo(colorType,                 kAT, nullptr, width, height);
120             GrImageInfo tmpInfo(supportedWrite.fColorType, kAT, nullptr, width, height);
121             if (!GrConvertPixels( GrPixmap(tmpInfo, tmpPixels.get(), tightRB ),
122                                  GrCPixmap(srcInfo,          buffer, rowBytes))) {
123                 return false;
124             }
125             rowBytes = tightRB;
126             buffer = tmpPixels.get();
127         }
128         return this->fGpu->writePixels(dstSurface, left, top, width, height, colorType,
129                                        supportedWrite.fColorType, buffer, rowBytes,
130                                        shouldPrepareSurfaceForSampling);
131     };
132     upload(wp);
133 }
134 
addInlineUpload(GrDeferredTextureUploadFn && upload)135 GrDeferredUploadToken GrOpFlushState::addInlineUpload(GrDeferredTextureUploadFn&& upload) {
136     return fInlineUploads.append(&fArena, std::move(upload), fTokenTracker->nextDrawToken())
137             .fUploadBeforeToken;
138 }
139 
addASAPUpload(GrDeferredTextureUploadFn && upload)140 GrDeferredUploadToken GrOpFlushState::addASAPUpload(GrDeferredTextureUploadFn&& upload) {
141     fASAPUploads.append(&fArena, std::move(upload));
142     return fTokenTracker->nextTokenToFlush();
143 }
144 
recordDraw(const GrGeometryProcessor * geomProc,const GrSimpleMesh meshes[],int meshCnt,const GrSurfaceProxy * const geomProcProxies[],GrPrimitiveType primitiveType)145 void GrOpFlushState::recordDraw(
146         const GrGeometryProcessor* geomProc,
147         const GrSimpleMesh meshes[],
148         int meshCnt,
149         const GrSurfaceProxy* const geomProcProxies[],
150         GrPrimitiveType primitiveType) {
151     SkASSERT(fOpArgs);
152     SkDEBUGCODE(fOpArgs->validate());
153     bool firstDraw = fDraws.begin() == fDraws.end();
154     auto& draw = fDraws.append(&fArena);
155     GrDeferredUploadToken token = fTokenTracker->issueDrawToken();
156     for (int i = 0; i < geomProc->numTextureSamplers(); ++i) {
157         SkASSERT(geomProcProxies && geomProcProxies[i]);
158         geomProcProxies[i]->ref();
159     }
160     draw.fGeometryProcessor = geomProc;
161     draw.fGeomProcProxies = geomProcProxies;
162     draw.fMeshes = meshes;
163     draw.fMeshCnt = meshCnt;
164     draw.fOp = fOpArgs->op();
165     draw.fPrimitiveType = primitiveType;
166     if (firstDraw) {
167         fBaseDrawToken = token;
168     }
169 }
170 
makeVertexSpace(size_t vertexSize,int vertexCount,sk_sp<const GrBuffer> * buffer,int * startVertex)171 void* GrOpFlushState::makeVertexSpace(size_t vertexSize, int vertexCount,
172                                       sk_sp<const GrBuffer>* buffer, int* startVertex) {
173     return fVertexPool.makeSpace(vertexSize, vertexCount, buffer, startVertex);
174 }
175 
makeIndexSpace(int indexCount,sk_sp<const GrBuffer> * buffer,int * startIndex)176 uint16_t* GrOpFlushState::makeIndexSpace(int indexCount, sk_sp<const GrBuffer>* buffer,
177                                          int* startIndex) {
178     return reinterpret_cast<uint16_t*>(fIndexPool.makeSpace(indexCount, buffer, startIndex));
179 }
180 
makeVertexSpaceAtLeast(size_t vertexSize,int minVertexCount,int fallbackVertexCount,sk_sp<const GrBuffer> * buffer,int * startVertex,int * actualVertexCount)181 void* GrOpFlushState::makeVertexSpaceAtLeast(size_t vertexSize, int minVertexCount,
182                                              int fallbackVertexCount, sk_sp<const GrBuffer>* buffer,
183                                              int* startVertex, int* actualVertexCount) {
184     return fVertexPool.makeSpaceAtLeast(vertexSize, minVertexCount, fallbackVertexCount, buffer,
185                                         startVertex, actualVertexCount);
186 }
187 
makeIndexSpaceAtLeast(int minIndexCount,int fallbackIndexCount,sk_sp<const GrBuffer> * buffer,int * startIndex,int * actualIndexCount)188 uint16_t* GrOpFlushState::makeIndexSpaceAtLeast(int minIndexCount, int fallbackIndexCount,
189                                                 sk_sp<const GrBuffer>* buffer, int* startIndex,
190                                                 int* actualIndexCount) {
191     return reinterpret_cast<uint16_t*>(fIndexPool.makeSpaceAtLeast(
192             minIndexCount, fallbackIndexCount, buffer, startIndex, actualIndexCount));
193 }
194 
putBackIndices(int indexCount)195 void GrOpFlushState::putBackIndices(int indexCount) {
196     fIndexPool.putBack(indexCount * sizeof(uint16_t));
197 }
198 
putBackVertices(int vertices,size_t vertexStride)199 void GrOpFlushState::putBackVertices(int vertices, size_t vertexStride) {
200     fVertexPool.putBack(vertices * vertexStride);
201 }
202 
detachAppliedClip()203 GrAppliedClip GrOpFlushState::detachAppliedClip() {
204     return fOpArgs->appliedClip() ? std::move(*fOpArgs->appliedClip()) : GrAppliedClip::Disabled();
205 }
206 
strikeCache() const207 GrStrikeCache* GrOpFlushState::strikeCache() const {
208     return fGpu->getContext()->priv().getGrStrikeCache();
209 }
210 
atlasManager() const211 GrAtlasManager* GrOpFlushState::atlasManager() const {
212     return fGpu->getContext()->priv().getAtlasManager();
213 }
214 
smallPathAtlasManager() const215 GrSmallPathAtlasMgr* GrOpFlushState::smallPathAtlasManager() const {
216     return fGpu->getContext()->priv().getSmallPathAtlasMgr();
217 }
218 
drawMesh(const GrSimpleMesh & mesh)219 void GrOpFlushState::drawMesh(const GrSimpleMesh& mesh) {
220     SkASSERT(mesh.fIsInitialized);
221     if (!mesh.fIndexBuffer) {
222         this->bindBuffers(nullptr, nullptr, mesh.fVertexBuffer);
223         this->draw(mesh.fVertexCount, mesh.fBaseVertex);
224     } else {
225         this->bindBuffers(mesh.fIndexBuffer, nullptr, mesh.fVertexBuffer, mesh.fPrimitiveRestart);
226         if (0 == mesh.fPatternRepeatCount) {
227             this->drawIndexed(mesh.fIndexCount, mesh.fBaseIndex, mesh.fMinIndexValue,
228                               mesh.fMaxIndexValue, mesh.fBaseVertex);
229         } else {
230             this->drawIndexPattern(mesh.fIndexCount, mesh.fPatternRepeatCount,
231                                    mesh.fMaxPatternRepetitionsInIndexBuffer, mesh.fVertexCount,
232                                    mesh.fBaseVertex);
233         }
234     }
235 }
236 
237 //////////////////////////////////////////////////////////////////////////////
238 
~Draw()239 GrOpFlushState::Draw::~Draw() {
240     for (int i = 0; i < fGeometryProcessor->numTextureSamplers(); ++i) {
241         SkASSERT(fGeomProcProxies && fGeomProcProxies[i]);
242         fGeomProcProxies[i]->unref();
243     }
244 }
245