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" 9d0c4e092d54d281991ecfdc2e4ddd5217e45b42afmalita#include "SkBlitter.h" 10feec878e850850cb0a092a765e3af0f5a3fa2a42herb#include "SkCanvas.h" 11feec878e850850cb0a092a765e3af0f5a3fa2a42herb#include "SkColor.h" 12feec878e850850cb0a092a765e3af0f5a3fa2a42herb#include "SkImage.h" 13feec878e850850cb0a092a765e3af0f5a3fa2a42herb#include "SkImageInfo.h" 14feec878e850850cb0a092a765e3af0f5a3fa2a42herb#include "SkLinearBitmapPipeline.h" 15feec878e850850cb0a092a765e3af0f5a3fa2a42herb#include "SkXfermode.h" 16feec878e850850cb0a092a765e3af0f5a3fa2a42herb#include "SkPM4fPriv.h" 17feec878e850850cb0a092a765e3af0f5a3fa2a42herb#include "SkShader.h" 18feec878e850850cb0a092a765e3af0f5a3fa2a42herb 19feec878e850850cb0a092a765e3af0f5a3fa2a42herbstatic void fill_in_bits(SkBitmap& bm, SkIRect ir, SkColor c, bool premul) { 20feec878e850850cb0a092a765e3af0f5a3fa2a42herb bm.allocN32Pixels(ir.width(), ir.height()); 21feec878e850850cb0a092a765e3af0f5a3fa2a42herb SkPixmap pm; 22feec878e850850cb0a092a765e3af0f5a3fa2a42herb bm.peekPixels(&pm); 23feec878e850850cb0a092a765e3af0f5a3fa2a42herb 24feec878e850850cb0a092a765e3af0f5a3fa2a42herb SkPMColor b = SkColorSetARGBMacro(255, 0, 0, 0); 25feec878e850850cb0a092a765e3af0f5a3fa2a42herb SkPMColor w; 26feec878e850850cb0a092a765e3af0f5a3fa2a42herb if (premul) { 27feec878e850850cb0a092a765e3af0f5a3fa2a42herb w = SkPreMultiplyColor(c); 28feec878e850850cb0a092a765e3af0f5a3fa2a42herb } else { 29feec878e850850cb0a092a765e3af0f5a3fa2a42herb w = SkPackARGB32NoCheck(SkColorGetA(c), SkColorGetR(c), SkColorGetG(c), SkColorGetB(c)); 30feec878e850850cb0a092a765e3af0f5a3fa2a42herb } 31feec878e850850cb0a092a765e3af0f5a3fa2a42herb 32feec878e850850cb0a092a765e3af0f5a3fa2a42herb for (int y = 0; y < ir.height(); y++) { 33feec878e850850cb0a092a765e3af0f5a3fa2a42herb for (int x = 0; x < ir.width(); x++) { 34feec878e850850cb0a092a765e3af0f5a3fa2a42herb if ((x ^ y) & 16) { 35feec878e850850cb0a092a765e3af0f5a3fa2a42herb *pm.writable_addr32(x, y) = b; 36feec878e850850cb0a092a765e3af0f5a3fa2a42herb } else { 37feec878e850850cb0a092a765e3af0f5a3fa2a42herb *pm.writable_addr32(x, y) = w; 38feec878e850850cb0a092a765e3af0f5a3fa2a42herb } 39feec878e850850cb0a092a765e3af0f5a3fa2a42herb } 40feec878e850850cb0a092a765e3af0f5a3fa2a42herb } 41feec878e850850cb0a092a765e3af0f5a3fa2a42herb} 42feec878e850850cb0a092a765e3af0f5a3fa2a42herb 43feec878e850850cb0a092a765e3af0f5a3fa2a42herbstatic void draw_rect_orig(SkCanvas* canvas, const SkRect& r, SkColor c, const SkMatrix* mat, bool useBilerp) { 44feec878e850850cb0a092a765e3af0f5a3fa2a42herb const SkIRect ir = r.round(); 45feec878e850850cb0a092a765e3af0f5a3fa2a42herb 46feec878e850850cb0a092a765e3af0f5a3fa2a42herb SkBitmap bmsrc; 47feec878e850850cb0a092a765e3af0f5a3fa2a42herb fill_in_bits(bmsrc, ir, c, true); 48feec878e850850cb0a092a765e3af0f5a3fa2a42herb 49feec878e850850cb0a092a765e3af0f5a3fa2a42herb SkPixmap pmsrc; 50feec878e850850cb0a092a765e3af0f5a3fa2a42herb bmsrc.peekPixels(&pmsrc); 51feec878e850850cb0a092a765e3af0f5a3fa2a42herb 52feec878e850850cb0a092a765e3af0f5a3fa2a42herb SkBitmap bmdst; 53feec878e850850cb0a092a765e3af0f5a3fa2a42herb bmdst.allocN32Pixels(ir.width(), ir.height()); 54feec878e850850cb0a092a765e3af0f5a3fa2a42herb bmdst.eraseColor(0xFFFFFFFF); 55feec878e850850cb0a092a765e3af0f5a3fa2a42herb SkPixmap pmdst; 56feec878e850850cb0a092a765e3af0f5a3fa2a42herb bmdst.peekPixels(&pmdst); 57feec878e850850cb0a092a765e3af0f5a3fa2a42herb 58feec878e850850cb0a092a765e3af0f5a3fa2a42herb SkImageInfo info = SkImageInfo::MakeN32Premul(ir.width(), ir.height(), kLinear_SkColorProfileType); 59feec878e850850cb0a092a765e3af0f5a3fa2a42herb 60feec878e850850cb0a092a765e3af0f5a3fa2a42herb SkAutoTUnref<SkImage> image{SkImage::NewRasterCopy( 61feec878e850850cb0a092a765e3af0f5a3fa2a42herb info, pmsrc.addr32(), pmsrc.rowBytes())}; 62feec878e850850cb0a092a765e3af0f5a3fa2a42herb SkPaint paint; 63feec878e850850cb0a092a765e3af0f5a3fa2a42herb int32_t storage[200]; 64feec878e850850cb0a092a765e3af0f5a3fa2a42herb SkShader* shader = image->newShader(SkShader::kClamp_TileMode, SkShader::kClamp_TileMode); 65feec878e850850cb0a092a765e3af0f5a3fa2a42herb if (useBilerp) { 66feec878e850850cb0a092a765e3af0f5a3fa2a42herb paint.setFilterQuality(SkFilterQuality::kLow_SkFilterQuality); 67feec878e850850cb0a092a765e3af0f5a3fa2a42herb } else { 68feec878e850850cb0a092a765e3af0f5a3fa2a42herb paint.setFilterQuality(SkFilterQuality::kNone_SkFilterQuality); 69feec878e850850cb0a092a765e3af0f5a3fa2a42herb } 70feec878e850850cb0a092a765e3af0f5a3fa2a42herb paint.setShader(shader)->unref(); 71d0c4e092d54d281991ecfdc2e4ddd5217e45b42afmalita const SkShader::ContextRec rec(paint, *mat, nullptr, 72d0c4e092d54d281991ecfdc2e4ddd5217e45b42afmalita SkBlitter::PreferredShaderDest(pmsrc.info())); 738d9f2e474ac9d175c28079357b022d31408e2fe4fmalita SkASSERT(paint.getShader()->contextSize(rec) <= sizeof(storage)); 74feec878e850850cb0a092a765e3af0f5a3fa2a42herb 758d9f2e474ac9d175c28079357b022d31408e2fe4fmalita SkShader::Context* ctx = paint.getShader()->createContext(rec, storage); 76feec878e850850cb0a092a765e3af0f5a3fa2a42herb 77feec878e850850cb0a092a765e3af0f5a3fa2a42herb for (int y = 0; y < ir.height(); y++) { 78feec878e850850cb0a092a765e3af0f5a3fa2a42herb ctx->shadeSpan(0, y, pmdst.writable_addr32(0, y), ir.width()); 79feec878e850850cb0a092a765e3af0f5a3fa2a42herb } 80feec878e850850cb0a092a765e3af0f5a3fa2a42herb 81feec878e850850cb0a092a765e3af0f5a3fa2a42herb canvas->drawBitmap(bmdst, r.left(), r.top(), nullptr); 82feec878e850850cb0a092a765e3af0f5a3fa2a42herb 83feec878e850850cb0a092a765e3af0f5a3fa2a42herb ctx->~Context(); 84feec878e850850cb0a092a765e3af0f5a3fa2a42herb 85feec878e850850cb0a092a765e3af0f5a3fa2a42herb} 86feec878e850850cb0a092a765e3af0f5a3fa2a42herb 87feec878e850850cb0a092a765e3af0f5a3fa2a42herbstatic void draw_rect_fp(SkCanvas* canvas, const SkRect& r, SkColor c, const SkMatrix* mat, bool useBilerp) { 88feec878e850850cb0a092a765e3af0f5a3fa2a42herb const SkIRect ir = r.round(); 89feec878e850850cb0a092a765e3af0f5a3fa2a42herb 90feec878e850850cb0a092a765e3af0f5a3fa2a42herb SkBitmap bmsrc; 91feec878e850850cb0a092a765e3af0f5a3fa2a42herb fill_in_bits(bmsrc, ir, c, true); 92feec878e850850cb0a092a765e3af0f5a3fa2a42herb SkPixmap pmsrc; 93feec878e850850cb0a092a765e3af0f5a3fa2a42herb bmsrc.peekPixels(&pmsrc); 94feec878e850850cb0a092a765e3af0f5a3fa2a42herb 95feec878e850850cb0a092a765e3af0f5a3fa2a42herb SkBitmap bmdst; 96feec878e850850cb0a092a765e3af0f5a3fa2a42herb bmdst.allocN32Pixels(ir.width(), ir.height()); 97feec878e850850cb0a092a765e3af0f5a3fa2a42herb bmdst.eraseColor(0xFFFFFFFF); 98feec878e850850cb0a092a765e3af0f5a3fa2a42herb SkPixmap pmdst; 99feec878e850850cb0a092a765e3af0f5a3fa2a42herb bmdst.peekPixels(&pmdst); 100feec878e850850cb0a092a765e3af0f5a3fa2a42herb 101feec878e850850cb0a092a765e3af0f5a3fa2a42herb SkPM4f* dstBits = new SkPM4f[ir.width()]; 102feec878e850850cb0a092a765e3af0f5a3fa2a42herb 103feec878e850850cb0a092a765e3af0f5a3fa2a42herb SkMatrix inv; 104feec878e850850cb0a092a765e3af0f5a3fa2a42herb bool trash = mat->invert(&inv); 105feec878e850850cb0a092a765e3af0f5a3fa2a42herb sk_ignore_unused_variable(trash); 106feec878e850850cb0a092a765e3af0f5a3fa2a42herb 107c5eddd7d8d67a6e931973a729c5868c155cb751fherb SkFilterQuality filterQuality; 108c5eddd7d8d67a6e931973a729c5868c155cb751fherb if (useBilerp) { 109c5eddd7d8d67a6e931973a729c5868c155cb751fherb filterQuality = SkFilterQuality::kLow_SkFilterQuality; 110c5eddd7d8d67a6e931973a729c5868c155cb751fherb } else { 111c5eddd7d8d67a6e931973a729c5868c155cb751fherb filterQuality = SkFilterQuality::kNone_SkFilterQuality; 112c5eddd7d8d67a6e931973a729c5868c155cb751fherb } 113feec878e850850cb0a092a765e3af0f5a3fa2a42herb 114feec878e850850cb0a092a765e3af0f5a3fa2a42herb uint32_t flags = 0; 115feec878e850850cb0a092a765e3af0f5a3fa2a42herb //if (kSRGB_SkColorProfileType == profile) { 116feec878e850850cb0a092a765e3af0f5a3fa2a42herb //flags |= SkXfermode::kDstIsSRGB_PM4fFlag; 117feec878e850850cb0a092a765e3af0f5a3fa2a42herb //} 1188f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed auto procN = SkXfermode::GetD32Proc(nullptr, flags); 119feec878e850850cb0a092a765e3af0f5a3fa2a42herb 120feec878e850850cb0a092a765e3af0f5a3fa2a42herb SkLinearBitmapPipeline pipeline{ 121c5eddd7d8d67a6e931973a729c5868c155cb751fherb inv, filterQuality, 122ed545042fca0e1d385561d956156e0b66532d161herb SkShader::kClamp_TileMode, SkShader::kClamp_TileMode, pmsrc}; 123feec878e850850cb0a092a765e3af0f5a3fa2a42herb 124feec878e850850cb0a092a765e3af0f5a3fa2a42herb for (int y = 0; y < ir.height(); y++) { 125feec878e850850cb0a092a765e3af0f5a3fa2a42herb pipeline.shadeSpan4f(0, y, dstBits, ir.width()); 1268f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed procN(nullptr, pmdst.writable_addr32(0, y), dstBits, ir.width(), nullptr); 127feec878e850850cb0a092a765e3af0f5a3fa2a42herb } 128feec878e850850cb0a092a765e3af0f5a3fa2a42herb 129feec878e850850cb0a092a765e3af0f5a3fa2a42herb delete [] dstBits; 130feec878e850850cb0a092a765e3af0f5a3fa2a42herb 131feec878e850850cb0a092a765e3af0f5a3fa2a42herb canvas->drawBitmap(bmdst, r.left(), r.top(), nullptr); 132feec878e850850cb0a092a765e3af0f5a3fa2a42herb} 133feec878e850850cb0a092a765e3af0f5a3fa2a42herb 134feec878e850850cb0a092a765e3af0f5a3fa2a42herbstatic void draw_rect_none(SkCanvas* canvas, const SkRect& r, SkColor c) { 135feec878e850850cb0a092a765e3af0f5a3fa2a42herb const SkIRect ir = r.round(); 136feec878e850850cb0a092a765e3af0f5a3fa2a42herb 137feec878e850850cb0a092a765e3af0f5a3fa2a42herb SkBitmap bm; 138feec878e850850cb0a092a765e3af0f5a3fa2a42herb fill_in_bits(bm, ir, c, true); 139feec878e850850cb0a092a765e3af0f5a3fa2a42herb 140feec878e850850cb0a092a765e3af0f5a3fa2a42herb canvas->drawBitmap(bm, r.left(), r.top(), nullptr); 141feec878e850850cb0a092a765e3af0f5a3fa2a42herb} 142feec878e850850cb0a092a765e3af0f5a3fa2a42herb 143feec878e850850cb0a092a765e3af0f5a3fa2a42herb/* 144feec878e850850cb0a092a765e3af0f5a3fa2a42herb * Test SkXfer4fProcs directly for src-over, comparing them to current SkColor blits. 145feec878e850850cb0a092a765e3af0f5a3fa2a42herb */ 146feec878e850850cb0a092a765e3af0f5a3fa2a42herbDEF_SIMPLE_GM(linear_pipeline, canvas, 580, 1400) { 147feec878e850850cb0a092a765e3af0f5a3fa2a42herb const int IW = 50; 148feec878e850850cb0a092a765e3af0f5a3fa2a42herb const SkScalar W = IW; 149feec878e850850cb0a092a765e3af0f5a3fa2a42herb const SkScalar H = 100; 150feec878e850850cb0a092a765e3af0f5a3fa2a42herb 151feec878e850850cb0a092a765e3af0f5a3fa2a42herb const SkColor colors[] = { 152feec878e850850cb0a092a765e3af0f5a3fa2a42herb 0x880000FF, 0x8800FF00, 0x88FF0000, 0x88000000, 153feec878e850850cb0a092a765e3af0f5a3fa2a42herb SK_ColorBLUE, SK_ColorGREEN, SK_ColorRED, SK_ColorBLACK, 154feec878e850850cb0a092a765e3af0f5a3fa2a42herb }; 155feec878e850850cb0a092a765e3af0f5a3fa2a42herb 156feec878e850850cb0a092a765e3af0f5a3fa2a42herb canvas->translate(20, 20); 157feec878e850850cb0a092a765e3af0f5a3fa2a42herb 158feec878e850850cb0a092a765e3af0f5a3fa2a42herb SkMatrix mi = SkMatrix::I(); 159feec878e850850cb0a092a765e3af0f5a3fa2a42herb SkMatrix mt; 160feec878e850850cb0a092a765e3af0f5a3fa2a42herb mt.setTranslate(8, 8); 161feec878e850850cb0a092a765e3af0f5a3fa2a42herb SkMatrix ms; 162feec878e850850cb0a092a765e3af0f5a3fa2a42herb ms.setScale(2.7f, 2.7f); 163feec878e850850cb0a092a765e3af0f5a3fa2a42herb SkMatrix mr; 164feec878e850850cb0a092a765e3af0f5a3fa2a42herb mr.setRotate(10); 165feec878e850850cb0a092a765e3af0f5a3fa2a42herb 166feec878e850850cb0a092a765e3af0f5a3fa2a42herb const SkMatrix* mats[] = {nullptr, &mi, &mt, &ms, &mr}; 167feec878e850850cb0a092a765e3af0f5a3fa2a42herb 168feec878e850850cb0a092a765e3af0f5a3fa2a42herb const SkRect r = SkRect::MakeWH(W, H); 169feec878e850850cb0a092a765e3af0f5a3fa2a42herb bool useBilerp = false; 170feec878e850850cb0a092a765e3af0f5a3fa2a42herb while (true) { 171feec878e850850cb0a092a765e3af0f5a3fa2a42herb canvas->save(); 172feec878e850850cb0a092a765e3af0f5a3fa2a42herb for (auto mat : mats) { 173feec878e850850cb0a092a765e3af0f5a3fa2a42herb canvas->save(); 174feec878e850850cb0a092a765e3af0f5a3fa2a42herb for (SkColor c : colors) { 175feec878e850850cb0a092a765e3af0f5a3fa2a42herb if (mat == nullptr) { 176feec878e850850cb0a092a765e3af0f5a3fa2a42herb SkPaint p; 177feec878e850850cb0a092a765e3af0f5a3fa2a42herb p.setColor(c); 178feec878e850850cb0a092a765e3af0f5a3fa2a42herb draw_rect_none(canvas, r, c); 179feec878e850850cb0a092a765e3af0f5a3fa2a42herb canvas->translate(W + 20, 0); 180feec878e850850cb0a092a765e3af0f5a3fa2a42herb draw_rect_none(canvas, r, c); 181feec878e850850cb0a092a765e3af0f5a3fa2a42herb 182feec878e850850cb0a092a765e3af0f5a3fa2a42herb } else { 183feec878e850850cb0a092a765e3af0f5a3fa2a42herb draw_rect_orig(canvas, r, c, mat, useBilerp); 184feec878e850850cb0a092a765e3af0f5a3fa2a42herb canvas->translate(W + 20, 0); 185feec878e850850cb0a092a765e3af0f5a3fa2a42herb draw_rect_fp(canvas, r, c, mat, useBilerp); 186feec878e850850cb0a092a765e3af0f5a3fa2a42herb } 187feec878e850850cb0a092a765e3af0f5a3fa2a42herb canvas->translate(W + 20, 0); 188feec878e850850cb0a092a765e3af0f5a3fa2a42herb } 189feec878e850850cb0a092a765e3af0f5a3fa2a42herb canvas->restore(); 190feec878e850850cb0a092a765e3af0f5a3fa2a42herb canvas->translate(0, H + 20); 191feec878e850850cb0a092a765e3af0f5a3fa2a42herb } 192feec878e850850cb0a092a765e3af0f5a3fa2a42herb canvas->restore(); 193feec878e850850cb0a092a765e3af0f5a3fa2a42herb canvas->translate(0, (H + 20) * SK_ARRAY_COUNT(mats)); 194feec878e850850cb0a092a765e3af0f5a3fa2a42herb if (useBilerp) break; 195feec878e850850cb0a092a765e3af0f5a3fa2a42herb useBilerp = true; 196feec878e850850cb0a092a765e3af0f5a3fa2a42herb } 197feec878e850850cb0a092a765e3af0f5a3fa2a42herb} 198