Home | History | Annotate | Download | only in gm
      1 /*
      2  * Copyright 2015 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #include "gm.h"
      9 #if SK_SUPPORT_GPU
     10 #include "GrContext.h"
     11 #include "GrDrawContext.h"
     12 #include "GrPipelineBuilder.h"
     13 #include "SkDevice.h"
     14 #include "SkRRect.h"
     15 #include "batches/GrDrawBatch.h"
     16 #include "batches/GrRectBatchFactory.h"
     17 #include "effects/GrRRectEffect.h"
     18 
     19 namespace skiagm {
     20 
     21 ///////////////////////////////////////////////////////////////////////////////
     22 
     23 class BigRRectAAEffectGM : public GM {
     24 public:
     25     BigRRectAAEffectGM(const SkRRect& rrect, const char* name)
     26         : fRRect(rrect)
     27         , fName(name) {
     28         this->setBGColor(sk_tool_utils::color_to_565(SK_ColorBLUE));
     29         // Each test case draws the rrect with gaps around it.
     30         fTestWidth = SkScalarCeilToInt(rrect.width()) + 2 * kGap;
     31         fTestHeight = SkScalarCeilToInt(rrect.height()) + 2 * kGap;
     32 
     33         // Add a pad between test cases.
     34         fTestOffsetX = fTestWidth + kPad;
     35         fTestOffsetY = fTestHeight + kPad;
     36 
     37         // We draw two tests in x (fill and inv-fill) and pad around
     38         // all four sides of the image.
     39         fWidth = 2 * fTestOffsetX + kPad;
     40         fHeight = fTestOffsetY + kPad;
     41     }
     42 
     43 protected:
     44     SkString onShortName() override {
     45         SkString name;
     46         name.printf("big_rrect_%s_aa_effect", fName);
     47         return name;
     48     }
     49 
     50     SkISize onISize() override { return SkISize::Make(fWidth, fHeight); }
     51 
     52     void onDraw(SkCanvas* canvas) override {
     53         GrRenderTarget* rt = canvas->internal_private_accessTopLayerRenderTarget();
     54         GrContext* context = rt ? rt->getContext() : nullptr;
     55         if (!context) {
     56             skiagm::GM::DrawGpuOnlyMessage(canvas);
     57             return;
     58         }
     59 
     60         SkAutoTUnref<GrDrawContext> drawContext(context->drawContext(rt));
     61         if (!drawContext) {
     62             return;
     63         }
     64 
     65         SkPaint paint;
     66 
     67         int y = kPad;
     68         int x = kPad;
     69         static const GrPrimitiveEdgeType kEdgeTypes[] = {
     70             kFillAA_GrProcessorEdgeType,
     71             kInverseFillAA_GrProcessorEdgeType,
     72         };
     73         SkRect testBounds = SkRect::MakeIWH(fTestWidth, fTestHeight);
     74         for (size_t et = 0; et < SK_ARRAY_COUNT(kEdgeTypes); ++et) {
     75             GrPrimitiveEdgeType edgeType = kEdgeTypes[et];
     76             canvas->save();
     77                 canvas->translate(SkIntToScalar(x), SkIntToScalar(y));
     78 
     79                 // Draw a background for the test case
     80                 SkPaint paint;
     81                 paint.setColor(SK_ColorWHITE);
     82                 canvas->drawRect(testBounds, paint);
     83 
     84                 GrPipelineBuilder pipelineBuilder;
     85                 pipelineBuilder.setXPFactory(
     86                     GrPorterDuffXPFactory::Create(SkXfermode::kSrc_Mode))->unref();
     87 
     88                 SkRRect rrect = fRRect;
     89                 rrect.offset(SkIntToScalar(x + kGap), SkIntToScalar(y + kGap));
     90                 SkAutoTUnref<GrFragmentProcessor> fp(GrRRectEffect::Create(edgeType, rrect));
     91                 SkASSERT(fp);
     92                 if (fp) {
     93                     pipelineBuilder.addCoverageFragmentProcessor(fp);
     94                     pipelineBuilder.setRenderTarget(rt);
     95 
     96                     SkRect bounds = testBounds;
     97                     bounds.offset(SkIntToScalar(x), SkIntToScalar(y));
     98 
     99                     SkAutoTUnref<GrDrawBatch> batch(
    100                             GrRectBatchFactory::CreateNonAAFill(0xff000000, SkMatrix::I(), bounds,
    101                                                                 nullptr, nullptr));
    102                     drawContext->internal_drawBatch(pipelineBuilder, batch);
    103                 }
    104             canvas->restore();
    105             x = x + fTestOffsetX;
    106         }
    107     }
    108 
    109 private:
    110     // pad between test cases
    111     static const int kPad = 7;
    112     // gap between rect for each case that is rendered and exterior of rrect
    113     static const int kGap = 3;
    114 
    115     SkRRect fRRect;
    116     int fWidth;
    117     int fHeight;
    118     int fTestWidth;
    119     int fTestHeight;
    120     int fTestOffsetX;
    121     int fTestOffsetY;
    122     const char* fName;
    123     typedef GM INHERITED;
    124 };
    125 
    126 ///////////////////////////////////////////////////////////////////////////////
    127 // This value is motivated by bug chromium:477684. It has to be large to cause overflow in
    128 // the shader
    129 static const int kSize = 700;
    130 
    131 DEF_GM( return new BigRRectAAEffectGM (SkRRect::MakeRect(SkRect::MakeIWH(kSize, kSize)), "rect"); )
    132 DEF_GM( return new BigRRectAAEffectGM (SkRRect::MakeOval(SkRect::MakeIWH(kSize, kSize)), "circle"); )
    133 DEF_GM( return new BigRRectAAEffectGM (SkRRect::MakeOval(SkRect::MakeIWH(kSize - 1, kSize - 10)), "ellipse"); )
    134 // The next two have small linear segments between the corners
    135 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"); )
    136 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"); )
    137 
    138 }
    139 #endif
    140