| 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..22b98208dd2aecfe2bcaed771c61f1014d050808
|
| --- /dev/null
|
| +++ b/src/gpu/draws/GrDrawRect.cpp
|
| @@ -0,0 +1,215 @@
|
| +/*
|
| + * 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"
|
| +
|
| +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()))
|
| + , 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) {
|
| + 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;
|
| + }
|
| +
|
| + 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:
|
| + 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;
|
| +
|
| + 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 (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, fRenderTarget, 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);
|
| + if (GrDrawRectSnap::CanSnap(paint)) {
|
| + batch->setDrawSnap(new GrDrawRectSnap(paint, clip, batchType, snapToPixelCenters));
|
| + }
|
| +}
|
|
|