OLD | NEW |
---|---|
(Empty) | |
1 /* | |
2 * Copyright 2015 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. | |
6 */ | |
7 | |
8 #include "GrDrawRect.h" | |
9 | |
10 #include "GrContext.h" | |
11 #include "GrClip.h" | |
12 #include "GrDrawTarget.h" | |
13 #include "GrRenderTarget.h" | |
14 #include "GrStrokeInfo.h" | |
15 #include "SkColorFilter.h" | |
16 #include "SkImageFilter.h" | |
17 #include "SkGr.h" | |
18 #include "SkMatrix.h" | |
19 #include "SkMaskFilter.h" | |
20 #include "SkPaint.h" | |
21 #include "SkRect.h" | |
22 #include "SkShader.h" | |
23 #include "SkXfermode.h" | |
24 #include "batches/GrRectBatchFactory.h" | |
25 | |
robertphillips
2015/09/25 12:48:49
AAStroke
AAFill
BWStroke
BWFill
?
joshualitt
2015/09/25 18:17:13
Brian doesn't like BW
robertphillips
2015/09/25 20:00:35
I proposing a reordering not a renaming.
| |
26 enum RectBatchType { | |
27 kAAStroke_RectBatchType, | |
28 kAAFill_RectBatchType, | |
29 kNonAAFill_RectBatchType, | |
30 kNonAAStroke_RectBatchType, | |
31 }; | |
32 | |
33 class GrDrawRectSnap : public GrDrawSnap { | |
34 public: | |
35 GrDrawRectSnap(const SkPaint& paint, | |
36 const GrClip& clip, | |
37 RectBatchType type, | |
38 bool snapToPixelCenter) | |
39 : fShader(SkSafeRef(paint.getShader())) | |
40 , fMaskFilter(SkSafeRef(paint.getMaskFilter())) | |
bsalomon
2015/09/23 13:49:38
Maybe just punt if the originating paint has a IM,
joshualitt
2015/09/25 18:17:13
Acknowledged.
| |
41 , fImageFilter(SkSafeRef(paint.getImageFilter())) | |
42 , fColorFilter(SkSafeRef(paint.getColorFilter())) | |
43 , fClipGenID(clip.clipType() != GrClip::kClipStack_ClipType ? | |
44 -1 : | |
45 clip.clipStack()->getTopmostGenID()) | |
46 , fType(type) | |
47 , fSnapToPixelCenters(snapToPixelCenter) | |
48 , fIsDither(paint.isDither()) { | |
49 fClassID = GrDrawRect::ClassID(); | |
50 } | |
51 | |
52 bool canBatch(const SkPaint& paint, | |
53 const GrClip& clip, | |
54 RectBatchType type, | |
55 bool snapToPixelCenters) const { | |
56 return paint.getShader() == fShader && | |
57 paint.getMaskFilter() == fMaskFilter && | |
58 paint.getImageFilter() == fImageFilter && | |
59 paint.getColorFilter() == fColorFilter && | |
60 paint.isDither() == fIsDither && | |
61 fClipGenID != -1 && clip.clipType() == GrClip::kClipStack_ClipTyp e && | |
62 fClipGenID == clip.clipStack()->getTopmostGenID() && | |
63 fType == type && | |
64 fSnapToPixelCenters == snapToPixelCenters; | |
65 } | |
66 | |
67 // we only bother fast pathing kSrcOver_Mode, though we could do quite a bit more | |
68 static bool CanSnap(const SkPaint& paint) { | |
bsalomon
2015/09/23 13:49:38
kSrcOver_Mode is always a nullptr for paint.getXfe
joshualitt
2015/09/25 18:17:13
Acknowledged.
| |
69 return SkXfermode::IsMode(paint.getXfermode(), SkXfermode::kSrcOver_Mode ); | |
70 } | |
71 | |
72 private: | |
73 SkAutoTUnref<SkShader> fShader; | |
74 SkAutoTUnref<SkMaskFilter> fMaskFilter; | |
75 SkAutoTUnref<SkImageFilter> fImageFilter; | |
76 SkAutoTUnref<SkColorFilter> fColorFilter; | |
77 int32_t fClipGenID; | |
78 RectBatchType fType; | |
79 bool fSnapToPixelCenters; | |
80 bool fIsDither; | |
81 | |
82 typedef GrDrawSnap INHERITED; | |
83 }; | |
84 | |
85 inline static RectBatchType compute_rect_batch_type(bool useAA, SkScalar width) { | |
86 if (useAA) { | |
87 if (width >= 0) { | |
88 return kAAStroke_RectBatchType; | |
89 } else { | |
90 return kAAFill_RectBatchType; | |
91 } | |
92 } else if (width >= 0) { | |
93 return kNonAAStroke_RectBatchType; | |
94 } else { | |
95 return kNonAAFill_RectBatchType; | |
96 } | |
97 } | |
98 | |
99 inline static bool can_fastpath(GrDrawTarget* drawTarget, | |
100 const SkPaint& paint, | |
101 const GrClip& clip, | |
102 GrColor color, | |
103 const SkMatrix& viewMatrix, | |
104 const SkRect& rect, | |
105 const GrStrokeInfo& strokeInfo, | |
106 RectBatchType batchType, | |
107 bool snapToPixelCenters) { | |
108 GrBatch* lastBatch = drawTarget->lastBatch(); | |
109 if (!lastBatch) { | |
110 return false; | |
111 } | |
112 | |
robertphillips
2015/09/25 12:48:49
drawSnap -> getLastSnap ?
calling drawSnap here s
joshualitt
2015/09/25 18:17:13
Acknowledged.
| |
113 const GrDrawSnap* lastSnap = lastBatch->drawSnap(); | |
114 if (!lastSnap) { | |
115 return false; | |
116 } | |
117 | |
118 if (lastSnap->classID() != GrDrawRect::ClassID()) { | |
119 return false; | |
120 } | |
121 | |
122 const GrDrawRectSnap* lastSnapCast = static_cast<const GrDrawRectSnap*>(last Snap); | |
123 if (lastSnapCast->canBatch(paint, clip, batchType, snapToPixelCenters)) { | |
124 switch (batchType) { | |
125 case kAAStroke_RectBatchType: | |
bsalomon
2015/09/23 13:49:38
Would it make sense to store an Append()/Create()
robertphillips
2015/09/25 12:48:49
We would still have to deal with all the different
joshualitt
2015/09/25 18:17:13
yea, I think in the short term this is the best wa
| |
126 if (GrAAStrokeRectBatch::Append(lastBatch, color, viewMatrix, re ct, | |
127 strokeInfo)) { | |
128 return true; | |
129 } | |
130 break; | |
131 case kAAFill_RectBatchType: | |
132 GrAAFillRectBatch::Append(lastBatch, color, viewMatrix, rect); | |
133 return true; | |
134 case kNonAAFill_RectBatchType: | |
135 if (GrNonAAFillRectBatch::Append(lastBatch, color, viewMatrix, r ect, | |
136 nullptr, nullptr)) { | |
137 return true; | |
138 } | |
139 break; | |
140 case kNonAAStroke_RectBatchType: | |
141 // GrNonAAStrokeRectBatch doesn't batch yet | |
142 break; | |
143 } | |
144 } | |
145 | |
146 return false; | |
147 } | |
148 | |
149 void GrDrawRect::execute(GrDrawTarget* drawTarget) const { | |
150 const SkPaint& paint = *fPaint; | |
151 const GrClip& clip = *fClip; | |
152 const SkMatrix& viewMatrix = *fViewMatrix; | |
153 const SkRect& rect = *fRect; | |
154 | |
robertphillips
2015/09/25 12:48:49
Didn't we pull all the info for fStrokeInfo out of
joshualitt
2015/09/25 18:17:13
yes, but why pull it out again if we don't have to
| |
155 SkScalar width = nullptr == fStrokeInfo ? -1 : fStrokeInfo->getWidth(); | |
156 | |
157 bool needAA = fPaint->isAntiAlias() && !fRenderTarget->isUnifiedMultisampled (); | |
158 | |
159 // The fill path can handle rotation but not skew | |
160 // The stroke path needs the rect to remain axis aligned (no rotation or ske w) | |
161 // None of our AA draw rect calls can handle perspective yet | |
162 bool canApplyAA = width >= 0 ? viewMatrix.rectStaysRect() : viewMatrix.prese rvesRightAngles(); | |
163 bool useAA = needAA && canApplyAA; | |
164 | |
165 // Non-AA hairlines are snapped to pixel centers to make which pixels are hi t deterministic | |
166 bool snapToPixelCenters = !useAA && (0 == width && !fRenderTarget->isUnified Multisampled()); | |
167 | |
168 // TODO we also do this on the paint, do we need to? | |
bsalomon
2015/09/23 13:49:38
I'd just punt on CF. I'm also changing how CF work
joshualitt
2015/09/25 18:17:13
I need to handle the color here either way unfortu
| |
169 SkColor paintColor = paint.getColor(); | |
170 if (fPaint->getColorFilter() && !paint.getShader()) { | |
171 paintColor = paint.getColorFilter()->filterColor(paintColor); | |
172 } | |
173 GrColor color = SkColor2GrColor(paintColor); | |
174 | |
175 RectBatchType batchType = compute_rect_batch_type(useAA, width); | |
robertphillips
2015/09/25 12:48:49
can_fastpath -> attempt_fastpath ?
joshualitt
2015/09/25 18:17:13
Acknowledged.
| |
176 if (can_fastpath(drawTarget, *fPaint, clip, color, viewMatrix, rect, *fStrok eInfo, batchType, | |
177 snapToPixelCenters)) { | |
178 return; | |
179 } | |
180 | |
181 SkAutoTUnref<GrDrawBatch> batch; | |
182 switch (batchType) { | |
183 case kAAStroke_RectBatchType: | |
184 batch.reset(GrRectBatchFactory::CreateAAStroke(color, viewMatrix, re ct, *fStrokeInfo)); | |
185 break; | |
186 case kAAFill_RectBatchType: | |
187 batch.reset(GrRectBatchFactory::CreateAAFill(color, viewMatrix, rect )); | |
188 break; | |
189 case kNonAAFill_RectBatchType: | |
190 batch.reset(GrRectBatchFactory::CreateNonAAFill(color, viewMatrix, r ect, nullptr, | |
191 nullptr)); | |
192 break; | |
193 case kNonAAStroke_RectBatchType: | |
194 batch.reset(GrRectBatchFactory::CreateNonAAStroke(color, viewMatrix, rect, width, | |
195 snapToPixelCenters )); | |
196 break; | |
197 } | |
198 | |
199 GrPaint grPaint; | |
200 if (!SkPaint2GrPaint(fContext, paint, viewMatrix, true, &grPaint)) { | |
201 return; | |
202 } | |
203 | |
204 GrPipelineBuilder pipelineBuilder(grPaint, fRenderTarget, clip); | |
205 | |
206 // Depending on sub-pixel coordinates and the particular GPU, we may lose a corner of | |
207 // hairline rects. We jam all the vertices to pixel centers to avoid this, b ut not when MSAA | |
208 // is enabled because it can cause ugly artifacts. | |
209 pipelineBuilder.setState(GrPipelineBuilder::kSnapVerticesToPixelCenters_Flag , | |
210 snapToPixelCenters); | |
211 drawTarget->drawBatch(pipelineBuilder, batch); | |
robertphillips
2015/09/25 12:48:49
So if we can't snap we just don't draw ?
joshualitt
2015/09/25 18:17:13
If we can't snap, we *do* draw(drawTarget->drawBat
| |
212 if (GrDrawRectSnap::CanSnap(paint)) { | |
213 GrDrawRectSnap* drawRectSnap = batch->getSnapStorage<GrDrawRectSnap>(); | |
214 new (drawRectSnap) GrDrawRectSnap(paint, clip, batchType, snapToPixelCen ters); | |
215 } | |
216 } | |
OLD | NEW |