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