1
2/*
3 * Copyright 2011 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
9
10#ifndef GrPaint_DEFINED
11#define GrPaint_DEFINED
12
13#include "GrColor.h"
14#include "GrXferProcessor.h"
15#include "effects/GrPorterDuffXferProcessor.h"
16#include "GrFragmentProcessor.h"
17
18#include "SkRegion.h"
19#include "SkXfermode.h"
20
21/**
22 * The paint describes how color and coverage are computed at each pixel by GrContext draw
23 * functions and the how color is blended with the destination pixel.
24 *
25 * The paint allows installation of custom color and coverage stages. New types of stages are
26 * created by subclassing GrProcessor.
27 *
28 * The primitive color computation starts with the color specified by setColor(). This color is the
29 * input to the first color stage. Each color stage feeds its output to the next color stage.
30 *
31 * Fractional pixel coverage follows a similar flow. The coverage is initially the value specified
32 * by setCoverage(). This is input to the first coverage stage. Coverage stages are chained
33 * together in the same manner as color stages. The output of the last stage is modulated by any
34 * fractional coverage produced by anti-aliasing. This last step produces the final coverage, C.
35 *
36 * setXPFactory is used to control blending between the output color and dest. It also implements
37 * the application of fractional coverage from the coverage pipeline.
38 */
39class GrPaint {
40public:
41    GrPaint();
42
43    GrPaint(const GrPaint& paint) { *this = paint; }
44
45    ~GrPaint() { this->resetFragmentProcessors();  }
46
47    /**
48     * The initial color of the drawn primitive. Defaults to solid white.
49     */
50    void setColor(GrColor color) { fColor = color; }
51    GrColor getColor() const { return fColor; }
52
53    /**
54     * Should primitives be anti-aliased or not. Defaults to false.
55     */
56    void setAntiAlias(bool aa) { fAntiAlias = aa; }
57    bool isAntiAlias() const { return fAntiAlias; }
58
59    const GrXPFactory* setXPFactory(const GrXPFactory* xpFactory) {
60        fXPFactory.reset(SkSafeRef(xpFactory));
61        return xpFactory;
62    }
63
64    void setPorterDuffXPFactory(SkXfermode::Mode mode) {
65        fXPFactory.reset(GrPorterDuffXPFactory::Create(mode));
66    }
67
68    void setCoverageSetOpXPFactory(SkRegion::Op regionOp, bool invertCoverage = false);
69
70    /**
71     * Appends an additional color processor to the color computation.
72     */
73    const GrFragmentProcessor* addColorFragmentProcessor(const GrFragmentProcessor* fp) {
74        SkASSERT(fp);
75        fColorFragmentProcessors.push_back(SkRef(fp));
76        return fp;
77    }
78
79    /**
80     * Appends an additional coverage processor to the coverage computation.
81     */
82    const GrFragmentProcessor* addCoverageFragmentProcessor(const GrFragmentProcessor* fp) {
83        SkASSERT(fp);
84        fCoverageFragmentProcessors.push_back(SkRef(fp));
85        return fp;
86    }
87
88    /**
89     * Helpers for adding color or coverage effects that sample a texture. The matrix is applied
90     * to the src space position to compute texture coordinates.
91     */
92    void addColorTextureProcessor(GrTexture*, const SkMatrix&);
93    void addCoverageTextureProcessor(GrTexture*, const SkMatrix&);
94    void addColorTextureProcessor(GrTexture*, const SkMatrix&, const GrTextureParams&);
95    void addCoverageTextureProcessor(GrTexture*, const SkMatrix&, const GrTextureParams&);
96
97    int numColorFragmentProcessors() const { return fColorFragmentProcessors.count(); }
98    int numCoverageFragmentProcessors() const { return fCoverageFragmentProcessors.count(); }
99    int numTotalFragmentProcessors() const { return this->numColorFragmentProcessors() +
100                                              this->numCoverageFragmentProcessors(); }
101
102    const GrXPFactory* getXPFactory() const {
103        return fXPFactory;
104    }
105
106    const GrFragmentProcessor* getColorFragmentProcessor(int i) const {
107        return fColorFragmentProcessors[i];
108    }
109    const GrFragmentProcessor* getCoverageFragmentProcessor(int i) const {
110        return fCoverageFragmentProcessors[i];
111    }
112
113    GrPaint& operator=(const GrPaint& paint) {
114        fAntiAlias = paint.fAntiAlias;
115
116        fColor = paint.fColor;
117        this->resetFragmentProcessors();
118        fColorFragmentProcessors = paint.fColorFragmentProcessors;
119        fCoverageFragmentProcessors = paint.fCoverageFragmentProcessors;
120        for (int i = 0; i < fColorFragmentProcessors.count(); ++i) {
121            fColorFragmentProcessors[i]->ref();
122        }
123        for (int i = 0; i < fCoverageFragmentProcessors.count(); ++i) {
124            fCoverageFragmentProcessors[i]->ref();
125        }
126
127        fXPFactory.reset(SkSafeRef(paint.getXPFactory()));
128
129        return *this;
130    }
131
132    /**
133     * Returns true if the paint's output color will be constant after blending. If the result is
134     * true, constantColor will be updated to contain the constant color. Note that we can conflate
135     * coverage and color, so the actual values written to pixels with partial coverage may still
136     * not seem constant, even if this function returns true.
137     */
138    bool isConstantBlendedColor(GrColor* constantColor) const;
139
140private:
141    void resetFragmentProcessors() {
142        for (int i = 0; i < fColorFragmentProcessors.count(); ++i) {
143            fColorFragmentProcessors[i]->unref();
144        }
145        for (int i = 0; i < fCoverageFragmentProcessors.count(); ++i) {
146            fCoverageFragmentProcessors[i]->unref();
147        }
148        fColorFragmentProcessors.reset();
149        fCoverageFragmentProcessors.reset();
150    }
151
152    mutable SkAutoTUnref<const GrXPFactory>         fXPFactory;
153    SkSTArray<4, const GrFragmentProcessor*, true>  fColorFragmentProcessors;
154    SkSTArray<2, const GrFragmentProcessor*, true>  fCoverageFragmentProcessors;
155
156    bool                                            fAntiAlias;
157
158    GrColor                                         fColor;
159};
160
161#endif
162