Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(292)

Unified Diff: src/gpu/draws/GrDrawRect.cpp

Issue 1355353002: Create GrDraw and start fast pathing src over rects (Closed) Base URL: https://skia.googlesource.com/skia.git@strokerect2
Patch Set: tweaks Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/gpu/draws/GrDrawRect.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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..74d1956d493effeaad542fb582295b0fb1c59728
--- /dev/null
+++ b/src/gpu/draws/GrDrawRect.cpp
@@ -0,0 +1,245 @@
+/*
+ * 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 "GrDrawContext.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"
+
+enum RectBatchType {
+ kAAStroke_RectBatchType,
+ kAAFill_RectBatchType,
+ kNonAAFill_RectBatchType,
+ kNonAAStroke_RectBatchType,
+};
+
+/*
+ * GrDrawRectSnap rules:
+ * 1) We don't handle mask filters, because they can be multiple draws, though we could handle
+ * a subset
+ * 2) We don't handle image filters for the same reason
+ * 3) We don't handle color filters, because they aren't very common, and they don't always multiply
+ * As a result we can end up doing optimizations which can't be trivially reconstructed in the
+ * fast path
+ * 5) We only handle shaders which have the same pointer, though we can and should do a little bit
+ * more analysis here
+ * TODO compute short shader keys for the cases we care about
+ * 6) We don't bother looking at the clip, aside from wide open or same clip generation
+ * 7) We only handle src over, we might be able to handle other blend modes, but we have to be
+ * careful about not breaking things, especially re: optimizations
+ *
+ * TODO don't try to snap if we got an override color
+ */
+class GrDrawRectSnap : public GrDrawSnap {
+public:
+ GrDrawRectSnap(const SkPaint& paint,
+ const GrClip& clip,
+ RectBatchType type,
+ bool snapToPixelCenter)
+ : fShader(SkSafeRef(paint.getShader()))
+ , fType(type)
+ , fClipType(clip.clipType())
+ , fClipGenID(fClipType == GrClip::kClipStack_ClipType ?
+ clip.clipStack()->getTopmostGenID() :
+ -1)
+ , fSnapToPixelCenters(snapToPixelCenter)
+ , fIsDither(paint.isDither()) {
+ fClassID = GrDrawRect::ClassID();
+ }
+
+ bool canBatch(const SkPaint& paint,
+ const GrClip& clip,
+ RectBatchType type,
+ bool snapToPixelCenters) const {
+ return fType == type &&
+ !paint.getXfermode() &&
+ !paint.getImageFilter() &&
+ !paint.getMaskFilter() &&
+ !paint.getColorFilter() &&
+ paint.getShader() == fShader &&
+ paint.isDither() == fIsDither &&
+ fClipType == clip.clipType() &&
+ (fClipType == GrClip::kWideOpen_ClipType ||
+ (fClipType == GrClip::kClipStack_ClipType &&
+ fClipGenID == clip.clipStack()->getTopmostGenID())) &&
+ fSnapToPixelCenters == snapToPixelCenters;
+ }
+
+ // we only bother fast pathing kSrcOver_Mode, though we could do quite a bit more
+ static bool CanSnap(const SkPaint& paint) {
+ return !paint.getXfermode() &&
+ !paint.getColorFilter() &&
+ !paint.getMaskFilter() &&
+ !paint.getImageFilter();
+ }
+
+private:
+ SkAutoTUnref<SkShader> fShader;
+ RectBatchType fType;
+ GrClip::ClipType fClipType;
+ int32_t fClipGenID;
+ 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 attempt_fastpath(GrDrawContext* drawContext,
+ const SkPaint& paint,
+ const GrClip& clip,
+ GrColor color,
+ const SkMatrix& viewMatrix,
+ const SkRect& rect,
+ const GrStrokeInfo& strokeInfo,
+ RectBatchType batchType,
+ bool snapToPixelCenters,
+ const GrRenderTarget* rt) {
+ GrBatch* lastBatch = drawContext->lastBatch();
+ if (!lastBatch) {
+ return false;
+ }
+
+ const GrDrawSnap* lastSnap = lastBatch->getDrawSnap();
+ if (!lastSnap) {
+ return false;
+ }
+
+ if (lastSnap->classID() != GrDrawRect::ClassID()) {
+ return false;
+ }
+
+ // TODO remove this and the RT arg when we have multidrawbuffer
+ // This downcast is safe because we only have drawbatches
+ const GrDrawBatch* drawBatch = reinterpret_cast<const GrDrawBatch*>(lastBatch);
+ if (rt != drawBatch->pipeline()->getRenderTarget()) {
+ return false;
+ }
+
+ const GrDrawRectSnap* lastSnapCast = static_cast<const GrDrawRectSnap*>(lastSnap);
+ if (lastSnapCast->canBatch(paint, clip, batchType, snapToPixelCenters)) {
+ switch (batchType) {
+ case kAAStroke_RectBatchType:
+ if (GrAAStrokeRectBatch::Append(lastBatch, color, viewMatrix, rect,
+ strokeInfo)) {
+ return true;
+ }
+ break;
+ case kAAFill_RectBatchType:
+ if (GrAAFillRectBatch::Append(lastBatch, color, viewMatrix, rect)) {
+ return true;
+ }
+ break;
+ 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(GrDrawContext* drawContext) const {
+ const SkPaint& paint = *fPaint;
+ const GrClip& clip = *fClip;
+ const SkMatrix& viewMatrix = *fViewMatrix;
+ const SkRect& rect = *fRect;
+
+ 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?
+ 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);
+ if (attempt_fastpath(drawContext, *fPaint, clip, color, viewMatrix, rect, *fStrokeInfo,
+ batchType, snapToPixelCenters, fRenderTarget)) {
+ 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);
+ drawContext->drawBatch(pipelineBuilder, batch);
+ if (GrDrawRectSnap::CanSnap(paint)) {
+ batch->initSnapStorage<GrDrawRectSnap>(paint, clip, batchType, snapToPixelCenters);
+ }
+}
« no previous file with comments | « src/gpu/draws/GrDrawRect.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698