1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2024 Google LLC
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 "tests/Test.h"
9*c8dee2aaSAndroid Build Coastguard Worker
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkCanvas.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/graphite/BackendTexture.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/graphite/Context.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/graphite/Image.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/graphite/Recorder.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/graphite/Surface.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkAutoPixmapStorage.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/Caps.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/ContextPriv.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "tools/gpu/ManagedBackendTexture.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "tools/graphite/GraphiteTestContext.h"
21*c8dee2aaSAndroid Build Coastguard Worker
22*c8dee2aaSAndroid Build Coastguard Worker using namespace skgpu;
23*c8dee2aaSAndroid Build Coastguard Worker using namespace skgpu::graphite;
24*c8dee2aaSAndroid Build Coastguard Worker
DEF_CONDITIONAL_GRAPHITE_TEST_FOR_ALL_CONTEXTS(ImageWrapTextureMipmapsTest,reporter,context,testContext,true,CtsEnforcement::kApiLevel_V)25*c8dee2aaSAndroid Build Coastguard Worker DEF_CONDITIONAL_GRAPHITE_TEST_FOR_ALL_CONTEXTS(ImageWrapTextureMipmapsTest,
26*c8dee2aaSAndroid Build Coastguard Worker reporter,
27*c8dee2aaSAndroid Build Coastguard Worker context,
28*c8dee2aaSAndroid Build Coastguard Worker testContext,
29*c8dee2aaSAndroid Build Coastguard Worker true,
30*c8dee2aaSAndroid Build Coastguard Worker CtsEnforcement::kApiLevel_V) {
31*c8dee2aaSAndroid Build Coastguard Worker auto recorder = context->makeRecorder();
32*c8dee2aaSAndroid Build Coastguard Worker if (!recorder) {
33*c8dee2aaSAndroid Build Coastguard Worker ERRORF(reporter, "Could not make recorder");
34*c8dee2aaSAndroid Build Coastguard Worker return;
35*c8dee2aaSAndroid Build Coastguard Worker }
36*c8dee2aaSAndroid Build Coastguard Worker
37*c8dee2aaSAndroid Build Coastguard Worker skgpu::Protected isProtected = skgpu::Protected(context->priv().caps()->protectedSupport());
38*c8dee2aaSAndroid Build Coastguard Worker
39*c8dee2aaSAndroid Build Coastguard Worker auto info = SkImageInfo::Make({2, 1}, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
40*c8dee2aaSAndroid Build Coastguard Worker SkAutoPixmapStorage basePM, topPM;
41*c8dee2aaSAndroid Build Coastguard Worker basePM.alloc(info);
42*c8dee2aaSAndroid Build Coastguard Worker basePM.erase(SK_ColorGREEN);
43*c8dee2aaSAndroid Build Coastguard Worker topPM.alloc(info.makeDimensions({1, 1}));
44*c8dee2aaSAndroid Build Coastguard Worker topPM.erase(SK_ColorBLUE);
45*c8dee2aaSAndroid Build Coastguard Worker
46*c8dee2aaSAndroid Build Coastguard Worker SkPixmap levelPMs[]{basePM, topPM};
47*c8dee2aaSAndroid Build Coastguard Worker auto mbet = sk_gpu_test::ManagedGraphiteTexture::MakeMipmappedFromPixmaps(recorder.get(),
48*c8dee2aaSAndroid Build Coastguard Worker levelPMs,
49*c8dee2aaSAndroid Build Coastguard Worker Renderable::kNo,
50*c8dee2aaSAndroid Build Coastguard Worker isProtected);
51*c8dee2aaSAndroid Build Coastguard Worker
52*c8dee2aaSAndroid Build Coastguard Worker if (!mbet) {
53*c8dee2aaSAndroid Build Coastguard Worker ERRORF(reporter, "Could not make backend texture");
54*c8dee2aaSAndroid Build Coastguard Worker return;
55*c8dee2aaSAndroid Build Coastguard Worker }
56*c8dee2aaSAndroid Build Coastguard Worker
57*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<Recording> recording = recorder->snap();
58*c8dee2aaSAndroid Build Coastguard Worker
59*c8dee2aaSAndroid Build Coastguard Worker auto recordingFinishProc = [](void* context, CallbackResult) {
60*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<Recording>(static_cast<Recording*>(context));
61*c8dee2aaSAndroid Build Coastguard Worker };
62*c8dee2aaSAndroid Build Coastguard Worker
63*c8dee2aaSAndroid Build Coastguard Worker skgpu::graphite::InsertRecordingInfo recordingInfo;
64*c8dee2aaSAndroid Build Coastguard Worker recordingInfo.fFinishedProc = recordingFinishProc;
65*c8dee2aaSAndroid Build Coastguard Worker recordingInfo.fRecording = recording.get();
66*c8dee2aaSAndroid Build Coastguard Worker recordingInfo.fFinishedContext = recording.release();
67*c8dee2aaSAndroid Build Coastguard Worker if (!context->insertRecording(recordingInfo)) {
68*c8dee2aaSAndroid Build Coastguard Worker ERRORF(reporter, "Could not insert recording");
69*c8dee2aaSAndroid Build Coastguard Worker return;
70*c8dee2aaSAndroid Build Coastguard Worker }
71*c8dee2aaSAndroid Build Coastguard Worker
72*c8dee2aaSAndroid Build Coastguard Worker static constexpr struct TestCase {
73*c8dee2aaSAndroid Build Coastguard Worker SkImages::GenerateMipmapsFromBase genMipmaps;
74*c8dee2aaSAndroid Build Coastguard Worker SkColor expectedColor;
75*c8dee2aaSAndroid Build Coastguard Worker } kTestCases[]{{SkImages::GenerateMipmapsFromBase::kNo , 0xFFFF0000},
76*c8dee2aaSAndroid Build Coastguard Worker {SkImages::GenerateMipmapsFromBase::kYes, 0XFF00FF00}};
77*c8dee2aaSAndroid Build Coastguard Worker
78*c8dee2aaSAndroid Build Coastguard Worker for (const auto& testCase : kTestCases) {
79*c8dee2aaSAndroid Build Coastguard Worker recorder = context->makeRecorder();
80*c8dee2aaSAndroid Build Coastguard Worker if (!recorder) {
81*c8dee2aaSAndroid Build Coastguard Worker ERRORF(reporter, "Could not make recorder");
82*c8dee2aaSAndroid Build Coastguard Worker return;
83*c8dee2aaSAndroid Build Coastguard Worker }
84*c8dee2aaSAndroid Build Coastguard Worker
85*c8dee2aaSAndroid Build Coastguard Worker auto image = SkImages::WrapTexture(recorder.get(),
86*c8dee2aaSAndroid Build Coastguard Worker mbet->texture(),
87*c8dee2aaSAndroid Build Coastguard Worker info.colorType(),
88*c8dee2aaSAndroid Build Coastguard Worker info.alphaType(),
89*c8dee2aaSAndroid Build Coastguard Worker info.refColorSpace(),
90*c8dee2aaSAndroid Build Coastguard Worker Origin::kTopLeft,
91*c8dee2aaSAndroid Build Coastguard Worker testCase.genMipmaps,
92*c8dee2aaSAndroid Build Coastguard Worker sk_gpu_test::ManagedGraphiteTexture::ImageReleaseProc,
93*c8dee2aaSAndroid Build Coastguard Worker mbet->releaseContext());
94*c8dee2aaSAndroid Build Coastguard Worker if (!recorder) {
95*c8dee2aaSAndroid Build Coastguard Worker ERRORF(reporter, "Could not make image");
96*c8dee2aaSAndroid Build Coastguard Worker return;
97*c8dee2aaSAndroid Build Coastguard Worker }
98*c8dee2aaSAndroid Build Coastguard Worker
99*c8dee2aaSAndroid Build Coastguard Worker // We determe the contents of the image's top level by doing a downsampling draw to a
100*c8dee2aaSAndroid Build Coastguard Worker // surface and then reading the surface's contents.
101*c8dee2aaSAndroid Build Coastguard Worker auto surface = SkSurfaces::RenderTarget(recorder.get(), info.makeDimensions({1, 1}));
102*c8dee2aaSAndroid Build Coastguard Worker if (!recorder) {
103*c8dee2aaSAndroid Build Coastguard Worker ERRORF(reporter, "Could not make surface");
104*c8dee2aaSAndroid Build Coastguard Worker return;
105*c8dee2aaSAndroid Build Coastguard Worker }
106*c8dee2aaSAndroid Build Coastguard Worker
107*c8dee2aaSAndroid Build Coastguard Worker auto shader = image->makeShader(
108*c8dee2aaSAndroid Build Coastguard Worker SkTileMode::kRepeat,
109*c8dee2aaSAndroid Build Coastguard Worker SkTileMode::kRepeat,
110*c8dee2aaSAndroid Build Coastguard Worker SkSamplingOptions(SkFilterMode::kNearest, SkMipmapMode::kNearest));
111*c8dee2aaSAndroid Build Coastguard Worker
112*c8dee2aaSAndroid Build Coastguard Worker surface->getCanvas()->scale(0.05f, 0.05f);
113*c8dee2aaSAndroid Build Coastguard Worker SkPaint paint;
114*c8dee2aaSAndroid Build Coastguard Worker paint.setShader(std::move(shader));
115*c8dee2aaSAndroid Build Coastguard Worker surface->getCanvas()->drawPaint(paint);
116*c8dee2aaSAndroid Build Coastguard Worker
117*c8dee2aaSAndroid Build Coastguard Worker recording = recorder->snap();
118*c8dee2aaSAndroid Build Coastguard Worker recordingInfo.fRecording = recording.get();
119*c8dee2aaSAndroid Build Coastguard Worker recordingInfo.fFinishedContext = recording.release();
120*c8dee2aaSAndroid Build Coastguard Worker if (!context->insertRecording(recordingInfo)) {
121*c8dee2aaSAndroid Build Coastguard Worker ERRORF(reporter, "Could not insert recording");
122*c8dee2aaSAndroid Build Coastguard Worker return;
123*c8dee2aaSAndroid Build Coastguard Worker }
124*c8dee2aaSAndroid Build Coastguard Worker
125*c8dee2aaSAndroid Build Coastguard Worker struct ReadContext {
126*c8dee2aaSAndroid Build Coastguard Worker bool called = false;
127*c8dee2aaSAndroid Build Coastguard Worker bool success = false;
128*c8dee2aaSAndroid Build Coastguard Worker uint32_t color;
129*c8dee2aaSAndroid Build Coastguard Worker };
130*c8dee2aaSAndroid Build Coastguard Worker auto readPixelsCallback = [](SkImage::ReadPixelsContext context,
131*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<const SkImage::AsyncReadResult> result) {
132*c8dee2aaSAndroid Build Coastguard Worker auto& readContext = *static_cast<ReadContext*>(context);
133*c8dee2aaSAndroid Build Coastguard Worker readContext.called = true;
134*c8dee2aaSAndroid Build Coastguard Worker if (result) {
135*c8dee2aaSAndroid Build Coastguard Worker readContext.success = true;
136*c8dee2aaSAndroid Build Coastguard Worker readContext.color = *static_cast<const uint32_t*>(result->data(0));
137*c8dee2aaSAndroid Build Coastguard Worker }
138*c8dee2aaSAndroid Build Coastguard Worker };
139*c8dee2aaSAndroid Build Coastguard Worker ReadContext readContext;
140*c8dee2aaSAndroid Build Coastguard Worker context->asyncRescaleAndReadPixels(surface.get(),
141*c8dee2aaSAndroid Build Coastguard Worker surface->imageInfo(),
142*c8dee2aaSAndroid Build Coastguard Worker SkIRect::MakeSize(surface->imageInfo().dimensions()),
143*c8dee2aaSAndroid Build Coastguard Worker SkImage::RescaleGamma::kSrc,
144*c8dee2aaSAndroid Build Coastguard Worker SkImage::RescaleMode::kNearest,
145*c8dee2aaSAndroid Build Coastguard Worker readPixelsCallback,
146*c8dee2aaSAndroid Build Coastguard Worker &readContext);
147*c8dee2aaSAndroid Build Coastguard Worker context->submit();
148*c8dee2aaSAndroid Build Coastguard Worker while (!readContext.called) {
149*c8dee2aaSAndroid Build Coastguard Worker testContext->tick();
150*c8dee2aaSAndroid Build Coastguard Worker context->checkAsyncWorkCompletion();
151*c8dee2aaSAndroid Build Coastguard Worker }
152*c8dee2aaSAndroid Build Coastguard Worker
153*c8dee2aaSAndroid Build Coastguard Worker if (!readContext.success) {
154*c8dee2aaSAndroid Build Coastguard Worker ERRORF(reporter, "Read pixels failed");
155*c8dee2aaSAndroid Build Coastguard Worker return;
156*c8dee2aaSAndroid Build Coastguard Worker }
157*c8dee2aaSAndroid Build Coastguard Worker
158*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, readContext.color == testCase.expectedColor);
159*c8dee2aaSAndroid Build Coastguard Worker }
160*c8dee2aaSAndroid Build Coastguard Worker }
161