1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/include/gpu/GrPaint.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,253 @@ 1.4 + 1.5 +/* 1.6 + * Copyright 2011 Google Inc. 1.7 + * 1.8 + * Use of this source code is governed by a BSD-style license that can be 1.9 + * found in the LICENSE file. 1.10 + */ 1.11 + 1.12 + 1.13 +#ifndef GrPaint_DEFINED 1.14 +#define GrPaint_DEFINED 1.15 + 1.16 +#include "GrColor.h" 1.17 +#include "GrEffectStage.h" 1.18 + 1.19 +#include "SkXfermode.h" 1.20 + 1.21 +/** 1.22 + * The paint describes how color and coverage are computed at each pixel by GrContext draw 1.23 + * functions and the how color is blended with the destination pixel. 1.24 + * 1.25 + * The paint allows installation of custom color and coverage stages. New types of stages are 1.26 + * created by subclassing GrEffect. 1.27 + * 1.28 + * The primitive color computation starts with the color specified by setColor(). This color is the 1.29 + * input to the first color stage. Each color stage feeds its output to the next color stage. The 1.30 + * final color stage's output color is input to the color filter specified by 1.31 + * setXfermodeColorFilter which produces the final source color, S. 1.32 + * 1.33 + * Fractional pixel coverage follows a similar flow. The coverage is initially the value specified 1.34 + * by setCoverage(). This is input to the first coverage stage. Coverage stages are chained 1.35 + * together in the same manner as color stages. The output of the last stage is modulated by any 1.36 + * fractional coverage produced by anti-aliasing. This last step produces the final coverage, C. 1.37 + * 1.38 + * setBlendFunc() specifies blending coefficients for S (described above) and D, the initial value 1.39 + * of the destination pixel, labeled Bs and Bd respectively. The final value of the destination 1.40 + * pixel is then D' = (1-C)*D + C*(Bd*D + Bs*S). 1.41 + * 1.42 + * Note that the coverage is applied after the blend. This is why they are computed as distinct 1.43 + * values. 1.44 + * 1.45 + * TODO: Encapsulate setXfermodeColorFilter in a GrEffect and remove from GrPaint. 1.46 + */ 1.47 +class GrPaint { 1.48 +public: 1.49 + GrPaint() { this->reset(); } 1.50 + 1.51 + GrPaint(const GrPaint& paint) { *this = paint; } 1.52 + 1.53 + ~GrPaint() {} 1.54 + 1.55 + /** 1.56 + * Sets the blending coefficients to use to blend the final primitive color with the 1.57 + * destination color. Defaults to kOne for src and kZero for dst (i.e. src mode). 1.58 + */ 1.59 + void setBlendFunc(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) { 1.60 + fSrcBlendCoeff = srcCoeff; 1.61 + fDstBlendCoeff = dstCoeff; 1.62 + } 1.63 + GrBlendCoeff getSrcBlendCoeff() const { return fSrcBlendCoeff; } 1.64 + GrBlendCoeff getDstBlendCoeff() const { return fDstBlendCoeff; } 1.65 + 1.66 + /** 1.67 + * The initial color of the drawn primitive. Defaults to solid white. 1.68 + */ 1.69 + void setColor(GrColor color) { fColor = color; } 1.70 + GrColor getColor() const { return fColor; } 1.71 + 1.72 + /** 1.73 + * Applies fractional coverage to the entire drawn primitive. Defaults to 0xff. 1.74 + */ 1.75 + void setCoverage(uint8_t coverage) { fCoverage = coverage; } 1.76 + uint8_t getCoverage() const { return fCoverage; } 1.77 + 1.78 + /** 1.79 + * Should primitives be anti-aliased or not. Defaults to false. 1.80 + */ 1.81 + void setAntiAlias(bool aa) { fAntiAlias = aa; } 1.82 + bool isAntiAlias() const { return fAntiAlias; } 1.83 + 1.84 + /** 1.85 + * Should dithering be applied. Defaults to false. 1.86 + */ 1.87 + void setDither(bool dither) { fDither = dither; } 1.88 + bool isDither() const { return fDither; } 1.89 + 1.90 + /** 1.91 + * Appends an additional color effect to the color computation. 1.92 + */ 1.93 + const GrEffectRef* addColorEffect(const GrEffectRef* effect, int attr0 = -1, int attr1 = -1) { 1.94 + SkASSERT(NULL != effect); 1.95 + if (!(*effect)->willUseInputColor()) { 1.96 + fColorStages.reset(); 1.97 + } 1.98 + SkNEW_APPEND_TO_TARRAY(&fColorStages, GrEffectStage, (effect, attr0, attr1)); 1.99 + return effect; 1.100 + } 1.101 + 1.102 + /** 1.103 + * Appends an additional coverage effect to the coverage computation. 1.104 + */ 1.105 + const GrEffectRef* addCoverageEffect(const GrEffectRef* effect, int attr0 = -1, int attr1 = -1) { 1.106 + SkASSERT(NULL != effect); 1.107 + if (!(*effect)->willUseInputColor()) { 1.108 + fCoverageStages.reset(); 1.109 + } 1.110 + SkNEW_APPEND_TO_TARRAY(&fCoverageStages, GrEffectStage, (effect, attr0, attr1)); 1.111 + return effect; 1.112 + } 1.113 + 1.114 + /** 1.115 + * Helpers for adding color or coverage effects that sample a texture. The matrix is applied 1.116 + * to the src space position to compute texture coordinates. 1.117 + */ 1.118 + void addColorTextureEffect(GrTexture* texture, const SkMatrix& matrix); 1.119 + void addCoverageTextureEffect(GrTexture* texture, const SkMatrix& matrix); 1.120 + 1.121 + void addColorTextureEffect(GrTexture* texture, 1.122 + const SkMatrix& matrix, 1.123 + const GrTextureParams& params); 1.124 + void addCoverageTextureEffect(GrTexture* texture, 1.125 + const SkMatrix& matrix, 1.126 + const GrTextureParams& params); 1.127 + 1.128 + int numColorStages() const { return fColorStages.count(); } 1.129 + int numCoverageStages() const { return fCoverageStages.count(); } 1.130 + int numTotalStages() const { return this->numColorStages() + this->numCoverageStages(); } 1.131 + 1.132 + const GrEffectStage& getColorStage(int s) const { return fColorStages[s]; } 1.133 + const GrEffectStage& getCoverageStage(int s) const { return fCoverageStages[s]; } 1.134 + 1.135 + GrPaint& operator=(const GrPaint& paint) { 1.136 + fSrcBlendCoeff = paint.fSrcBlendCoeff; 1.137 + fDstBlendCoeff = paint.fDstBlendCoeff; 1.138 + fAntiAlias = paint.fAntiAlias; 1.139 + fDither = paint.fDither; 1.140 + 1.141 + fColor = paint.fColor; 1.142 + fCoverage = paint.fCoverage; 1.143 + 1.144 + fColorStages = paint.fColorStages; 1.145 + fCoverageStages = paint.fCoverageStages; 1.146 + 1.147 + return *this; 1.148 + } 1.149 + 1.150 + /** 1.151 + * Resets the paint to the defaults. 1.152 + */ 1.153 + void reset() { 1.154 + this->resetBlend(); 1.155 + this->resetOptions(); 1.156 + this->resetColor(); 1.157 + this->resetCoverage(); 1.158 + this->resetStages(); 1.159 + } 1.160 + 1.161 + /** 1.162 + * Determines whether the drawing with this paint is opaque with respect to both color blending 1.163 + * and fractional coverage. It does not consider whether AA has been enabled on the paint or 1.164 + * not. Depending upon whether multisampling or coverage-based AA is in use, AA may make the 1.165 + * result only apply to the interior of primitives. 1.166 + * 1.167 + */ 1.168 + bool isOpaque() const; 1.169 + 1.170 + /** 1.171 + * Returns true if isOpaque would return true and the paint represents a solid constant color 1.172 + * draw. If the result is true, constantColor will be updated to contain the constant color. 1.173 + */ 1.174 + bool isOpaqueAndConstantColor(GrColor* constantColor) const; 1.175 + 1.176 +private: 1.177 + 1.178 + /** 1.179 + * Helper for isOpaque and isOpaqueAndConstantColor. 1.180 + */ 1.181 + bool getOpaqueAndKnownColor(GrColor* solidColor, uint32_t* solidColorKnownComponents) const; 1.182 + 1.183 + /** 1.184 + * Called when the source coord system from which geometry is rendered changes. It ensures that 1.185 + * the local coordinates seen by effects remains unchanged. oldToNew gives the transformation 1.186 + * from the previous coord system to the new coord system. 1.187 + */ 1.188 + void localCoordChange(const SkMatrix& oldToNew) { 1.189 + for (int i = 0; i < fColorStages.count(); ++i) { 1.190 + fColorStages[i].localCoordChange(oldToNew); 1.191 + } 1.192 + for (int i = 0; i < fCoverageStages.count(); ++i) { 1.193 + fCoverageStages[i].localCoordChange(oldToNew); 1.194 + } 1.195 + } 1.196 + 1.197 + bool localCoordChangeInverse(const SkMatrix& newToOld) { 1.198 + SkMatrix oldToNew; 1.199 + bool computed = false; 1.200 + for (int i = 0; i < fColorStages.count(); ++i) { 1.201 + if (!computed && !newToOld.invert(&oldToNew)) { 1.202 + return false; 1.203 + } else { 1.204 + computed = true; 1.205 + } 1.206 + fColorStages[i].localCoordChange(oldToNew); 1.207 + } 1.208 + for (int i = 0; i < fCoverageStages.count(); ++i) { 1.209 + if (!computed && !newToOld.invert(&oldToNew)) { 1.210 + return false; 1.211 + } else { 1.212 + computed = true; 1.213 + } 1.214 + fCoverageStages[i].localCoordChange(oldToNew); 1.215 + } 1.216 + return true; 1.217 + } 1.218 + 1.219 + friend class GrContext; // To access above two functions 1.220 + 1.221 + SkSTArray<4, GrEffectStage> fColorStages; 1.222 + SkSTArray<2, GrEffectStage> fCoverageStages; 1.223 + 1.224 + GrBlendCoeff fSrcBlendCoeff; 1.225 + GrBlendCoeff fDstBlendCoeff; 1.226 + bool fAntiAlias; 1.227 + bool fDither; 1.228 + 1.229 + GrColor fColor; 1.230 + uint8_t fCoverage; 1.231 + 1.232 + void resetBlend() { 1.233 + fSrcBlendCoeff = kOne_GrBlendCoeff; 1.234 + fDstBlendCoeff = kZero_GrBlendCoeff; 1.235 + } 1.236 + 1.237 + void resetOptions() { 1.238 + fAntiAlias = false; 1.239 + fDither = false; 1.240 + } 1.241 + 1.242 + void resetColor() { 1.243 + fColor = GrColorPackRGBA(0xff, 0xff, 0xff, 0xff); 1.244 + } 1.245 + 1.246 + void resetCoverage() { 1.247 + fCoverage = 0xff; 1.248 + } 1.249 + 1.250 + void resetStages() { 1.251 + fColorStages.reset(); 1.252 + fCoverageStages.reset(); 1.253 + } 1.254 +}; 1.255 + 1.256 +#endif