1 /*
2 * Copyright 2023 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/SkBitmap.h"
11 #include "include/core/SkColorSpace.h"
12 #include "include/core/SkRect.h"
13 #include "include/core/SkTileMode.h"
14 #include "include/gpu/graphite/Context.h"
15 #include "include/gpu/graphite/Image.h"
16 #include "include/gpu/graphite/Surface.h"
17 #include "src/gpu/graphite/Caps.h"
18 #include "src/gpu/graphite/ContextPriv.h"
19 #include "src/gpu/graphite/Surface_Graphite.h"
20 #include "src/shaders/SkImageShader.h"
21 #include "tools/ToolUtils.h"
22 #include "tools/gpu/ManagedBackendTexture.h"
23
24 namespace skgpu::graphite {
25
26 namespace {
27
28 using DrawFn = void (*)(sk_sp<SkImage>, SkCanvas*, SkRect /*srcRect*/, SkRect /*dstRect*/);
29
30 constexpr SkColor4f kTopColor = SkColors::kRed;
31 constexpr SkColor4f kBottomColor = SkColors::kBlue;
32 constexpr int32_t kHalfSize = 4;
33 constexpr SkISize kImageSize = {2*kHalfSize, 2*kHalfSize};
34
test_draw(skiatest::Reporter * reporter,Context * context,skgpu::Origin origin,SkRect srcRect,SkRect dstRect,DrawFn drawImageFn)35 void test_draw(skiatest::Reporter* reporter,
36 Context* context,
37 skgpu::Origin origin,
38 SkRect srcRect,
39 SkRect dstRect,
40 DrawFn drawImageFn) {
41 std::unique_ptr<Recorder> recorder = context->makeRecorder();
42
43 skgpu::Protected isProtected = skgpu::Protected(context->priv().caps()->protectedSupport());
44
45 SkBitmap bitmap;
46 bitmap.allocPixels(SkImageInfo::Make(kImageSize, kRGBA_8888_SkColorType, kPremul_SkAlphaType),
47 0);
48 bitmap.eraseColor(kTopColor);
49 bitmap.erase(kBottomColor,
50 SkIRect::MakeLTRB(0, kHalfSize, kImageSize.width(), kImageSize.height()));
51
52 auto managedTexture =
53 sk_gpu_test::ManagedGraphiteTexture::MakeFromPixmap(recorder.get(),
54 bitmap.pixmap(),
55 skgpu::Mipmapped::kNo,
56 skgpu::Renderable::kNo,
57 isProtected);
58
59 REPORTER_ASSERT(reporter, managedTexture);
60 if (!managedTexture) {
61 return;
62 }
63
64 sk_sp<SkImage> image = SkImages::WrapTexture(recorder.get(),
65 managedTexture->texture(),
66 kRGBA_8888_SkColorType,
67 kPremul_SkAlphaType,
68 /*colorSpace=*/nullptr,
69 origin);
70
71 REPORTER_ASSERT(reporter, image);
72 if (!image) {
73 return;
74 }
75
76 sk_sp<SkSurface> surface = SkSurfaces::RenderTarget(
77 recorder.get(),
78 SkImageInfo::Make(kImageSize, kRGBA_8888_SkColorType, kPremul_SkAlphaType));
79
80 REPORTER_ASSERT(reporter, surface);
81 if (!surface) {
82 return;
83 }
84
85 SkCanvas* canvas = surface->getCanvas();
86
87 drawImageFn(image, canvas, srcRect, dstRect);
88
89 SkPixmap pm;
90
91 SkBitmap result;
92 result.allocPixels(SkImageInfo::Make(kImageSize, kRGBA_8888_SkColorType, kPremul_SkAlphaType));
93 bool peekPixelsSuccess = result.peekPixels(&pm);
94 REPORTER_ASSERT(reporter, peekPixelsSuccess);
95
96 bool readPixelsSuccess = surface->readPixels(pm, 0, 0);
97 REPORTER_ASSERT(reporter, readPixelsSuccess);
98
99 bool resultTopColorOnTop = origin == skgpu::Origin::kTopLeft;
100
101 for (int32_t y = 0; y < kImageSize.height(); ++y) {
102 for (int32_t x = 0; x < kImageSize.width(); ++x) {
103 SkColor4f color = pm.getColor4f(x, y);
104
105 SkColor4f expectedColor = ((y < kHalfSize) == resultTopColorOnTop) ? kTopColor
106 : kBottomColor;
107 REPORTER_ASSERT(reporter,
108 color == expectedColor,
109 "At position {%d, %d}, "
110 "expected {%.1f, %.1f, %.1f, %.1f}, "
111 "found {%.1f, %.1f, %.1f, %.1f}",
112 x, y,
113 expectedColor.fR, expectedColor.fG, expectedColor.fB, expectedColor.fA,
114 color.fR, color.fG, color.fB, color.fA);
115 }
116 }
117 }
118
119 const SkRect kTestSrcRects[] = {
120 // entire thing
121 SkRect::MakeWH(kImageSize.width(), kImageSize.height()),
122 // half rect still splitting top and bottom colors
123 SkRect::MakeXYWH(2, 2, kHalfSize, kHalfSize),
124 };
125
test_draw_fn(skiatest::Reporter * reporter,Context * context,DrawFn drawImageFn)126 void test_draw_fn(skiatest::Reporter* reporter,
127 Context* context,
128 DrawFn drawImageFn) {
129 for (auto origin : {skgpu::Origin::kTopLeft, skgpu::Origin::kBottomLeft}) {
130 for (auto srcRect: kTestSrcRects) {
131 test_draw(reporter,
132 context,
133 origin,
134 srcRect,
135 SkRect::MakeWH(kImageSize.width(), kImageSize.height()),
136 drawImageFn);
137 }
138 }
139 }
140
draw_image(sk_sp<SkImage> image,SkCanvas * canvas,SkRect srcRect,SkRect dstRect)141 void draw_image(sk_sp<SkImage> image,
142 SkCanvas* canvas,
143 SkRect srcRect,
144 SkRect dstRect) {
145 canvas->drawImageRect(image,
146 srcRect,
147 dstRect,
148 SkSamplingOptions(),
149 /*paint=*/nullptr,
150 SkCanvas::kStrict_SrcRectConstraint);
151 }
152
draw_image_with_shader(sk_sp<SkImage> image,SkCanvas * canvas,SkRect srcRect,SkRect dstRect)153 void draw_image_with_shader(sk_sp<SkImage> image,
154 SkCanvas* canvas,
155 SkRect srcRect,
156 SkRect dstRect) {
157 SkPaint p;
158 SkMatrix srcToDst = SkMatrix::RectToRect(srcRect, dstRect);
159 p.setShader(SkImageShader::MakeSubset(
160 std::move(image),
161 srcRect,
162 SkTileMode::kClamp,
163 SkTileMode::kClamp,
164 SkSamplingOptions(),
165 &srcToDst));
166 canvas->drawRect(dstRect, p);
167 }
168
169 } // anonymous namespace
170
171
DEF_GRAPHITE_TEST_FOR_RENDERING_CONTEXTS(ImageOriginTest_drawImage_Graphite,reporter,context,CtsEnforcement::kApiLevel_V)172 DEF_GRAPHITE_TEST_FOR_RENDERING_CONTEXTS(ImageOriginTest_drawImage_Graphite, reporter, context,
173 CtsEnforcement::kApiLevel_V) {
174 test_draw_fn(reporter, context, draw_image);
175 }
176
DEF_GRAPHITE_TEST_FOR_RENDERING_CONTEXTS(ImageOriginTest_imageShader_Graphite,reporter,context,CtsEnforcement::kApiLevel_V)177 DEF_GRAPHITE_TEST_FOR_RENDERING_CONTEXTS(ImageOriginTest_imageShader_Graphite, reporter, context,
178 CtsEnforcement::kApiLevel_V) {
179 test_draw_fn(reporter, context, draw_image_with_shader);
180 }
181
182 } // namespace skgpu::graphite
183