1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/src/gpu/effects/GrBezierEffect.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,250 @@ 1.4 +/* 1.5 + * Copyright 2013 Google Inc. 1.6 + * 1.7 + * Use of this source code is governed by a BSD-style license that can be 1.8 + * found in the LICENSE file. 1.9 + */ 1.10 + 1.11 +#ifndef GrBezierEffect_DEFINED 1.12 +#define GrBezierEffect_DEFINED 1.13 + 1.14 +#include "GrDrawTargetCaps.h" 1.15 +#include "GrEffect.h" 1.16 +#include "GrVertexEffect.h" 1.17 +#include "GrTypesPriv.h" 1.18 + 1.19 +/** 1.20 + * Shader is based off of Loop-Blinn Quadratic GPU Rendering 1.21 + * The output of this effect is a hairline edge for conics. 1.22 + * Conics specified by implicit equation K^2 - LM. 1.23 + * K, L, and M, are the first three values of the vertex attribute, 1.24 + * the fourth value is not used. Distance is calculated using a 1.25 + * first order approximation from the taylor series. 1.26 + * Coverage for AA is max(0, 1-distance). 1.27 + * 1.28 + * Test were also run using a second order distance approximation. 1.29 + * There were two versions of the second order approx. The first version 1.30 + * is of roughly the form: 1.31 + * f(q) = |f(p)| - ||f'(p)||*||q-p|| - ||f''(p)||*||q-p||^2. 1.32 + * The second is similar: 1.33 + * f(q) = |f(p)| + ||f'(p)||*||q-p|| + ||f''(p)||*||q-p||^2. 1.34 + * The exact version of the equations can be found in the paper 1.35 + * "Distance Approximations for Rasterizing Implicit Curves" by Gabriel Taubin 1.36 + * 1.37 + * In both versions we solve the quadratic for ||q-p||. 1.38 + * Version 1: 1.39 + * gFM is magnitude of first partials and gFM2 is magnitude of 2nd partials (as derived from paper) 1.40 + * builder->fsCodeAppend("\t\tedgeAlpha = (sqrt(gFM*gFM+4.0*func*gF2M) - gFM)/(2.0*gF2M);\n"); 1.41 + * Version 2: 1.42 + * builder->fsCodeAppend("\t\tedgeAlpha = (gFM - sqrt(gFM*gFM-4.0*func*gF2M))/(2.0*gF2M);\n"); 1.43 + * 1.44 + * Also note that 2nd partials of k,l,m are zero 1.45 + * 1.46 + * When comparing the two second order approximations to the first order approximations, 1.47 + * the following results were found. Version 1 tends to underestimate the distances, thus it 1.48 + * basically increases all the error that we were already seeing in the first order 1.49 + * approx. So this version is not the one to use. Version 2 has the opposite effect 1.50 + * and tends to overestimate the distances. This is much closer to what we are 1.51 + * looking for. It is able to render ellipses (even thin ones) without the need to chop. 1.52 + * However, it can not handle thin hyperbolas well and thus would still rely on 1.53 + * chopping to tighten the clipping. Another side effect of the overestimating is 1.54 + * that the curves become much thinner and "ropey". If all that was ever rendered 1.55 + * were "not too thin" curves and ellipses then 2nd order may have an advantage since 1.56 + * only one geometry would need to be rendered. However no benches were run comparing 1.57 + * chopped first order and non chopped 2nd order. 1.58 + */ 1.59 +class GrGLConicEffect; 1.60 + 1.61 +class GrConicEffect : public GrVertexEffect { 1.62 +public: 1.63 + static GrEffectRef* Create(const GrEffectEdgeType edgeType, const GrDrawTargetCaps& caps) { 1.64 + GR_CREATE_STATIC_EFFECT(gConicFillAA, GrConicEffect, (kFillAA_GrEffectEdgeType)); 1.65 + GR_CREATE_STATIC_EFFECT(gConicHairAA, GrConicEffect, (kHairlineAA_GrEffectEdgeType)); 1.66 + GR_CREATE_STATIC_EFFECT(gConicFillBW, GrConicEffect, (kFillBW_GrEffectEdgeType)); 1.67 + switch (edgeType) { 1.68 + case kFillAA_GrEffectEdgeType: 1.69 + if (!caps.shaderDerivativeSupport()) { 1.70 + return NULL; 1.71 + } 1.72 + gConicFillAA->ref(); 1.73 + return gConicFillAA; 1.74 + case kHairlineAA_GrEffectEdgeType: 1.75 + if (!caps.shaderDerivativeSupport()) { 1.76 + return NULL; 1.77 + } 1.78 + gConicHairAA->ref(); 1.79 + return gConicHairAA; 1.80 + case kFillBW_GrEffectEdgeType: 1.81 + gConicFillBW->ref(); 1.82 + return gConicFillBW; 1.83 + default: 1.84 + return NULL; 1.85 + } 1.86 + } 1.87 + 1.88 + virtual ~GrConicEffect(); 1.89 + 1.90 + static const char* Name() { return "Conic"; } 1.91 + 1.92 + inline bool isAntiAliased() const { return GrEffectEdgeTypeIsAA(fEdgeType); } 1.93 + inline bool isFilled() const { return GrEffectEdgeTypeIsFill(fEdgeType); } 1.94 + inline GrEffectEdgeType getEdgeType() const { return fEdgeType; } 1.95 + 1.96 + typedef GrGLConicEffect GLEffect; 1.97 + 1.98 + virtual void getConstantColorComponents(GrColor* color, 1.99 + uint32_t* validFlags) const SK_OVERRIDE { 1.100 + *validFlags = 0; 1.101 + } 1.102 + 1.103 + virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE; 1.104 + 1.105 +private: 1.106 + GrConicEffect(GrEffectEdgeType); 1.107 + 1.108 + virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE; 1.109 + 1.110 + GrEffectEdgeType fEdgeType; 1.111 + 1.112 + GR_DECLARE_EFFECT_TEST; 1.113 + 1.114 + typedef GrVertexEffect INHERITED; 1.115 +}; 1.116 + 1.117 +/////////////////////////////////////////////////////////////////////////////// 1.118 +/** 1.119 + * The output of this effect is a hairline edge for quadratics. 1.120 + * Quadratic specified by 0=u^2-v canonical coords. u and v are the first 1.121 + * two components of the vertex attribute. At the three control points that define 1.122 + * the Quadratic, u, v have the values {0,0}, {1/2, 0}, and {1, 1} respectively. 1.123 + * Coverage for AA is min(0, 1-distance). 3rd & 4th cimponent unused. 1.124 + * Requires shader derivative instruction support. 1.125 + */ 1.126 +class GrGLQuadEffect; 1.127 + 1.128 +class GrQuadEffect : public GrVertexEffect { 1.129 +public: 1.130 + static GrEffectRef* Create(const GrEffectEdgeType edgeType, const GrDrawTargetCaps& caps) { 1.131 + GR_CREATE_STATIC_EFFECT(gQuadFillAA, GrQuadEffect, (kFillAA_GrEffectEdgeType)); 1.132 + GR_CREATE_STATIC_EFFECT(gQuadHairAA, GrQuadEffect, (kHairlineAA_GrEffectEdgeType)); 1.133 + GR_CREATE_STATIC_EFFECT(gQuadFillBW, GrQuadEffect, (kFillBW_GrEffectEdgeType)); 1.134 + switch (edgeType) { 1.135 + case kFillAA_GrEffectEdgeType: 1.136 + if (!caps.shaderDerivativeSupport()) { 1.137 + return NULL; 1.138 + } 1.139 + gQuadFillAA->ref(); 1.140 + return gQuadFillAA; 1.141 + case kHairlineAA_GrEffectEdgeType: 1.142 + if (!caps.shaderDerivativeSupport()) { 1.143 + return NULL; 1.144 + } 1.145 + gQuadHairAA->ref(); 1.146 + return gQuadHairAA; 1.147 + case kFillBW_GrEffectEdgeType: 1.148 + gQuadFillBW->ref(); 1.149 + return gQuadFillBW; 1.150 + default: 1.151 + return NULL; 1.152 + } 1.153 + } 1.154 + 1.155 + virtual ~GrQuadEffect(); 1.156 + 1.157 + static const char* Name() { return "Quad"; } 1.158 + 1.159 + inline bool isAntiAliased() const { return GrEffectEdgeTypeIsAA(fEdgeType); } 1.160 + inline bool isFilled() const { return GrEffectEdgeTypeIsFill(fEdgeType); } 1.161 + inline GrEffectEdgeType getEdgeType() const { return fEdgeType; } 1.162 + 1.163 + typedef GrGLQuadEffect GLEffect; 1.164 + 1.165 + virtual void getConstantColorComponents(GrColor* color, 1.166 + uint32_t* validFlags) const SK_OVERRIDE { 1.167 + *validFlags = 0; 1.168 + } 1.169 + 1.170 + virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE; 1.171 + 1.172 +private: 1.173 + GrQuadEffect(GrEffectEdgeType); 1.174 + 1.175 + virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE; 1.176 + 1.177 + GrEffectEdgeType fEdgeType; 1.178 + 1.179 + GR_DECLARE_EFFECT_TEST; 1.180 + 1.181 + typedef GrVertexEffect INHERITED; 1.182 +}; 1.183 + 1.184 +////////////////////////////////////////////////////////////////////////////// 1.185 +/** 1.186 + * Shader is based off of "Resolution Independent Curve Rendering using 1.187 + * Programmable Graphics Hardware" by Loop and Blinn. 1.188 + * The output of this effect is a hairline edge for non rational cubics. 1.189 + * Cubics are specified by implicit equation K^3 - LM. 1.190 + * K, L, and M, are the first three values of the vertex attribute, 1.191 + * the fourth value is not used. Distance is calculated using a 1.192 + * first order approximation from the taylor series. 1.193 + * Coverage for AA is max(0, 1-distance). 1.194 + */ 1.195 +class GrGLCubicEffect; 1.196 + 1.197 +class GrCubicEffect : public GrVertexEffect { 1.198 +public: 1.199 + static GrEffectRef* Create(const GrEffectEdgeType edgeType, const GrDrawTargetCaps& caps) { 1.200 + GR_CREATE_STATIC_EFFECT(gCubicFillAA, GrCubicEffect, (kFillAA_GrEffectEdgeType)); 1.201 + GR_CREATE_STATIC_EFFECT(gCubicHairAA, GrCubicEffect, (kHairlineAA_GrEffectEdgeType)); 1.202 + GR_CREATE_STATIC_EFFECT(gCubicFillBW, GrCubicEffect, (kFillBW_GrEffectEdgeType)); 1.203 + switch (edgeType) { 1.204 + case kFillAA_GrEffectEdgeType: 1.205 + if (!caps.shaderDerivativeSupport()) { 1.206 + return NULL; 1.207 + } 1.208 + gCubicFillAA->ref(); 1.209 + return gCubicFillAA; 1.210 + case kHairlineAA_GrEffectEdgeType: 1.211 + if (!caps.shaderDerivativeSupport()) { 1.212 + return NULL; 1.213 + } 1.214 + gCubicHairAA->ref(); 1.215 + return gCubicHairAA; 1.216 + case kFillBW_GrEffectEdgeType: 1.217 + gCubicFillBW->ref(); 1.218 + return gCubicFillBW; 1.219 + default: 1.220 + return NULL; 1.221 + } 1.222 + } 1.223 + 1.224 + virtual ~GrCubicEffect(); 1.225 + 1.226 + static const char* Name() { return "Cubic"; } 1.227 + 1.228 + inline bool isAntiAliased() const { return GrEffectEdgeTypeIsAA(fEdgeType); } 1.229 + inline bool isFilled() const { return GrEffectEdgeTypeIsFill(fEdgeType); } 1.230 + inline GrEffectEdgeType getEdgeType() const { return fEdgeType; } 1.231 + 1.232 + typedef GrGLCubicEffect GLEffect; 1.233 + 1.234 + virtual void getConstantColorComponents(GrColor* color, 1.235 + uint32_t* validFlags) const SK_OVERRIDE { 1.236 + *validFlags = 0; 1.237 + } 1.238 + 1.239 + virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE; 1.240 + 1.241 +private: 1.242 + GrCubicEffect(GrEffectEdgeType); 1.243 + 1.244 + virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE; 1.245 + 1.246 + GrEffectEdgeType fEdgeType; 1.247 + 1.248 + GR_DECLARE_EFFECT_TEST; 1.249 + 1.250 + typedef GrVertexEffect INHERITED; 1.251 +}; 1.252 + 1.253 +#endif