1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2015 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/SkBlendMode.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkCanvas.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColor.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColorPriv.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColorSpace.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColorType.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkData.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkDataTable.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkImage.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkImageGenerator.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkImageInfo.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkM44.h"
22*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPaint.h"
23*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPicture.h"
24*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPictureRecorder.h"
25*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPixmap.h"
26*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRect.h"
27*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRefCnt.h"
28*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSamplingOptions.h"
29*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkScalar.h"
30*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSerialProcs.h"
31*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSize.h"
32*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkStream.h"
33*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSurface.h"
34*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTypes.h"
35*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkYUVAInfo.h"
36*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkYUVAPixmaps.h"
37*c8dee2aaSAndroid Build Coastguard Worker #include "include/encode/SkPngEncoder.h"
38*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/GpuTypes.h"
39*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/GrBackendSurface.h"
40*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/GrDirectContext.h"
41*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/GrTypes.h"
42*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/SkImageGanesh.h"
43*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/SkSurfaceGanesh.h"
44*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/SkColorData.h"
45*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkCPUTypes.h"
46*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkDebug.h"
47*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkFloatingPoint.h"
48*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkTemplates.h"
49*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkTo.h"
50*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/gpu/ganesh/GrImageContext.h"
51*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/gpu/ganesh/GrTypesPriv.h"
52*c8dee2aaSAndroid Build Coastguard Worker #include "modules/skcms/skcms.h"
53*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkAutoPixmapStorage.h"
54*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkBitmapCache.h"
55*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkColorSpacePriv.h"
56*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkImagePriv.h"
57*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkMemset.h"
58*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ResourceKey.h"
59*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrCaps.h"
60*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrDirectContextPriv.h"
61*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrGpu.h"
62*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrImageContextPriv.h"
63*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrRecordingContextPriv.h"
64*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrSurfaceProxyView.h"
65*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrTextureProxy.h"
66*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/image/GrImageUtils.h"
67*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/image/SkImage_GaneshYUVA.h"
68*c8dee2aaSAndroid Build Coastguard Worker #include "src/image/SkImageGeneratorPriv.h"
69*c8dee2aaSAndroid Build Coastguard Worker #include "src/image/SkImage_Base.h"
70*c8dee2aaSAndroid Build Coastguard Worker #include "src/shaders/SkImageShader.h"
71*c8dee2aaSAndroid Build Coastguard Worker #include "tests/CtsEnforcement.h"
72*c8dee2aaSAndroid Build Coastguard Worker #include "tests/Test.h"
73*c8dee2aaSAndroid Build Coastguard Worker #include "tools/DecodeUtils.h"
74*c8dee2aaSAndroid Build Coastguard Worker #include "tools/Resources.h"
75*c8dee2aaSAndroid Build Coastguard Worker #include "tools/ToolUtils.h"
76*c8dee2aaSAndroid Build Coastguard Worker #include "tools/gpu/FenceSync.h"
77*c8dee2aaSAndroid Build Coastguard Worker #include "tools/gpu/ManagedBackendTexture.h"
78*c8dee2aaSAndroid Build Coastguard Worker #include "tools/gpu/ProxyUtils.h"
79*c8dee2aaSAndroid Build Coastguard Worker #include "tools/gpu/TestContext.h"
80*c8dee2aaSAndroid Build Coastguard Worker
81*c8dee2aaSAndroid Build Coastguard Worker #include <algorithm>
82*c8dee2aaSAndroid Build Coastguard Worker #include <cmath>
83*c8dee2aaSAndroid Build Coastguard Worker #include <cstdint>
84*c8dee2aaSAndroid Build Coastguard Worker #include <cstring>
85*c8dee2aaSAndroid Build Coastguard Worker #include <functional>
86*c8dee2aaSAndroid Build Coastguard Worker #include <initializer_list>
87*c8dee2aaSAndroid Build Coastguard Worker #include <memory>
88*c8dee2aaSAndroid Build Coastguard Worker #include <tuple>
89*c8dee2aaSAndroid Build Coastguard Worker #include <utility>
90*c8dee2aaSAndroid Build Coastguard Worker #include <vector>
91*c8dee2aaSAndroid Build Coastguard Worker
92*c8dee2aaSAndroid Build Coastguard Worker class GrContextThreadSafeProxy;
93*c8dee2aaSAndroid Build Coastguard Worker class GrRecordingContext;
94*c8dee2aaSAndroid Build Coastguard Worker struct GrContextOptions;
95*c8dee2aaSAndroid Build Coastguard Worker
96*c8dee2aaSAndroid Build Coastguard Worker using namespace sk_gpu_test;
97*c8dee2aaSAndroid Build Coastguard Worker
read_pixels_info(SkImage * image)98*c8dee2aaSAndroid Build Coastguard Worker SkImageInfo read_pixels_info(SkImage* image) {
99*c8dee2aaSAndroid Build Coastguard Worker if (image->colorSpace()) {
100*c8dee2aaSAndroid Build Coastguard Worker return SkImageInfo::MakeS32(image->width(), image->height(), image->alphaType());
101*c8dee2aaSAndroid Build Coastguard Worker }
102*c8dee2aaSAndroid Build Coastguard Worker
103*c8dee2aaSAndroid Build Coastguard Worker return SkImageInfo::MakeN32(image->width(), image->height(), image->alphaType());
104*c8dee2aaSAndroid Build Coastguard Worker }
105*c8dee2aaSAndroid Build Coastguard Worker
106*c8dee2aaSAndroid Build Coastguard Worker // image `b` is assumed to be raster
assert_equal(skiatest::Reporter * reporter,GrDirectContext * dContextA,SkImage * a,const SkIRect * subsetA,SkImage * b)107*c8dee2aaSAndroid Build Coastguard Worker static void assert_equal(skiatest::Reporter* reporter, GrDirectContext* dContextA, SkImage* a,
108*c8dee2aaSAndroid Build Coastguard Worker const SkIRect* subsetA, SkImage* b) {
109*c8dee2aaSAndroid Build Coastguard Worker const int widthA = subsetA ? subsetA->width() : a->width();
110*c8dee2aaSAndroid Build Coastguard Worker const int heightA = subsetA ? subsetA->height() : a->height();
111*c8dee2aaSAndroid Build Coastguard Worker
112*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, widthA == b->width());
113*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, heightA == b->height());
114*c8dee2aaSAndroid Build Coastguard Worker
115*c8dee2aaSAndroid Build Coastguard Worker // see https://bug.skia.org/3965
116*c8dee2aaSAndroid Build Coastguard Worker //REPORTER_ASSERT(reporter, a->isOpaque() == b->isOpaque());
117*c8dee2aaSAndroid Build Coastguard Worker
118*c8dee2aaSAndroid Build Coastguard Worker SkAutoPixmapStorage pmapA, pmapB;
119*c8dee2aaSAndroid Build Coastguard Worker pmapA.alloc(read_pixels_info(a));
120*c8dee2aaSAndroid Build Coastguard Worker pmapB.alloc(read_pixels_info(b));
121*c8dee2aaSAndroid Build Coastguard Worker
122*c8dee2aaSAndroid Build Coastguard Worker const int srcX = subsetA ? subsetA->x() : 0;
123*c8dee2aaSAndroid Build Coastguard Worker const int srcY = subsetA ? subsetA->y() : 0;
124*c8dee2aaSAndroid Build Coastguard Worker
125*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, a->readPixels(dContextA, pmapA, srcX, srcY));
126*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, b->readPixels(nullptr, pmapB, 0, 0));
127*c8dee2aaSAndroid Build Coastguard Worker
128*c8dee2aaSAndroid Build Coastguard Worker const size_t widthBytes = widthA * 4;
129*c8dee2aaSAndroid Build Coastguard Worker for (int y = 0; y < heightA; ++y) {
130*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, !memcmp(pmapA.addr32(0, y), pmapB.addr32(0, y), widthBytes));
131*c8dee2aaSAndroid Build Coastguard Worker }
132*c8dee2aaSAndroid Build Coastguard Worker }
draw_image_test_pattern(SkCanvas * canvas)133*c8dee2aaSAndroid Build Coastguard Worker static void draw_image_test_pattern(SkCanvas* canvas) {
134*c8dee2aaSAndroid Build Coastguard Worker canvas->clear(SK_ColorWHITE);
135*c8dee2aaSAndroid Build Coastguard Worker SkPaint paint;
136*c8dee2aaSAndroid Build Coastguard Worker paint.setColor(SK_ColorBLACK);
137*c8dee2aaSAndroid Build Coastguard Worker canvas->drawRect(SkRect::MakeXYWH(5, 5, 10, 10), paint);
138*c8dee2aaSAndroid Build Coastguard Worker }
create_image()139*c8dee2aaSAndroid Build Coastguard Worker static sk_sp<SkImage> create_image() {
140*c8dee2aaSAndroid Build Coastguard Worker const SkImageInfo info = SkImageInfo::MakeN32(20, 20, kOpaque_SkAlphaType);
141*c8dee2aaSAndroid Build Coastguard Worker auto surface(SkSurfaces::Raster(info));
142*c8dee2aaSAndroid Build Coastguard Worker draw_image_test_pattern(surface->getCanvas());
143*c8dee2aaSAndroid Build Coastguard Worker return surface->makeImageSnapshot();
144*c8dee2aaSAndroid Build Coastguard Worker }
create_image_data(SkImageInfo * info)145*c8dee2aaSAndroid Build Coastguard Worker static sk_sp<SkData> create_image_data(SkImageInfo* info) {
146*c8dee2aaSAndroid Build Coastguard Worker *info = SkImageInfo::MakeN32(20, 20, kOpaque_SkAlphaType);
147*c8dee2aaSAndroid Build Coastguard Worker const size_t rowBytes = info->minRowBytes();
148*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkData> data(SkData::MakeUninitialized(rowBytes * info->height()));
149*c8dee2aaSAndroid Build Coastguard Worker {
150*c8dee2aaSAndroid Build Coastguard Worker SkBitmap bm;
151*c8dee2aaSAndroid Build Coastguard Worker bm.installPixels(*info, data->writable_data(), rowBytes);
152*c8dee2aaSAndroid Build Coastguard Worker SkCanvas canvas(bm);
153*c8dee2aaSAndroid Build Coastguard Worker draw_image_test_pattern(&canvas);
154*c8dee2aaSAndroid Build Coastguard Worker }
155*c8dee2aaSAndroid Build Coastguard Worker return data;
156*c8dee2aaSAndroid Build Coastguard Worker }
create_data_image()157*c8dee2aaSAndroid Build Coastguard Worker static sk_sp<SkImage> create_data_image() {
158*c8dee2aaSAndroid Build Coastguard Worker SkImageInfo info;
159*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkData> data(create_image_data(&info));
160*c8dee2aaSAndroid Build Coastguard Worker return SkImages::RasterFromData(info, std::move(data), info.minRowBytes());
161*c8dee2aaSAndroid Build Coastguard Worker }
create_image_large(int maxTextureSize)162*c8dee2aaSAndroid Build Coastguard Worker static sk_sp<SkImage> create_image_large(int maxTextureSize) {
163*c8dee2aaSAndroid Build Coastguard Worker const SkImageInfo info = SkImageInfo::MakeN32(maxTextureSize + 1, 32, kOpaque_SkAlphaType);
164*c8dee2aaSAndroid Build Coastguard Worker auto surface(SkSurfaces::Raster(info));
165*c8dee2aaSAndroid Build Coastguard Worker surface->getCanvas()->clear(SK_ColorWHITE);
166*c8dee2aaSAndroid Build Coastguard Worker SkPaint paint;
167*c8dee2aaSAndroid Build Coastguard Worker paint.setColor(SK_ColorBLACK);
168*c8dee2aaSAndroid Build Coastguard Worker surface->getCanvas()->drawRect(SkRect::MakeXYWH(4000, 2, 28000, 30), paint);
169*c8dee2aaSAndroid Build Coastguard Worker return surface->makeImageSnapshot();
170*c8dee2aaSAndroid Build Coastguard Worker }
create_picture_image()171*c8dee2aaSAndroid Build Coastguard Worker static sk_sp<SkImage> create_picture_image() {
172*c8dee2aaSAndroid Build Coastguard Worker SkPictureRecorder recorder;
173*c8dee2aaSAndroid Build Coastguard Worker SkCanvas* canvas = recorder.beginRecording(10, 10);
174*c8dee2aaSAndroid Build Coastguard Worker canvas->clear(SK_ColorCYAN);
175*c8dee2aaSAndroid Build Coastguard Worker return SkImages::DeferredFromPicture(recorder.finishRecordingAsPicture(),
176*c8dee2aaSAndroid Build Coastguard Worker SkISize::Make(10, 10),
177*c8dee2aaSAndroid Build Coastguard Worker nullptr,
178*c8dee2aaSAndroid Build Coastguard Worker nullptr,
179*c8dee2aaSAndroid Build Coastguard Worker SkImages::BitDepth::kU8,
180*c8dee2aaSAndroid Build Coastguard Worker SkColorSpace::MakeSRGB());
181*c8dee2aaSAndroid Build Coastguard Worker }
182*c8dee2aaSAndroid Build Coastguard Worker // Want to ensure that our Release is called when the owning image is destroyed
183*c8dee2aaSAndroid Build Coastguard Worker struct RasterDataHolder {
RasterDataHolderRasterDataHolder184*c8dee2aaSAndroid Build Coastguard Worker RasterDataHolder() : fReleaseCount(0) {}
185*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkData> fData;
186*c8dee2aaSAndroid Build Coastguard Worker int fReleaseCount;
ReleaseRasterDataHolder187*c8dee2aaSAndroid Build Coastguard Worker static void Release(const void* pixels, void* context) {
188*c8dee2aaSAndroid Build Coastguard Worker RasterDataHolder* self = static_cast<RasterDataHolder*>(context);
189*c8dee2aaSAndroid Build Coastguard Worker self->fReleaseCount++;
190*c8dee2aaSAndroid Build Coastguard Worker self->fData.reset();
191*c8dee2aaSAndroid Build Coastguard Worker }
192*c8dee2aaSAndroid Build Coastguard Worker };
create_rasterproc_image(RasterDataHolder * dataHolder)193*c8dee2aaSAndroid Build Coastguard Worker static sk_sp<SkImage> create_rasterproc_image(RasterDataHolder* dataHolder) {
194*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(dataHolder);
195*c8dee2aaSAndroid Build Coastguard Worker SkImageInfo info;
196*c8dee2aaSAndroid Build Coastguard Worker dataHolder->fData = create_image_data(&info);
197*c8dee2aaSAndroid Build Coastguard Worker return SkImages::RasterFromPixmap(SkPixmap(info, dataHolder->fData->data(), info.minRowBytes()),
198*c8dee2aaSAndroid Build Coastguard Worker RasterDataHolder::Release,
199*c8dee2aaSAndroid Build Coastguard Worker dataHolder);
200*c8dee2aaSAndroid Build Coastguard Worker }
create_codec_image()201*c8dee2aaSAndroid Build Coastguard Worker static sk_sp<SkImage> create_codec_image() {
202*c8dee2aaSAndroid Build Coastguard Worker SkImageInfo info;
203*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkData> data(create_image_data(&info));
204*c8dee2aaSAndroid Build Coastguard Worker SkBitmap bitmap;
205*c8dee2aaSAndroid Build Coastguard Worker bitmap.installPixels(info, data->writable_data(), info.minRowBytes());
206*c8dee2aaSAndroid Build Coastguard Worker SkDynamicMemoryWStream stream;
207*c8dee2aaSAndroid Build Coastguard Worker SkASSERT_RELEASE(SkPngEncoder::Encode(&stream, bitmap.pixmap(), {}));
208*c8dee2aaSAndroid Build Coastguard Worker return SkImages::DeferredFromEncodedData(stream.detachAsData());
209*c8dee2aaSAndroid Build Coastguard Worker }
create_gpu_image(GrRecordingContext * rContext,bool withMips=false,skgpu::Budgeted budgeted=skgpu::Budgeted::kYes)210*c8dee2aaSAndroid Build Coastguard Worker static sk_sp<SkImage> create_gpu_image(GrRecordingContext* rContext,
211*c8dee2aaSAndroid Build Coastguard Worker bool withMips = false,
212*c8dee2aaSAndroid Build Coastguard Worker skgpu::Budgeted budgeted = skgpu::Budgeted::kYes) {
213*c8dee2aaSAndroid Build Coastguard Worker const SkImageInfo info = SkImageInfo::MakeN32(20, 20, kOpaque_SkAlphaType);
214*c8dee2aaSAndroid Build Coastguard Worker auto surface = SkSurfaces::RenderTarget(
215*c8dee2aaSAndroid Build Coastguard Worker rContext, budgeted, info, 0, kBottomLeft_GrSurfaceOrigin, nullptr, withMips);
216*c8dee2aaSAndroid Build Coastguard Worker draw_image_test_pattern(surface->getCanvas());
217*c8dee2aaSAndroid Build Coastguard Worker return surface->makeImageSnapshot();
218*c8dee2aaSAndroid Build Coastguard Worker }
219*c8dee2aaSAndroid Build Coastguard Worker
test_encode(skiatest::Reporter * reporter,GrDirectContext * dContext,SkImage * image)220*c8dee2aaSAndroid Build Coastguard Worker static void test_encode(skiatest::Reporter* reporter, GrDirectContext* dContext, SkImage* image) {
221*c8dee2aaSAndroid Build Coastguard Worker const SkIRect ir = SkIRect::MakeXYWH(5, 5, 10, 10);
222*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkData> origEncoded = SkPngEncoder::Encode(dContext, image, {});
223*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, origEncoded);
224*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, origEncoded->size() > 0);
225*c8dee2aaSAndroid Build Coastguard Worker
226*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> decoded(SkImages::DeferredFromEncodedData(origEncoded));
227*c8dee2aaSAndroid Build Coastguard Worker if (!decoded) {
228*c8dee2aaSAndroid Build Coastguard Worker ERRORF(reporter, "failed to decode image!");
229*c8dee2aaSAndroid Build Coastguard Worker return;
230*c8dee2aaSAndroid Build Coastguard Worker }
231*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, decoded);
232*c8dee2aaSAndroid Build Coastguard Worker assert_equal(reporter, dContext, image, nullptr, decoded.get());
233*c8dee2aaSAndroid Build Coastguard Worker
234*c8dee2aaSAndroid Build Coastguard Worker // Now see if we can instantiate an image from a subset of the surface/origEncoded
235*c8dee2aaSAndroid Build Coastguard Worker
236*c8dee2aaSAndroid Build Coastguard Worker decoded = SkImages::DeferredFromEncodedData(origEncoded)->makeSubset(nullptr, ir);
237*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, decoded);
238*c8dee2aaSAndroid Build Coastguard Worker assert_equal(reporter, dContext, image, &ir, decoded.get());
239*c8dee2aaSAndroid Build Coastguard Worker }
240*c8dee2aaSAndroid Build Coastguard Worker
DEF_TEST(ImageEncode,reporter)241*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(ImageEncode, reporter) {
242*c8dee2aaSAndroid Build Coastguard Worker test_encode(reporter, nullptr, create_image().get());
243*c8dee2aaSAndroid Build Coastguard Worker }
244*c8dee2aaSAndroid Build Coastguard Worker
DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(ImageEncode_Gpu,reporter,ctxInfo,CtsEnforcement::kApiLevel_T)245*c8dee2aaSAndroid Build Coastguard Worker DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(ImageEncode_Gpu,
246*c8dee2aaSAndroid Build Coastguard Worker reporter,
247*c8dee2aaSAndroid Build Coastguard Worker ctxInfo,
248*c8dee2aaSAndroid Build Coastguard Worker CtsEnforcement::kApiLevel_T) {
249*c8dee2aaSAndroid Build Coastguard Worker auto dContext = ctxInfo.directContext();
250*c8dee2aaSAndroid Build Coastguard Worker test_encode(reporter, dContext, create_gpu_image(dContext).get());
251*c8dee2aaSAndroid Build Coastguard Worker }
252*c8dee2aaSAndroid Build Coastguard Worker
DEF_TEST(Image_MakeFromRasterBitmap,reporter)253*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(Image_MakeFromRasterBitmap, reporter) {
254*c8dee2aaSAndroid Build Coastguard Worker const struct {
255*c8dee2aaSAndroid Build Coastguard Worker SkCopyPixelsMode fCPM;
256*c8dee2aaSAndroid Build Coastguard Worker bool fExpectSameAsMutable;
257*c8dee2aaSAndroid Build Coastguard Worker bool fExpectSameAsImmutable;
258*c8dee2aaSAndroid Build Coastguard Worker } recs[] = {
259*c8dee2aaSAndroid Build Coastguard Worker { kIfMutable_SkCopyPixelsMode, false, true },
260*c8dee2aaSAndroid Build Coastguard Worker { kAlways_SkCopyPixelsMode, false, false },
261*c8dee2aaSAndroid Build Coastguard Worker { kNever_SkCopyPixelsMode, true, true },
262*c8dee2aaSAndroid Build Coastguard Worker };
263*c8dee2aaSAndroid Build Coastguard Worker for (auto rec : recs) {
264*c8dee2aaSAndroid Build Coastguard Worker SkPixmap pm;
265*c8dee2aaSAndroid Build Coastguard Worker SkBitmap bm;
266*c8dee2aaSAndroid Build Coastguard Worker bm.allocN32Pixels(100, 100);
267*c8dee2aaSAndroid Build Coastguard Worker
268*c8dee2aaSAndroid Build Coastguard Worker auto img = SkMakeImageFromRasterBitmap(bm, rec.fCPM);
269*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, img->peekPixels(&pm));
270*c8dee2aaSAndroid Build Coastguard Worker const bool sameMutable = pm.addr32(0, 0) == bm.getAddr32(0, 0);
271*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, rec.fExpectSameAsMutable == sameMutable);
272*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, (bm.getGenerationID() == img->uniqueID()) == sameMutable);
273*c8dee2aaSAndroid Build Coastguard Worker
274*c8dee2aaSAndroid Build Coastguard Worker bm.notifyPixelsChanged(); // force a new generation ID
275*c8dee2aaSAndroid Build Coastguard Worker
276*c8dee2aaSAndroid Build Coastguard Worker bm.setImmutable();
277*c8dee2aaSAndroid Build Coastguard Worker img = SkMakeImageFromRasterBitmap(bm, rec.fCPM);
278*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, img->peekPixels(&pm));
279*c8dee2aaSAndroid Build Coastguard Worker const bool sameImmutable = pm.addr32(0, 0) == bm.getAddr32(0, 0);
280*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, rec.fExpectSameAsImmutable == sameImmutable);
281*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, (bm.getGenerationID() == img->uniqueID()) == sameImmutable);
282*c8dee2aaSAndroid Build Coastguard Worker }
283*c8dee2aaSAndroid Build Coastguard Worker }
284*c8dee2aaSAndroid Build Coastguard Worker
285*c8dee2aaSAndroid Build Coastguard Worker // Test that image encoding failures do not break picture serialization/deserialization.
DEF_TEST(Image_Serialize_Encoding_Failure,reporter)286*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(Image_Serialize_Encoding_Failure, reporter) {
287*c8dee2aaSAndroid Build Coastguard Worker auto surface(SkSurfaces::Raster(SkImageInfo::MakeN32Premul(100, 100)));
288*c8dee2aaSAndroid Build Coastguard Worker surface->getCanvas()->clear(SK_ColorGREEN);
289*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> image(surface->makeImageSnapshot());
290*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, image);
291*c8dee2aaSAndroid Build Coastguard Worker
292*c8dee2aaSAndroid Build Coastguard Worker SkPictureRecorder recorder;
293*c8dee2aaSAndroid Build Coastguard Worker SkCanvas* canvas = recorder.beginRecording(100, 100);
294*c8dee2aaSAndroid Build Coastguard Worker canvas->drawImage(image.get(), 0, 0, SkSamplingOptions());
295*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkPicture> picture(recorder.finishRecordingAsPicture());
296*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, picture);
297*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, picture->approximateOpCount() > 0);
298*c8dee2aaSAndroid Build Coastguard Worker
299*c8dee2aaSAndroid Build Coastguard Worker bool was_called = false;
300*c8dee2aaSAndroid Build Coastguard Worker SkSerialProcs procs;
301*c8dee2aaSAndroid Build Coastguard Worker procs.fImageProc = [](SkImage*, void* called) {
302*c8dee2aaSAndroid Build Coastguard Worker *(bool*)called = true;
303*c8dee2aaSAndroid Build Coastguard Worker return SkData::MakeEmpty();
304*c8dee2aaSAndroid Build Coastguard Worker };
305*c8dee2aaSAndroid Build Coastguard Worker procs.fImageCtx = &was_called;
306*c8dee2aaSAndroid Build Coastguard Worker
307*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, !was_called);
308*c8dee2aaSAndroid Build Coastguard Worker auto data = picture->serialize(&procs);
309*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, was_called);
310*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, data && data->size() > 0);
311*c8dee2aaSAndroid Build Coastguard Worker
312*c8dee2aaSAndroid Build Coastguard Worker auto deserialized = SkPicture::MakeFromData(data->data(), data->size());
313*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, deserialized);
314*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, deserialized->approximateOpCount() > 0);
315*c8dee2aaSAndroid Build Coastguard Worker }
316*c8dee2aaSAndroid Build Coastguard Worker
317*c8dee2aaSAndroid Build Coastguard Worker // Test that a draw that only partially covers the drawing surface isn't
318*c8dee2aaSAndroid Build Coastguard Worker // interpreted as covering the entire drawing surface (i.e., exercise one of the
319*c8dee2aaSAndroid Build Coastguard Worker // conditions of SkCanvas::wouldOverwriteEntireSurface()).
DEF_TEST(Image_RetainSnapshot,reporter)320*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(Image_RetainSnapshot, reporter) {
321*c8dee2aaSAndroid Build Coastguard Worker const SkPMColor red = SkPackARGB32(0xFF, 0xFF, 0, 0);
322*c8dee2aaSAndroid Build Coastguard Worker const SkPMColor green = SkPackARGB32(0xFF, 0, 0xFF, 0);
323*c8dee2aaSAndroid Build Coastguard Worker SkImageInfo info = SkImageInfo::MakeN32Premul(2, 2);
324*c8dee2aaSAndroid Build Coastguard Worker auto surface(SkSurfaces::Raster(info));
325*c8dee2aaSAndroid Build Coastguard Worker surface->getCanvas()->clear(0xFF00FF00);
326*c8dee2aaSAndroid Build Coastguard Worker
327*c8dee2aaSAndroid Build Coastguard Worker SkPMColor pixels[4];
328*c8dee2aaSAndroid Build Coastguard Worker memset(pixels, 0xFF, sizeof(pixels)); // init with values we don't expect
329*c8dee2aaSAndroid Build Coastguard Worker const SkImageInfo dstInfo = SkImageInfo::MakeN32Premul(2, 2);
330*c8dee2aaSAndroid Build Coastguard Worker const size_t dstRowBytes = 2 * sizeof(SkPMColor);
331*c8dee2aaSAndroid Build Coastguard Worker
332*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> image1(surface->makeImageSnapshot());
333*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, image1->readPixels(nullptr, dstInfo, pixels, dstRowBytes, 0, 0));
334*c8dee2aaSAndroid Build Coastguard Worker for (size_t i = 0; i < std::size(pixels); ++i) {
335*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, pixels[i] == green);
336*c8dee2aaSAndroid Build Coastguard Worker }
337*c8dee2aaSAndroid Build Coastguard Worker
338*c8dee2aaSAndroid Build Coastguard Worker SkPaint paint;
339*c8dee2aaSAndroid Build Coastguard Worker paint.setBlendMode(SkBlendMode::kSrc);
340*c8dee2aaSAndroid Build Coastguard Worker paint.setColor(SK_ColorRED);
341*c8dee2aaSAndroid Build Coastguard Worker
342*c8dee2aaSAndroid Build Coastguard Worker surface->getCanvas()->drawRect(SkRect::MakeXYWH(1, 1, 1, 1), paint);
343*c8dee2aaSAndroid Build Coastguard Worker
344*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> image2(surface->makeImageSnapshot());
345*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, image2->readPixels(nullptr, dstInfo, pixels, dstRowBytes, 0, 0));
346*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, pixels[0] == green);
347*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, pixels[1] == green);
348*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, pixels[2] == green);
349*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, pixels[3] == red);
350*c8dee2aaSAndroid Build Coastguard Worker }
351*c8dee2aaSAndroid Build Coastguard Worker
352*c8dee2aaSAndroid Build Coastguard Worker /////////////////////////////////////////////////////////////////////////////////////////////////
353*c8dee2aaSAndroid Build Coastguard Worker
make_bitmap_mutable(SkBitmap * bm)354*c8dee2aaSAndroid Build Coastguard Worker static void make_bitmap_mutable(SkBitmap* bm) {
355*c8dee2aaSAndroid Build Coastguard Worker bm->allocN32Pixels(10, 10);
356*c8dee2aaSAndroid Build Coastguard Worker }
357*c8dee2aaSAndroid Build Coastguard Worker
make_bitmap_immutable(SkBitmap * bm)358*c8dee2aaSAndroid Build Coastguard Worker static void make_bitmap_immutable(SkBitmap* bm) {
359*c8dee2aaSAndroid Build Coastguard Worker bm->allocN32Pixels(10, 10);
360*c8dee2aaSAndroid Build Coastguard Worker bm->setImmutable();
361*c8dee2aaSAndroid Build Coastguard Worker }
362*c8dee2aaSAndroid Build Coastguard Worker
DEF_TEST(image_newfrombitmap,reporter)363*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(image_newfrombitmap, reporter) {
364*c8dee2aaSAndroid Build Coastguard Worker const struct {
365*c8dee2aaSAndroid Build Coastguard Worker void (*fMakeProc)(SkBitmap*);
366*c8dee2aaSAndroid Build Coastguard Worker bool fExpectPeekSuccess;
367*c8dee2aaSAndroid Build Coastguard Worker bool fExpectSharedID;
368*c8dee2aaSAndroid Build Coastguard Worker bool fExpectLazy;
369*c8dee2aaSAndroid Build Coastguard Worker } rec[] = {
370*c8dee2aaSAndroid Build Coastguard Worker { make_bitmap_mutable, true, false, false },
371*c8dee2aaSAndroid Build Coastguard Worker { make_bitmap_immutable, true, true, false },
372*c8dee2aaSAndroid Build Coastguard Worker };
373*c8dee2aaSAndroid Build Coastguard Worker
374*c8dee2aaSAndroid Build Coastguard Worker for (size_t i = 0; i < std::size(rec); ++i) {
375*c8dee2aaSAndroid Build Coastguard Worker SkBitmap bm;
376*c8dee2aaSAndroid Build Coastguard Worker rec[i].fMakeProc(&bm);
377*c8dee2aaSAndroid Build Coastguard Worker
378*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> image(bm.asImage());
379*c8dee2aaSAndroid Build Coastguard Worker SkPixmap pmap;
380*c8dee2aaSAndroid Build Coastguard Worker
381*c8dee2aaSAndroid Build Coastguard Worker const bool sharedID = (image->uniqueID() == bm.getGenerationID());
382*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, sharedID == rec[i].fExpectSharedID);
383*c8dee2aaSAndroid Build Coastguard Worker
384*c8dee2aaSAndroid Build Coastguard Worker const bool peekSuccess = image->peekPixels(&pmap);
385*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, peekSuccess == rec[i].fExpectPeekSuccess);
386*c8dee2aaSAndroid Build Coastguard Worker
387*c8dee2aaSAndroid Build Coastguard Worker const bool lazy = image->isLazyGenerated();
388*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, lazy == rec[i].fExpectLazy);
389*c8dee2aaSAndroid Build Coastguard Worker }
390*c8dee2aaSAndroid Build Coastguard Worker }
391*c8dee2aaSAndroid Build Coastguard Worker
392*c8dee2aaSAndroid Build Coastguard Worker ///////////////////////////////////////////////////////////////////////////////////////////////////
393*c8dee2aaSAndroid Build Coastguard Worker
394*c8dee2aaSAndroid Build Coastguard Worker /*
395*c8dee2aaSAndroid Build Coastguard Worker * This tests the caching (and preemptive purge) of the raster equivalent of a gpu-image.
396*c8dee2aaSAndroid Build Coastguard Worker * We cache it for performance when drawing into a raster surface.
397*c8dee2aaSAndroid Build Coastguard Worker *
398*c8dee2aaSAndroid Build Coastguard Worker * A cleaner test would know if each drawImage call triggered a read-back from the gpu,
399*c8dee2aaSAndroid Build Coastguard Worker * but we don't have that facility (at the moment) so we use a little internal knowledge
400*c8dee2aaSAndroid Build Coastguard Worker * of *how* the raster version is cached, and look for that.
401*c8dee2aaSAndroid Build Coastguard Worker */
DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(SkImage_Ganesh2Cpu,reporter,ctxInfo,CtsEnforcement::kApiLevel_T)402*c8dee2aaSAndroid Build Coastguard Worker DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(SkImage_Ganesh2Cpu,
403*c8dee2aaSAndroid Build Coastguard Worker reporter,
404*c8dee2aaSAndroid Build Coastguard Worker ctxInfo,
405*c8dee2aaSAndroid Build Coastguard Worker CtsEnforcement::kApiLevel_T) {
406*c8dee2aaSAndroid Build Coastguard Worker SkImageInfo info = SkImageInfo::MakeN32(20, 20, kOpaque_SkAlphaType);
407*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> image(create_gpu_image(ctxInfo.directContext()));
408*c8dee2aaSAndroid Build Coastguard Worker const auto desc = SkBitmapCacheDesc::Make(image.get());
409*c8dee2aaSAndroid Build Coastguard Worker
410*c8dee2aaSAndroid Build Coastguard Worker auto surface(SkSurfaces::Raster(info));
411*c8dee2aaSAndroid Build Coastguard Worker
412*c8dee2aaSAndroid Build Coastguard Worker // now we can test drawing a gpu-backed image into a cpu-backed surface
413*c8dee2aaSAndroid Build Coastguard Worker
414*c8dee2aaSAndroid Build Coastguard Worker {
415*c8dee2aaSAndroid Build Coastguard Worker SkBitmap cachedBitmap;
416*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, !SkBitmapCache::Find(desc, &cachedBitmap));
417*c8dee2aaSAndroid Build Coastguard Worker }
418*c8dee2aaSAndroid Build Coastguard Worker
419*c8dee2aaSAndroid Build Coastguard Worker surface->getCanvas()->drawImage(image, 0, 0);
420*c8dee2aaSAndroid Build Coastguard Worker {
421*c8dee2aaSAndroid Build Coastguard Worker SkBitmap cachedBitmap;
422*c8dee2aaSAndroid Build Coastguard Worker if (SkBitmapCache::Find(desc, &cachedBitmap)) {
423*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, cachedBitmap.isImmutable());
424*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, cachedBitmap.getPixels());
425*c8dee2aaSAndroid Build Coastguard Worker } else {
426*c8dee2aaSAndroid Build Coastguard Worker // unexpected, but not really a bug, since the cache is global and this test may be
427*c8dee2aaSAndroid Build Coastguard Worker // run w/ other threads competing for its budget.
428*c8dee2aaSAndroid Build Coastguard Worker SkDebugf("SkImage_Ganesh2Cpu : cachedBitmap was already purged\n");
429*c8dee2aaSAndroid Build Coastguard Worker }
430*c8dee2aaSAndroid Build Coastguard Worker }
431*c8dee2aaSAndroid Build Coastguard Worker
432*c8dee2aaSAndroid Build Coastguard Worker image.reset(nullptr);
433*c8dee2aaSAndroid Build Coastguard Worker {
434*c8dee2aaSAndroid Build Coastguard Worker SkBitmap cachedBitmap;
435*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, !SkBitmapCache::Find(desc, &cachedBitmap));
436*c8dee2aaSAndroid Build Coastguard Worker }
437*c8dee2aaSAndroid Build Coastguard Worker }
438*c8dee2aaSAndroid Build Coastguard Worker
DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(SkImage_makeTextureImage,reporter,contextInfo,CtsEnforcement::kApiLevel_T)439*c8dee2aaSAndroid Build Coastguard Worker DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(SkImage_makeTextureImage,
440*c8dee2aaSAndroid Build Coastguard Worker reporter,
441*c8dee2aaSAndroid Build Coastguard Worker contextInfo,
442*c8dee2aaSAndroid Build Coastguard Worker CtsEnforcement::kApiLevel_T) {
443*c8dee2aaSAndroid Build Coastguard Worker auto dContext = contextInfo.directContext();
444*c8dee2aaSAndroid Build Coastguard Worker sk_gpu_test::TestContext* testContext = contextInfo.testContext();
445*c8dee2aaSAndroid Build Coastguard Worker GrContextFactory otherFactory;
446*c8dee2aaSAndroid Build Coastguard Worker ContextInfo otherContextInfo = otherFactory.getContextInfo(contextInfo.type());
447*c8dee2aaSAndroid Build Coastguard Worker testContext->makeCurrent();
448*c8dee2aaSAndroid Build Coastguard Worker std::function<sk_sp<SkImage>()> imageFactories[] = {
449*c8dee2aaSAndroid Build Coastguard Worker create_image,
450*c8dee2aaSAndroid Build Coastguard Worker create_codec_image,
451*c8dee2aaSAndroid Build Coastguard Worker create_data_image,
452*c8dee2aaSAndroid Build Coastguard Worker // Create an image from a picture.
453*c8dee2aaSAndroid Build Coastguard Worker create_picture_image,
454*c8dee2aaSAndroid Build Coastguard Worker // Create a texture image.
455*c8dee2aaSAndroid Build Coastguard Worker [dContext] { return create_gpu_image(dContext, true, skgpu::Budgeted::kYes); },
456*c8dee2aaSAndroid Build Coastguard Worker [dContext] { return create_gpu_image(dContext, false, skgpu::Budgeted::kNo); },
457*c8dee2aaSAndroid Build Coastguard Worker // Create a texture image in a another context.
458*c8dee2aaSAndroid Build Coastguard Worker [otherContextInfo] {
459*c8dee2aaSAndroid Build Coastguard Worker auto restore = otherContextInfo.testContext()->makeCurrentAndAutoRestore();
460*c8dee2aaSAndroid Build Coastguard Worker auto otherContextImage = create_gpu_image(otherContextInfo.directContext());
461*c8dee2aaSAndroid Build Coastguard Worker otherContextInfo.directContext()->flushAndSubmit();
462*c8dee2aaSAndroid Build Coastguard Worker return otherContextImage;
463*c8dee2aaSAndroid Build Coastguard Worker }};
464*c8dee2aaSAndroid Build Coastguard Worker for (auto mipmapped : {skgpu::Mipmapped::kNo, skgpu::Mipmapped::kYes}) {
465*c8dee2aaSAndroid Build Coastguard Worker for (const auto& factory : imageFactories) {
466*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> image(factory());
467*c8dee2aaSAndroid Build Coastguard Worker if (!image) {
468*c8dee2aaSAndroid Build Coastguard Worker ERRORF(reporter, "Error creating image.");
469*c8dee2aaSAndroid Build Coastguard Worker continue;
470*c8dee2aaSAndroid Build Coastguard Worker }
471*c8dee2aaSAndroid Build Coastguard Worker GrTextureProxy* origProxy = nullptr;
472*c8dee2aaSAndroid Build Coastguard Worker bool origIsMippedTexture = false;
473*c8dee2aaSAndroid Build Coastguard Worker
474*c8dee2aaSAndroid Build Coastguard Worker if ((origProxy = sk_gpu_test::GetTextureImageProxy(image.get(), dContext))) {
475*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(
476*c8dee2aaSAndroid Build Coastguard Worker reporter,
477*c8dee2aaSAndroid Build Coastguard Worker (origProxy->mipmapped() == skgpu::Mipmapped::kYes) == image->hasMipmaps());
478*c8dee2aaSAndroid Build Coastguard Worker origIsMippedTexture = image->hasMipmaps();
479*c8dee2aaSAndroid Build Coastguard Worker }
480*c8dee2aaSAndroid Build Coastguard Worker for (auto budgeted : {skgpu::Budgeted::kNo, skgpu::Budgeted::kYes}) {
481*c8dee2aaSAndroid Build Coastguard Worker auto texImage = SkImages::TextureFromImage(dContext, image, mipmapped, budgeted);
482*c8dee2aaSAndroid Build Coastguard Worker if (!texImage) {
483*c8dee2aaSAndroid Build Coastguard Worker auto imageContext = as_IB(image)->context();
484*c8dee2aaSAndroid Build Coastguard Worker // We expect to fail if image comes from a different context
485*c8dee2aaSAndroid Build Coastguard Worker if (!image->isTextureBacked() || imageContext->priv().matches(dContext)) {
486*c8dee2aaSAndroid Build Coastguard Worker ERRORF(reporter, "makeTextureImage failed.");
487*c8dee2aaSAndroid Build Coastguard Worker }
488*c8dee2aaSAndroid Build Coastguard Worker continue;
489*c8dee2aaSAndroid Build Coastguard Worker }
490*c8dee2aaSAndroid Build Coastguard Worker if (!texImage->isTextureBacked()) {
491*c8dee2aaSAndroid Build Coastguard Worker ERRORF(reporter, "makeTextureImage returned non-texture image.");
492*c8dee2aaSAndroid Build Coastguard Worker continue;
493*c8dee2aaSAndroid Build Coastguard Worker }
494*c8dee2aaSAndroid Build Coastguard Worker
495*c8dee2aaSAndroid Build Coastguard Worker GrTextureProxy* copyProxy = sk_gpu_test::GetTextureImageProxy(texImage.get(),
496*c8dee2aaSAndroid Build Coastguard Worker dContext);
497*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(copyProxy);
498*c8dee2aaSAndroid Build Coastguard Worker // Did we ask for MIPs on a context that supports them?
499*c8dee2aaSAndroid Build Coastguard Worker bool validRequestForMips = (mipmapped == skgpu::Mipmapped::kYes &&
500*c8dee2aaSAndroid Build Coastguard Worker dContext->priv().caps()->mipmapSupport());
501*c8dee2aaSAndroid Build Coastguard Worker // Do we expect the "copy" to have MIPs?
502*c8dee2aaSAndroid Build Coastguard Worker bool shouldBeMipped = origIsMippedTexture || validRequestForMips;
503*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, shouldBeMipped == texImage->hasMipmaps());
504*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(
505*c8dee2aaSAndroid Build Coastguard Worker reporter,
506*c8dee2aaSAndroid Build Coastguard Worker shouldBeMipped == (copyProxy->mipmapped() == skgpu::Mipmapped::kYes));
507*c8dee2aaSAndroid Build Coastguard Worker
508*c8dee2aaSAndroid Build Coastguard Worker // We should only make a copy of an already texture-backed image if it didn't
509*c8dee2aaSAndroid Build Coastguard Worker // already have MIPs but we asked for MIPs and the context supports it.
510*c8dee2aaSAndroid Build Coastguard Worker if (image->isTextureBacked() && (!validRequestForMips || origIsMippedTexture)) {
511*c8dee2aaSAndroid Build Coastguard Worker if (origProxy->underlyingUniqueID() != copyProxy->underlyingUniqueID()) {
512*c8dee2aaSAndroid Build Coastguard Worker ERRORF(reporter, "makeTextureImage made unnecessary texture copy.");
513*c8dee2aaSAndroid Build Coastguard Worker }
514*c8dee2aaSAndroid Build Coastguard Worker } else {
515*c8dee2aaSAndroid Build Coastguard Worker GrTextureProxy* texProxy = sk_gpu_test::GetTextureImageProxy(texImage.get(),
516*c8dee2aaSAndroid Build Coastguard Worker dContext);
517*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, !texProxy->getUniqueKey().isValid());
518*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, texProxy->isBudgeted() == budgeted);
519*c8dee2aaSAndroid Build Coastguard Worker }
520*c8dee2aaSAndroid Build Coastguard Worker if (image->width() != texImage->width() || image->height() != texImage->height()) {
521*c8dee2aaSAndroid Build Coastguard Worker ERRORF(reporter, "makeTextureImage changed the image size.");
522*c8dee2aaSAndroid Build Coastguard Worker }
523*c8dee2aaSAndroid Build Coastguard Worker if (image->alphaType() != texImage->alphaType()) {
524*c8dee2aaSAndroid Build Coastguard Worker ERRORF(reporter, "makeTextureImage changed image alpha type.");
525*c8dee2aaSAndroid Build Coastguard Worker }
526*c8dee2aaSAndroid Build Coastguard Worker }
527*c8dee2aaSAndroid Build Coastguard Worker }
528*c8dee2aaSAndroid Build Coastguard Worker }
529*c8dee2aaSAndroid Build Coastguard Worker dContext->flushAndSubmit();
530*c8dee2aaSAndroid Build Coastguard Worker }
531*c8dee2aaSAndroid Build Coastguard Worker
DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(SkImage_makeNonTextureImage,reporter,contextInfo,CtsEnforcement::kApiLevel_T)532*c8dee2aaSAndroid Build Coastguard Worker DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(SkImage_makeNonTextureImage,
533*c8dee2aaSAndroid Build Coastguard Worker reporter,
534*c8dee2aaSAndroid Build Coastguard Worker contextInfo,
535*c8dee2aaSAndroid Build Coastguard Worker CtsEnforcement::kApiLevel_T) {
536*c8dee2aaSAndroid Build Coastguard Worker auto dContext = contextInfo.directContext();
537*c8dee2aaSAndroid Build Coastguard Worker
538*c8dee2aaSAndroid Build Coastguard Worker std::function<sk_sp<SkImage>()> imageFactories[] = {
539*c8dee2aaSAndroid Build Coastguard Worker create_image,
540*c8dee2aaSAndroid Build Coastguard Worker create_codec_image,
541*c8dee2aaSAndroid Build Coastguard Worker create_data_image,
542*c8dee2aaSAndroid Build Coastguard Worker create_picture_image,
543*c8dee2aaSAndroid Build Coastguard Worker [dContext] { return create_gpu_image(dContext); },
544*c8dee2aaSAndroid Build Coastguard Worker };
545*c8dee2aaSAndroid Build Coastguard Worker for (const auto& factory : imageFactories) {
546*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> image = factory();
547*c8dee2aaSAndroid Build Coastguard Worker if (!image->isTextureBacked()) {
548*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, image->makeNonTextureImage().get() == image.get());
549*c8dee2aaSAndroid Build Coastguard Worker if (!(image = SkImages::TextureFromImage(dContext, image))) {
550*c8dee2aaSAndroid Build Coastguard Worker continue;
551*c8dee2aaSAndroid Build Coastguard Worker }
552*c8dee2aaSAndroid Build Coastguard Worker }
553*c8dee2aaSAndroid Build Coastguard Worker auto rasterImage = image->makeNonTextureImage();
554*c8dee2aaSAndroid Build Coastguard Worker if (!rasterImage) {
555*c8dee2aaSAndroid Build Coastguard Worker ERRORF(reporter, "makeNonTextureImage failed for texture-backed image.");
556*c8dee2aaSAndroid Build Coastguard Worker }
557*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, !rasterImage->isTextureBacked());
558*c8dee2aaSAndroid Build Coastguard Worker assert_equal(reporter, dContext, image.get(), nullptr, rasterImage.get());
559*c8dee2aaSAndroid Build Coastguard Worker }
560*c8dee2aaSAndroid Build Coastguard Worker }
561*c8dee2aaSAndroid Build Coastguard Worker
DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(GrContext_colorTypeSupportedAsImage,reporter,ctxInfo,CtsEnforcement::kApiLevel_T)562*c8dee2aaSAndroid Build Coastguard Worker DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(GrContext_colorTypeSupportedAsImage,
563*c8dee2aaSAndroid Build Coastguard Worker reporter,
564*c8dee2aaSAndroid Build Coastguard Worker ctxInfo,
565*c8dee2aaSAndroid Build Coastguard Worker CtsEnforcement::kApiLevel_T) {
566*c8dee2aaSAndroid Build Coastguard Worker using namespace skgpu;
567*c8dee2aaSAndroid Build Coastguard Worker
568*c8dee2aaSAndroid Build Coastguard Worker auto dContext = ctxInfo.directContext();
569*c8dee2aaSAndroid Build Coastguard Worker
570*c8dee2aaSAndroid Build Coastguard Worker Protected isProtected = Protected(dContext->priv().caps()->supportsProtectedContent());
571*c8dee2aaSAndroid Build Coastguard Worker
572*c8dee2aaSAndroid Build Coastguard Worker static constexpr int kSize = 10;
573*c8dee2aaSAndroid Build Coastguard Worker
574*c8dee2aaSAndroid Build Coastguard Worker for (int ct = 0; ct < kLastEnum_SkColorType; ++ct) {
575*c8dee2aaSAndroid Build Coastguard Worker SkColorType colorType = static_cast<SkColorType>(ct);
576*c8dee2aaSAndroid Build Coastguard Worker bool can = dContext->colorTypeSupportedAsImage(colorType);
577*c8dee2aaSAndroid Build Coastguard Worker
578*c8dee2aaSAndroid Build Coastguard Worker auto mbet = sk_gpu_test::ManagedBackendTexture::MakeWithoutData(
579*c8dee2aaSAndroid Build Coastguard Worker dContext, kSize, kSize, colorType, skgpu::Mipmapped::kNo, GrRenderable::kNo,
580*c8dee2aaSAndroid Build Coastguard Worker isProtected);
581*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> img;
582*c8dee2aaSAndroid Build Coastguard Worker if (mbet) {
583*c8dee2aaSAndroid Build Coastguard Worker img = SkImages::BorrowTextureFrom(dContext,
584*c8dee2aaSAndroid Build Coastguard Worker mbet->texture(),
585*c8dee2aaSAndroid Build Coastguard Worker kTopLeft_GrSurfaceOrigin,
586*c8dee2aaSAndroid Build Coastguard Worker colorType,
587*c8dee2aaSAndroid Build Coastguard Worker kOpaque_SkAlphaType,
588*c8dee2aaSAndroid Build Coastguard Worker nullptr);
589*c8dee2aaSAndroid Build Coastguard Worker }
590*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, can == SkToBool(img),
591*c8dee2aaSAndroid Build Coastguard Worker "colorTypeSupportedAsImage:%d, actual:%d, ct:%d", can, SkToBool(img),
592*c8dee2aaSAndroid Build Coastguard Worker colorType);
593*c8dee2aaSAndroid Build Coastguard Worker }
594*c8dee2aaSAndroid Build Coastguard Worker }
595*c8dee2aaSAndroid Build Coastguard Worker
DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(UnpremulTextureImage,reporter,ctxInfo,CtsEnforcement::kApiLevel_T)596*c8dee2aaSAndroid Build Coastguard Worker DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(UnpremulTextureImage,
597*c8dee2aaSAndroid Build Coastguard Worker reporter,
598*c8dee2aaSAndroid Build Coastguard Worker ctxInfo,
599*c8dee2aaSAndroid Build Coastguard Worker CtsEnforcement::kApiLevel_T) {
600*c8dee2aaSAndroid Build Coastguard Worker SkBitmap bmp;
601*c8dee2aaSAndroid Build Coastguard Worker bmp.allocPixels(
602*c8dee2aaSAndroid Build Coastguard Worker SkImageInfo::Make(256, 256, kRGBA_8888_SkColorType, kUnpremul_SkAlphaType, nullptr));
603*c8dee2aaSAndroid Build Coastguard Worker for (int y = 0; y < 256; ++y) {
604*c8dee2aaSAndroid Build Coastguard Worker for (int x = 0; x < 256; ++x) {
605*c8dee2aaSAndroid Build Coastguard Worker *bmp.getAddr32(x, y) =
606*c8dee2aaSAndroid Build Coastguard Worker SkColorSetARGB((U8CPU)y, 255 - (U8CPU)y, (U8CPU)x, 255 - (U8CPU)x);
607*c8dee2aaSAndroid Build Coastguard Worker }
608*c8dee2aaSAndroid Build Coastguard Worker }
609*c8dee2aaSAndroid Build Coastguard Worker auto dContext = ctxInfo.directContext();
610*c8dee2aaSAndroid Build Coastguard Worker auto texImage = SkImages::TextureFromImage(dContext, bmp.asImage());
611*c8dee2aaSAndroid Build Coastguard Worker if (!texImage || texImage->alphaType() != kUnpremul_SkAlphaType) {
612*c8dee2aaSAndroid Build Coastguard Worker ERRORF(reporter, "Failed to make unpremul texture image.");
613*c8dee2aaSAndroid Build Coastguard Worker return;
614*c8dee2aaSAndroid Build Coastguard Worker }
615*c8dee2aaSAndroid Build Coastguard Worker SkBitmap unpremul;
616*c8dee2aaSAndroid Build Coastguard Worker unpremul.allocPixels(SkImageInfo::Make(256, 256, kRGBA_8888_SkColorType,
617*c8dee2aaSAndroid Build Coastguard Worker kUnpremul_SkAlphaType, nullptr));
618*c8dee2aaSAndroid Build Coastguard Worker if (!texImage->readPixels(dContext, unpremul.info(), unpremul.getPixels(), unpremul.rowBytes(),
619*c8dee2aaSAndroid Build Coastguard Worker 0, 0)) {
620*c8dee2aaSAndroid Build Coastguard Worker ERRORF(reporter, "Unpremul readback failed.");
621*c8dee2aaSAndroid Build Coastguard Worker return;
622*c8dee2aaSAndroid Build Coastguard Worker }
623*c8dee2aaSAndroid Build Coastguard Worker for (int y = 0; y < 256; ++y) {
624*c8dee2aaSAndroid Build Coastguard Worker for (int x = 0; x < 256; ++x) {
625*c8dee2aaSAndroid Build Coastguard Worker if (*bmp.getAddr32(x, y) != *unpremul.getAddr32(x, y)) {
626*c8dee2aaSAndroid Build Coastguard Worker ERRORF(reporter, "unpremul(0x%08x)->unpremul(0x%08x) at %d, %d.",
627*c8dee2aaSAndroid Build Coastguard Worker *bmp.getAddr32(x, y), *unpremul.getAddr32(x, y), x, y);
628*c8dee2aaSAndroid Build Coastguard Worker return;
629*c8dee2aaSAndroid Build Coastguard Worker }
630*c8dee2aaSAndroid Build Coastguard Worker }
631*c8dee2aaSAndroid Build Coastguard Worker }
632*c8dee2aaSAndroid Build Coastguard Worker SkBitmap premul;
633*c8dee2aaSAndroid Build Coastguard Worker premul.allocPixels(
634*c8dee2aaSAndroid Build Coastguard Worker SkImageInfo::Make(256, 256, kRGBA_8888_SkColorType, kPremul_SkAlphaType, nullptr));
635*c8dee2aaSAndroid Build Coastguard Worker if (!texImage->readPixels(dContext, premul.info(), premul.getPixels(), premul.rowBytes(),
636*c8dee2aaSAndroid Build Coastguard Worker 0, 0)) {
637*c8dee2aaSAndroid Build Coastguard Worker ERRORF(reporter, "Unpremul readback failed.");
638*c8dee2aaSAndroid Build Coastguard Worker return;
639*c8dee2aaSAndroid Build Coastguard Worker }
640*c8dee2aaSAndroid Build Coastguard Worker for (int y = 0; y < 256; ++y) {
641*c8dee2aaSAndroid Build Coastguard Worker for (int x = 0; x < 256; ++x) {
642*c8dee2aaSAndroid Build Coastguard Worker uint32_t origColor = *bmp.getAddr32(x, y);
643*c8dee2aaSAndroid Build Coastguard Worker int32_t origA = (origColor >> 24) & 0xff;
644*c8dee2aaSAndroid Build Coastguard Worker float a = origA / 255.f;
645*c8dee2aaSAndroid Build Coastguard Worker int32_t origB = sk_float_round2int(((origColor >> 16) & 0xff) * a);
646*c8dee2aaSAndroid Build Coastguard Worker int32_t origG = sk_float_round2int(((origColor >> 8) & 0xff) * a);
647*c8dee2aaSAndroid Build Coastguard Worker int32_t origR = sk_float_round2int(((origColor >> 0) & 0xff) * a);
648*c8dee2aaSAndroid Build Coastguard Worker
649*c8dee2aaSAndroid Build Coastguard Worker uint32_t read = *premul.getAddr32(x, y);
650*c8dee2aaSAndroid Build Coastguard Worker int32_t readA = (read >> 24) & 0xff;
651*c8dee2aaSAndroid Build Coastguard Worker int32_t readB = (read >> 16) & 0xff;
652*c8dee2aaSAndroid Build Coastguard Worker int32_t readG = (read >> 8) & 0xff;
653*c8dee2aaSAndroid Build Coastguard Worker int32_t readR = (read >> 0) & 0xff;
654*c8dee2aaSAndroid Build Coastguard Worker // We expect that alpha=1 and alpha=0 should come out exact. Otherwise allow a little
655*c8dee2aaSAndroid Build Coastguard Worker // bit of tolerance for GPU vs CPU premul math.
656*c8dee2aaSAndroid Build Coastguard Worker int32_t tol = (origA == 0 || origA == 255) ? 0 : 1;
657*c8dee2aaSAndroid Build Coastguard Worker if (origA != readA || SkTAbs(readB - origB) > tol || SkTAbs(readG - origG) > tol ||
658*c8dee2aaSAndroid Build Coastguard Worker SkTAbs(readR - origR) > tol) {
659*c8dee2aaSAndroid Build Coastguard Worker ERRORF(reporter, "unpremul(0x%08x)->premul(0x%08x) expected(0x%08x) at %d, %d.",
660*c8dee2aaSAndroid Build Coastguard Worker *bmp.getAddr32(x, y), *premul.getAddr32(x, y), origColor, x, y);
661*c8dee2aaSAndroid Build Coastguard Worker return;
662*c8dee2aaSAndroid Build Coastguard Worker }
663*c8dee2aaSAndroid Build Coastguard Worker }
664*c8dee2aaSAndroid Build Coastguard Worker }
665*c8dee2aaSAndroid Build Coastguard Worker }
666*c8dee2aaSAndroid Build Coastguard Worker
DEF_GANESH_TEST(AbandonedContextImage,reporter,options,CtsEnforcement::kApiLevel_T)667*c8dee2aaSAndroid Build Coastguard Worker DEF_GANESH_TEST(AbandonedContextImage, reporter, options, CtsEnforcement::kApiLevel_T) {
668*c8dee2aaSAndroid Build Coastguard Worker using Factory = sk_gpu_test::GrContextFactory;
669*c8dee2aaSAndroid Build Coastguard Worker for (int ct = 0; ct < skgpu::kContextTypeCount; ++ct) {
670*c8dee2aaSAndroid Build Coastguard Worker auto type = static_cast<Factory::ContextType>(ct);
671*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<Factory> factory(new Factory);
672*c8dee2aaSAndroid Build Coastguard Worker if (!factory->get(type)) {
673*c8dee2aaSAndroid Build Coastguard Worker continue;
674*c8dee2aaSAndroid Build Coastguard Worker }
675*c8dee2aaSAndroid Build Coastguard Worker
676*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> img;
677*c8dee2aaSAndroid Build Coastguard Worker auto gsurf = SkSurfaces::RenderTarget(
678*c8dee2aaSAndroid Build Coastguard Worker factory->get(type),
679*c8dee2aaSAndroid Build Coastguard Worker skgpu::Budgeted::kYes,
680*c8dee2aaSAndroid Build Coastguard Worker SkImageInfo::Make(100, 100, kRGBA_8888_SkColorType, kPremul_SkAlphaType),
681*c8dee2aaSAndroid Build Coastguard Worker 1,
682*c8dee2aaSAndroid Build Coastguard Worker nullptr);
683*c8dee2aaSAndroid Build Coastguard Worker if (!gsurf) {
684*c8dee2aaSAndroid Build Coastguard Worker continue;
685*c8dee2aaSAndroid Build Coastguard Worker }
686*c8dee2aaSAndroid Build Coastguard Worker img = gsurf->makeImageSnapshot();
687*c8dee2aaSAndroid Build Coastguard Worker gsurf.reset();
688*c8dee2aaSAndroid Build Coastguard Worker
689*c8dee2aaSAndroid Build Coastguard Worker auto rsurf = SkSurfaces::Raster(SkImageInfo::MakeN32Premul(100, 100));
690*c8dee2aaSAndroid Build Coastguard Worker
691*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, img->isValid(factory->get(type)));
692*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, img->isValid(rsurf->getCanvas()->recordingContext()));
693*c8dee2aaSAndroid Build Coastguard Worker
694*c8dee2aaSAndroid Build Coastguard Worker factory->get(type)->abandonContext();
695*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, !img->isValid(factory->get(type)));
696*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, !img->isValid(rsurf->getCanvas()->recordingContext()));
697*c8dee2aaSAndroid Build Coastguard Worker // This shouldn't crash.
698*c8dee2aaSAndroid Build Coastguard Worker rsurf->getCanvas()->drawImage(img, 0, 0);
699*c8dee2aaSAndroid Build Coastguard Worker
700*c8dee2aaSAndroid Build Coastguard Worker // Give up all other refs on the context.
701*c8dee2aaSAndroid Build Coastguard Worker factory.reset(nullptr);
702*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, !img->isValid(rsurf->getCanvas()->recordingContext()));
703*c8dee2aaSAndroid Build Coastguard Worker // This shouldn't crash.
704*c8dee2aaSAndroid Build Coastguard Worker rsurf->getCanvas()->drawImage(img, 0, 0);
705*c8dee2aaSAndroid Build Coastguard Worker }
706*c8dee2aaSAndroid Build Coastguard Worker }
707*c8dee2aaSAndroid Build Coastguard Worker
708*c8dee2aaSAndroid Build Coastguard Worker class EmptyGenerator : public SkImageGenerator {
709*c8dee2aaSAndroid Build Coastguard Worker public:
EmptyGenerator()710*c8dee2aaSAndroid Build Coastguard Worker EmptyGenerator() : SkImageGenerator(SkImageInfo::MakeN32Premul(0, 0)) {}
711*c8dee2aaSAndroid Build Coastguard Worker };
712*c8dee2aaSAndroid Build Coastguard Worker
DEF_TEST(ImageEmpty,reporter)713*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(ImageEmpty, reporter) {
714*c8dee2aaSAndroid Build Coastguard Worker const SkImageInfo info = SkImageInfo::Make(0, 0, kN32_SkColorType, kPremul_SkAlphaType);
715*c8dee2aaSAndroid Build Coastguard Worker SkPixmap pmap(info, nullptr, 0);
716*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, nullptr == SkImages::RasterFromPixmapCopy(pmap));
717*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, nullptr == SkImages::RasterFromData(info, nullptr, 0));
718*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, nullptr == SkImages::RasterFromPixmap(pmap, nullptr, nullptr));
719*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter,
720*c8dee2aaSAndroid Build Coastguard Worker nullptr == SkImages::DeferredFromGenerator(std::make_unique<EmptyGenerator>()));
721*c8dee2aaSAndroid Build Coastguard Worker }
722*c8dee2aaSAndroid Build Coastguard Worker
DEF_TEST(ImageDataRef,reporter)723*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(ImageDataRef, reporter) {
724*c8dee2aaSAndroid Build Coastguard Worker SkImageInfo info = SkImageInfo::MakeN32Premul(1, 1);
725*c8dee2aaSAndroid Build Coastguard Worker size_t rowBytes = info.minRowBytes();
726*c8dee2aaSAndroid Build Coastguard Worker size_t size = info.computeByteSize(rowBytes);
727*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkData> data = SkData::MakeUninitialized(size);
728*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, data->unique());
729*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> image = SkImages::RasterFromData(info, data, rowBytes);
730*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, !data->unique());
731*c8dee2aaSAndroid Build Coastguard Worker image.reset();
732*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, data->unique());
733*c8dee2aaSAndroid Build Coastguard Worker }
734*c8dee2aaSAndroid Build Coastguard Worker
has_pixels(const SkPMColor pixels[],int count,SkPMColor expected)735*c8dee2aaSAndroid Build Coastguard Worker static bool has_pixels(const SkPMColor pixels[], int count, SkPMColor expected) {
736*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < count; ++i) {
737*c8dee2aaSAndroid Build Coastguard Worker if (pixels[i] != expected) {
738*c8dee2aaSAndroid Build Coastguard Worker return false;
739*c8dee2aaSAndroid Build Coastguard Worker }
740*c8dee2aaSAndroid Build Coastguard Worker }
741*c8dee2aaSAndroid Build Coastguard Worker return true;
742*c8dee2aaSAndroid Build Coastguard Worker }
743*c8dee2aaSAndroid Build Coastguard Worker
image_test_read_pixels(GrDirectContext * dContext,skiatest::Reporter * reporter,SkImage * image)744*c8dee2aaSAndroid Build Coastguard Worker static void image_test_read_pixels(GrDirectContext* dContext, skiatest::Reporter* reporter,
745*c8dee2aaSAndroid Build Coastguard Worker SkImage* image) {
746*c8dee2aaSAndroid Build Coastguard Worker if (!image) {
747*c8dee2aaSAndroid Build Coastguard Worker ERRORF(reporter, "Failed to create image!");
748*c8dee2aaSAndroid Build Coastguard Worker return;
749*c8dee2aaSAndroid Build Coastguard Worker }
750*c8dee2aaSAndroid Build Coastguard Worker const SkPMColor expected = SkPreMultiplyColor(SK_ColorWHITE);
751*c8dee2aaSAndroid Build Coastguard Worker const SkPMColor notExpected = ~expected;
752*c8dee2aaSAndroid Build Coastguard Worker
753*c8dee2aaSAndroid Build Coastguard Worker const int w = 2, h = 2;
754*c8dee2aaSAndroid Build Coastguard Worker const size_t rowBytes = w * sizeof(SkPMColor);
755*c8dee2aaSAndroid Build Coastguard Worker SkPMColor pixels[w*h];
756*c8dee2aaSAndroid Build Coastguard Worker
757*c8dee2aaSAndroid Build Coastguard Worker SkImageInfo info;
758*c8dee2aaSAndroid Build Coastguard Worker
759*c8dee2aaSAndroid Build Coastguard Worker info = SkImageInfo::MakeUnknown(w, h);
760*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, !image->readPixels(dContext, info, pixels, rowBytes, 0, 0));
761*c8dee2aaSAndroid Build Coastguard Worker
762*c8dee2aaSAndroid Build Coastguard Worker // out-of-bounds should fail
763*c8dee2aaSAndroid Build Coastguard Worker info = SkImageInfo::MakeN32Premul(w, h);
764*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, !image->readPixels(dContext, info, pixels, rowBytes, -w, 0));
765*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, !image->readPixels(dContext, info, pixels, rowBytes, 0, -h));
766*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, !image->readPixels(dContext, info, pixels, rowBytes,
767*c8dee2aaSAndroid Build Coastguard Worker image->width(), 0));
768*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, !image->readPixels(dContext, info, pixels, rowBytes,
769*c8dee2aaSAndroid Build Coastguard Worker 0, image->height()));
770*c8dee2aaSAndroid Build Coastguard Worker
771*c8dee2aaSAndroid Build Coastguard Worker // top-left should succeed
772*c8dee2aaSAndroid Build Coastguard Worker SkOpts::memset32(pixels, notExpected, w*h);
773*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, image->readPixels(dContext, info, pixels, rowBytes, 0, 0));
774*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, has_pixels(pixels, w*h, expected));
775*c8dee2aaSAndroid Build Coastguard Worker
776*c8dee2aaSAndroid Build Coastguard Worker // bottom-right should succeed
777*c8dee2aaSAndroid Build Coastguard Worker SkOpts::memset32(pixels, notExpected, w*h);
778*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, image->readPixels(dContext, info, pixels, rowBytes,
779*c8dee2aaSAndroid Build Coastguard Worker image->width() - w, image->height() - h));
780*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, has_pixels(pixels, w*h, expected));
781*c8dee2aaSAndroid Build Coastguard Worker
782*c8dee2aaSAndroid Build Coastguard Worker // partial top-left should succeed
783*c8dee2aaSAndroid Build Coastguard Worker SkOpts::memset32(pixels, notExpected, w*h);
784*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, image->readPixels(dContext, info, pixels, rowBytes, -1, -1));
785*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, pixels[3] == expected);
786*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, has_pixels(pixels, w*h - 1, notExpected));
787*c8dee2aaSAndroid Build Coastguard Worker
788*c8dee2aaSAndroid Build Coastguard Worker // partial bottom-right should succeed
789*c8dee2aaSAndroid Build Coastguard Worker SkOpts::memset32(pixels, notExpected, w*h);
790*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, image->readPixels(dContext, info, pixels, rowBytes,
791*c8dee2aaSAndroid Build Coastguard Worker image->width() - 1, image->height() - 1));
792*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, pixels[0] == expected);
793*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, has_pixels(&pixels[1], w*h - 1, notExpected));
794*c8dee2aaSAndroid Build Coastguard Worker }
DEF_TEST(ImageReadPixels,reporter)795*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(ImageReadPixels, reporter) {
796*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> image(create_image());
797*c8dee2aaSAndroid Build Coastguard Worker image_test_read_pixels(nullptr, reporter, image.get());
798*c8dee2aaSAndroid Build Coastguard Worker
799*c8dee2aaSAndroid Build Coastguard Worker image = create_data_image();
800*c8dee2aaSAndroid Build Coastguard Worker image_test_read_pixels(nullptr, reporter, image.get());
801*c8dee2aaSAndroid Build Coastguard Worker
802*c8dee2aaSAndroid Build Coastguard Worker RasterDataHolder dataHolder;
803*c8dee2aaSAndroid Build Coastguard Worker image = create_rasterproc_image(&dataHolder);
804*c8dee2aaSAndroid Build Coastguard Worker image_test_read_pixels(nullptr, reporter, image.get());
805*c8dee2aaSAndroid Build Coastguard Worker image.reset();
806*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 1 == dataHolder.fReleaseCount);
807*c8dee2aaSAndroid Build Coastguard Worker
808*c8dee2aaSAndroid Build Coastguard Worker image = create_codec_image();
809*c8dee2aaSAndroid Build Coastguard Worker image_test_read_pixels(nullptr, reporter, image.get());
810*c8dee2aaSAndroid Build Coastguard Worker }
DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(ImageReadPixels_Gpu,reporter,ctxInfo,CtsEnforcement::kApiLevel_T)811*c8dee2aaSAndroid Build Coastguard Worker DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(ImageReadPixels_Gpu,
812*c8dee2aaSAndroid Build Coastguard Worker reporter,
813*c8dee2aaSAndroid Build Coastguard Worker ctxInfo,
814*c8dee2aaSAndroid Build Coastguard Worker CtsEnforcement::kApiLevel_T) {
815*c8dee2aaSAndroid Build Coastguard Worker auto dContext = ctxInfo.directContext();
816*c8dee2aaSAndroid Build Coastguard Worker image_test_read_pixels(dContext, reporter, create_gpu_image(dContext).get());
817*c8dee2aaSAndroid Build Coastguard Worker }
818*c8dee2aaSAndroid Build Coastguard Worker
check_legacy_bitmap(skiatest::Reporter * reporter,GrDirectContext * dContext,const SkImage * image,const SkBitmap & bitmap)819*c8dee2aaSAndroid Build Coastguard Worker static void check_legacy_bitmap(skiatest::Reporter* reporter, GrDirectContext* dContext,
820*c8dee2aaSAndroid Build Coastguard Worker const SkImage* image, const SkBitmap& bitmap) {
821*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, image->width() == bitmap.width());
822*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, image->height() == bitmap.height());
823*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, image->alphaType() == bitmap.alphaType());
824*c8dee2aaSAndroid Build Coastguard Worker
825*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, bitmap.isImmutable());
826*c8dee2aaSAndroid Build Coastguard Worker
827*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, bitmap.getPixels());
828*c8dee2aaSAndroid Build Coastguard Worker
829*c8dee2aaSAndroid Build Coastguard Worker const SkImageInfo info = SkImageInfo::MakeN32(1, 1, bitmap.alphaType());
830*c8dee2aaSAndroid Build Coastguard Worker SkPMColor imageColor;
831*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, image->readPixels(dContext, info, &imageColor, sizeof(SkPMColor),
832*c8dee2aaSAndroid Build Coastguard Worker 0, 0));
833*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, imageColor == *bitmap.getAddr32(0, 0));
834*c8dee2aaSAndroid Build Coastguard Worker }
835*c8dee2aaSAndroid Build Coastguard Worker
test_legacy_bitmap(skiatest::Reporter * reporter,GrDirectContext * dContext,const SkImage * image)836*c8dee2aaSAndroid Build Coastguard Worker static void test_legacy_bitmap(skiatest::Reporter* reporter, GrDirectContext* dContext,
837*c8dee2aaSAndroid Build Coastguard Worker const SkImage* image) {
838*c8dee2aaSAndroid Build Coastguard Worker if (!image) {
839*c8dee2aaSAndroid Build Coastguard Worker ERRORF(reporter, "Failed to create image.");
840*c8dee2aaSAndroid Build Coastguard Worker return;
841*c8dee2aaSAndroid Build Coastguard Worker }
842*c8dee2aaSAndroid Build Coastguard Worker SkBitmap bitmap;
843*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, image->asLegacyBitmap(&bitmap));
844*c8dee2aaSAndroid Build Coastguard Worker check_legacy_bitmap(reporter, dContext, image, bitmap);
845*c8dee2aaSAndroid Build Coastguard Worker
846*c8dee2aaSAndroid Build Coastguard Worker // Test subsetting to exercise the rowBytes logic.
847*c8dee2aaSAndroid Build Coastguard Worker SkBitmap tmp;
848*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, bitmap.extractSubset(&tmp, SkIRect::MakeWH(image->width() / 2,
849*c8dee2aaSAndroid Build Coastguard Worker image->height() / 2)));
850*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> subsetImage(tmp.asImage());
851*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, subsetImage.get());
852*c8dee2aaSAndroid Build Coastguard Worker
853*c8dee2aaSAndroid Build Coastguard Worker SkBitmap subsetBitmap;
854*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, subsetImage->asLegacyBitmap(&subsetBitmap));
855*c8dee2aaSAndroid Build Coastguard Worker check_legacy_bitmap(reporter, nullptr, subsetImage.get(), subsetBitmap);
856*c8dee2aaSAndroid Build Coastguard Worker }
DEF_TEST(ImageLegacyBitmap,reporter)857*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(ImageLegacyBitmap, reporter) {
858*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> image(create_image());
859*c8dee2aaSAndroid Build Coastguard Worker test_legacy_bitmap(reporter, nullptr, image.get());
860*c8dee2aaSAndroid Build Coastguard Worker
861*c8dee2aaSAndroid Build Coastguard Worker image = create_data_image();
862*c8dee2aaSAndroid Build Coastguard Worker test_legacy_bitmap(reporter, nullptr, image.get());
863*c8dee2aaSAndroid Build Coastguard Worker
864*c8dee2aaSAndroid Build Coastguard Worker RasterDataHolder dataHolder;
865*c8dee2aaSAndroid Build Coastguard Worker image = create_rasterproc_image(&dataHolder);
866*c8dee2aaSAndroid Build Coastguard Worker test_legacy_bitmap(reporter, nullptr, image.get());
867*c8dee2aaSAndroid Build Coastguard Worker image.reset();
868*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 1 == dataHolder.fReleaseCount);
869*c8dee2aaSAndroid Build Coastguard Worker
870*c8dee2aaSAndroid Build Coastguard Worker image = create_codec_image();
871*c8dee2aaSAndroid Build Coastguard Worker test_legacy_bitmap(reporter, nullptr, image.get());
872*c8dee2aaSAndroid Build Coastguard Worker }
DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(ImageLegacyBitmap_Gpu,reporter,ctxInfo,CtsEnforcement::kApiLevel_T)873*c8dee2aaSAndroid Build Coastguard Worker DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(ImageLegacyBitmap_Gpu,
874*c8dee2aaSAndroid Build Coastguard Worker reporter,
875*c8dee2aaSAndroid Build Coastguard Worker ctxInfo,
876*c8dee2aaSAndroid Build Coastguard Worker CtsEnforcement::kApiLevel_T) {
877*c8dee2aaSAndroid Build Coastguard Worker auto dContext = ctxInfo.directContext();
878*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> image(create_gpu_image(dContext));
879*c8dee2aaSAndroid Build Coastguard Worker test_legacy_bitmap(reporter, dContext, image.get());
880*c8dee2aaSAndroid Build Coastguard Worker }
881*c8dee2aaSAndroid Build Coastguard Worker
test_peek(skiatest::Reporter * reporter,SkImage * image,bool expectPeekSuccess)882*c8dee2aaSAndroid Build Coastguard Worker static void test_peek(skiatest::Reporter* reporter, SkImage* image, bool expectPeekSuccess) {
883*c8dee2aaSAndroid Build Coastguard Worker if (!image) {
884*c8dee2aaSAndroid Build Coastguard Worker ERRORF(reporter, "Failed to create image!");
885*c8dee2aaSAndroid Build Coastguard Worker return;
886*c8dee2aaSAndroid Build Coastguard Worker }
887*c8dee2aaSAndroid Build Coastguard Worker SkPixmap pm;
888*c8dee2aaSAndroid Build Coastguard Worker bool success = image->peekPixels(&pm);
889*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, expectPeekSuccess == success);
890*c8dee2aaSAndroid Build Coastguard Worker if (success) {
891*c8dee2aaSAndroid Build Coastguard Worker const SkImageInfo& info = pm.info();
892*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 20 == info.width());
893*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 20 == info.height());
894*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, kN32_SkColorType == info.colorType());
895*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, kPremul_SkAlphaType == info.alphaType() ||
896*c8dee2aaSAndroid Build Coastguard Worker kOpaque_SkAlphaType == info.alphaType());
897*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, info.minRowBytes() <= pm.rowBytes());
898*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, SkPreMultiplyColor(SK_ColorWHITE) == *pm.addr32(0, 0));
899*c8dee2aaSAndroid Build Coastguard Worker }
900*c8dee2aaSAndroid Build Coastguard Worker }
DEF_TEST(ImagePeek,reporter)901*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(ImagePeek, reporter) {
902*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> image(create_image());
903*c8dee2aaSAndroid Build Coastguard Worker test_peek(reporter, image.get(), true);
904*c8dee2aaSAndroid Build Coastguard Worker
905*c8dee2aaSAndroid Build Coastguard Worker image = create_data_image();
906*c8dee2aaSAndroid Build Coastguard Worker test_peek(reporter, image.get(), true);
907*c8dee2aaSAndroid Build Coastguard Worker
908*c8dee2aaSAndroid Build Coastguard Worker RasterDataHolder dataHolder;
909*c8dee2aaSAndroid Build Coastguard Worker image = create_rasterproc_image(&dataHolder);
910*c8dee2aaSAndroid Build Coastguard Worker test_peek(reporter, image.get(), true);
911*c8dee2aaSAndroid Build Coastguard Worker image.reset();
912*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 1 == dataHolder.fReleaseCount);
913*c8dee2aaSAndroid Build Coastguard Worker
914*c8dee2aaSAndroid Build Coastguard Worker image = create_codec_image();
915*c8dee2aaSAndroid Build Coastguard Worker test_peek(reporter, image.get(), false);
916*c8dee2aaSAndroid Build Coastguard Worker }
DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(ImagePeek_Gpu,reporter,ctxInfo,CtsEnforcement::kApiLevel_T)917*c8dee2aaSAndroid Build Coastguard Worker DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(ImagePeek_Gpu,
918*c8dee2aaSAndroid Build Coastguard Worker reporter,
919*c8dee2aaSAndroid Build Coastguard Worker ctxInfo,
920*c8dee2aaSAndroid Build Coastguard Worker CtsEnforcement::kApiLevel_T) {
921*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> image(create_gpu_image(ctxInfo.directContext()));
922*c8dee2aaSAndroid Build Coastguard Worker test_peek(reporter, image.get(), false);
923*c8dee2aaSAndroid Build Coastguard Worker }
924*c8dee2aaSAndroid Build Coastguard Worker
925*c8dee2aaSAndroid Build Coastguard Worker struct TextureReleaseChecker {
TextureReleaseCheckerTextureReleaseChecker926*c8dee2aaSAndroid Build Coastguard Worker TextureReleaseChecker() : fReleaseCount(0) {}
927*c8dee2aaSAndroid Build Coastguard Worker int fReleaseCount;
ReleaseTextureReleaseChecker928*c8dee2aaSAndroid Build Coastguard Worker static void Release(void* self) {
929*c8dee2aaSAndroid Build Coastguard Worker static_cast<TextureReleaseChecker*>(self)->fReleaseCount++;
930*c8dee2aaSAndroid Build Coastguard Worker }
931*c8dee2aaSAndroid Build Coastguard Worker };
932*c8dee2aaSAndroid Build Coastguard Worker
DEF_GANESH_TEST_FOR_GL_CONTEXT(SkImage_NewFromTextureRelease,reporter,ctxInfo,CtsEnforcement::kApiLevel_T)933*c8dee2aaSAndroid Build Coastguard Worker DEF_GANESH_TEST_FOR_GL_CONTEXT(SkImage_NewFromTextureRelease,
934*c8dee2aaSAndroid Build Coastguard Worker reporter,
935*c8dee2aaSAndroid Build Coastguard Worker ctxInfo,
936*c8dee2aaSAndroid Build Coastguard Worker CtsEnforcement::kApiLevel_T) {
937*c8dee2aaSAndroid Build Coastguard Worker const int kWidth = 10;
938*c8dee2aaSAndroid Build Coastguard Worker const int kHeight = 10;
939*c8dee2aaSAndroid Build Coastguard Worker
940*c8dee2aaSAndroid Build Coastguard Worker auto dContext = ctxInfo.directContext();
941*c8dee2aaSAndroid Build Coastguard Worker
942*c8dee2aaSAndroid Build Coastguard Worker auto mbet = sk_gpu_test::ManagedBackendTexture::MakeWithoutData(dContext,
943*c8dee2aaSAndroid Build Coastguard Worker kWidth,
944*c8dee2aaSAndroid Build Coastguard Worker kHeight,
945*c8dee2aaSAndroid Build Coastguard Worker kRGBA_8888_SkColorType,
946*c8dee2aaSAndroid Build Coastguard Worker skgpu::Mipmapped::kNo,
947*c8dee2aaSAndroid Build Coastguard Worker GrRenderable::kNo,
948*c8dee2aaSAndroid Build Coastguard Worker GrProtected::kNo);
949*c8dee2aaSAndroid Build Coastguard Worker if (!mbet) {
950*c8dee2aaSAndroid Build Coastguard Worker ERRORF(reporter, "couldn't create backend texture\n");
951*c8dee2aaSAndroid Build Coastguard Worker return;
952*c8dee2aaSAndroid Build Coastguard Worker }
953*c8dee2aaSAndroid Build Coastguard Worker
954*c8dee2aaSAndroid Build Coastguard Worker TextureReleaseChecker releaseChecker;
955*c8dee2aaSAndroid Build Coastguard Worker GrSurfaceOrigin texOrigin = kBottomLeft_GrSurfaceOrigin;
956*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> refImg = SkImages::BorrowTextureFrom(
957*c8dee2aaSAndroid Build Coastguard Worker dContext,
958*c8dee2aaSAndroid Build Coastguard Worker mbet->texture(),
959*c8dee2aaSAndroid Build Coastguard Worker texOrigin,
960*c8dee2aaSAndroid Build Coastguard Worker kRGBA_8888_SkColorType,
961*c8dee2aaSAndroid Build Coastguard Worker kPremul_SkAlphaType,
962*c8dee2aaSAndroid Build Coastguard Worker /*color space*/ nullptr,
963*c8dee2aaSAndroid Build Coastguard Worker sk_gpu_test::ManagedBackendTexture::ReleaseProc,
964*c8dee2aaSAndroid Build Coastguard Worker mbet->releaseContext(TextureReleaseChecker::Release, &releaseChecker));
965*c8dee2aaSAndroid Build Coastguard Worker
966*c8dee2aaSAndroid Build Coastguard Worker GrSurfaceOrigin readBackOrigin;
967*c8dee2aaSAndroid Build Coastguard Worker GrBackendTexture readBackBackendTex;
968*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter,
969*c8dee2aaSAndroid Build Coastguard Worker SkImages::GetBackendTextureFromImage(
970*c8dee2aaSAndroid Build Coastguard Worker refImg, &readBackBackendTex, false, &readBackOrigin),
971*c8dee2aaSAndroid Build Coastguard Worker "Did not get backend texture");
972*c8dee2aaSAndroid Build Coastguard Worker if (!GrBackendTexture::TestingOnly_Equals(readBackBackendTex, mbet->texture())) {
973*c8dee2aaSAndroid Build Coastguard Worker ERRORF(reporter, "backend mismatch\n");
974*c8dee2aaSAndroid Build Coastguard Worker }
975*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter,
976*c8dee2aaSAndroid Build Coastguard Worker GrBackendTexture::TestingOnly_Equals(readBackBackendTex, mbet->texture()));
977*c8dee2aaSAndroid Build Coastguard Worker if (readBackOrigin != texOrigin) {
978*c8dee2aaSAndroid Build Coastguard Worker ERRORF(reporter, "origin mismatch %d %d\n", readBackOrigin, texOrigin);
979*c8dee2aaSAndroid Build Coastguard Worker }
980*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, readBackOrigin == texOrigin);
981*c8dee2aaSAndroid Build Coastguard Worker
982*c8dee2aaSAndroid Build Coastguard Worker // Now exercise the release proc
983*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 0 == releaseChecker.fReleaseCount);
984*c8dee2aaSAndroid Build Coastguard Worker refImg.reset(nullptr); // force a release of the image
985*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 1 == releaseChecker.fReleaseCount);
986*c8dee2aaSAndroid Build Coastguard Worker }
987*c8dee2aaSAndroid Build Coastguard Worker
test_cross_context_image(skiatest::Reporter * reporter,const GrContextOptions & options,const char * testName,const std::function<sk_sp<SkImage> (GrDirectContext *)> & imageMaker)988*c8dee2aaSAndroid Build Coastguard Worker static void test_cross_context_image(
989*c8dee2aaSAndroid Build Coastguard Worker skiatest::Reporter* reporter,
990*c8dee2aaSAndroid Build Coastguard Worker const GrContextOptions& options,
991*c8dee2aaSAndroid Build Coastguard Worker const char* testName,
992*c8dee2aaSAndroid Build Coastguard Worker const std::function<sk_sp<SkImage>(GrDirectContext*)>& imageMaker) {
993*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < skgpu::kContextTypeCount; ++i) {
994*c8dee2aaSAndroid Build Coastguard Worker GrContextFactory testFactory(options);
995*c8dee2aaSAndroid Build Coastguard Worker skgpu::ContextType ctxType = static_cast<skgpu::ContextType>(i);
996*c8dee2aaSAndroid Build Coastguard Worker ContextInfo ctxInfo = testFactory.getContextInfo(ctxType);
997*c8dee2aaSAndroid Build Coastguard Worker auto dContext = ctxInfo.directContext();
998*c8dee2aaSAndroid Build Coastguard Worker if (!dContext) {
999*c8dee2aaSAndroid Build Coastguard Worker continue;
1000*c8dee2aaSAndroid Build Coastguard Worker }
1001*c8dee2aaSAndroid Build Coastguard Worker
1002*c8dee2aaSAndroid Build Coastguard Worker // If we don't have proper support for this feature, the factory will fallback to returning
1003*c8dee2aaSAndroid Build Coastguard Worker // codec-backed images. Those will "work", but some of our checks will fail because we
1004*c8dee2aaSAndroid Build Coastguard Worker // expect the cross-context images not to work on multiple contexts at once.
1005*c8dee2aaSAndroid Build Coastguard Worker if (!dContext->priv().caps()->crossContextTextureSupport()) {
1006*c8dee2aaSAndroid Build Coastguard Worker continue;
1007*c8dee2aaSAndroid Build Coastguard Worker }
1008*c8dee2aaSAndroid Build Coastguard Worker
1009*c8dee2aaSAndroid Build Coastguard Worker // We test three lifetime patterns for a single context:
1010*c8dee2aaSAndroid Build Coastguard Worker // 1) Create image, free image
1011*c8dee2aaSAndroid Build Coastguard Worker // 2) Create image, draw, flush, free image
1012*c8dee2aaSAndroid Build Coastguard Worker // 3) Create image, draw, free image, flush
1013*c8dee2aaSAndroid Build Coastguard Worker // ... and then repeat the last two patterns with drawing on a second* context:
1014*c8dee2aaSAndroid Build Coastguard Worker // 4) Create image, draw*, flush*, free image
1015*c8dee2aaSAndroid Build Coastguard Worker // 5) Create image, draw*, free image, flush*
1016*c8dee2aaSAndroid Build Coastguard Worker
1017*c8dee2aaSAndroid Build Coastguard Worker // Case #1: Create image, free image
1018*c8dee2aaSAndroid Build Coastguard Worker {
1019*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> refImg(imageMaker(dContext));
1020*c8dee2aaSAndroid Build Coastguard Worker refImg.reset(nullptr); // force a release of the image
1021*c8dee2aaSAndroid Build Coastguard Worker }
1022*c8dee2aaSAndroid Build Coastguard Worker
1023*c8dee2aaSAndroid Build Coastguard Worker SkImageInfo info = SkImageInfo::MakeN32Premul(128, 128);
1024*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkSurface> surface = SkSurfaces::RenderTarget(dContext, skgpu::Budgeted::kNo, info);
1025*c8dee2aaSAndroid Build Coastguard Worker if (!surface) {
1026*c8dee2aaSAndroid Build Coastguard Worker ERRORF(reporter, "SkSurfaces::RenderTarget failed for %s.", testName);
1027*c8dee2aaSAndroid Build Coastguard Worker continue;
1028*c8dee2aaSAndroid Build Coastguard Worker }
1029*c8dee2aaSAndroid Build Coastguard Worker
1030*c8dee2aaSAndroid Build Coastguard Worker SkCanvas* canvas = surface->getCanvas();
1031*c8dee2aaSAndroid Build Coastguard Worker
1032*c8dee2aaSAndroid Build Coastguard Worker // Case #2: Create image, draw, flush, free image
1033*c8dee2aaSAndroid Build Coastguard Worker {
1034*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> refImg(imageMaker(dContext));
1035*c8dee2aaSAndroid Build Coastguard Worker
1036*c8dee2aaSAndroid Build Coastguard Worker canvas->drawImage(refImg, 0, 0);
1037*c8dee2aaSAndroid Build Coastguard Worker dContext->flushAndSubmit(surface.get(), GrSyncCpu::kNo);
1038*c8dee2aaSAndroid Build Coastguard Worker
1039*c8dee2aaSAndroid Build Coastguard Worker refImg.reset(nullptr); // force a release of the image
1040*c8dee2aaSAndroid Build Coastguard Worker }
1041*c8dee2aaSAndroid Build Coastguard Worker
1042*c8dee2aaSAndroid Build Coastguard Worker // Case #3: Create image, draw, free image, flush
1043*c8dee2aaSAndroid Build Coastguard Worker {
1044*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> refImg(imageMaker(dContext));
1045*c8dee2aaSAndroid Build Coastguard Worker
1046*c8dee2aaSAndroid Build Coastguard Worker canvas->drawImage(refImg, 0, 0);
1047*c8dee2aaSAndroid Build Coastguard Worker refImg.reset(nullptr); // force a release of the image
1048*c8dee2aaSAndroid Build Coastguard Worker
1049*c8dee2aaSAndroid Build Coastguard Worker dContext->flushAndSubmit(surface.get(), GrSyncCpu::kNo);
1050*c8dee2aaSAndroid Build Coastguard Worker }
1051*c8dee2aaSAndroid Build Coastguard Worker
1052*c8dee2aaSAndroid Build Coastguard Worker // Configure second context
1053*c8dee2aaSAndroid Build Coastguard Worker sk_gpu_test::TestContext* testContext = ctxInfo.testContext();
1054*c8dee2aaSAndroid Build Coastguard Worker
1055*c8dee2aaSAndroid Build Coastguard Worker ContextInfo otherContextInfo = testFactory.getSharedContextInfo(dContext);
1056*c8dee2aaSAndroid Build Coastguard Worker auto otherCtx = otherContextInfo.directContext();
1057*c8dee2aaSAndroid Build Coastguard Worker sk_gpu_test::TestContext* otherTestContext = otherContextInfo.testContext();
1058*c8dee2aaSAndroid Build Coastguard Worker
1059*c8dee2aaSAndroid Build Coastguard Worker // Creating a context in a share group may fail
1060*c8dee2aaSAndroid Build Coastguard Worker if (!otherCtx) {
1061*c8dee2aaSAndroid Build Coastguard Worker continue;
1062*c8dee2aaSAndroid Build Coastguard Worker }
1063*c8dee2aaSAndroid Build Coastguard Worker
1064*c8dee2aaSAndroid Build Coastguard Worker surface = SkSurfaces::RenderTarget(otherCtx, skgpu::Budgeted::kNo, info);
1065*c8dee2aaSAndroid Build Coastguard Worker canvas = surface->getCanvas();
1066*c8dee2aaSAndroid Build Coastguard Worker
1067*c8dee2aaSAndroid Build Coastguard Worker // Case #4: Create image, draw*, flush*, free image
1068*c8dee2aaSAndroid Build Coastguard Worker {
1069*c8dee2aaSAndroid Build Coastguard Worker testContext->makeCurrent();
1070*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> refImg(imageMaker(dContext));
1071*c8dee2aaSAndroid Build Coastguard Worker
1072*c8dee2aaSAndroid Build Coastguard Worker otherTestContext->makeCurrent();
1073*c8dee2aaSAndroid Build Coastguard Worker canvas->drawImage(refImg, 0, 0);
1074*c8dee2aaSAndroid Build Coastguard Worker otherCtx->flushAndSubmit(surface.get(), GrSyncCpu::kNo);
1075*c8dee2aaSAndroid Build Coastguard Worker
1076*c8dee2aaSAndroid Build Coastguard Worker testContext->makeCurrent();
1077*c8dee2aaSAndroid Build Coastguard Worker refImg.reset(nullptr); // force a release of the image
1078*c8dee2aaSAndroid Build Coastguard Worker }
1079*c8dee2aaSAndroid Build Coastguard Worker
1080*c8dee2aaSAndroid Build Coastguard Worker // Case #5: Create image, draw*, free image, flush*
1081*c8dee2aaSAndroid Build Coastguard Worker {
1082*c8dee2aaSAndroid Build Coastguard Worker testContext->makeCurrent();
1083*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> refImg(imageMaker(dContext));
1084*c8dee2aaSAndroid Build Coastguard Worker
1085*c8dee2aaSAndroid Build Coastguard Worker otherTestContext->makeCurrent();
1086*c8dee2aaSAndroid Build Coastguard Worker canvas->drawImage(refImg, 0, 0);
1087*c8dee2aaSAndroid Build Coastguard Worker
1088*c8dee2aaSAndroid Build Coastguard Worker testContext->makeCurrent();
1089*c8dee2aaSAndroid Build Coastguard Worker refImg.reset(nullptr); // force a release of the image
1090*c8dee2aaSAndroid Build Coastguard Worker
1091*c8dee2aaSAndroid Build Coastguard Worker otherTestContext->makeCurrent();
1092*c8dee2aaSAndroid Build Coastguard Worker // Sync is specifically here for vulkan to guarantee the command buffer will finish
1093*c8dee2aaSAndroid Build Coastguard Worker // which is when we call the ReleaseProc.
1094*c8dee2aaSAndroid Build Coastguard Worker otherCtx->flushAndSubmit(surface.get(), GrSyncCpu::kYes);
1095*c8dee2aaSAndroid Build Coastguard Worker }
1096*c8dee2aaSAndroid Build Coastguard Worker
1097*c8dee2aaSAndroid Build Coastguard Worker // Case #6: Verify that only one context can be using the image at a time
1098*c8dee2aaSAndroid Build Coastguard Worker {
1099*c8dee2aaSAndroid Build Coastguard Worker // Suppress warnings about trying to use a texture in two contexts.
1100*c8dee2aaSAndroid Build Coastguard Worker GrRecordingContextPriv::AutoSuppressWarningMessages aswm(otherCtx);
1101*c8dee2aaSAndroid Build Coastguard Worker
1102*c8dee2aaSAndroid Build Coastguard Worker testContext->makeCurrent();
1103*c8dee2aaSAndroid Build Coastguard Worker sk_sp <SkImage> refImg(imageMaker(dContext));
1104*c8dee2aaSAndroid Build Coastguard Worker GrSurfaceProxyView view, otherView, viewSecondRef;
1105*c8dee2aaSAndroid Build Coastguard Worker
1106*c8dee2aaSAndroid Build Coastguard Worker // Any context should be able to borrow the texture at this point
1107*c8dee2aaSAndroid Build Coastguard Worker
1108*c8dee2aaSAndroid Build Coastguard Worker std::tie(view, std::ignore) =
1109*c8dee2aaSAndroid Build Coastguard Worker skgpu::ganesh::AsView(dContext, refImg, skgpu::Mipmapped::kNo);
1110*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, view);
1111*c8dee2aaSAndroid Build Coastguard Worker
1112*c8dee2aaSAndroid Build Coastguard Worker // But once it's borrowed, no other context should be able to borrow
1113*c8dee2aaSAndroid Build Coastguard Worker otherTestContext->makeCurrent();
1114*c8dee2aaSAndroid Build Coastguard Worker std::tie(otherView, std::ignore) =
1115*c8dee2aaSAndroid Build Coastguard Worker skgpu::ganesh::AsView(otherCtx, refImg, skgpu::Mipmapped::kNo);
1116*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, !otherView);
1117*c8dee2aaSAndroid Build Coastguard Worker
1118*c8dee2aaSAndroid Build Coastguard Worker // Original context (that's already borrowing) should be okay
1119*c8dee2aaSAndroid Build Coastguard Worker testContext->makeCurrent();
1120*c8dee2aaSAndroid Build Coastguard Worker std::tie(viewSecondRef, std::ignore) =
1121*c8dee2aaSAndroid Build Coastguard Worker skgpu::ganesh::AsView(dContext, refImg, skgpu::Mipmapped::kNo);
1122*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, viewSecondRef);
1123*c8dee2aaSAndroid Build Coastguard Worker
1124*c8dee2aaSAndroid Build Coastguard Worker // Release first ref from the original context
1125*c8dee2aaSAndroid Build Coastguard Worker view.reset();
1126*c8dee2aaSAndroid Build Coastguard Worker
1127*c8dee2aaSAndroid Build Coastguard Worker // We released one proxy but not the other from the current borrowing context. Make sure
1128*c8dee2aaSAndroid Build Coastguard Worker // a new context is still not able to borrow the texture.
1129*c8dee2aaSAndroid Build Coastguard Worker otherTestContext->makeCurrent();
1130*c8dee2aaSAndroid Build Coastguard Worker std::tie(otherView, std::ignore) =
1131*c8dee2aaSAndroid Build Coastguard Worker skgpu::ganesh::AsView(otherCtx, refImg, skgpu::Mipmapped::kNo);
1132*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, !otherView);
1133*c8dee2aaSAndroid Build Coastguard Worker
1134*c8dee2aaSAndroid Build Coastguard Worker // Release second ref from the original context
1135*c8dee2aaSAndroid Build Coastguard Worker testContext->makeCurrent();
1136*c8dee2aaSAndroid Build Coastguard Worker viewSecondRef.reset();
1137*c8dee2aaSAndroid Build Coastguard Worker
1138*c8dee2aaSAndroid Build Coastguard Worker // Now we should be able to borrow the texture from the other context
1139*c8dee2aaSAndroid Build Coastguard Worker otherTestContext->makeCurrent();
1140*c8dee2aaSAndroid Build Coastguard Worker std::tie(otherView, std::ignore) =
1141*c8dee2aaSAndroid Build Coastguard Worker skgpu::ganesh::AsView(otherCtx, refImg, skgpu::Mipmapped::kNo);
1142*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, otherView);
1143*c8dee2aaSAndroid Build Coastguard Worker
1144*c8dee2aaSAndroid Build Coastguard Worker // Release everything
1145*c8dee2aaSAndroid Build Coastguard Worker otherView.reset();
1146*c8dee2aaSAndroid Build Coastguard Worker refImg.reset(nullptr);
1147*c8dee2aaSAndroid Build Coastguard Worker }
1148*c8dee2aaSAndroid Build Coastguard Worker }
1149*c8dee2aaSAndroid Build Coastguard Worker }
1150*c8dee2aaSAndroid Build Coastguard Worker
DEF_GANESH_TEST(SkImage_MakeCrossContextFromPixmapRelease,reporter,options,CtsEnforcement::kApiLevel_T)1151*c8dee2aaSAndroid Build Coastguard Worker DEF_GANESH_TEST(SkImage_MakeCrossContextFromPixmapRelease,
1152*c8dee2aaSAndroid Build Coastguard Worker reporter,
1153*c8dee2aaSAndroid Build Coastguard Worker options,
1154*c8dee2aaSAndroid Build Coastguard Worker CtsEnforcement::kApiLevel_T) {
1155*c8dee2aaSAndroid Build Coastguard Worker SkBitmap bitmap;
1156*c8dee2aaSAndroid Build Coastguard Worker SkPixmap pixmap;
1157*c8dee2aaSAndroid Build Coastguard Worker if (!ToolUtils::GetResourceAsBitmap("images/mandrill_128.png", &bitmap) ||
1158*c8dee2aaSAndroid Build Coastguard Worker !bitmap.peekPixels(&pixmap)) {
1159*c8dee2aaSAndroid Build Coastguard Worker ERRORF(reporter, "missing resource");
1160*c8dee2aaSAndroid Build Coastguard Worker return;
1161*c8dee2aaSAndroid Build Coastguard Worker }
1162*c8dee2aaSAndroid Build Coastguard Worker test_cross_context_image(reporter,
1163*c8dee2aaSAndroid Build Coastguard Worker options,
1164*c8dee2aaSAndroid Build Coastguard Worker "SkImage_MakeCrossContextFromPixmapRelease",
1165*c8dee2aaSAndroid Build Coastguard Worker [&pixmap](GrDirectContext* dContext) {
1166*c8dee2aaSAndroid Build Coastguard Worker return SkImages::CrossContextTextureFromPixmap(
1167*c8dee2aaSAndroid Build Coastguard Worker dContext, pixmap, false);
1168*c8dee2aaSAndroid Build Coastguard Worker });
1169*c8dee2aaSAndroid Build Coastguard Worker }
1170*c8dee2aaSAndroid Build Coastguard Worker
DEF_GANESH_TEST(SkImage_CrossContextGrayAlphaConfigs,reporter,options,CtsEnforcement::kApiLevel_T)1171*c8dee2aaSAndroid Build Coastguard Worker DEF_GANESH_TEST(SkImage_CrossContextGrayAlphaConfigs,
1172*c8dee2aaSAndroid Build Coastguard Worker reporter,
1173*c8dee2aaSAndroid Build Coastguard Worker options,
1174*c8dee2aaSAndroid Build Coastguard Worker CtsEnforcement::kApiLevel_T) {
1175*c8dee2aaSAndroid Build Coastguard Worker for (SkColorType ct : { kGray_8_SkColorType, kAlpha_8_SkColorType }) {
1176*c8dee2aaSAndroid Build Coastguard Worker SkAutoPixmapStorage pixmap;
1177*c8dee2aaSAndroid Build Coastguard Worker pixmap.alloc(SkImageInfo::Make(4, 4, ct, kPremul_SkAlphaType));
1178*c8dee2aaSAndroid Build Coastguard Worker
1179*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < skgpu::kContextTypeCount; ++i) {
1180*c8dee2aaSAndroid Build Coastguard Worker GrContextFactory testFactory(options);
1181*c8dee2aaSAndroid Build Coastguard Worker skgpu::ContextType ctxType = static_cast<skgpu::ContextType>(i);
1182*c8dee2aaSAndroid Build Coastguard Worker ContextInfo ctxInfo = testFactory.getContextInfo(ctxType);
1183*c8dee2aaSAndroid Build Coastguard Worker auto dContext = ctxInfo.directContext();
1184*c8dee2aaSAndroid Build Coastguard Worker if (!dContext || !dContext->priv().caps()->crossContextTextureSupport()) {
1185*c8dee2aaSAndroid Build Coastguard Worker continue;
1186*c8dee2aaSAndroid Build Coastguard Worker }
1187*c8dee2aaSAndroid Build Coastguard Worker
1188*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> image = SkImages::CrossContextTextureFromPixmap(dContext, pixmap, false);
1189*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, image);
1190*c8dee2aaSAndroid Build Coastguard Worker
1191*c8dee2aaSAndroid Build Coastguard Worker auto [view, viewCT] = skgpu::ganesh::AsView(dContext, image, skgpu::Mipmapped::kNo);
1192*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, view);
1193*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, GrColorTypeToSkColorType(viewCT) == ct);
1194*c8dee2aaSAndroid Build Coastguard Worker
1195*c8dee2aaSAndroid Build Coastguard Worker bool expectAlpha = kAlpha_8_SkColorType == ct;
1196*c8dee2aaSAndroid Build Coastguard Worker GrColorType grCT = SkColorTypeToGrColorType(image->colorType());
1197*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, expectAlpha == GrColorTypeIsAlphaOnly(grCT));
1198*c8dee2aaSAndroid Build Coastguard Worker }
1199*c8dee2aaSAndroid Build Coastguard Worker }
1200*c8dee2aaSAndroid Build Coastguard Worker }
1201*c8dee2aaSAndroid Build Coastguard Worker
DEF_GANESH_TEST_FOR_GL_CONTEXT(makeBackendTexture,reporter,ctxInfo,CtsEnforcement::kApiLevel_T)1202*c8dee2aaSAndroid Build Coastguard Worker DEF_GANESH_TEST_FOR_GL_CONTEXT(makeBackendTexture, reporter, ctxInfo, CtsEnforcement::kApiLevel_T) {
1203*c8dee2aaSAndroid Build Coastguard Worker auto context = ctxInfo.directContext();
1204*c8dee2aaSAndroid Build Coastguard Worker sk_gpu_test::TestContext* testContext = ctxInfo.testContext();
1205*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrContextThreadSafeProxy> proxy = context->threadSafeProxy();
1206*c8dee2aaSAndroid Build Coastguard Worker
1207*c8dee2aaSAndroid Build Coastguard Worker GrContextFactory otherFactory;
1208*c8dee2aaSAndroid Build Coastguard Worker ContextInfo otherContextInfo = otherFactory.getContextInfo(ctxInfo.type());
1209*c8dee2aaSAndroid Build Coastguard Worker
1210*c8dee2aaSAndroid Build Coastguard Worker testContext->makeCurrent();
1211*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, proxy);
1212*c8dee2aaSAndroid Build Coastguard Worker auto createLarge = [context] {
1213*c8dee2aaSAndroid Build Coastguard Worker return create_image_large(context->priv().caps()->maxTextureSize());
1214*c8dee2aaSAndroid Build Coastguard Worker };
1215*c8dee2aaSAndroid Build Coastguard Worker struct TestCase {
1216*c8dee2aaSAndroid Build Coastguard Worker std::function<sk_sp<SkImage>()> fImageFactory;
1217*c8dee2aaSAndroid Build Coastguard Worker bool fExpectation;
1218*c8dee2aaSAndroid Build Coastguard Worker bool fCanTakeDirectly;
1219*c8dee2aaSAndroid Build Coastguard Worker };
1220*c8dee2aaSAndroid Build Coastguard Worker TestCase testCases[] = {
1221*c8dee2aaSAndroid Build Coastguard Worker { create_image, true, false },
1222*c8dee2aaSAndroid Build Coastguard Worker { create_codec_image, true, false },
1223*c8dee2aaSAndroid Build Coastguard Worker { create_data_image, true, false },
1224*c8dee2aaSAndroid Build Coastguard Worker { create_picture_image, true, false },
1225*c8dee2aaSAndroid Build Coastguard Worker { [context] { return create_gpu_image(context); }, true, true },
1226*c8dee2aaSAndroid Build Coastguard Worker // Create a texture image in a another context.
1227*c8dee2aaSAndroid Build Coastguard Worker { [otherContextInfo] {
1228*c8dee2aaSAndroid Build Coastguard Worker auto restore = otherContextInfo.testContext()->makeCurrentAndAutoRestore();
1229*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> otherContextImage = create_gpu_image(otherContextInfo.directContext());
1230*c8dee2aaSAndroid Build Coastguard Worker otherContextInfo.directContext()->flushAndSubmit();
1231*c8dee2aaSAndroid Build Coastguard Worker return otherContextImage;
1232*c8dee2aaSAndroid Build Coastguard Worker }, false, false },
1233*c8dee2aaSAndroid Build Coastguard Worker // Create an image that is too large to be texture backed.
1234*c8dee2aaSAndroid Build Coastguard Worker { createLarge, false, false }
1235*c8dee2aaSAndroid Build Coastguard Worker };
1236*c8dee2aaSAndroid Build Coastguard Worker
1237*c8dee2aaSAndroid Build Coastguard Worker for (const TestCase& testCase : testCases) {
1238*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> image(testCase.fImageFactory());
1239*c8dee2aaSAndroid Build Coastguard Worker if (!image) {
1240*c8dee2aaSAndroid Build Coastguard Worker ERRORF(reporter, "Failed to create image!");
1241*c8dee2aaSAndroid Build Coastguard Worker continue;
1242*c8dee2aaSAndroid Build Coastguard Worker }
1243*c8dee2aaSAndroid Build Coastguard Worker
1244*c8dee2aaSAndroid Build Coastguard Worker GrBackendTexture origBackend;
1245*c8dee2aaSAndroid Build Coastguard Worker SkImages::GetBackendTextureFromImage(image, &origBackend, true);
1246*c8dee2aaSAndroid Build Coastguard Worker if (testCase.fCanTakeDirectly) {
1247*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(origBackend.isValid());
1248*c8dee2aaSAndroid Build Coastguard Worker }
1249*c8dee2aaSAndroid Build Coastguard Worker
1250*c8dee2aaSAndroid Build Coastguard Worker GrBackendTexture newBackend;
1251*c8dee2aaSAndroid Build Coastguard Worker SkImages::BackendTextureReleaseProc proc;
1252*c8dee2aaSAndroid Build Coastguard Worker bool result = SkImages::MakeBackendTextureFromImage(
1253*c8dee2aaSAndroid Build Coastguard Worker context, std::move(image), &newBackend, &proc);
1254*c8dee2aaSAndroid Build Coastguard Worker if (result != testCase.fExpectation) {
1255*c8dee2aaSAndroid Build Coastguard Worker static const char *const kFS[] = { "fail", "succeed" };
1256*c8dee2aaSAndroid Build Coastguard Worker ERRORF(reporter, "This image was expected to %s but did not.",
1257*c8dee2aaSAndroid Build Coastguard Worker kFS[testCase.fExpectation]);
1258*c8dee2aaSAndroid Build Coastguard Worker }
1259*c8dee2aaSAndroid Build Coastguard Worker
1260*c8dee2aaSAndroid Build Coastguard Worker if (result) {
1261*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(newBackend.isValid());
1262*c8dee2aaSAndroid Build Coastguard Worker }
1263*c8dee2aaSAndroid Build Coastguard Worker
1264*c8dee2aaSAndroid Build Coastguard Worker bool tookDirectly = result && GrBackendTexture::TestingOnly_Equals(origBackend, newBackend);
1265*c8dee2aaSAndroid Build Coastguard Worker if (testCase.fCanTakeDirectly != tookDirectly) {
1266*c8dee2aaSAndroid Build Coastguard Worker static const char *const kExpectedState[] = { "not expected", "expected" };
1267*c8dee2aaSAndroid Build Coastguard Worker ERRORF(reporter, "This backend texture was %s to be taken directly.",
1268*c8dee2aaSAndroid Build Coastguard Worker kExpectedState[testCase.fCanTakeDirectly]);
1269*c8dee2aaSAndroid Build Coastguard Worker }
1270*c8dee2aaSAndroid Build Coastguard Worker
1271*c8dee2aaSAndroid Build Coastguard Worker context->flushAndSubmit();
1272*c8dee2aaSAndroid Build Coastguard Worker }
1273*c8dee2aaSAndroid Build Coastguard Worker }
1274*c8dee2aaSAndroid Build Coastguard Worker
DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(ImageBackendAccessAbandoned_Gpu,reporter,ctxInfo,CtsEnforcement::kApiLevel_T)1275*c8dee2aaSAndroid Build Coastguard Worker DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(ImageBackendAccessAbandoned_Gpu,
1276*c8dee2aaSAndroid Build Coastguard Worker reporter,
1277*c8dee2aaSAndroid Build Coastguard Worker ctxInfo,
1278*c8dee2aaSAndroid Build Coastguard Worker CtsEnforcement::kApiLevel_T) {
1279*c8dee2aaSAndroid Build Coastguard Worker auto dContext = ctxInfo.directContext();
1280*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> image(create_gpu_image(ctxInfo.directContext()));
1281*c8dee2aaSAndroid Build Coastguard Worker if (!image) {
1282*c8dee2aaSAndroid Build Coastguard Worker return;
1283*c8dee2aaSAndroid Build Coastguard Worker }
1284*c8dee2aaSAndroid Build Coastguard Worker
1285*c8dee2aaSAndroid Build Coastguard Worker GrBackendTexture beTex;
1286*c8dee2aaSAndroid Build Coastguard Worker bool ok = SkImages::GetBackendTextureFromImage(image, &beTex, true);
1287*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, ok);
1288*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, beTex.isValid());
1289*c8dee2aaSAndroid Build Coastguard Worker
1290*c8dee2aaSAndroid Build Coastguard Worker dContext->abandonContext();
1291*c8dee2aaSAndroid Build Coastguard Worker
1292*c8dee2aaSAndroid Build Coastguard Worker // After abandoning the context the backend texture should not be valid.
1293*c8dee2aaSAndroid Build Coastguard Worker ok = SkImages::GetBackendTextureFromImage(image, &beTex, true);
1294*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, !ok);
1295*c8dee2aaSAndroid Build Coastguard Worker }
1296*c8dee2aaSAndroid Build Coastguard Worker
1297*c8dee2aaSAndroid Build Coastguard Worker ///////////////////////////////////////////////////////////////////////////////////////////////////
1298*c8dee2aaSAndroid Build Coastguard Worker
create_picture_image(sk_sp<SkColorSpace> space)1299*c8dee2aaSAndroid Build Coastguard Worker static sk_sp<SkImage> create_picture_image(sk_sp<SkColorSpace> space) {
1300*c8dee2aaSAndroid Build Coastguard Worker SkPictureRecorder recorder;
1301*c8dee2aaSAndroid Build Coastguard Worker SkCanvas* canvas = recorder.beginRecording(10, 10);
1302*c8dee2aaSAndroid Build Coastguard Worker canvas->clear(SK_ColorCYAN);
1303*c8dee2aaSAndroid Build Coastguard Worker return SkImages::DeferredFromPicture(recorder.finishRecordingAsPicture(),
1304*c8dee2aaSAndroid Build Coastguard Worker SkISize::Make(10, 10),
1305*c8dee2aaSAndroid Build Coastguard Worker nullptr,
1306*c8dee2aaSAndroid Build Coastguard Worker nullptr,
1307*c8dee2aaSAndroid Build Coastguard Worker SkImages::BitDepth::kU8,
1308*c8dee2aaSAndroid Build Coastguard Worker std::move(space));
1309*c8dee2aaSAndroid Build Coastguard Worker }
1310*c8dee2aaSAndroid Build Coastguard Worker
DEF_TEST(Image_ColorSpace,r)1311*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(Image_ColorSpace, r) {
1312*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkColorSpace> srgb = SkColorSpace::MakeSRGB();
1313*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> image = ToolUtils::GetResourceAsImage("images/mandrill_512_q075.jpg");
1314*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, srgb.get() == image->colorSpace());
1315*c8dee2aaSAndroid Build Coastguard Worker
1316*c8dee2aaSAndroid Build Coastguard Worker image = ToolUtils::GetResourceAsImage("images/webp-color-profile-lossy.webp");
1317*c8dee2aaSAndroid Build Coastguard Worker skcms_TransferFunction fn;
1318*c8dee2aaSAndroid Build Coastguard Worker bool success = image->colorSpace()->isNumericalTransferFn(&fn);
1319*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, success);
1320*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, color_space_almost_equal(1.8f, fn.g));
1321*c8dee2aaSAndroid Build Coastguard Worker
1322*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkColorSpace> rec2020 = SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB,
1323*c8dee2aaSAndroid Build Coastguard Worker SkNamedGamut::kRec2020);
1324*c8dee2aaSAndroid Build Coastguard Worker image = create_picture_image(rec2020);
1325*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, SkColorSpace::Equals(rec2020.get(), image->colorSpace()));
1326*c8dee2aaSAndroid Build Coastguard Worker
1327*c8dee2aaSAndroid Build Coastguard Worker SkBitmap bitmap;
1328*c8dee2aaSAndroid Build Coastguard Worker SkImageInfo info = SkImageInfo::MakeN32(10, 10, kPremul_SkAlphaType, rec2020);
1329*c8dee2aaSAndroid Build Coastguard Worker bitmap.allocPixels(info);
1330*c8dee2aaSAndroid Build Coastguard Worker image = bitmap.asImage();
1331*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, SkColorSpace::Equals(rec2020.get(), image->colorSpace()));
1332*c8dee2aaSAndroid Build Coastguard Worker
1333*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkSurface> surface =
1334*c8dee2aaSAndroid Build Coastguard Worker SkSurfaces::Raster(SkImageInfo::MakeN32Premul(SkISize::Make(10, 10)));
1335*c8dee2aaSAndroid Build Coastguard Worker image = surface->makeImageSnapshot();
1336*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, nullptr == image->colorSpace());
1337*c8dee2aaSAndroid Build Coastguard Worker
1338*c8dee2aaSAndroid Build Coastguard Worker surface = SkSurfaces::Raster(info);
1339*c8dee2aaSAndroid Build Coastguard Worker image = surface->makeImageSnapshot();
1340*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, SkColorSpace::Equals(rec2020.get(), image->colorSpace()));
1341*c8dee2aaSAndroid Build Coastguard Worker }
1342*c8dee2aaSAndroid Build Coastguard Worker
DEF_TEST(Image_makeColorSpace,r)1343*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(Image_makeColorSpace, r) {
1344*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkColorSpace> p3 = SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB, SkNamedGamut::kDisplayP3);
1345*c8dee2aaSAndroid Build Coastguard Worker skcms_TransferFunction fn;
1346*c8dee2aaSAndroid Build Coastguard Worker fn.a = 1.f; fn.b = 0.f; fn.c = 0.f; fn.d = 0.f; fn.e = 0.f; fn.f = 0.f; fn.g = 1.8f;
1347*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkColorSpace> adobeGamut = SkColorSpace::MakeRGB(fn, SkNamedGamut::kAdobeRGB);
1348*c8dee2aaSAndroid Build Coastguard Worker
1349*c8dee2aaSAndroid Build Coastguard Worker SkBitmap srgbBitmap;
1350*c8dee2aaSAndroid Build Coastguard Worker srgbBitmap.allocPixels(SkImageInfo::MakeS32(1, 1, kOpaque_SkAlphaType));
1351*c8dee2aaSAndroid Build Coastguard Worker *srgbBitmap.getAddr32(0, 0) = SkSwizzle_RGBA_to_PMColor(0xFF604020);
1352*c8dee2aaSAndroid Build Coastguard Worker srgbBitmap.setImmutable();
1353*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> srgbImage = srgbBitmap.asImage();
1354*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> p3Image = srgbImage->makeColorSpace(nullptr, p3);
1355*c8dee2aaSAndroid Build Coastguard Worker SkBitmap p3Bitmap;
1356*c8dee2aaSAndroid Build Coastguard Worker bool success = p3Image->asLegacyBitmap(&p3Bitmap);
1357*c8dee2aaSAndroid Build Coastguard Worker
1358*c8dee2aaSAndroid Build Coastguard Worker auto almost_equal = [](int a, int b) { return SkTAbs(a - b) <= 2; };
1359*c8dee2aaSAndroid Build Coastguard Worker
1360*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, success);
1361*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, almost_equal(0x28, SkGetPackedR32(*p3Bitmap.getAddr32(0, 0))));
1362*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, almost_equal(0x40, SkGetPackedG32(*p3Bitmap.getAddr32(0, 0))));
1363*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, almost_equal(0x5E, SkGetPackedB32(*p3Bitmap.getAddr32(0, 0))));
1364*c8dee2aaSAndroid Build Coastguard Worker
1365*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> adobeImage = srgbImage->makeColorSpace(nullptr, adobeGamut);
1366*c8dee2aaSAndroid Build Coastguard Worker SkBitmap adobeBitmap;
1367*c8dee2aaSAndroid Build Coastguard Worker success = adobeImage->asLegacyBitmap(&adobeBitmap);
1368*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, success);
1369*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, almost_equal(0x21, SkGetPackedR32(*adobeBitmap.getAddr32(0, 0))));
1370*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, almost_equal(0x31, SkGetPackedG32(*adobeBitmap.getAddr32(0, 0))));
1371*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, almost_equal(0x4C, SkGetPackedB32(*adobeBitmap.getAddr32(0, 0))));
1372*c8dee2aaSAndroid Build Coastguard Worker
1373*c8dee2aaSAndroid Build Coastguard Worker srgbImage = ToolUtils::GetResourceAsImage("images/1x1.png");
1374*c8dee2aaSAndroid Build Coastguard Worker p3Image = srgbImage->makeColorSpace(nullptr, p3);
1375*c8dee2aaSAndroid Build Coastguard Worker success = p3Image->asLegacyBitmap(&p3Bitmap);
1376*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, success);
1377*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, almost_equal(0x8B, SkGetPackedR32(*p3Bitmap.getAddr32(0, 0))));
1378*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, almost_equal(0x82, SkGetPackedG32(*p3Bitmap.getAddr32(0, 0))));
1379*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, almost_equal(0x77, SkGetPackedB32(*p3Bitmap.getAddr32(0, 0))));
1380*c8dee2aaSAndroid Build Coastguard Worker }
1381*c8dee2aaSAndroid Build Coastguard Worker
1382*c8dee2aaSAndroid Build Coastguard Worker ///////////////////////////////////////////////////////////////////////////////////////////////////
1383*c8dee2aaSAndroid Build Coastguard Worker
make_all_premul(SkBitmap * bm)1384*c8dee2aaSAndroid Build Coastguard Worker static void make_all_premul(SkBitmap* bm) {
1385*c8dee2aaSAndroid Build Coastguard Worker bm->allocPixels(SkImageInfo::MakeN32(256, 256, kPremul_SkAlphaType));
1386*c8dee2aaSAndroid Build Coastguard Worker for (int a = 0; a < 256; ++a) {
1387*c8dee2aaSAndroid Build Coastguard Worker for (int r = 0; r < 256; ++r) {
1388*c8dee2aaSAndroid Build Coastguard Worker // make all valid premul combinations
1389*c8dee2aaSAndroid Build Coastguard Worker int c = std::min(a, r);
1390*c8dee2aaSAndroid Build Coastguard Worker *bm->getAddr32(a, r) = SkPackARGB32(a, c, c, c);
1391*c8dee2aaSAndroid Build Coastguard Worker }
1392*c8dee2aaSAndroid Build Coastguard Worker }
1393*c8dee2aaSAndroid Build Coastguard Worker }
1394*c8dee2aaSAndroid Build Coastguard Worker
equal(const SkBitmap & a,const SkBitmap & b)1395*c8dee2aaSAndroid Build Coastguard Worker static bool equal(const SkBitmap& a, const SkBitmap& b) {
1396*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(a.width() == b.width());
1397*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(a.height() == b.height());
1398*c8dee2aaSAndroid Build Coastguard Worker for (int y = 0; y < a.height(); ++y) {
1399*c8dee2aaSAndroid Build Coastguard Worker for (int x = 0; x < a.width(); ++x) {
1400*c8dee2aaSAndroid Build Coastguard Worker SkPMColor pa = *a.getAddr32(x, y);
1401*c8dee2aaSAndroid Build Coastguard Worker SkPMColor pb = *b.getAddr32(x, y);
1402*c8dee2aaSAndroid Build Coastguard Worker if (pa != pb) {
1403*c8dee2aaSAndroid Build Coastguard Worker return false;
1404*c8dee2aaSAndroid Build Coastguard Worker }
1405*c8dee2aaSAndroid Build Coastguard Worker }
1406*c8dee2aaSAndroid Build Coastguard Worker }
1407*c8dee2aaSAndroid Build Coastguard Worker return true;
1408*c8dee2aaSAndroid Build Coastguard Worker }
1409*c8dee2aaSAndroid Build Coastguard Worker
DEF_TEST(image_roundtrip_encode,reporter)1410*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(image_roundtrip_encode, reporter) {
1411*c8dee2aaSAndroid Build Coastguard Worker SkBitmap bm0;
1412*c8dee2aaSAndroid Build Coastguard Worker make_all_premul(&bm0);
1413*c8dee2aaSAndroid Build Coastguard Worker
1414*c8dee2aaSAndroid Build Coastguard Worker auto img0 = bm0.asImage();
1415*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkData> data = SkPngEncoder::Encode(nullptr, img0.get(), {});
1416*c8dee2aaSAndroid Build Coastguard Worker auto img1 = SkImages::DeferredFromEncodedData(data);
1417*c8dee2aaSAndroid Build Coastguard Worker
1418*c8dee2aaSAndroid Build Coastguard Worker SkBitmap bm1;
1419*c8dee2aaSAndroid Build Coastguard Worker bm1.allocPixels(SkImageInfo::MakeN32(256, 256, kPremul_SkAlphaType));
1420*c8dee2aaSAndroid Build Coastguard Worker img1->readPixels(nullptr, bm1.info(), bm1.getPixels(), bm1.rowBytes(), 0, 0);
1421*c8dee2aaSAndroid Build Coastguard Worker
1422*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, equal(bm0, bm1));
1423*c8dee2aaSAndroid Build Coastguard Worker }
1424*c8dee2aaSAndroid Build Coastguard Worker
DEF_TEST(image_roundtrip_premul,reporter)1425*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(image_roundtrip_premul, reporter) {
1426*c8dee2aaSAndroid Build Coastguard Worker SkBitmap bm0;
1427*c8dee2aaSAndroid Build Coastguard Worker make_all_premul(&bm0);
1428*c8dee2aaSAndroid Build Coastguard Worker
1429*c8dee2aaSAndroid Build Coastguard Worker SkBitmap bm1;
1430*c8dee2aaSAndroid Build Coastguard Worker bm1.allocPixels(SkImageInfo::MakeN32(256, 256, kUnpremul_SkAlphaType));
1431*c8dee2aaSAndroid Build Coastguard Worker bm0.readPixels(bm1.info(), bm1.getPixels(), bm1.rowBytes(), 0, 0);
1432*c8dee2aaSAndroid Build Coastguard Worker
1433*c8dee2aaSAndroid Build Coastguard Worker SkBitmap bm2;
1434*c8dee2aaSAndroid Build Coastguard Worker bm2.allocPixels(SkImageInfo::MakeN32(256, 256, kPremul_SkAlphaType));
1435*c8dee2aaSAndroid Build Coastguard Worker bm1.readPixels(bm2.info(), bm2.getPixels(), bm2.rowBytes(), 0, 0);
1436*c8dee2aaSAndroid Build Coastguard Worker
1437*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, equal(bm0, bm2));
1438*c8dee2aaSAndroid Build Coastguard Worker }
1439*c8dee2aaSAndroid Build Coastguard Worker
DEF_TEST(image_from_encoded_alphatype_override,reporter)1440*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(image_from_encoded_alphatype_override, reporter) {
1441*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkData> data = GetResourceAsData("images/mandrill_32.png");
1442*c8dee2aaSAndroid Build Coastguard Worker
1443*c8dee2aaSAndroid Build Coastguard Worker // Ensure that we can decode the image when we specifically request premul or unpremul, but
1444*c8dee2aaSAndroid Build Coastguard Worker // not when we request kOpaque
1445*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, SkImages::DeferredFromEncodedData(data, kPremul_SkAlphaType));
1446*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, SkImages::DeferredFromEncodedData(data, kUnpremul_SkAlphaType));
1447*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, !SkImages::DeferredFromEncodedData(data, kOpaque_SkAlphaType));
1448*c8dee2aaSAndroid Build Coastguard Worker
1449*c8dee2aaSAndroid Build Coastguard Worker // Same tests as above, but using SkImageGenerators::MakeFromEncoded
1450*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, SkImageGenerators::MakeFromEncoded(data, kPremul_SkAlphaType));
1451*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, SkImageGenerators::MakeFromEncoded(data, kUnpremul_SkAlphaType));
1452*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, !SkImageGenerators::MakeFromEncoded(data, kOpaque_SkAlphaType));
1453*c8dee2aaSAndroid Build Coastguard Worker }
1454*c8dee2aaSAndroid Build Coastguard Worker
1455*c8dee2aaSAndroid Build Coastguard Worker ///////////////////////////////////////////////////////////////////////////////////////////////////
1456*c8dee2aaSAndroid Build Coastguard Worker
check_scaled_pixels(skiatest::Reporter * reporter,SkPixmap * pmap,uint32_t expected)1457*c8dee2aaSAndroid Build Coastguard Worker static void check_scaled_pixels(skiatest::Reporter* reporter, SkPixmap* pmap, uint32_t expected) {
1458*c8dee2aaSAndroid Build Coastguard Worker // Verify that all pixels contain the original test color
1459*c8dee2aaSAndroid Build Coastguard Worker for (auto y = 0; y < pmap->height(); ++y) {
1460*c8dee2aaSAndroid Build Coastguard Worker for (auto x = 0; x < pmap->width(); ++x) {
1461*c8dee2aaSAndroid Build Coastguard Worker uint32_t pixel = *pmap->addr32(x, y);
1462*c8dee2aaSAndroid Build Coastguard Worker if (pixel != expected) {
1463*c8dee2aaSAndroid Build Coastguard Worker ERRORF(reporter, "Expected scaled pixels to be the same. At %d,%d 0x%08x != 0x%08x",
1464*c8dee2aaSAndroid Build Coastguard Worker x, y, pixel, expected);
1465*c8dee2aaSAndroid Build Coastguard Worker return;
1466*c8dee2aaSAndroid Build Coastguard Worker }
1467*c8dee2aaSAndroid Build Coastguard Worker }
1468*c8dee2aaSAndroid Build Coastguard Worker }
1469*c8dee2aaSAndroid Build Coastguard Worker }
1470*c8dee2aaSAndroid Build Coastguard Worker
test_scale_pixels(skiatest::Reporter * reporter,const SkImage * image,uint32_t expected)1471*c8dee2aaSAndroid Build Coastguard Worker static void test_scale_pixels(skiatest::Reporter* reporter, const SkImage* image,
1472*c8dee2aaSAndroid Build Coastguard Worker uint32_t expected) {
1473*c8dee2aaSAndroid Build Coastguard Worker SkImageInfo info = SkImageInfo::MakeN32Premul(image->width() * 2, image->height() * 2);
1474*c8dee2aaSAndroid Build Coastguard Worker
1475*c8dee2aaSAndroid Build Coastguard Worker // Make sure to test kDisallow first, so we don't just get a cache hit in that case
1476*c8dee2aaSAndroid Build Coastguard Worker for (auto chint : { SkImage::kDisallow_CachingHint, SkImage::kAllow_CachingHint }) {
1477*c8dee2aaSAndroid Build Coastguard Worker SkAutoPixmapStorage scaled;
1478*c8dee2aaSAndroid Build Coastguard Worker scaled.alloc(info);
1479*c8dee2aaSAndroid Build Coastguard Worker if (!image->scalePixels(scaled, SkSamplingOptions(SkFilterMode::kLinear), chint)) {
1480*c8dee2aaSAndroid Build Coastguard Worker ERRORF(reporter, "Failed to scale image");
1481*c8dee2aaSAndroid Build Coastguard Worker continue;
1482*c8dee2aaSAndroid Build Coastguard Worker }
1483*c8dee2aaSAndroid Build Coastguard Worker
1484*c8dee2aaSAndroid Build Coastguard Worker check_scaled_pixels(reporter, &scaled, expected);
1485*c8dee2aaSAndroid Build Coastguard Worker }
1486*c8dee2aaSAndroid Build Coastguard Worker }
1487*c8dee2aaSAndroid Build Coastguard Worker
DEF_TEST(ImageScalePixels,reporter)1488*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(ImageScalePixels, reporter) {
1489*c8dee2aaSAndroid Build Coastguard Worker const SkPMColor pmRed = SkPackARGB32(0xFF, 0xFF, 0, 0);
1490*c8dee2aaSAndroid Build Coastguard Worker const SkColor red = SK_ColorRED;
1491*c8dee2aaSAndroid Build Coastguard Worker
1492*c8dee2aaSAndroid Build Coastguard Worker // Test raster image
1493*c8dee2aaSAndroid Build Coastguard Worker SkImageInfo info = SkImageInfo::MakeN32Premul(1, 1);
1494*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkSurface> surface = SkSurfaces::Raster(info);
1495*c8dee2aaSAndroid Build Coastguard Worker surface->getCanvas()->clear(red);
1496*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> rasterImage = surface->makeImageSnapshot();
1497*c8dee2aaSAndroid Build Coastguard Worker test_scale_pixels(reporter, rasterImage.get(), pmRed);
1498*c8dee2aaSAndroid Build Coastguard Worker
1499*c8dee2aaSAndroid Build Coastguard Worker // Test encoded image
1500*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkData> data = SkPngEncoder::Encode(nullptr, rasterImage.get(), {});
1501*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> codecImage = SkImages::DeferredFromEncodedData(data);
1502*c8dee2aaSAndroid Build Coastguard Worker test_scale_pixels(reporter, codecImage.get(), pmRed);
1503*c8dee2aaSAndroid Build Coastguard Worker }
1504*c8dee2aaSAndroid Build Coastguard Worker
DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(ImageScalePixels_Gpu,reporter,ctxInfo,CtsEnforcement::kApiLevel_T)1505*c8dee2aaSAndroid Build Coastguard Worker DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(ImageScalePixels_Gpu,
1506*c8dee2aaSAndroid Build Coastguard Worker reporter,
1507*c8dee2aaSAndroid Build Coastguard Worker ctxInfo,
1508*c8dee2aaSAndroid Build Coastguard Worker CtsEnforcement::kApiLevel_T) {
1509*c8dee2aaSAndroid Build Coastguard Worker const SkPMColor pmRed = SkPackARGB32(0xFF, 0xFF, 0, 0);
1510*c8dee2aaSAndroid Build Coastguard Worker const SkColor red = SK_ColorRED;
1511*c8dee2aaSAndroid Build Coastguard Worker
1512*c8dee2aaSAndroid Build Coastguard Worker SkImageInfo info = SkImageInfo::MakeN32Premul(16, 16);
1513*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkSurface> surface =
1514*c8dee2aaSAndroid Build Coastguard Worker SkSurfaces::RenderTarget(ctxInfo.directContext(), skgpu::Budgeted::kNo, info);
1515*c8dee2aaSAndroid Build Coastguard Worker surface->getCanvas()->clear(red);
1516*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> gpuImage = surface->makeImageSnapshot();
1517*c8dee2aaSAndroid Build Coastguard Worker test_scale_pixels(reporter, gpuImage.get(), pmRed);
1518*c8dee2aaSAndroid Build Coastguard Worker }
1519*c8dee2aaSAndroid Build Coastguard Worker
any_image_will_do()1520*c8dee2aaSAndroid Build Coastguard Worker static sk_sp<SkImage> any_image_will_do() {
1521*c8dee2aaSAndroid Build Coastguard Worker return ToolUtils::GetResourceAsImage("images/mandrill_32.png");
1522*c8dee2aaSAndroid Build Coastguard Worker }
1523*c8dee2aaSAndroid Build Coastguard Worker
DEF_TEST(Image_nonfinite_dst,reporter)1524*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(Image_nonfinite_dst, reporter) {
1525*c8dee2aaSAndroid Build Coastguard Worker auto surf = SkSurfaces::Raster(SkImageInfo::MakeN32Premul(10, 10));
1526*c8dee2aaSAndroid Build Coastguard Worker auto img = any_image_will_do();
1527*c8dee2aaSAndroid Build Coastguard Worker
1528*c8dee2aaSAndroid Build Coastguard Worker for (SkScalar bad : { SK_ScalarInfinity, SK_ScalarNaN}) {
1529*c8dee2aaSAndroid Build Coastguard Worker for (int bits = 1; bits <= 15; ++bits) {
1530*c8dee2aaSAndroid Build Coastguard Worker SkRect dst = { 0, 0, 10, 10 };
1531*c8dee2aaSAndroid Build Coastguard Worker if (bits & 1) dst.fLeft = bad;
1532*c8dee2aaSAndroid Build Coastguard Worker if (bits & 2) dst.fTop = bad;
1533*c8dee2aaSAndroid Build Coastguard Worker if (bits & 4) dst.fRight = bad;
1534*c8dee2aaSAndroid Build Coastguard Worker if (bits & 8) dst.fBottom = bad;
1535*c8dee2aaSAndroid Build Coastguard Worker
1536*c8dee2aaSAndroid Build Coastguard Worker surf->getCanvas()->drawImageRect(img, dst, SkSamplingOptions());
1537*c8dee2aaSAndroid Build Coastguard Worker
1538*c8dee2aaSAndroid Build Coastguard Worker // we should draw nothing
1539*c8dee2aaSAndroid Build Coastguard Worker ToolUtils::PixelIter iter(surf.get());
1540*c8dee2aaSAndroid Build Coastguard Worker while (void* addr = iter.next()) {
1541*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, *(SkPMColor*)addr == 0);
1542*c8dee2aaSAndroid Build Coastguard Worker }
1543*c8dee2aaSAndroid Build Coastguard Worker }
1544*c8dee2aaSAndroid Build Coastguard Worker }
1545*c8dee2aaSAndroid Build Coastguard Worker }
1546*c8dee2aaSAndroid Build Coastguard Worker
make_yuva_image(GrDirectContext * dContext)1547*c8dee2aaSAndroid Build Coastguard Worker static sk_sp<SkImage> make_yuva_image(GrDirectContext* dContext) {
1548*c8dee2aaSAndroid Build Coastguard Worker SkAutoPixmapStorage pm;
1549*c8dee2aaSAndroid Build Coastguard Worker pm.alloc(SkImageInfo::Make(1, 1, kAlpha_8_SkColorType, kPremul_SkAlphaType));
1550*c8dee2aaSAndroid Build Coastguard Worker SkYUVAInfo yuvaInfo({1, 1},
1551*c8dee2aaSAndroid Build Coastguard Worker SkYUVAInfo::PlaneConfig::kY_U_V,
1552*c8dee2aaSAndroid Build Coastguard Worker SkYUVAInfo::Subsampling::k444,
1553*c8dee2aaSAndroid Build Coastguard Worker kJPEG_Full_SkYUVColorSpace);
1554*c8dee2aaSAndroid Build Coastguard Worker const SkPixmap pmaps[] = {pm, pm, pm};
1555*c8dee2aaSAndroid Build Coastguard Worker auto yuvaPixmaps = SkYUVAPixmaps::FromExternalPixmaps(yuvaInfo, pmaps);
1556*c8dee2aaSAndroid Build Coastguard Worker
1557*c8dee2aaSAndroid Build Coastguard Worker return SkImages::TextureFromYUVAPixmaps(dContext, yuvaPixmaps);
1558*c8dee2aaSAndroid Build Coastguard Worker }
1559*c8dee2aaSAndroid Build Coastguard Worker
DEF_GANESH_TEST_FOR_ALL_CONTEXTS(ImageFlush,reporter,ctxInfo,CtsEnforcement::kApiLevel_T)1560*c8dee2aaSAndroid Build Coastguard Worker DEF_GANESH_TEST_FOR_ALL_CONTEXTS(ImageFlush, reporter, ctxInfo, CtsEnforcement::kApiLevel_T) {
1561*c8dee2aaSAndroid Build Coastguard Worker auto dContext = ctxInfo.directContext();
1562*c8dee2aaSAndroid Build Coastguard Worker auto ii = SkImageInfo::Make(10, 10, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
1563*c8dee2aaSAndroid Build Coastguard Worker auto s = SkSurfaces::RenderTarget(dContext, skgpu::Budgeted::kYes, ii, 1, nullptr);
1564*c8dee2aaSAndroid Build Coastguard Worker
1565*c8dee2aaSAndroid Build Coastguard Worker s->getCanvas()->clear(SK_ColorRED);
1566*c8dee2aaSAndroid Build Coastguard Worker auto i0 = s->makeImageSnapshot();
1567*c8dee2aaSAndroid Build Coastguard Worker s->getCanvas()->clear(SK_ColorBLUE);
1568*c8dee2aaSAndroid Build Coastguard Worker auto i1 = s->makeImageSnapshot();
1569*c8dee2aaSAndroid Build Coastguard Worker s->getCanvas()->clear(SK_ColorGREEN);
1570*c8dee2aaSAndroid Build Coastguard Worker // Make a YUVA image.
1571*c8dee2aaSAndroid Build Coastguard Worker auto i2 = make_yuva_image(dContext);
1572*c8dee2aaSAndroid Build Coastguard Worker
1573*c8dee2aaSAndroid Build Coastguard Worker // Flush all the setup work we did above and then make little lambda that reports the flush
1574*c8dee2aaSAndroid Build Coastguard Worker // count delta since the last time it was called.
1575*c8dee2aaSAndroid Build Coastguard Worker dContext->flushAndSubmit();
1576*c8dee2aaSAndroid Build Coastguard Worker auto numSubmits =
1577*c8dee2aaSAndroid Build Coastguard Worker [dContext,
1578*c8dee2aaSAndroid Build Coastguard Worker submitCnt = dContext->priv().getGpu()->stats()->numSubmitToGpus()]() mutable {
1579*c8dee2aaSAndroid Build Coastguard Worker int curr = dContext->priv().getGpu()->stats()->numSubmitToGpus();
1580*c8dee2aaSAndroid Build Coastguard Worker int n = curr - submitCnt;
1581*c8dee2aaSAndroid Build Coastguard Worker submitCnt = curr;
1582*c8dee2aaSAndroid Build Coastguard Worker return n;
1583*c8dee2aaSAndroid Build Coastguard Worker };
1584*c8dee2aaSAndroid Build Coastguard Worker
1585*c8dee2aaSAndroid Build Coastguard Worker // Images aren't used therefore flush is ignored, but submit is still called.
1586*c8dee2aaSAndroid Build Coastguard Worker dContext->flushAndSubmit(i0);
1587*c8dee2aaSAndroid Build Coastguard Worker dContext->flushAndSubmit(i1);
1588*c8dee2aaSAndroid Build Coastguard Worker dContext->flushAndSubmit(i2);
1589*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, numSubmits() == 3);
1590*c8dee2aaSAndroid Build Coastguard Worker
1591*c8dee2aaSAndroid Build Coastguard Worker // Syncing forces the flush to happen even if the images aren't used.
1592*c8dee2aaSAndroid Build Coastguard Worker dContext->flush(i0);
1593*c8dee2aaSAndroid Build Coastguard Worker dContext->submit(GrSyncCpu::kYes);
1594*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, numSubmits() == 1);
1595*c8dee2aaSAndroid Build Coastguard Worker dContext->flush(i1);
1596*c8dee2aaSAndroid Build Coastguard Worker dContext->submit(GrSyncCpu::kYes);
1597*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, numSubmits() == 1);
1598*c8dee2aaSAndroid Build Coastguard Worker dContext->flush(i2);
1599*c8dee2aaSAndroid Build Coastguard Worker dContext->submit(GrSyncCpu::kYes);
1600*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, numSubmits() == 1);
1601*c8dee2aaSAndroid Build Coastguard Worker
1602*c8dee2aaSAndroid Build Coastguard Worker // Use image 1
1603*c8dee2aaSAndroid Build Coastguard Worker s->getCanvas()->drawImage(i1, 0, 0);
1604*c8dee2aaSAndroid Build Coastguard Worker // Flushing image 0 should do nothing, but submit is still called.
1605*c8dee2aaSAndroid Build Coastguard Worker dContext->flushAndSubmit(i0);
1606*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, numSubmits() == 1);
1607*c8dee2aaSAndroid Build Coastguard Worker // Flushing image 1 should flush.
1608*c8dee2aaSAndroid Build Coastguard Worker dContext->flushAndSubmit(i1);
1609*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, numSubmits() == 1);
1610*c8dee2aaSAndroid Build Coastguard Worker // Flushing image 2 should do nothing, but submit is still called.
1611*c8dee2aaSAndroid Build Coastguard Worker dContext->flushAndSubmit(i2);
1612*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, numSubmits() == 1);
1613*c8dee2aaSAndroid Build Coastguard Worker
1614*c8dee2aaSAndroid Build Coastguard Worker // Use image 2
1615*c8dee2aaSAndroid Build Coastguard Worker s->getCanvas()->drawImage(i2, 0, 0);
1616*c8dee2aaSAndroid Build Coastguard Worker // Flushing image 0 should do nothing, but submit is still called.
1617*c8dee2aaSAndroid Build Coastguard Worker dContext->flushAndSubmit(i0);
1618*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, numSubmits() == 1);
1619*c8dee2aaSAndroid Build Coastguard Worker // Flushing image 1 do nothing, but submit is still called.
1620*c8dee2aaSAndroid Build Coastguard Worker dContext->flushAndSubmit(i1);
1621*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, numSubmits() == 1);
1622*c8dee2aaSAndroid Build Coastguard Worker // Flushing image 2 should flush.
1623*c8dee2aaSAndroid Build Coastguard Worker dContext->flushAndSubmit(i2);
1624*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, numSubmits() == 1);
1625*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, static_cast<SkImage_GaneshYUVA*>(as_IB(i2.get()))->isTextureBacked());
1626*c8dee2aaSAndroid Build Coastguard Worker s->getCanvas()->drawImage(i2, 0, 0);
1627*c8dee2aaSAndroid Build Coastguard Worker // Flushing image 0 should do nothing, but submit is still called.
1628*c8dee2aaSAndroid Build Coastguard Worker dContext->flushAndSubmit(i0);
1629*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, numSubmits() == 1);
1630*c8dee2aaSAndroid Build Coastguard Worker // Flushing image 1 do nothing, but submit is still called.
1631*c8dee2aaSAndroid Build Coastguard Worker dContext->flushAndSubmit(i1);
1632*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, numSubmits() == 1);
1633*c8dee2aaSAndroid Build Coastguard Worker // Flushing image 2 should flush.
1634*c8dee2aaSAndroid Build Coastguard Worker dContext->flushAndSubmit(i2);
1635*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, numSubmits() == 1);
1636*c8dee2aaSAndroid Build Coastguard Worker }
1637*c8dee2aaSAndroid Build Coastguard Worker
1638*c8dee2aaSAndroid Build Coastguard Worker constexpr SkM44 gCentripetalCatmulRom
1639*c8dee2aaSAndroid Build Coastguard Worker (0.0f/2, -1.0f/2, 2.0f/2, -1.0f/2,
1640*c8dee2aaSAndroid Build Coastguard Worker 2.0f/2, 0.0f/2, -5.0f/2, 3.0f/2,
1641*c8dee2aaSAndroid Build Coastguard Worker 0.0f/2, 1.0f/2, 4.0f/2, -3.0f/2,
1642*c8dee2aaSAndroid Build Coastguard Worker 0.0f/2, 0.0f/2, -1.0f/2, 1.0f/2);
1643*c8dee2aaSAndroid Build Coastguard Worker
1644*c8dee2aaSAndroid Build Coastguard Worker constexpr SkM44 gMitchellNetravali
1645*c8dee2aaSAndroid Build Coastguard Worker ( 1.0f/18, -9.0f/18, 15.0f/18, -7.0f/18,
1646*c8dee2aaSAndroid Build Coastguard Worker 16.0f/18, 0.0f/18, -36.0f/18, 21.0f/18,
1647*c8dee2aaSAndroid Build Coastguard Worker 1.0f/18, 9.0f/18, 27.0f/18, -21.0f/18,
1648*c8dee2aaSAndroid Build Coastguard Worker 0.0f/18, 0.0f/18, -6.0f/18, 7.0f/18);
1649*c8dee2aaSAndroid Build Coastguard Worker
DEF_TEST(image_cubicresampler,reporter)1650*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(image_cubicresampler, reporter) {
1651*c8dee2aaSAndroid Build Coastguard Worker auto diff = [reporter](const SkM44& a, const SkM44& b) {
1652*c8dee2aaSAndroid Build Coastguard Worker const float tolerance = 0.000001f;
1653*c8dee2aaSAndroid Build Coastguard Worker for (int r = 0; r < 4; ++r) {
1654*c8dee2aaSAndroid Build Coastguard Worker for (int c = 0; c < 4; ++c) {
1655*c8dee2aaSAndroid Build Coastguard Worker float d = std::abs(a.rc(r, c) - b.rc(r, c));
1656*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, d <= tolerance);
1657*c8dee2aaSAndroid Build Coastguard Worker }
1658*c8dee2aaSAndroid Build Coastguard Worker }
1659*c8dee2aaSAndroid Build Coastguard Worker };
1660*c8dee2aaSAndroid Build Coastguard Worker
1661*c8dee2aaSAndroid Build Coastguard Worker diff(SkImageShader::CubicResamplerMatrix(1.0f/3, 1.0f/3), gMitchellNetravali);
1662*c8dee2aaSAndroid Build Coastguard Worker
1663*c8dee2aaSAndroid Build Coastguard Worker diff(SkImageShader::CubicResamplerMatrix(0, 1.0f/2), gCentripetalCatmulRom);
1664*c8dee2aaSAndroid Build Coastguard Worker }
1665*c8dee2aaSAndroid Build Coastguard Worker
DEF_TEST(image_subset_encode_skbug_7752,reporter)1666*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(image_subset_encode_skbug_7752, reporter) {
1667*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> image = ToolUtils::GetResourceAsImage("images/mandrill_128.png");
1668*c8dee2aaSAndroid Build Coastguard Worker const int W = image->width();
1669*c8dee2aaSAndroid Build Coastguard Worker const int H = image->height();
1670*c8dee2aaSAndroid Build Coastguard Worker
1671*c8dee2aaSAndroid Build Coastguard Worker auto check_roundtrip = [&](const sk_sp<SkImage>& img) {
1672*c8dee2aaSAndroid Build Coastguard Worker auto img2 = SkImages::DeferredFromEncodedData(SkPngEncoder::Encode(nullptr, img.get(), {}));
1673*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, ToolUtils::equal_pixels(img.get(), img2.get()));
1674*c8dee2aaSAndroid Build Coastguard Worker };
1675*c8dee2aaSAndroid Build Coastguard Worker check_roundtrip(image); // should trivially pass
1676*c8dee2aaSAndroid Build Coastguard Worker check_roundtrip(image->makeSubset(nullptr, {0, 0, W/2, H/2}));
1677*c8dee2aaSAndroid Build Coastguard Worker check_roundtrip(image->makeSubset(nullptr, {W/2, H/2, W, H}));
1678*c8dee2aaSAndroid Build Coastguard Worker check_roundtrip(image->makeColorSpace(nullptr, SkColorSpace::MakeSRGBLinear()));
1679*c8dee2aaSAndroid Build Coastguard Worker }
1680