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 |
| 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())) |
| 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) { |
| 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 |
| 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: |
| 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 |
| 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? |
| 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); |
| 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, fRenderTarget, paint, viewMatrix, true, &grPa
int)) { |
| 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); |
| 212 if (GrDrawRectSnap::CanSnap(paint)) { |
| 213 batch->setDrawSnap(new GrDrawRectSnap(paint, clip, batchType, snapToPixe
lCenters)); |
| 214 } |
| 215 } |
OLD | NEW |