• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 "GrClip.h"
12 #include "GrContext.h"
13 #include "GrContextPriv.h"
14 #include "GrProxyProvider.h"
15 #include "GrRenderTargetContext.h"
16 #include "GrResourceProvider.h"
17 #include "GrTexture.h"
18 #include "effects/GrSimpleTextureEffect.h"
19 
20 template <typename I>
21 static SK_WHEN(std::is_integral<I>::value && 4 == sizeof(I), void)
check_pixels(skiatest::Reporter * reporter,int w,int h,const I exepctedData[],const I actualData[],const char * testName)22 check_pixels(skiatest::Reporter* reporter, int w, int h, const I exepctedData[],
23              const I actualData[], const char* testName) {
24     for (int j = 0; j < h; ++j) {
25         for (int i = 0; i < w; ++i) {
26             I expected = exepctedData[j * w + i];
27             I actual = actualData[j * w + i];
28             if (expected != actual) {
29                 ERRORF(reporter, "[%s] Expected 0x08%x, got 0x%08x at %d, %d.", testName, expected,
30                        actual, i, j);
31                 return;
32             }
33         }
34     }
35 }
36 
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(IntTexture,reporter,ctxInfo)37 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(IntTexture, reporter, ctxInfo) {
38     GrContext* context = ctxInfo.grContext();
39     if (!context->caps()->isConfigTexturable(kRGBA_8888_sint_GrPixelConfig)) {
40         return;
41     }
42 
43     GrProxyProvider* proxyProvider = context->contextPriv().proxyProvider();
44     auto resourceProvider = context->contextPriv().resourceProvider();
45 
46     static const int kS = UINT8_MAX + 1;
47     static const size_t kRowBytes = kS * sizeof(int32_t);
48 
49     GrSurfaceDesc desc;
50     desc.fOrigin = kTopLeft_GrSurfaceOrigin;
51     desc.fConfig = kRGBA_8888_sint_GrPixelConfig;
52     desc.fWidth = kS;
53     desc.fHeight = kS;
54 
55     std::unique_ptr<int32_t[]> testData(new int32_t[kS * kS]);
56     for (int j = 0; j < kS; ++j) {
57         for (int i = 0; i < kS; ++i) {
58             uint32_t r = i - INT8_MIN;
59             uint32_t g = j - INT8_MIN;
60             uint32_t b = INT8_MAX - r;
61             uint32_t a = INT8_MAX - g;
62             testData.get()[j * kS + i] = (a << 24) | (b << 16) | (g << 8) | r;
63         }
64     }
65 
66     // Test that attempting to create a integer texture with multiple MIP levels fails.
67     {
68         GrMipLevel levels[2];
69         levels[0].fPixels = testData.get();
70         levels[0].fRowBytes = kRowBytes;
71         levels[1].fPixels = testData.get();
72         levels[1].fRowBytes = (kS / 2) * sizeof(int32_t);
73 
74         sk_sp<GrTextureProxy> temp = proxyProvider->createMipMapProxy(
75                                                                 desc, SkBudgeted::kYes, levels, 2);
76         REPORTER_ASSERT(reporter, !temp);
77     }
78 
79     sk_sp<GrSurfaceContext> sContext;
80     // Test that we can create a non-mipmapped integer texture.
81     {
82         sk_sp<GrTextureProxy> proxy = proxyProvider->createTextureProxy(desc, SkBudgeted::kYes,
83                                                                         testData.get(), kRowBytes);
84         REPORTER_ASSERT(reporter, proxy);
85         if (!proxy) {
86             return;
87         }
88 
89         sContext = context->contextPriv().makeWrappedSurfaceContext(std::move(proxy));
90         if (!sContext) {
91             return;
92         }
93     }
94 
95     std::unique_ptr<int32_t[]> readData(new int32_t[kS * kS]);
96     // Test that reading to a non-integer config fails.
97     {
98         bool success = context->contextPriv().readSurfacePixels(sContext.get(),
99                                                                 0, 0, kS, kS,
100                                                                 kRGBA_8888_GrPixelConfig,
101                                                                 nullptr, readData.get());
102         REPORTER_ASSERT(reporter, !success);
103     }
104     {
105         std::unique_ptr<uint16_t[]> halfData(new uint16_t[4 * kS * kS]);
106         bool success = context->contextPriv().readSurfacePixels(sContext.get(),
107                                                                 0, 0, kS, kS,
108                                                                 kRGBA_half_GrPixelConfig,
109                                                                 nullptr, halfData.get());
110         REPORTER_ASSERT(reporter, !success);
111     }
112     {
113         // Can read back as ints. (ES only requires being able to read back into 32bit ints which
114         // we don't support. Right now this test is counting on GR_RGBA_INTEGER/GL_BYTE being the
115         // implementation-dependent second format).
116         sk_bzero(readData.get(), sizeof(int32_t) * kS * kS);
117         bool success = context->contextPriv().readSurfacePixels(sContext.get(),
118                                                                 0, 0, kS, kS,
119                                                                 kRGBA_8888_sint_GrPixelConfig,
120                                                                 nullptr, readData.get());
121         REPORTER_ASSERT(reporter, success);
122         if (success) {
123             check_pixels(reporter, kS, kS, testData.get(), readData.get(), "readPixels");
124         }
125     }
126     {
127         // readPixels should fail if we attempt to use the unpremul flag with an integer texture.
128         bool success = context->contextPriv().readSurfacePixels(
129                                                 sContext.get(),
130                                                 0, 0, kS, kS,
131                                                 kRGBA_8888_sint_GrPixelConfig,
132                                                 nullptr, readData.get(), 0,
133                                                 GrContextPriv::kUnpremul_PixelOpsFlag);
134         REPORTER_ASSERT(reporter, !success);
135     }
136 
137     // Test that copying from one integer texture to another succeeds.
138     {
139         sk_sp<GrSurfaceContext> dstContext(GrSurfaceProxy::TestCopy(context, desc,
140                                                                     sContext->asSurfaceProxy()));
141         REPORTER_ASSERT(reporter, dstContext);
142         if (!dstContext || !dstContext->asTextureProxy()) {
143             return;
144         }
145 
146         sk_bzero(readData.get(), sizeof(int32_t) * kS * kS);
147         bool success = context->contextPriv().readSurfacePixels(dstContext.get(), 0, 0, kS, kS,
148                                                                 kRGBA_8888_sint_GrPixelConfig,
149                                                                 nullptr, readData.get());
150         REPORTER_ASSERT(reporter, success);
151         if (success) {
152             check_pixels(reporter, kS, kS, testData.get(), readData.get(), "copyIntegerToInteger");
153         }
154     }
155 
156 
157     // Test that copying to a non-integer (8888) texture fails.
158     {
159         GrSurfaceDesc nonIntDesc = desc;
160         nonIntDesc.fConfig = kRGBA_8888_GrPixelConfig;
161 
162         sk_sp<GrSurfaceContext> dstContext(GrSurfaceProxy::TestCopy(context, nonIntDesc,
163                                                                     sContext->asSurfaceProxy()));
164         REPORTER_ASSERT(reporter, !dstContext);
165     }
166 
167     // Test that copying to a non-integer (RGBA_half) texture fails.
168     if (context->caps()->isConfigTexturable(kRGBA_half_GrPixelConfig)) {
169         GrSurfaceDesc nonIntDesc = desc;
170         nonIntDesc.fConfig = kRGBA_half_GrPixelConfig;
171 
172         sk_sp<GrSurfaceContext> dstContext(GrSurfaceProxy::TestCopy(context, nonIntDesc,
173                                                                     sContext->asSurfaceProxy()));
174         REPORTER_ASSERT(reporter, !dstContext);
175     }
176 
177     // We overwrite the top left quarter of the texture with the bottom right quarter of the
178     // original data.
179     const void* bottomRightQuarter = testData.get() + kS / 2 * kS + kS / 2;
180 
181     {
182         // Can't write pixels from a non-int config.
183         bool success = context->contextPriv().writeSurfacePixels(sContext.get(),
184                                                                  0, 0, kS/2, kS/2,
185                                                                  kRGBA_8888_GrPixelConfig, nullptr,
186                                                                  bottomRightQuarter, kRowBytes);
187         REPORTER_ASSERT(reporter, !success);
188     }
189     {
190         // Can't use unpremul flag.
191         bool success = context->contextPriv().writeSurfacePixels(
192                                             sContext.get(),
193                                             0, 0, kS/2, kS/2,
194                                             kRGBA_8888_sint_GrPixelConfig,
195                                             nullptr,
196                                             bottomRightQuarter, kRowBytes,
197                                             GrContextPriv::kUnpremul_PixelOpsFlag);
198         REPORTER_ASSERT(reporter, !success);
199     }
200     {
201         bool success = context->contextPriv().writeSurfacePixels(sContext.get(),
202                                                                  0, 0, kS/2, kS/2,
203                                                                  kRGBA_8888_sint_GrPixelConfig,
204                                                                  nullptr,
205                                                                  bottomRightQuarter, kRowBytes);
206         REPORTER_ASSERT(reporter, success);
207         if (!success) {
208             return;
209         }
210 
211         sk_bzero(readData.get(), sizeof(int32_t) * kS * kS);
212         success = context->contextPriv().readSurfacePixels(sContext.get(),
213                                                            0, 0, kS, kS,
214                                                            kRGBA_8888_sint_GrPixelConfig,
215                                                            nullptr, readData.get(), 0);
216         REPORTER_ASSERT(reporter, success);
217         if (!success) {
218             return;
219         }
220         std::unique_ptr<int32_t[]> overwrittenTestData(new int32_t[kS * kS]);
221         memcpy(overwrittenTestData.get(), testData.get(), sizeof(int32_t) * kS * kS);
222         char* dst = (char*)overwrittenTestData.get();
223         char* src = (char*)(testData.get() + kS/2 * kS + kS/2);
224         for (int i = 0; i < kS/2; ++i) {
225             memcpy(dst, src, sizeof(int32_t) * kS/2);
226             dst += kRowBytes;
227             src += kRowBytes;
228         }
229         check_pixels(reporter, kS, kS, overwrittenTestData.get(), readData.get(), "overwrite");
230     }
231 
232     // Test drawing from the integer texture to a fixed point texture. To avoid any premul issues
233     // we init the int texture with 0s and 1s and make alpha always be 1. We expect that 1s turn
234     // into 0xffs and zeros stay zero.
235     std::unique_ptr<uint32_t[]> expectedData(new uint32_t[kS * kS]);
236     std::unique_ptr<uint32_t[]> actualData(new uint32_t[kS * kS]);
237     for (int i = 0; i < kS*kS; ++i) {
238         int32_t a = 0x1;
239         int32_t b = ((i & 0x1) ? 1 : 0);
240         int32_t g = ((i & 0x1) ? 0 : 1);
241         int32_t r = ((i & 0x2) ? 1 : 0);
242         testData.get()[i] = (a << 24) | (b << 16) | (g << 8) | r;
243         expectedData.get()[i] = ((0xFF * a) << 24) | ((0xFF * b) << 16) |
244                                 ((0xFF * g) << 8) | (0xFF * r);
245     }
246     context->contextPriv().writeSurfacePixels(sContext.get(),
247                                               0, 0, kS, kS,
248                                               kRGBA_8888_sint_GrPixelConfig, nullptr,
249                                               testData.get(), 0);
250 
251     sk_sp<GrRenderTargetContext> rtContext = context->makeDeferredRenderTargetContext(
252             SkBackingFit::kExact, kS, kS, kRGBA_8888_GrPixelConfig, nullptr);
253 
254     struct {
255         GrSamplerState::Filter fMode;
256         const char* fName;
257     } kNamedFilters[] = {{GrSamplerState::Filter::kNearest, "filter-none"},
258                          {GrSamplerState::Filter::kBilerp, "filter-bilerp"},
259                          {GrSamplerState::Filter::kMipMap, "filter-mipmap"}};
260 
261     for (auto filter : kNamedFilters) {
262         auto fp = GrSimpleTextureEffect::Make(sContext->asTextureProxyRef(), SkMatrix::I(),
263                                               filter.fMode);
264         REPORTER_ASSERT(reporter, fp);
265         if (!fp) {
266             return;
267         }
268         rtContext->clear(nullptr, 0xDDAABBCC, GrRenderTargetContext::CanClearFullscreen::kYes);
269         GrPaint paint;
270         paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
271         paint.addColorFragmentProcessor(std::move(fp));
272         rtContext->drawPaint(GrNoClip(), std::move(paint), SkMatrix::I());
273         SkImageInfo readInfo = SkImageInfo::Make(kS, kS, kRGBA_8888_SkColorType,
274                                                  kPremul_SkAlphaType);
275         rtContext->readPixels(readInfo, actualData.get(), 0, 0, 0);
276         check_pixels(reporter, kS, kS, expectedData.get(), actualData.get(), filter.fName);
277     }
278 
279     {
280         // No rendering to integer textures.
281         GrSurfaceDesc intRTDesc = desc;
282         intRTDesc.fFlags = kRenderTarget_GrSurfaceFlag;
283         sk_sp<GrTexture> temp(resourceProvider->createTexture(intRTDesc, SkBudgeted::kYes));
284         REPORTER_ASSERT(reporter, !temp);
285     }
286 }
287 
288 #endif
289