Index: src/gpu/draws/GrDrawRect.cpp |
diff --git a/src/gpu/draws/GrDrawRect.cpp b/src/gpu/draws/GrDrawRect.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..64024b7a3e9ae2d71cf6a13daea35c553fb6536b |
--- /dev/null |
+++ b/src/gpu/draws/GrDrawRect.cpp |
@@ -0,0 +1,216 @@ |
+/* |
+ * Copyright 2015 Google Inc. |
+ * |
+ * Use of this source code is governed by a BSD-style license that can be |
+ * found in the LICENSE file. |
+ */ |
+ |
+#include "GrDrawRect.h" |
+ |
+#include "GrContext.h" |
+#include "GrClip.h" |
+#include "GrDrawTarget.h" |
+#include "GrRenderTarget.h" |
+#include "GrStrokeInfo.h" |
+#include "SkColorFilter.h" |
+#include "SkImageFilter.h" |
+#include "SkGr.h" |
+#include "SkMatrix.h" |
+#include "SkMaskFilter.h" |
+#include "SkPaint.h" |
+#include "SkRect.h" |
+#include "SkShader.h" |
+#include "SkXfermode.h" |
+#include "batches/GrRectBatchFactory.h" |
+ |
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.
|
+enum RectBatchType { |
+ kAAStroke_RectBatchType, |
+ kAAFill_RectBatchType, |
+ kNonAAFill_RectBatchType, |
+ kNonAAStroke_RectBatchType, |
+}; |
+ |
+class GrDrawRectSnap : public GrDrawSnap { |
+public: |
+ GrDrawRectSnap(const SkPaint& paint, |
+ const GrClip& clip, |
+ RectBatchType type, |
+ bool snapToPixelCenter) |
+ : fShader(SkSafeRef(paint.getShader())) |
+ , 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.
|
+ , fImageFilter(SkSafeRef(paint.getImageFilter())) |
+ , fColorFilter(SkSafeRef(paint.getColorFilter())) |
+ , fClipGenID(clip.clipType() != GrClip::kClipStack_ClipType ? |
+ -1 : |
+ clip.clipStack()->getTopmostGenID()) |
+ , fType(type) |
+ , fSnapToPixelCenters(snapToPixelCenter) |
+ , fIsDither(paint.isDither()) { |
+ fClassID = GrDrawRect::ClassID(); |
+ } |
+ |
+ bool canBatch(const SkPaint& paint, |
+ const GrClip& clip, |
+ RectBatchType type, |
+ bool snapToPixelCenters) const { |
+ return paint.getShader() == fShader && |
+ paint.getMaskFilter() == fMaskFilter && |
+ paint.getImageFilter() == fImageFilter && |
+ paint.getColorFilter() == fColorFilter && |
+ paint.isDither() == fIsDither && |
+ fClipGenID != -1 && clip.clipType() == GrClip::kClipStack_ClipType && |
+ fClipGenID == clip.clipStack()->getTopmostGenID() && |
+ fType == type && |
+ fSnapToPixelCenters == snapToPixelCenters; |
+ } |
+ |
+ // we only bother fast pathing kSrcOver_Mode, though we could do quite a bit more |
+ 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.
|
+ return SkXfermode::IsMode(paint.getXfermode(), SkXfermode::kSrcOver_Mode); |
+ } |
+ |
+private: |
+ SkAutoTUnref<SkShader> fShader; |
+ SkAutoTUnref<SkMaskFilter> fMaskFilter; |
+ SkAutoTUnref<SkImageFilter> fImageFilter; |
+ SkAutoTUnref<SkColorFilter> fColorFilter; |
+ int32_t fClipGenID; |
+ RectBatchType fType; |
+ bool fSnapToPixelCenters; |
+ bool fIsDither; |
+ |
+ typedef GrDrawSnap INHERITED; |
+}; |
+ |
+inline static RectBatchType compute_rect_batch_type(bool useAA, SkScalar width) { |
+ if (useAA) { |
+ if (width >= 0) { |
+ return kAAStroke_RectBatchType; |
+ } else { |
+ return kAAFill_RectBatchType; |
+ } |
+ } else if (width >= 0) { |
+ return kNonAAStroke_RectBatchType; |
+ } else { |
+ return kNonAAFill_RectBatchType; |
+ } |
+} |
+ |
+inline static bool can_fastpath(GrDrawTarget* drawTarget, |
+ const SkPaint& paint, |
+ const GrClip& clip, |
+ GrColor color, |
+ const SkMatrix& viewMatrix, |
+ const SkRect& rect, |
+ const GrStrokeInfo& strokeInfo, |
+ RectBatchType batchType, |
+ bool snapToPixelCenters) { |
+ GrBatch* lastBatch = drawTarget->lastBatch(); |
+ if (!lastBatch) { |
+ return false; |
+ } |
+ |
robertphillips
2015/09/25 12:48:49
drawSnap -> getLastSnap ?
calling drawSnap here s
joshualitt
2015/09/25 18:17:13
Acknowledged.
|
+ const GrDrawSnap* lastSnap = lastBatch->drawSnap(); |
+ if (!lastSnap) { |
+ return false; |
+ } |
+ |
+ if (lastSnap->classID() != GrDrawRect::ClassID()) { |
+ return false; |
+ } |
+ |
+ const GrDrawRectSnap* lastSnapCast = static_cast<const GrDrawRectSnap*>(lastSnap); |
+ if (lastSnapCast->canBatch(paint, clip, batchType, snapToPixelCenters)) { |
+ switch (batchType) { |
+ 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
|
+ if (GrAAStrokeRectBatch::Append(lastBatch, color, viewMatrix, rect, |
+ strokeInfo)) { |
+ return true; |
+ } |
+ break; |
+ case kAAFill_RectBatchType: |
+ GrAAFillRectBatch::Append(lastBatch, color, viewMatrix, rect); |
+ return true; |
+ case kNonAAFill_RectBatchType: |
+ if (GrNonAAFillRectBatch::Append(lastBatch, color, viewMatrix, rect, |
+ nullptr, nullptr)) { |
+ return true; |
+ } |
+ break; |
+ case kNonAAStroke_RectBatchType: |
+ // GrNonAAStrokeRectBatch doesn't batch yet |
+ break; |
+ } |
+ } |
+ |
+ return false; |
+} |
+ |
+void GrDrawRect::execute(GrDrawTarget* drawTarget) const { |
+ const SkPaint& paint = *fPaint; |
+ const GrClip& clip = *fClip; |
+ const SkMatrix& viewMatrix = *fViewMatrix; |
+ const SkRect& rect = *fRect; |
+ |
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
|
+ SkScalar width = nullptr == fStrokeInfo ? -1 : fStrokeInfo->getWidth(); |
+ |
+ bool needAA = fPaint->isAntiAlias() && !fRenderTarget->isUnifiedMultisampled(); |
+ |
+ // The fill path can handle rotation but not skew |
+ // The stroke path needs the rect to remain axis aligned (no rotation or skew) |
+ // None of our AA draw rect calls can handle perspective yet |
+ bool canApplyAA = width >= 0 ? viewMatrix.rectStaysRect() : viewMatrix.preservesRightAngles(); |
+ bool useAA = needAA && canApplyAA; |
+ |
+ // Non-AA hairlines are snapped to pixel centers to make which pixels are hit deterministic |
+ bool snapToPixelCenters = !useAA && (0 == width && !fRenderTarget->isUnifiedMultisampled()); |
+ |
+ // 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
|
+ SkColor paintColor = paint.getColor(); |
+ if (fPaint->getColorFilter() && !paint.getShader()) { |
+ paintColor = paint.getColorFilter()->filterColor(paintColor); |
+ } |
+ GrColor color = SkColor2GrColor(paintColor); |
+ |
+ 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.
|
+ if (can_fastpath(drawTarget, *fPaint, clip, color, viewMatrix, rect, *fStrokeInfo, batchType, |
+ snapToPixelCenters)) { |
+ return; |
+ } |
+ |
+ SkAutoTUnref<GrDrawBatch> batch; |
+ switch (batchType) { |
+ case kAAStroke_RectBatchType: |
+ batch.reset(GrRectBatchFactory::CreateAAStroke(color, viewMatrix, rect, *fStrokeInfo)); |
+ break; |
+ case kAAFill_RectBatchType: |
+ batch.reset(GrRectBatchFactory::CreateAAFill(color, viewMatrix, rect)); |
+ break; |
+ case kNonAAFill_RectBatchType: |
+ batch.reset(GrRectBatchFactory::CreateNonAAFill(color, viewMatrix, rect, nullptr, |
+ nullptr)); |
+ break; |
+ case kNonAAStroke_RectBatchType: |
+ batch.reset(GrRectBatchFactory::CreateNonAAStroke(color, viewMatrix, rect, width, |
+ snapToPixelCenters)); |
+ break; |
+ } |
+ |
+ GrPaint grPaint; |
+ if (!SkPaint2GrPaint(fContext, paint, viewMatrix, true, &grPaint)) { |
+ return; |
+ } |
+ |
+ GrPipelineBuilder pipelineBuilder(grPaint, fRenderTarget, clip); |
+ |
+ // Depending on sub-pixel coordinates and the particular GPU, we may lose a corner of |
+ // hairline rects. We jam all the vertices to pixel centers to avoid this, but not when MSAA |
+ // is enabled because it can cause ugly artifacts. |
+ pipelineBuilder.setState(GrPipelineBuilder::kSnapVerticesToPixelCenters_Flag, |
+ snapToPixelCenters); |
+ 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
|
+ if (GrDrawRectSnap::CanSnap(paint)) { |
+ GrDrawRectSnap* drawRectSnap = batch->getSnapStorage<GrDrawRectSnap>(); |
+ new (drawRectSnap) GrDrawRectSnap(paint, clip, batchType, snapToPixelCenters); |
+ } |
+} |