blob: 35019b8937cda51d507b883ebc538721358d418f [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;
Robert Phillipsb7b7e5f2017-05-22 13:23:19 -040045 desc.fOrigin = kTopLeft_GrSurfaceOrigin;
Brian Salomonbf7b6202016-11-11 16:08:03 -050046 desc.fConfig = kRGBA_8888_sint_GrPixelConfig;
47 desc.fWidth = kS;
48 desc.fHeight = kS;
Brian Salomonbf7b6202016-11-11 16:08:03 -050049
50 std::unique_ptr<int32_t[]> testData(new int32_t[kS * kS]);
51 for (int j = 0; j < kS; ++j) {
52 for (int i = 0; i < kS; ++i) {
53 uint32_t r = i - INT8_MIN;
54 uint32_t g = j - INT8_MIN;
55 uint32_t b = INT8_MAX - r;
56 uint32_t a = INT8_MAX - g;
57 testData.get()[j * kS + i] = (a << 24) | (b << 16) | (g << 8) | r;
58 }
59 }
60
Robert Phillipsd46697a2017-01-25 12:10:37 -050061 // Test that attempting to create a integer texture with multiple MIP levels fails.
62 {
63 GrMipLevel levels[2];
64 levels[0].fPixels = testData.get();
65 levels[0].fRowBytes = kRowBytes;
66 levels[1].fPixels = testData.get();
67 levels[1].fRowBytes = (kS / 2) * sizeof(int32_t);
Brian Salomonbf7b6202016-11-11 16:08:03 -050068
Robert Phillips8e8c7552017-07-10 12:06:05 -040069 sk_sp<GrTextureProxy> temp(GrSurfaceProxy::MakeDeferredMipMap(context->resourceProvider(),
70 desc,
71 SkBudgeted::kYes,
72 levels, 2));
Robert Phillipsd46697a2017-01-25 12:10:37 -050073 REPORTER_ASSERT(reporter, !temp);
74 }
75
76 // Test that we can create an integer texture.
Robert Phillips26c90e02017-03-14 14:39:29 -040077 sk_sp<GrTextureProxy> proxy = GrSurfaceProxy::MakeDeferred(context->resourceProvider(),
Robert Phillips2f493142017-03-02 18:18:38 -050078 desc, SkBudgeted::kYes,
79 testData.get(),
80 kRowBytes);
Robert Phillipsd46697a2017-01-25 12:10:37 -050081 REPORTER_ASSERT(reporter, proxy);
Robert Phillips2f493142017-03-02 18:18:38 -050082 if (!proxy) {
Robert Phillipsd46697a2017-01-25 12:10:37 -050083 return;
84 }
85
Robert Phillipsf41c22f2017-04-18 07:48:58 -040086 sk_sp<GrSurfaceContext> sContext = context->contextPriv().makeWrappedSurfaceContext(
87 std::move(proxy), nullptr);
88 if (!sContext) {
89 return;
90 }
91
Brian Salomonbf7b6202016-11-11 16:08:03 -050092 std::unique_ptr<int32_t[]> readData(new int32_t[kS * kS]);
Robert Phillipsd46697a2017-01-25 12:10:37 -050093 // Test that reading to a non-integer config fails.
94 {
Robert Phillipsf41c22f2017-04-18 07:48:58 -040095 bool success = context->contextPriv().readSurfacePixels(sContext.get(),
Robert Phillipse78b7252017-04-06 07:59:41 -040096 0, 0, kS, kS,
97 kRGBA_8888_GrPixelConfig,
98 nullptr, readData.get());
Robert Phillipsd46697a2017-01-25 12:10:37 -050099 REPORTER_ASSERT(reporter, !success);
Brian Salomonbf7b6202016-11-11 16:08:03 -0500100 }
Robert Phillipsd46697a2017-01-25 12:10:37 -0500101 {
102 std::unique_ptr<uint16_t[]> halfData(new uint16_t[4 * kS * kS]);
Robert Phillipsf41c22f2017-04-18 07:48:58 -0400103 bool success = context->contextPriv().readSurfacePixels(sContext.get(),
Robert Phillipse78b7252017-04-06 07:59:41 -0400104 0, 0, kS, kS,
105 kRGBA_half_GrPixelConfig,
106 nullptr, halfData.get());
Robert Phillipsd46697a2017-01-25 12:10:37 -0500107 REPORTER_ASSERT(reporter, !success);
108 }
109 {
110 // Can read back as ints. (ES only requires being able to read back into 32bit ints which
111 // we don't support. Right now this test is counting on GR_RGBA_INTEGER/GL_BYTE being the
112 // implementation-dependent second format).
113 sk_bzero(readData.get(), sizeof(int32_t) * kS * kS);
Robert Phillipsf41c22f2017-04-18 07:48:58 -0400114 bool success = context->contextPriv().readSurfacePixels(sContext.get(),
Robert Phillipse78b7252017-04-06 07:59:41 -0400115 0, 0, kS, kS,
116 kRGBA_8888_sint_GrPixelConfig,
117 nullptr, readData.get());
Robert Phillipsd46697a2017-01-25 12:10:37 -0500118 REPORTER_ASSERT(reporter, success);
119 if (success) {
120 check_pixels(reporter, kS, kS, testData.get(), readData.get(), "readPixels");
121 }
122 }
123 {
124 // readPixels should fail if we attempt to use the unpremul flag with an integer texture.
Robert Phillipse78b7252017-04-06 07:59:41 -0400125 bool success = context->contextPriv().readSurfacePixels(
Robert Phillipsf41c22f2017-04-18 07:48:58 -0400126 sContext.get(),
Robert Phillipse78b7252017-04-06 07:59:41 -0400127 0, 0, kS, kS,
128 kRGBA_8888_sint_GrPixelConfig,
129 nullptr, readData.get(), 0,
130 GrContextPriv::kUnpremul_PixelOpsFlag);
Robert Phillipsd46697a2017-01-25 12:10:37 -0500131 REPORTER_ASSERT(reporter, !success);
132 }
Brian Salomonbf7b6202016-11-11 16:08:03 -0500133
134 // Test that copying from one integer texture to another succeeds.
Robert Phillipse2f7d182016-12-15 09:23:05 -0500135 {
Robert Phillipsd46697a2017-01-25 12:10:37 -0500136 sk_sp<GrSurfaceContext> dstContext(GrSurfaceProxy::TestCopy(context, desc,
Robert Phillipsf41c22f2017-04-18 07:48:58 -0400137 sContext->asSurfaceProxy()));
Robert Phillipsd46697a2017-01-25 12:10:37 -0500138 REPORTER_ASSERT(reporter, dstContext);
Robert Phillipsf200a902017-01-30 13:27:37 -0500139 if (!dstContext || !dstContext->asTextureProxy()) {
Robert Phillipse2f7d182016-12-15 09:23:05 -0500140 return;
141 }
142
Robert Phillipse2f7d182016-12-15 09:23:05 -0500143 sk_bzero(readData.get(), sizeof(int32_t) * kS * kS);
Robert Phillipsf41c22f2017-04-18 07:48:58 -0400144 bool success = context->contextPriv().readSurfacePixels(dstContext.get(), 0, 0, kS, kS,
Robert Phillipse78b7252017-04-06 07:59:41 -0400145 kRGBA_8888_sint_GrPixelConfig,
146 nullptr, readData.get());
Robert Phillipse2f7d182016-12-15 09:23:05 -0500147 REPORTER_ASSERT(reporter, success);
148 if (success) {
Brian Osman07792b22017-01-04 14:11:36 -0500149 check_pixels(reporter, kS, kS, testData.get(), readData.get(), "copyIntegerToInteger");
Robert Phillipse2f7d182016-12-15 09:23:05 -0500150 }
Brian Salomonbf7b6202016-11-11 16:08:03 -0500151 }
152
Robert Phillipse2f7d182016-12-15 09:23:05 -0500153
154 // Test that copying to a non-integer (8888) texture fails.
155 {
156 GrSurfaceDesc nonIntDesc = desc;
157 nonIntDesc.fConfig = kRGBA_8888_GrPixelConfig;
158
Robert Phillipsd46697a2017-01-25 12:10:37 -0500159 sk_sp<GrSurfaceContext> dstContext(GrSurfaceProxy::TestCopy(context, nonIntDesc,
Robert Phillipsf41c22f2017-04-18 07:48:58 -0400160 sContext->asSurfaceProxy()));
Robert Phillipsd46697a2017-01-25 12:10:37 -0500161 REPORTER_ASSERT(reporter, !dstContext);
Brian Salomonbf7b6202016-11-11 16:08:03 -0500162 }
Robert Phillipse2f7d182016-12-15 09:23:05 -0500163
164 // Test that copying to a non-integer (RGBA_half) texture fails.
165 if (context->caps()->isConfigTexturable(kRGBA_half_GrPixelConfig)) {
166 GrSurfaceDesc nonIntDesc = desc;
167 nonIntDesc.fConfig = kRGBA_half_GrPixelConfig;
168
Robert Phillipsd46697a2017-01-25 12:10:37 -0500169 sk_sp<GrSurfaceContext> dstContext(GrSurfaceProxy::TestCopy(context, nonIntDesc,
Robert Phillipsf41c22f2017-04-18 07:48:58 -0400170 sContext->asSurfaceProxy()));
Robert Phillipsd46697a2017-01-25 12:10:37 -0500171 REPORTER_ASSERT(reporter, !dstContext);
Brian Salomonbf7b6202016-11-11 16:08:03 -0500172 }
173
174 // We overwrite the top left quarter of the texture with the bottom right quarter of the
175 // original data.
176 const void* bottomRightQuarter = testData.get() + kS / 2 * kS + kS / 2;
Brian Salomonbf7b6202016-11-11 16:08:03 -0500177
Robert Phillipsd46697a2017-01-25 12:10:37 -0500178 {
179 // Can't write pixels from a non-int config.
Robert Phillipsf41c22f2017-04-18 07:48:58 -0400180 bool success = context->contextPriv().writeSurfacePixels(sContext.get(),
Robert Phillipse78b7252017-04-06 07:59:41 -0400181 0, 0, kS/2, kS/2,
182 kRGBA_8888_GrPixelConfig, nullptr,
183 bottomRightQuarter, kRowBytes);
Robert Phillipsd46697a2017-01-25 12:10:37 -0500184 REPORTER_ASSERT(reporter, !success);
185 }
186 {
187 // Can't use unpremul flag.
Robert Phillipse78b7252017-04-06 07:59:41 -0400188 bool success = context->contextPriv().writeSurfacePixels(
Robert Phillipsf41c22f2017-04-18 07:48:58 -0400189 sContext.get(),
Robert Phillipse78b7252017-04-06 07:59:41 -0400190 0, 0, kS/2, kS/2,
191 kRGBA_8888_sint_GrPixelConfig,
192 nullptr,
Robert Phillipsd46697a2017-01-25 12:10:37 -0500193 bottomRightQuarter, kRowBytes,
Robert Phillipse78b7252017-04-06 07:59:41 -0400194 GrContextPriv::kUnpremul_PixelOpsFlag);
Robert Phillipsd46697a2017-01-25 12:10:37 -0500195 REPORTER_ASSERT(reporter, !success);
196 }
197 {
Robert Phillipsf41c22f2017-04-18 07:48:58 -0400198 bool success = context->contextPriv().writeSurfacePixels(sContext.get(),
Robert Phillipse78b7252017-04-06 07:59:41 -0400199 0, 0, kS/2, kS/2,
200 kRGBA_8888_sint_GrPixelConfig,
201 nullptr,
202 bottomRightQuarter, kRowBytes);
Robert Phillipsd46697a2017-01-25 12:10:37 -0500203 REPORTER_ASSERT(reporter, success);
204 if (!success) {
205 return;
206 }
Brian Salomonbf7b6202016-11-11 16:08:03 -0500207
Robert Phillipsd46697a2017-01-25 12:10:37 -0500208 sk_bzero(readData.get(), sizeof(int32_t) * kS * kS);
Robert Phillipsf41c22f2017-04-18 07:48:58 -0400209 success = context->contextPriv().readSurfacePixels(sContext.get(),
Robert Phillipse78b7252017-04-06 07:59:41 -0400210 0, 0, kS, kS,
211 kRGBA_8888_sint_GrPixelConfig,
212 nullptr, readData.get(), 0);
Robert Phillipsd46697a2017-01-25 12:10:37 -0500213 REPORTER_ASSERT(reporter, success);
214 if (!success) {
215 return;
216 }
217 std::unique_ptr<int32_t[]> overwrittenTestData(new int32_t[kS * kS]);
218 memcpy(overwrittenTestData.get(), testData.get(), sizeof(int32_t) * kS * kS);
219 char* dst = (char*)overwrittenTestData.get();
220 char* src = (char*)(testData.get() + kS/2 * kS + kS/2);
221 for (int i = 0; i < kS/2; ++i) {
222 memcpy(dst, src, sizeof(int32_t) * kS/2);
223 dst += kRowBytes;
224 src += kRowBytes;
225 }
226 check_pixels(reporter, kS, kS, overwrittenTestData.get(), readData.get(), "overwrite");
Brian Salomonbf7b6202016-11-11 16:08:03 -0500227 }
Brian Salomonbf7b6202016-11-11 16:08:03 -0500228
229 // Test drawing from the integer texture to a fixed point texture. To avoid any premul issues
230 // we init the int texture with 0s and 1s and make alpha always be 1. We expect that 1s turn
231 // into 0xffs and zeros stay zero.
232 std::unique_ptr<uint32_t[]> expectedData(new uint32_t[kS * kS]);
233 std::unique_ptr<uint32_t[]> actualData(new uint32_t[kS * kS]);
234 for (int i = 0; i < kS*kS; ++i) {
235 int32_t a = 0x1;
236 int32_t b = ((i & 0x1) ? 1 : 0);
237 int32_t g = ((i & 0x1) ? 0 : 1);
238 int32_t r = ((i & 0x2) ? 1 : 0);
239 testData.get()[i] = (a << 24) | (b << 16) | (g << 8) | r;
240 expectedData.get()[i] = ((0xFF * a) << 24) | ((0xFF * b) << 16) |
241 ((0xFF * g) << 8) | (0xFF * r);
242 }
Robert Phillipsf41c22f2017-04-18 07:48:58 -0400243 context->contextPriv().writeSurfacePixels(sContext.get(),
Robert Phillipse78b7252017-04-06 07:59:41 -0400244 0, 0, kS, kS,
245 kRGBA_8888_sint_GrPixelConfig, nullptr,
246 testData.get(), 0);
Robert Phillips769e80d2017-03-29 13:06:57 -0400247
Robert Phillipsdd3b3f42017-04-24 10:57:28 -0400248 sk_sp<GrRenderTargetContext> rtContext = context->makeDeferredRenderTargetContext(
Brian Salomonbf7b6202016-11-11 16:08:03 -0500249 SkBackingFit::kExact, kS, kS, kRGBA_8888_GrPixelConfig, nullptr);
250
Brian Osman07792b22017-01-04 14:11:36 -0500251 struct {
252 GrSamplerParams::FilterMode fMode;
253 const char* fName;
254 } kNamedFilters[] ={
255 { GrSamplerParams::kNone_FilterMode, "filter-none" },
256 { GrSamplerParams::kBilerp_FilterMode, "filter-bilerp" },
257 { GrSamplerParams::kMipMap_FilterMode, "filter-mipmap" }
258 };
259
260 for (auto filter : kNamedFilters) {
Brian Salomonaff329b2017-08-11 09:40:37 -0400261 auto fp = GrSimpleTextureEffect::Make(sContext->asTextureProxyRef(), nullptr, SkMatrix::I(),
262 filter.fMode);
Brian Salomonbf7b6202016-11-11 16:08:03 -0500263 REPORTER_ASSERT(reporter, fp);
264 if (!fp) {
265 return;
266 }
267 rtContext->clear(nullptr, 0xDDAABBCC, true);
268 GrPaint paint;
269 paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
Brian Salomonaff329b2017-08-11 09:40:37 -0400270 paint.addColorFragmentProcessor(std::move(fp));
Brian Salomon82f44312017-01-11 13:42:54 -0500271 rtContext->drawPaint(GrNoClip(), std::move(paint), SkMatrix::I());
Brian Salomonbf7b6202016-11-11 16:08:03 -0500272 SkImageInfo readInfo = SkImageInfo::Make(kS, kS, kRGBA_8888_SkColorType,
273 kPremul_SkAlphaType);
274 rtContext->readPixels(readInfo, actualData.get(), 0, 0, 0);
Brian Osman07792b22017-01-04 14:11:36 -0500275 check_pixels(reporter, kS, kS, expectedData.get(), actualData.get(), filter.fName);
Brian Salomonbf7b6202016-11-11 16:08:03 -0500276 }
277
Robert Phillipsd46697a2017-01-25 12:10:37 -0500278 {
279 // No rendering to integer textures.
280 GrSurfaceDesc intRTDesc = desc;
281 intRTDesc.fFlags = kRenderTarget_GrSurfaceFlag;
Brian Osman32342f02017-03-04 08:12:46 -0500282 sk_sp<GrTexture> temp(context->resourceProvider()->createTexture(intRTDesc,
283 SkBudgeted::kYes));
Robert Phillipsd46697a2017-01-25 12:10:37 -0500284 REPORTER_ASSERT(reporter, !temp);
285 }
Brian Salomonbf7b6202016-11-11 16:08:03 -0500286}
287
288#endif