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