15ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt/* 25ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt * Copyright 2013 Google Inc. 35ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt * 45ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt * Use of this source code is governed by a BSD-style license that can be 55ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt * found in the LICENSE file. 65ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt */ 75ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt#include "gm.h" 833d2055e594177b27360f84e0631b26d74a55a9bMike Klein#include "sk_tool_utils.h" 95ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt#include "SkBitmap.h" 10d3ebb48320cf1b7e969974673e4bd7743816985ebungeman#include "SkPath.h" 115ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt#include "SkRandom.h" 125ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt#include "SkShader.h" 138336e949b8aecc664a4f2690b56369d3821b2a1bBrian Salomon#include "SkSurface.h" 145ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt 155ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualittnamespace skiagm { 165ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt 175ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt/** 185ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt * Renders overlapping shapes with colorburn against a checkerboard. 195ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt */ 205ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualittclass DstReadShuffle : public GM { 215ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualittpublic: 22d02b6f331bca054b0654e213ea6a7ddd94257bf7Brian Salomon DstReadShuffle() { this->setBGColor(kBackground); } 235ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt 245ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualittprotected: 255ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt enum ShapeType { 265ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt kCircle_ShapeType, 275ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt kRoundRect_ShapeType, 285ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt kRect_ShapeType, 295ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt kConvexPath_ShapeType, 305ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt kConcavePath_ShapeType, 315ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt kText_ShapeType, 325ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt kNumShapeTypes 335ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt }; 345ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt 3536352bf5e38f45a70ee4f4fc132a38048d38206dmtklein SkString onShortName() override { 365ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt return SkString("dstreadshuffle"); 375ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt } 385ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt 3936352bf5e38f45a70ee4f4fc132a38048d38206dmtklein SkISize onISize() override { 408336e949b8aecc664a4f2690b56369d3821b2a1bBrian Salomon return SkISize::Make(530, 680); 415ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt } 425ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt 438336e949b8aecc664a4f2690b56369d3821b2a1bBrian Salomon void drawShape(SkCanvas* canvas, SkPaint* paint, ShapeType type) { 448336e949b8aecc664a4f2690b56369d3821b2a1bBrian Salomon const SkRect kRect = SkRect::MakeXYWH(0, 0, 75.f, 85.f); 455ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt switch (type) { 465ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt case kCircle_ShapeType: 478336e949b8aecc664a4f2690b56369d3821b2a1bBrian Salomon canvas->drawCircle(kRect.centerX(), kRect.centerY(), kRect.width() / 2.f, *paint); 485ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt break; 495ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt case kRoundRect_ShapeType: 508336e949b8aecc664a4f2690b56369d3821b2a1bBrian Salomon canvas->drawRoundRect(kRect, 15.f, 15.f, *paint); 515ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt break; 525ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt case kRect_ShapeType: 535ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt canvas->drawRect(kRect, *paint); 545ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt break; 555ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt case kConvexPath_ShapeType: 565ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt if (fConvexPath.isEmpty()) { 575ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt SkPoint points[4]; 585ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt kRect.toQuad(points); 595ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt fConvexPath.moveTo(points[0]); 605ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt fConvexPath.quadTo(points[1], points[2]); 615ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt fConvexPath.quadTo(points[3], points[0]); 625ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt SkASSERT(fConvexPath.isConvex()); 635ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt } 645ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt canvas->drawPath(fConvexPath, *paint); 655ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt break; 665ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt case kConcavePath_ShapeType: 675ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt if (fConcavePath.isEmpty()) { 688336e949b8aecc664a4f2690b56369d3821b2a1bBrian Salomon SkPoint points[5] = {{50.f, 0.f}}; 695ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt SkMatrix rot; 708336e949b8aecc664a4f2690b56369d3821b2a1bBrian Salomon rot.setRotate(360.f / 5, 50.f, 70.f); 715ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt for (int i = 1; i < 5; ++i) { 725ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt rot.mapPoints(points + i, points + i - 1, 1); 735ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt } 745ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt fConcavePath.moveTo(points[0]); 755ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt for (int i = 0; i < 5; ++i) { 765ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt fConcavePath.lineTo(points[(2 * i) % 5]); 775ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt } 785ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt fConcavePath.setFillType(SkPath::kEvenOdd_FillType); 795ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt SkASSERT(!fConcavePath.isConvex()); 805ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt } 815ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt canvas->drawPath(fConcavePath, *paint); 825ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt break; 835ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt case kText_ShapeType: { 848336e949b8aecc664a4f2690b56369d3821b2a1bBrian Salomon const char* text = "N"; 858336e949b8aecc664a4f2690b56369d3821b2a1bBrian Salomon paint->setTextSize(100.f); 868336e949b8aecc664a4f2690b56369d3821b2a1bBrian Salomon paint->setFakeBoldText(true); 87f1f8bd58513848440d76e49cc3fde585bc888ff5caryclark sk_tool_utils::set_portable_typeface(paint); 888336e949b8aecc664a4f2690b56369d3821b2a1bBrian Salomon canvas->drawText(text, strlen(text), 0.f, 100.f, *paint); 895ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt } 905ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt default: 915ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt break; 925ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt } 935ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt } 945ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt 958336e949b8aecc664a4f2690b56369d3821b2a1bBrian Salomon static SkColor GetColor(SkRandom* random) { 968336e949b8aecc664a4f2690b56369d3821b2a1bBrian Salomon SkColor color = sk_tool_utils::color_to_565(random->nextU() | 0xFF000000); 978336e949b8aecc664a4f2690b56369d3821b2a1bBrian Salomon return SkColorSetA(color, 0x80); 985ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt } 995ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt 1008336e949b8aecc664a4f2690b56369d3821b2a1bBrian Salomon static void DrawHairlines(SkCanvas* canvas) { 101d02b6f331bca054b0654e213ea6a7ddd94257bf7Brian Salomon if (canvas->imageInfo().alphaType() == kOpaque_SkAlphaType) { 102d02b6f331bca054b0654e213ea6a7ddd94257bf7Brian Salomon canvas->clear(kBackground); 103d02b6f331bca054b0654e213ea6a7ddd94257bf7Brian Salomon } else { 104d02b6f331bca054b0654e213ea6a7ddd94257bf7Brian Salomon canvas->clear(SK_ColorTRANSPARENT); 105d02b6f331bca054b0654e213ea6a7ddd94257bf7Brian Salomon } 1068336e949b8aecc664a4f2690b56369d3821b2a1bBrian Salomon SkPaint hairPaint; 1078336e949b8aecc664a4f2690b56369d3821b2a1bBrian Salomon hairPaint.setStyle(SkPaint::kStroke_Style); 1088336e949b8aecc664a4f2690b56369d3821b2a1bBrian Salomon hairPaint.setStrokeWidth(0); 1098336e949b8aecc664a4f2690b56369d3821b2a1bBrian Salomon hairPaint.setAntiAlias(true); 1108336e949b8aecc664a4f2690b56369d3821b2a1bBrian Salomon static constexpr int kNumHairlines = 12; 1118336e949b8aecc664a4f2690b56369d3821b2a1bBrian Salomon SkPoint pts[] = {{3.f, 7.f}, {29.f, 7.f}}; 1128336e949b8aecc664a4f2690b56369d3821b2a1bBrian Salomon SkRandom colorRandom; 1138336e949b8aecc664a4f2690b56369d3821b2a1bBrian Salomon SkMatrix rot; 1148336e949b8aecc664a4f2690b56369d3821b2a1bBrian Salomon rot.setRotate(360.f / kNumHairlines, 15.5f, 12.f); 1158336e949b8aecc664a4f2690b56369d3821b2a1bBrian Salomon rot.postTranslate(3.f, 0); 1168336e949b8aecc664a4f2690b56369d3821b2a1bBrian Salomon for (int i = 0; i < 12; ++i) { 1178336e949b8aecc664a4f2690b56369d3821b2a1bBrian Salomon hairPaint.setColor(GetColor(&colorRandom)); 1188336e949b8aecc664a4f2690b56369d3821b2a1bBrian Salomon canvas->drawLine(pts[0].fX, pts[0].fY, pts[1].fX, pts[1].fY, hairPaint); 1198336e949b8aecc664a4f2690b56369d3821b2a1bBrian Salomon rot.mapPoints(pts, 2); 1205ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt } 1215ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt } 1225ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt 12336352bf5e38f45a70ee4f4fc132a38048d38206dmtklein void onDraw(SkCanvas* canvas) override { 1248336e949b8aecc664a4f2690b56369d3821b2a1bBrian Salomon SkScalar y = 5; 1255ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt for (int i = 0; i < kNumShapeTypes; i++) { 1268336e949b8aecc664a4f2690b56369d3821b2a1bBrian Salomon SkRandom colorRandom; 1275ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt ShapeType shapeType = static_cast<ShapeType>(i); 1288336e949b8aecc664a4f2690b56369d3821b2a1bBrian Salomon SkScalar x = 5; 1298336e949b8aecc664a4f2690b56369d3821b2a1bBrian Salomon for (int r = 0; r <= 15; r++) { 1308336e949b8aecc664a4f2690b56369d3821b2a1bBrian Salomon SkPaint p; 1318336e949b8aecc664a4f2690b56369d3821b2a1bBrian Salomon p.setAntiAlias(true); 1328336e949b8aecc664a4f2690b56369d3821b2a1bBrian Salomon p.setColor(GetColor(&colorRandom)); 1338336e949b8aecc664a4f2690b56369d3821b2a1bBrian Salomon // In order to get some op combining on the GPU backend we do 2 src over 1348336e949b8aecc664a4f2690b56369d3821b2a1bBrian Salomon // for each xfer mode which requires a dst read 1358336e949b8aecc664a4f2690b56369d3821b2a1bBrian Salomon p.setBlendMode(r % 3 == 0 ? SkBlendMode::kColorBurn : SkBlendMode::kSrcOver); 1368336e949b8aecc664a4f2690b56369d3821b2a1bBrian Salomon canvas->save(); 1378336e949b8aecc664a4f2690b56369d3821b2a1bBrian Salomon canvas->translate(x, y); 1388336e949b8aecc664a4f2690b56369d3821b2a1bBrian Salomon this->drawShape(canvas, &p, shapeType); 1398336e949b8aecc664a4f2690b56369d3821b2a1bBrian Salomon canvas->restore(); 1408336e949b8aecc664a4f2690b56369d3821b2a1bBrian Salomon x += 15; 1415ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt } 1428336e949b8aecc664a4f2690b56369d3821b2a1bBrian Salomon y += 110; 1438336e949b8aecc664a4f2690b56369d3821b2a1bBrian Salomon } 1448336e949b8aecc664a4f2690b56369d3821b2a1bBrian Salomon // Draw hairlines to a surface and then draw that to the main canvas with a zoom so that 1458336e949b8aecc664a4f2690b56369d3821b2a1bBrian Salomon // it is easier to see how they blend. 1468336e949b8aecc664a4f2690b56369d3821b2a1bBrian Salomon SkImageInfo info; 147d02b6f331bca054b0654e213ea6a7ddd94257bf7Brian Salomon // Recording canvases don't have a color type. 148d02b6f331bca054b0654e213ea6a7ddd94257bf7Brian Salomon if (SkColorType::kUnknown_SkColorType == canvas->imageInfo().colorType()) { 149d02b6f331bca054b0654e213ea6a7ddd94257bf7Brian Salomon info = SkImageInfo::MakeN32Premul(35, 35); 150d02b6f331bca054b0654e213ea6a7ddd94257bf7Brian Salomon } else { 1518336e949b8aecc664a4f2690b56369d3821b2a1bBrian Salomon info = SkImageInfo::Make(35, 35, 1528336e949b8aecc664a4f2690b56369d3821b2a1bBrian Salomon canvas->imageInfo().colorType(), 1538336e949b8aecc664a4f2690b56369d3821b2a1bBrian Salomon canvas->imageInfo().alphaType(), 1548336e949b8aecc664a4f2690b56369d3821b2a1bBrian Salomon canvas->imageInfo().refColorSpace()); 1555ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt } 1568336e949b8aecc664a4f2690b56369d3821b2a1bBrian Salomon auto surf = canvas->makeSurface(info); 1578336e949b8aecc664a4f2690b56369d3821b2a1bBrian Salomon if (!surf) { 158d02b6f331bca054b0654e213ea6a7ddd94257bf7Brian Salomon // Fall back to raster. Raster supports only one of the 8 bit per-channel RGBA or BGRA 159d02b6f331bca054b0654e213ea6a7ddd94257bf7Brian Salomon // formats. This fall back happens when running with --preAbandonGpuContext. 160d02b6f331bca054b0654e213ea6a7ddd94257bf7Brian Salomon if ((info.colorType() == kRGBA_8888_SkColorType || 161d02b6f331bca054b0654e213ea6a7ddd94257bf7Brian Salomon info.colorType() == kBGRA_8888_SkColorType) && 162d02b6f331bca054b0654e213ea6a7ddd94257bf7Brian Salomon info.colorType() != kN32_SkColorType) { 163d02b6f331bca054b0654e213ea6a7ddd94257bf7Brian Salomon info = SkImageInfo::Make(35, 35, 164d02b6f331bca054b0654e213ea6a7ddd94257bf7Brian Salomon kN32_SkColorType, 165d02b6f331bca054b0654e213ea6a7ddd94257bf7Brian Salomon canvas->imageInfo().alphaType(), 166d02b6f331bca054b0654e213ea6a7ddd94257bf7Brian Salomon canvas->imageInfo().refColorSpace()); 167d02b6f331bca054b0654e213ea6a7ddd94257bf7Brian Salomon } 1688336e949b8aecc664a4f2690b56369d3821b2a1bBrian Salomon surf = SkSurface::MakeRaster(info); 1698336e949b8aecc664a4f2690b56369d3821b2a1bBrian Salomon } 1708336e949b8aecc664a4f2690b56369d3821b2a1bBrian Salomon canvas->scale(5.f, 5.f); 1718336e949b8aecc664a4f2690b56369d3821b2a1bBrian Salomon canvas->translate(67.f, 10.f); 1728336e949b8aecc664a4f2690b56369d3821b2a1bBrian Salomon DrawHairlines(surf->getCanvas()); 1738336e949b8aecc664a4f2690b56369d3821b2a1bBrian Salomon canvas->drawImage(surf->makeImageSnapshot(), 0.f, 0.f); 1745ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt } 1755ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt 1765ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualittprivate: 177d02b6f331bca054b0654e213ea6a7ddd94257bf7Brian Salomon static constexpr SkColor kBackground = SK_ColorLTGRAY; 1788336e949b8aecc664a4f2690b56369d3821b2a1bBrian Salomon SkPath fConcavePath; 1798336e949b8aecc664a4f2690b56369d3821b2a1bBrian Salomon SkPath fConvexPath; 1805ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt typedef GM INHERITED; 1815ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt}; 1825ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt 1835ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt////////////////////////////////////////////////////////////////////////////// 1845ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt 1855ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualittstatic GM* MyFactory(void*) { return new DstReadShuffle; } 1865ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualittstatic GMRegistry reg(MyFactory); 1875ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt 1885ce33c17afb9f10e8faf6907f030268d97fdf1d8joshualitt} 189