blob: d68a24292e54e9150382e8e30a561f29096b5fa5 [file] [log] [blame]
robertphillips193ea932015-03-03 12:40:49 -08001/*
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 "GrTargetCommands.h"
9
10#include "GrColor.h"
11#include "GrDefaultGeoProcFactory.h"
12#include "GrInOrderDrawBuffer.h"
13#include "GrTemplates.h"
14#include "SkPoint.h"
15
robertphillips193ea932015-03-03 12:40:49 -080016static bool path_fill_type_is_winding(const GrStencilSettings& pathStencilSettings) {
17 static const GrStencilSettings::Face pathFace = GrStencilSettings::kFront_Face;
18 bool isWinding = kInvert_StencilOp != pathStencilSettings.passOp(pathFace);
19 if (isWinding) {
20 // Double check that it is in fact winding.
21 SkASSERT(kIncClamp_StencilOp == pathStencilSettings.passOp(pathFace));
22 SkASSERT(kIncClamp_StencilOp == pathStencilSettings.failOp(pathFace));
23 SkASSERT(0x1 != pathStencilSettings.writeMask(pathFace));
24 SkASSERT(!pathStencilSettings.isTwoSided());
25 }
26 return isWinding;
27}
28
joshualitt09114302015-05-04 10:41:57 -070029GrTargetCommands::Cmd* GrTargetCommands::recordDrawBatch(State* state, GrBatch* batch) {
robertphillips193ea932015-03-03 12:40:49 -080030 // Check if there is a Batch Draw we can batch with
joshualitt09114302015-05-04 10:41:57 -070031 if (!fCmdBuffer.empty() && Cmd::kDrawBatch_CmdType == fCmdBuffer.back().type()) {
joshualitta30009b2015-04-30 09:05:54 -070032 DrawBatch* previous = static_cast<DrawBatch*>(&fCmdBuffer.back());
joshualitt09114302015-05-04 10:41:57 -070033 if (previous->fState == state && previous->fBatch->combineIfPossible(batch)) {
joshualitta30009b2015-04-30 09:05:54 -070034 return NULL;
35 }
robertphillips193ea932015-03-03 12:40:49 -080036 }
37
joshualitt09114302015-05-04 10:41:57 -070038 return GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawBatch, (state, batch, &fBatchTarget));
robertphillips193ea932015-03-03 12:40:49 -080039}
40
41GrTargetCommands::Cmd* GrTargetCommands::recordStencilPath(
robertphillips193ea932015-03-03 12:40:49 -080042 const GrPipelineBuilder& pipelineBuilder,
43 const GrPathProcessor* pathProc,
44 const GrPath* path,
45 const GrScissorState& scissorState,
46 const GrStencilSettings& stencilSettings) {
robertphillips193ea932015-03-03 12:40:49 -080047 StencilPath* sp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, StencilPath,
48 (path, pipelineBuilder.getRenderTarget()));
49
50 sp->fScissor = scissorState;
51 sp->fUseHWAA = pipelineBuilder.isHWAntialias();
52 sp->fViewMatrix = pathProc->viewMatrix();
53 sp->fStencil = stencilSettings;
54 return sp;
55}
56
57GrTargetCommands::Cmd* GrTargetCommands::recordDrawPath(
joshualitt09114302015-05-04 10:41:57 -070058 State* state,
robertphillips193ea932015-03-03 12:40:49 -080059 const GrPathProcessor* pathProc,
60 const GrPath* path,
joshualitt09114302015-05-04 10:41:57 -070061 const GrStencilSettings& stencilSettings) {
62 DrawPath* dp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawPath, (state, path));
robertphillips193ea932015-03-03 12:40:49 -080063 dp->fStencilSettings = stencilSettings;
64 return dp;
65}
66
67GrTargetCommands::Cmd* GrTargetCommands::recordDrawPaths(
joshualitt09114302015-05-04 10:41:57 -070068 State* state,
robertphillips193ea932015-03-03 12:40:49 -080069 GrInOrderDrawBuffer* iodb,
70 const GrPathProcessor* pathProc,
71 const GrPathRange* pathRange,
72 const void* indexValues,
73 GrDrawTarget::PathIndexType indexType,
74 const float transformValues[],
75 GrDrawTarget::PathTransformType transformType,
76 int count,
77 const GrStencilSettings& stencilSettings,
78 const GrDrawTarget::PipelineInfo& pipelineInfo) {
79 SkASSERT(pathRange);
80 SkASSERT(indexValues);
81 SkASSERT(transformValues);
robertphillips193ea932015-03-03 12:40:49 -080082
robertphillips193ea932015-03-03 12:40:49 -080083 char* savedIndices;
84 float* savedTransforms;
85
86 iodb->appendIndicesAndTransforms(indexValues, indexType,
87 transformValues, transformType,
88 count, &savedIndices, &savedTransforms);
89
joshualitt09114302015-05-04 10:41:57 -070090 if (!fCmdBuffer.empty() && Cmd::kDrawPaths_CmdType == fCmdBuffer.back().type()) {
robertphillips193ea932015-03-03 12:40:49 -080091 // The previous command was also DrawPaths. Try to collapse this call into the one
92 // before. Note that stenciling all the paths at once, then covering, may not be
93 // equivalent to two separate draw calls if there is overlap. Blending won't work,
94 // and the combined calls may also cancel each other's winding numbers in some
95 // places. For now the winding numbers are only an issue if the fill is even/odd,
96 // because DrawPaths is currently only used for glyphs, and glyphs in the same
97 // font tend to all wind in the same direction.
98 DrawPaths* previous = static_cast<DrawPaths*>(&fCmdBuffer.back());
99 if (pathRange == previous->pathRange() &&
100 indexType == previous->fIndexType &&
101 transformType == previous->fTransformType &&
102 stencilSettings == previous->fStencilSettings &&
103 path_fill_type_is_winding(stencilSettings) &&
joshualitt09114302015-05-04 10:41:57 -0700104 !pipelineInfo.willBlendWithDst(pathProc) &&
105 previous->fState == state) {
robertphillips193ea932015-03-03 12:40:49 -0800106 const int indexBytes = GrPathRange::PathIndexSizeInBytes(indexType);
107 const int xformSize = GrPathRendering::PathTransformSize(transformType);
108 if (&previous->fIndices[previous->fCount*indexBytes] == savedIndices &&
109 (0 == xformSize ||
110 &previous->fTransforms[previous->fCount*xformSize] == savedTransforms)) {
111 // Fold this DrawPaths call into the one previous.
112 previous->fCount += count;
113 return NULL;
114 }
115 }
116 }
117
joshualitt09114302015-05-04 10:41:57 -0700118 DrawPaths* dp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawPaths, (state, pathRange));
robertphillips193ea932015-03-03 12:40:49 -0800119 dp->fIndices = savedIndices;
120 dp->fIndexType = indexType;
121 dp->fTransforms = savedTransforms;
122 dp->fTransformType = transformType;
123 dp->fCount = count;
124 dp->fStencilSettings = stencilSettings;
125 return dp;
126}
127
joshualitt09114302015-05-04 10:41:57 -0700128GrTargetCommands::Cmd* GrTargetCommands::recordClear(const SkIRect* rect,
robertphillips193ea932015-03-03 12:40:49 -0800129 GrColor color,
130 bool canIgnoreRect,
131 GrRenderTarget* renderTarget) {
132 SkASSERT(renderTarget);
robertphillips193ea932015-03-03 12:40:49 -0800133
134 SkIRect r;
135 if (NULL == rect) {
136 // We could do something smart and remove previous draws and clears to
137 // the current render target. If we get that smart we have to make sure
138 // those draws aren't read before this clear (render-to-texture).
139 r.setLTRB(0, 0, renderTarget->width(), renderTarget->height());
140 rect = &r;
141 }
142 Clear* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Clear, (renderTarget));
143 GrColorIsPMAssert(color);
144 clr->fColor = color;
145 clr->fRect = *rect;
146 clr->fCanIgnoreRect = canIgnoreRect;
147 return clr;
148}
149
joshualitt09114302015-05-04 10:41:57 -0700150GrTargetCommands::Cmd* GrTargetCommands::recordClearStencilClip(const SkIRect& rect,
robertphillips193ea932015-03-03 12:40:49 -0800151 bool insideClip,
152 GrRenderTarget* renderTarget) {
153 SkASSERT(renderTarget);
robertphillips193ea932015-03-03 12:40:49 -0800154
155 ClearStencilClip* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, ClearStencilClip, (renderTarget));
156 clr->fRect = rect;
157 clr->fInsideClip = insideClip;
158 return clr;
159}
160
joshualitt09114302015-05-04 10:41:57 -0700161GrTargetCommands::Cmd* GrTargetCommands::recordDiscard(GrRenderTarget* renderTarget) {
robertphillips193ea932015-03-03 12:40:49 -0800162 SkASSERT(renderTarget);
robertphillips193ea932015-03-03 12:40:49 -0800163
164 Clear* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Clear, (renderTarget));
165 clr->fColor = GrColor_ILLEGAL;
166 return clr;
167}
168
169void GrTargetCommands::reset() {
170 fCmdBuffer.reset();
robertphillips193ea932015-03-03 12:40:49 -0800171}
172
173void GrTargetCommands::flush(GrInOrderDrawBuffer* iodb) {
174 if (fCmdBuffer.empty()) {
175 return;
176 }
177
joshualitt385e26e2015-04-27 11:42:30 -0700178 GrGpu* gpu = iodb->getGpu();
179
joshualitt0dcb8e32015-04-27 12:03:05 -0700180 // Loop over all batches and generate geometry
181 CmdBuffer::Iter genIter(fCmdBuffer);
182 while (genIter.next()) {
183 if (Cmd::kDrawBatch_CmdType == genIter->type()) {
184 DrawBatch* db = reinterpret_cast<DrawBatch*>(genIter.get());
185 fBatchTarget.resetNumberOfDraws();
joshualitt09114302015-05-04 10:41:57 -0700186 db->fBatch->generateGeometry(&fBatchTarget, db->fState->getPipeline());
joshualitt0dcb8e32015-04-27 12:03:05 -0700187 db->fBatch->setNumberOfDraws(fBatchTarget.numberOfDraws());
joshualitt0dcb8e32015-04-27 12:03:05 -0700188 }
189 }
joshualitt0dcb8e32015-04-27 12:03:05 -0700190
191 iodb->getVertexAllocPool()->unmap();
192 iodb->getIndexAllocPool()->unmap();
193 fBatchTarget.preFlush();
194
195 CmdBuffer::Iter iter(fCmdBuffer);
196
robertphillips193ea932015-03-03 12:40:49 -0800197 while (iter.next()) {
robertphillips193ea932015-03-03 12:40:49 -0800198 GrGpuTraceMarker newMarker("", -1);
199 SkString traceString;
200 if (iter->isTraced()) {
robertphillipsbca3c9f2015-03-05 09:17:17 -0800201 traceString = iodb->getCmdString(iter->markerID());
robertphillips193ea932015-03-03 12:40:49 -0800202 newMarker.fMarker = traceString.c_str();
203 gpu->addGpuTraceMarker(&newMarker);
robertphillips193ea932015-03-03 12:40:49 -0800204 }
205
joshualitt09114302015-05-04 10:41:57 -0700206 iter->execute(gpu);
robertphillips193ea932015-03-03 12:40:49 -0800207 if (iter->isTraced()) {
208 gpu->removeGpuTraceMarker(&newMarker);
209 }
210 }
211
robertphillips193ea932015-03-03 12:40:49 -0800212 fBatchTarget.postFlush();
213}
214
joshualitt09114302015-05-04 10:41:57 -0700215void GrTargetCommands::StencilPath::execute(GrGpu* gpu) {
robertphillips193ea932015-03-03 12:40:49 -0800216 GrGpu::StencilPathState state;
217 state.fRenderTarget = fRenderTarget.get();
218 state.fScissor = &fScissor;
219 state.fStencil = &fStencil;
220 state.fUseHWAA = fUseHWAA;
221 state.fViewMatrix = &fViewMatrix;
222
223 gpu->stencilPath(this->path(), state);
224}
225
joshualitt09114302015-05-04 10:41:57 -0700226void GrTargetCommands::DrawPath::execute(GrGpu* gpu) {
227 if (!fState->fCompiled) {
228 gpu->buildProgramDesc(&fState->fDesc, *fState->fPrimitiveProcessor, *fState->getPipeline(),
229 fState->fBatchTracker);
230 fState->fCompiled = true;
231 }
232 DrawArgs args(fState->fPrimitiveProcessor.get(), fState->getPipeline(),
233 &fState->fDesc, &fState->fBatchTracker);
robertphillips193ea932015-03-03 12:40:49 -0800234 gpu->drawPath(args, this->path(), fStencilSettings);
235}
236
joshualitt09114302015-05-04 10:41:57 -0700237void GrTargetCommands::DrawPaths::execute(GrGpu* gpu) {
238 if (!fState->fCompiled) {
239 gpu->buildProgramDesc(&fState->fDesc, *fState->fPrimitiveProcessor, *fState->getPipeline(),
240 fState->fBatchTracker);
241 fState->fCompiled = true;
242 }
243 DrawArgs args(fState->fPrimitiveProcessor.get(), fState->getPipeline(),
244 &fState->fDesc, &fState->fBatchTracker);
robertphillips193ea932015-03-03 12:40:49 -0800245 gpu->drawPaths(args, this->pathRange(),
246 fIndices, fIndexType,
247 fTransforms, fTransformType,
248 fCount, fStencilSettings);
249}
250
joshualitt09114302015-05-04 10:41:57 -0700251void GrTargetCommands::DrawBatch::execute(GrGpu*) {
252 fBatchTarget->flushNext(fBatch->numberOfDraws());
robertphillips193ea932015-03-03 12:40:49 -0800253}
254
joshualitt09114302015-05-04 10:41:57 -0700255void GrTargetCommands::Clear::execute(GrGpu* gpu) {
robertphillips193ea932015-03-03 12:40:49 -0800256 if (GrColor_ILLEGAL == fColor) {
257 gpu->discard(this->renderTarget());
258 } else {
259 gpu->clear(&fRect, fColor, fCanIgnoreRect, this->renderTarget());
260 }
261}
262
joshualitt09114302015-05-04 10:41:57 -0700263void GrTargetCommands::ClearStencilClip::execute(GrGpu* gpu) {
robertphillips193ea932015-03-03 12:40:49 -0800264 gpu->clearStencilClip(fRect, fInsideClip, this->renderTarget());
265}
266
joshualitt09114302015-05-04 10:41:57 -0700267void GrTargetCommands::CopySurface::execute(GrGpu* gpu) {
robertphillips193ea932015-03-03 12:40:49 -0800268 gpu->copySurface(this->dst(), this->src(), fSrcRect, fDstPoint);
269}
270
joshualitt09114302015-05-04 10:41:57 -0700271void GrTargetCommands::XferBarrier::execute(GrGpu* gpu) {
cdalton9954bc32015-04-29 14:17:00 -0700272 gpu->xferBarrier(fBarrierType);
273}
274
bsalomona73239a2015-04-28 13:35:17 -0700275GrTargetCommands::Cmd* GrTargetCommands::recordCopySurface(GrSurface* dst,
robertphillips193ea932015-03-03 12:40:49 -0800276 GrSurface* src,
277 const SkIRect& srcRect,
278 const SkIPoint& dstPoint) {
bsalomona73239a2015-04-28 13:35:17 -0700279 CopySurface* cs = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, CopySurface, (dst, src));
280 cs->fSrcRect = srcRect;
281 cs->fDstPoint = dstPoint;
282 return cs;
robertphillips193ea932015-03-03 12:40:49 -0800283}
284
joshualitt09114302015-05-04 10:41:57 -0700285void GrTargetCommands::recordXferBarrierIfNecessary(const GrPipeline& pipeline,
286 GrInOrderDrawBuffer* iodb) {
287 const GrXferProcessor& xp = *pipeline.getXferProcessor();
288 GrRenderTarget* rt = pipeline.getRenderTarget();
cdalton9954bc32015-04-29 14:17:00 -0700289
290 GrXferBarrierType barrierType;
291 if (!xp.willNeedXferBarrier(rt, *iodb->caps(), &barrierType)) {
292 return;
293 }
294
295 XferBarrier* xb = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, XferBarrier, ());
296 xb->fBarrierType = barrierType;
297
298 iodb->recordTraceMarkersIfNecessary(xb);
299}
300