GrMipMappedTest.cpp revision 261b8aa1de8562f79c1a7c515d968787e027a2c8
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// Test that the correct mip map states are on the GrTextures when wrapping GrBackendTextures in
32// SkImages and SkSurfaces
33DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrWrappedMipMappedTest, reporter, ctxInfo) {
34    GrContext* context = ctxInfo.grContext();
35    if (!context->caps()->mipMapSupport()) {
36        return;
37    }
38    for (auto mipMapped : {GrMipMapped::kNo, GrMipMapped::kYes}) {
39        for (auto isRT : {false, true}) {
40            // CreateTestingOnlyBackendTexture currently doesn't support uploading data to mip maps
41            // so we don't send any. However, we pretend there is data for the checks below which is
42            // fine since we are never actually using these textures for any work on the gpu.
43            GrBackendObject backendHandle = context->getGpu()->createTestingOnlyBackendTexture(
44                    nullptr, 8, 8, kRGBA_8888_GrPixelConfig, isRT, mipMapped);
45
46            GrBackend backend = context->contextPriv().getBackend();
47            GrBackendTexture backendTex = GrTest::CreateBackendTexture(backend,
48                                                                       8,
49                                                                       8,
50                                                                       kRGBA_8888_GrPixelConfig,
51                                                                       mipMapped,
52                                                                       backendHandle);
53
54            GrTextureProxy* proxy;
55            sk_sp<SkImage> image;
56            if (isRT) {
57                sk_sp<SkSurface> surface = SkSurface::MakeFromBackendTexture(
58                                                                           context,
59                                                                           backendTex,
60                                                                           kTopLeft_GrSurfaceOrigin,
61                                                                           0,
62                                                                           nullptr,
63                                                                           nullptr);
64
65                SkGpuDevice* device = ((SkSurface_Gpu*)surface.get())->getDevice();
66                proxy = device->accessRenderTargetContext()->asTextureProxy();
67            } else {
68                image = SkImage::MakeFromTexture(context, backendTex,
69                                                 kTopLeft_GrSurfaceOrigin,
70                                                 kPremul_SkAlphaType, nullptr);
71                proxy = as_IB(image)->peekProxy();
72            }
73            REPORTER_ASSERT(reporter, proxy);
74            if (!proxy) {
75                context->getGpu()->deleteTestingOnlyBackendTexture(backendHandle);
76                return;
77            }
78
79            REPORTER_ASSERT(reporter, proxy->priv().isInstantiated());
80
81            GrTexture* texture = proxy->priv().peekTexture();
82            REPORTER_ASSERT(reporter, texture);
83            if (!texture) {
84                context->getGpu()->deleteTestingOnlyBackendTexture(backendHandle);
85                return;
86            }
87
88            if (GrMipMapped::kYes == mipMapped) {
89                REPORTER_ASSERT(reporter, texture->texturePriv().hasMipMaps());
90                if (isRT) {
91                    REPORTER_ASSERT(reporter, texture->texturePriv().mipMapsAreDirty());
92                } else {
93                    REPORTER_ASSERT(reporter, !texture->texturePriv().mipMapsAreDirty());
94                }
95            } else {
96                REPORTER_ASSERT(reporter, !texture->texturePriv().hasMipMaps());
97            }
98            context->getGpu()->deleteTestingOnlyBackendTexture(backendHandle);
99        }
100    }
101}
102
103// Test that we correctly copy or don't copy GrBackendTextures in the GrBackendTextureImageGenerator
104// based on if we will use mips in the draw and the mip status of the GrBackendTexture.
105DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrBackendTextureImageMipMappedTest, reporter, ctxInfo) {
106    static const int kSize = 8;
107
108    GrContext* context = ctxInfo.grContext();
109    if (!context->caps()->mipMapSupport()) {
110        return;
111    }
112    for (auto mipMapped : {GrMipMapped::kNo, GrMipMapped::kYes}) {
113        for (auto willUseMips : {false, true}) {
114            GrBackendObject backendHandle = context->getGpu()->createTestingOnlyBackendTexture(
115                    nullptr, kSize, kSize, kRGBA_8888_GrPixelConfig, false, mipMapped);
116
117            GrBackend backend = context->contextPriv().getBackend();
118            GrBackendTexture backendTex = GrTest::CreateBackendTexture(backend,
119                                                                       kSize,
120                                                                       kSize,
121                                                                       kRGBA_8888_GrPixelConfig,
122                                                                       mipMapped,
123                                                                       backendHandle);
124
125            sk_sp<SkImage> image = SkImage::MakeFromTexture(context, backendTex,
126                                                            kTopLeft_GrSurfaceOrigin,
127                                                            kPremul_SkAlphaType, nullptr);
128
129            GrTextureProxy* proxy = as_IB(image)->peekProxy();
130            REPORTER_ASSERT(reporter, proxy);
131            if (!proxy) {
132                context->getGpu()->deleteTestingOnlyBackendTexture(backendHandle);
133                return;
134            }
135
136            REPORTER_ASSERT(reporter, proxy->priv().isInstantiated());
137
138            sk_sp<GrTexture> texture = sk_ref_sp(proxy->priv().peekTexture());
139            REPORTER_ASSERT(reporter, texture);
140            if (!texture) {
141                context->getGpu()->deleteTestingOnlyBackendTexture(backendHandle);
142                return;
143            }
144
145            std::unique_ptr<SkImageGenerator> imageGen = GrBackendTextureImageGenerator::Make(
146                    texture, kTopLeft_GrSurfaceOrigin, nullptr, kPremul_SkAlphaType, nullptr);
147            REPORTER_ASSERT(reporter, imageGen);
148            if (!imageGen) {
149                context->getGpu()->deleteTestingOnlyBackendTexture(backendHandle);
150                return;
151            }
152
153            SkIPoint origin = SkIPoint::Make(0,0);
154            // The transfer function behavior isn't used in the generator so set we set it
155            // arbitrarily here.
156            SkTransferFunctionBehavior behavior = SkTransferFunctionBehavior::kIgnore;
157            SkImageInfo imageInfo = SkImageInfo::Make(kSize, kSize, kRGBA_8888_SkColorType,
158                                                      kPremul_SkAlphaType);
159            sk_sp<GrTextureProxy> genProxy = imageGen->generateTexture(context, imageInfo,
160                                                                       origin, behavior,
161                                                                       willUseMips);
162
163            REPORTER_ASSERT(reporter, genProxy);
164            if (!genProxy) {
165                context->getGpu()->deleteTestingOnlyBackendTexture(backendHandle);
166                return;
167            }
168
169            REPORTER_ASSERT(reporter, genProxy->priv().isInstantiated());
170
171            GrTexture* genTexture = genProxy->priv().peekTexture();
172            REPORTER_ASSERT(reporter, genTexture);
173            if (!genTexture) {
174                context->getGpu()->deleteTestingOnlyBackendTexture(backendHandle);
175                return;
176            }
177
178            GrBackendObject genBackendObject = genTexture->getTextureHandle();
179
180            if (kOpenGL_GrBackend == backend) {
181                const GrGLTextureInfo* origTexInfo = backendTex.getGLTextureInfo();
182                GrGLTextureInfo* genTexInfo = (GrGLTextureInfo*)genBackendObject;
183                if (willUseMips && GrMipMapped::kNo == mipMapped) {
184                    // We did a copy so the texture IDs should be different
185                    REPORTER_ASSERT(reporter, origTexInfo->fID != genTexInfo->fID);
186                } else {
187                    REPORTER_ASSERT(reporter, origTexInfo->fID == genTexInfo->fID);
188                }
189            } else if (kVulkan_GrBackend == backend) {
190#ifdef SK_VULKAN
191                const GrVkImageInfo* origImageInfo = backendTex.getVkImageInfo();
192                GrVkImageInfo* genImageInfo = (GrVkImageInfo*)genBackendObject;
193                if (willUseMips && GrMipMapped::kNo == mipMapped) {
194                    // We did a copy so the texture IDs should be different
195                    REPORTER_ASSERT(reporter, origImageInfo->fImage != genImageInfo->fImage);
196                } else {
197                    REPORTER_ASSERT(reporter, origImageInfo->fImage == genImageInfo->fImage);
198                }
199#endif
200            } else if (kMetal_GrBackend == backend) {
201                REPORTER_ASSERT(reporter, false);
202            } else {
203                REPORTER_ASSERT(reporter, false);
204            }
205
206            // Must make sure the uses of the backend texture have finished (we possibly have a
207            // queued up copy) before we delete the backend texture. Thus we use readPixels here
208            // just to force the synchronization.
209            sk_sp<GrSurfaceContext> surfContext =
210                    context->contextPriv().makeWrappedSurfaceContext(genProxy, nullptr);
211
212            SkBitmap bitmap;
213            bitmap.allocPixels(imageInfo);
214            surfContext->readPixels(imageInfo, bitmap.getPixels(), 0, 0, 0, 0);
215
216            context->getGpu()->deleteTestingOnlyBackendTexture(backendHandle);
217        }
218    }
219}
220
221
222#endif
223