xref: /aosp_15_r20/external/skia/tests/graphite/ImageWrapTextureMipmapsTest.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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