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/GrTexture.h"
11 #include "src/core/SkConvertPixels.h"
12 #include "src/gpu/GrContextPriv.h"
13 #include "src/gpu/GrDrawOpAtlas.h"
14 #include "src/gpu/GrGpu.h"
15 #include "src/gpu/GrResourceProvider.h"
16
17 //////////////////////////////////////////////////////////////////////////////
18
GrOpFlushState(GrGpu * gpu,GrResourceProvider * resourceProvider,GrTokenTracker * tokenTracker,sk_sp<GrBufferAllocPool::CpuBufferCache> cpuBufferCache)19 GrOpFlushState::GrOpFlushState(GrGpu* gpu, GrResourceProvider* resourceProvider,
20 GrTokenTracker* tokenTracker,
21 sk_sp<GrBufferAllocPool::CpuBufferCache> cpuBufferCache)
22 : fVertexPool(gpu, cpuBufferCache)
23 , fIndexPool(gpu, std::move(cpuBufferCache))
24 , fGpu(gpu)
25 , fResourceProvider(resourceProvider)
26 , fTokenTracker(tokenTracker)
27 , fDeinstantiateProxyTracker() {}
28
caps() const29 const GrCaps& GrOpFlushState::caps() const {
30 return *fGpu->caps();
31 }
32
rtCommandBuffer()33 GrGpuRTCommandBuffer* GrOpFlushState::rtCommandBuffer() {
34 return fCommandBuffer->asRTCommandBuffer();
35 }
36
executeDrawsAndUploadsForMeshDrawOp(const GrOp * op,const SkRect & chainBounds,GrProcessorSet && processorSet,GrPipeline::InputFlags pipelineFlags,const GrUserStencilSettings * stencilSettings)37 void GrOpFlushState::executeDrawsAndUploadsForMeshDrawOp(
38 const GrOp* op, const SkRect& chainBounds, GrProcessorSet&& processorSet,
39 GrPipeline::InputFlags pipelineFlags, const GrUserStencilSettings* stencilSettings) {
40 SkASSERT(this->rtCommandBuffer());
41
42 GrPipeline::InitArgs pipelineArgs;
43 pipelineArgs.fInputFlags = pipelineFlags;
44 pipelineArgs.fDstProxy = this->dstProxy();
45 pipelineArgs.fCaps = &this->caps();
46 pipelineArgs.fUserStencil = stencilSettings;
47 pipelineArgs.fOutputSwizzle = this->drawOpArgs().fOutputSwizzle;
48 GrPipeline* pipeline = this->allocator()->make<GrPipeline>(pipelineArgs,
49 std::move(processorSet),
50 this->detachAppliedClip());
51
52 while (fCurrDraw != fDraws.end() && fCurrDraw->fOp == op) {
53 GrDeferredUploadToken drawToken = fTokenTracker->nextTokenToFlush();
54 while (fCurrUpload != fInlineUploads.end() &&
55 fCurrUpload->fUploadBeforeToken == drawToken) {
56 this->rtCommandBuffer()->inlineUpload(this, fCurrUpload->fUpload);
57 ++fCurrUpload;
58 }
59 this->rtCommandBuffer()->draw(
60 *fCurrDraw->fGeometryProcessor, *pipeline, fCurrDraw->fFixedDynamicState,
61 fCurrDraw->fDynamicStateArrays, fCurrDraw->fMeshes, fCurrDraw->fMeshCnt,
62 chainBounds);
63 fTokenTracker->flushToken();
64 ++fCurrDraw;
65 }
66 }
67
preExecuteDraws()68 void GrOpFlushState::preExecuteDraws() {
69 fVertexPool.unmap();
70 fIndexPool.unmap();
71 for (auto& upload : fASAPUploads) {
72 this->doUpload(upload);
73 }
74 // Setup execution iterators.
75 fCurrDraw = fDraws.begin();
76 fCurrUpload = fInlineUploads.begin();
77 }
78
reset()79 void GrOpFlushState::reset() {
80 SkASSERT(fCurrDraw == fDraws.end());
81 SkASSERT(fCurrUpload == fInlineUploads.end());
82 fVertexPool.reset();
83 fIndexPool.reset();
84 fArena.reset();
85 fASAPUploads.reset();
86 fInlineUploads.reset();
87 fDraws.reset();
88 fBaseDrawToken = GrDeferredUploadToken::AlreadyFlushedToken();
89 }
90
doUpload(GrDeferredTextureUploadFn & upload)91 void GrOpFlushState::doUpload(GrDeferredTextureUploadFn& upload) {
92 GrDeferredTextureUploadWritePixelsFn wp = [this](GrTextureProxy* dstProxy, int left, int top,
93 int width, int height, GrColorType colorType,
94 const void* buffer, size_t rowBytes) {
95 GrSurface* dstSurface = dstProxy->peekSurface();
96 if (!fGpu->caps()->surfaceSupportsWritePixels(dstSurface)) {
97 return false;
98 }
99 GrCaps::SupportedWrite supportedWrite = fGpu->caps()->supportedWritePixelsColorType(
100 colorType, dstSurface->backendFormat(), colorType);
101 size_t tightRB = width * GrColorTypeBytesPerPixel(supportedWrite.fColorType);
102 SkASSERT(rowBytes >= tightRB);
103 std::unique_ptr<char[]> tmpPixels;
104 if (supportedWrite.fColorType != colorType ||
105 (!fGpu->caps()->writePixelsRowBytesSupport() && rowBytes != tightRB)) {
106 tmpPixels.reset(new char[height * tightRB]);
107 // Use kUnpremul to ensure no alpha type conversions or clamping occur.
108 static constexpr auto kAT = kUnpremul_SkAlphaType;
109 GrPixelInfo srcInfo(colorType, kAT, nullptr, width, height);
110 GrPixelInfo tmpInfo(supportedWrite.fColorType, kAT, nullptr, width,
111 height);
112 if (!GrConvertPixels(tmpInfo, tmpPixels.get(), tightRB, srcInfo, buffer, rowBytes)) {
113 return false;
114 }
115 rowBytes = tightRB;
116 buffer = tmpPixels.get();
117 }
118 return this->fGpu->writePixels(dstSurface, left, top, width, height, colorType,
119 supportedWrite.fColorType, buffer, rowBytes);
120 };
121 upload(wp);
122 }
123
addInlineUpload(GrDeferredTextureUploadFn && upload)124 GrDeferredUploadToken GrOpFlushState::addInlineUpload(GrDeferredTextureUploadFn&& upload) {
125 return fInlineUploads.append(&fArena, std::move(upload), fTokenTracker->nextDrawToken())
126 .fUploadBeforeToken;
127 }
128
addASAPUpload(GrDeferredTextureUploadFn && upload)129 GrDeferredUploadToken GrOpFlushState::addASAPUpload(GrDeferredTextureUploadFn&& upload) {
130 fASAPUploads.append(&fArena, std::move(upload));
131 return fTokenTracker->nextTokenToFlush();
132 }
133
recordDraw(sk_sp<const GrGeometryProcessor> gp,const GrMesh meshes[],int meshCnt,const GrPipeline::FixedDynamicState * fixedDynamicState,const GrPipeline::DynamicStateArrays * dynamicStateArrays)134 void GrOpFlushState::recordDraw(
135 sk_sp<const GrGeometryProcessor> gp, const GrMesh meshes[], int meshCnt,
136 const GrPipeline::FixedDynamicState* fixedDynamicState,
137 const GrPipeline::DynamicStateArrays* dynamicStateArrays) {
138 SkASSERT(fOpArgs);
139 SkASSERT(fOpArgs->fOp);
140 bool firstDraw = fDraws.begin() == fDraws.end();
141 auto& draw = fDraws.append(&fArena);
142 GrDeferredUploadToken token = fTokenTracker->issueDrawToken();
143 if (fixedDynamicState && fixedDynamicState->fPrimitiveProcessorTextures) {
144 for (int i = 0; i < gp->numTextureSamplers(); ++i) {
145 fixedDynamicState->fPrimitiveProcessorTextures[i]->ref();
146 }
147 }
148 if (dynamicStateArrays && dynamicStateArrays->fPrimitiveProcessorTextures) {
149 int n = gp->numTextureSamplers() * meshCnt;
150 for (int i = 0; i < n; ++i) {
151 dynamicStateArrays->fPrimitiveProcessorTextures[i]->ref();
152 }
153 }
154 draw.fGeometryProcessor = std::move(gp);
155 draw.fFixedDynamicState = fixedDynamicState;
156 draw.fDynamicStateArrays = dynamicStateArrays;
157 draw.fMeshes = meshes;
158 draw.fMeshCnt = meshCnt;
159 draw.fOp = fOpArgs->fOp;
160 if (firstDraw) {
161 fBaseDrawToken = token;
162 }
163 }
164
makeVertexSpace(size_t vertexSize,int vertexCount,sk_sp<const GrBuffer> * buffer,int * startVertex)165 void* GrOpFlushState::makeVertexSpace(size_t vertexSize, int vertexCount,
166 sk_sp<const GrBuffer>* buffer, int* startVertex) {
167 return fVertexPool.makeSpace(vertexSize, vertexCount, buffer, startVertex);
168 }
169
makeIndexSpace(int indexCount,sk_sp<const GrBuffer> * buffer,int * startIndex)170 uint16_t* GrOpFlushState::makeIndexSpace(int indexCount, sk_sp<const GrBuffer>* buffer,
171 int* startIndex) {
172 return reinterpret_cast<uint16_t*>(fIndexPool.makeSpace(indexCount, buffer, startIndex));
173 }
174
makeVertexSpaceAtLeast(size_t vertexSize,int minVertexCount,int fallbackVertexCount,sk_sp<const GrBuffer> * buffer,int * startVertex,int * actualVertexCount)175 void* GrOpFlushState::makeVertexSpaceAtLeast(size_t vertexSize, int minVertexCount,
176 int fallbackVertexCount, sk_sp<const GrBuffer>* buffer,
177 int* startVertex, int* actualVertexCount) {
178 return fVertexPool.makeSpaceAtLeast(vertexSize, minVertexCount, fallbackVertexCount, buffer,
179 startVertex, actualVertexCount);
180 }
181
makeIndexSpaceAtLeast(int minIndexCount,int fallbackIndexCount,sk_sp<const GrBuffer> * buffer,int * startIndex,int * actualIndexCount)182 uint16_t* GrOpFlushState::makeIndexSpaceAtLeast(int minIndexCount, int fallbackIndexCount,
183 sk_sp<const GrBuffer>* buffer, int* startIndex,
184 int* actualIndexCount) {
185 return reinterpret_cast<uint16_t*>(fIndexPool.makeSpaceAtLeast(
186 minIndexCount, fallbackIndexCount, buffer, startIndex, actualIndexCount));
187 }
188
putBackIndices(int indexCount)189 void GrOpFlushState::putBackIndices(int indexCount) {
190 fIndexPool.putBack(indexCount * sizeof(uint16_t));
191 }
192
putBackVertices(int vertices,size_t vertexStride)193 void GrOpFlushState::putBackVertices(int vertices, size_t vertexStride) {
194 fVertexPool.putBack(vertices * vertexStride);
195 }
196
detachAppliedClip()197 GrAppliedClip GrOpFlushState::detachAppliedClip() {
198 return fOpArgs->fAppliedClip ? std::move(*fOpArgs->fAppliedClip) : GrAppliedClip();
199 }
200
glyphCache() const201 GrStrikeCache* GrOpFlushState::glyphCache() const {
202 return fGpu->getContext()->priv().getGrStrikeCache();
203 }
204
atlasManager() const205 GrAtlasManager* GrOpFlushState::atlasManager() const {
206 return fGpu->getContext()->priv().getAtlasManager();
207 }
208
209 //////////////////////////////////////////////////////////////////////////////
210
~Draw()211 GrOpFlushState::Draw::~Draw() {
212 if (fFixedDynamicState && fFixedDynamicState->fPrimitiveProcessorTextures) {
213 for (int i = 0; i < fGeometryProcessor->numTextureSamplers(); ++i) {
214 fFixedDynamicState->fPrimitiveProcessorTextures[i]->unref();
215 }
216 }
217 if (fDynamicStateArrays && fDynamicStateArrays->fPrimitiveProcessorTextures) {
218 int n = fGeometryProcessor->numTextureSamplers() * fMeshCnt;
219 const auto* textures = fDynamicStateArrays->fPrimitiveProcessorTextures;
220 for (int i = 0; i < n; ++i) {
221 textures[i]->unref();
222 }
223 }
224 }
225