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