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