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