aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/GrBufferedDrawTarget.cpp
blob: dde57d36ea8e7e8923c79c6a0deacb0f23dd5fd1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
/*
 * Copyright 2011 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "GrBufferedDrawTarget.h"

// We will use the reordering buffer, unless we have NVPR.
// TODO move NVPR to batch so we can reorder
static inline bool allow_reordering(const GrCaps* caps) {
    return caps && caps->shaderCaps() && !caps->shaderCaps()->pathRenderingSupport();
}

GrBufferedDrawTarget::GrBufferedDrawTarget(GrContext* context)
    : INHERITED(context)
    , fCommands(GrCommandBuilder::Create(context->getGpu(), allow_reordering(context->caps())))
    , fPathIndexBuffer(kPathIdxBufferMinReserve * sizeof(char)/4)
    , fPathTransformBuffer(kPathXformBufferMinReserve * sizeof(float)/4)
    , fPipelineBuffer(kPipelineBufferMinReserve)
    , fDrawID(0) {
}

GrBufferedDrawTarget::~GrBufferedDrawTarget() {
    this->reset();
}

void GrBufferedDrawTarget::onDrawBatch(GrBatch* batch) {
    fCommands->recordDrawBatch(batch, *this->caps());
}

void GrBufferedDrawTarget::onDrawPath(const GrPathProcessor* pathProc,
                                      const GrPath* path,
                                      const GrStencilSettings& stencilSettings,
                                      const PipelineInfo& pipelineInfo) {
    GrPipelineOptimizations opts;
    StateForPathDraw* state = this->createStateForPathDraw(pathProc, pipelineInfo, &opts);
    if (!state) {
        return;
    }
    fCommands->recordDrawPath(state, pathProc, path, stencilSettings);
}

void GrBufferedDrawTarget::onDrawPaths(const GrPathProcessor* pathProc,
                                       const GrPathRange* pathRange,
                                       const void* indices,
                                       PathIndexType indexType,
                                       const float transformValues[],
                                       PathTransformType transformType,
                                       int count,
                                       const GrStencilSettings& stencilSettings,
                                       const PipelineInfo& pipelineInfo) {
    GrPipelineOptimizations opts;
    StateForPathDraw* state = this->createStateForPathDraw(pathProc, pipelineInfo, &opts);
    if (!state) {
        return;
    }
    fCommands->recordDrawPaths(state, this, pathProc, pathRange, indices, indexType,
                               transformValues, transformType, count, stencilSettings,
                               opts);
}

void GrBufferedDrawTarget::onReset() {
    fCommands->reset();
    fPathIndexBuffer.rewind();
    fPathTransformBuffer.rewind();

    fPrevState.reset(NULL);
    // Note, fPrevState points into fPipelineBuffer's allocation, so we have to reset first.
    // Furthermore, we have to reset fCommands before fPipelineBuffer too.
    if (fDrawID % kPipelineBufferHighWaterMark) {
        fPipelineBuffer.rewind();
    } else {
        fPipelineBuffer.reset();
    }
}

void GrBufferedDrawTarget::onFlush() {
    fCommands->flush(this->getGpu(), this->getContext()->resourceProvider());
    ++fDrawID;
}

GrTargetCommands::StateForPathDraw*
GrBufferedDrawTarget::createStateForPathDraw(const GrPrimitiveProcessor* primProc,
                                             const GrDrawTarget::PipelineInfo& pipelineInfo,
                                             GrPipelineOptimizations* opts) {
    StateForPathDraw* state = this->allocState(primProc);
    if (!GrPipeline::CreateAt(state->pipelineLocation(), pipelineInfo.pipelineCreateArgs(), opts)) {
        this->unallocState(state);
        return NULL;
    }

    state->fPrimitiveProcessor->initBatchTracker(&state->fBatchTracker, *opts);

    if (fPrevState && fPrevState->fPrimitiveProcessor.get() &&
        fPrevState->fPrimitiveProcessor->canMakeEqual(fPrevState->fBatchTracker,
                                                      *state->fPrimitiveProcessor,
                                                      state->fBatchTracker) &&
        GrPipeline::AreEqual(*fPrevState->getPipeline(), *state->getPipeline(), false)) {
        this->unallocState(state);
    } else {
        fPrevState.reset(state);
    }

    return fPrevState;
}