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
1004194f32f4f5ec9029357a18c0f1f9dc3404fc0cjoshualitt#include "GrContext.h"
1104194f32f4f5ec9029357a18c0f1f9dc3404fc0cjoshualitt#include "GrDrawContext.h"
1204194f32f4f5ec9029357a18c0f1f9dc3404fc0cjoshualitt#include "GrPipelineBuilder.h"
13c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon#include "SkDevice.h"
14c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon#include "SkRRect.h"
1504194f32f4f5ec9029357a18c0f1f9dc3404fc0cjoshualitt#include "batches/GrDrawBatch.h"
1604194f32f4f5ec9029357a18c0f1f9dc3404fc0cjoshualitt#include "batches/GrRectBatchFactory.h"
1704194f32f4f5ec9029357a18c0f1f9dc3404fc0cjoshualitt#include "effects/GrRRectEffect.h"
18c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon
19c41f4d60559b0891353f8028d521b52e7a36d5dabsalomonnamespace skiagm {
20c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon
21c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon///////////////////////////////////////////////////////////////////////////////
22c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon
23c41f4d60559b0891353f8028d521b52e7a36d5dabsalomonclass BigRRectAAEffectGM : public GM {
24c41f4d60559b0891353f8028d521b52e7a36d5dabsalomonpublic:
254a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon    BigRRectAAEffectGM(const SkRRect& rrect, const char* name)
264a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon        : fRRect(rrect)
274a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon        , fName(name) {
284a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon        this->setBGColor(sk_tool_utils::color_to_565(SK_ColorBLUE));
294a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon        // Each test case draws the rrect with gaps around it.
304a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon        fTestWidth = SkScalarCeilToInt(rrect.width()) + 2 * kGap;
314a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon        fTestHeight = SkScalarCeilToInt(rrect.height()) + 2 * kGap;
324a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon
334a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon        // Add a pad between test cases.
344a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon        fTestOffsetX = fTestWidth + kPad;
354a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon        fTestOffsetY = fTestHeight + kPad;
364a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon
374a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon        // We draw two tests in x (fill and inv-fill) and pad around
384a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon        // all four sides of the image.
394a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon        fWidth = 2 * fTestOffsetX + kPad;
404a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon        fHeight = fTestOffsetY + kPad;
41c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon    }
42c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon
43c41f4d60559b0891353f8028d521b52e7a36d5dabsalomonprotected:
44c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon    SkString onShortName() override {
454a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon        SkString name;
464a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon        name.printf("big_rrect_%s_aa_effect", fName);
474a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon        return name;
48c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon    }
49c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon
504a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon    SkISize onISize() override { return SkISize::Make(fWidth, fHeight); }
51c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon
52c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon    void onDraw(SkCanvas* canvas) override {
53c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon        GrRenderTarget* rt = canvas->internal_private_accessTopLayerRenderTarget();
5496fcdcc219d2a0d3579719b84b28bede76efba64halcanary        GrContext* context = rt ? rt->getContext() : nullptr;
55c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon        if (!context) {
562a24338c777462e04a2b26295f9c034155ee8f3ehalcanary            skiagm::GM::DrawGpuOnlyMessage(canvas);
57c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon            return;
58c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon        }
59c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon
6004194f32f4f5ec9029357a18c0f1f9dc3404fc0cjoshualitt        SkAutoTUnref<GrDrawContext> drawContext(context->drawContext(rt));
6104194f32f4f5ec9029357a18c0f1f9dc3404fc0cjoshualitt        if (!drawContext) {
6204194f32f4f5ec9029357a18c0f1f9dc3404fc0cjoshualitt            return;
6304194f32f4f5ec9029357a18c0f1f9dc3404fc0cjoshualitt        }
6404194f32f4f5ec9029357a18c0f1f9dc3404fc0cjoshualitt
65c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon        SkPaint paint;
66c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon
67c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon        int y = kPad;
68c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon        int x = kPad;
69c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon        static const GrPrimitiveEdgeType kEdgeTypes[] = {
70c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon            kFillAA_GrProcessorEdgeType,
71c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon            kInverseFillAA_GrProcessorEdgeType,
72c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon        };
734a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon        SkRect testBounds = SkRect::MakeIWH(fTestWidth, fTestHeight);
74c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon        for (size_t et = 0; et < SK_ARRAY_COUNT(kEdgeTypes); ++et) {
75c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon            GrPrimitiveEdgeType edgeType = kEdgeTypes[et];
764a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon            canvas->save();
774a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon                canvas->translate(SkIntToScalar(x), SkIntToScalar(y));
784a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon
794a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon                // Draw a background for the test case
804a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon                SkPaint paint;
814a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon                paint.setColor(SK_ColorWHITE);
824a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon                canvas->drawRect(testBounds, paint);
834a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon
844a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon                GrPipelineBuilder pipelineBuilder;
854a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon                pipelineBuilder.setXPFactory(
864a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon                    GrPorterDuffXPFactory::Create(SkXfermode::kSrc_Mode))->unref();
874a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon
884a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon                SkRRect rrect = fRRect;
894a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon                rrect.offset(SkIntToScalar(x + kGap), SkIntToScalar(y + kGap));
904a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon                SkAutoTUnref<GrFragmentProcessor> fp(GrRRectEffect::Create(edgeType, rrect));
914a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon                SkASSERT(fp);
924a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon                if (fp) {
934a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon                    pipelineBuilder.addCoverageFragmentProcessor(fp);
944a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon                    pipelineBuilder.setRenderTarget(rt);
954a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon
964a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon                    SkRect bounds = testBounds;
974a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon                    bounds.offset(SkIntToScalar(x), SkIntToScalar(y));
984a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon
9904194f32f4f5ec9029357a18c0f1f9dc3404fc0cjoshualitt                    SkAutoTUnref<GrDrawBatch> batch(
10004194f32f4f5ec9029357a18c0f1f9dc3404fc0cjoshualitt                            GrRectBatchFactory::CreateNonAAFill(0xff000000, SkMatrix::I(), bounds,
10104194f32f4f5ec9029357a18c0f1f9dc3404fc0cjoshualitt                                                                nullptr, nullptr));
10204194f32f4f5ec9029357a18c0f1f9dc3404fc0cjoshualitt                    drawContext->internal_drawBatch(pipelineBuilder, batch);
1034a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon                }
1044a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon            canvas->restore();
1054a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon            x = x + fTestOffsetX;
106c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon        }
107c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon    }
108c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon
109c41f4d60559b0891353f8028d521b52e7a36d5dabsalomonprivate:
1104a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon    // pad between test cases
1114a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon    static const int kPad = 7;
1124a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon    // gap between rect for each case that is rendered and exterior of rrect
1134a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon    static const int kGap = 3;
1144a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon
1154a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon    SkRRect fRRect;
1164a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon    int fWidth;
1174a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon    int fHeight;
1184a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon    int fTestWidth;
1194a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon    int fTestHeight;
1204a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon    int fTestOffsetX;
1214a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon    int fTestOffsetY;
1224a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon    const char* fName;
123c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon    typedef GM INHERITED;
124c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon};
125c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon
126c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon///////////////////////////////////////////////////////////////////////////////
1274a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon// This value is motivated by bug chromium:477684. It has to be large to cause overflow in
1284a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon// the shader
1294a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomonstatic const int kSize = 700;
1304a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon
1314a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomonDEF_GM( return new BigRRectAAEffectGM (SkRRect::MakeRect(SkRect::MakeIWH(kSize, kSize)), "rect"); )
1324a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomonDEF_GM( return new BigRRectAAEffectGM (SkRRect::MakeOval(SkRect::MakeIWH(kSize, kSize)), "circle"); )
1334a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomonDEF_GM( return new BigRRectAAEffectGM (SkRRect::MakeOval(SkRect::MakeIWH(kSize - 1, kSize - 10)), "ellipse"); )
1344a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon// The next two have small linear segments between the corners
1354a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomonDEF_GM( return new BigRRectAAEffectGM (SkRRect::MakeRectXY(SkRect::MakeIWH(kSize - 1, kSize - 10), kSize/2.f - 10.f, kSize/2.f - 10.f), "circular_corner"); )
1364a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomonDEF_GM( return new BigRRectAAEffectGM (SkRRect::MakeRectXY(SkRect::MakeIWH(kSize - 1, kSize - 10), kSize/2.f - 10.f, kSize/2.f - 15.f), "elliptical_corner"); )
137c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon
138c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon}
139c41f4d60559b0891353f8028d521b52e7a36d5dabsalomon#endif
140