1 /*
2 * Copyright 2013 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 "SkTypes.h"
9
10 #if SK_SUPPORT_GPU
11
12 #include "GrContext.h"
13 #include "GrContextPriv.h"
14 #include "GrGpu.h"
15 #include "GrProxyProvider.h"
16 #include "GrRenderTarget.h"
17 #include "GrResourceProvider.h"
18 #include "GrTest.h"
19 #include "GrTexture.h"
20 #include "SkMipMap.h"
21 #include "Test.h"
22
23 // Tests that GrSurface::asTexture(), GrSurface::asRenderTarget(), and static upcasting of texture
24 // and render targets to GrSurface all work as expected.
DEF_GPUTEST_FOR_NULLGL_CONTEXT(GrSurface,reporter,ctxInfo)25 DEF_GPUTEST_FOR_NULLGL_CONTEXT(GrSurface, reporter, ctxInfo) {
26 GrContext* context = ctxInfo.grContext();
27 auto resourceProvider = context->contextPriv().resourceProvider();
28 GrGpu* gpu = context->contextPriv().getGpu();
29
30 GrSurfaceDesc desc;
31 desc.fFlags = kRenderTarget_GrSurfaceFlag;
32 desc.fOrigin = kBottomLeft_GrSurfaceOrigin;
33 desc.fWidth = 256;
34 desc.fHeight = 256;
35 desc.fConfig = kRGBA_8888_GrPixelConfig;
36 desc.fSampleCnt = 1;
37 sk_sp<GrSurface> texRT1 = resourceProvider->createTexture(desc, SkBudgeted::kNo);
38
39 REPORTER_ASSERT(reporter, texRT1.get() == texRT1->asRenderTarget());
40 REPORTER_ASSERT(reporter, texRT1.get() == texRT1->asTexture());
41 REPORTER_ASSERT(reporter, static_cast<GrSurface*>(texRT1->asRenderTarget()) ==
42 texRT1->asTexture());
43 REPORTER_ASSERT(reporter, texRT1->asRenderTarget() ==
44 static_cast<GrSurface*>(texRT1->asTexture()));
45 REPORTER_ASSERT(reporter, static_cast<GrSurface*>(texRT1->asRenderTarget()) ==
46 static_cast<GrSurface*>(texRT1->asTexture()));
47
48 desc.fFlags = kNone_GrSurfaceFlags;
49 desc.fOrigin = kTopLeft_GrSurfaceOrigin;
50 sk_sp<GrTexture> tex1 = resourceProvider->createTexture(desc, SkBudgeted::kNo);
51 REPORTER_ASSERT(reporter, nullptr == tex1->asRenderTarget());
52 REPORTER_ASSERT(reporter, tex1.get() == tex1->asTexture());
53 REPORTER_ASSERT(reporter, static_cast<GrSurface*>(tex1.get()) == tex1->asTexture());
54
55 GrBackendTexture backendTex = gpu->createTestingOnlyBackendTexture(
56 nullptr, 256, 256, kRGBA_8888_GrPixelConfig, false, GrMipMapped::kNo);
57
58 sk_sp<GrSurface> texRT2 =
59 resourceProvider->wrapRenderableBackendTexture(backendTex, 1, kBorrow_GrWrapOwnership);
60
61 REPORTER_ASSERT(reporter, texRT2.get() == texRT2->asRenderTarget());
62 REPORTER_ASSERT(reporter, texRT2.get() == texRT2->asTexture());
63 REPORTER_ASSERT(reporter, static_cast<GrSurface*>(texRT2->asRenderTarget()) ==
64 texRT2->asTexture());
65 REPORTER_ASSERT(reporter, texRT2->asRenderTarget() ==
66 static_cast<GrSurface*>(texRT2->asTexture()));
67 REPORTER_ASSERT(reporter, static_cast<GrSurface*>(texRT2->asRenderTarget()) ==
68 static_cast<GrSurface*>(texRT2->asTexture()));
69
70 gpu->deleteTestingOnlyBackendTexture(&backendTex);
71 }
72
73 // This test checks that the isConfigTexturable and isConfigRenderable are
74 // consistent with createTexture's result.
DEF_GPUTEST_FOR_ALL_CONTEXTS(GrSurfaceRenderability,reporter,ctxInfo)75 DEF_GPUTEST_FOR_ALL_CONTEXTS(GrSurfaceRenderability, reporter, ctxInfo) {
76 GrContext* context = ctxInfo.grContext();
77 GrProxyProvider* proxyProvider = context->contextPriv().proxyProvider();
78 GrResourceProvider* resourceProvider = context->contextPriv().resourceProvider();
79 const GrCaps* caps = context->caps();
80
81 GrPixelConfig configs[] = {
82 kUnknown_GrPixelConfig,
83 kAlpha_8_GrPixelConfig,
84 kAlpha_8_as_Alpha_GrPixelConfig,
85 kAlpha_8_as_Red_GrPixelConfig,
86 kGray_8_GrPixelConfig,
87 kGray_8_as_Lum_GrPixelConfig,
88 kGray_8_as_Red_GrPixelConfig,
89 kRGB_565_GrPixelConfig,
90 kRGBA_4444_GrPixelConfig,
91 kRGBA_8888_GrPixelConfig,
92 kBGRA_8888_GrPixelConfig,
93 kSRGBA_8888_GrPixelConfig,
94 kSBGRA_8888_GrPixelConfig,
95 kRGBA_8888_sint_GrPixelConfig,
96 kRGBA_float_GrPixelConfig,
97 kRG_float_GrPixelConfig,
98 kAlpha_half_GrPixelConfig,
99 kAlpha_half_as_Red_GrPixelConfig,
100 kRGBA_half_GrPixelConfig,
101 };
102 SkASSERT(kGrPixelConfigCnt == SK_ARRAY_COUNT(configs));
103
104 GrSurfaceDesc desc;
105 desc.fWidth = 64;
106 desc.fHeight = 64;
107
108 // Enough space for the first mip of our largest pixel config
109 const size_t pixelBufferSize = desc.fWidth * desc.fHeight *
110 GrBytesPerPixel(kRGBA_float_GrPixelConfig);
111 std::unique_ptr<char[]> pixelData(new char[pixelBufferSize]);
112 memset(pixelData.get(), 0, pixelBufferSize);
113
114 // We re-use the same mip level objects (with updated pointers and rowBytes) for each config
115 const int levelCount = SkMipMap::ComputeLevelCount(desc.fWidth, desc.fHeight) + 1;
116 std::unique_ptr<GrMipLevel[]> texels(new GrMipLevel[levelCount]);
117
118 for (GrPixelConfig config : configs) {
119 for (GrSurfaceOrigin origin : { kTopLeft_GrSurfaceOrigin, kBottomLeft_GrSurfaceOrigin }) {
120 desc.fFlags = kNone_GrSurfaceFlags;
121 desc.fOrigin = origin;
122 desc.fConfig = config;
123 desc.fSampleCnt = 1;
124
125 sk_sp<GrSurface> tex = resourceProvider->createTexture(desc, SkBudgeted::kNo);
126 bool ict = caps->isConfigTexturable(desc.fConfig);
127 REPORTER_ASSERT(reporter, SkToBool(tex) == ict,
128 "config:%d, tex:%d, isConfigTexturable:%d", config, SkToBool(tex), ict);
129
130 size_t rowBytes = desc.fWidth * GrBytesPerPixel(desc.fConfig);
131 for (int i = 0; i < levelCount; ++i) {
132 texels[i].fPixels = pixelData.get();
133 texels[i].fRowBytes = rowBytes >> i;
134 }
135
136 sk_sp<GrTextureProxy> proxy = proxyProvider->createMipMapProxy(
137 desc, SkBudgeted::kNo,
138 texels.get(), levelCount);
139 REPORTER_ASSERT(reporter, SkToBool(proxy.get()) ==
140 (caps->isConfigTexturable(desc.fConfig) &&
141 caps->mipMapSupport() &&
142 !GrPixelConfigIsSint(desc.fConfig)));
143
144 desc.fFlags = kRenderTarget_GrSurfaceFlag;
145 tex = resourceProvider->createTexture(desc, SkBudgeted::kNo);
146 bool icr = caps->isConfigRenderable(config, false);
147 REPORTER_ASSERT(reporter, SkToBool(tex) == icr,
148 "config:%d, tex:%d, isConfigRenderable(false):%d", config,
149 SkToBool(tex), icr);
150
151 desc.fSampleCnt = 2;
152 tex = resourceProvider->createTexture(desc, SkBudgeted::kNo);
153 icr = caps->isConfigRenderable(config, true);
154 REPORTER_ASSERT(reporter, SkToBool(tex) == icr,
155 "config:%d, tex:%d, isConfigRenderable(true):%d", config, SkToBool(tex),
156 icr);
157 }
158 }
159 }
160
161 #include "GrDrawingManager.h"
162 #include "GrSurfaceProxy.h"
163 #include "GrTextureContext.h"
164
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(InitialTextureClear,reporter,context_info)165 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(InitialTextureClear, reporter, context_info) {
166 static constexpr int kSize = 100;
167 GrSurfaceDesc desc;
168 desc.fWidth = desc.fHeight = kSize;
169 std::unique_ptr<uint32_t[]> data(new uint32_t[kSize * kSize]);
170
171 GrContext* context = context_info.grContext();
172 GrProxyProvider* proxyProvider = context->contextPriv().proxyProvider();
173
174 for (int c = 0; c <= kLast_GrPixelConfig; ++c) {
175 desc.fConfig = static_cast<GrPixelConfig>(c);
176 if (!context_info.grContext()->caps()->isConfigTexturable(desc.fConfig)) {
177 continue;
178 }
179 desc.fFlags = kPerformInitialClear_GrSurfaceFlag;
180 for (bool rt : {false, true}) {
181 if (rt && !context->caps()->isConfigRenderable(desc.fConfig, false)) {
182 continue;
183 }
184 desc.fFlags |= rt ? kRenderTarget_GrSurfaceFlag : kNone_GrSurfaceFlags;
185 for (GrSurfaceOrigin origin :
186 {kTopLeft_GrSurfaceOrigin, kBottomLeft_GrSurfaceOrigin}) {
187 desc.fOrigin = origin;
188 for (auto fit : { SkBackingFit::kApprox, SkBackingFit::kExact }) {
189 // Try directly creating the texture.
190 // Do this twice in an attempt to hit the cache on the second time through.
191 for (int i = 0; i < 2; ++i) {
192 sk_sp<GrTextureProxy> proxy = proxyProvider->createInstantiatedProxy(
193 desc, fit, SkBudgeted::kYes);
194 if (!proxy) {
195 continue;
196 }
197
198 auto texCtx = context->contextPriv().makeWrappedSurfaceContext(
199 std::move(proxy));
200 SkImageInfo info = SkImageInfo::Make(
201 kSize, kSize, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
202 memset(data.get(), 0xAB, kSize * kSize * sizeof(uint32_t));
203 if (texCtx->readPixels(info, data.get(), 0, 0, 0)) {
204 uint32_t cmp = GrPixelConfigIsOpaque(desc.fConfig) ? 0xFF000000 : 0;
205 for (int i = 0; i < kSize * kSize; ++i) {
206 if (cmp != data.get()[i]) {
207 ERRORF(reporter, "Failed on config %d", desc.fConfig);
208 break;
209 }
210 }
211 }
212 memset(data.get(), 0xBC, kSize * kSize * sizeof(uint32_t));
213 // Here we overwrite the texture so that the second time through we
214 // test against recycling without reclearing.
215 if (0 == i) {
216 texCtx->writePixels(info, data.get(), 0, 0, 0);
217 }
218 }
219 context->purgeAllUnlockedResources();
220
221 // Try creating the texture as a deferred proxy.
222 for (int i = 0; i < 2; ++i) {
223 auto surfCtx = context->contextPriv().makeDeferredSurfaceContext(
224 desc, GrMipMapped::kNo, fit, SkBudgeted::kYes);
225 if (!surfCtx) {
226 continue;
227 }
228 SkImageInfo info = SkImageInfo::Make(
229 kSize, kSize, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
230 memset(data.get(), 0xAB, kSize * kSize * sizeof(uint32_t));
231 if (surfCtx->readPixels(info, data.get(), 0, 0, 0)) {
232 uint32_t cmp = GrPixelConfigIsOpaque(desc.fConfig) ? 0xFF000000 : 0;
233 for (int i = 0; i < kSize * kSize; ++i) {
234 if (cmp != data.get()[i]) {
235 ERRORF(reporter, "Failed on config %d", desc.fConfig);
236 break;
237 }
238 }
239 }
240 // Here we overwrite the texture so that the second time through we
241 // test against recycling without reclearing.
242 if (0 == i) {
243 surfCtx->writePixels(info, data.get(), 0, 0, 0);
244 }
245 }
246 context->purgeAllUnlockedResources();
247 }
248 }
249 }
250 }
251 }
252 #endif
253