blob: a8dd8b1b7e32d57d46f27f1754b1d84eddcfc904 [file] [log] [blame]
bsalomon16b99132015-08-13 14:55:50 -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 Salomondad29232016-12-01 16:40:24 -05008#include "GrMeshDrawOp.h"
Brian Salomon742e31d2016-12-07 17:06:19 -05009#include "GrOpFlushState.h"
bsalomon16b99132015-08-13 14:55:50 -070010#include "GrResourceProvider.h"
11
Brian Salomondad29232016-12-01 16:40:24 -050012GrMeshDrawOp::GrMeshDrawOp(uint32_t classID)
13 : INHERITED(classID), fBaseDrawToken(GrDrawOpUploadToken::AlreadyFlushedToken()) {}
bsalomon16b99132015-08-13 14:55:50 -070014
Brian Salomon742e31d2016-12-07 17:06:19 -050015void GrMeshDrawOp::onPrepare(GrOpFlushState* state) {
bsalomon75398562015-08-17 12:55:38 -070016 Target target(state, this);
17 this->onPrepareDraws(&target);
18}
19
Brian Salomondad29232016-12-01 16:40:24 -050020void* GrMeshDrawOp::InstancedHelper::init(Target* target, GrPrimitiveType primType,
21 size_t vertexStride, const GrBuffer* indexBuffer,
22 int verticesPerInstance, int indicesPerInstance,
23 int instancesToDraw) {
bsalomon75398562015-08-17 12:55:38 -070024 SkASSERT(target);
bsalomon16b99132015-08-13 14:55:50 -070025 if (!indexBuffer) {
halcanary96fcdcc2015-08-27 07:41:13 -070026 return nullptr;
bsalomon16b99132015-08-13 14:55:50 -070027 }
cdalton397536c2016-03-25 12:15:03 -070028 const GrBuffer* vertexBuffer;
bsalomon16b99132015-08-13 14:55:50 -070029 int firstVertex;
30 int vertexCount = verticesPerInstance * instancesToDraw;
Brian Salomondad29232016-12-01 16:40:24 -050031 void* vertices =
32 target->makeVertexSpace(vertexStride, vertexCount, &vertexBuffer, &firstVertex);
bsalomon16b99132015-08-13 14:55:50 -070033 if (!vertices) {
34 SkDebugf("Vertices could not be allocated for instanced rendering.");
halcanary96fcdcc2015-08-27 07:41:13 -070035 return nullptr;
bsalomon16b99132015-08-13 14:55:50 -070036 }
37 SkASSERT(vertexBuffer);
38 size_t ibSize = indexBuffer->gpuMemorySize();
39 int maxInstancesPerDraw = static_cast<int>(ibSize / (sizeof(uint16_t) * indicesPerInstance));
40
Brian Salomondad29232016-12-01 16:40:24 -050041 fMesh.initInstanced(primType, vertexBuffer, indexBuffer, firstVertex, verticesPerInstance,
42 indicesPerInstance, instancesToDraw, maxInstancesPerDraw);
bsalomon16b99132015-08-13 14:55:50 -070043 return vertices;
44}
45
Brian Salomondad29232016-12-01 16:40:24 -050046void GrMeshDrawOp::InstancedHelper::recordDraw(Target* target, const GrGeometryProcessor* gp) {
egdaniel0e1853c2016-03-17 11:35:45 -070047 SkASSERT(fMesh.instanceCount());
bsalomon342bfc22016-04-01 06:06:20 -070048 target->draw(gp, fMesh);
bsalomon75398562015-08-17 12:55:38 -070049}
50
Brian Salomondad29232016-12-01 16:40:24 -050051void* GrMeshDrawOp::QuadHelper::init(Target* target, size_t vertexStride, int quadsToDraw) {
52 sk_sp<const GrBuffer> quadIndexBuffer(target->resourceProvider()->refQuadIndexBuffer());
bsalomon16b99132015-08-13 14:55:50 -070053 if (!quadIndexBuffer) {
54 SkDebugf("Could not get quad index buffer.");
halcanary96fcdcc2015-08-27 07:41:13 -070055 return nullptr;
bsalomon16b99132015-08-13 14:55:50 -070056 }
bsalomon75398562015-08-17 12:55:38 -070057 return this->INHERITED::init(target, kTriangles_GrPrimitiveType, vertexStride,
Hal Canary144caf52016-11-07 17:57:18 -050058 quadIndexBuffer.get(), kVerticesPerQuad, kIndicesPerQuad,
59 quadsToDraw);
bsalomon16b99132015-08-13 14:55:50 -070060}
bsalomon75398562015-08-17 12:55:38 -070061
Brian Salomonbde42852016-12-21 11:37:49 -050062void GrMeshDrawOp::onExecute(GrOpFlushState* state, const SkRect& bounds) {
bsalomon342bfc22016-04-01 06:06:20 -070063 int currUploadIdx = 0;
64 int currMeshIdx = 0;
bsalomon75398562015-08-17 12:55:38 -070065
bsalomon342bfc22016-04-01 06:06:20 -070066 SkASSERT(fQueuedDraws.empty() || fBaseDrawToken == state->nextTokenToFlush());
67
68 for (int currDrawIdx = 0; currDrawIdx < fQueuedDraws.count(); ++currDrawIdx) {
Brian Salomon9afd3712016-12-01 10:59:09 -050069 GrDrawOpUploadToken drawToken = state->nextTokenToFlush();
bsalomon342bfc22016-04-01 06:06:20 -070070 while (currUploadIdx < fInlineUploads.count() &&
71 fInlineUploads[currUploadIdx].fUploadBeforeToken == drawToken) {
Greg Daniel77b53f62016-10-18 11:48:51 -040072 state->commandBuffer()->inlineUpload(state, fInlineUploads[currUploadIdx++].fUpload);
bsalomon75398562015-08-17 12:55:38 -070073 }
Brian Salomondad29232016-12-01 16:40:24 -050074 const QueuedDraw& draw = fQueuedDraws[currDrawIdx];
egdaniel9cb63402016-06-23 08:37:05 -070075 state->commandBuffer()->draw(*this->pipeline(), *draw.fGeometryProcessor.get(),
Greg Daniel36a77ee2016-10-18 10:33:25 -040076 fMeshes.begin() + currMeshIdx, draw.fMeshCnt, bounds);
bsalomon342bfc22016-04-01 06:06:20 -070077 currMeshIdx += draw.fMeshCnt;
78 state->flushToken();
79 }
80 SkASSERT(currUploadIdx == fInlineUploads.count());
81 SkASSERT(currMeshIdx == fMeshes.count());
82 fQueuedDraws.reset();
83 fInlineUploads.reset();
84}
bsalomon75398562015-08-17 12:55:38 -070085
bsalomon342bfc22016-04-01 06:06:20 -070086//////////////////////////////////////////////////////////////////////////////
87
Brian Salomondad29232016-12-01 16:40:24 -050088void GrMeshDrawOp::Target::draw(const GrGeometryProcessor* gp, const GrMesh& mesh) {
Brian Salomon742e31d2016-12-07 17:06:19 -050089 GrMeshDrawOp* op = this->meshDrawOp();
90 op->fMeshes.push_back(mesh);
91 if (!op->fQueuedDraws.empty()) {
bsalomon342bfc22016-04-01 06:06:20 -070092 // If the last draw shares a geometry processor and there are no intervening uploads,
93 // add this mesh to it.
Brian Salomon742e31d2016-12-07 17:06:19 -050094 GrMeshDrawOp::QueuedDraw& lastDraw = op->fQueuedDraws.back();
bsalomon342bfc22016-04-01 06:06:20 -070095 if (lastDraw.fGeometryProcessor == gp &&
Brian Salomon742e31d2016-12-07 17:06:19 -050096 (op->fInlineUploads.empty() ||
97 op->fInlineUploads.back().fUploadBeforeToken != this->nextDrawToken())) {
bsalomon342bfc22016-04-01 06:06:20 -070098 ++lastDraw.fMeshCnt;
99 return;
100 }
101 }
Brian Salomon742e31d2016-12-07 17:06:19 -0500102 GrMeshDrawOp::QueuedDraw& draw = op->fQueuedDraws.push_back();
Brian Salomon9afd3712016-12-01 10:59:09 -0500103 GrDrawOpUploadToken token = this->state()->issueDrawToken();
bsalomon342bfc22016-04-01 06:06:20 -0700104 draw.fGeometryProcessor.reset(gp);
105 draw.fMeshCnt = 1;
Brian Salomon742e31d2016-12-07 17:06:19 -0500106 if (op->fQueuedDraws.count() == 1) {
107 op->fBaseDrawToken = token;
bsalomon75398562015-08-17 12:55:38 -0700108 }
109}