blob: 3edd4cc986d4ada0aebd5dc2a6517cf2bccf578f [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
11#include "GrContext.h"
12#include "GrRenderTargetContext.h"
13#include "GrTexture.h"
14#include "effects/GrSimpleTextureEffect.h"
15
16template <typename I>
17static SK_WHEN(std::is_integral<I>::value && 4 == sizeof(I), void)
Brian Osman07792b22017-01-04 14:11:36 -050018check_pixels(skiatest::Reporter* reporter, int w, int h, const I exepctedData[],
19 const I actualData[], const char* testName) {
Brian Salomonbf7b6202016-11-11 16:08:03 -050020 for (int j = 0; j < h; ++j) {
21 for (int i = 0; i < w; ++i) {
22 I expected = exepctedData[j * w + i];
23 I actual = actualData[j * w + i];
24 if (expected != actual) {
Brian Osman07792b22017-01-04 14:11:36 -050025 ERRORF(reporter, "[%s] Expected 0x08%x, got 0x%08x at %d, %d.", testName, expected,
26 actual, i, j);
Brian Salomonbf7b6202016-11-11 16:08:03 -050027 return;
28 }
29 }
30 }
31}
32
33DEF_GPUTEST_FOR_RENDERING_CONTEXTS(IntTexture, reporter, ctxInfo) {
34 GrContext* context = ctxInfo.grContext();
35 if (!context->caps()->isConfigTexturable(kRGBA_8888_sint_GrPixelConfig)) {
36 return;
37 }
38 static const int kS = UINT8_MAX + 1;
39 GrSurfaceDesc desc;
40 desc.fConfig = kRGBA_8888_sint_GrPixelConfig;
41 desc.fWidth = kS;
42 desc.fHeight = kS;
43 sk_sp<GrTexture> texture;
44
45 std::unique_ptr<int32_t[]> testData(new int32_t[kS * kS]);
46 for (int j = 0; j < kS; ++j) {
47 for (int i = 0; i < kS; ++i) {
48 uint32_t r = i - INT8_MIN;
49 uint32_t g = j - INT8_MIN;
50 uint32_t b = INT8_MAX - r;
51 uint32_t a = INT8_MAX - g;
52 testData.get()[j * kS + i] = (a << 24) | (b << 16) | (g << 8) | r;
53 }
54 }
55
56 // Test that attempting to create a integer texture with multiple MIP level fails.
57 GrMipLevel levels[2];
58 levels[0].fPixels = testData.get();
59 levels[0].fRowBytes = kS * sizeof(int32_t);
60 levels[1].fPixels = testData.get();
61 levels[1].fRowBytes = (kS / 2) * sizeof(int32_t);
62 texture.reset(context->textureProvider()->createMipMappedTexture(desc, SkBudgeted::kYes, levels,
63 2));
64 REPORTER_ASSERT(reporter, !texture);
65
66 // Test that we can create a integer texture.
67 texture.reset(context->textureProvider()->createTexture(desc, SkBudgeted::kYes,
68 levels[0].fPixels,
69 levels[0].fRowBytes));
70 REPORTER_ASSERT(reporter, texture);
71 if (!texture) {
72 return;
73 }
74
75 // Test that reading to a non-integer config fails.
76 std::unique_ptr<int32_t[]> readData(new int32_t[kS * kS]);
77 bool success = texture->readPixels(0, 0, kS, kS, kRGBA_8888_GrPixelConfig, readData.get());
78 REPORTER_ASSERT(reporter, !success);
79 std::unique_ptr<uint16_t[]> halfData(new uint16_t[4 * kS * kS]);
80 success = texture->readPixels(0, 0, kS, kS, kRGBA_half_GrPixelConfig, halfData.get());
81 REPORTER_ASSERT(reporter, !success);
82
83 // Can read back as ints. (ES only requires being able to read back into 32bit ints which
84 // we don't support. Right now this test is counting on GR_RGBA_INTEGER/GL_BYTE being the
85 // implementation-dependent second format).
86 sk_bzero(readData.get(), sizeof(int32_t) * kS * kS);
87 success = texture->readPixels(0, 0, kS, kS, kRGBA_8888_sint_GrPixelConfig, readData.get());
88 REPORTER_ASSERT(reporter, success);
89 if (success) {
Brian Osman07792b22017-01-04 14:11:36 -050090 check_pixels(reporter, kS, kS, testData.get(), readData.get(), "readPixels");
Brian Salomonbf7b6202016-11-11 16:08:03 -050091 }
92
93 // readPixels should fail if we attempt to use the unpremul flag with an integer texture.
94 success = texture->readPixels(0, 0, kS, kS, kRGBA_8888_sint_GrPixelConfig, readData.get(), 0,
95 GrContext::kUnpremul_PixelOpsFlag);
96 REPORTER_ASSERT(reporter, !success);
97
98 // Test that copying from one integer texture to another succeeds.
Robert Phillipse2f7d182016-12-15 09:23:05 -050099 {
100 sk_sp<GrSurfaceProxy> copy(GrSurfaceProxy::TestCopy(context, desc,
101 texture.get(), SkBudgeted::kYes));
102 REPORTER_ASSERT(reporter, copy);
103 if (!copy) {
104 return;
105 }
106
107 GrSurface* copySurface = copy->instantiate(context->textureProvider());
108 REPORTER_ASSERT(reporter, copySurface);
109 if (!copySurface) {
110 return;
111 }
112
113 sk_bzero(readData.get(), sizeof(int32_t) * kS * kS);
114 success = copySurface->readPixels(0, 0, kS, kS,
115 kRGBA_8888_sint_GrPixelConfig, readData.get());
116 REPORTER_ASSERT(reporter, success);
117 if (success) {
Brian Osman07792b22017-01-04 14:11:36 -0500118 check_pixels(reporter, kS, kS, testData.get(), readData.get(), "copyIntegerToInteger");
Robert Phillipse2f7d182016-12-15 09:23:05 -0500119 }
Brian Salomonbf7b6202016-11-11 16:08:03 -0500120 }
121
Robert Phillipse2f7d182016-12-15 09:23:05 -0500122
123 // Test that copying to a non-integer (8888) texture fails.
124 {
125 GrSurfaceDesc nonIntDesc = desc;
126 nonIntDesc.fConfig = kRGBA_8888_GrPixelConfig;
127
128 sk_sp<GrSurfaceProxy> copy(GrSurfaceProxy::TestCopy(context, nonIntDesc,
129 texture.get(), SkBudgeted::kYes));
130 REPORTER_ASSERT(reporter, !copy);
Brian Salomonbf7b6202016-11-11 16:08:03 -0500131 }
Robert Phillipse2f7d182016-12-15 09:23:05 -0500132
133 // Test that copying to a non-integer (RGBA_half) texture fails.
134 if (context->caps()->isConfigTexturable(kRGBA_half_GrPixelConfig)) {
135 GrSurfaceDesc nonIntDesc = desc;
136 nonIntDesc.fConfig = kRGBA_half_GrPixelConfig;
137
138 sk_sp<GrSurfaceProxy> copy(GrSurfaceProxy::TestCopy(context, nonIntDesc,
139 texture.get(), SkBudgeted::kYes));
140 REPORTER_ASSERT(reporter, !copy);
Brian Salomonbf7b6202016-11-11 16:08:03 -0500141 }
142
143 // We overwrite the top left quarter of the texture with the bottom right quarter of the
144 // original data.
145 const void* bottomRightQuarter = testData.get() + kS / 2 * kS + kS / 2;
146 size_t rowBytes = kS * sizeof(int32_t);
147
148 // Can't write pixels from a non-int config.
149 success = texture->writePixels(0, 0, kS/2, kS/2, kRGBA_8888_GrPixelConfig, bottomRightQuarter,
150 rowBytes);
151 REPORTER_ASSERT(reporter, !success);
152
153 // Can't use unpremul flag.
154 success = texture->writePixels(0, 0, kS/2, kS/2, kRGBA_8888_sint_GrPixelConfig,
155 bottomRightQuarter, rowBytes,
156 GrContext::kUnpremul_PixelOpsFlag);
157 REPORTER_ASSERT(reporter, !success);
158
159 success = texture->writePixels(0, 0, kS/2, kS/2, kRGBA_8888_sint_GrPixelConfig,
160 bottomRightQuarter, rowBytes);
161 REPORTER_ASSERT(reporter, success);
162 if (!success) {
163 return;
164 }
165 sk_bzero(readData.get(), sizeof(int32_t) * kS * kS);
166 success = texture->readPixels(0, 0, kS, kS, kRGBA_8888_sint_GrPixelConfig, readData.get());
167 REPORTER_ASSERT(reporter, success);
168 if (!success) {
169 return;
170 }
171 std::unique_ptr<int32_t[]> overwrittenTestData(new int32_t[kS * kS]);
172 memcpy(overwrittenTestData.get(), testData.get(), sizeof(int32_t) * kS * kS);
173 char* dst = (char*)overwrittenTestData.get();
174 char* src = (char*)(testData.get() + kS/2 * kS + kS/2);
175 for (int i = 0; i < kS/2; ++i) {
176 memcpy(dst, src, sizeof(int32_t) * kS/2);
177 dst += rowBytes;
178 src += rowBytes;
179 }
Brian Osman07792b22017-01-04 14:11:36 -0500180 check_pixels(reporter, kS, kS, overwrittenTestData.get(), readData.get(), "overwrite");
Brian Salomonbf7b6202016-11-11 16:08:03 -0500181
182 // Test drawing from the integer texture to a fixed point texture. To avoid any premul issues
183 // we init the int texture with 0s and 1s and make alpha always be 1. We expect that 1s turn
184 // into 0xffs and zeros stay zero.
185 std::unique_ptr<uint32_t[]> expectedData(new uint32_t[kS * kS]);
186 std::unique_ptr<uint32_t[]> actualData(new uint32_t[kS * kS]);
187 for (int i = 0; i < kS*kS; ++i) {
188 int32_t a = 0x1;
189 int32_t b = ((i & 0x1) ? 1 : 0);
190 int32_t g = ((i & 0x1) ? 0 : 1);
191 int32_t r = ((i & 0x2) ? 1 : 0);
192 testData.get()[i] = (a << 24) | (b << 16) | (g << 8) | r;
193 expectedData.get()[i] = ((0xFF * a) << 24) | ((0xFF * b) << 16) |
194 ((0xFF * g) << 8) | (0xFF * r);
195 }
196 texture->writePixels(0, 0, kS, kS, kRGBA_8888_sint_GrPixelConfig, testData.get());
197 sk_sp<GrRenderTargetContext> rtContext = context->makeRenderTargetContext(
198 SkBackingFit::kExact, kS, kS, kRGBA_8888_GrPixelConfig, nullptr);
199
Brian Osman07792b22017-01-04 14:11:36 -0500200 struct {
201 GrSamplerParams::FilterMode fMode;
202 const char* fName;
203 } kNamedFilters[] ={
204 { GrSamplerParams::kNone_FilterMode, "filter-none" },
205 { GrSamplerParams::kBilerp_FilterMode, "filter-bilerp" },
206 { GrSamplerParams::kMipMap_FilterMode, "filter-mipmap" }
207 };
208
209 for (auto filter : kNamedFilters) {
Robert Phillips4493a9d2017-01-17 11:52:21 -0500210 sk_sp<GrFragmentProcessor> fp(GrSimpleTextureEffect::Make(texture.get(), nullptr,
211 SkMatrix::I(),
Brian Osman07792b22017-01-04 14:11:36 -0500212 filter.fMode));
Brian Salomonbf7b6202016-11-11 16:08:03 -0500213 REPORTER_ASSERT(reporter, fp);
214 if (!fp) {
215 return;
216 }
217 rtContext->clear(nullptr, 0xDDAABBCC, true);
218 GrPaint paint;
219 paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
220 paint.addColorFragmentProcessor(fp);
Brian Salomon82f44312017-01-11 13:42:54 -0500221 rtContext->drawPaint(GrNoClip(), std::move(paint), SkMatrix::I());
Brian Salomonbf7b6202016-11-11 16:08:03 -0500222 SkImageInfo readInfo = SkImageInfo::Make(kS, kS, kRGBA_8888_SkColorType,
223 kPremul_SkAlphaType);
224 rtContext->readPixels(readInfo, actualData.get(), 0, 0, 0);
Brian Osman07792b22017-01-04 14:11:36 -0500225 check_pixels(reporter, kS, kS, expectedData.get(), actualData.get(), filter.fName);
Brian Salomonbf7b6202016-11-11 16:08:03 -0500226 }
227
228 // No rendering to integer textures.
229 GrSurfaceDesc intRTDesc = desc;
230 intRTDesc.fFlags = kRenderTarget_GrSurfaceFlag;
231 texture.reset(context->textureProvider()->createTexture(intRTDesc, SkBudgeted::kYes));
232 REPORTER_ASSERT(reporter, !texture);
233}
234
235#endif