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