2015-08-03 21:23:03 +00:00
|
|
|
/*
|
|
|
|
* Copyright 2015 Google Inc.
|
|
|
|
*
|
|
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
|
|
* found in the LICENSE file.
|
|
|
|
*/
|
|
|
|
|
2019-04-23 17:05:21 +00:00
|
|
|
#include "gm/gm.h"
|
2019-05-01 14:59:30 +00:00
|
|
|
#include "include/core/SkBlendMode.h"
|
|
|
|
#include "include/core/SkCanvas.h"
|
|
|
|
#include "include/core/SkColor.h"
|
|
|
|
#include "include/core/SkMatrix.h"
|
|
|
|
#include "include/core/SkPaint.h"
|
2019-04-23 17:05:21 +00:00
|
|
|
#include "include/core/SkRRect.h"
|
2019-05-01 14:59:30 +00:00
|
|
|
#include "include/core/SkRect.h"
|
|
|
|
#include "include/core/SkScalar.h"
|
|
|
|
#include "include/core/SkSize.h"
|
|
|
|
#include "include/core/SkString.h"
|
|
|
|
#include "include/core/SkTypes.h"
|
|
|
|
#include "include/private/GrTypesPriv.h"
|
2021-07-21 19:39:51 +00:00
|
|
|
#include "src/core/SkCanvasPriv.h"
|
2019-04-23 17:05:21 +00:00
|
|
|
#include "src/gpu/GrCaps.h"
|
2019-05-01 14:59:30 +00:00
|
|
|
#include "src/gpu/GrFragmentProcessor.h"
|
|
|
|
#include "src/gpu/GrPaint.h"
|
2020-12-09 21:37:04 +00:00
|
|
|
#include "src/gpu/GrSurfaceDrawContext.h"
|
2019-05-01 14:59:30 +00:00
|
|
|
#include "src/gpu/effects/GrPorterDuffXferProcessor.h"
|
2019-04-23 17:05:21 +00:00
|
|
|
#include "src/gpu/effects/GrRRectEffect.h"
|
|
|
|
#include "src/gpu/ops/GrDrawOp.h"
|
|
|
|
#include "src/gpu/ops/GrFillRectOp.h"
|
|
|
|
#include "tools/ToolUtils.h"
|
2015-08-03 21:23:03 +00:00
|
|
|
|
2019-05-01 14:59:30 +00:00
|
|
|
#include <memory>
|
|
|
|
#include <utility>
|
|
|
|
|
2015-08-03 21:23:03 +00:00
|
|
|
namespace skiagm {
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2019-02-07 22:23:36 +00:00
|
|
|
class BigRRectAAEffectGM : public GpuGM {
|
2015-08-03 21:23:03 +00:00
|
|
|
public:
|
2015-12-09 18:17:35 +00:00
|
|
|
BigRRectAAEffectGM(const SkRRect& rrect, const char* name)
|
|
|
|
: fRRect(rrect)
|
|
|
|
, fName(name) {
|
2019-03-20 16:12:10 +00:00
|
|
|
this->setBGColor(ToolUtils::color_to_565(SK_ColorBLUE));
|
2015-12-09 18:17:35 +00:00
|
|
|
// Each test case draws the rrect with gaps around it.
|
|
|
|
fTestWidth = SkScalarCeilToInt(rrect.width()) + 2 * kGap;
|
|
|
|
fTestHeight = SkScalarCeilToInt(rrect.height()) + 2 * kGap;
|
|
|
|
|
|
|
|
// Add a pad between test cases.
|
|
|
|
fTestOffsetX = fTestWidth + kPad;
|
|
|
|
fTestOffsetY = fTestHeight + kPad;
|
|
|
|
|
|
|
|
// We draw two tests in x (fill and inv-fill) and pad around
|
|
|
|
// all four sides of the image.
|
|
|
|
fWidth = 2 * fTestOffsetX + kPad;
|
|
|
|
fHeight = fTestOffsetY + kPad;
|
2015-08-03 21:23:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
protected:
|
|
|
|
SkString onShortName() override {
|
2015-12-09 18:17:35 +00:00
|
|
|
SkString name;
|
|
|
|
name.printf("big_rrect_%s_aa_effect", fName);
|
|
|
|
return name;
|
2015-08-03 21:23:03 +00:00
|
|
|
}
|
|
|
|
|
2015-12-09 18:17:35 +00:00
|
|
|
SkISize onISize() override { return SkISize::Make(fWidth, fHeight); }
|
2015-08-03 21:23:03 +00:00
|
|
|
|
2021-07-21 19:39:51 +00:00
|
|
|
DrawResult onDraw(GrRecordingContext* rContext, SkCanvas* canvas, SkString* errorMsg) override {
|
2015-08-03 21:23:03 +00:00
|
|
|
SkPaint paint;
|
|
|
|
|
2021-07-21 19:39:51 +00:00
|
|
|
auto sdc = SkCanvasPriv::TopDeviceSurfaceDrawContext(canvas);
|
|
|
|
if (!sdc) {
|
|
|
|
*errorMsg = kErrorMsg_DrawSkippedGpuOnly;
|
|
|
|
return DrawResult::kSkip;
|
|
|
|
}
|
|
|
|
|
2015-08-03 21:23:03 +00:00
|
|
|
int y = kPad;
|
|
|
|
int x = kPad;
|
2017-11-09 19:51:17 +00:00
|
|
|
constexpr GrClipEdgeType kEdgeTypes[] = {
|
2017-11-10 16:58:19 +00:00
|
|
|
GrClipEdgeType::kFillAA,
|
|
|
|
GrClipEdgeType::kInverseFillAA,
|
2015-08-03 21:23:03 +00:00
|
|
|
};
|
2015-12-09 18:17:35 +00:00
|
|
|
SkRect testBounds = SkRect::MakeIWH(fTestWidth, fTestHeight);
|
2015-08-03 21:23:03 +00:00
|
|
|
for (size_t et = 0; et < SK_ARRAY_COUNT(kEdgeTypes); ++et) {
|
2017-11-09 19:51:17 +00:00
|
|
|
GrClipEdgeType edgeType = kEdgeTypes[et];
|
2015-12-09 18:17:35 +00:00
|
|
|
canvas->save();
|
2016-03-29 16:03:52 +00:00
|
|
|
canvas->translate(SkIntToScalar(x), SkIntToScalar(y));
|
2015-12-09 18:17:35 +00:00
|
|
|
|
|
|
|
// Draw a background for the test case
|
|
|
|
SkPaint paint;
|
|
|
|
paint.setColor(SK_ColorWHITE);
|
|
|
|
canvas->drawRect(testBounds, paint);
|
|
|
|
|
|
|
|
SkRRect rrect = fRRect;
|
|
|
|
rrect.offset(SkIntToScalar(x + kGap), SkIntToScalar(y + kGap));
|
2021-07-21 19:39:51 +00:00
|
|
|
const auto& caps = *rContext->priv().caps()->shaderCaps();
|
2020-06-17 17:53:37 +00:00
|
|
|
auto [success, fp] = GrRRectEffect::Make(/*inputFP=*/nullptr, edgeType, rrect,
|
|
|
|
caps);
|
|
|
|
SkASSERT(success);
|
|
|
|
if (success) {
|
|
|
|
SkASSERT(fp);
|
2017-01-11 18:42:54 +00:00
|
|
|
GrPaint grPaint;
|
2018-10-16 19:19:28 +00:00
|
|
|
grPaint.setColor4f({ 0, 0, 0, 1.f });
|
2017-01-11 18:42:54 +00:00
|
|
|
grPaint.setXPFactory(GrPorterDuffXPFactory::Get(SkBlendMode::kSrc));
|
2020-07-21 18:39:40 +00:00
|
|
|
grPaint.setCoverageFragmentProcessor(std::move(fp));
|
2015-12-09 18:17:35 +00:00
|
|
|
|
|
|
|
SkRect bounds = testBounds;
|
|
|
|
bounds.offset(SkIntToScalar(x), SkIntToScalar(y));
|
|
|
|
|
2021-07-21 19:39:51 +00:00
|
|
|
sdc->addDrawOp(GrFillRectOp::MakeNonAARect(
|
|
|
|
rContext, std::move(grPaint), SkMatrix::I(), bounds));
|
2015-12-09 18:17:35 +00:00
|
|
|
}
|
|
|
|
canvas->restore();
|
|
|
|
x = x + fTestOffsetX;
|
2015-08-03 21:23:03 +00:00
|
|
|
}
|
2021-07-21 19:39:51 +00:00
|
|
|
|
|
|
|
return DrawResult::kOk;
|
2015-08-03 21:23:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2015-12-09 18:17:35 +00:00
|
|
|
// pad between test cases
|
2016-09-01 18:24:54 +00:00
|
|
|
static constexpr int kPad = 7;
|
2015-12-09 18:17:35 +00:00
|
|
|
// gap between rect for each case that is rendered and exterior of rrect
|
2016-09-01 18:24:54 +00:00
|
|
|
static constexpr int kGap = 3;
|
2015-12-09 18:17:35 +00:00
|
|
|
|
|
|
|
SkRRect fRRect;
|
|
|
|
int fWidth;
|
|
|
|
int fHeight;
|
|
|
|
int fTestWidth;
|
|
|
|
int fTestHeight;
|
|
|
|
int fTestOffsetX;
|
|
|
|
int fTestOffsetY;
|
|
|
|
const char* fName;
|
2020-09-03 02:42:33 +00:00
|
|
|
using INHERITED = GM;
|
2015-08-03 21:23:03 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
2015-12-09 18:17:35 +00:00
|
|
|
// This value is motivated by bug chromium:477684. It has to be large to cause overflow in
|
|
|
|
// the shader
|
2016-09-01 18:24:54 +00:00
|
|
|
constexpr int kSize = 700;
|
2015-12-09 18:17:35 +00:00
|
|
|
|
|
|
|
DEF_GM( return new BigRRectAAEffectGM (SkRRect::MakeRect(SkRect::MakeIWH(kSize, kSize)), "rect"); )
|
|
|
|
DEF_GM( return new BigRRectAAEffectGM (SkRRect::MakeOval(SkRect::MakeIWH(kSize, kSize)), "circle"); )
|
|
|
|
DEF_GM( return new BigRRectAAEffectGM (SkRRect::MakeOval(SkRect::MakeIWH(kSize - 1, kSize - 10)), "ellipse"); )
|
|
|
|
// The next two have small linear segments between the corners
|
|
|
|
DEF_GM( return new BigRRectAAEffectGM (SkRRect::MakeRectXY(SkRect::MakeIWH(kSize - 1, kSize - 10), kSize/2.f - 10.f, kSize/2.f - 10.f), "circular_corner"); )
|
|
|
|
DEF_GM( return new BigRRectAAEffectGM (SkRRect::MakeRectXY(SkRect::MakeIWH(kSize - 1, kSize - 10), kSize/2.f - 10.f, kSize/2.f - 15.f), "elliptical_corner"); )
|
2015-08-03 21:23:03 +00:00
|
|
|
|
2020-08-06 18:11:56 +00:00
|
|
|
} // namespace skiagm
|