1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/src/gpu/GrPathRenderer.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,213 @@ 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 +#ifndef GrPathRenderer_DEFINED 1.13 +#define GrPathRenderer_DEFINED 1.14 + 1.15 +#include "GrDrawTarget.h" 1.16 +#include "GrPathRendererChain.h" 1.17 +#include "GrStencil.h" 1.18 + 1.19 +#include "SkDrawProcs.h" 1.20 +#include "SkStrokeRec.h" 1.21 +#include "SkTArray.h" 1.22 + 1.23 +class SkPath; 1.24 + 1.25 +struct GrPoint; 1.26 + 1.27 +/** 1.28 + * Base class for drawing paths into a GrDrawTarget. 1.29 + * 1.30 + * Derived classes can use stages GrPaint::kTotalStages through GrDrawState::kNumStages-1. The 1.31 + * stages before GrPaint::kTotalStages are reserved for setting up the draw (i.e., textures and 1.32 + * filter masks). 1.33 + */ 1.34 +class SK_API GrPathRenderer : public SkRefCnt { 1.35 +public: 1.36 + SK_DECLARE_INST_COUNT(GrPathRenderer) 1.37 + 1.38 + /** 1.39 + * This is called to install custom path renderers in every GrContext at create time. The 1.40 + * default implementation in GrCreatePathRenderer_none.cpp does not add any additional 1.41 + * renderers. Link against another implementation to install your own. The first added is the 1.42 + * most preferred path renderer, second is second most preferred, etc. 1.43 + * 1.44 + * @param context the context that will use the path renderer 1.45 + * @param prChain the chain to add path renderers to. 1.46 + */ 1.47 + static void AddPathRenderers(GrContext* context, GrPathRendererChain* prChain); 1.48 + 1.49 + 1.50 + GrPathRenderer(); 1.51 + 1.52 + /** 1.53 + * A caller may wish to use a path renderer to draw a path into the stencil buffer. However, 1.54 + * the path renderer itself may require use of the stencil buffer. Also a path renderer may 1.55 + * use a GrEffect coverage stage that sets coverage to zero to eliminate pixels that are covered 1.56 + * by bounding geometry but outside the path. These exterior pixels would still be rendered into 1.57 + * the stencil. 1.58 + * 1.59 + * A GrPathRenderer can provide three levels of support for stenciling paths: 1.60 + * 1) kNoRestriction: This is the most general. The caller sets up the GrDrawState on the target 1.61 + * and calls drawPath(). The path is rendered exactly as the draw state 1.62 + * indicates including support for simultaneous color and stenciling with 1.63 + * arbitrary stenciling rules. Pixels partially covered by AA paths are 1.64 + * affected by the stencil settings. 1.65 + * 2) kStencilOnly: The path renderer cannot apply arbitrary stencil rules nor shade and stencil 1.66 + * simultaneously. The path renderer does support the stencilPath() function 1.67 + * which performs no color writes and writes a non-zero stencil value to pixels 1.68 + * covered by the path. 1.69 + * 3) kNoSupport: This path renderer cannot be used to stencil the path. 1.70 + */ 1.71 + typedef GrPathRendererChain::StencilSupport StencilSupport; 1.72 + static const StencilSupport kNoSupport_StencilSupport = 1.73 + GrPathRendererChain::kNoSupport_StencilSupport; 1.74 + static const StencilSupport kStencilOnly_StencilSupport = 1.75 + GrPathRendererChain::kStencilOnly_StencilSupport; 1.76 + static const StencilSupport kNoRestriction_StencilSupport = 1.77 + GrPathRendererChain::kNoRestriction_StencilSupport; 1.78 + 1.79 + /** 1.80 + * This function is to get the stencil support for a particular path. The path's fill must 1.81 + * not be an inverse type. 1.82 + * 1.83 + * @param target target that the path will be rendered to 1.84 + * @param path the path that will be drawn 1.85 + * @param stroke the stroke information (width, join, cap). 1.86 + */ 1.87 + StencilSupport getStencilSupport(const SkPath& path, 1.88 + const SkStrokeRec& stroke, 1.89 + const GrDrawTarget* target) const { 1.90 + SkASSERT(!path.isInverseFillType()); 1.91 + return this->onGetStencilSupport(path, stroke, target); 1.92 + } 1.93 + 1.94 + /** 1.95 + * Returns true if this path renderer is able to render the path. Returning false allows the 1.96 + * caller to fallback to another path renderer This function is called when searching for a path 1.97 + * renderer capable of rendering a path. 1.98 + * 1.99 + * @param path The path to draw 1.100 + * @param stroke The stroke information (width, join, cap) 1.101 + * @param target The target that the path will be rendered to 1.102 + * @param antiAlias True if anti-aliasing is required. 1.103 + * 1.104 + * @return true if the path can be drawn by this object, false otherwise. 1.105 + */ 1.106 + virtual bool canDrawPath(const SkPath& path, 1.107 + const SkStrokeRec& rec, 1.108 + const GrDrawTarget* target, 1.109 + bool antiAlias) const = 0; 1.110 + /** 1.111 + * Draws the path into the draw target. If getStencilSupport() would return kNoRestriction then 1.112 + * the subclass must respect the stencil settings of the target's draw state. 1.113 + * 1.114 + * @param path the path to draw. 1.115 + * @param stroke the stroke information (width, join, cap) 1.116 + * @param target target that the path will be rendered to 1.117 + * @param antiAlias true if anti-aliasing is required. 1.118 + */ 1.119 + bool drawPath(const SkPath& path, 1.120 + const SkStrokeRec& stroke, 1.121 + GrDrawTarget* target, 1.122 + bool antiAlias) { 1.123 + SkASSERT(!path.isEmpty()); 1.124 + SkASSERT(this->canDrawPath(path, stroke, target, antiAlias)); 1.125 + SkASSERT(target->drawState()->getStencil().isDisabled() || 1.126 + kNoRestriction_StencilSupport == this->getStencilSupport(path, stroke, target)); 1.127 + return this->onDrawPath(path, stroke, target, antiAlias); 1.128 + } 1.129 + 1.130 + /** 1.131 + * Draws the path to the stencil buffer. Assume the writable stencil bits are already 1.132 + * initialized to zero. The pixels inside the path will have non-zero stencil values afterwards. 1.133 + * 1.134 + * @param path the path to draw. 1.135 + * @param stroke the stroke information (width, join, cap) 1.136 + * @param target target that the path will be rendered to 1.137 + */ 1.138 + void stencilPath(const SkPath& path, const SkStrokeRec& stroke, GrDrawTarget* target) { 1.139 + SkASSERT(!path.isEmpty()); 1.140 + SkASSERT(kNoSupport_StencilSupport != this->getStencilSupport(path, stroke, target)); 1.141 + this->onStencilPath(path, stroke, target); 1.142 + } 1.143 + 1.144 + // Helper for determining if we can treat a thin stroke as a hairline w/ coverage. 1.145 + // If we can, we draw lots faster (raster device does this same test). 1.146 + static bool IsStrokeHairlineOrEquivalent(const SkStrokeRec& stroke, const SkMatrix& matrix, 1.147 + SkScalar* outCoverage) { 1.148 + if (stroke.isHairlineStyle()) { 1.149 + if (NULL != outCoverage) { 1.150 + *outCoverage = SK_Scalar1; 1.151 + } 1.152 + return true; 1.153 + } 1.154 + return stroke.getStyle() == SkStrokeRec::kStroke_Style && 1.155 + SkDrawTreatAAStrokeAsHairline(stroke.getWidth(), matrix, outCoverage); 1.156 + } 1.157 + 1.158 +protected: 1.159 + /** 1.160 + * Subclass overrides if it has any limitations of stenciling support. 1.161 + */ 1.162 + virtual StencilSupport onGetStencilSupport(const SkPath&, 1.163 + const SkStrokeRec&, 1.164 + const GrDrawTarget*) const { 1.165 + return kNoRestriction_StencilSupport; 1.166 + } 1.167 + 1.168 + /** 1.169 + * Subclass implementation of drawPath() 1.170 + */ 1.171 + virtual bool onDrawPath(const SkPath& path, 1.172 + const SkStrokeRec& stroke, 1.173 + GrDrawTarget* target, 1.174 + bool antiAlias) = 0; 1.175 + 1.176 + /** 1.177 + * Subclass implementation of stencilPath(). Subclass must override iff it ever returns 1.178 + * kStencilOnly in onGetStencilSupport(). 1.179 + */ 1.180 + virtual void onStencilPath(const SkPath& path, const SkStrokeRec& stroke, GrDrawTarget* target) { 1.181 + GrDrawTarget::AutoStateRestore asr(target, GrDrawTarget::kPreserve_ASRInit); 1.182 + GrDrawState* drawState = target->drawState(); 1.183 + GR_STATIC_CONST_SAME_STENCIL(kIncrementStencil, 1.184 + kReplace_StencilOp, 1.185 + kReplace_StencilOp, 1.186 + kAlways_StencilFunc, 1.187 + 0xffff, 1.188 + 0xffff, 1.189 + 0xffff); 1.190 + drawState->setStencil(kIncrementStencil); 1.191 + drawState->enableState(GrDrawState::kNoColorWrites_StateBit); 1.192 + this->drawPath(path, stroke, target, false); 1.193 + } 1.194 + 1.195 + // Helper for getting the device bounds of a path. Inverse filled paths will have bounds set 1.196 + // by devSize. Non-inverse path bounds will not necessarily be clipped to devSize. 1.197 + static void GetPathDevBounds(const SkPath& path, 1.198 + int devW, 1.199 + int devH, 1.200 + const SkMatrix& matrix, 1.201 + SkRect* bounds); 1.202 + 1.203 + // Helper version that gets the dev width and height from a GrSurface. 1.204 + static void GetPathDevBounds(const SkPath& path, 1.205 + const GrSurface* device, 1.206 + const SkMatrix& matrix, 1.207 + SkRect* bounds) { 1.208 + GetPathDevBounds(path, device->width(), device->height(), matrix, bounds); 1.209 + } 1.210 + 1.211 +private: 1.212 + 1.213 + typedef SkRefCnt INHERITED; 1.214 +}; 1.215 + 1.216 +#endif