xref: /aosp_15_r20/external/skia/tests/SpecialImageTest.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker  * Copyright 2016 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 "include/core/SkAlphaType.h"
9*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkBitmap.h"
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkCanvas.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColor.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColorSpace.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColorType.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkImage.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkImageInfo.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPaint.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRect.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRefCnt.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkScalar.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSize.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSurface.h"
22*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSurfaceProps.h"
23*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTypes.h"
24*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/GpuTypes.h"
25*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/GrDirectContext.h"
26*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/SkSurfaceGanesh.h"
27*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkSpecialImage.h"
28*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrColorInfo.h" // IWYU pragma: keep
29*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrSurfaceProxyView.h"
30*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/SkGr.h"
31*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/image/SkSpecialImage_Ganesh.h"
32*c8dee2aaSAndroid Build Coastguard Worker #include "tests/CtsEnforcement.h"
33*c8dee2aaSAndroid Build Coastguard Worker #include "tests/Test.h"
34*c8dee2aaSAndroid Build Coastguard Worker 
35*c8dee2aaSAndroid Build Coastguard Worker #include <utility>
36*c8dee2aaSAndroid Build Coastguard Worker 
37*c8dee2aaSAndroid Build Coastguard Worker class GrRecordingContext;
38*c8dee2aaSAndroid Build Coastguard Worker struct GrContextOptions;
39*c8dee2aaSAndroid Build Coastguard Worker 
40*c8dee2aaSAndroid Build Coastguard Worker // This test creates backing resources exactly sized to [kFullSize x kFullSize].
41*c8dee2aaSAndroid Build Coastguard Worker // It then wraps them in an SkSpecialImage with only the center (red) region being active.
42*c8dee2aaSAndroid Build Coastguard Worker // It then draws the SkSpecialImage to a full sized (all blue) canvas and checks that none
43*c8dee2aaSAndroid Build Coastguard Worker // of the inactive (green) region leaked out.
44*c8dee2aaSAndroid Build Coastguard Worker 
45*c8dee2aaSAndroid Build Coastguard Worker static const int kSmallerSize = 10;
46*c8dee2aaSAndroid Build Coastguard Worker static const int kPad = 3;
47*c8dee2aaSAndroid Build Coastguard Worker static const int kFullSize = kSmallerSize + 2 * kPad;
48*c8dee2aaSAndroid Build Coastguard Worker 
49*c8dee2aaSAndroid Build Coastguard Worker // Create a bitmap with red in the center and green around it
create_bm()50*c8dee2aaSAndroid Build Coastguard Worker static SkBitmap create_bm() {
51*c8dee2aaSAndroid Build Coastguard Worker     SkImageInfo ii = SkImageInfo::Make(kFullSize, kFullSize, kRGBA_8888_SkColorType,
52*c8dee2aaSAndroid Build Coastguard Worker                                        kPremul_SkAlphaType);
53*c8dee2aaSAndroid Build Coastguard Worker 
54*c8dee2aaSAndroid Build Coastguard Worker     SkBitmap bm;
55*c8dee2aaSAndroid Build Coastguard Worker     bm.allocPixels(ii);
56*c8dee2aaSAndroid Build Coastguard Worker 
57*c8dee2aaSAndroid Build Coastguard Worker     SkCanvas temp(bm);
58*c8dee2aaSAndroid Build Coastguard Worker 
59*c8dee2aaSAndroid Build Coastguard Worker     temp.clear(SK_ColorGREEN);
60*c8dee2aaSAndroid Build Coastguard Worker     SkPaint p;
61*c8dee2aaSAndroid Build Coastguard Worker     p.setColor(SK_ColorRED);
62*c8dee2aaSAndroid Build Coastguard Worker     p.setAntiAlias(false);
63*c8dee2aaSAndroid Build Coastguard Worker 
64*c8dee2aaSAndroid Build Coastguard Worker     temp.drawRect(SkRect::MakeXYWH(SkIntToScalar(kPad), SkIntToScalar(kPad),
65*c8dee2aaSAndroid Build Coastguard Worker                                    SkIntToScalar(kSmallerSize), SkIntToScalar(kSmallerSize)),
66*c8dee2aaSAndroid Build Coastguard Worker                   p);
67*c8dee2aaSAndroid Build Coastguard Worker 
68*c8dee2aaSAndroid Build Coastguard Worker     bm.setImmutable();
69*c8dee2aaSAndroid Build Coastguard Worker     return bm;
70*c8dee2aaSAndroid Build Coastguard Worker }
71*c8dee2aaSAndroid Build Coastguard Worker 
72*c8dee2aaSAndroid Build Coastguard Worker // Basic test of the SkSpecialImage public API (e.g., peekTexture, peekPixels & draw)
test_image(const sk_sp<SkSpecialImage> & img,skiatest::Reporter * reporter,GrRecordingContext * rContext,bool isGPUBacked)73*c8dee2aaSAndroid Build Coastguard Worker static void test_image(const sk_sp<SkSpecialImage>& img, skiatest::Reporter* reporter,
74*c8dee2aaSAndroid Build Coastguard Worker                        GrRecordingContext* rContext, bool isGPUBacked) {
75*c8dee2aaSAndroid Build Coastguard Worker     const SkIRect subset = img->subset();
76*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, kPad == subset.left());
77*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, kPad == subset.top());
78*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, kSmallerSize == subset.width());
79*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, kSmallerSize == subset.height());
80*c8dee2aaSAndroid Build Coastguard Worker 
81*c8dee2aaSAndroid Build Coastguard Worker     //--------------
82*c8dee2aaSAndroid Build Coastguard Worker     // Test that isTextureBacked reports the correct backing type
83*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, isGPUBacked == img->isGaneshBacked());
84*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, !img->isGraphiteBacked());
85*c8dee2aaSAndroid Build Coastguard Worker 
86*c8dee2aaSAndroid Build Coastguard Worker     //--------------
87*c8dee2aaSAndroid Build Coastguard Worker     // Test view - only succeeds if it's Ganesh backed
88*c8dee2aaSAndroid Build Coastguard Worker     if (rContext) {
89*c8dee2aaSAndroid Build Coastguard Worker         GrSurfaceProxyView view = SkSpecialImages::AsView(rContext, img);
90*c8dee2aaSAndroid Build Coastguard Worker         REPORTER_ASSERT(reporter, SkToBool(view.asTextureProxy()) == isGPUBacked);
91*c8dee2aaSAndroid Build Coastguard Worker     }
92*c8dee2aaSAndroid Build Coastguard Worker 
93*c8dee2aaSAndroid Build Coastguard Worker     //--------------
94*c8dee2aaSAndroid Build Coastguard Worker     // Test AsBitmap - this only works for raster-backed special images
95*c8dee2aaSAndroid Build Coastguard Worker     if (!img->isGaneshBacked() && !img->isGraphiteBacked()) {
96*c8dee2aaSAndroid Build Coastguard Worker         SkBitmap bitmap;
97*c8dee2aaSAndroid Build Coastguard Worker         REPORTER_ASSERT(reporter, SkSpecialImages::AsBitmap(img.get(), &bitmap));
98*c8dee2aaSAndroid Build Coastguard Worker         REPORTER_ASSERT(reporter, kSmallerSize == bitmap.width());
99*c8dee2aaSAndroid Build Coastguard Worker         REPORTER_ASSERT(reporter, kSmallerSize == bitmap.height());
100*c8dee2aaSAndroid Build Coastguard Worker     } else {
101*c8dee2aaSAndroid Build Coastguard Worker         SkBitmap bitmap;
102*c8dee2aaSAndroid Build Coastguard Worker         REPORTER_ASSERT(reporter, !SkSpecialImages::AsBitmap(img.get(), &bitmap));
103*c8dee2aaSAndroid Build Coastguard Worker     }
104*c8dee2aaSAndroid Build Coastguard Worker 
105*c8dee2aaSAndroid Build Coastguard Worker     //--------------
106*c8dee2aaSAndroid Build Coastguard Worker     // Test that draw restricts itself to the subset
107*c8dee2aaSAndroid Build Coastguard Worker     SkImageInfo imageInfo = SkImageInfo::Make(SkISize::Make(kFullSize, kFullSize),
108*c8dee2aaSAndroid Build Coastguard Worker                                               kN32_SkColorType,
109*c8dee2aaSAndroid Build Coastguard Worker                                               kPremul_SkAlphaType,
110*c8dee2aaSAndroid Build Coastguard Worker                                               sk_ref_sp(img->getColorSpace()));
111*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<SkSurface> surf = isGPUBacked
112*c8dee2aaSAndroid Build Coastguard Worker             ? SkSurfaces::RenderTarget(rContext, skgpu::Budgeted::kNo, imageInfo)
113*c8dee2aaSAndroid Build Coastguard Worker             : SkSurfaces::Raster(imageInfo, {});
114*c8dee2aaSAndroid Build Coastguard Worker 
115*c8dee2aaSAndroid Build Coastguard Worker     SkCanvas* canvas = surf->getCanvas();
116*c8dee2aaSAndroid Build Coastguard Worker 
117*c8dee2aaSAndroid Build Coastguard Worker     canvas->clear(SK_ColorBLUE);
118*c8dee2aaSAndroid Build Coastguard Worker     img->draw(canvas, SkIntToScalar(kPad), SkIntToScalar(kPad));
119*c8dee2aaSAndroid Build Coastguard Worker 
120*c8dee2aaSAndroid Build Coastguard Worker     SkBitmap bm;
121*c8dee2aaSAndroid Build Coastguard Worker     bm.allocN32Pixels(kFullSize, kFullSize, false);
122*c8dee2aaSAndroid Build Coastguard Worker 
123*c8dee2aaSAndroid Build Coastguard Worker     bool result = canvas->readPixels(bm.info(), bm.getPixels(), bm.rowBytes(), 0, 0);
124*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT_RELEASE(result);
125*c8dee2aaSAndroid Build Coastguard Worker 
126*c8dee2aaSAndroid Build Coastguard Worker     // Only the center (red) portion should've been drawn into the canvas
127*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, SK_ColorBLUE == bm.getColor(kPad-1, kPad-1));
128*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, SK_ColorRED  == bm.getColor(kPad, kPad));
129*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, SK_ColorRED  == bm.getColor(kSmallerSize+kPad-1,
130*c8dee2aaSAndroid Build Coastguard Worker                                                           kSmallerSize+kPad-1));
131*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, SK_ColorBLUE == bm.getColor(kSmallerSize+kPad,
132*c8dee2aaSAndroid Build Coastguard Worker                                                           kSmallerSize+kPad));
133*c8dee2aaSAndroid Build Coastguard Worker }
134*c8dee2aaSAndroid Build Coastguard Worker 
DEF_TEST(SpecialImage_Raster,reporter)135*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(SpecialImage_Raster, reporter) {
136*c8dee2aaSAndroid Build Coastguard Worker     SkBitmap bm = create_bm();
137*c8dee2aaSAndroid Build Coastguard Worker 
138*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<SkSpecialImage> fullSImage(SkSpecialImages::MakeFromRaster(
139*c8dee2aaSAndroid Build Coastguard Worker             SkIRect::MakeWH(kFullSize, kFullSize), bm, SkSurfaceProps()));
140*c8dee2aaSAndroid Build Coastguard Worker 
141*c8dee2aaSAndroid Build Coastguard Worker     const SkIRect& subset = SkIRect::MakeXYWH(kPad, kPad, kSmallerSize, kSmallerSize);
142*c8dee2aaSAndroid Build Coastguard Worker 
143*c8dee2aaSAndroid Build Coastguard Worker     {
144*c8dee2aaSAndroid Build Coastguard Worker         sk_sp<SkSpecialImage> subSImg1(
145*c8dee2aaSAndroid Build Coastguard Worker                 SkSpecialImages::MakeFromRaster(subset, bm, SkSurfaceProps()));
146*c8dee2aaSAndroid Build Coastguard Worker         test_image(subSImg1, reporter, nullptr, false);
147*c8dee2aaSAndroid Build Coastguard Worker     }
148*c8dee2aaSAndroid Build Coastguard Worker 
149*c8dee2aaSAndroid Build Coastguard Worker     {
150*c8dee2aaSAndroid Build Coastguard Worker         sk_sp<SkSpecialImage> subSImg2(fullSImage->makeSubset(subset));
151*c8dee2aaSAndroid Build Coastguard Worker         test_image(subSImg2, reporter, nullptr, false);
152*c8dee2aaSAndroid Build Coastguard Worker     }
153*c8dee2aaSAndroid Build Coastguard Worker }
154*c8dee2aaSAndroid Build Coastguard Worker 
test_specialimage_image(skiatest::Reporter * reporter)155*c8dee2aaSAndroid Build Coastguard Worker static void test_specialimage_image(skiatest::Reporter* reporter) {
156*c8dee2aaSAndroid Build Coastguard Worker     SkBitmap bm = create_bm();
157*c8dee2aaSAndroid Build Coastguard Worker 
158*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<SkImage> fullImage(bm.asImage());
159*c8dee2aaSAndroid Build Coastguard Worker 
160*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<SkSpecialImage> fullSImage(SkSpecialImages::MakeFromRaster(
161*c8dee2aaSAndroid Build Coastguard Worker             SkIRect::MakeWH(kFullSize, kFullSize), fullImage, SkSurfaceProps()));
162*c8dee2aaSAndroid Build Coastguard Worker 
163*c8dee2aaSAndroid Build Coastguard Worker     const SkIRect& subset = SkIRect::MakeXYWH(kPad, kPad, kSmallerSize, kSmallerSize);
164*c8dee2aaSAndroid Build Coastguard Worker 
165*c8dee2aaSAndroid Build Coastguard Worker     {
166*c8dee2aaSAndroid Build Coastguard Worker         sk_sp<SkSpecialImage> subSImg1(
167*c8dee2aaSAndroid Build Coastguard Worker                 SkSpecialImages::MakeFromRaster(subset, fullImage, SkSurfaceProps()));
168*c8dee2aaSAndroid Build Coastguard Worker         test_image(subSImg1, reporter, nullptr, false);
169*c8dee2aaSAndroid Build Coastguard Worker     }
170*c8dee2aaSAndroid Build Coastguard Worker 
171*c8dee2aaSAndroid Build Coastguard Worker     {
172*c8dee2aaSAndroid Build Coastguard Worker         sk_sp<SkSpecialImage> subSImg2(fullSImage->makeSubset(subset));
173*c8dee2aaSAndroid Build Coastguard Worker         test_image(subSImg2, reporter, nullptr, false);
174*c8dee2aaSAndroid Build Coastguard Worker     }
175*c8dee2aaSAndroid Build Coastguard Worker }
176*c8dee2aaSAndroid Build Coastguard Worker 
DEF_TEST(SpecialImage_Image_Legacy,reporter)177*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(SpecialImage_Image_Legacy, reporter) {
178*c8dee2aaSAndroid Build Coastguard Worker     test_specialimage_image(reporter);
179*c8dee2aaSAndroid Build Coastguard Worker }
180*c8dee2aaSAndroid Build Coastguard Worker 
DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(SpecialImage_Gpu,reporter,ctxInfo,CtsEnforcement::kApiLevel_T)181*c8dee2aaSAndroid Build Coastguard Worker DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(SpecialImage_Gpu,
182*c8dee2aaSAndroid Build Coastguard Worker                                        reporter,
183*c8dee2aaSAndroid Build Coastguard Worker                                        ctxInfo,
184*c8dee2aaSAndroid Build Coastguard Worker                                        CtsEnforcement::kApiLevel_T) {
185*c8dee2aaSAndroid Build Coastguard Worker     auto context = ctxInfo.directContext();
186*c8dee2aaSAndroid Build Coastguard Worker     SkBitmap bm = create_bm();
187*c8dee2aaSAndroid Build Coastguard Worker     auto [view, ct] = GrMakeUncachedBitmapProxyView(context, bm);
188*c8dee2aaSAndroid Build Coastguard Worker     if (!view) {
189*c8dee2aaSAndroid Build Coastguard Worker         return;
190*c8dee2aaSAndroid Build Coastguard Worker     }
191*c8dee2aaSAndroid Build Coastguard Worker 
192*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<SkSpecialImage> fullSImg =
193*c8dee2aaSAndroid Build Coastguard Worker             SkSpecialImages::MakeDeferredFromGpu(context,
194*c8dee2aaSAndroid Build Coastguard Worker                                                  SkIRect::MakeWH(kFullSize, kFullSize),
195*c8dee2aaSAndroid Build Coastguard Worker                                                  kNeedNewImageUniqueID_SpecialImage,
196*c8dee2aaSAndroid Build Coastguard Worker                                                  view,
197*c8dee2aaSAndroid Build Coastguard Worker                                                  {ct, kPremul_SkAlphaType, nullptr},
198*c8dee2aaSAndroid Build Coastguard Worker                                                  SkSurfaceProps());
199*c8dee2aaSAndroid Build Coastguard Worker 
200*c8dee2aaSAndroid Build Coastguard Worker     const SkIRect& subset = SkIRect::MakeXYWH(kPad, kPad, kSmallerSize, kSmallerSize);
201*c8dee2aaSAndroid Build Coastguard Worker 
202*c8dee2aaSAndroid Build Coastguard Worker     {
203*c8dee2aaSAndroid Build Coastguard Worker         sk_sp<SkSpecialImage> subSImg1 =
204*c8dee2aaSAndroid Build Coastguard Worker                 SkSpecialImages::MakeDeferredFromGpu(context,
205*c8dee2aaSAndroid Build Coastguard Worker                                                      subset,
206*c8dee2aaSAndroid Build Coastguard Worker                                                      kNeedNewImageUniqueID_SpecialImage,
207*c8dee2aaSAndroid Build Coastguard Worker                                                      std::move(view),
208*c8dee2aaSAndroid Build Coastguard Worker                                                      {ct, kPremul_SkAlphaType, nullptr},
209*c8dee2aaSAndroid Build Coastguard Worker                                                      SkSurfaceProps());
210*c8dee2aaSAndroid Build Coastguard Worker         test_image(subSImg1, reporter, context, true);
211*c8dee2aaSAndroid Build Coastguard Worker     }
212*c8dee2aaSAndroid Build Coastguard Worker 
213*c8dee2aaSAndroid Build Coastguard Worker     {
214*c8dee2aaSAndroid Build Coastguard Worker         sk_sp<SkSpecialImage> subSImg2 = fullSImg->makeSubset(subset);
215*c8dee2aaSAndroid Build Coastguard Worker         test_image(subSImg2, reporter, context, true);
216*c8dee2aaSAndroid Build Coastguard Worker     }
217*c8dee2aaSAndroid Build Coastguard Worker }
218