blob: 5b59563edad096005ab9e68a9051f7ae09c474a3 [file] [log] [blame]
bsalomon@google.comdfe75bc2011-03-25 12:31:16 +00001/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00002 * Copyright 2011 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
bsalomon@google.comdfe75bc2011-03-25 12:31:16 +00006 */
7
8#ifndef GrPathRenderer_DEFINED
9#define GrPathRenderer_DEFINED
10
Brian Salomon653f42f2018-07-10 10:07:31 -040011#include "GrTypesPriv.h"
bsalomon@google.com49313f62011-09-14 13:54:05 +000012#include "SkTArray.h"
Brian Salomon653f42f2018-07-10 10:07:31 -040013#include "SkRefCnt.h"
bsalomon@google.com49313f62011-09-14 13:54:05 +000014
Brian Salomon653f42f2018-07-10 10:07:31 -040015class GrCaps;
16class GrClip;
17class GrContext;
robertphillips976f5f02016-06-03 10:59:20 -070018class GrFixedClip;
Chris Daltonbbfd5162017-11-07 13:35:22 -070019class GrHardClip;
Brian Salomon653f42f2018-07-10 10:07:31 -040020class GrPaint;
21class GrRenderTargetContext;
22class GrShape;
23class GrStyle;
24struct GrUserStencilSettings;
25struct SkIRect;
26class SkMatrix;
27class SkPath;
bsalomon@google.comdfe75bc2011-03-25 12:31:16 +000028
29/**
Robert Phillipsf2361d22016-10-25 14:20:06 -040030 * Base class for drawing paths into a GrOpList.
bsalomon@google.comdfe75bc2011-03-25 12:31:16 +000031 */
commit-bot@chromium.orga4de8c22013-09-09 13:38:37 +000032class SK_API GrPathRenderer : public SkRefCnt {
bsalomon@google.comdfe75bc2011-03-25 12:31:16 +000033public:
bsalomon@google.comc2099d22012-03-02 21:26:50 +000034 GrPathRenderer();
bsalomon@google.comdfe75bc2011-03-25 12:31:16 +000035
36 /**
bsalomon@google.com45a15f52012-12-10 19:10:17 +000037 * A caller may wish to use a path renderer to draw a path into the stencil buffer. However,
38 * the path renderer itself may require use of the stencil buffer. Also a path renderer may
joshualittb0a8a372014-09-23 09:50:21 -070039 * use a GrProcessor coverage stage that sets coverage to zero to eliminate pixels that are
40 * covered by bounding geometry but outside the path. These exterior pixels would still be
41 * rendered into the stencil.
bsalomon@google.com45a15f52012-12-10 19:10:17 +000042 *
43 * A GrPathRenderer can provide three levels of support for stenciling paths:
Brian Salomone5b399e2017-07-19 13:50:54 -040044 * 1) kNoRestriction: This is the most general. The caller passes a GrPaint and calls drawPath().
45 * The path is rendered exactly as the draw state indicates including support
46 * for simultaneous color and stenciling with arbitrary stenciling rules.
47 * Pixels partially covered by AA paths are affected by the stencil settings.
bsalomon@google.com45a15f52012-12-10 19:10:17 +000048 * 2) kStencilOnly: The path renderer cannot apply arbitrary stencil rules nor shade and stencil
49 * simultaneously. The path renderer does support the stencilPath() function
50 * which performs no color writes and writes a non-zero stencil value to pixels
51 * covered by the path.
52 * 3) kNoSupport: This path renderer cannot be used to stencil the path.
53 */
robertphillips68737822015-10-29 12:12:21 -070054 enum StencilSupport {
55 kNoSupport_StencilSupport,
56 kStencilOnly_StencilSupport,
57 kNoRestriction_StencilSupport,
58 };
bsalomon@google.com45a15f52012-12-10 19:10:17 +000059
60 /**
robertphillips@google.come79f3202014-02-11 16:30:21 +000061 * This function is to get the stencil support for a particular path. The path's fill must
bsalomond6f25bf2016-05-05 09:26:21 -070062 * not be an inverse type. The path will always be filled and not stroked.
bsalomon@google.comdfe75bc2011-03-25 12:31:16 +000063 *
bsalomon8acedde2016-06-24 10:42:16 -070064 * @param shape the shape that will be drawn. Must be simple fill styled and non-inverse
65 * filled.
bsalomon@google.comdfe75bc2011-03-25 12:31:16 +000066 */
Brian Salomon653f42f2018-07-10 10:07:31 -040067 StencilSupport getStencilSupport(const GrShape& shape) const;
bsalomon@google.comdfe75bc2011-03-25 12:31:16 +000068
Chris Dalton5ed44232017-09-07 13:22:46 -060069 enum class CanDrawPath {
70 kNo,
71 kAsBackup, // i.e. This renderer is better than SW fallback if no others can draw the path.
72 kYes
73 };
74
bsalomon0aff2fa2015-07-31 06:48:27 -070075 struct CanDrawPathArgs {
Chris Daltondb91c6e2017-09-08 16:25:08 -060076 SkDEBUGCODE(CanDrawPathArgs() { memset(this, 0, sizeof(*this)); }) // For validation.
77
Eric Karl5c779752017-05-08 12:02:07 -070078 const GrCaps* fCaps;
Chris Daltondb91c6e2017-09-08 16:25:08 -060079 const SkIRect* fClipConservativeBounds;
bsalomon0aff2fa2015-07-31 06:48:27 -070080 const SkMatrix* fViewMatrix;
bsalomon8acedde2016-06-24 10:42:16 -070081 const GrShape* fShape;
Brian Salomon0e8fc8b2016-12-09 15:10:07 -050082 GrAAType fAAType;
robertphillipse7d4b2f2015-08-13 07:57:10 -070083
robertphillips68737822015-10-29 12:12:21 -070084 // These next two are only used by GrStencilAndCoverPathRenderer
cdalton93a379b2016-05-11 13:58:08 -070085 bool fHasUserStencilSettings;
robertphillips68737822015-10-29 12:12:21 -070086
bsalomon8acedde2016-06-24 10:42:16 -070087#ifdef SK_DEBUG
robertphillipse7d4b2f2015-08-13 07:57:10 -070088 void validate() const {
Eric Karl5c779752017-05-08 12:02:07 -070089 SkASSERT(fCaps);
Chris Daltondb91c6e2017-09-08 16:25:08 -060090 SkASSERT(fClipConservativeBounds);
robertphillipse7d4b2f2015-08-13 07:57:10 -070091 SkASSERT(fViewMatrix);
bsalomon8acedde2016-06-24 10:42:16 -070092 SkASSERT(fShape);
robertphillipse7d4b2f2015-08-13 07:57:10 -070093 }
bsalomon8acedde2016-06-24 10:42:16 -070094#endif
bsalomon0aff2fa2015-07-31 06:48:27 -070095 };
96
bsalomon@google.com208236d2012-03-12 13:15:33 +000097 /**
Chris Dalton5ed44232017-09-07 13:22:46 -060098 * Returns how well this path renderer is able to render the given path. Returning kNo or
99 * kAsBackup allows the caller to keep searching for a better path renderer. This function is
100 * called when searching for the best path renderer to draw a path.
bsalomon@google.com208236d2012-03-12 13:15:33 +0000101 */
Chris Dalton5ed44232017-09-07 13:22:46 -0600102 CanDrawPath canDrawPath(const CanDrawPathArgs& args) const {
robertphillipse7d4b2f2015-08-13 07:57:10 -0700103 SkDEBUGCODE(args.validate();)
bsalomon0aff2fa2015-07-31 06:48:27 -0700104 return this->onCanDrawPath(args);
105 }
106
bsalomon0aff2fa2015-07-31 06:48:27 -0700107 struct DrawPathArgs {
Robert Phillips256c37b2017-03-01 14:32:46 -0500108 GrContext* fContext;
Brian Salomon82f44312017-01-11 13:42:54 -0500109 GrPaint&& fPaint;
110 const GrUserStencilSettings* fUserStencilSettings;
111 GrRenderTargetContext* fRenderTargetContext;
112 const GrClip* fClip;
Chris Daltondb91c6e2017-09-08 16:25:08 -0600113 const SkIRect* fClipConservativeBounds;
Brian Salomon82f44312017-01-11 13:42:54 -0500114 const SkMatrix* fViewMatrix;
115 const GrShape* fShape;
116 GrAAType fAAType;
117 bool fGammaCorrect;
bsalomon8acedde2016-06-24 10:42:16 -0700118#ifdef SK_DEBUG
robertphillipse7d4b2f2015-08-13 07:57:10 -0700119 void validate() const {
Robert Phillips256c37b2017-03-01 14:32:46 -0500120 SkASSERT(fContext);
robertphillips976f5f02016-06-03 10:59:20 -0700121 SkASSERT(fUserStencilSettings);
Brian Osman11052242016-10-27 14:47:55 -0400122 SkASSERT(fRenderTargetContext);
cdalton862cff32016-05-12 15:09:48 -0700123 SkASSERT(fClip);
Chris Daltondb91c6e2017-09-08 16:25:08 -0600124 SkASSERT(fClipConservativeBounds);
robertphillipse7d4b2f2015-08-13 07:57:10 -0700125 SkASSERT(fViewMatrix);
bsalomon8acedde2016-06-24 10:42:16 -0700126 SkASSERT(fShape);
robertphillipse7d4b2f2015-08-13 07:57:10 -0700127 }
bsalomon8acedde2016-06-24 10:42:16 -0700128#endif
bsalomon0aff2fa2015-07-31 06:48:27 -0700129 };
130
bsalomon@google.comee435122011-07-01 14:57:55 +0000131 /**
robertphillips@google.come79f3202014-02-11 16:30:21 +0000132 * Draws the path into the draw target. If getStencilSupport() would return kNoRestriction then
Brian Salomone5b399e2017-07-19 13:50:54 -0400133 * the subclass must respect the stencil settings.
bsalomon@google.comee435122011-07-01 14:57:55 +0000134 */
Brian Salomon653f42f2018-07-10 10:07:31 -0400135 bool drawPath(const DrawPathArgs& args);
Chris Daltondb91c6e2017-09-08 16:25:08 -0600136 /**
137 * Args to stencilPath(). fAAType cannot be kCoverage.
bsalomon0aff2fa2015-07-31 06:48:27 -0700138 */
139 struct StencilPathArgs {
Chris Daltondb91c6e2017-09-08 16:25:08 -0600140 SkDEBUGCODE(StencilPathArgs() { memset(this, 0, sizeof(*this)); }) // For validation.
141
Robert Phillips256c37b2017-03-01 14:32:46 -0500142 GrContext* fContext;
Brian Osman11052242016-10-27 14:47:55 -0400143 GrRenderTargetContext* fRenderTargetContext;
Chris Daltonbbfd5162017-11-07 13:35:22 -0700144 const GrHardClip* fClip;
Chris Daltondb91c6e2017-09-08 16:25:08 -0600145 const SkIRect* fClipConservativeBounds;
Brian Osman11052242016-10-27 14:47:55 -0400146 const SkMatrix* fViewMatrix;
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500147 GrAAType fAAType;
Brian Osman11052242016-10-27 14:47:55 -0400148 const GrShape* fShape;
robertphillipse7d4b2f2015-08-13 07:57:10 -0700149
Brian Salomon653f42f2018-07-10 10:07:31 -0400150 SkDEBUGCODE(void validate() const);
bsalomon0aff2fa2015-07-31 06:48:27 -0700151 };
152
bsalomon@google.comee435122011-07-01 14:57:55 +0000153 /**
robertphillips@google.come79f3202014-02-11 16:30:21 +0000154 * Draws the path to the stencil buffer. Assume the writable stencil bits are already
155 * initialized to zero. The pixels inside the path will have non-zero stencil values afterwards.
bsalomon@google.com45a15f52012-12-10 19:10:17 +0000156 */
bsalomon0aff2fa2015-07-31 06:48:27 -0700157 void stencilPath(const StencilPathArgs& args) {
robertphillipse7d4b2f2015-08-13 07:57:10 -0700158 SkDEBUGCODE(args.validate();)
bsalomon8acedde2016-06-24 10:42:16 -0700159 SkASSERT(kNoSupport_StencilSupport != this->getStencilSupport(*args.fShape));
bsalomon0aff2fa2015-07-31 06:48:27 -0700160 this->onStencilPath(args);
bsalomon@google.com45a15f52012-12-10 19:10:17 +0000161 }
162
commit-bot@chromium.orge0a868c2013-11-22 07:02:11 +0000163 // Helper for determining if we can treat a thin stroke as a hairline w/ coverage.
164 // If we can, we draw lots faster (raster device does this same test).
Brian Salomon653f42f2018-07-10 10:07:31 -0400165 static bool IsStrokeHairlineOrEquivalent(const GrStyle&, const SkMatrix&,
166 SkScalar* outCoverage);
commit-bot@chromium.orge0a868c2013-11-22 07:02:11 +0000167
bsalomon@google.com45a15f52012-12-10 19:10:17 +0000168protected:
bsalomon@google.com1dd9baa2013-05-20 16:49:06 +0000169 // Helper for getting the device bounds of a path. Inverse filled paths will have bounds set
170 // by devSize. Non-inverse path bounds will not necessarily be clipped to devSize.
171 static void GetPathDevBounds(const SkPath& path,
172 int devW,
173 int devH,
174 const SkMatrix& matrix,
175 SkRect* bounds);
176
bsalomon@google.comdfe75bc2011-03-25 12:31:16 +0000177private:
bsalomon0aff2fa2015-07-31 06:48:27 -0700178 /**
179 * Subclass overrides if it has any limitations of stenciling support.
180 */
bsalomon8acedde2016-06-24 10:42:16 -0700181 virtual StencilSupport onGetStencilSupport(const GrShape&) const {
bsalomon0aff2fa2015-07-31 06:48:27 -0700182 return kNoRestriction_StencilSupport;
183 }
184
185 /**
186 * Subclass implementation of drawPath()
187 */
188 virtual bool onDrawPath(const DrawPathArgs& args) = 0;
189
190 /**
191 * Subclass implementation of canDrawPath()
192 */
Chris Dalton5ed44232017-09-07 13:22:46 -0600193 virtual CanDrawPath onCanDrawPath(const CanDrawPathArgs& args) const = 0;
bsalomon0aff2fa2015-07-31 06:48:27 -0700194
195 /**
196 * Subclass implementation of stencilPath(). Subclass must override iff it ever returns
197 * kStencilOnly in onGetStencilSupport().
198 */
Brian Salomon653f42f2018-07-10 10:07:31 -0400199 virtual void onStencilPath(const StencilPathArgs&);
bsalomon0aff2fa2015-07-31 06:48:27 -0700200
commit-bot@chromium.orga4de8c22013-09-09 13:38:37 +0000201 typedef SkRefCnt INHERITED;
bsalomon@google.comdfe75bc2011-03-25 12:31:16 +0000202};
203
bsalomon@google.comdfe75bc2011-03-25 12:31:16 +0000204#endif