xref: /aosp_15_r20/external/skia/tests/CompressedBackendAllocationTest.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker  * Copyright 2019 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/SkBlendMode.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/SkSamplingOptions.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSize.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkString.h"
22*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSurface.h"
23*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTextureCompressionType.h"
24*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTypes.h"
25*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/GpuTypes.h"
26*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/GrBackendSurface.h"
27*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/GrDirectContext.h"
28*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/GrTypes.h"
29*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/SkImageGanesh.h"
30*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/SkSurfaceGanesh.h"
31*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkTArray.h"
32*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/gpu/ganesh/GrTypesPriv.h"
33*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkAutoPixmapStorage.h"
34*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkCompressedDataUtils.h"
35*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkMipmap.h"
36*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/DataUtils.h"
37*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/GpuTypesPriv.h"
38*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrBackendUtils.h"
39*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrCaps.h"
40*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrDataUtils.h"
41*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrDirectContextPriv.h"
42*c8dee2aaSAndroid Build Coastguard Worker #include "tests/CtsEnforcement.h"
43*c8dee2aaSAndroid Build Coastguard Worker #include "tests/Test.h"
44*c8dee2aaSAndroid Build Coastguard Worker #include "tests/TestUtils.h"
45*c8dee2aaSAndroid Build Coastguard Worker 
46*c8dee2aaSAndroid Build Coastguard Worker #include <algorithm>
47*c8dee2aaSAndroid Build Coastguard Worker #include <cstddef>
48*c8dee2aaSAndroid Build Coastguard Worker #include <functional>
49*c8dee2aaSAndroid Build Coastguard Worker #include <initializer_list>
50*c8dee2aaSAndroid Build Coastguard Worker #include <memory>
51*c8dee2aaSAndroid Build Coastguard Worker #include <utility>
52*c8dee2aaSAndroid Build Coastguard Worker 
53*c8dee2aaSAndroid Build Coastguard Worker using namespace skia_private;
54*c8dee2aaSAndroid Build Coastguard Worker 
55*c8dee2aaSAndroid Build Coastguard Worker class GrRecordingContext;
56*c8dee2aaSAndroid Build Coastguard Worker class SkPixmap;
57*c8dee2aaSAndroid Build Coastguard Worker struct GrContextOptions;
58*c8dee2aaSAndroid Build Coastguard Worker 
59*c8dee2aaSAndroid Build Coastguard Worker // Just verify that 'actual' is entirely 'expected'
check_solid_pixmap(skiatest::Reporter * reporter,const SkColor4f & expected,const SkPixmap & actual,const char * label0,const char * label1,const char * label2)60*c8dee2aaSAndroid Build Coastguard Worker static void check_solid_pixmap(skiatest::Reporter* reporter,
61*c8dee2aaSAndroid Build Coastguard Worker                                const SkColor4f& expected, const SkPixmap& actual,
62*c8dee2aaSAndroid Build Coastguard Worker                                const char* label0, const char* label1, const char* label2) {
63*c8dee2aaSAndroid Build Coastguard Worker     const float tols[4] = { 0.01f, 0.01f, 0.01f, 0.01f };
64*c8dee2aaSAndroid Build Coastguard Worker 
65*c8dee2aaSAndroid Build Coastguard Worker     auto error = std::function<ComparePixmapsErrorReporter>(
66*c8dee2aaSAndroid Build Coastguard Worker         [reporter, label0, label1, label2](int x, int y, const float diffs[4]) {
67*c8dee2aaSAndroid Build Coastguard Worker             SkASSERT(x >= 0 && y >= 0);
68*c8dee2aaSAndroid Build Coastguard Worker             ERRORF(reporter, "%s %s %s - mismatch at %d, %d (%f, %f, %f %f)",
69*c8dee2aaSAndroid Build Coastguard Worker                    label0, label1, label2, x, y,
70*c8dee2aaSAndroid Build Coastguard Worker                    diffs[0], diffs[1], diffs[2], diffs[3]);
71*c8dee2aaSAndroid Build Coastguard Worker         });
72*c8dee2aaSAndroid Build Coastguard Worker 
73*c8dee2aaSAndroid Build Coastguard Worker     CheckSolidPixels(expected, actual, tols, error);
74*c8dee2aaSAndroid Build Coastguard Worker }
75*c8dee2aaSAndroid Build Coastguard Worker 
76*c8dee2aaSAndroid Build Coastguard Worker // Create an SkImage to wrap 'backendTex'
create_image(GrDirectContext * dContext,const GrBackendTexture & backendTex)77*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> create_image(GrDirectContext* dContext, const GrBackendTexture& backendTex) {
78*c8dee2aaSAndroid Build Coastguard Worker     SkTextureCompressionType compression =
79*c8dee2aaSAndroid Build Coastguard Worker             GrBackendFormatToCompressionType(backendTex.getBackendFormat());
80*c8dee2aaSAndroid Build Coastguard Worker 
81*c8dee2aaSAndroid Build Coastguard Worker     SkAlphaType at = SkTextureCompressionTypeIsOpaque(compression) ? kOpaque_SkAlphaType
82*c8dee2aaSAndroid Build Coastguard Worker                                                             : kPremul_SkAlphaType;
83*c8dee2aaSAndroid Build Coastguard Worker 
84*c8dee2aaSAndroid Build Coastguard Worker     return SkImages::TextureFromCompressedTexture(
85*c8dee2aaSAndroid Build Coastguard Worker             dContext, backendTex, kTopLeft_GrSurfaceOrigin, at, nullptr);
86*c8dee2aaSAndroid Build Coastguard Worker }
87*c8dee2aaSAndroid Build Coastguard Worker 
88*c8dee2aaSAndroid Build Coastguard Worker // Draw the compressed backend texture (wrapped in an SkImage) into an RGBA surface, attempting
89*c8dee2aaSAndroid Build Coastguard Worker // to access all the mipMap levels.
check_compressed_mipmaps(GrRecordingContext * rContext,sk_sp<SkImage> img,SkTextureCompressionType compressionType,const SkColor4f expectedColors[6],skgpu::Mipmapped mipmapped,skiatest::Reporter * reporter,const char * label)90*c8dee2aaSAndroid Build Coastguard Worker static void check_compressed_mipmaps(GrRecordingContext* rContext,
91*c8dee2aaSAndroid Build Coastguard Worker                                      sk_sp<SkImage> img,
92*c8dee2aaSAndroid Build Coastguard Worker                                      SkTextureCompressionType compressionType,
93*c8dee2aaSAndroid Build Coastguard Worker                                      const SkColor4f expectedColors[6],
94*c8dee2aaSAndroid Build Coastguard Worker                                      skgpu::Mipmapped mipmapped,
95*c8dee2aaSAndroid Build Coastguard Worker                                      skiatest::Reporter* reporter,
96*c8dee2aaSAndroid Build Coastguard Worker                                      const char* label) {
97*c8dee2aaSAndroid Build Coastguard Worker     SkImageInfo readbackSurfaceII = SkImageInfo::Make(32, 32, kRGBA_8888_SkColorType,
98*c8dee2aaSAndroid Build Coastguard Worker                                                       kPremul_SkAlphaType);
99*c8dee2aaSAndroid Build Coastguard Worker 
100*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<SkSurface> surf = SkSurfaces::RenderTarget(rContext,
101*c8dee2aaSAndroid Build Coastguard Worker                                                      skgpu::Budgeted::kNo,
102*c8dee2aaSAndroid Build Coastguard Worker                                                      readbackSurfaceII,
103*c8dee2aaSAndroid Build Coastguard Worker                                                      1,
104*c8dee2aaSAndroid Build Coastguard Worker                                                      kTopLeft_GrSurfaceOrigin,
105*c8dee2aaSAndroid Build Coastguard Worker                                                      nullptr);
106*c8dee2aaSAndroid Build Coastguard Worker     if (!surf) {
107*c8dee2aaSAndroid Build Coastguard Worker         return;
108*c8dee2aaSAndroid Build Coastguard Worker     }
109*c8dee2aaSAndroid Build Coastguard Worker 
110*c8dee2aaSAndroid Build Coastguard Worker     SkCanvas* canvas = surf->getCanvas();
111*c8dee2aaSAndroid Build Coastguard Worker 
112*c8dee2aaSAndroid Build Coastguard Worker     // When MIP map sampling is biased (as it is by default), hitting a level exactly using
113*c8dee2aaSAndroid Build Coastguard Worker     // SkMipmap::kLinear is difficult so we use kNearest.
114*c8dee2aaSAndroid Build Coastguard Worker     const SkSamplingOptions sampling(SkFilterMode::kLinear,
115*c8dee2aaSAndroid Build Coastguard Worker                                      SkMipmapMode::kNearest);
116*c8dee2aaSAndroid Build Coastguard Worker     SkPaint p;
117*c8dee2aaSAndroid Build Coastguard Worker     p.setBlendMode(SkBlendMode::kSrc);
118*c8dee2aaSAndroid Build Coastguard Worker 
119*c8dee2aaSAndroid Build Coastguard Worker     int numMipLevels = 1;
120*c8dee2aaSAndroid Build Coastguard Worker     if (mipmapped == skgpu::Mipmapped::kYes) {
121*c8dee2aaSAndroid Build Coastguard Worker         numMipLevels = SkMipmap::ComputeLevelCount(32, 32)+1;
122*c8dee2aaSAndroid Build Coastguard Worker     }
123*c8dee2aaSAndroid Build Coastguard Worker 
124*c8dee2aaSAndroid Build Coastguard Worker     for (int i = 0, rectSize = 32; i < numMipLevels; ++i, rectSize /= 2) {
125*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(rectSize >= 1);
126*c8dee2aaSAndroid Build Coastguard Worker 
127*c8dee2aaSAndroid Build Coastguard Worker         canvas->clear(SK_ColorTRANSPARENT);
128*c8dee2aaSAndroid Build Coastguard Worker 
129*c8dee2aaSAndroid Build Coastguard Worker         SkRect r = SkRect::MakeWH(rectSize, rectSize);
130*c8dee2aaSAndroid Build Coastguard Worker         canvas->drawImageRect(img, r, sampling, &p);
131*c8dee2aaSAndroid Build Coastguard Worker 
132*c8dee2aaSAndroid Build Coastguard Worker         SkImageInfo readbackII = SkImageInfo::Make(rectSize, rectSize,
133*c8dee2aaSAndroid Build Coastguard Worker                                                    kRGBA_8888_SkColorType,
134*c8dee2aaSAndroid Build Coastguard Worker                                                    kUnpremul_SkAlphaType);
135*c8dee2aaSAndroid Build Coastguard Worker         SkAutoPixmapStorage actual2;
136*c8dee2aaSAndroid Build Coastguard Worker         SkAssertResult(actual2.tryAlloc(readbackII));
137*c8dee2aaSAndroid Build Coastguard Worker         actual2.erase(SkColors::kTransparent);
138*c8dee2aaSAndroid Build Coastguard Worker 
139*c8dee2aaSAndroid Build Coastguard Worker         bool result = surf->readPixels(actual2, 0, 0);
140*c8dee2aaSAndroid Build Coastguard Worker         REPORTER_ASSERT(reporter, result);
141*c8dee2aaSAndroid Build Coastguard Worker 
142*c8dee2aaSAndroid Build Coastguard Worker         SkString str;
143*c8dee2aaSAndroid Build Coastguard Worker         str.appendf("mip-level %d", i);
144*c8dee2aaSAndroid Build Coastguard Worker 
145*c8dee2aaSAndroid Build Coastguard Worker         check_solid_pixmap(reporter, expectedColors[i], actual2,
146*c8dee2aaSAndroid Build Coastguard Worker                            skgpu::CompressionTypeToStr(compressionType), label, str.c_str());
147*c8dee2aaSAndroid Build Coastguard Worker     }
148*c8dee2aaSAndroid Build Coastguard Worker }
149*c8dee2aaSAndroid Build Coastguard Worker 
150*c8dee2aaSAndroid Build Coastguard Worker // Verify that we can readback from a compressed texture
check_readback(GrDirectContext * dContext,sk_sp<SkImage> img,SkTextureCompressionType compressionType,const SkColor4f & expectedColor,skiatest::Reporter * reporter,const char * label)151*c8dee2aaSAndroid Build Coastguard Worker static void check_readback(GrDirectContext* dContext, sk_sp<SkImage> img,
152*c8dee2aaSAndroid Build Coastguard Worker                            SkTextureCompressionType compressionType,
153*c8dee2aaSAndroid Build Coastguard Worker                            const SkColor4f& expectedColor,
154*c8dee2aaSAndroid Build Coastguard Worker                            skiatest::Reporter* reporter, const char* label) {
155*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_BUILD_FOR_IOS
156*c8dee2aaSAndroid Build Coastguard Worker     // reading back ETC2 is broken on Metal/iOS (skbug.com/9839)
157*c8dee2aaSAndroid Build Coastguard Worker     if (dContext->backend() == GrBackendApi::kMetal) {
158*c8dee2aaSAndroid Build Coastguard Worker       return;
159*c8dee2aaSAndroid Build Coastguard Worker     }
160*c8dee2aaSAndroid Build Coastguard Worker #endif
161*c8dee2aaSAndroid Build Coastguard Worker 
162*c8dee2aaSAndroid Build Coastguard Worker     SkAutoPixmapStorage actual;
163*c8dee2aaSAndroid Build Coastguard Worker 
164*c8dee2aaSAndroid Build Coastguard Worker     SkImageInfo readBackII = SkImageInfo::Make(img->width(), img->height(),
165*c8dee2aaSAndroid Build Coastguard Worker                                                kRGBA_8888_SkColorType,
166*c8dee2aaSAndroid Build Coastguard Worker                                                kUnpremul_SkAlphaType);
167*c8dee2aaSAndroid Build Coastguard Worker 
168*c8dee2aaSAndroid Build Coastguard Worker     SkAssertResult(actual.tryAlloc(readBackII));
169*c8dee2aaSAndroid Build Coastguard Worker     actual.erase(SkColors::kTransparent);
170*c8dee2aaSAndroid Build Coastguard Worker 
171*c8dee2aaSAndroid Build Coastguard Worker     bool result = img->readPixels(dContext, actual, 0, 0);
172*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, result);
173*c8dee2aaSAndroid Build Coastguard Worker 
174*c8dee2aaSAndroid Build Coastguard Worker     check_solid_pixmap(reporter, expectedColor, actual,
175*c8dee2aaSAndroid Build Coastguard Worker                        skgpu::CompressionTypeToStr(compressionType), label, "");
176*c8dee2aaSAndroid Build Coastguard Worker }
177*c8dee2aaSAndroid Build Coastguard Worker 
178*c8dee2aaSAndroid Build Coastguard Worker // Test initialization of compressed GrBackendTextures to a specific color
test_compressed_color_init(GrDirectContext * dContext,skiatest::Reporter * reporter,std::function<GrBackendTexture (GrDirectContext *,const SkColor4f &,skgpu::Mipmapped)> create,const SkColor4f & color,SkTextureCompressionType compression,skgpu::Mipmapped mipmapped)179*c8dee2aaSAndroid Build Coastguard Worker static void test_compressed_color_init(
180*c8dee2aaSAndroid Build Coastguard Worker         GrDirectContext* dContext,
181*c8dee2aaSAndroid Build Coastguard Worker         skiatest::Reporter* reporter,
182*c8dee2aaSAndroid Build Coastguard Worker         std::function<GrBackendTexture(GrDirectContext*, const SkColor4f&, skgpu::Mipmapped)>
183*c8dee2aaSAndroid Build Coastguard Worker                 create,
184*c8dee2aaSAndroid Build Coastguard Worker         const SkColor4f& color,
185*c8dee2aaSAndroid Build Coastguard Worker         SkTextureCompressionType compression,
186*c8dee2aaSAndroid Build Coastguard Worker         skgpu::Mipmapped mipmapped) {
187*c8dee2aaSAndroid Build Coastguard Worker     GrBackendTexture backendTex = create(dContext, color, mipmapped);
188*c8dee2aaSAndroid Build Coastguard Worker     if (!backendTex.isValid()) {
189*c8dee2aaSAndroid Build Coastguard Worker         return;
190*c8dee2aaSAndroid Build Coastguard Worker     }
191*c8dee2aaSAndroid Build Coastguard Worker 
192*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<SkImage> img = create_image(dContext, backendTex);
193*c8dee2aaSAndroid Build Coastguard Worker     if (!img) {
194*c8dee2aaSAndroid Build Coastguard Worker         return;
195*c8dee2aaSAndroid Build Coastguard Worker     }
196*c8dee2aaSAndroid Build Coastguard Worker 
197*c8dee2aaSAndroid Build Coastguard Worker     SkColor4f expectedColors[6] = { color, color, color, color, color, color };
198*c8dee2aaSAndroid Build Coastguard Worker 
199*c8dee2aaSAndroid Build Coastguard Worker     check_compressed_mipmaps(dContext, img, compression, expectedColors, mipmapped,
200*c8dee2aaSAndroid Build Coastguard Worker                              reporter, "colorinit");
201*c8dee2aaSAndroid Build Coastguard Worker     check_readback(dContext, img, compression, color, reporter, "solid readback");
202*c8dee2aaSAndroid Build Coastguard Worker 
203*c8dee2aaSAndroid Build Coastguard Worker     SkColor4f newColor;
204*c8dee2aaSAndroid Build Coastguard Worker     newColor.fR = color.fB;
205*c8dee2aaSAndroid Build Coastguard Worker     newColor.fG = color.fR;
206*c8dee2aaSAndroid Build Coastguard Worker     newColor.fB = color.fG;
207*c8dee2aaSAndroid Build Coastguard Worker     newColor.fA = color.fA;
208*c8dee2aaSAndroid Build Coastguard Worker 
209*c8dee2aaSAndroid Build Coastguard Worker     bool result = dContext->updateCompressedBackendTexture(backendTex, newColor, nullptr, nullptr);
210*c8dee2aaSAndroid Build Coastguard Worker     // Since we were able to create the compressed texture we should be able to update it.
211*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, result);
212*c8dee2aaSAndroid Build Coastguard Worker 
213*c8dee2aaSAndroid Build Coastguard Worker     SkColor4f expectedNewColors[6] = {newColor, newColor, newColor, newColor, newColor, newColor};
214*c8dee2aaSAndroid Build Coastguard Worker 
215*c8dee2aaSAndroid Build Coastguard Worker     check_compressed_mipmaps(dContext, img, compression, expectedNewColors, mipmapped, reporter,
216*c8dee2aaSAndroid Build Coastguard Worker                              "colorinit");
217*c8dee2aaSAndroid Build Coastguard Worker     check_readback(dContext, std::move(img), compression, newColor, reporter, "solid readback");
218*c8dee2aaSAndroid Build Coastguard Worker 
219*c8dee2aaSAndroid Build Coastguard Worker     dContext->deleteBackendTexture(backendTex);
220*c8dee2aaSAndroid Build Coastguard Worker }
221*c8dee2aaSAndroid Build Coastguard Worker 
222*c8dee2aaSAndroid Build Coastguard Worker // Create compressed data pulling the color for each mipmap level from 'levelColors'.
make_compressed_data(SkTextureCompressionType compression,SkColor4f levelColors[6],skgpu::Mipmapped mipmapped)223*c8dee2aaSAndroid Build Coastguard Worker static std::unique_ptr<const char[]> make_compressed_data(SkTextureCompressionType compression,
224*c8dee2aaSAndroid Build Coastguard Worker                                                           SkColor4f levelColors[6],
225*c8dee2aaSAndroid Build Coastguard Worker                                                           skgpu::Mipmapped mipmapped) {
226*c8dee2aaSAndroid Build Coastguard Worker     SkISize dimensions { 32, 32 };
227*c8dee2aaSAndroid Build Coastguard Worker 
228*c8dee2aaSAndroid Build Coastguard Worker     int numMipLevels = 1;
229*c8dee2aaSAndroid Build Coastguard Worker     if (mipmapped == skgpu::Mipmapped::kYes) {
230*c8dee2aaSAndroid Build Coastguard Worker         numMipLevels = SkMipmap::ComputeLevelCount(dimensions.width(), dimensions.height()) + 1;
231*c8dee2aaSAndroid Build Coastguard Worker     }
232*c8dee2aaSAndroid Build Coastguard Worker 
233*c8dee2aaSAndroid Build Coastguard Worker     TArray<size_t> mipMapOffsets(numMipLevels);
234*c8dee2aaSAndroid Build Coastguard Worker 
235*c8dee2aaSAndroid Build Coastguard Worker     size_t dataSize = SkCompressedDataSize(
236*c8dee2aaSAndroid Build Coastguard Worker             compression, dimensions, &mipMapOffsets, mipmapped == skgpu::Mipmapped::kYes);
237*c8dee2aaSAndroid Build Coastguard Worker     char* data = new char[dataSize];
238*c8dee2aaSAndroid Build Coastguard Worker 
239*c8dee2aaSAndroid Build Coastguard Worker     for (int level = 0; level < numMipLevels; ++level) {
240*c8dee2aaSAndroid Build Coastguard Worker         // We have to do this a level at a time bc we might have a different color for
241*c8dee2aaSAndroid Build Coastguard Worker         // each level
242*c8dee2aaSAndroid Build Coastguard Worker         skgpu::FillInCompressedData(compression,
243*c8dee2aaSAndroid Build Coastguard Worker                                     dimensions,
244*c8dee2aaSAndroid Build Coastguard Worker                                     skgpu::Mipmapped::kNo,
245*c8dee2aaSAndroid Build Coastguard Worker                                     &data[mipMapOffsets[level]],
246*c8dee2aaSAndroid Build Coastguard Worker                                     levelColors[level]);
247*c8dee2aaSAndroid Build Coastguard Worker 
248*c8dee2aaSAndroid Build Coastguard Worker         dimensions = {std::max(1, dimensions.width() /2), std::max(1, dimensions.height()/2)};
249*c8dee2aaSAndroid Build Coastguard Worker     }
250*c8dee2aaSAndroid Build Coastguard Worker 
251*c8dee2aaSAndroid Build Coastguard Worker     return std::unique_ptr<const char[]>(data);
252*c8dee2aaSAndroid Build Coastguard Worker }
253*c8dee2aaSAndroid Build Coastguard Worker 
254*c8dee2aaSAndroid Build Coastguard Worker // Verify that we can initialize a compressed backend texture with data (esp.
255*c8dee2aaSAndroid Build Coastguard Worker // the mipmap levels).
test_compressed_data_init(GrDirectContext * dContext,skiatest::Reporter * reporter,std::function<GrBackendTexture (GrDirectContext *,const char * data,size_t dataSize,skgpu::Mipmapped)> create,SkTextureCompressionType compression,skgpu::Mipmapped mipmapped)256*c8dee2aaSAndroid Build Coastguard Worker static void test_compressed_data_init(
257*c8dee2aaSAndroid Build Coastguard Worker         GrDirectContext* dContext,
258*c8dee2aaSAndroid Build Coastguard Worker         skiatest::Reporter* reporter,
259*c8dee2aaSAndroid Build Coastguard Worker         std::function<GrBackendTexture(
260*c8dee2aaSAndroid Build Coastguard Worker                 GrDirectContext*, const char* data, size_t dataSize, skgpu::Mipmapped)> create,
261*c8dee2aaSAndroid Build Coastguard Worker         SkTextureCompressionType compression,
262*c8dee2aaSAndroid Build Coastguard Worker         skgpu::Mipmapped mipmapped) {
263*c8dee2aaSAndroid Build Coastguard Worker     SkColor4f expectedColors[6] = {
264*c8dee2aaSAndroid Build Coastguard Worker         { 1.0f, 0.0f, 0.0f, 1.0f }, // R
265*c8dee2aaSAndroid Build Coastguard Worker         { 0.0f, 1.0f, 0.0f, 1.0f }, // G
266*c8dee2aaSAndroid Build Coastguard Worker         { 0.0f, 0.0f, 1.0f, 1.0f }, // B
267*c8dee2aaSAndroid Build Coastguard Worker         { 0.0f, 1.0f, 1.0f, 1.0f }, // C
268*c8dee2aaSAndroid Build Coastguard Worker         { 1.0f, 0.0f, 1.0f, 1.0f }, // M
269*c8dee2aaSAndroid Build Coastguard Worker         { 1.0f, 1.0f, 0.0f, 1.0f }, // Y
270*c8dee2aaSAndroid Build Coastguard Worker     };
271*c8dee2aaSAndroid Build Coastguard Worker 
272*c8dee2aaSAndroid Build Coastguard Worker     std::unique_ptr<const char[]> data(make_compressed_data(compression, expectedColors,
273*c8dee2aaSAndroid Build Coastguard Worker                                                             mipmapped));
274*c8dee2aaSAndroid Build Coastguard Worker     size_t dataSize = SkCompressedDataSize(
275*c8dee2aaSAndroid Build Coastguard Worker             compression, {32, 32}, nullptr, mipmapped == skgpu::Mipmapped::kYes);
276*c8dee2aaSAndroid Build Coastguard Worker 
277*c8dee2aaSAndroid Build Coastguard Worker     GrBackendTexture backendTex = create(dContext, data.get(), dataSize, mipmapped);
278*c8dee2aaSAndroid Build Coastguard Worker     if (!backendTex.isValid()) {
279*c8dee2aaSAndroid Build Coastguard Worker         return;
280*c8dee2aaSAndroid Build Coastguard Worker     }
281*c8dee2aaSAndroid Build Coastguard Worker 
282*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<SkImage> img = create_image(dContext, backendTex);
283*c8dee2aaSAndroid Build Coastguard Worker     if (!img) {
284*c8dee2aaSAndroid Build Coastguard Worker         return;
285*c8dee2aaSAndroid Build Coastguard Worker     }
286*c8dee2aaSAndroid Build Coastguard Worker 
287*c8dee2aaSAndroid Build Coastguard Worker     check_compressed_mipmaps(dContext, img, compression, expectedColors,
288*c8dee2aaSAndroid Build Coastguard Worker                              mipmapped, reporter, "pixmap");
289*c8dee2aaSAndroid Build Coastguard Worker     check_readback(dContext, img, compression, expectedColors[0], reporter, "data readback");
290*c8dee2aaSAndroid Build Coastguard Worker 
291*c8dee2aaSAndroid Build Coastguard Worker     SkColor4f expectedColorsNew[6] = {
292*c8dee2aaSAndroid Build Coastguard Worker         {1.0f, 1.0f, 0.0f, 1.0f},  // Y
293*c8dee2aaSAndroid Build Coastguard Worker         {1.0f, 0.0f, 0.0f, 1.0f},  // R
294*c8dee2aaSAndroid Build Coastguard Worker         {0.0f, 1.0f, 0.0f, 1.0f},  // G
295*c8dee2aaSAndroid Build Coastguard Worker         {0.0f, 0.0f, 1.0f, 1.0f},  // B
296*c8dee2aaSAndroid Build Coastguard Worker         {0.0f, 1.0f, 1.0f, 1.0f},  // C
297*c8dee2aaSAndroid Build Coastguard Worker         {1.0f, 0.0f, 1.0f, 1.0f},  // M
298*c8dee2aaSAndroid Build Coastguard Worker     };
299*c8dee2aaSAndroid Build Coastguard Worker 
300*c8dee2aaSAndroid Build Coastguard Worker     std::unique_ptr<const char[]> dataNew(
301*c8dee2aaSAndroid Build Coastguard Worker             make_compressed_data(compression, expectedColorsNew, mipmapped));
302*c8dee2aaSAndroid Build Coastguard Worker     size_t dataNewSize = SkCompressedDataSize(
303*c8dee2aaSAndroid Build Coastguard Worker             compression, {32, 32}, nullptr, mipmapped == skgpu::Mipmapped::kYes);
304*c8dee2aaSAndroid Build Coastguard Worker 
305*c8dee2aaSAndroid Build Coastguard Worker     bool result = dContext->updateCompressedBackendTexture(backendTex, dataNew.get(), dataNewSize,
306*c8dee2aaSAndroid Build Coastguard Worker                                                            nullptr, nullptr);
307*c8dee2aaSAndroid Build Coastguard Worker     // Since we were able to create the compressed texture we should be able to update it.
308*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, result);
309*c8dee2aaSAndroid Build Coastguard Worker 
310*c8dee2aaSAndroid Build Coastguard Worker     check_compressed_mipmaps(dContext, img, compression, expectedColorsNew, mipmapped, reporter,
311*c8dee2aaSAndroid Build Coastguard Worker                              "pixmap");
312*c8dee2aaSAndroid Build Coastguard Worker     check_readback(dContext, std::move(img), compression, expectedColorsNew[0], reporter,
313*c8dee2aaSAndroid Build Coastguard Worker                    "data readback");
314*c8dee2aaSAndroid Build Coastguard Worker 
315*c8dee2aaSAndroid Build Coastguard Worker     dContext->deleteBackendTexture(backendTex);
316*c8dee2aaSAndroid Build Coastguard Worker }
317*c8dee2aaSAndroid Build Coastguard Worker 
DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(CompressedBackendAllocationTest,reporter,ctxInfo,CtsEnforcement::kApiLevel_T)318*c8dee2aaSAndroid Build Coastguard Worker DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(CompressedBackendAllocationTest,
319*c8dee2aaSAndroid Build Coastguard Worker                                        reporter,
320*c8dee2aaSAndroid Build Coastguard Worker                                        ctxInfo,
321*c8dee2aaSAndroid Build Coastguard Worker                                        CtsEnforcement::kApiLevel_T) {
322*c8dee2aaSAndroid Build Coastguard Worker     auto dContext = ctxInfo.directContext();
323*c8dee2aaSAndroid Build Coastguard Worker     const GrCaps* caps = dContext->priv().caps();
324*c8dee2aaSAndroid Build Coastguard Worker 
325*c8dee2aaSAndroid Build Coastguard Worker     struct {
326*c8dee2aaSAndroid Build Coastguard Worker         SkTextureCompressionType fCompression;
327*c8dee2aaSAndroid Build Coastguard Worker         SkColor4f                fColor;
328*c8dee2aaSAndroid Build Coastguard Worker     } combinations[] = {
329*c8dee2aaSAndroid Build Coastguard Worker         { SkTextureCompressionType::kETC2_RGB8_UNORM, SkColors::kRed },
330*c8dee2aaSAndroid Build Coastguard Worker         { SkTextureCompressionType::kBC1_RGB8_UNORM,  SkColors::kBlue },
331*c8dee2aaSAndroid Build Coastguard Worker         { SkTextureCompressionType::kBC1_RGBA8_UNORM, SkColors::kTransparent },
332*c8dee2aaSAndroid Build Coastguard Worker     };
333*c8dee2aaSAndroid Build Coastguard Worker 
334*c8dee2aaSAndroid Build Coastguard Worker     for (auto combo : combinations) {
335*c8dee2aaSAndroid Build Coastguard Worker         GrBackendFormat format = dContext->compressedBackendFormat(combo.fCompression);
336*c8dee2aaSAndroid Build Coastguard Worker         if (!format.isValid()) {
337*c8dee2aaSAndroid Build Coastguard Worker             continue;
338*c8dee2aaSAndroid Build Coastguard Worker         }
339*c8dee2aaSAndroid Build Coastguard Worker 
340*c8dee2aaSAndroid Build Coastguard Worker         if (!caps->isFormatTexturable(format, GrTextureType::k2D)) {
341*c8dee2aaSAndroid Build Coastguard Worker             continue;
342*c8dee2aaSAndroid Build Coastguard Worker         }
343*c8dee2aaSAndroid Build Coastguard Worker 
344*c8dee2aaSAndroid Build Coastguard Worker         for (auto mipmapped : {skgpu::Mipmapped::kNo, skgpu::Mipmapped::kYes}) {
345*c8dee2aaSAndroid Build Coastguard Worker             if (skgpu::Mipmapped::kYes == mipmapped && !caps->mipmapSupport()) {
346*c8dee2aaSAndroid Build Coastguard Worker                 continue;
347*c8dee2aaSAndroid Build Coastguard Worker             }
348*c8dee2aaSAndroid Build Coastguard Worker 
349*c8dee2aaSAndroid Build Coastguard Worker             // color initialized
350*c8dee2aaSAndroid Build Coastguard Worker             {
351*c8dee2aaSAndroid Build Coastguard Worker                 auto createWithColorMtd = [format](GrDirectContext* dContext,
352*c8dee2aaSAndroid Build Coastguard Worker                                                    const SkColor4f& color,
353*c8dee2aaSAndroid Build Coastguard Worker                                                    skgpu::Mipmapped mipmapped) {
354*c8dee2aaSAndroid Build Coastguard Worker                     return dContext->createCompressedBackendTexture(32, 32, format, color,
355*c8dee2aaSAndroid Build Coastguard Worker                                                                     mipmapped, GrProtected::kNo);
356*c8dee2aaSAndroid Build Coastguard Worker                 };
357*c8dee2aaSAndroid Build Coastguard Worker 
358*c8dee2aaSAndroid Build Coastguard Worker                 test_compressed_color_init(dContext, reporter, createWithColorMtd,
359*c8dee2aaSAndroid Build Coastguard Worker                                            combo.fColor, combo.fCompression, mipmapped);
360*c8dee2aaSAndroid Build Coastguard Worker             }
361*c8dee2aaSAndroid Build Coastguard Worker 
362*c8dee2aaSAndroid Build Coastguard Worker             // data initialized
363*c8dee2aaSAndroid Build Coastguard Worker             {
364*c8dee2aaSAndroid Build Coastguard Worker                 auto createWithDataMtd = [format](GrDirectContext* dContext,
365*c8dee2aaSAndroid Build Coastguard Worker                                                   const char* data,
366*c8dee2aaSAndroid Build Coastguard Worker                                                   size_t dataSize,
367*c8dee2aaSAndroid Build Coastguard Worker                                                   skgpu::Mipmapped mipmapped) {
368*c8dee2aaSAndroid Build Coastguard Worker                     return dContext->createCompressedBackendTexture(32, 32, format, data, dataSize,
369*c8dee2aaSAndroid Build Coastguard Worker                                                                     mipmapped, GrProtected::kNo);
370*c8dee2aaSAndroid Build Coastguard Worker                 };
371*c8dee2aaSAndroid Build Coastguard Worker 
372*c8dee2aaSAndroid Build Coastguard Worker                 test_compressed_data_init(dContext, reporter, createWithDataMtd,
373*c8dee2aaSAndroid Build Coastguard Worker                                           combo.fCompression, mipmapped);
374*c8dee2aaSAndroid Build Coastguard Worker             }
375*c8dee2aaSAndroid Build Coastguard Worker         }
376*c8dee2aaSAndroid Build Coastguard Worker     }
377*c8dee2aaSAndroid Build Coastguard Worker }
378