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