Update rive-cpp to 2.0 version
[platform/core/uifw/rive-tizen.git] / submodule / skia / src / gpu / ganesh / GrOpsRenderPass.cpp
1 /*
2 * Copyright 2016 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/ganesh/GrOpsRenderPass.h"
9
10 #include "include/core/SkRect.h"
11 #include "src/gpu/ganesh/GrCaps.h"
12 #include "src/gpu/ganesh/GrCpuBuffer.h"
13 #include "src/gpu/ganesh/GrDrawIndirectCommand.h"
14 #include "src/gpu/ganesh/GrGeometryProcessor.h"
15 #include "src/gpu/ganesh/GrGpu.h"
16 #include "src/gpu/ganesh/GrProgramInfo.h"
17 #include "src/gpu/ganesh/GrRenderTarget.h"
18 #include "src/gpu/ganesh/GrScissorState.h"
19 #include "src/gpu/ganesh/GrSimpleMesh.h"
20 #include "src/gpu/ganesh/GrTexture.h"
21
22 void GrOpsRenderPass::begin() {
23     fDrawPipelineStatus = DrawPipelineStatus::kNotConfigured;
24 #ifdef SK_DEBUG
25     fScissorStatus = DynamicStateStatus::kDisabled;
26     fTextureBindingStatus = DynamicStateStatus::kDisabled;
27     fHasIndexBuffer = false;
28     fInstanceBufferStatus = DynamicStateStatus::kDisabled;
29     fVertexBufferStatus = DynamicStateStatus::kDisabled;
30 #endif
31     this->onBegin();
32 }
33
34 void GrOpsRenderPass::end() {
35     this->onEnd();
36     this->resetActiveBuffers();
37 }
38
39 void GrOpsRenderPass::clear(const GrScissorState& scissor, std::array<float, 4> color) {
40     SkASSERT(fRenderTarget);
41     // A clear at this level will always be a true clear, so make sure clears were not supposed to
42     // be redirected to draws instead
43     SkASSERT(!this->gpu()->caps()->performColorClearsAsDraws());
44     SkASSERT(!scissor.enabled() || !this->gpu()->caps()->performPartialClearsAsDraws());
45     fDrawPipelineStatus = DrawPipelineStatus::kNotConfigured;
46     this->onClear(scissor, color);
47 }
48
49 void GrOpsRenderPass::clearStencilClip(const GrScissorState& scissor, bool insideStencilMask) {
50     // As above, make sure the stencil clear wasn't supposed to be a draw rect with stencil settings
51     SkASSERT(!this->gpu()->caps()->performStencilClearsAsDraws());
52     SkASSERT(!scissor.enabled() || !this->gpu()->caps()->performPartialClearsAsDraws());
53     fDrawPipelineStatus = DrawPipelineStatus::kNotConfigured;
54     this->onClearStencilClip(scissor, insideStencilMask);
55 }
56
57 void GrOpsRenderPass::executeDrawable(std::unique_ptr<SkDrawable::GpuDrawHandler> drawable) {
58     fDrawPipelineStatus = DrawPipelineStatus::kNotConfigured;
59     this->onExecuteDrawable(std::move(drawable));
60 }
61
62 void GrOpsRenderPass::bindPipeline(const GrProgramInfo& programInfo, const SkRect& drawBounds) {
63 #ifdef SK_DEBUG
64     // Both the 'programInfo' and this renderPass have an origin. Since they come from the same
65     // place (i.e., the target renderTargetProxy) they had best agree.
66     SkASSERT(programInfo.origin() == fOrigin);
67     if (programInfo.geomProc().hasInstanceAttributes()) {
68          SkASSERT(this->gpu()->caps()->drawInstancedSupport());
69     }
70     if (programInfo.pipeline().usesConservativeRaster()) {
71         SkASSERT(this->gpu()->caps()->conservativeRasterSupport());
72     }
73     if (programInfo.pipeline().isWireframe()) {
74          SkASSERT(this->gpu()->caps()->wireframeSupport());
75     }
76     if (this->gpu()->caps()->twoSidedStencilRefsAndMasksMustMatch() &&
77         programInfo.isStencilEnabled()) {
78         const GrUserStencilSettings* stencil = programInfo.userStencilSettings();
79         if (stencil->isTwoSided(programInfo.pipeline().hasStencilClip())) {
80             SkASSERT(stencil->fCCWFace.fRef == stencil->fCWFace.fRef);
81             SkASSERT(stencil->fCCWFace.fTestMask == stencil->fCWFace.fTestMask);
82             SkASSERT(stencil->fCCWFace.fWriteMask == stencil->fCWFace.fWriteMask);
83         }
84     }
85     programInfo.checkAllInstantiated();
86     programInfo.checkMSAAAndMIPSAreResolved();
87 #endif
88
89     this->resetActiveBuffers();
90
91     if (programInfo.geomProc().numVertexAttributes() > this->gpu()->caps()->maxVertexAttributes()) {
92         fDrawPipelineStatus = DrawPipelineStatus::kFailedToBind;
93         return;
94     }
95
96     if (!this->onBindPipeline(programInfo, drawBounds)) {
97         fDrawPipelineStatus = DrawPipelineStatus::kFailedToBind;
98         return;
99     }
100
101 #ifdef SK_DEBUG
102     fScissorStatus = (programInfo.pipeline().isScissorTestEnabled()) ?
103             DynamicStateStatus::kUninitialized : DynamicStateStatus::kDisabled;
104     bool hasTextures = (programInfo.geomProc().numTextureSamplers() > 0);
105     if (!hasTextures) {
106         programInfo.pipeline().visitProxies([&hasTextures](GrSurfaceProxy*, GrMipmapped) {
107             hasTextures = true;
108         });
109     }
110     fTextureBindingStatus = (hasTextures) ?
111             DynamicStateStatus::kUninitialized : DynamicStateStatus::kDisabled;
112     fHasIndexBuffer = false;
113     fInstanceBufferStatus = (programInfo.geomProc().hasInstanceAttributes()) ?
114             DynamicStateStatus::kUninitialized : DynamicStateStatus::kDisabled;
115     fVertexBufferStatus = (programInfo.geomProc().hasVertexAttributes()) ?
116             DynamicStateStatus::kUninitialized : DynamicStateStatus::kDisabled;
117 #endif
118
119     fDrawPipelineStatus = DrawPipelineStatus::kOk;
120     fXferBarrierType = programInfo.pipeline().xferBarrierType(*this->gpu()->caps());
121 }
122
123 void GrOpsRenderPass::setScissorRect(const SkIRect& scissor) {
124     if (DrawPipelineStatus::kOk != fDrawPipelineStatus) {
125         SkASSERT(DrawPipelineStatus::kNotConfigured != fDrawPipelineStatus);
126         return;
127     }
128     SkASSERT(DynamicStateStatus::kDisabled != fScissorStatus);
129     this->onSetScissorRect(scissor);
130     SkDEBUGCODE(fScissorStatus = DynamicStateStatus::kConfigured);
131 }
132
133 void GrOpsRenderPass::bindTextures(const GrGeometryProcessor& geomProc,
134                                    const GrSurfaceProxy* const geomProcTextures[],
135                                    const GrPipeline& pipeline) {
136 #ifdef SK_DEBUG
137     SkASSERT((geomProc.numTextureSamplers() > 0) == SkToBool(geomProcTextures));
138     for (int i = 0; i < geomProc.numTextureSamplers(); ++i) {
139         const auto& sampler = geomProc.textureSampler(i);
140         const GrSurfaceProxy* proxy = geomProcTextures[i];
141         SkASSERT(proxy);
142         SkASSERT(proxy->backendFormat() == sampler.backendFormat());
143         SkASSERT(proxy->backendFormat().textureType() == sampler.backendFormat().textureType());
144
145         const GrTexture* tex = proxy->peekTexture();
146         SkASSERT(tex);
147         if (sampler.samplerState().mipmapped() == GrMipmapped::kYes &&
148             (tex->width() != 1 || tex->height() != 1)) {
149             // There are some cases where we might be given a non-mipmapped texture with a mipmap
150             // filter. See skbug.com/7094.
151             SkASSERT(tex->mipmapped() != GrMipmapped::kYes || !tex->mipmapsAreDirty());
152         }
153     }
154 #endif
155
156     if (DrawPipelineStatus::kOk != fDrawPipelineStatus) {
157         SkASSERT(DrawPipelineStatus::kNotConfigured != fDrawPipelineStatus);
158         return;
159     }
160
161     // Don't assert on fTextureBindingStatus. onBindTextures() just turns into a no-op when there
162     // aren't any textures, and it's hard to tell from the GrPipeline whether there are any. For
163     // many clients it is easier to just always call this method.
164     if (!this->onBindTextures(geomProc, geomProcTextures, pipeline)) {
165         fDrawPipelineStatus = DrawPipelineStatus::kFailedToBind;
166         return;
167     }
168
169     SkDEBUGCODE(fTextureBindingStatus = DynamicStateStatus::kConfigured);
170 }
171
172 void GrOpsRenderPass::bindBuffers(sk_sp<const GrBuffer> indexBuffer,
173                                   sk_sp<const GrBuffer> instanceBuffer,
174                                   sk_sp<const GrBuffer> vertexBuffer,
175                                   GrPrimitiveRestart primRestart) {
176     if (DrawPipelineStatus::kOk != fDrawPipelineStatus) {
177         SkASSERT(DrawPipelineStatus::kNotConfigured != fDrawPipelineStatus);
178         return;
179     }
180
181 #ifdef SK_DEBUG
182     if (indexBuffer) {
183         fHasIndexBuffer = true;
184     }
185
186     SkASSERT((DynamicStateStatus::kDisabled == fInstanceBufferStatus) != SkToBool(instanceBuffer));
187     if (instanceBuffer) {
188         fInstanceBufferStatus = DynamicStateStatus::kConfigured;
189     }
190
191     SkASSERT((DynamicStateStatus::kDisabled == fVertexBufferStatus) != SkToBool(vertexBuffer));
192     if (vertexBuffer) {
193         fVertexBufferStatus = DynamicStateStatus::kConfigured;
194     }
195
196     if (GrPrimitiveRestart::kYes == primRestart) {
197         SkASSERT(this->gpu()->caps()->usePrimitiveRestart());
198     }
199 #endif
200
201     this->onBindBuffers(std::move(indexBuffer), std::move(instanceBuffer), std::move(vertexBuffer),
202                         primRestart);
203 }
204
205 bool GrOpsRenderPass::prepareToDraw() {
206     if (DrawPipelineStatus::kOk != fDrawPipelineStatus) {
207         SkASSERT(DrawPipelineStatus::kNotConfigured != fDrawPipelineStatus);
208         this->gpu()->stats()->incNumFailedDraws();
209         return false;
210     }
211     SkASSERT(DynamicStateStatus::kUninitialized != fScissorStatus);
212     SkASSERT(DynamicStateStatus::kUninitialized != fTextureBindingStatus);
213
214     if (kNone_GrXferBarrierType != fXferBarrierType) {
215         this->gpu()->xferBarrier(fRenderTarget, fXferBarrierType);
216     }
217     return true;
218 }
219
220 void GrOpsRenderPass::draw(int vertexCount, int baseVertex) {
221     if (!this->prepareToDraw()) {
222         return;
223     }
224     SkASSERT(!fHasIndexBuffer);
225     SkASSERT(DynamicStateStatus::kConfigured != fInstanceBufferStatus);
226     SkASSERT(DynamicStateStatus::kUninitialized != fVertexBufferStatus);
227     this->onDraw(vertexCount, baseVertex);
228 }
229
230 void GrOpsRenderPass::drawIndexed(int indexCount, int baseIndex, uint16_t minIndexValue,
231                                   uint16_t maxIndexValue, int baseVertex) {
232     if (!this->prepareToDraw()) {
233         return;
234     }
235     SkASSERT(fHasIndexBuffer);
236     SkASSERT(DynamicStateStatus::kConfigured != fInstanceBufferStatus);
237     SkASSERT(DynamicStateStatus::kUninitialized != fVertexBufferStatus);
238     this->onDrawIndexed(indexCount, baseIndex, minIndexValue, maxIndexValue, baseVertex);
239 }
240
241 void GrOpsRenderPass::drawInstanced(int instanceCount, int baseInstance, int vertexCount,
242                                     int baseVertex) {
243     SkASSERT(this->gpu()->caps()->drawInstancedSupport());
244     if (!this->prepareToDraw()) {
245         return;
246     }
247     SkASSERT(!fHasIndexBuffer);
248     SkASSERT(DynamicStateStatus::kUninitialized != fInstanceBufferStatus);
249     SkASSERT(DynamicStateStatus::kUninitialized != fVertexBufferStatus);
250     this->onDrawInstanced(instanceCount, baseInstance, vertexCount, baseVertex);
251 }
252
253 void GrOpsRenderPass::drawIndexedInstanced(int indexCount, int baseIndex, int instanceCount,
254                                            int baseInstance, int baseVertex) {
255     SkASSERT(this->gpu()->caps()->drawInstancedSupport());
256     if (!this->prepareToDraw()) {
257         return;
258     }
259     SkASSERT(fHasIndexBuffer);
260     SkASSERT(DynamicStateStatus::kUninitialized != fInstanceBufferStatus);
261     SkASSERT(DynamicStateStatus::kUninitialized != fVertexBufferStatus);
262     this->onDrawIndexedInstanced(indexCount, baseIndex, instanceCount, baseInstance, baseVertex);
263 }
264
265 void GrOpsRenderPass::drawIndirect(const GrBuffer* drawIndirectBuffer, size_t bufferOffset,
266                                    int drawCount) {
267     SkASSERT(this->gpu()->caps()->drawInstancedSupport());
268     SkASSERT(drawIndirectBuffer->isCpuBuffer() ||
269              !static_cast<const GrGpuBuffer*>(drawIndirectBuffer)->isMapped());
270     if (!this->prepareToDraw()) {
271         return;
272     }
273     SkASSERT(!fHasIndexBuffer);
274     SkASSERT(DynamicStateStatus::kUninitialized != fInstanceBufferStatus);
275     SkASSERT(DynamicStateStatus::kUninitialized != fVertexBufferStatus);
276     if (!this->gpu()->caps()->nativeDrawIndirectSupport()) {
277         // Polyfill indirect draws with looping instanced calls.
278         SkASSERT(drawIndirectBuffer->isCpuBuffer());
279         auto* cpuIndirectBuffer = static_cast<const GrCpuBuffer*>(drawIndirectBuffer);
280         auto* cmds = reinterpret_cast<const GrDrawIndirectCommand*>(
281                 cpuIndirectBuffer->data() + bufferOffset);
282         for (int i = 0; i < drawCount; ++i) {
283             auto [vertexCount, instanceCount, baseVertex, baseInstance] = cmds[i];
284             this->onDrawInstanced(instanceCount, baseInstance, vertexCount, baseVertex);
285         }
286         return;
287     }
288     this->onDrawIndirect(drawIndirectBuffer, bufferOffset, drawCount);
289 }
290
291 void GrOpsRenderPass::drawIndexedIndirect(const GrBuffer* drawIndirectBuffer, size_t bufferOffset,
292                                           int drawCount) {
293     SkASSERT(this->gpu()->caps()->drawInstancedSupport());
294     SkASSERT(drawIndirectBuffer->isCpuBuffer() ||
295              !static_cast<const GrGpuBuffer*>(drawIndirectBuffer)->isMapped());
296     if (!this->prepareToDraw()) {
297         return;
298     }
299     SkASSERT(fHasIndexBuffer);
300     SkASSERT(DynamicStateStatus::kUninitialized != fInstanceBufferStatus);
301     SkASSERT(DynamicStateStatus::kUninitialized != fVertexBufferStatus);
302     if (!this->gpu()->caps()->nativeDrawIndirectSupport() ||
303         this->gpu()->caps()->nativeDrawIndexedIndirectIsBroken()) {
304         // Polyfill indexedIndirect draws with looping indexedInstanced calls.
305         SkASSERT(drawIndirectBuffer->isCpuBuffer());
306         auto* cpuIndirectBuffer = static_cast<const GrCpuBuffer*>(drawIndirectBuffer);
307         auto* cmds = reinterpret_cast<const GrDrawIndexedIndirectCommand*>(
308                 cpuIndirectBuffer->data() + bufferOffset);
309         for (int i = 0; i < drawCount; ++i) {
310             auto [indexCount, instanceCount, baseIndex, baseVertex, baseInstance] = cmds[i];
311             this->onDrawIndexedInstanced(indexCount, baseIndex, instanceCount, baseInstance,
312                                          baseVertex);
313         }
314         return;
315     }
316     this->onDrawIndexedIndirect(drawIndirectBuffer, bufferOffset, drawCount);
317 }
318
319 void GrOpsRenderPass::drawIndexPattern(int patternIndexCount, int patternRepeatCount,
320                                        int maxPatternRepetitionsInIndexBuffer,
321                                        int patternVertexCount, int baseVertex) {
322     int baseRepetition = 0;
323     while (baseRepetition < patternRepeatCount) {
324         int repeatCount = std::min(patternRepeatCount - baseRepetition,
325                                    maxPatternRepetitionsInIndexBuffer);
326         int drawIndexCount = repeatCount * patternIndexCount;
327         // A patterned index buffer must contain indices in the range [0..vertexCount].
328         int minIndexValue = 0;
329         int maxIndexValue = patternVertexCount * repeatCount - 1;
330         this->drawIndexed(drawIndexCount, 0, minIndexValue, maxIndexValue,
331                           patternVertexCount * baseRepetition + baseVertex);
332         baseRepetition += repeatCount;
333     }
334 }