xref: /aosp_15_r20/external/skia/gm/mirrortile.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2022 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker *
4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker */
7*c8dee2aaSAndroid Build Coastguard Worker 
8*c8dee2aaSAndroid Build Coastguard Worker #include "gm/gm.h"
9*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkCanvas.h"
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkImage.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPaint.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPixmap.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkShader.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSurface.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTileMode.h"
16*c8dee2aaSAndroid Build Coastguard Worker 
17*c8dee2aaSAndroid Build Coastguard Worker /**
18*c8dee2aaSAndroid Build Coastguard Worker  * Tests image shader mirror tile mode with scale factors of 1 and -1, with nearest and linear
19*c8dee2aaSAndroid Build Coastguard Worker  * filtering, and with/without a half pixel offset between device and image space. The linear filter
20*c8dee2aaSAndroid Build Coastguard Worker  * should only have an effect when there is a half pixel offset. We test mirror tile mode in x and
21*c8dee2aaSAndroid Build Coastguard Worker  * in y separately.
22*c8dee2aaSAndroid Build Coastguard Worker  */
23*c8dee2aaSAndroid Build Coastguard Worker DEF_SIMPLE_GM_CAN_FAIL(mirror_tile, canvas, errorMsg, 140, 370) {
24*c8dee2aaSAndroid Build Coastguard Worker     // We don't run this test on the GPU because we're at the driver/hw's mercy for how this
25*c8dee2aaSAndroid Build Coastguard Worker     // is handled. We also don't test this on recording or vector canvases.
26*c8dee2aaSAndroid Build Coastguard Worker     if (SkPixmap unused; !canvas->peekPixels(&unused)) {
27*c8dee2aaSAndroid Build Coastguard Worker         *errorMsg = "Test only works with canvases backed by CPU pixels";
28*c8dee2aaSAndroid Build Coastguard Worker         return skiagm::DrawResult::kSkip;
29*c8dee2aaSAndroid Build Coastguard Worker     }
30*c8dee2aaSAndroid Build Coastguard Worker 
31*c8dee2aaSAndroid Build Coastguard Worker     uint32_t colors[] {0xFFFF0000, 0xFF00FF00, 0xFF0000FF};
32*c8dee2aaSAndroid Build Coastguard Worker     SkPixmap pmx(SkImageInfo::Make({std::size(colors), 1},
33*c8dee2aaSAndroid Build Coastguard Worker                                    kRGBA_8888_SkColorType,
34*c8dee2aaSAndroid Build Coastguard Worker                                    kPremul_SkAlphaType),
35*c8dee2aaSAndroid Build Coastguard Worker                  colors,
36*c8dee2aaSAndroid Build Coastguard Worker                  sizeof(colors));
37*c8dee2aaSAndroid Build Coastguard Worker     auto imgx = SkImages::RasterFromPixmapCopy(pmx);
38*c8dee2aaSAndroid Build Coastguard Worker 
39*c8dee2aaSAndroid Build Coastguard Worker     SkPixmap pmy(SkImageInfo::Make({1, std::size(colors)},
40*c8dee2aaSAndroid Build Coastguard Worker                                    kRGBA_8888_SkColorType,
41*c8dee2aaSAndroid Build Coastguard Worker                                    kPremul_SkAlphaType),
42*c8dee2aaSAndroid Build Coastguard Worker                  colors,
43*c8dee2aaSAndroid Build Coastguard Worker                  sizeof(colors[0]));
44*c8dee2aaSAndroid Build Coastguard Worker     auto imgy = SkImages::RasterFromPixmapCopy(pmy);
45*c8dee2aaSAndroid Build Coastguard Worker 
46*c8dee2aaSAndroid Build Coastguard Worker     // We draw offscreen and then zoom that up to make the result clear.
47*c8dee2aaSAndroid Build Coastguard Worker     auto surf = canvas->makeSurface(canvas->imageInfo().makeWH(80, 80));
48*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(surf);
49*c8dee2aaSAndroid Build Coastguard Worker     auto* c = surf->getCanvas();
50*c8dee2aaSAndroid Build Coastguard Worker     c->clear(SK_ColorWHITE);
51*c8dee2aaSAndroid Build Coastguard Worker 
52*c8dee2aaSAndroid Build Coastguard Worker     for (bool offset : {false, true}) {
53*c8dee2aaSAndroid Build Coastguard Worker         for (SkFilterMode fm : {SkFilterMode::kNearest, SkFilterMode::kLinear}) {
54*c8dee2aaSAndroid Build Coastguard Worker             SkPaint paint;
55*c8dee2aaSAndroid Build Coastguard Worker 
56*c8dee2aaSAndroid Build Coastguard Worker             // Draw single row image with mirror tiling in x and clamped in y.
57*c8dee2aaSAndroid Build Coastguard Worker             paint.setShader(imgx->makeShader(SkTileMode::kMirror,
58*c8dee2aaSAndroid Build Coastguard Worker                                              SkTileMode::kClamp,
59*c8dee2aaSAndroid Build Coastguard Worker                                              SkSamplingOptions{fm}));
60*c8dee2aaSAndroid Build Coastguard Worker             c->save();
61*c8dee2aaSAndroid Build Coastguard Worker             c->translate(imgx->width(), 0);
62*c8dee2aaSAndroid Build Coastguard Worker             if (offset) {
63*c8dee2aaSAndroid Build Coastguard Worker                 c->translate(0.5, 0);
64*c8dee2aaSAndroid Build Coastguard Worker             }
65*c8dee2aaSAndroid Build Coastguard Worker             c->drawRect(SkRect::MakeXYWH(-imgx->width(), 0, 3*imgx->width(), 5), paint);
66*c8dee2aaSAndroid Build Coastguard Worker             c->restore();
67*c8dee2aaSAndroid Build Coastguard Worker 
68*c8dee2aaSAndroid Build Coastguard Worker             // Draw single column image with mirror tiling in y and clamped in x.
69*c8dee2aaSAndroid Build Coastguard Worker             paint.setShader(imgy->makeShader(SkTileMode::kClamp,
70*c8dee2aaSAndroid Build Coastguard Worker                                              SkTileMode::kMirror,
71*c8dee2aaSAndroid Build Coastguard Worker                                              SkSamplingOptions{fm}));
72*c8dee2aaSAndroid Build Coastguard Worker             c->save();
73*c8dee2aaSAndroid Build Coastguard Worker             c->translate(3*imgx->width() + 3, imgy->height());
74*c8dee2aaSAndroid Build Coastguard Worker             if (offset) {
75*c8dee2aaSAndroid Build Coastguard Worker                 c->translate(0, 0.5);
76*c8dee2aaSAndroid Build Coastguard Worker             }
77*c8dee2aaSAndroid Build Coastguard Worker             c->drawRect(SkRect::MakeXYWH(0, -imgy->height(), 5, 3*imgy->height()), paint);
78*c8dee2aaSAndroid Build Coastguard Worker             c->restore();
79*c8dee2aaSAndroid Build Coastguard Worker 
80*c8dee2aaSAndroid Build Coastguard Worker             c->translate(0, 3*imgy->height() + 3);
81*c8dee2aaSAndroid Build Coastguard Worker         }
82*c8dee2aaSAndroid Build Coastguard Worker     }
83*c8dee2aaSAndroid Build Coastguard Worker 
84*c8dee2aaSAndroid Build Coastguard Worker     canvas->scale(8, 8);
85*c8dee2aaSAndroid Build Coastguard Worker     canvas->drawImage(surf->makeImageSnapshot(), 0, 0);
86*c8dee2aaSAndroid Build Coastguard Worker     return skiagm::DrawResult::kOk;
87*c8dee2aaSAndroid Build Coastguard Worker }
88