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