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