blob: 661d9aaa7676e5a03451dfe787cbca363e46c15b [file] [log] [blame]
bsalomon75398562015-08-17 12:55:38 -07001/*
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
Brian Salomon742e31d2016-12-07 17:06:19 -05008#include "GrOpFlushState.h"
bsalomon75398562015-08-17 12:55:38 -07009
Robert Phillipsc4039ea2018-03-01 11:36:45 -050010#include "GrContextPriv.h"
Brian Salomon903da792016-12-16 14:24:46 -050011#include "GrDrawOpAtlas.h"
Robert Phillips646e4292017-06-13 12:44:56 -040012#include "GrGpu.h"
Brian Salomon9bada542017-06-12 12:09:30 -040013#include "GrResourceProvider.h"
Robert Phillips646e4292017-06-13 12:44:56 -040014#include "GrTexture.h"
bsalomon75398562015-08-17 12:55:38 -070015
Brian Salomon7dc6e752017-11-02 11:34:51 -040016//////////////////////////////////////////////////////////////////////////////
17
Robert Phillips40a29d72018-01-18 12:59:22 -050018GrOpFlushState::GrOpFlushState(GrGpu* gpu,
19 GrResourceProvider* resourceProvider,
20 GrTokenTracker* tokenTracker)
21 : fVertexPool(gpu)
22 , fIndexPool(gpu)
23 , fGpu(gpu)
24 , fResourceProvider(resourceProvider)
25 , fTokenTracker(tokenTracker) {
26}
bsalomon75398562015-08-17 12:55:38 -070027
Robert Phillips646e4292017-06-13 12:44:56 -040028const GrCaps& GrOpFlushState::caps() const {
29 return *fGpu->caps();
30}
31
Greg Daniel500d58b2017-08-24 15:59:33 -040032GrGpuRTCommandBuffer* GrOpFlushState::rtCommandBuffer() {
33 return fCommandBuffer->asRTCommandBuffer();
34}
35
Brian Salomon7dc6e752017-11-02 11:34:51 -040036void GrOpFlushState::executeDrawsAndUploadsForMeshDrawOp(uint32_t opID, const SkRect& opBounds) {
37 SkASSERT(this->rtCommandBuffer());
38 while (fCurrDraw != fDraws.end() && fCurrDraw->fOpID == opID) {
Robert Phillips40a29d72018-01-18 12:59:22 -050039 GrDeferredUploadToken drawToken = fTokenTracker->nextTokenToFlush();
Brian Salomon7dc6e752017-11-02 11:34:51 -040040 while (fCurrUpload != fInlineUploads.end() &&
41 fCurrUpload->fUploadBeforeToken == drawToken) {
42 this->rtCommandBuffer()->inlineUpload(this, fCurrUpload->fUpload);
43 ++fCurrUpload;
44 }
45 SkASSERT(fCurrDraw->fPipeline->proxy() == this->drawOpArgs().fProxy);
46 this->rtCommandBuffer()->draw(*fCurrDraw->fPipeline, *fCurrDraw->fGeometryProcessor,
47 fMeshes.begin() + fCurrMesh, nullptr, fCurrDraw->fMeshCnt,
48 opBounds);
49 fCurrMesh += fCurrDraw->fMeshCnt;
Robert Phillips40a29d72018-01-18 12:59:22 -050050 fTokenTracker->flushToken();
Brian Salomon7dc6e752017-11-02 11:34:51 -040051 ++fCurrDraw;
52 }
53}
54
55void GrOpFlushState::preExecuteDraws() {
56 fVertexPool.unmap();
57 fIndexPool.unmap();
Robert Phillips40a29d72018-01-18 12:59:22 -050058 for (auto& upload : fASAPUploads) {
Brian Salomon7dc6e752017-11-02 11:34:51 -040059 this->doUpload(upload);
60 }
61 // Setup execution iterators.
62 fCurrDraw = fDraws.begin();
63 fCurrUpload = fInlineUploads.begin();
64 fCurrMesh = 0;
65}
66
67void GrOpFlushState::reset() {
68 SkASSERT(fCurrDraw == fDraws.end());
69 SkASSERT(fCurrUpload == fInlineUploads.end());
70 fVertexPool.reset();
71 fIndexPool.reset();
72 fArena.reset();
Robert Phillips40a29d72018-01-18 12:59:22 -050073 fASAPUploads.reset();
Brian Salomon7dc6e752017-11-02 11:34:51 -040074 fInlineUploads.reset();
75 fDraws.reset();
76 fMeshes.reset();
77 fCurrMesh = 0;
78 fBaseDrawToken = GrDeferredUploadToken::AlreadyFlushedToken();
79}
80
Brian Salomon943ed792017-10-30 09:37:55 -040081void GrOpFlushState::doUpload(GrDeferredTextureUploadFn& upload) {
Robert Phillips88260b52018-01-19 12:56:09 -050082 GrDeferredTextureUploadWritePixelsFn wp = [this](GrTextureProxy* dstProxy, int left, int top,
Brian Salomonc320b152018-02-20 14:05:36 -050083 int width, int height,
84 GrColorType srcColorType, const void* buffer,
85 size_t rowBytes) {
Brian Salomon9b009bb2018-02-14 13:53:55 -050086 // We don't allow srgb conversions via op flush state uploads.
87 static constexpr auto kSRGBConversion = GrSRGBConversion::kNone;
Robert Phillips88260b52018-01-19 12:56:09 -050088 GrSurface* dstSurface = dstProxy->priv().peekSurface();
Brian Salomon9bada542017-06-12 12:09:30 -040089 GrGpu::DrawPreference drawPreference = GrGpu::kNoDraw_DrawPreference;
90 GrGpu::WritePixelTempDrawInfo tempInfo;
Brian Salomonc320b152018-02-20 14:05:36 -050091 if (!fGpu->getWritePixelsInfo(dstSurface, dstProxy->origin(), width, height, srcColorType,
Brian Salomon9b009bb2018-02-14 13:53:55 -050092 kSRGBConversion, &drawPreference, &tempInfo)) {
Robert Phillips88260b52018-01-19 12:56:09 -050093 return false;
94 }
Brian Salomon9bada542017-06-12 12:09:30 -040095 if (GrGpu::kNoDraw_DrawPreference == drawPreference) {
Brian Salomonc320b152018-02-20 14:05:36 -050096 return this->fGpu->writePixels(dstSurface, dstProxy->origin(), left, top, width, height,
97 srcColorType, buffer, rowBytes);
Brian Salomon9bada542017-06-12 12:09:30 -040098 }
Brian Salomonc320b152018-02-20 14:05:36 -050099 // TODO: Shouldn't we be bailing here if a draw is really required instead of a copy?
100 // e.g. if (tempInfo.fSwizzle != "RGBA") fail.
Brian Salomon9bada542017-06-12 12:09:30 -0400101 GrSurfaceDesc desc;
Brian Salomon9bada542017-06-12 12:09:30 -0400102 desc.fWidth = width;
103 desc.fHeight = height;
Robert Phillips88260b52018-01-19 12:56:09 -0500104 desc.fConfig = dstProxy->config();
Brian Salomon9bada542017-06-12 12:09:30 -0400105 sk_sp<GrTexture> temp(this->fResourceProvider->createApproxTexture(
106 desc, GrResourceProvider::kNoPendingIO_Flag));
107 if (!temp) {
108 return false;
109 }
Brian Salomonc320b152018-02-20 14:05:36 -0500110 if (!fGpu->writePixels(temp.get(), dstProxy->origin(), 0, 0, width, height,
111 tempInfo.fWriteColorType, buffer, rowBytes)) {
Brian Salomon9bada542017-06-12 12:09:30 -0400112 return false;
113 }
Robert Phillips88260b52018-01-19 12:56:09 -0500114 return fGpu->copySurface(dstSurface, dstProxy->origin(), temp.get(), dstProxy->origin(),
Robert Phillipsacaa6072017-07-28 10:54:53 -0400115 SkIRect::MakeWH(width, height), {left, top});
Brian Salomon9bada542017-06-12 12:09:30 -0400116 };
117 upload(wp);
118}
Brian Salomon29b60c92017-10-31 14:42:10 -0400119
120GrDeferredUploadToken GrOpFlushState::addInlineUpload(GrDeferredTextureUploadFn&& upload) {
Robert Phillips40a29d72018-01-18 12:59:22 -0500121 return fInlineUploads.append(&fArena, std::move(upload), fTokenTracker->nextDrawToken())
Brian Salomon7dc6e752017-11-02 11:34:51 -0400122 .fUploadBeforeToken;
Brian Salomon29b60c92017-10-31 14:42:10 -0400123}
124
125GrDeferredUploadToken GrOpFlushState::addASAPUpload(GrDeferredTextureUploadFn&& upload) {
Robert Phillips40a29d72018-01-18 12:59:22 -0500126 fASAPUploads.append(&fArena, std::move(upload));
127 return fTokenTracker->nextTokenToFlush();
Brian Salomon29b60c92017-10-31 14:42:10 -0400128}
129
130void GrOpFlushState::draw(const GrGeometryProcessor* gp, const GrPipeline* pipeline,
131 const GrMesh& mesh) {
132 SkASSERT(fOpArgs);
133 SkASSERT(fOpArgs->fOp);
Brian Salomon7dc6e752017-11-02 11:34:51 -0400134 fMeshes.push_back(mesh);
135 bool firstDraw = fDraws.begin() == fDraws.end();
136 if (!firstDraw) {
137 Draw& lastDraw = *fDraws.begin();
Brian Salomon29b60c92017-10-31 14:42:10 -0400138 // If the last draw shares a geometry processor and pipeline and there are no intervening
139 // uploads, add this mesh to it.
Brian Salomon7dc6e752017-11-02 11:34:51 -0400140 if (lastDraw.fGeometryProcessor == gp && lastDraw.fPipeline == pipeline) {
141 if (fInlineUploads.begin() == fInlineUploads.end() ||
Robert Phillips40a29d72018-01-18 12:59:22 -0500142 fInlineUploads.tail()->fUploadBeforeToken != fTokenTracker->nextDrawToken()) {
Brian Salomon7dc6e752017-11-02 11:34:51 -0400143 ++lastDraw.fMeshCnt;
144 return;
145 }
Brian Salomon29b60c92017-10-31 14:42:10 -0400146 }
147 }
Brian Salomon7dc6e752017-11-02 11:34:51 -0400148 auto& draw = fDraws.append(&fArena);
Robert Phillips40a29d72018-01-18 12:59:22 -0500149 GrDeferredUploadToken token = fTokenTracker->issueDrawToken();
Brian Salomon29b60c92017-10-31 14:42:10 -0400150
Brian Salomon7dc6e752017-11-02 11:34:51 -0400151 draw.fGeometryProcessor.reset(gp);
152 draw.fPipeline = pipeline;
153 draw.fMeshCnt = 1;
154 draw.fOpID = fOpArgs->fOp->uniqueID();
155 if (firstDraw) {
156 fBaseDrawToken = token;
Brian Salomon29b60c92017-10-31 14:42:10 -0400157 }
158}
159
160void* GrOpFlushState::makeVertexSpace(size_t vertexSize, int vertexCount, const GrBuffer** buffer,
161 int* startVertex) {
162 return fVertexPool.makeSpace(vertexSize, vertexCount, buffer, startVertex);
163}
164
165uint16_t* GrOpFlushState::makeIndexSpace(int indexCount, const GrBuffer** buffer, int* startIndex) {
166 return reinterpret_cast<uint16_t*>(fIndexPool.makeSpace(indexCount, buffer, startIndex));
167}
168
169void* GrOpFlushState::makeVertexSpaceAtLeast(size_t vertexSize, int minVertexCount,
170 int fallbackVertexCount, const GrBuffer** buffer,
171 int* startVertex, int* actualVertexCount) {
172 return fVertexPool.makeSpaceAtLeast(vertexSize, minVertexCount, fallbackVertexCount, buffer,
173 startVertex, actualVertexCount);
174}
175
176uint16_t* GrOpFlushState::makeIndexSpaceAtLeast(int minIndexCount, int fallbackIndexCount,
177 const GrBuffer** buffer, int* startIndex,
178 int* actualIndexCount) {
179 return reinterpret_cast<uint16_t*>(fIndexPool.makeSpaceAtLeast(
180 minIndexCount, fallbackIndexCount, buffer, startIndex, actualIndexCount));
181}
182
183void GrOpFlushState::putBackIndices(int indexCount) {
184 fIndexPool.putBack(indexCount * sizeof(uint16_t));
185}
186
187void GrOpFlushState::putBackVertices(int vertices, size_t vertexStride) {
188 fVertexPool.putBack(vertices * vertexStride);
189}
190
191GrAppliedClip GrOpFlushState::detachAppliedClip() {
192 return fOpArgs->fAppliedClip ? std::move(*fOpArgs->fAppliedClip) : GrAppliedClip();
193}
Robert Phillipsc4039ea2018-03-01 11:36:45 -0500194
195GrGlyphCache* GrOpFlushState::glyphCache() const {
196 return fGpu->getContext()->contextPriv().getGlyphCache();
197}
198
Robert Phillips5a66efb2018-03-07 15:13:18 -0500199GrAtlasManager* GrOpFlushState::atlasManager() const {
200 return fGpu->getContext()->contextPriv().getAtlasManager();
Robert Phillipsc4039ea2018-03-01 11:36:45 -0500201}