GrMipMappedTest.cpp revision faa095e9842b924c20de84dce1bcc1adad7fe2e4
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    for (auto willUseMips : {false, true}) {
215        for (auto isWrapped : {false, true}) {
216            GrMipMapped mipMapped = willUseMips ? GrMipMapped::kYes : GrMipMapped::kNo;
217            sk_sp<SkSurface> surface;
218            GrBackendTexture backendTex = context->getGpu()->createTestingOnlyBackendTexture(
219                    nullptr, kSize, kSize, kRGBA_8888_GrPixelConfig, true, mipMapped);
220            if (isWrapped) {
221                surface = SkSurface::MakeFromBackendTexture(context,
222                                                            backendTex,
223                                                            kTopLeft_GrSurfaceOrigin,
224                                                            0,
225                                                            kRGBA_8888_SkColorType,
226                                                            nullptr,
227                                                            nullptr);
228            } else {
229                SkImageInfo info = SkImageInfo::Make(kSize, kSize, kRGBA_8888_SkColorType,
230                                                     kPremul_SkAlphaType);
231                surface = SkSurface::MakeRenderTarget(context, SkBudgeted::kYes, info, 0,
232                                                      kTopLeft_GrSurfaceOrigin, nullptr,
233                                                      willUseMips);
234            }
235            REPORTER_ASSERT(reporter, surface);
236            if (!surface) {
237                context->getGpu()->deleteTestingOnlyBackendTexture(&backendTex);
238            }
239            SkGpuDevice* device = ((SkSurface_Gpu*)surface.get())->getDevice();
240            GrTextureProxy* texProxy = device->accessRenderTargetContext()->asTextureProxy();
241            REPORTER_ASSERT(reporter, mipMapped == texProxy->mipMapped());
242
243            texProxy->instantiate(context->resourceProvider());
244            GrTexture* texture = texProxy->priv().peekTexture();
245            REPORTER_ASSERT(reporter, mipMapped == texture->texturePriv().mipMapped());
246
247            sk_sp<SkImage> image = surface->makeImageSnapshot();
248            REPORTER_ASSERT(reporter, image);
249            if (!image) {
250                context->getGpu()->deleteTestingOnlyBackendTexture(&backendTex);
251            }
252            texProxy = as_IB(image)->peekProxy();
253            REPORTER_ASSERT(reporter, mipMapped == texProxy->mipMapped());
254
255            texProxy->instantiate(context->resourceProvider());
256            texture = texProxy->priv().peekTexture();
257            REPORTER_ASSERT(reporter, mipMapped == texture->texturePriv().mipMapped());
258
259            // Must flush the context to make sure all the cmds (copies, etc.) from above are sent
260            // to the gpu before we delete the backendHandle.
261            context->flush();
262            context->getGpu()->deleteTestingOnlyBackendTexture(&backendTex);
263        }
264    }
265}
266
267#endif
268