• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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