blob: 346f56bc6862dcd8bf0e7ed916f6891e474392cf [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"
13#include "GrRenderTargetContext.h"
Brian Osman32342f02017-03-04 08:12:46 -050014#include "GrResourceProvider.h"
Brian Salomonbf7b6202016-11-11 16:08:03 -050015#include "GrTexture.h"
16#include "effects/GrSimpleTextureEffect.h"
17
18template <typename I>
19static SK_WHEN(std::is_integral<I>::value && 4 == sizeof(I), void)
Brian Osman07792b22017-01-04 14:11:36 -050020check_pixels(skiatest::Reporter* reporter, int w, int h, const I exepctedData[],
21 const I actualData[], const char* testName) {
Brian Salomonbf7b6202016-11-11 16:08:03 -050022 for (int j = 0; j < h; ++j) {
23 for (int i = 0; i < w; ++i) {
24 I expected = exepctedData[j * w + i];
25 I actual = actualData[j * w + i];
26 if (expected != actual) {
Brian Osman07792b22017-01-04 14:11:36 -050027 ERRORF(reporter, "[%s] Expected 0x08%x, got 0x%08x at %d, %d.", testName, expected,
28 actual, i, j);
Brian Salomonbf7b6202016-11-11 16:08:03 -050029 return;
30 }
31 }
32 }
33}
34
35DEF_GPUTEST_FOR_RENDERING_CONTEXTS(IntTexture, reporter, ctxInfo) {
36 GrContext* context = ctxInfo.grContext();
37 if (!context->caps()->isConfigTexturable(kRGBA_8888_sint_GrPixelConfig)) {
38 return;
39 }
40 static const int kS = UINT8_MAX + 1;
Robert Phillipsd46697a2017-01-25 12:10:37 -050041 static const size_t kRowBytes = kS * sizeof(int32_t);
42
Brian Salomonbf7b6202016-11-11 16:08:03 -050043 GrSurfaceDesc desc;
44 desc.fConfig = kRGBA_8888_sint_GrPixelConfig;
45 desc.fWidth = kS;
46 desc.fHeight = kS;
Brian Salomonbf7b6202016-11-11 16:08:03 -050047
48 std::unique_ptr<int32_t[]> testData(new int32_t[kS * kS]);
49 for (int j = 0; j < kS; ++j) {
50 for (int i = 0; i < kS; ++i) {
51 uint32_t r = i - INT8_MIN;
52 uint32_t g = j - INT8_MIN;
53 uint32_t b = INT8_MAX - r;
54 uint32_t a = INT8_MAX - g;
55 testData.get()[j * kS + i] = (a << 24) | (b << 16) | (g << 8) | r;
56 }
57 }
58
Robert Phillipsd46697a2017-01-25 12:10:37 -050059 // Test that attempting to create a integer texture with multiple MIP levels fails.
60 {
61 GrMipLevel levels[2];
62 levels[0].fPixels = testData.get();
63 levels[0].fRowBytes = kRowBytes;
64 levels[1].fPixels = testData.get();
65 levels[1].fRowBytes = (kS / 2) * sizeof(int32_t);
Brian Salomonbf7b6202016-11-11 16:08:03 -050066
Brian Osman32342f02017-03-04 08:12:46 -050067 sk_sp<GrTexture> temp(context->resourceProvider()->createMipMappedTexture(desc,
68 SkBudgeted::kYes,
69 levels, 2));
Robert Phillipsd46697a2017-01-25 12:10:37 -050070 REPORTER_ASSERT(reporter, !temp);
71 }
72
73 // Test that we can create an integer texture.
Robert Phillips26c90e02017-03-14 14:39:29 -040074 sk_sp<GrTextureProxy> proxy = GrSurfaceProxy::MakeDeferred(context->resourceProvider(),
Robert Phillips2f493142017-03-02 18:18:38 -050075 desc, SkBudgeted::kYes,
76 testData.get(),
77 kRowBytes);
Robert Phillipsd46697a2017-01-25 12:10:37 -050078 REPORTER_ASSERT(reporter, proxy);
Robert Phillips2f493142017-03-02 18:18:38 -050079 if (!proxy) {
Robert Phillipsd46697a2017-01-25 12:10:37 -050080 return;
81 }
82
Brian Osman32342f02017-03-04 08:12:46 -050083 GrTexture* texture = proxy->instantiate(context->resourceProvider());
Brian Salomonbf7b6202016-11-11 16:08:03 -050084 REPORTER_ASSERT(reporter, texture);
85 if (!texture) {
86 return;
87 }
88
Brian Salomonbf7b6202016-11-11 16:08:03 -050089 std::unique_ptr<int32_t[]> readData(new int32_t[kS * kS]);
Robert Phillipsd46697a2017-01-25 12:10:37 -050090 // Test that reading to a non-integer config fails.
91 {
92 bool success = texture->readPixels(0, 0, kS, kS, kRGBA_8888_GrPixelConfig, readData.get());
93 REPORTER_ASSERT(reporter, !success);
Brian Salomonbf7b6202016-11-11 16:08:03 -050094 }
Robert Phillipsd46697a2017-01-25 12:10:37 -050095 {
96 std::unique_ptr<uint16_t[]> halfData(new uint16_t[4 * kS * kS]);
97 bool success = texture->readPixels(0, 0, kS, kS, kRGBA_half_GrPixelConfig, halfData.get());
98 REPORTER_ASSERT(reporter, !success);
99 }
100 {
101 // Can read back as ints. (ES only requires being able to read back into 32bit ints which
102 // we don't support. Right now this test is counting on GR_RGBA_INTEGER/GL_BYTE being the
103 // implementation-dependent second format).
104 sk_bzero(readData.get(), sizeof(int32_t) * kS * kS);
105 bool success = texture->readPixels(0, 0, kS, kS, kRGBA_8888_sint_GrPixelConfig,
106 readData.get());
107 REPORTER_ASSERT(reporter, success);
108 if (success) {
109 check_pixels(reporter, kS, kS, testData.get(), readData.get(), "readPixels");
110 }
111 }
112 {
113 // readPixels should fail if we attempt to use the unpremul flag with an integer texture.
114 bool success = texture->readPixels(0, 0, kS, kS, kRGBA_8888_sint_GrPixelConfig,
115 readData.get(), 0, GrContext::kUnpremul_PixelOpsFlag);
116 REPORTER_ASSERT(reporter, !success);
117 }
Brian Salomonbf7b6202016-11-11 16:08:03 -0500118
119 // Test that copying from one integer texture to another succeeds.
Robert Phillipse2f7d182016-12-15 09:23:05 -0500120 {
Robert Phillipsd46697a2017-01-25 12:10:37 -0500121 sk_sp<GrSurfaceContext> dstContext(GrSurfaceProxy::TestCopy(context, desc,
122 proxy.get()));
123 REPORTER_ASSERT(reporter, dstContext);
Robert Phillipsf200a902017-01-30 13:27:37 -0500124 if (!dstContext || !dstContext->asTextureProxy()) {
Robert Phillipse2f7d182016-12-15 09:23:05 -0500125 return;
126 }
127
Robert Phillipsf200a902017-01-30 13:27:37 -0500128 GrSurface* copySurface = dstContext->asTextureProxy()->instantiate(
Brian Osman32342f02017-03-04 08:12:46 -0500129 context->resourceProvider());
Robert Phillipse2f7d182016-12-15 09:23:05 -0500130 REPORTER_ASSERT(reporter, copySurface);
131 if (!copySurface) {
132 return;
133 }
134
135 sk_bzero(readData.get(), sizeof(int32_t) * kS * kS);
Robert Phillipsd46697a2017-01-25 12:10:37 -0500136 bool success = copySurface->readPixels(0, 0, kS, kS,
137 kRGBA_8888_sint_GrPixelConfig, readData.get());
Robert Phillipse2f7d182016-12-15 09:23:05 -0500138 REPORTER_ASSERT(reporter, success);
139 if (success) {
Brian Osman07792b22017-01-04 14:11:36 -0500140 check_pixels(reporter, kS, kS, testData.get(), readData.get(), "copyIntegerToInteger");
Robert Phillipse2f7d182016-12-15 09:23:05 -0500141 }
Brian Salomonbf7b6202016-11-11 16:08:03 -0500142 }
143
Robert Phillipse2f7d182016-12-15 09:23:05 -0500144
145 // Test that copying to a non-integer (8888) texture fails.
146 {
147 GrSurfaceDesc nonIntDesc = desc;
148 nonIntDesc.fConfig = kRGBA_8888_GrPixelConfig;
149
Robert Phillipsd46697a2017-01-25 12:10:37 -0500150 sk_sp<GrSurfaceContext> dstContext(GrSurfaceProxy::TestCopy(context, nonIntDesc,
151 proxy.get()));
152 REPORTER_ASSERT(reporter, !dstContext);
Brian Salomonbf7b6202016-11-11 16:08:03 -0500153 }
Robert Phillipse2f7d182016-12-15 09:23:05 -0500154
155 // Test that copying to a non-integer (RGBA_half) texture fails.
156 if (context->caps()->isConfigTexturable(kRGBA_half_GrPixelConfig)) {
157 GrSurfaceDesc nonIntDesc = desc;
158 nonIntDesc.fConfig = kRGBA_half_GrPixelConfig;
159
Robert Phillipsd46697a2017-01-25 12:10:37 -0500160 sk_sp<GrSurfaceContext> dstContext(GrSurfaceProxy::TestCopy(context, nonIntDesc,
161 proxy.get()));
162 REPORTER_ASSERT(reporter, !dstContext);
Brian Salomonbf7b6202016-11-11 16:08:03 -0500163 }
164
165 // We overwrite the top left quarter of the texture with the bottom right quarter of the
166 // original data.
167 const void* bottomRightQuarter = testData.get() + kS / 2 * kS + kS / 2;
Brian Salomonbf7b6202016-11-11 16:08:03 -0500168
Robert Phillipsd46697a2017-01-25 12:10:37 -0500169 {
170 // Can't write pixels from a non-int config.
171 bool success = texture->writePixels(0, 0, kS/2, kS/2, kRGBA_8888_GrPixelConfig,
172 bottomRightQuarter, kRowBytes);
173 REPORTER_ASSERT(reporter, !success);
174 }
175 {
176 // Can't use unpremul flag.
177 bool success = texture->writePixels(0, 0, kS/2, kS/2, kRGBA_8888_sint_GrPixelConfig,
178 bottomRightQuarter, kRowBytes,
179 GrContext::kUnpremul_PixelOpsFlag);
180 REPORTER_ASSERT(reporter, !success);
181 }
182 {
183 bool success = texture->writePixels(0, 0, kS/2, kS/2, kRGBA_8888_sint_GrPixelConfig,
184 bottomRightQuarter, kRowBytes);
185 REPORTER_ASSERT(reporter, success);
186 if (!success) {
187 return;
188 }
Brian Salomonbf7b6202016-11-11 16:08:03 -0500189
Robert Phillipsd46697a2017-01-25 12:10:37 -0500190 sk_bzero(readData.get(), sizeof(int32_t) * kS * kS);
191 success = texture->readPixels(0, 0, kS, kS, kRGBA_8888_sint_GrPixelConfig, readData.get());
192 REPORTER_ASSERT(reporter, success);
193 if (!success) {
194 return;
195 }
196 std::unique_ptr<int32_t[]> overwrittenTestData(new int32_t[kS * kS]);
197 memcpy(overwrittenTestData.get(), testData.get(), sizeof(int32_t) * kS * kS);
198 char* dst = (char*)overwrittenTestData.get();
199 char* src = (char*)(testData.get() + kS/2 * kS + kS/2);
200 for (int i = 0; i < kS/2; ++i) {
201 memcpy(dst, src, sizeof(int32_t) * kS/2);
202 dst += kRowBytes;
203 src += kRowBytes;
204 }
205 check_pixels(reporter, kS, kS, overwrittenTestData.get(), readData.get(), "overwrite");
Brian Salomonbf7b6202016-11-11 16:08:03 -0500206 }
Brian Salomonbf7b6202016-11-11 16:08:03 -0500207
208 // Test drawing from the integer texture to a fixed point texture. To avoid any premul issues
209 // we init the int texture with 0s and 1s and make alpha always be 1. We expect that 1s turn
210 // into 0xffs and zeros stay zero.
211 std::unique_ptr<uint32_t[]> expectedData(new uint32_t[kS * kS]);
212 std::unique_ptr<uint32_t[]> actualData(new uint32_t[kS * kS]);
213 for (int i = 0; i < kS*kS; ++i) {
214 int32_t a = 0x1;
215 int32_t b = ((i & 0x1) ? 1 : 0);
216 int32_t g = ((i & 0x1) ? 0 : 1);
217 int32_t r = ((i & 0x2) ? 1 : 0);
218 testData.get()[i] = (a << 24) | (b << 16) | (g << 8) | r;
219 expectedData.get()[i] = ((0xFF * a) << 24) | ((0xFF * b) << 16) |
220 ((0xFF * g) << 8) | (0xFF * r);
221 }
222 texture->writePixels(0, 0, kS, kS, kRGBA_8888_sint_GrPixelConfig, testData.get());
Robert Phillipsd46697a2017-01-25 12:10:37 -0500223
Brian Salomonbf7b6202016-11-11 16:08:03 -0500224 sk_sp<GrRenderTargetContext> rtContext = context->makeRenderTargetContext(
225 SkBackingFit::kExact, kS, kS, kRGBA_8888_GrPixelConfig, nullptr);
226
Brian Osman07792b22017-01-04 14:11:36 -0500227 struct {
228 GrSamplerParams::FilterMode fMode;
229 const char* fName;
230 } kNamedFilters[] ={
231 { GrSamplerParams::kNone_FilterMode, "filter-none" },
232 { GrSamplerParams::kBilerp_FilterMode, "filter-bilerp" },
233 { GrSamplerParams::kMipMap_FilterMode, "filter-mipmap" }
234 };
235
236 for (auto filter : kNamedFilters) {
Robert Phillipsd46697a2017-01-25 12:10:37 -0500237 sk_sp<GrFragmentProcessor> fp(GrSimpleTextureEffect::Make(texture, nullptr,
Robert Phillips67c18d62017-01-20 12:44:06 -0500238 SkMatrix::I(),
Brian Osman07792b22017-01-04 14:11:36 -0500239 filter.fMode));
Brian Salomonbf7b6202016-11-11 16:08:03 -0500240 REPORTER_ASSERT(reporter, fp);
241 if (!fp) {
242 return;
243 }
244 rtContext->clear(nullptr, 0xDDAABBCC, true);
245 GrPaint paint;
246 paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
247 paint.addColorFragmentProcessor(fp);
Brian Salomon82f44312017-01-11 13:42:54 -0500248 rtContext->drawPaint(GrNoClip(), std::move(paint), SkMatrix::I());
Brian Salomonbf7b6202016-11-11 16:08:03 -0500249 SkImageInfo readInfo = SkImageInfo::Make(kS, kS, kRGBA_8888_SkColorType,
250 kPremul_SkAlphaType);
251 rtContext->readPixels(readInfo, actualData.get(), 0, 0, 0);
Brian Osman07792b22017-01-04 14:11:36 -0500252 check_pixels(reporter, kS, kS, expectedData.get(), actualData.get(), filter.fName);
Brian Salomonbf7b6202016-11-11 16:08:03 -0500253 }
254
Robert Phillipsd46697a2017-01-25 12:10:37 -0500255 {
256 // No rendering to integer textures.
257 GrSurfaceDesc intRTDesc = desc;
258 intRTDesc.fFlags = kRenderTarget_GrSurfaceFlag;
Brian Osman32342f02017-03-04 08:12:46 -0500259 sk_sp<GrTexture> temp(context->resourceProvider()->createTexture(intRTDesc,
260 SkBudgeted::kYes));
Robert Phillipsd46697a2017-01-25 12:10:37 -0500261 REPORTER_ASSERT(reporter, !temp);
262 }
Brian Salomonbf7b6202016-11-11 16:08:03 -0500263}
264
265#endif