blob: 72f05f9591c110d15bf43cdf99d3657ca7393af3 [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
Robert Phillipsf41c22f2017-04-18 07:48:58 -040085 sk_sp<GrSurfaceContext> sContext = context->contextPriv().makeWrappedSurfaceContext(
86 std::move(proxy), nullptr);
87 if (!sContext) {
88 return;
89 }
90
Brian Salomonbf7b6202016-11-11 16:08:03 -050091 std::unique_ptr<int32_t[]> readData(new int32_t[kS * kS]);
Robert Phillipsd46697a2017-01-25 12:10:37 -050092 // Test that reading to a non-integer config fails.
93 {
Robert Phillipsf41c22f2017-04-18 07:48:58 -040094 bool success = context->contextPriv().readSurfacePixels(sContext.get(),
Robert Phillipse78b7252017-04-06 07:59:41 -040095 0, 0, kS, kS,
96 kRGBA_8888_GrPixelConfig,
97 nullptr, readData.get());
Robert Phillipsd46697a2017-01-25 12:10:37 -050098 REPORTER_ASSERT(reporter, !success);
Brian Salomonbf7b6202016-11-11 16:08:03 -050099 }
Robert Phillipsd46697a2017-01-25 12:10:37 -0500100 {
101 std::unique_ptr<uint16_t[]> halfData(new uint16_t[4 * kS * kS]);
Robert Phillipsf41c22f2017-04-18 07:48:58 -0400102 bool success = context->contextPriv().readSurfacePixels(sContext.get(),
Robert Phillipse78b7252017-04-06 07:59:41 -0400103 0, 0, kS, kS,
104 kRGBA_half_GrPixelConfig,
105 nullptr, halfData.get());
Robert Phillipsd46697a2017-01-25 12:10:37 -0500106 REPORTER_ASSERT(reporter, !success);
107 }
108 {
109 // Can read back as ints. (ES only requires being able to read back into 32bit ints which
110 // we don't support. Right now this test is counting on GR_RGBA_INTEGER/GL_BYTE being the
111 // implementation-dependent second format).
112 sk_bzero(readData.get(), sizeof(int32_t) * kS * kS);
Robert Phillipsf41c22f2017-04-18 07:48:58 -0400113 bool success = context->contextPriv().readSurfacePixels(sContext.get(),
Robert Phillipse78b7252017-04-06 07:59:41 -0400114 0, 0, kS, kS,
115 kRGBA_8888_sint_GrPixelConfig,
116 nullptr, readData.get());
Robert Phillipsd46697a2017-01-25 12:10:37 -0500117 REPORTER_ASSERT(reporter, success);
118 if (success) {
119 check_pixels(reporter, kS, kS, testData.get(), readData.get(), "readPixels");
120 }
121 }
122 {
123 // readPixels should fail if we attempt to use the unpremul flag with an integer texture.
Robert Phillipse78b7252017-04-06 07:59:41 -0400124 bool success = context->contextPriv().readSurfacePixels(
Robert Phillipsf41c22f2017-04-18 07:48:58 -0400125 sContext.get(),
Robert Phillipse78b7252017-04-06 07:59:41 -0400126 0, 0, kS, kS,
127 kRGBA_8888_sint_GrPixelConfig,
128 nullptr, readData.get(), 0,
129 GrContextPriv::kUnpremul_PixelOpsFlag);
Robert Phillipsd46697a2017-01-25 12:10:37 -0500130 REPORTER_ASSERT(reporter, !success);
131 }
Brian Salomonbf7b6202016-11-11 16:08:03 -0500132
133 // Test that copying from one integer texture to another succeeds.
Robert Phillipse2f7d182016-12-15 09:23:05 -0500134 {
Robert Phillipsd46697a2017-01-25 12:10:37 -0500135 sk_sp<GrSurfaceContext> dstContext(GrSurfaceProxy::TestCopy(context, desc,
Robert Phillipsf41c22f2017-04-18 07:48:58 -0400136 sContext->asSurfaceProxy()));
Robert Phillipsd46697a2017-01-25 12:10:37 -0500137 REPORTER_ASSERT(reporter, dstContext);
Robert Phillipsf200a902017-01-30 13:27:37 -0500138 if (!dstContext || !dstContext->asTextureProxy()) {
Robert Phillipse2f7d182016-12-15 09:23:05 -0500139 return;
140 }
141
Robert Phillipse2f7d182016-12-15 09:23:05 -0500142 sk_bzero(readData.get(), sizeof(int32_t) * kS * kS);
Robert Phillipsf41c22f2017-04-18 07:48:58 -0400143 bool success = context->contextPriv().readSurfacePixels(dstContext.get(), 0, 0, kS, kS,
Robert Phillipse78b7252017-04-06 07:59:41 -0400144 kRGBA_8888_sint_GrPixelConfig,
145 nullptr, readData.get());
Robert Phillipse2f7d182016-12-15 09:23:05 -0500146 REPORTER_ASSERT(reporter, success);
147 if (success) {
Brian Osman07792b22017-01-04 14:11:36 -0500148 check_pixels(reporter, kS, kS, testData.get(), readData.get(), "copyIntegerToInteger");
Robert Phillipse2f7d182016-12-15 09:23:05 -0500149 }
Brian Salomonbf7b6202016-11-11 16:08:03 -0500150 }
151
Robert Phillipse2f7d182016-12-15 09:23:05 -0500152
153 // Test that copying to a non-integer (8888) texture fails.
154 {
155 GrSurfaceDesc nonIntDesc = desc;
156 nonIntDesc.fConfig = kRGBA_8888_GrPixelConfig;
157
Robert Phillipsd46697a2017-01-25 12:10:37 -0500158 sk_sp<GrSurfaceContext> dstContext(GrSurfaceProxy::TestCopy(context, nonIntDesc,
Robert Phillipsf41c22f2017-04-18 07:48:58 -0400159 sContext->asSurfaceProxy()));
Robert Phillipsd46697a2017-01-25 12:10:37 -0500160 REPORTER_ASSERT(reporter, !dstContext);
Brian Salomonbf7b6202016-11-11 16:08:03 -0500161 }
Robert Phillipse2f7d182016-12-15 09:23:05 -0500162
163 // Test that copying to a non-integer (RGBA_half) texture fails.
164 if (context->caps()->isConfigTexturable(kRGBA_half_GrPixelConfig)) {
165 GrSurfaceDesc nonIntDesc = desc;
166 nonIntDesc.fConfig = kRGBA_half_GrPixelConfig;
167
Robert Phillipsd46697a2017-01-25 12:10:37 -0500168 sk_sp<GrSurfaceContext> dstContext(GrSurfaceProxy::TestCopy(context, nonIntDesc,
Robert Phillipsf41c22f2017-04-18 07:48:58 -0400169 sContext->asSurfaceProxy()));
Robert Phillipsd46697a2017-01-25 12:10:37 -0500170 REPORTER_ASSERT(reporter, !dstContext);
Brian Salomonbf7b6202016-11-11 16:08:03 -0500171 }
172
173 // We overwrite the top left quarter of the texture with the bottom right quarter of the
174 // original data.
175 const void* bottomRightQuarter = testData.get() + kS / 2 * kS + kS / 2;
Brian Salomonbf7b6202016-11-11 16:08:03 -0500176
Robert Phillipsd46697a2017-01-25 12:10:37 -0500177 {
178 // Can't write pixels from a non-int config.
Robert Phillipsf41c22f2017-04-18 07:48:58 -0400179 bool success = context->contextPriv().writeSurfacePixels(sContext.get(),
Robert Phillipse78b7252017-04-06 07:59:41 -0400180 0, 0, kS/2, kS/2,
181 kRGBA_8888_GrPixelConfig, nullptr,
182 bottomRightQuarter, kRowBytes);
Robert Phillipsd46697a2017-01-25 12:10:37 -0500183 REPORTER_ASSERT(reporter, !success);
184 }
185 {
186 // Can't use unpremul flag.
Robert Phillipse78b7252017-04-06 07:59:41 -0400187 bool success = context->contextPriv().writeSurfacePixels(
Robert Phillipsf41c22f2017-04-18 07:48:58 -0400188 sContext.get(),
Robert Phillipse78b7252017-04-06 07:59:41 -0400189 0, 0, kS/2, kS/2,
190 kRGBA_8888_sint_GrPixelConfig,
191 nullptr,
Robert Phillipsd46697a2017-01-25 12:10:37 -0500192 bottomRightQuarter, kRowBytes,
Robert Phillipse78b7252017-04-06 07:59:41 -0400193 GrContextPriv::kUnpremul_PixelOpsFlag);
Robert Phillipsd46697a2017-01-25 12:10:37 -0500194 REPORTER_ASSERT(reporter, !success);
195 }
196 {
Robert Phillipsf41c22f2017-04-18 07:48:58 -0400197 bool success = context->contextPriv().writeSurfacePixels(sContext.get(),
Robert Phillipse78b7252017-04-06 07:59:41 -0400198 0, 0, kS/2, kS/2,
199 kRGBA_8888_sint_GrPixelConfig,
200 nullptr,
201 bottomRightQuarter, kRowBytes);
Robert Phillipsd46697a2017-01-25 12:10:37 -0500202 REPORTER_ASSERT(reporter, success);
203 if (!success) {
204 return;
205 }
Brian Salomonbf7b6202016-11-11 16:08:03 -0500206
Robert Phillipsd46697a2017-01-25 12:10:37 -0500207 sk_bzero(readData.get(), sizeof(int32_t) * kS * kS);
Robert Phillipsf41c22f2017-04-18 07:48:58 -0400208 success = context->contextPriv().readSurfacePixels(sContext.get(),
Robert Phillipse78b7252017-04-06 07:59:41 -0400209 0, 0, kS, kS,
210 kRGBA_8888_sint_GrPixelConfig,
211 nullptr, readData.get(), 0);
Robert Phillipsd46697a2017-01-25 12:10:37 -0500212 REPORTER_ASSERT(reporter, success);
213 if (!success) {
214 return;
215 }
216 std::unique_ptr<int32_t[]> overwrittenTestData(new int32_t[kS * kS]);
217 memcpy(overwrittenTestData.get(), testData.get(), sizeof(int32_t) * kS * kS);
218 char* dst = (char*)overwrittenTestData.get();
219 char* src = (char*)(testData.get() + kS/2 * kS + kS/2);
220 for (int i = 0; i < kS/2; ++i) {
221 memcpy(dst, src, sizeof(int32_t) * kS/2);
222 dst += kRowBytes;
223 src += kRowBytes;
224 }
225 check_pixels(reporter, kS, kS, overwrittenTestData.get(), readData.get(), "overwrite");
Brian Salomonbf7b6202016-11-11 16:08:03 -0500226 }
Brian Salomonbf7b6202016-11-11 16:08:03 -0500227
228 // Test drawing from the integer texture to a fixed point texture. To avoid any premul issues
229 // we init the int texture with 0s and 1s and make alpha always be 1. We expect that 1s turn
230 // into 0xffs and zeros stay zero.
231 std::unique_ptr<uint32_t[]> expectedData(new uint32_t[kS * kS]);
232 std::unique_ptr<uint32_t[]> actualData(new uint32_t[kS * kS]);
233 for (int i = 0; i < kS*kS; ++i) {
234 int32_t a = 0x1;
235 int32_t b = ((i & 0x1) ? 1 : 0);
236 int32_t g = ((i & 0x1) ? 0 : 1);
237 int32_t r = ((i & 0x2) ? 1 : 0);
238 testData.get()[i] = (a << 24) | (b << 16) | (g << 8) | r;
239 expectedData.get()[i] = ((0xFF * a) << 24) | ((0xFF * b) << 16) |
240 ((0xFF * g) << 8) | (0xFF * r);
241 }
Robert Phillipsf41c22f2017-04-18 07:48:58 -0400242 context->contextPriv().writeSurfacePixels(sContext.get(),
Robert Phillipse78b7252017-04-06 07:59:41 -0400243 0, 0, kS, kS,
244 kRGBA_8888_sint_GrPixelConfig, nullptr,
245 testData.get(), 0);
Robert Phillips769e80d2017-03-29 13:06:57 -0400246
Robert Phillipsdd3b3f42017-04-24 10:57:28 -0400247 sk_sp<GrRenderTargetContext> rtContext = context->makeDeferredRenderTargetContext(
Brian Salomonbf7b6202016-11-11 16:08:03 -0500248 SkBackingFit::kExact, kS, kS, kRGBA_8888_GrPixelConfig, nullptr);
249
Brian Osman07792b22017-01-04 14:11:36 -0500250 struct {
251 GrSamplerParams::FilterMode fMode;
252 const char* fName;
253 } kNamedFilters[] ={
254 { GrSamplerParams::kNone_FilterMode, "filter-none" },
255 { GrSamplerParams::kBilerp_FilterMode, "filter-bilerp" },
256 { GrSamplerParams::kMipMap_FilterMode, "filter-mipmap" }
257 };
258
259 for (auto filter : kNamedFilters) {
Robert Phillips769e80d2017-03-29 13:06:57 -0400260 sk_sp<GrFragmentProcessor> fp(GrSimpleTextureEffect::Make(context->resourceProvider(),
Robert Phillipsf41c22f2017-04-18 07:48:58 -0400261 sContext->asTextureProxyRef(),
262 nullptr,
Robert Phillips67c18d62017-01-20 12:44:06 -0500263 SkMatrix::I(),
Brian Osman07792b22017-01-04 14:11:36 -0500264 filter.fMode));
Brian Salomonbf7b6202016-11-11 16:08:03 -0500265 REPORTER_ASSERT(reporter, fp);
266 if (!fp) {
267 return;
268 }
269 rtContext->clear(nullptr, 0xDDAABBCC, true);
270 GrPaint paint;
271 paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
272 paint.addColorFragmentProcessor(fp);
Brian Salomon82f44312017-01-11 13:42:54 -0500273 rtContext->drawPaint(GrNoClip(), std::move(paint), SkMatrix::I());
Brian Salomonbf7b6202016-11-11 16:08:03 -0500274 SkImageInfo readInfo = SkImageInfo::Make(kS, kS, kRGBA_8888_SkColorType,
275 kPremul_SkAlphaType);
276 rtContext->readPixels(readInfo, actualData.get(), 0, 0, 0);
Brian Osman07792b22017-01-04 14:11:36 -0500277 check_pixels(reporter, kS, kS, expectedData.get(), actualData.get(), filter.fName);
Brian Salomonbf7b6202016-11-11 16:08:03 -0500278 }
279
Robert Phillipsd46697a2017-01-25 12:10:37 -0500280 {
281 // No rendering to integer textures.
282 GrSurfaceDesc intRTDesc = desc;
283 intRTDesc.fFlags = kRenderTarget_GrSurfaceFlag;
Brian Osman32342f02017-03-04 08:12:46 -0500284 sk_sp<GrTexture> temp(context->resourceProvider()->createTexture(intRTDesc,
285 SkBudgeted::kYes));
Robert Phillipsd46697a2017-01-25 12:10:37 -0500286 REPORTER_ASSERT(reporter, !temp);
287 }
Brian Salomonbf7b6202016-11-11 16:08:03 -0500288}
289
290#endif