bigrrectaaeffect.cpp revision 4a4f14ba3f93cc6bb9146be0f029a9badb1b95d9
1c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon/*
2c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon * Copyright 2015 Google Inc.
3c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon *
4c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon * Use of this source code is governed by a BSD-style license that can be
5c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon * found in the LICENSE file.
6c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon */
7c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon
8c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon#include "gm.h"
9c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon#if SK_SUPPORT_GPU
10c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon#include "GrTest.h"
11c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon#include "effects/GrRRectEffect.h"
12c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon#include "SkDevice.h"
13c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon#include "SkRRect.h"
14c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon
15c41f4d60559b0891353f8028d521b52e7a36d5dabsalomonnamespace skiagm {
16c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon
17c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon///////////////////////////////////////////////////////////////////////////////
18c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon
19c41f4d60559b0891353f8028d521b52e7a36d5dabsalomonclass BigRRectAAEffectGM : public GM {
20c41f4d60559b0891353f8028d521b52e7a36d5dabsalomonpublic:
214a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon    BigRRectAAEffectGM(const SkRRect& rrect, const char* name)
224a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon        : fRRect(rrect)
234a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon        , fName(name) {
244a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon        this->setBGColor(sk_tool_utils::color_to_565(SK_ColorBLUE));
254a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon        // Each test case draws the rrect with gaps around it.
264a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon        fTestWidth = SkScalarCeilToInt(rrect.width()) + 2 * kGap;
274a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon        fTestHeight = SkScalarCeilToInt(rrect.height()) + 2 * kGap;
284a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon
294a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon        // Add a pad between test cases.
304a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon        fTestOffsetX = fTestWidth + kPad;
314a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon        fTestOffsetY = fTestHeight + kPad;
324a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon
334a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon        // We draw two tests in x (fill and inv-fill) and pad around
344a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon        // all four sides of the image.
354a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon        fWidth = 2 * fTestOffsetX + kPad;
364a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon        fHeight = fTestOffsetY + kPad;
37c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon    }
38c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon
39c41f4d60559b0891353f8028d521b52e7a36d5dabsalomonprotected:
40c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon    SkString onShortName() override {
414a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon        SkString name;
424a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon        name.printf("big_rrect_%s_aa_effect", fName);
434a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon        return name;
44c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon    }
45c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon
464a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon    SkISize onISize() override { return SkISize::Make(fWidth, fHeight); }
47c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon
48c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon    void onDraw(SkCanvas* canvas) override {
49c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon        GrRenderTarget* rt = canvas->internal_private_accessTopLayerRenderTarget();
5096fcdcc219d2a0d3579719b84b28bede76efba64halcanary        GrContext* context = rt ? rt->getContext() : nullptr;
51c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon        if (!context) {
522a24338c777462e04a2b26295f9c034155ee8f3ehalcanary            skiagm::GM::DrawGpuOnlyMessage(canvas);
53c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon            return;
54c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon        }
55c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon
56c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon        SkPaint paint;
57c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon
58c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon        int y = kPad;
59c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon        int x = kPad;
60c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon        static const GrPrimitiveEdgeType kEdgeTypes[] = {
61c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon            kFillAA_GrProcessorEdgeType,
62c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon            kInverseFillAA_GrProcessorEdgeType,
63c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon        };
644a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon        SkRect testBounds = SkRect::MakeIWH(fTestWidth, fTestHeight);
65c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon        for (size_t et = 0; et < SK_ARRAY_COUNT(kEdgeTypes); ++et) {
66c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon            GrPrimitiveEdgeType edgeType = kEdgeTypes[et];
674a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon            canvas->save();
684a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon                canvas->translate(SkIntToScalar(x), SkIntToScalar(y));
694a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon
704a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon                // Draw a background for the test case
714a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon                SkPaint paint;
724a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon                paint.setColor(SK_ColorWHITE);
734a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon                canvas->drawRect(testBounds, paint);
744a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon
754a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon                GrTestTarget tt;
764a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon                context->getTestTarget(&tt, rt);
774a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon                if (!tt.target()) {
784a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon                    SkDEBUGFAIL("Couldn't get Gr test target.");
794a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon                    return;
80c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon                }
814a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon                GrPipelineBuilder pipelineBuilder;
824a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon                pipelineBuilder.setXPFactory(
834a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon                    GrPorterDuffXPFactory::Create(SkXfermode::kSrc_Mode))->unref();
844a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon
854a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon                SkRRect rrect = fRRect;
864a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon                rrect.offset(SkIntToScalar(x + kGap), SkIntToScalar(y + kGap));
874a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon                SkAutoTUnref<GrFragmentProcessor> fp(GrRRectEffect::Create(edgeType, rrect));
884a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon                SkASSERT(fp);
894a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon                if (fp) {
904a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon                    pipelineBuilder.addCoverageFragmentProcessor(fp);
914a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon                    pipelineBuilder.setRenderTarget(rt);
924a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon
934a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon                    SkRect bounds = testBounds;
944a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon                    bounds.offset(SkIntToScalar(x), SkIntToScalar(y));
954a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon
964a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon                    tt.target()->drawNonAARect(pipelineBuilder,
974a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon                                               0xff000000,
984a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon                                               SkMatrix::I(),
994a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon                                               bounds);
1004a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon                }
1014a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon            canvas->restore();
1024a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon            x = x + fTestOffsetX;
103c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon        }
104c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon    }
105c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon
106c41f4d60559b0891353f8028d521b52e7a36d5dabsalomonprivate:
1074a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon    // pad between test cases
1084a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon    static const int kPad = 7;
1094a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon    // gap between rect for each case that is rendered and exterior of rrect
1104a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon    static const int kGap = 3;
1114a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon
1124a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon    SkRRect fRRect;
1134a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon    int fWidth;
1144a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon    int fHeight;
1154a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon    int fTestWidth;
1164a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon    int fTestHeight;
1174a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon    int fTestOffsetX;
1184a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon    int fTestOffsetY;
1194a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon    const char* fName;
120c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon    typedef GM INHERITED;
121c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon};
122c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon
123c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon///////////////////////////////////////////////////////////////////////////////
1244a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon// This value is motivated by bug chromium:477684. It has to be large to cause overflow in
1254a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon// the shader
1264a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomonstatic const int kSize = 700;
1274a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon
1284a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomonDEF_GM( return new BigRRectAAEffectGM (SkRRect::MakeRect(SkRect::MakeIWH(kSize, kSize)), "rect"); )
1294a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomonDEF_GM( return new BigRRectAAEffectGM (SkRRect::MakeOval(SkRect::MakeIWH(kSize, kSize)), "circle"); )
1304a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomonDEF_GM( return new BigRRectAAEffectGM (SkRRect::MakeOval(SkRect::MakeIWH(kSize - 1, kSize - 10)), "ellipse"); )
1314a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon// The next two have small linear segments between the corners
1324a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomonDEF_GM( return new BigRRectAAEffectGM (SkRRect::MakeRectXY(SkRect::MakeIWH(kSize - 1, kSize - 10), kSize/2.f - 10.f, kSize/2.f - 10.f), "circular_corner"); )
1334a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomonDEF_GM( return new BigRRectAAEffectGM (SkRRect::MakeRectXY(SkRect::MakeIWH(kSize - 1, kSize - 10), kSize/2.f - 10.f, kSize/2.f - 15.f), "elliptical_corner"); )
134c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon
135c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon}
136c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon#endif
137