blob: 8a5dd6289bb30ad7427ea4b8ff5671ed3cfbb981 [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
8#include "GrVertexBatch.h"
bsalomon75398562015-08-17 12:55:38 -07009#include "GrBatchFlushState.h"
bsalomon16b99132015-08-13 14:55:50 -070010#include "GrResourceProvider.h"
11
bsalomon342bfc22016-04-01 06:06:20 -070012GrVertexBatch::GrVertexBatch(uint32_t classID)
13 : INHERITED(classID)
14 , fBaseDrawToken(GrBatchDrawToken::AlreadyFlushedToken()) {
15}
bsalomon16b99132015-08-13 14:55:50 -070016
bsalomon53469832015-08-18 09:20:09 -070017void GrVertexBatch::onPrepare(GrBatchFlushState* state) {
bsalomon75398562015-08-17 12:55:38 -070018 Target target(state, this);
19 this->onPrepareDraws(&target);
20}
21
22void* GrVertexBatch::InstancedHelper::init(Target* target, GrPrimitiveType primType,
cdalton397536c2016-03-25 12:15:03 -070023 size_t vertexStride, const GrBuffer* indexBuffer,
bsalomon75398562015-08-17 12:55:38 -070024 int verticesPerInstance, int indicesPerInstance,
25 int instancesToDraw) {
26 SkASSERT(target);
bsalomon16b99132015-08-13 14:55:50 -070027 if (!indexBuffer) {
halcanary96fcdcc2015-08-27 07:41:13 -070028 return nullptr;
bsalomon16b99132015-08-13 14:55:50 -070029 }
cdalton397536c2016-03-25 12:15:03 -070030 const GrBuffer* vertexBuffer;
bsalomon16b99132015-08-13 14:55:50 -070031 int firstVertex;
32 int vertexCount = verticesPerInstance * instancesToDraw;
bsalomon75398562015-08-17 12:55:38 -070033 void* vertices = target->makeVertexSpace(vertexStride, vertexCount, &vertexBuffer, &firstVertex);
bsalomon16b99132015-08-13 14:55:50 -070034 if (!vertices) {
35 SkDebugf("Vertices could not be allocated for instanced rendering.");
halcanary96fcdcc2015-08-27 07:41:13 -070036 return nullptr;
bsalomon16b99132015-08-13 14:55:50 -070037 }
38 SkASSERT(vertexBuffer);
39 size_t ibSize = indexBuffer->gpuMemorySize();
40 int maxInstancesPerDraw = static_cast<int>(ibSize / (sizeof(uint16_t) * indicesPerInstance));
41
egdaniel0e1853c2016-03-17 11:35:45 -070042 fMesh.initInstanced(primType, vertexBuffer, indexBuffer,
bsalomon16b99132015-08-13 14:55:50 -070043 firstVertex, verticesPerInstance, indicesPerInstance, instancesToDraw,
44 maxInstancesPerDraw);
45 return vertices;
46}
47
bsalomon342bfc22016-04-01 06:06:20 -070048void GrVertexBatch::InstancedHelper::recordDraw(Target* target, const GrGeometryProcessor* gp) {
egdaniel0e1853c2016-03-17 11:35:45 -070049 SkASSERT(fMesh.instanceCount());
bsalomon342bfc22016-04-01 06:06:20 -070050 target->draw(gp, fMesh);
bsalomon75398562015-08-17 12:55:38 -070051}
52
53void* GrVertexBatch::QuadHelper::init(Target* target, size_t vertexStride,
bsalomon16b99132015-08-13 14:55:50 -070054 int quadsToDraw) {
cdalton397536c2016-03-25 12:15:03 -070055 SkAutoTUnref<const GrBuffer> quadIndexBuffer(
bsalomon75398562015-08-17 12:55:38 -070056 target->resourceProvider()->refQuadIndexBuffer());
bsalomon16b99132015-08-13 14:55:50 -070057 if (!quadIndexBuffer) {
58 SkDebugf("Could not get quad index buffer.");
halcanary96fcdcc2015-08-27 07:41:13 -070059 return nullptr;
bsalomon16b99132015-08-13 14:55:50 -070060 }
bsalomon75398562015-08-17 12:55:38 -070061 return this->INHERITED::init(target, kTriangles_GrPrimitiveType, vertexStride,
bsalomon16b99132015-08-13 14:55:50 -070062 quadIndexBuffer, kVerticesPerQuad, kIndicesPerQuad, quadsToDraw);
63}
bsalomon75398562015-08-17 12:55:38 -070064
bsalomon53469832015-08-18 09:20:09 -070065void GrVertexBatch::onDraw(GrBatchFlushState* state) {
bsalomon342bfc22016-04-01 06:06:20 -070066 int currUploadIdx = 0;
67 int currMeshIdx = 0;
bsalomon75398562015-08-17 12:55:38 -070068
bsalomon342bfc22016-04-01 06:06:20 -070069 SkASSERT(fQueuedDraws.empty() || fBaseDrawToken == state->nextTokenToFlush());
70
71 for (int currDrawIdx = 0; currDrawIdx < fQueuedDraws.count(); ++currDrawIdx) {
72 GrBatchDrawToken drawToken = state->nextTokenToFlush();
73 while (currUploadIdx < fInlineUploads.count() &&
74 fInlineUploads[currUploadIdx].fUploadBeforeToken == drawToken) {
75 state->doUpload(fInlineUploads[currUploadIdx++].fUpload);
bsalomon75398562015-08-17 12:55:38 -070076 }
bsalomon342bfc22016-04-01 06:06:20 -070077 const QueuedDraw &draw = fQueuedDraws[currDrawIdx];
78 state->gpu()->draw(*this->pipeline(), *draw.fGeometryProcessor.get(),
79 fMeshes.begin() + currMeshIdx, draw.fMeshCnt);
80 currMeshIdx += draw.fMeshCnt;
81 state->flushToken();
82 }
83 SkASSERT(currUploadIdx == fInlineUploads.count());
84 SkASSERT(currMeshIdx == fMeshes.count());
85 fQueuedDraws.reset();
86 fInlineUploads.reset();
87}
bsalomon75398562015-08-17 12:55:38 -070088
bsalomon342bfc22016-04-01 06:06:20 -070089//////////////////////////////////////////////////////////////////////////////
90
91void GrVertexBatch::Target::draw(const GrGeometryProcessor* gp, const GrMesh& mesh) {
92 GrVertexBatch* batch = this->vertexBatch();
93 batch->fMeshes.push_back(mesh);
94 if (!batch->fQueuedDraws.empty()) {
95 // If the last draw shares a geometry processor and there are no intervening uploads,
96 // add this mesh to it.
97 GrVertexBatch::QueuedDraw& lastDraw = this->vertexBatch()->fQueuedDraws.back();
98 if (lastDraw.fGeometryProcessor == gp &&
99 (batch->fInlineUploads.empty() ||
100 batch->fInlineUploads.back().fUploadBeforeToken != this->nextDrawToken())) {
101 ++lastDraw.fMeshCnt;
102 return;
103 }
104 }
105 GrVertexBatch::QueuedDraw& draw = this->vertexBatch()->fQueuedDraws.push_back();
106 GrBatchDrawToken token = this->state()->issueDrawToken();
107 draw.fGeometryProcessor.reset(gp);
108 draw.fMeshCnt = 1;
109 if (batch->fQueuedDraws.count() == 1) {
110 batch->fBaseDrawToken = token;
bsalomon75398562015-08-17 12:55:38 -0700111 }
112}