• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2017 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 "GrBackendSurface.h"
13 #include "GrBackendTextureImageGenerator.h"
14 #include "GrContext.h"
15 #include "GrContextPriv.h"
16 #include "GrGpu.h"
17 #include "GrRenderTargetContext.h"
18 #include "GrSemaphore.h"
19 #include "GrSurfaceProxyPriv.h"
20 #include "GrTest.h"
21 #include "GrTexturePriv.h"
22 #include "GrTextureProxy.h"
23 #include "SkCanvas.h"
24 #include "SkImage_Base.h"
25 #include "SkGpuDevice.h"
26 #include "SkPoint.h"
27 #include "SkSurface.h"
28 #include "SkSurface_Gpu.h"
29 #include "Test.h"
30 
31 static constexpr int kSize = 8;
32 
33 // Test that the correct mip map states are on the GrTextures when wrapping GrBackendTextures in
34 // SkImages and SkSurfaces
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrWrappedMipMappedTest,reporter,ctxInfo)35 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrWrappedMipMappedTest, reporter, ctxInfo) {
36     GrContext* context = ctxInfo.grContext();
37     if (!context->caps()->mipMapSupport()) {
38         return;
39     }
40     GrGpu* gpu = context->contextPriv().getGpu();
41 
42     for (auto mipMapped : {GrMipMapped::kNo, GrMipMapped::kYes}) {
43         for (auto isRT : {false, true}) {
44             // CreateTestingOnlyBackendTexture currently doesn't support uploading data to mip maps
45             // so we don't send any. However, we pretend there is data for the checks below which is
46             // fine since we are never actually using these textures for any work on the gpu.
47             GrBackendTexture backendTex = gpu->createTestingOnlyBackendTexture(
48                     nullptr, kSize, kSize, kRGBA_8888_GrPixelConfig, isRT, mipMapped);
49 
50             sk_sp<GrTextureProxy> proxy;
51             sk_sp<SkImage> image;
52             if (isRT) {
53                 sk_sp<SkSurface> surface = SkSurface::MakeFromBackendTexture(
54                                                                            context,
55                                                                            backendTex,
56                                                                            kTopLeft_GrSurfaceOrigin,
57                                                                            0,
58                                                                            kRGBA_8888_SkColorType,
59                                                                            nullptr,
60                                                                            nullptr);
61 
62                 SkGpuDevice* device = ((SkSurface_Gpu*)surface.get())->getDevice();
63                 proxy = device->accessRenderTargetContext()->asTextureProxyRef();
64             } else {
65                 image = SkImage::MakeFromTexture(context, backendTex,
66                                                  kTopLeft_GrSurfaceOrigin,
67                                                  kRGBA_8888_SkColorType,
68                                                  kPremul_SkAlphaType, nullptr,
69                                                  nullptr, nullptr);
70                 proxy = as_IB(image)->asTextureProxyRef();
71             }
72             REPORTER_ASSERT(reporter, proxy);
73             if (!proxy) {
74                 gpu->deleteTestingOnlyBackendTexture(&backendTex);
75                 return;
76             }
77 
78             REPORTER_ASSERT(reporter, proxy->priv().isInstantiated());
79 
80             GrTexture* texture = proxy->priv().peekTexture();
81             REPORTER_ASSERT(reporter, texture);
82             if (!texture) {
83                 gpu->deleteTestingOnlyBackendTexture(&backendTex);
84                 return;
85             }
86 
87             if (GrMipMapped::kYes == mipMapped) {
88                 REPORTER_ASSERT(reporter, GrMipMapped::kYes == texture->texturePriv().mipMapped());
89                 if (isRT) {
90                     REPORTER_ASSERT(reporter, texture->texturePriv().mipMapsAreDirty());
91                 } else {
92                     REPORTER_ASSERT(reporter, !texture->texturePriv().mipMapsAreDirty());
93                 }
94             } else {
95                 REPORTER_ASSERT(reporter, GrMipMapped::kNo == texture->texturePriv().mipMapped());
96             }
97             gpu->deleteTestingOnlyBackendTexture(&backendTex);
98         }
99     }
100 }
101 
102 // Test that we correctly copy or don't copy GrBackendTextures in the GrBackendTextureImageGenerator
103 // based on if we will use mips in the draw and the mip status of the GrBackendTexture.
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrBackendTextureImageMipMappedTest,reporter,ctxInfo)104 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrBackendTextureImageMipMappedTest, reporter, ctxInfo) {
105     GrContext* context = ctxInfo.grContext();
106     if (!context->caps()->mipMapSupport()) {
107         return;
108     }
109     GrGpu* gpu = context->contextPriv().getGpu();
110 
111     for (auto mipMapped : {GrMipMapped::kNo, GrMipMapped::kYes}) {
112         for (auto willUseMips : {false, true}) {
113             GrBackendTexture backendTex = gpu->createTestingOnlyBackendTexture(
114                     nullptr, kSize, kSize, kRGBA_8888_GrPixelConfig, false, mipMapped);
115 
116             sk_sp<SkImage> image = SkImage::MakeFromTexture(context, backendTex,
117                                                             kTopLeft_GrSurfaceOrigin,
118                                                             kRGBA_8888_SkColorType,
119                                                             kPremul_SkAlphaType, nullptr,
120                                                             nullptr, nullptr);
121 
122             GrTextureProxy* proxy = as_IB(image)->peekProxy();
123             REPORTER_ASSERT(reporter, proxy);
124             if (!proxy) {
125                 gpu->deleteTestingOnlyBackendTexture(&backendTex);
126                 return;
127             }
128 
129             REPORTER_ASSERT(reporter, proxy->priv().isInstantiated());
130 
131             sk_sp<GrTexture> texture = sk_ref_sp(proxy->priv().peekTexture());
132             REPORTER_ASSERT(reporter, texture);
133             if (!texture) {
134                 gpu->deleteTestingOnlyBackendTexture(&backendTex);
135                 return;
136             }
137 
138             std::unique_ptr<SkImageGenerator> imageGen = GrBackendTextureImageGenerator::Make(
139                     texture, kTopLeft_GrSurfaceOrigin, nullptr, kPremul_SkAlphaType, nullptr);
140             REPORTER_ASSERT(reporter, imageGen);
141             if (!imageGen) {
142                 gpu->deleteTestingOnlyBackendTexture(&backendTex);
143                 return;
144             }
145 
146             SkIPoint origin = SkIPoint::Make(0,0);
147             // The transfer function behavior isn't used in the generator so set we set it
148             // arbitrarily here.
149             SkTransferFunctionBehavior behavior = SkTransferFunctionBehavior::kIgnore;
150             SkImageInfo imageInfo = SkImageInfo::Make(kSize, kSize, kRGBA_8888_SkColorType,
151                                                       kPremul_SkAlphaType);
152             sk_sp<GrTextureProxy> genProxy = imageGen->generateTexture(context, imageInfo,
153                                                                        origin, behavior,
154                                                                        willUseMips);
155 
156             REPORTER_ASSERT(reporter, genProxy);
157             if (!genProxy) {
158                 gpu->deleteTestingOnlyBackendTexture(&backendTex);
159                 return;
160             }
161 
162             if (GrSurfaceProxy::LazyState::kNot != genProxy->lazyInstantiationState()) {
163                 genProxy->priv().doLazyInstantiation(context->contextPriv().resourceProvider());
164             } else if (!genProxy->priv().isInstantiated()) {
165                 genProxy->instantiate(context->contextPriv().resourceProvider());
166             }
167 
168             REPORTER_ASSERT(reporter, genProxy->priv().isInstantiated());
169             if (!genProxy->priv().isInstantiated()) {
170                 gpu->deleteTestingOnlyBackendTexture(&backendTex);
171                 return;
172             }
173 
174             GrTexture* genTexture = genProxy->priv().peekTexture();
175             REPORTER_ASSERT(reporter, genTexture);
176             if (!genTexture) {
177                 gpu->deleteTestingOnlyBackendTexture(&backendTex);
178                 return;
179             }
180 
181             GrBackendTexture genBackendTex = genTexture->getBackendTexture();
182 
183             if (const GrGLTextureInfo* genTexInfo = genBackendTex.getGLTextureInfo()) {
184                 const GrGLTextureInfo* origTexInfo = backendTex.getGLTextureInfo();
185                 if (willUseMips && GrMipMapped::kNo == mipMapped) {
186                     // We did a copy so the texture IDs should be different
187                     REPORTER_ASSERT(reporter, origTexInfo->fID != genTexInfo->fID);
188                 } else {
189                     REPORTER_ASSERT(reporter, origTexInfo->fID == genTexInfo->fID);
190                 }
191 #ifdef SK_VULKAN
192             } else if (const GrVkImageInfo* genImageInfo = genBackendTex.getVkImageInfo()) {
193                 const GrVkImageInfo* origImageInfo = backendTex.getVkImageInfo();
194                 if (willUseMips && GrMipMapped::kNo == mipMapped) {
195                     // We did a copy so the texture IDs should be different
196                     REPORTER_ASSERT(reporter, origImageInfo->fImage != genImageInfo->fImage);
197                 } else {
198                     REPORTER_ASSERT(reporter, origImageInfo->fImage == genImageInfo->fImage);
199                 }
200 #endif
201             } else {
202                 REPORTER_ASSERT(reporter, false);
203             }
204 
205             // Must make sure the uses of the backend texture have finished (we possibly have a
206             // queued up copy) before we delete the backend texture. Thus we use readPixels here
207             // just to force the synchronization.
208             sk_sp<GrSurfaceContext> surfContext =
209                     context->contextPriv().makeWrappedSurfaceContext(genProxy);
210 
211             SkBitmap bitmap;
212             bitmap.allocPixels(imageInfo);
213             surfContext->readPixels(imageInfo, bitmap.getPixels(), 0, 0, 0, 0);
214 
215             gpu->deleteTestingOnlyBackendTexture(&backendTex);
216         }
217     }
218 }
219 
220 // Test that when we call makeImageSnapshot on an SkSurface we retains the same mip status as the
221 // resource we took the snapshot of.
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrImageSnapshotMipMappedTest,reporter,ctxInfo)222 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrImageSnapshotMipMappedTest, reporter, ctxInfo) {
223     GrContext* context = ctxInfo.grContext();
224     if (!context->caps()->mipMapSupport()) {
225         return;
226     }
227 
228     auto resourceProvider = context->contextPriv().resourceProvider();
229     GrGpu* gpu = context->contextPriv().getGpu();
230 
231     for (auto willUseMips : {false, true}) {
232         for (auto isWrapped : {false, true}) {
233             GrMipMapped mipMapped = willUseMips ? GrMipMapped::kYes : GrMipMapped::kNo;
234             sk_sp<SkSurface> surface;
235             GrBackendTexture backendTex = gpu->createTestingOnlyBackendTexture(
236                     nullptr, kSize, kSize, kRGBA_8888_GrPixelConfig, true, mipMapped);
237             if (isWrapped) {
238                 surface = SkSurface::MakeFromBackendTexture(context,
239                                                             backendTex,
240                                                             kTopLeft_GrSurfaceOrigin,
241                                                             0,
242                                                             kRGBA_8888_SkColorType,
243                                                             nullptr,
244                                                             nullptr);
245             } else {
246                 SkImageInfo info = SkImageInfo::Make(kSize, kSize, kRGBA_8888_SkColorType,
247                                                      kPremul_SkAlphaType);
248                 surface = SkSurface::MakeRenderTarget(context, SkBudgeted::kYes, info, 0,
249                                                       kTopLeft_GrSurfaceOrigin, nullptr,
250                                                       willUseMips);
251             }
252             REPORTER_ASSERT(reporter, surface);
253             if (!surface) {
254                 gpu->deleteTestingOnlyBackendTexture(&backendTex);
255             }
256             SkGpuDevice* device = ((SkSurface_Gpu*)surface.get())->getDevice();
257             GrTextureProxy* texProxy = device->accessRenderTargetContext()->asTextureProxy();
258             REPORTER_ASSERT(reporter, mipMapped == texProxy->mipMapped());
259 
260             texProxy->instantiate(resourceProvider);
261             GrTexture* texture = texProxy->priv().peekTexture();
262             REPORTER_ASSERT(reporter, mipMapped == texture->texturePriv().mipMapped());
263 
264             sk_sp<SkImage> image = surface->makeImageSnapshot();
265             REPORTER_ASSERT(reporter, image);
266             if (!image) {
267                 gpu->deleteTestingOnlyBackendTexture(&backendTex);
268             }
269             texProxy = as_IB(image)->peekProxy();
270             REPORTER_ASSERT(reporter, mipMapped == texProxy->mipMapped());
271 
272             texProxy->instantiate(resourceProvider);
273             texture = texProxy->priv().peekTexture();
274             REPORTER_ASSERT(reporter, mipMapped == texture->texturePriv().mipMapped());
275 
276             // Must flush the context to make sure all the cmds (copies, etc.) from above are sent
277             // to the gpu before we delete the backendHandle.
278             context->flush();
279             gpu->deleteTestingOnlyBackendTexture(&backendTex);
280         }
281     }
282 }
283 
284 #endif
285