123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310 |
- /*
- * Copyright 2014 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
- // This test only works with the GPU backend.
- #include "gm/gm.h"
- #include "include/core/SkBlendMode.h"
- #include "include/core/SkCanvas.h"
- #include "include/core/SkMatrix.h"
- #include "include/core/SkPaint.h"
- #include "include/core/SkPath.h"
- #include "include/core/SkPoint.h"
- #include "include/core/SkRect.h"
- #include "include/core/SkRefCnt.h"
- #include "include/core/SkScalar.h"
- #include "include/core/SkSize.h"
- #include "include/core/SkString.h"
- #include "include/core/SkTypes.h"
- #include "include/gpu/GrContext.h"
- #include "include/private/GrRecordingContext.h"
- #include "include/private/GrSharedEnums.h"
- #include "include/private/GrTypesPriv.h"
- #include "include/private/SkColorData.h"
- #include "src/core/SkPointPriv.h"
- #include "src/core/SkTLList.h"
- #include "src/gpu/GrCaps.h"
- #include "src/gpu/GrDefaultGeoProcFactory.h"
- #include "src/gpu/GrFragmentProcessor.h"
- #include "src/gpu/GrGeometryProcessor.h"
- #include "src/gpu/GrMemoryPool.h"
- #include "src/gpu/GrOpFlushState.h"
- #include "src/gpu/GrPaint.h"
- #include "src/gpu/GrProcessorAnalysis.h"
- #include "src/gpu/GrProcessorSet.h"
- #include "src/gpu/GrRecordingContextPriv.h"
- #include "src/gpu/GrRenderTargetContext.h"
- #include "src/gpu/GrRenderTargetContextPriv.h"
- #include "src/gpu/GrUserStencilSettings.h"
- #include "src/gpu/effects/GrConvexPolyEffect.h"
- #include "src/gpu/effects/GrPorterDuffXferProcessor.h"
- #include "src/gpu/ops/GrDrawOp.h"
- #include "src/gpu/ops/GrMeshDrawOp.h"
- #include "src/gpu/ops/GrOp.h"
- #include <memory>
- #include <utility>
- class GrAppliedClip;
- /** outset rendered rect to visualize anti-aliased poly edges */
- static SkRect outset(const SkRect& unsorted) {
- SkRect r = unsorted;
- r.outset(5.f, 5.f);
- return r;
- }
- /** sorts a rect */
- static SkRect sorted_rect(const SkRect& unsorted) {
- SkRect r = unsorted;
- r.sort();
- return r;
- }
- namespace skiagm {
- class PolyBoundsOp : public GrMeshDrawOp {
- public:
- DEFINE_OP_CLASS_ID
- static std::unique_ptr<GrDrawOp> Make(GrRecordingContext* context,
- GrPaint&& paint,
- const SkRect& rect) {
- GrOpMemoryPool* pool = context->priv().opMemoryPool();
- return pool->allocate<PolyBoundsOp>(std::move(paint), rect);
- }
- const char* name() const override { return "PolyBoundsOp"; }
- void visitProxies(const VisitProxyFunc& func) const override {
- fProcessors.visitProxies(func);
- }
- FixedFunctionFlags fixedFunctionFlags() const override { return FixedFunctionFlags::kNone; }
- GrProcessorSet::Analysis finalize(
- const GrCaps& caps, const GrAppliedClip* clip, bool hasMixedSampledCoverage,
- GrClampType clampType) override {
- return fProcessors.finalize(
- fColor, GrProcessorAnalysisCoverage::kNone, clip, &GrUserStencilSettings::kUnused,
- hasMixedSampledCoverage, caps, clampType, &fColor);
- }
- private:
- friend class ::GrOpMemoryPool; // for ctor
- PolyBoundsOp(GrPaint&& paint, const SkRect& rect)
- : INHERITED(ClassID())
- , fColor(paint.getColor4f())
- , fProcessors(std::move(paint))
- , fRect(outset(rect)) {
- this->setBounds(sorted_rect(fRect), HasAABloat::kNo, IsZeroArea::kNo);
- }
- void onPrepareDraws(Target* target) override {
- using namespace GrDefaultGeoProcFactory;
- Color color(fColor);
- sk_sp<GrGeometryProcessor> gp(GrDefaultGeoProcFactory::Make(
- target->caps().shaderCaps(),
- color,
- Coverage::kSolid_Type,
- LocalCoords::kUnused_Type,
- SkMatrix::I()));
- SkASSERT(gp->vertexStride() == sizeof(SkPoint));
- QuadHelper helper(target, sizeof(SkPoint), 1);
- SkPoint* verts = reinterpret_cast<SkPoint*>(helper.vertices());
- if (!verts) {
- return;
- }
- SkPointPriv::SetRectTriStrip(verts, fRect, sizeof(SkPoint));
- helper.recordDraw(target, std::move(gp));
- }
- void onExecute(GrOpFlushState* flushState, const SkRect& chainBounds) override {
- flushState->executeDrawsAndUploadsForMeshDrawOp(this, chainBounds, std::move(fProcessors));
- }
- SkPMColor4f fColor;
- GrProcessorSet fProcessors;
- SkRect fRect;
- typedef GrMeshDrawOp INHERITED;
- };
- /**
- * This GM directly exercises a GrProcessor that draws convex polygons.
- */
- class ConvexPolyEffect : public GpuGM {
- public:
- ConvexPolyEffect() {
- this->setBGColor(0xFFFFFFFF);
- }
- protected:
- SkString onShortName() override {
- return SkString("convex_poly_effect");
- }
- SkISize onISize() override {
- return SkISize::Make(720, 800);
- }
- void onOnceBeforeDraw() override {
- SkPath tri;
- tri.moveTo(5.f, 5.f);
- tri.lineTo(100.f, 20.f);
- tri.lineTo(15.f, 100.f);
- fPaths.addToTail(tri);
- fPaths.addToTail(SkPath())->reverseAddPath(tri);
- tri.close();
- fPaths.addToTail(tri);
- SkPath ngon;
- constexpr SkScalar kRadius = 50.f;
- const SkPoint center = { kRadius, kRadius };
- for (int i = 0; i < GrConvexPolyEffect::kMaxEdges; ++i) {
- SkScalar angle = 2 * SK_ScalarPI * i / GrConvexPolyEffect::kMaxEdges;
- SkPoint point = { SkScalarCos(angle), SkScalarSin(angle) };
- point.scale(kRadius);
- point = center + point;
- if (0 == i) {
- ngon.moveTo(point);
- } else {
- ngon.lineTo(point);
- }
- }
- fPaths.addToTail(ngon);
- SkMatrix scaleM;
- scaleM.setScale(1.1f, 0.4f);
- ngon.transform(scaleM);
- fPaths.addToTail(ngon);
- SkPath linePath;
- linePath.moveTo(5.f, 5.f);
- linePath.lineTo(6.f, 6.f);
- fPaths.addToTail(linePath);
- // integer edges
- fRects.addToTail(SkRect::MakeLTRB(5.f, 1.f, 30.f, 25.f));
- // half-integer edges
- fRects.addToTail(SkRect::MakeLTRB(5.5f, 0.5f, 29.5f, 24.5f));
- // vertically/horizontally thin rects that cover pixel centers
- fRects.addToTail(SkRect::MakeLTRB(5.25f, 0.5f, 5.75f, 24.5f));
- fRects.addToTail(SkRect::MakeLTRB(5.5f, 0.5f, 29.5f, 0.75f));
- // vertically/horizontally thin rects that don't cover pixel centers
- fRects.addToTail(SkRect::MakeLTRB(5.55f, 0.5f, 5.75f, 24.5f));
- fRects.addToTail(SkRect::MakeLTRB(5.5f, .05f, 29.5f, .25f));
- // small in x and y
- fRects.addToTail(SkRect::MakeLTRB(5.05f, .55f, 5.45f, .85f));
- // inverted in x and y
- fRects.addToTail(SkRect::MakeLTRB(100.f, 50.5f, 5.f, 0.5f));
- }
- void onDraw(GrContext* context, GrRenderTargetContext* renderTargetContext,
- SkCanvas* canvas) override {
- SkScalar y = 0;
- constexpr SkScalar kDX = 12.f;
- for (PathList::Iter iter(fPaths, PathList::Iter::kHead_IterStart);
- iter.get();
- iter.next()) {
- const SkPath* path = iter.get();
- SkScalar x = 0;
- for (int et = 0; et < kGrClipEdgeTypeCnt; ++et) {
- const SkMatrix m = SkMatrix::MakeTrans(x, y);
- SkPath p;
- path->transform(m, &p);
- GrClipEdgeType edgeType = (GrClipEdgeType) et;
- std::unique_ptr<GrFragmentProcessor> fp(GrConvexPolyEffect::Make(edgeType, p));
- if (!fp) {
- continue;
- }
- GrPaint grPaint;
- grPaint.setColor4f({ 0, 0, 0, 1.f });
- grPaint.setXPFactory(GrPorterDuffXPFactory::Get(SkBlendMode::kSrc));
- grPaint.addCoverageFragmentProcessor(std::move(fp));
- std::unique_ptr<GrDrawOp> op =
- PolyBoundsOp::Make(context, std::move(grPaint), p.getBounds());
- renderTargetContext->priv().testingOnly_addDrawOp(std::move(op));
- x += SkScalarCeilToScalar(path->getBounds().width() + kDX);
- }
- // Draw AA and non AA paths using normal API for reference.
- canvas->save();
- canvas->translate(x, y);
- SkPaint paint;
- canvas->drawPath(*path, paint);
- canvas->translate(path->getBounds().width() + 10.f, 0);
- paint.setAntiAlias(true);
- canvas->drawPath(*path, paint);
- canvas->restore();
- y += SkScalarCeilToScalar(path->getBounds().height() + 20.f);
- }
- for (RectList::Iter iter(fRects, RectList::Iter::kHead_IterStart);
- iter.get();
- iter.next()) {
- SkScalar x = 0;
- for (int et = 0; et < kGrClipEdgeTypeCnt; ++et) {
- SkRect rect = *iter.get();
- rect.offset(x, y);
- GrClipEdgeType edgeType = (GrClipEdgeType) et;
- std::unique_ptr<GrFragmentProcessor> fp(GrConvexPolyEffect::Make(edgeType, rect));
- if (!fp) {
- continue;
- }
- GrPaint grPaint;
- grPaint.setColor4f({ 0, 0, 0, 1.f });
- grPaint.setXPFactory(GrPorterDuffXPFactory::Get(SkBlendMode::kSrc));
- grPaint.addCoverageFragmentProcessor(std::move(fp));
- std::unique_ptr<GrDrawOp> op = PolyBoundsOp::Make(context, std::move(grPaint),
- rect);
- renderTargetContext->priv().testingOnly_addDrawOp(std::move(op));
- x += SkScalarCeilToScalar(rect.width() + kDX);
- }
- // Draw rect without and with AA using normal API for reference
- canvas->save();
- canvas->translate(x, y);
- SkPaint paint;
- canvas->drawRect(*iter.get(), paint);
- x += SkScalarCeilToScalar(iter.get()->width() + kDX);
- paint.setAntiAlias(true);
- canvas->drawRect(*iter.get(), paint);
- canvas->restore();
- y += SkScalarCeilToScalar(iter.get()->height() + 20.f);
- }
- }
- private:
- typedef SkTLList<SkPath, 1> PathList;
- typedef SkTLList<SkRect, 1> RectList;
- PathList fPaths;
- RectList fRects;
- typedef GM INHERITED;
- };
- DEF_GM(return new ConvexPolyEffect;)
- }
|