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.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "gm.h"
|
|
|
|
#if SK_SUPPORT_GPU
|
2016-01-13 18:08:27 +00:00
|
|
|
#include "GrContext.h"
|
2016-03-02 17:26:36 +00:00
|
|
|
#include "GrDrawContextPriv.h"
|
2016-01-13 18:08:27 +00:00
|
|
|
#include "GrPipelineBuilder.h"
|
2015-08-03 21:23:03 +00:00
|
|
|
#include "SkRRect.h"
|
2016-01-13 18:08:27 +00:00
|
|
|
#include "batches/GrDrawBatch.h"
|
|
|
|
#include "batches/GrRectBatchFactory.h"
|
|
|
|
#include "effects/GrRRectEffect.h"
|
2015-08-03 21:23:03 +00:00
|
|
|
|
|
|
|
namespace skiagm {
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
class BigRRectAAEffectGM : public GM {
|
|
|
|
public:
|
2015-12-09 18:17:35 +00:00
|
|
|
BigRRectAAEffectGM(const SkRRect& rrect, const char* name)
|
|
|
|
: fRRect(rrect)
|
|
|
|
, fName(name) {
|
|
|
|
this->setBGColor(sk_tool_utils::color_to_565(SK_ColorBLUE));
|
|
|
|
// 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
|
|
|
|
|
|
|
void onDraw(SkCanvas* canvas) override {
|
2016-04-28 21:32:04 +00:00
|
|
|
GrDrawContext* drawContext = canvas->internal_private_accessTopLayerDrawContext();
|
2016-01-13 18:08:27 +00:00
|
|
|
if (!drawContext) {
|
2016-04-28 21:32:04 +00:00
|
|
|
skiagm::GM::DrawGpuOnlyMessage(canvas);
|
2016-01-13 18:08:27 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-08-03 21:23:03 +00:00
|
|
|
SkPaint paint;
|
|
|
|
|
|
|
|
int y = kPad;
|
|
|
|
int x = kPad;
|
|
|
|
static const GrPrimitiveEdgeType kEdgeTypes[] = {
|
|
|
|
kFillAA_GrProcessorEdgeType,
|
|
|
|
kInverseFillAA_GrProcessorEdgeType,
|
|
|
|
};
|
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) {
|
|
|
|
GrPrimitiveEdgeType 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);
|
|
|
|
|
|
|
|
GrPipelineBuilder pipelineBuilder;
|
|
|
|
pipelineBuilder.setXPFactory(
|
|
|
|
GrPorterDuffXPFactory::Create(SkXfermode::kSrc_Mode))->unref();
|
|
|
|
|
|
|
|
SkRRect rrect = fRRect;
|
|
|
|
rrect.offset(SkIntToScalar(x + kGap), SkIntToScalar(y + kGap));
|
|
|
|
SkAutoTUnref<GrFragmentProcessor> fp(GrRRectEffect::Create(edgeType, rrect));
|
|
|
|
SkASSERT(fp);
|
|
|
|
if (fp) {
|
|
|
|
pipelineBuilder.addCoverageFragmentProcessor(fp);
|
2016-04-28 21:32:04 +00:00
|
|
|
pipelineBuilder.setRenderTarget(drawContext->accessRenderTarget());
|
2015-12-09 18:17:35 +00:00
|
|
|
|
|
|
|
SkRect bounds = testBounds;
|
|
|
|
bounds.offset(SkIntToScalar(x), SkIntToScalar(y));
|
|
|
|
|
2016-01-13 18:08:27 +00:00
|
|
|
SkAutoTUnref<GrDrawBatch> batch(
|
|
|
|
GrRectBatchFactory::CreateNonAAFill(0xff000000, SkMatrix::I(), bounds,
|
|
|
|
nullptr, nullptr));
|
2016-03-02 17:26:36 +00:00
|
|
|
drawContext->drawContextPriv().testingOnly_drawBatch(pipelineBuilder, batch);
|
2015-12-09 18:17:35 +00:00
|
|
|
}
|
|
|
|
canvas->restore();
|
|
|
|
x = x + fTestOffsetX;
|
2015-08-03 21:23:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2015-12-09 18:17:35 +00:00
|
|
|
// pad between test cases
|
|
|
|
static const int kPad = 7;
|
|
|
|
// gap between rect for each case that is rendered and exterior of rrect
|
|
|
|
static const int kGap = 3;
|
|
|
|
|
|
|
|
SkRRect fRRect;
|
|
|
|
int fWidth;
|
|
|
|
int fHeight;
|
|
|
|
int fTestWidth;
|
|
|
|
int fTestHeight;
|
|
|
|
int fTestOffsetX;
|
|
|
|
int fTestOffsetY;
|
|
|
|
const char* fName;
|
2015-08-03 21:23:03 +00:00
|
|
|
typedef GM INHERITED;
|
|
|
|
};
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
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
|
|
|
|
static const int kSize = 700;
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
}
|
|
|
|
#endif
|