Line data Source code
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 "GrMeshDrawOp.h"
9 : #include "GrOpFlushState.h"
10 : #include "GrResourceProvider.h"
11 :
12 0 : GrMeshDrawOp::GrMeshDrawOp(uint32_t classID)
13 0 : : INHERITED(classID), fBaseDrawToken(GrDrawOpUploadToken::AlreadyFlushedToken()) {}
14 :
15 0 : void GrMeshDrawOp::onPrepare(GrOpFlushState* state) {
16 0 : Target target(state, this);
17 0 : this->onPrepareDraws(&target);
18 0 : }
19 :
20 0 : void* GrMeshDrawOp::InstancedHelper::init(Target* target, GrPrimitiveType primType,
21 : size_t vertexStride, const GrBuffer* indexBuffer,
22 : int verticesPerInstance, int indicesPerInstance,
23 : int instancesToDraw) {
24 0 : SkASSERT(target);
25 0 : if (!indexBuffer) {
26 0 : return nullptr;
27 : }
28 : const GrBuffer* vertexBuffer;
29 : int firstVertex;
30 0 : int vertexCount = verticesPerInstance * instancesToDraw;
31 : void* vertices =
32 0 : target->makeVertexSpace(vertexStride, vertexCount, &vertexBuffer, &firstVertex);
33 0 : if (!vertices) {
34 0 : SkDebugf("Vertices could not be allocated for instanced rendering.");
35 0 : return nullptr;
36 : }
37 0 : SkASSERT(vertexBuffer);
38 0 : size_t ibSize = indexBuffer->gpuMemorySize();
39 0 : int maxInstancesPerDraw = static_cast<int>(ibSize / (sizeof(uint16_t) * indicesPerInstance));
40 :
41 0 : fMesh.initInstanced(primType, vertexBuffer, indexBuffer, firstVertex, verticesPerInstance,
42 0 : indicesPerInstance, instancesToDraw, maxInstancesPerDraw);
43 0 : return vertices;
44 : }
45 :
46 0 : void GrMeshDrawOp::InstancedHelper::recordDraw(Target* target, const GrGeometryProcessor* gp,
47 : const GrPipeline* pipeline) {
48 0 : SkASSERT(fMesh.instanceCount());
49 0 : target->draw(gp, pipeline, fMesh);
50 0 : }
51 :
52 0 : void* GrMeshDrawOp::QuadHelper::init(Target* target, size_t vertexStride, int quadsToDraw) {
53 0 : sk_sp<const GrBuffer> quadIndexBuffer(target->resourceProvider()->refQuadIndexBuffer());
54 0 : if (!quadIndexBuffer) {
55 0 : SkDebugf("Could not get quad index buffer.");
56 0 : return nullptr;
57 : }
58 0 : return this->INHERITED::init(target, kTriangles_GrPrimitiveType, vertexStride,
59 : quadIndexBuffer.get(), kVerticesPerQuad, kIndicesPerQuad,
60 0 : quadsToDraw);
61 : }
62 :
63 0 : void GrMeshDrawOp::onExecute(GrOpFlushState* state) {
64 0 : SkASSERT(!state->drawOpArgs().fAppliedClip);
65 0 : SkASSERT(!state->drawOpArgs().fDstTexture.texture());
66 0 : int currUploadIdx = 0;
67 0 : int currMeshIdx = 0;
68 :
69 0 : SkASSERT(fQueuedDraws.empty() || fBaseDrawToken == state->nextTokenToFlush());
70 :
71 0 : for (int currDrawIdx = 0; currDrawIdx < fQueuedDraws.count(); ++currDrawIdx) {
72 0 : GrDrawOpUploadToken drawToken = state->nextTokenToFlush();
73 0 : while (currUploadIdx < fInlineUploads.count() &&
74 0 : fInlineUploads[currUploadIdx].fUploadBeforeToken == drawToken) {
75 0 : state->commandBuffer()->inlineUpload(state, fInlineUploads[currUploadIdx++].fUpload,
76 0 : state->drawOpArgs().fRenderTarget);
77 : }
78 0 : const QueuedDraw& draw = fQueuedDraws[currDrawIdx];
79 0 : SkASSERT(draw.fPipeline->getRenderTarget() == state->drawOpArgs().fRenderTarget);
80 0 : state->commandBuffer()->draw(*draw.fPipeline, *draw.fGeometryProcessor.get(),
81 0 : fMeshes.begin() + currMeshIdx, draw.fMeshCnt, this->bounds());
82 0 : currMeshIdx += draw.fMeshCnt;
83 0 : state->flushToken();
84 : }
85 0 : SkASSERT(currUploadIdx == fInlineUploads.count());
86 0 : SkASSERT(currMeshIdx == fMeshes.count());
87 0 : fQueuedDraws.reset();
88 0 : fInlineUploads.reset();
89 0 : }
90 :
91 : //////////////////////////////////////////////////////////////////////////////
92 :
93 0 : void GrMeshDrawOp::Target::draw(const GrGeometryProcessor* gp, const GrPipeline* pipeline,
94 : const GrMesh& mesh) {
95 0 : GrMeshDrawOp* op = this->meshDrawOp();
96 0 : op->fMeshes.push_back(mesh);
97 0 : if (!op->fQueuedDraws.empty()) {
98 : // If the last draw shares a geometry processor and pipeline and there are no intervening
99 : // uploads, add this mesh to it.
100 0 : GrLegacyMeshDrawOp::QueuedDraw& lastDraw = op->fQueuedDraws.back();
101 0 : if (lastDraw.fGeometryProcessor == gp && lastDraw.fPipeline == pipeline &&
102 0 : (op->fInlineUploads.empty() ||
103 0 : op->fInlineUploads.back().fUploadBeforeToken != this->nextDrawToken())) {
104 0 : ++lastDraw.fMeshCnt;
105 0 : return;
106 : }
107 : }
108 0 : GrLegacyMeshDrawOp::QueuedDraw& draw = op->fQueuedDraws.push_back();
109 0 : GrDrawOpUploadToken token = this->state()->issueDrawToken();
110 0 : draw.fGeometryProcessor.reset(gp);
111 0 : draw.fPipeline = pipeline;
112 0 : draw.fMeshCnt = 1;
113 0 : if (op->fQueuedDraws.count() == 1) {
114 0 : op->fBaseDrawToken = token;
115 : }
116 : }
|