blob: eacd0617a2dde06fb9b9bbf979239c754cbd78ca [file] [log] [blame]
Brian Salomonbf7b6202016-11-11 16:08:03 -05001/*
2 * Copyright 2016 Google Inc.
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 "Test.h"
9
10#if SK_SUPPORT_GPU
Brian Salomonc65aec92017-03-09 09:03:58 -050011#include "GrClip.h"
Brian Salomonbf7b6202016-11-11 16:08:03 -050012#include "GrContext.h"
Robert Phillipse78b7252017-04-06 07:59:41 -040013#include "GrContextPriv.h"
Brian Salomonbf7b6202016-11-11 16:08:03 -050014#include "GrRenderTargetContext.h"
Brian Osman32342f02017-03-04 08:12:46 -050015#include "GrResourceProvider.h"
Brian Salomonbf7b6202016-11-11 16:08:03 -050016#include "GrTexture.h"
17#include "effects/GrSimpleTextureEffect.h"
18
19template <typename I>
20static SK_WHEN(std::is_integral<I>::value && 4 == sizeof(I), void)
Brian Osman07792b22017-01-04 14:11:36 -050021check_pixels(skiatest::Reporter* reporter, int w, int h, const I exepctedData[],
22 const I actualData[], const char* testName) {
Brian Salomonbf7b6202016-11-11 16:08:03 -050023 for (int j = 0; j < h; ++j) {
24 for (int i = 0; i < w; ++i) {
25 I expected = exepctedData[j * w + i];
26 I actual = actualData[j * w + i];
27 if (expected != actual) {
Brian Osman07792b22017-01-04 14:11:36 -050028 ERRORF(reporter, "[%s] Expected 0x08%x, got 0x%08x at %d, %d.", testName, expected,
29 actual, i, j);
Brian Salomonbf7b6202016-11-11 16:08:03 -050030 return;
31 }
32 }
33 }
34}
35
36DEF_GPUTEST_FOR_RENDERING_CONTEXTS(IntTexture, reporter, ctxInfo) {
37 GrContext* context = ctxInfo.grContext();
38 if (!context->caps()->isConfigTexturable(kRGBA_8888_sint_GrPixelConfig)) {
39 return;
40 }
41 static const int kS = UINT8_MAX + 1;
Robert Phillipsd46697a2017-01-25 12:10:37 -050042 static const size_t kRowBytes = kS * sizeof(int32_t);
43
Brian Salomonbf7b6202016-11-11 16:08:03 -050044 GrSurfaceDesc desc;
45 desc.fConfig = kRGBA_8888_sint_GrPixelConfig;
46 desc.fWidth = kS;
47 desc.fHeight = kS;
Brian Salomonbf7b6202016-11-11 16:08:03 -050048
49 std::unique_ptr<int32_t[]> testData(new int32_t[kS * kS]);
50 for (int j = 0; j < kS; ++j) {
51 for (int i = 0; i < kS; ++i) {
52 uint32_t r = i - INT8_MIN;
53 uint32_t g = j - INT8_MIN;
54 uint32_t b = INT8_MAX - r;
55 uint32_t a = INT8_MAX - g;
56 testData.get()[j * kS + i] = (a << 24) | (b << 16) | (g << 8) | r;
57 }
58 }
59
Robert Phillipsd46697a2017-01-25 12:10:37 -050060 // Test that attempting to create a integer texture with multiple MIP levels fails.
61 {
62 GrMipLevel levels[2];
63 levels[0].fPixels = testData.get();
64 levels[0].fRowBytes = kRowBytes;
65 levels[1].fPixels = testData.get();
66 levels[1].fRowBytes = (kS / 2) * sizeof(int32_t);
Brian Salomonbf7b6202016-11-11 16:08:03 -050067
Robert Phillipse78b7252017-04-06 07:59:41 -040068 sk_sp<GrTextureProxy> temp(context->resourceProvider()->createMipMappedTexture(
69 desc,
Brian Osman32342f02017-03-04 08:12:46 -050070 SkBudgeted::kYes,
71 levels, 2));
Robert Phillipsd46697a2017-01-25 12:10:37 -050072 REPORTER_ASSERT(reporter, !temp);
73 }
74
75 // Test that we can create an integer texture.
Robert Phillips26c90e02017-03-14 14:39:29 -040076 sk_sp<GrTextureProxy> proxy = GrSurfaceProxy::MakeDeferred(context->resourceProvider(),
Robert Phillips2f493142017-03-02 18:18:38 -050077 desc, SkBudgeted::kYes,
78 testData.get(),
79 kRowBytes);
Robert Phillipsd46697a2017-01-25 12:10:37 -050080 REPORTER_ASSERT(reporter, proxy);
Robert Phillips2f493142017-03-02 18:18:38 -050081 if (!proxy) {
Robert Phillipsd46697a2017-01-25 12:10:37 -050082 return;
83 }
84
Brian Salomonbf7b6202016-11-11 16:08:03 -050085 std::unique_ptr<int32_t[]> readData(new int32_t[kS * kS]);
Robert Phillipsd46697a2017-01-25 12:10:37 -050086 // Test that reading to a non-integer config fails.
87 {
Robert Phillipse78b7252017-04-06 07:59:41 -040088 bool success = context->contextPriv().readSurfacePixels(proxy.get(), nullptr,
89 0, 0, kS, kS,
90 kRGBA_8888_GrPixelConfig,
91 nullptr, readData.get());
Robert Phillipsd46697a2017-01-25 12:10:37 -050092 REPORTER_ASSERT(reporter, !success);
Brian Salomonbf7b6202016-11-11 16:08:03 -050093 }
Robert Phillipsd46697a2017-01-25 12:10:37 -050094 {
95 std::unique_ptr<uint16_t[]> halfData(new uint16_t[4 * kS * kS]);
Robert Phillipse78b7252017-04-06 07:59:41 -040096 bool success = context->contextPriv().readSurfacePixels(proxy.get(), nullptr,
97 0, 0, kS, kS,
98 kRGBA_half_GrPixelConfig,
99 nullptr, halfData.get());
Robert Phillipsd46697a2017-01-25 12:10:37 -0500100 REPORTER_ASSERT(reporter, !success);
101 }
102 {
103 // Can read back as ints. (ES only requires being able to read back into 32bit ints which
104 // we don't support. Right now this test is counting on GR_RGBA_INTEGER/GL_BYTE being the
105 // implementation-dependent second format).
106 sk_bzero(readData.get(), sizeof(int32_t) * kS * kS);
Robert Phillipse78b7252017-04-06 07:59:41 -0400107 bool success = context->contextPriv().readSurfacePixels(proxy.get(), nullptr,
108 0, 0, kS, kS,
109 kRGBA_8888_sint_GrPixelConfig,
110 nullptr, readData.get());
Robert Phillipsd46697a2017-01-25 12:10:37 -0500111 REPORTER_ASSERT(reporter, success);
112 if (success) {
113 check_pixels(reporter, kS, kS, testData.get(), readData.get(), "readPixels");
114 }
115 }
116 {
117 // readPixels should fail if we attempt to use the unpremul flag with an integer texture.
Robert Phillipse78b7252017-04-06 07:59:41 -0400118 bool success = context->contextPriv().readSurfacePixels(
119 proxy.get(), nullptr,
120 0, 0, kS, kS,
121 kRGBA_8888_sint_GrPixelConfig,
122 nullptr, readData.get(), 0,
123 GrContextPriv::kUnpremul_PixelOpsFlag);
Robert Phillipsd46697a2017-01-25 12:10:37 -0500124 REPORTER_ASSERT(reporter, !success);
125 }
Brian Salomonbf7b6202016-11-11 16:08:03 -0500126
127 // Test that copying from one integer texture to another succeeds.
Robert Phillipse2f7d182016-12-15 09:23:05 -0500128 {
Robert Phillipsd46697a2017-01-25 12:10:37 -0500129 sk_sp<GrSurfaceContext> dstContext(GrSurfaceProxy::TestCopy(context, desc,
130 proxy.get()));
131 REPORTER_ASSERT(reporter, dstContext);
Robert Phillipsf200a902017-01-30 13:27:37 -0500132 if (!dstContext || !dstContext->asTextureProxy()) {
Robert Phillipse2f7d182016-12-15 09:23:05 -0500133 return;
134 }
135
Robert Phillipse2f7d182016-12-15 09:23:05 -0500136 sk_bzero(readData.get(), sizeof(int32_t) * kS * kS);
Robert Phillipse78b7252017-04-06 07:59:41 -0400137 bool success = context->contextPriv().readSurfacePixels(dstContext->asSurfaceProxy(),
138 nullptr, 0, 0, kS, kS,
139 kRGBA_8888_sint_GrPixelConfig,
140 nullptr, readData.get());
Robert Phillipse2f7d182016-12-15 09:23:05 -0500141 REPORTER_ASSERT(reporter, success);
142 if (success) {
Brian Osman07792b22017-01-04 14:11:36 -0500143 check_pixels(reporter, kS, kS, testData.get(), readData.get(), "copyIntegerToInteger");
Robert Phillipse2f7d182016-12-15 09:23:05 -0500144 }
Brian Salomonbf7b6202016-11-11 16:08:03 -0500145 }
146
Robert Phillipse2f7d182016-12-15 09:23:05 -0500147
148 // Test that copying to a non-integer (8888) texture fails.
149 {
150 GrSurfaceDesc nonIntDesc = desc;
151 nonIntDesc.fConfig = kRGBA_8888_GrPixelConfig;
152
Robert Phillipsd46697a2017-01-25 12:10:37 -0500153 sk_sp<GrSurfaceContext> dstContext(GrSurfaceProxy::TestCopy(context, nonIntDesc,
154 proxy.get()));
155 REPORTER_ASSERT(reporter, !dstContext);
Brian Salomonbf7b6202016-11-11 16:08:03 -0500156 }
Robert Phillipse2f7d182016-12-15 09:23:05 -0500157
158 // Test that copying to a non-integer (RGBA_half) texture fails.
159 if (context->caps()->isConfigTexturable(kRGBA_half_GrPixelConfig)) {
160 GrSurfaceDesc nonIntDesc = desc;
161 nonIntDesc.fConfig = kRGBA_half_GrPixelConfig;
162
Robert Phillipsd46697a2017-01-25 12:10:37 -0500163 sk_sp<GrSurfaceContext> dstContext(GrSurfaceProxy::TestCopy(context, nonIntDesc,
164 proxy.get()));
165 REPORTER_ASSERT(reporter, !dstContext);
Brian Salomonbf7b6202016-11-11 16:08:03 -0500166 }
167
168 // We overwrite the top left quarter of the texture with the bottom right quarter of the
169 // original data.
170 const void* bottomRightQuarter = testData.get() + kS / 2 * kS + kS / 2;
Brian Salomonbf7b6202016-11-11 16:08:03 -0500171
Robert Phillipsd46697a2017-01-25 12:10:37 -0500172 {
173 // Can't write pixels from a non-int config.
Robert Phillipse78b7252017-04-06 07:59:41 -0400174 bool success = context->contextPriv().writeSurfacePixels(proxy.get(), nullptr,
175 0, 0, kS/2, kS/2,
176 kRGBA_8888_GrPixelConfig, nullptr,
177 bottomRightQuarter, kRowBytes);
Robert Phillipsd46697a2017-01-25 12:10:37 -0500178 REPORTER_ASSERT(reporter, !success);
179 }
180 {
181 // Can't use unpremul flag.
Robert Phillipse78b7252017-04-06 07:59:41 -0400182 bool success = context->contextPriv().writeSurfacePixels(
183 proxy.get(), nullptr,
184 0, 0, kS/2, kS/2,
185 kRGBA_8888_sint_GrPixelConfig,
186 nullptr,
Robert Phillipsd46697a2017-01-25 12:10:37 -0500187 bottomRightQuarter, kRowBytes,
Robert Phillipse78b7252017-04-06 07:59:41 -0400188 GrContextPriv::kUnpremul_PixelOpsFlag);
Robert Phillipsd46697a2017-01-25 12:10:37 -0500189 REPORTER_ASSERT(reporter, !success);
190 }
191 {
Robert Phillipse78b7252017-04-06 07:59:41 -0400192 bool success = context->contextPriv().writeSurfacePixels(proxy.get(), nullptr,
193 0, 0, kS/2, kS/2,
194 kRGBA_8888_sint_GrPixelConfig,
195 nullptr,
196 bottomRightQuarter, kRowBytes);
Robert Phillipsd46697a2017-01-25 12:10:37 -0500197 REPORTER_ASSERT(reporter, success);
198 if (!success) {
199 return;
200 }
Brian Salomonbf7b6202016-11-11 16:08:03 -0500201
Robert Phillipsd46697a2017-01-25 12:10:37 -0500202 sk_bzero(readData.get(), sizeof(int32_t) * kS * kS);
Robert Phillipse78b7252017-04-06 07:59:41 -0400203 success = context->contextPriv().readSurfacePixels(proxy.get(), nullptr,
204 0, 0, kS, kS,
205 kRGBA_8888_sint_GrPixelConfig,
206 nullptr, readData.get(), 0);
Robert Phillipsd46697a2017-01-25 12:10:37 -0500207 REPORTER_ASSERT(reporter, success);
208 if (!success) {
209 return;
210 }
211 std::unique_ptr<int32_t[]> overwrittenTestData(new int32_t[kS * kS]);
212 memcpy(overwrittenTestData.get(), testData.get(), sizeof(int32_t) * kS * kS);
213 char* dst = (char*)overwrittenTestData.get();
214 char* src = (char*)(testData.get() + kS/2 * kS + kS/2);
215 for (int i = 0; i < kS/2; ++i) {
216 memcpy(dst, src, sizeof(int32_t) * kS/2);
217 dst += kRowBytes;
218 src += kRowBytes;
219 }
220 check_pixels(reporter, kS, kS, overwrittenTestData.get(), readData.get(), "overwrite");
Brian Salomonbf7b6202016-11-11 16:08:03 -0500221 }
Brian Salomonbf7b6202016-11-11 16:08:03 -0500222
223 // Test drawing from the integer texture to a fixed point texture. To avoid any premul issues
224 // we init the int texture with 0s and 1s and make alpha always be 1. We expect that 1s turn
225 // into 0xffs and zeros stay zero.
226 std::unique_ptr<uint32_t[]> expectedData(new uint32_t[kS * kS]);
227 std::unique_ptr<uint32_t[]> actualData(new uint32_t[kS * kS]);
228 for (int i = 0; i < kS*kS; ++i) {
229 int32_t a = 0x1;
230 int32_t b = ((i & 0x1) ? 1 : 0);
231 int32_t g = ((i & 0x1) ? 0 : 1);
232 int32_t r = ((i & 0x2) ? 1 : 0);
233 testData.get()[i] = (a << 24) | (b << 16) | (g << 8) | r;
234 expectedData.get()[i] = ((0xFF * a) << 24) | ((0xFF * b) << 16) |
235 ((0xFF * g) << 8) | (0xFF * r);
236 }
Robert Phillipse78b7252017-04-06 07:59:41 -0400237 context->contextPriv().writeSurfacePixels(proxy.get(), nullptr,
238 0, 0, kS, kS,
239 kRGBA_8888_sint_GrPixelConfig, nullptr,
240 testData.get(), 0);
Robert Phillips769e80d2017-03-29 13:06:57 -0400241
Brian Salomonbf7b6202016-11-11 16:08:03 -0500242 sk_sp<GrRenderTargetContext> rtContext = context->makeRenderTargetContext(
243 SkBackingFit::kExact, kS, kS, kRGBA_8888_GrPixelConfig, nullptr);
244
Brian Osman07792b22017-01-04 14:11:36 -0500245 struct {
246 GrSamplerParams::FilterMode fMode;
247 const char* fName;
248 } kNamedFilters[] ={
249 { GrSamplerParams::kNone_FilterMode, "filter-none" },
250 { GrSamplerParams::kBilerp_FilterMode, "filter-bilerp" },
251 { GrSamplerParams::kMipMap_FilterMode, "filter-mipmap" }
252 };
253
254 for (auto filter : kNamedFilters) {
Robert Phillips769e80d2017-03-29 13:06:57 -0400255 sk_sp<GrFragmentProcessor> fp(GrSimpleTextureEffect::Make(context->resourceProvider(),
Robert Phillipse78b7252017-04-06 07:59:41 -0400256 proxy, nullptr,
Robert Phillips67c18d62017-01-20 12:44:06 -0500257 SkMatrix::I(),
Brian Osman07792b22017-01-04 14:11:36 -0500258 filter.fMode));
Brian Salomonbf7b6202016-11-11 16:08:03 -0500259 REPORTER_ASSERT(reporter, fp);
260 if (!fp) {
261 return;
262 }
263 rtContext->clear(nullptr, 0xDDAABBCC, true);
264 GrPaint paint;
265 paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
266 paint.addColorFragmentProcessor(fp);
Brian Salomon82f44312017-01-11 13:42:54 -0500267 rtContext->drawPaint(GrNoClip(), std::move(paint), SkMatrix::I());
Brian Salomonbf7b6202016-11-11 16:08:03 -0500268 SkImageInfo readInfo = SkImageInfo::Make(kS, kS, kRGBA_8888_SkColorType,
269 kPremul_SkAlphaType);
270 rtContext->readPixels(readInfo, actualData.get(), 0, 0, 0);
Brian Osman07792b22017-01-04 14:11:36 -0500271 check_pixels(reporter, kS, kS, expectedData.get(), actualData.get(), filter.fName);
Brian Salomonbf7b6202016-11-11 16:08:03 -0500272 }
273
Robert Phillipsd46697a2017-01-25 12:10:37 -0500274 {
275 // No rendering to integer textures.
276 GrSurfaceDesc intRTDesc = desc;
277 intRTDesc.fFlags = kRenderTarget_GrSurfaceFlag;
Brian Osman32342f02017-03-04 08:12:46 -0500278 sk_sp<GrTexture> temp(context->resourceProvider()->createTexture(intRTDesc,
279 SkBudgeted::kYes));
Robert Phillipsd46697a2017-01-25 12:10:37 -0500280 REPORTER_ASSERT(reporter, !temp);
281 }
Brian Salomonbf7b6202016-11-11 16:08:03 -0500282}
283
284#endif