• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2022 Google LLC
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 "tests/Test.h"
9 
10 #include "include/core/SkColorSpace.h"
11 #include "include/gpu/graphite/BackendTexture.h"
12 #include "include/gpu/graphite/Context.h"
13 #include "include/gpu/graphite/Image.h"
14 #include "include/gpu/graphite/Recorder.h"
15 #include "include/gpu/graphite/Surface.h"
16 #include "src/core/SkAutoPixmapStorage.h"
17 #include "src/gpu/graphite/Caps.h"
18 #include "src/gpu/graphite/ContextPriv.h"
19 #include "src/gpu/graphite/Surface_Graphite.h"
20 #include "tests/TestUtils.h"
21 #include "tools/ToolUtils.h"
22 
23 using namespace skgpu;
24 using namespace skgpu::graphite;
25 
26 namespace {
27 const SkISize kSize = { 32, 32 };
28 constexpr int kNumMipLevels = 6;
29 
check_solid_pixmap(skiatest::Reporter * reporter,const SkColor4f & expected,const SkPixmap & actual,SkColorType ct,const char * label)30 void check_solid_pixmap(skiatest::Reporter* reporter,
31                         const SkColor4f& expected,
32                         const SkPixmap& actual,
33                         SkColorType ct,
34                         const char* label) {
35     const float kTols[4] = { 0.01f, 0.01f, 0.01f, 0.01f };
36 
37     auto error = std::function<ComparePixmapsErrorReporter>(
38         [reporter, ct, label, expected](int x, int y, const float diffs[4]) {
39             SkASSERT(x >= 0 && y >= 0);
40             ERRORF(reporter, "%s %s - mismatch at %d, %d "
41                              "expected: (%.2f, %.2f, %.2f, %.2f) "
42                              "- diffs: (%.2f, %.2f, %.2f, %.2f)",
43                    ToolUtils::colortype_name(ct), label, x, y,
44                    expected.fR, expected.fG, expected.fB, expected.fA,
45                    diffs[0], diffs[1], diffs[2], diffs[3]);
46         });
47 
48     CheckSolidPixels(expected, actual, kTols, error);
49 }
50 
update_backend_texture(Recorder * recorder,const BackendTexture & backendTex,SkColorType ct,bool withMips,const SkColor4f colors[6])51 void update_backend_texture(Recorder* recorder,
52                             const BackendTexture& backendTex,
53                             SkColorType ct,
54                             bool withMips,
55                             const SkColor4f colors[6]) {
56     SkPixmap pixmaps[6];
57     std::unique_ptr<char[]> memForPixmaps;
58 
59     int numMipLevels = ToolUtils::make_pixmaps(ct, kPremul_SkAlphaType, withMips, colors, pixmaps,
60                                                &memForPixmaps);
61     SkASSERT(numMipLevels == 1 || numMipLevels == kNumMipLevels);
62     SkASSERT(kSize == pixmaps[0].dimensions());
63 
64     recorder->updateBackendTexture(backendTex, pixmaps, numMipLevels);
65 
66 }
67 
create_backend_texture(skiatest::Reporter * reporter,const Caps * caps,Recorder * recorder,SkColorType ct,bool withMips,Renderable renderable,const SkColor4f colors[6])68 BackendTexture create_backend_texture(skiatest::Reporter* reporter,
69                                       const Caps* caps,
70                                       Recorder* recorder,
71                                       SkColorType ct,
72                                       bool withMips,
73                                       Renderable renderable,
74                                       const SkColor4f colors[6]) {
75     Mipmapped mipmapped = withMips ? Mipmapped::kYes : Mipmapped::kNo;
76     TextureInfo info = caps->getDefaultSampledTextureInfo(ct,
77                                                           mipmapped,
78                                                           Protected::kNo,
79                                                           renderable);
80 
81     BackendTexture backendTex = recorder->createBackendTexture(kSize, info);
82     REPORTER_ASSERT(reporter, backendTex.isValid());
83 
84     update_backend_texture(recorder, backendTex, ct, withMips, colors);
85 
86     return backendTex;
87 }
88 
wrap_backend_texture(skiatest::Reporter * reporter,Recorder * recorder,const skgpu::graphite::BackendTexture & backendTex,SkColorType ct,bool withMips)89 sk_sp<SkImage> wrap_backend_texture(skiatest::Reporter* reporter,
90                                     Recorder* recorder,
91                                     const skgpu::graphite::BackendTexture& backendTex,
92                                     SkColorType ct,
93                                     bool withMips) {
94     sk_sp<SkImage> image = SkImages::WrapTexture(recorder,
95                                                  backendTex,
96                                                  ct,
97                                                  kPremul_SkAlphaType,
98                                                  /* colorSpace= */ nullptr);
99     REPORTER_ASSERT(reporter, image);
100     REPORTER_ASSERT(reporter, image->hasMipmaps() == withMips);
101 
102     return image;
103 }
104 
check_levels(skiatest::Reporter * reporter,Context * context,Recorder * recorder,SkImage * image,bool withMips,const SkColor4f colors[6])105 void check_levels(skiatest::Reporter* reporter,
106                   Context* context,
107                   Recorder* recorder,
108                   SkImage* image,
109                   bool withMips,
110                   const SkColor4f colors[6]) {
111     int numLevels = withMips ? kNumMipLevels : 1;
112 
113     SkSamplingOptions sampling = withMips
114                                  ? SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kNearest)
115                                  : SkSamplingOptions(SkFilterMode::kNearest);
116 
117     SkImageInfo surfaceII = SkImageInfo::Make(kSize, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
118     sk_sp<SkSurface> surf = SkSurfaces::RenderTarget(recorder, surfaceII, Mipmapped::kNo);
119     SkCanvas* canvas = surf->getCanvas();
120 
121     for (int i = 0, drawSize = kSize.width(); i < numLevels; ++i, drawSize /= 2) {
122         if (i == 5) {
123             // TODO: Metal currently never draws the top-most mip-level (skbug.com/13792)
124             continue;
125         }
126 
127         SkImageInfo readbackII = SkImageInfo::Make({drawSize, drawSize}, kRGBA_8888_SkColorType,
128                                                    kUnpremul_SkAlphaType);
129         SkAutoPixmapStorage actual;
130         SkAssertResult(actual.tryAlloc(readbackII));
131         actual.erase(SkColors::kTransparent);
132 
133         SkPaint paint;
134         paint.setBlendMode(SkBlendMode::kSrc);
135 
136         canvas->clear(SkColors::kTransparent);
137 
138 #if 0
139         // This option gives greater control over the tilemodes and texture scaling
140         SkMatrix lm;
141         lm.setScale(1.0f / (1 << i), 1.0f / (1 << i));
142 
143         paint.setShader(image->makeShader(SkTileMode::kClamp, SkTileMode::kClamp, sampling, lm));
144         canvas->drawRect(SkRect::MakeWH(drawSize, drawSize), paint);
145 #else
146         canvas->drawImageRect(image, SkRect::MakeWH(drawSize, drawSize), sampling, &paint);
147 #endif
148 
149         if (!surf->readPixels(actual, 0, 0)) {
150             ERRORF(reporter, "readPixels failed");
151             return;
152         }
153 
154         SkString str;
155         str.appendf("mip-level %d", i);
156 
157         check_solid_pixmap(reporter, colors[i], actual, image->colorType(), str.c_str());
158     }
159 }
160 
161 } // anonymous namespace
162 
DEF_GRAPHITE_TEST_FOR_RENDERING_CONTEXTS(UpdateImageBackendTextureTest,reporter,context,CtsEnforcement::kNextRelease)163 DEF_GRAPHITE_TEST_FOR_RENDERING_CONTEXTS(UpdateImageBackendTextureTest, reporter, context,
164                                          CtsEnforcement::kNextRelease) {
165     // TODO: Remove this check once Vulkan supports creating default TexutreInfo from caps and we
166     // implement createBackendTexture.
167     if (context->backend() == BackendApi::kVulkan) {
168         return;
169     }
170 
171     const Caps* caps = context->priv().caps();
172     std::unique_ptr<Recorder> recorder = context->makeRecorder();
173 
174     constexpr SkColor4f kColors[6] = {
175         { 1.0f, 0.0f, 0.0f, 1.0f }, // R
176         { 0.0f, 1.0f, 0.0f, 0.9f }, // G
177         { 0.0f, 0.0f, 1.0f, 0.7f }, // B
178         { 0.0f, 1.0f, 1.0f, 0.5f }, // C
179         { 1.0f, 0.0f, 1.0f, 0.3f }, // M
180         { 1.0f, 1.0f, 0.0f, 0.2f }, // Y
181     };
182 
183     constexpr SkColor4f kColorsNew[6] = {
184         { 1.0f, 1.0f, 0.0f, 0.2f },  // Y
185         { 1.0f, 0.0f, 0.0f, 1.0f },  // R
186         { 0.0f, 1.0f, 0.0f, 0.9f },  // G
187         { 0.0f, 0.0f, 1.0f, 0.7f },  // B
188         { 0.0f, 1.0f, 1.0f, 0.5f },  // C
189         { 1.0f, 0.0f, 1.0f, 0.3f },  // M
190     };
191 
192     // TODO: test more than just RGBA8
193     for (SkColorType ct : { kRGBA_8888_SkColorType }) {
194         for (bool withMips : { true, false }) {
195             for (Renderable renderable : { Renderable::kYes, Renderable::kNo }) {
196 
197                 BackendTexture backendTex = create_backend_texture(reporter, caps, recorder.get(),
198                                                                    ct, withMips, renderable,
199                                                                    kColors);
200 
201                 sk_sp<SkImage> image = wrap_backend_texture(reporter, recorder.get(), backendTex,
202                                                             ct, withMips);
203                 if (!image) {
204                     continue;
205                 }
206 
207                 check_levels(reporter, context, recorder.get(), image.get(), withMips, kColors);
208 
209                 image.reset();
210 
211                 update_backend_texture(recorder.get(), backendTex, ct, withMips, kColorsNew);
212 
213                 image = wrap_backend_texture(reporter, recorder.get(), backendTex, ct, withMips);
214                 if (!image) {
215                     continue;
216                 }
217 
218                 check_levels(reporter, context, recorder.get(), image.get(), withMips, kColorsNew);
219 
220                 image.reset();
221 
222                 recorder->deleteBackendTexture(backendTex);
223             }
224         }
225     }
226 }
227