1feec878e850850cb0a092a765e3af0f5a3fa2a42herb/* 2feec878e850850cb0a092a765e3af0f5a3fa2a42herb * Copyright 2016 Google Inc. 3feec878e850850cb0a092a765e3af0f5a3fa2a42herb * 4feec878e850850cb0a092a765e3af0f5a3fa2a42herb * Use of this source code is governed by a BSD-style license that can be 5feec878e850850cb0a092a765e3af0f5a3fa2a42herb * found in the LICENSE file. 6feec878e850850cb0a092a765e3af0f5a3fa2a42herb */ 7feec878e850850cb0a092a765e3af0f5a3fa2a42herb 8feec878e850850cb0a092a765e3af0f5a3fa2a42herb#include "gm.h" 983e939bcb79790f5ae3b28c398fbcf034675a6e5Herb Derby 1083e939bcb79790f5ae3b28c398fbcf034675a6e5Herb Derby#include "SkArenaAlloc.h" 11d0c4e092d54d281991ecfdc2e4ddd5217e45b42afmalita#include "SkBlitter.h" 12feec878e850850cb0a092a765e3af0f5a3fa2a42herb#include "SkCanvas.h" 13feec878e850850cb0a092a765e3af0f5a3fa2a42herb#include "SkColor.h" 14feec878e850850cb0a092a765e3af0f5a3fa2a42herb#include "SkImage.h" 15feec878e850850cb0a092a765e3af0f5a3fa2a42herb#include "SkImageInfo.h" 16feec878e850850cb0a092a765e3af0f5a3fa2a42herb#include "SkLinearBitmapPipeline.h" 17d47067392848ba132d4e86ffbeebe2dcacda9534Mike Reed#include "SkXfermodePriv.h" 18feec878e850850cb0a092a765e3af0f5a3fa2a42herb#include "SkPM4fPriv.h" 19feec878e850850cb0a092a765e3af0f5a3fa2a42herb#include "SkShader.h" 20feec878e850850cb0a092a765e3af0f5a3fa2a42herb 21feec878e850850cb0a092a765e3af0f5a3fa2a42herbstatic void fill_in_bits(SkBitmap& bm, SkIRect ir, SkColor c, bool premul) { 22feec878e850850cb0a092a765e3af0f5a3fa2a42herb bm.allocN32Pixels(ir.width(), ir.height()); 23feec878e850850cb0a092a765e3af0f5a3fa2a42herb SkPixmap pm; 24feec878e850850cb0a092a765e3af0f5a3fa2a42herb bm.peekPixels(&pm); 25feec878e850850cb0a092a765e3af0f5a3fa2a42herb 26feec878e850850cb0a092a765e3af0f5a3fa2a42herb SkPMColor b = SkColorSetARGBMacro(255, 0, 0, 0); 27feec878e850850cb0a092a765e3af0f5a3fa2a42herb SkPMColor w; 28feec878e850850cb0a092a765e3af0f5a3fa2a42herb if (premul) { 29feec878e850850cb0a092a765e3af0f5a3fa2a42herb w = SkPreMultiplyColor(c); 30feec878e850850cb0a092a765e3af0f5a3fa2a42herb } else { 31feec878e850850cb0a092a765e3af0f5a3fa2a42herb w = SkPackARGB32NoCheck(SkColorGetA(c), SkColorGetR(c), SkColorGetG(c), SkColorGetB(c)); 32feec878e850850cb0a092a765e3af0f5a3fa2a42herb } 33feec878e850850cb0a092a765e3af0f5a3fa2a42herb 34feec878e850850cb0a092a765e3af0f5a3fa2a42herb for (int y = 0; y < ir.height(); y++) { 35feec878e850850cb0a092a765e3af0f5a3fa2a42herb for (int x = 0; x < ir.width(); x++) { 36feec878e850850cb0a092a765e3af0f5a3fa2a42herb if ((x ^ y) & 16) { 37feec878e850850cb0a092a765e3af0f5a3fa2a42herb *pm.writable_addr32(x, y) = b; 38feec878e850850cb0a092a765e3af0f5a3fa2a42herb } else { 39feec878e850850cb0a092a765e3af0f5a3fa2a42herb *pm.writable_addr32(x, y) = w; 40feec878e850850cb0a092a765e3af0f5a3fa2a42herb } 41feec878e850850cb0a092a765e3af0f5a3fa2a42herb } 42feec878e850850cb0a092a765e3af0f5a3fa2a42herb } 43feec878e850850cb0a092a765e3af0f5a3fa2a42herb} 44feec878e850850cb0a092a765e3af0f5a3fa2a42herb 45feec878e850850cb0a092a765e3af0f5a3fa2a42herbstatic void draw_rect_orig(SkCanvas* canvas, const SkRect& r, SkColor c, const SkMatrix* mat, bool useBilerp) { 46feec878e850850cb0a092a765e3af0f5a3fa2a42herb const SkIRect ir = r.round(); 47feec878e850850cb0a092a765e3af0f5a3fa2a42herb 48feec878e850850cb0a092a765e3af0f5a3fa2a42herb SkBitmap bmsrc; 49feec878e850850cb0a092a765e3af0f5a3fa2a42herb fill_in_bits(bmsrc, ir, c, true); 50feec878e850850cb0a092a765e3af0f5a3fa2a42herb 51feec878e850850cb0a092a765e3af0f5a3fa2a42herb SkPixmap pmsrc; 52feec878e850850cb0a092a765e3af0f5a3fa2a42herb bmsrc.peekPixels(&pmsrc); 53feec878e850850cb0a092a765e3af0f5a3fa2a42herb 54feec878e850850cb0a092a765e3af0f5a3fa2a42herb SkBitmap bmdst; 55feec878e850850cb0a092a765e3af0f5a3fa2a42herb bmdst.allocN32Pixels(ir.width(), ir.height()); 56feec878e850850cb0a092a765e3af0f5a3fa2a42herb bmdst.eraseColor(0xFFFFFFFF); 57feec878e850850cb0a092a765e3af0f5a3fa2a42herb SkPixmap pmdst; 58feec878e850850cb0a092a765e3af0f5a3fa2a42herb bmdst.peekPixels(&pmdst); 59feec878e850850cb0a092a765e3af0f5a3fa2a42herb 6052ede1d905728cdcaa98db1e4a33724f5a85c62dbrianosman SkImageInfo info = SkImageInfo::MakeN32Premul(ir.width(), ir.height()); 61feec878e850850cb0a092a765e3af0f5a3fa2a42herb 629ce9d6772df650ceb0511f275e1a83dffa78ff72reed sk_sp<SkImage> image(SkImage::MakeRasterCopy(SkPixmap(info, pmsrc.addr32(), pmsrc.rowBytes()))); 63feec878e850850cb0a092a765e3af0f5a3fa2a42herb SkPaint paint; 649852dc027f77c20640796d6988b0efcd42aa0b73Herb Derby SkArenaAlloc alloc{0}; 656eff52afb458bf6702a715d88611fd571544ef73herb 666eff52afb458bf6702a715d88611fd571544ef73herb sk_sp<SkShader> shader = image->makeShader(SkShader::kRepeat_TileMode, 676eff52afb458bf6702a715d88611fd571544ef73herb SkShader::kRepeat_TileMode); 686eff52afb458bf6702a715d88611fd571544ef73herb 69feec878e850850cb0a092a765e3af0f5a3fa2a42herb if (useBilerp) { 70feec878e850850cb0a092a765e3af0f5a3fa2a42herb paint.setFilterQuality(SkFilterQuality::kLow_SkFilterQuality); 71feec878e850850cb0a092a765e3af0f5a3fa2a42herb } else { 72feec878e850850cb0a092a765e3af0f5a3fa2a42herb paint.setFilterQuality(SkFilterQuality::kNone_SkFilterQuality); 73feec878e850850cb0a092a765e3af0f5a3fa2a42herb } 746eff52afb458bf6702a715d88611fd571544ef73herb paint.setShader(std::move(shader)); 75d0c4e092d54d281991ecfdc2e4ddd5217e45b42afmalita const SkShader::ContextRec rec(paint, *mat, nullptr, 7611970e56c10b49ad06adbe9e835d32c00a63dd7dBrian Osman SkBlitter::PreferredShaderDest(pmsrc.info()), 7711970e56c10b49ad06adbe9e835d32c00a63dd7dBrian Osman canvas->imageInfo().colorSpace()); 78feec878e850850cb0a092a765e3af0f5a3fa2a42herb 7983e939bcb79790f5ae3b28c398fbcf034675a6e5Herb Derby SkShader::Context* ctx = paint.getShader()->makeContext(rec, &alloc); 80feec878e850850cb0a092a765e3af0f5a3fa2a42herb 81feec878e850850cb0a092a765e3af0f5a3fa2a42herb for (int y = 0; y < ir.height(); y++) { 82feec878e850850cb0a092a765e3af0f5a3fa2a42herb ctx->shadeSpan(0, y, pmdst.writable_addr32(0, y), ir.width()); 83feec878e850850cb0a092a765e3af0f5a3fa2a42herb } 84feec878e850850cb0a092a765e3af0f5a3fa2a42herb 85feec878e850850cb0a092a765e3af0f5a3fa2a42herb canvas->drawBitmap(bmdst, r.left(), r.top(), nullptr); 86feec878e850850cb0a092a765e3af0f5a3fa2a42herb} 87feec878e850850cb0a092a765e3af0f5a3fa2a42herb 88feec878e850850cb0a092a765e3af0f5a3fa2a42herbstatic void draw_rect_fp(SkCanvas* canvas, const SkRect& r, SkColor c, const SkMatrix* mat, bool useBilerp) { 89feec878e850850cb0a092a765e3af0f5a3fa2a42herb const SkIRect ir = r.round(); 90feec878e850850cb0a092a765e3af0f5a3fa2a42herb 91feec878e850850cb0a092a765e3af0f5a3fa2a42herb SkBitmap bmsrc; 92feec878e850850cb0a092a765e3af0f5a3fa2a42herb fill_in_bits(bmsrc, ir, c, true); 93feec878e850850cb0a092a765e3af0f5a3fa2a42herb SkPixmap pmsrc; 94feec878e850850cb0a092a765e3af0f5a3fa2a42herb bmsrc.peekPixels(&pmsrc); 95feec878e850850cb0a092a765e3af0f5a3fa2a42herb 96feec878e850850cb0a092a765e3af0f5a3fa2a42herb SkBitmap bmdst; 97feec878e850850cb0a092a765e3af0f5a3fa2a42herb bmdst.allocN32Pixels(ir.width(), ir.height()); 98feec878e850850cb0a092a765e3af0f5a3fa2a42herb bmdst.eraseColor(0xFFFFFFFF); 99feec878e850850cb0a092a765e3af0f5a3fa2a42herb SkPixmap pmdst; 100feec878e850850cb0a092a765e3af0f5a3fa2a42herb bmdst.peekPixels(&pmdst); 101feec878e850850cb0a092a765e3af0f5a3fa2a42herb 102feec878e850850cb0a092a765e3af0f5a3fa2a42herb SkPM4f* dstBits = new SkPM4f[ir.width()]; 103feec878e850850cb0a092a765e3af0f5a3fa2a42herb 104feec878e850850cb0a092a765e3af0f5a3fa2a42herb SkMatrix inv; 105feec878e850850cb0a092a765e3af0f5a3fa2a42herb bool trash = mat->invert(&inv); 106feec878e850850cb0a092a765e3af0f5a3fa2a42herb sk_ignore_unused_variable(trash); 107feec878e850850cb0a092a765e3af0f5a3fa2a42herb 108c5eddd7d8d67a6e931973a729c5868c155cb751fherb SkFilterQuality filterQuality; 109c5eddd7d8d67a6e931973a729c5868c155cb751fherb if (useBilerp) { 110c5eddd7d8d67a6e931973a729c5868c155cb751fherb filterQuality = SkFilterQuality::kLow_SkFilterQuality; 111c5eddd7d8d67a6e931973a729c5868c155cb751fherb } else { 112c5eddd7d8d67a6e931973a729c5868c155cb751fherb filterQuality = SkFilterQuality::kNone_SkFilterQuality; 113c5eddd7d8d67a6e931973a729c5868c155cb751fherb } 114feec878e850850cb0a092a765e3af0f5a3fa2a42herb 115feec878e850850cb0a092a765e3af0f5a3fa2a42herb uint32_t flags = 0; 1166a01554e9e8687c56e6b6707e0c6a02062a1824eMike Reed auto procN = SkXfermode::GetD32Proc(SkBlendMode::kSrcOver, flags); 117feec878e850850cb0a092a765e3af0f5a3fa2a42herb 118dfa492e580269a9f0c357e23d540721b62183c96Herb Derby char storage[512]; 1190497f088bb41338b1b1400556b9b690decc846faHerb Derby SkArenaAlloc allocator{storage, sizeof(storage)}; 120feec878e850850cb0a092a765e3af0f5a3fa2a42herb SkLinearBitmapPipeline pipeline{ 121c5eddd7d8d67a6e931973a729c5868c155cb751fherb inv, filterQuality, 122dfa492e580269a9f0c357e23d540721b62183c96Herb Derby SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode, 123dfa492e580269a9f0c357e23d540721b62183c96Herb Derby SK_ColorBLACK, pmsrc, &allocator}; 124feec878e850850cb0a092a765e3af0f5a3fa2a42herb 125feec878e850850cb0a092a765e3af0f5a3fa2a42herb for (int y = 0; y < ir.height(); y++) { 126feec878e850850cb0a092a765e3af0f5a3fa2a42herb pipeline.shadeSpan4f(0, y, dstBits, ir.width()); 1276a01554e9e8687c56e6b6707e0c6a02062a1824eMike Reed procN(SkBlendMode::kSrcOver, pmdst.writable_addr32(0, y), dstBits, ir.width(), nullptr); 128feec878e850850cb0a092a765e3af0f5a3fa2a42herb } 129feec878e850850cb0a092a765e3af0f5a3fa2a42herb 130feec878e850850cb0a092a765e3af0f5a3fa2a42herb delete [] dstBits; 131feec878e850850cb0a092a765e3af0f5a3fa2a42herb 132feec878e850850cb0a092a765e3af0f5a3fa2a42herb canvas->drawBitmap(bmdst, r.left(), r.top(), nullptr); 133feec878e850850cb0a092a765e3af0f5a3fa2a42herb} 134feec878e850850cb0a092a765e3af0f5a3fa2a42herb 135feec878e850850cb0a092a765e3af0f5a3fa2a42herbstatic void draw_rect_none(SkCanvas* canvas, const SkRect& r, SkColor c) { 136feec878e850850cb0a092a765e3af0f5a3fa2a42herb const SkIRect ir = r.round(); 137feec878e850850cb0a092a765e3af0f5a3fa2a42herb 138feec878e850850cb0a092a765e3af0f5a3fa2a42herb SkBitmap bm; 139feec878e850850cb0a092a765e3af0f5a3fa2a42herb fill_in_bits(bm, ir, c, true); 140feec878e850850cb0a092a765e3af0f5a3fa2a42herb 141feec878e850850cb0a092a765e3af0f5a3fa2a42herb canvas->drawBitmap(bm, r.left(), r.top(), nullptr); 142feec878e850850cb0a092a765e3af0f5a3fa2a42herb} 143feec878e850850cb0a092a765e3af0f5a3fa2a42herb 144feec878e850850cb0a092a765e3af0f5a3fa2a42herb/* 145feec878e850850cb0a092a765e3af0f5a3fa2a42herb * Test SkXfer4fProcs directly for src-over, comparing them to current SkColor blits. 146feec878e850850cb0a092a765e3af0f5a3fa2a42herb */ 1479466571f8ebde1429cca7b6dcd2d4b85bad1b088herbDEF_SIMPLE_GM(linear_pipeline, canvas, 580, 2200) { 148feec878e850850cb0a092a765e3af0f5a3fa2a42herb const int IW = 50; 149feec878e850850cb0a092a765e3af0f5a3fa2a42herb const SkScalar W = IW; 150feec878e850850cb0a092a765e3af0f5a3fa2a42herb const SkScalar H = 100; 151feec878e850850cb0a092a765e3af0f5a3fa2a42herb 152feec878e850850cb0a092a765e3af0f5a3fa2a42herb const SkColor colors[] = { 153feec878e850850cb0a092a765e3af0f5a3fa2a42herb 0x880000FF, 0x8800FF00, 0x88FF0000, 0x88000000, 154feec878e850850cb0a092a765e3af0f5a3fa2a42herb SK_ColorBLUE, SK_ColorGREEN, SK_ColorRED, SK_ColorBLACK, 155feec878e850850cb0a092a765e3af0f5a3fa2a42herb }; 156feec878e850850cb0a092a765e3af0f5a3fa2a42herb 157feec878e850850cb0a092a765e3af0f5a3fa2a42herb canvas->translate(20, 20); 158feec878e850850cb0a092a765e3af0f5a3fa2a42herb 159feec878e850850cb0a092a765e3af0f5a3fa2a42herb SkMatrix mi = SkMatrix::I(); 1609466571f8ebde1429cca7b6dcd2d4b85bad1b088herb SkMatrix mlr; 1619466571f8ebde1429cca7b6dcd2d4b85bad1b088herb mlr.setScale(-1.0f, 1.0f, 20, 0.0f); 162feec878e850850cb0a092a765e3af0f5a3fa2a42herb SkMatrix mt; 163feec878e850850cb0a092a765e3af0f5a3fa2a42herb mt.setTranslate(8, 8); 1649466571f8ebde1429cca7b6dcd2d4b85bad1b088herb SkMatrix mt2; 1659466571f8ebde1429cca7b6dcd2d4b85bad1b088herb mt2.setTranslate(-18, -18); 166feec878e850850cb0a092a765e3af0f5a3fa2a42herb SkMatrix ms; 1676eff52afb458bf6702a715d88611fd571544ef73herb ms.setScale(2.7f, 2.7f, -1.5f, 0); 1689466571f8ebde1429cca7b6dcd2d4b85bad1b088herb SkMatrix ms2; 1696eff52afb458bf6702a715d88611fd571544ef73herb ms2.setScale(-0.4f, 0.4f); 170feec878e850850cb0a092a765e3af0f5a3fa2a42herb SkMatrix mr; 171feec878e850850cb0a092a765e3af0f5a3fa2a42herb mr.setRotate(10); 172feec878e850850cb0a092a765e3af0f5a3fa2a42herb 1739466571f8ebde1429cca7b6dcd2d4b85bad1b088herb const SkMatrix* mats[] = {nullptr, &mi, &mlr, &mt, &mt2, &ms, &ms2, &mr}; 174feec878e850850cb0a092a765e3af0f5a3fa2a42herb 175feec878e850850cb0a092a765e3af0f5a3fa2a42herb const SkRect r = SkRect::MakeWH(W, H); 176feec878e850850cb0a092a765e3af0f5a3fa2a42herb bool useBilerp = false; 177feec878e850850cb0a092a765e3af0f5a3fa2a42herb while (true) { 178feec878e850850cb0a092a765e3af0f5a3fa2a42herb canvas->save(); 179feec878e850850cb0a092a765e3af0f5a3fa2a42herb for (auto mat : mats) { 180feec878e850850cb0a092a765e3af0f5a3fa2a42herb canvas->save(); 181feec878e850850cb0a092a765e3af0f5a3fa2a42herb for (SkColor c : colors) { 182feec878e850850cb0a092a765e3af0f5a3fa2a42herb if (mat == nullptr) { 183feec878e850850cb0a092a765e3af0f5a3fa2a42herb SkPaint p; 184feec878e850850cb0a092a765e3af0f5a3fa2a42herb p.setColor(c); 185feec878e850850cb0a092a765e3af0f5a3fa2a42herb draw_rect_none(canvas, r, c); 186feec878e850850cb0a092a765e3af0f5a3fa2a42herb canvas->translate(W + 20, 0); 187feec878e850850cb0a092a765e3af0f5a3fa2a42herb draw_rect_none(canvas, r, c); 188feec878e850850cb0a092a765e3af0f5a3fa2a42herb 189feec878e850850cb0a092a765e3af0f5a3fa2a42herb } else { 190feec878e850850cb0a092a765e3af0f5a3fa2a42herb draw_rect_orig(canvas, r, c, mat, useBilerp); 191feec878e850850cb0a092a765e3af0f5a3fa2a42herb canvas->translate(W + 20, 0); 192feec878e850850cb0a092a765e3af0f5a3fa2a42herb draw_rect_fp(canvas, r, c, mat, useBilerp); 193feec878e850850cb0a092a765e3af0f5a3fa2a42herb } 194feec878e850850cb0a092a765e3af0f5a3fa2a42herb canvas->translate(W + 20, 0); 195feec878e850850cb0a092a765e3af0f5a3fa2a42herb } 196feec878e850850cb0a092a765e3af0f5a3fa2a42herb canvas->restore(); 197feec878e850850cb0a092a765e3af0f5a3fa2a42herb canvas->translate(0, H + 20); 198feec878e850850cb0a092a765e3af0f5a3fa2a42herb } 199feec878e850850cb0a092a765e3af0f5a3fa2a42herb canvas->restore(); 200feec878e850850cb0a092a765e3af0f5a3fa2a42herb canvas->translate(0, (H + 20) * SK_ARRAY_COUNT(mats)); 201feec878e850850cb0a092a765e3af0f5a3fa2a42herb if (useBilerp) break; 202feec878e850850cb0a092a765e3af0f5a3fa2a42herb useBilerp = true; 203feec878e850850cb0a092a765e3af0f5a3fa2a42herb } 204feec878e850850cb0a092a765e3af0f5a3fa2a42herb} 205