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