1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2017 Google Inc.
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci * found in the LICENSE file.
6cb93a386Sopenharmony_ci */
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ci#include "include/core/SkTypes.h"
9cb93a386Sopenharmony_ci
10cb93a386Sopenharmony_ci#include "include/core/SkCanvas.h"
11cb93a386Sopenharmony_ci#include "include/core/SkPoint.h"
12cb93a386Sopenharmony_ci#include "include/core/SkSurface.h"
13cb93a386Sopenharmony_ci#include "include/gpu/GrBackendSurface.h"
14cb93a386Sopenharmony_ci#include "include/gpu/GrDirectContext.h"
15cb93a386Sopenharmony_ci#ifdef SK_DIRECT3D
16cb93a386Sopenharmony_ci#include "include/gpu/d3d/GrD3DTypes.h"
17cb93a386Sopenharmony_ci#endif
18cb93a386Sopenharmony_ci#include "src/gpu/BaseDevice.h"
19cb93a386Sopenharmony_ci#include "src/gpu/GrBackendTextureImageGenerator.h"
20cb93a386Sopenharmony_ci#include "src/gpu/GrDirectContextPriv.h"
21cb93a386Sopenharmony_ci#include "src/gpu/GrDrawingManager.h"
22cb93a386Sopenharmony_ci#include "src/gpu/GrGpu.h"
23cb93a386Sopenharmony_ci#include "src/gpu/GrProxyProvider.h"
24cb93a386Sopenharmony_ci#include "src/gpu/GrRecordingContextPriv.h"
25cb93a386Sopenharmony_ci#include "src/gpu/GrSemaphore.h"
26cb93a386Sopenharmony_ci#include "src/gpu/GrSurfaceProxyPriv.h"
27cb93a386Sopenharmony_ci#include "src/gpu/GrTexture.h"
28cb93a386Sopenharmony_ci#include "src/gpu/GrTextureProxy.h"
29cb93a386Sopenharmony_ci#include "src/gpu/v1/SurfaceDrawContext_v1.h"
30cb93a386Sopenharmony_ci#include "src/image/SkImage_Base.h"
31cb93a386Sopenharmony_ci#include "src/image/SkSurface_Gpu.h"
32cb93a386Sopenharmony_ci#include "tests/Test.h"
33cb93a386Sopenharmony_ci#include "tests/TestUtils.h"
34cb93a386Sopenharmony_ci#include "tools/gpu/BackendSurfaceFactory.h"
35cb93a386Sopenharmony_ci#include "tools/gpu/BackendTextureImageFactory.h"
36cb93a386Sopenharmony_ci#include "tools/gpu/ManagedBackendTexture.h"
37cb93a386Sopenharmony_ci#include "tools/gpu/ProxyUtils.h"
38cb93a386Sopenharmony_ci
39cb93a386Sopenharmony_cistatic constexpr int kSize = 8;
40cb93a386Sopenharmony_ci
41cb93a386Sopenharmony_ci// Test that the correct mip map states are on the GrTextures when wrapping GrBackendTextures in
42cb93a386Sopenharmony_ci// SkImages and SkSurfaces
43cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrWrappedMipMappedTest, reporter, ctxInfo) {
44cb93a386Sopenharmony_ci    auto dContext = ctxInfo.directContext();
45cb93a386Sopenharmony_ci    if (!dContext->priv().caps()->mipmapSupport()) {
46cb93a386Sopenharmony_ci        return;
47cb93a386Sopenharmony_ci    }
48cb93a386Sopenharmony_ci
49cb93a386Sopenharmony_ci    for (auto mipmapped : {GrMipmapped::kNo, GrMipmapped::kYes}) {
50cb93a386Sopenharmony_ci        for (auto renderable : {GrRenderable::kNo, GrRenderable::kYes}) {
51cb93a386Sopenharmony_ci            // createBackendTexture currently doesn't support uploading data to mip maps
52cb93a386Sopenharmony_ci            // so we don't send any. However, we pretend there is data for the checks below which is
53cb93a386Sopenharmony_ci            // fine since we are never actually using these textures for any work on the gpu.
54cb93a386Sopenharmony_ci            auto mbet = sk_gpu_test::ManagedBackendTexture::MakeWithData(dContext,
55cb93a386Sopenharmony_ci                                                                         kSize,
56cb93a386Sopenharmony_ci                                                                         kSize,
57cb93a386Sopenharmony_ci                                                                         kRGBA_8888_SkColorType,
58cb93a386Sopenharmony_ci                                                                         SkColors::kTransparent,
59cb93a386Sopenharmony_ci                                                                         mipmapped,
60cb93a386Sopenharmony_ci                                                                         renderable,
61cb93a386Sopenharmony_ci                                                                         GrProtected::kNo);
62cb93a386Sopenharmony_ci            if (!mbet) {
63cb93a386Sopenharmony_ci                ERRORF(reporter, "Could not make texture.");
64cb93a386Sopenharmony_ci                return;
65cb93a386Sopenharmony_ci            }
66cb93a386Sopenharmony_ci
67cb93a386Sopenharmony_ci            sk_sp<GrTextureProxy> proxy;
68cb93a386Sopenharmony_ci            sk_sp<SkImage> image;
69cb93a386Sopenharmony_ci            if (renderable == GrRenderable::kYes) {
70cb93a386Sopenharmony_ci                sk_sp<SkSurface> surface = SkSurface::MakeFromBackendTexture(
71cb93a386Sopenharmony_ci                        dContext,
72cb93a386Sopenharmony_ci                        mbet->texture(),
73cb93a386Sopenharmony_ci                        kTopLeft_GrSurfaceOrigin,
74cb93a386Sopenharmony_ci                        0,
75cb93a386Sopenharmony_ci                        kRGBA_8888_SkColorType,
76cb93a386Sopenharmony_ci                        /*color space*/ nullptr,
77cb93a386Sopenharmony_ci                        /*surface props*/ nullptr,
78cb93a386Sopenharmony_ci                        sk_gpu_test::ManagedBackendTexture::ReleaseProc,
79cb93a386Sopenharmony_ci                        mbet->releaseContext());
80cb93a386Sopenharmony_ci
81cb93a386Sopenharmony_ci                auto device = ((SkSurface_Gpu*)surface.get())->getDevice();
82cb93a386Sopenharmony_ci                proxy = device->readSurfaceView().asTextureProxyRef();
83cb93a386Sopenharmony_ci            } else {
84cb93a386Sopenharmony_ci                image = SkImage::MakeFromTexture(dContext,
85cb93a386Sopenharmony_ci                                                 mbet->texture(),
86cb93a386Sopenharmony_ci                                                 kTopLeft_GrSurfaceOrigin,
87cb93a386Sopenharmony_ci                                                 kRGBA_8888_SkColorType,
88cb93a386Sopenharmony_ci                                                 kPremul_SkAlphaType,
89cb93a386Sopenharmony_ci                                                 /* color space */ nullptr,
90cb93a386Sopenharmony_ci                                                 sk_gpu_test::ManagedBackendTexture::ReleaseProc,
91cb93a386Sopenharmony_ci                                                 mbet->releaseContext());
92cb93a386Sopenharmony_ci                REPORTER_ASSERT(reporter, (mipmapped == GrMipmapped::kYes) == image->hasMipmaps());
93cb93a386Sopenharmony_ci                proxy = sk_ref_sp(sk_gpu_test::GetTextureImageProxy(image.get(), dContext));
94cb93a386Sopenharmony_ci            }
95cb93a386Sopenharmony_ci            REPORTER_ASSERT(reporter, proxy);
96cb93a386Sopenharmony_ci            if (!proxy) {
97cb93a386Sopenharmony_ci                continue;
98cb93a386Sopenharmony_ci            }
99cb93a386Sopenharmony_ci
100cb93a386Sopenharmony_ci            REPORTER_ASSERT(reporter, proxy->isInstantiated());
101cb93a386Sopenharmony_ci
102cb93a386Sopenharmony_ci            GrTexture* texture = proxy->peekTexture();
103cb93a386Sopenharmony_ci            REPORTER_ASSERT(reporter, texture);
104cb93a386Sopenharmony_ci            if (!texture) {
105cb93a386Sopenharmony_ci                continue;
106cb93a386Sopenharmony_ci            }
107cb93a386Sopenharmony_ci
108cb93a386Sopenharmony_ci            if (mipmapped == GrMipmapped::kYes) {
109cb93a386Sopenharmony_ci                REPORTER_ASSERT(reporter, GrMipmapped::kYes == texture->mipmapped());
110cb93a386Sopenharmony_ci                if (GrRenderable::kYes == renderable) {
111cb93a386Sopenharmony_ci                    REPORTER_ASSERT(reporter, texture->mipmapsAreDirty());
112cb93a386Sopenharmony_ci                } else {
113cb93a386Sopenharmony_ci                    REPORTER_ASSERT(reporter, !texture->mipmapsAreDirty());
114cb93a386Sopenharmony_ci                }
115cb93a386Sopenharmony_ci            } else {
116cb93a386Sopenharmony_ci                REPORTER_ASSERT(reporter, GrMipmapped::kNo == texture->mipmapped());
117cb93a386Sopenharmony_ci            }
118cb93a386Sopenharmony_ci        }
119cb93a386Sopenharmony_ci    }
120cb93a386Sopenharmony_ci}
121cb93a386Sopenharmony_ci
122cb93a386Sopenharmony_ci// Test that we correctly copy or don't copy GrBackendTextures in the GrBackendTextureImageGenerator
123cb93a386Sopenharmony_ci// based on if we will use mips in the draw and the mip status of the GrBackendTexture.
124cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrBackendTextureImageMipMappedTest, reporter, ctxInfo) {
125cb93a386Sopenharmony_ci    auto dContext = ctxInfo.directContext();
126cb93a386Sopenharmony_ci    if (!dContext->priv().caps()->mipmapSupport()) {
127cb93a386Sopenharmony_ci        return;
128cb93a386Sopenharmony_ci    }
129cb93a386Sopenharmony_ci
130cb93a386Sopenharmony_ci    for (auto betMipmapped : {GrMipmapped::kNo, GrMipmapped::kYes}) {
131cb93a386Sopenharmony_ci        for (auto requestMipmapped : {GrMipmapped::kNo, GrMipmapped::kYes}) {
132cb93a386Sopenharmony_ci            auto ii =
133cb93a386Sopenharmony_ci                    SkImageInfo::Make({kSize, kSize}, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
134cb93a386Sopenharmony_ci            sk_sp<SkImage> image = sk_gpu_test::MakeBackendTextureImage(
135cb93a386Sopenharmony_ci                    dContext, ii, SkColors::kTransparent, betMipmapped);
136cb93a386Sopenharmony_ci            REPORTER_ASSERT(reporter, (betMipmapped == GrMipmapped::kYes) == image->hasMipmaps());
137cb93a386Sopenharmony_ci
138cb93a386Sopenharmony_ci            GrTextureProxy* proxy = sk_gpu_test::GetTextureImageProxy(image.get(), dContext);
139cb93a386Sopenharmony_ci            REPORTER_ASSERT(reporter, proxy);
140cb93a386Sopenharmony_ci            if (!proxy) {
141cb93a386Sopenharmony_ci                return;
142cb93a386Sopenharmony_ci            }
143cb93a386Sopenharmony_ci
144cb93a386Sopenharmony_ci            REPORTER_ASSERT(reporter, proxy->isInstantiated());
145cb93a386Sopenharmony_ci
146cb93a386Sopenharmony_ci            sk_sp<GrTexture> texture = sk_ref_sp(proxy->peekTexture());
147cb93a386Sopenharmony_ci            REPORTER_ASSERT(reporter, texture);
148cb93a386Sopenharmony_ci            if (!texture) {
149cb93a386Sopenharmony_ci                return;
150cb93a386Sopenharmony_ci            }
151cb93a386Sopenharmony_ci
152cb93a386Sopenharmony_ci            std::unique_ptr<SkImageGenerator> imageGen = GrBackendTextureImageGenerator::Make(
153cb93a386Sopenharmony_ci                    texture, kTopLeft_GrSurfaceOrigin, nullptr, kRGBA_8888_SkColorType,
154cb93a386Sopenharmony_ci                    kPremul_SkAlphaType, nullptr);
155cb93a386Sopenharmony_ci            REPORTER_ASSERT(reporter, imageGen);
156cb93a386Sopenharmony_ci            if (!imageGen) {
157cb93a386Sopenharmony_ci                return;
158cb93a386Sopenharmony_ci            }
159cb93a386Sopenharmony_ci
160cb93a386Sopenharmony_ci            SkIPoint origin = SkIPoint::Make(0,0);
161cb93a386Sopenharmony_ci            SkImageInfo imageInfo = SkImageInfo::Make(kSize, kSize, kRGBA_8888_SkColorType,
162cb93a386Sopenharmony_ci                                                      kPremul_SkAlphaType);
163cb93a386Sopenharmony_ci            GrSurfaceProxyView genView = imageGen->generateTexture(
164cb93a386Sopenharmony_ci                    dContext, imageInfo, origin, requestMipmapped, GrImageTexGenPolicy::kDraw);
165cb93a386Sopenharmony_ci            GrSurfaceProxy* genProxy = genView.proxy();
166cb93a386Sopenharmony_ci
167cb93a386Sopenharmony_ci            REPORTER_ASSERT(reporter, genProxy);
168cb93a386Sopenharmony_ci            if (!genProxy) {
169cb93a386Sopenharmony_ci                return;
170cb93a386Sopenharmony_ci            }
171cb93a386Sopenharmony_ci
172cb93a386Sopenharmony_ci            if (genProxy->isLazy()) {
173cb93a386Sopenharmony_ci                genProxy->priv().doLazyInstantiation(dContext->priv().resourceProvider());
174cb93a386Sopenharmony_ci            } else if (!genProxy->isInstantiated()) {
175cb93a386Sopenharmony_ci                genProxy->instantiate(dContext->priv().resourceProvider());
176cb93a386Sopenharmony_ci            }
177cb93a386Sopenharmony_ci
178cb93a386Sopenharmony_ci            REPORTER_ASSERT(reporter, genProxy->isInstantiated());
179cb93a386Sopenharmony_ci            if (!genProxy->isInstantiated()) {
180cb93a386Sopenharmony_ci                return;
181cb93a386Sopenharmony_ci            }
182cb93a386Sopenharmony_ci
183cb93a386Sopenharmony_ci            GrTexture* genTexture = genProxy->peekTexture();
184cb93a386Sopenharmony_ci            REPORTER_ASSERT(reporter, genTexture);
185cb93a386Sopenharmony_ci            if (!genTexture) {
186cb93a386Sopenharmony_ci                return;
187cb93a386Sopenharmony_ci            }
188cb93a386Sopenharmony_ci
189cb93a386Sopenharmony_ci            GrBackendTexture backendTex = texture->getBackendTexture();
190cb93a386Sopenharmony_ci            GrBackendTexture genBackendTex = genTexture->getBackendTexture();
191cb93a386Sopenharmony_ci
192cb93a386Sopenharmony_ci            if (GrBackendApi::kOpenGL == genBackendTex.backend()) {
193cb93a386Sopenharmony_ci#ifdef SK_GL
194cb93a386Sopenharmony_ci                GrGLTextureInfo genTexInfo;
195cb93a386Sopenharmony_ci                GrGLTextureInfo origTexInfo;
196cb93a386Sopenharmony_ci                if (genBackendTex.getGLTextureInfo(&genTexInfo) &&
197cb93a386Sopenharmony_ci                    backendTex.getGLTextureInfo(&origTexInfo)) {
198cb93a386Sopenharmony_ci                    if (requestMipmapped == GrMipmapped::kYes && betMipmapped == GrMipmapped::kNo) {
199cb93a386Sopenharmony_ci                        // We did a copy so the texture IDs should be different
200cb93a386Sopenharmony_ci                        REPORTER_ASSERT(reporter, origTexInfo.fID != genTexInfo.fID);
201cb93a386Sopenharmony_ci                    } else {
202cb93a386Sopenharmony_ci                        REPORTER_ASSERT(reporter, origTexInfo.fID == genTexInfo.fID);
203cb93a386Sopenharmony_ci                    }
204cb93a386Sopenharmony_ci                } else {
205cb93a386Sopenharmony_ci                    ERRORF(reporter, "Failed to get GrGLTextureInfo");
206cb93a386Sopenharmony_ci                }
207cb93a386Sopenharmony_ci#endif
208cb93a386Sopenharmony_ci#ifdef SK_VULKAN
209cb93a386Sopenharmony_ci            } else if (GrBackendApi::kVulkan == genBackendTex.backend()) {
210cb93a386Sopenharmony_ci                GrVkImageInfo genImageInfo;
211cb93a386Sopenharmony_ci                GrVkImageInfo origImageInfo;
212cb93a386Sopenharmony_ci                if (genBackendTex.getVkImageInfo(&genImageInfo) &&
213cb93a386Sopenharmony_ci                    backendTex.getVkImageInfo(&origImageInfo)) {
214cb93a386Sopenharmony_ci                    if (requestMipmapped == GrMipmapped::kYes && betMipmapped == GrMipmapped::kNo) {
215cb93a386Sopenharmony_ci                        // We did a copy so the texture IDs should be different
216cb93a386Sopenharmony_ci                        REPORTER_ASSERT(reporter, origImageInfo.fImage != genImageInfo.fImage);
217cb93a386Sopenharmony_ci                    } else {
218cb93a386Sopenharmony_ci                        REPORTER_ASSERT(reporter, origImageInfo.fImage == genImageInfo.fImage);
219cb93a386Sopenharmony_ci                    }
220cb93a386Sopenharmony_ci                } else {
221cb93a386Sopenharmony_ci                    ERRORF(reporter, "Failed to get GrVkImageInfo");
222cb93a386Sopenharmony_ci                }
223cb93a386Sopenharmony_ci#endif
224cb93a386Sopenharmony_ci#ifdef SK_METAL
225cb93a386Sopenharmony_ci            } else if (GrBackendApi::kMetal == genBackendTex.backend()) {
226cb93a386Sopenharmony_ci                GrMtlTextureInfo genImageInfo;
227cb93a386Sopenharmony_ci                GrMtlTextureInfo origImageInfo;
228cb93a386Sopenharmony_ci                if (genBackendTex.getMtlTextureInfo(&genImageInfo) &&
229cb93a386Sopenharmony_ci                    backendTex.getMtlTextureInfo(&origImageInfo)) {
230cb93a386Sopenharmony_ci                    if (requestMipmapped == GrMipmapped::kYes && betMipmapped == GrMipmapped::kNo) {
231cb93a386Sopenharmony_ci                        // We did a copy so the texture IDs should be different
232cb93a386Sopenharmony_ci                        REPORTER_ASSERT(reporter, origImageInfo.fTexture != genImageInfo.fTexture);
233cb93a386Sopenharmony_ci                    } else {
234cb93a386Sopenharmony_ci                        REPORTER_ASSERT(reporter, origImageInfo.fTexture == genImageInfo.fTexture);
235cb93a386Sopenharmony_ci                    }
236cb93a386Sopenharmony_ci                } else {
237cb93a386Sopenharmony_ci                    ERRORF(reporter, "Failed to get GrMtlTextureInfo");
238cb93a386Sopenharmony_ci                }
239cb93a386Sopenharmony_ci#endif
240cb93a386Sopenharmony_ci#ifdef SK_DIRECT3D
241cb93a386Sopenharmony_ci            } else if (GrBackendApi::kDirect3D == genBackendTex.backend()) {
242cb93a386Sopenharmony_ci                GrD3DTextureResourceInfo genImageInfo;
243cb93a386Sopenharmony_ci                GrD3DTextureResourceInfo origImageInfo;
244cb93a386Sopenharmony_ci                if (genBackendTex.getD3DTextureResourceInfo(&genImageInfo) &&
245cb93a386Sopenharmony_ci                    backendTex.getD3DTextureResourceInfo(&origImageInfo)) {
246cb93a386Sopenharmony_ci                    if (requestMipmapped == GrMipmapped::kYes && betMipmapped == GrMipmapped::kNo) {
247cb93a386Sopenharmony_ci                        // We did a copy so the texture resources should be different
248cb93a386Sopenharmony_ci                        REPORTER_ASSERT(reporter,
249cb93a386Sopenharmony_ci                                        origImageInfo.fResource != genImageInfo.fResource);
250cb93a386Sopenharmony_ci                    } else {
251cb93a386Sopenharmony_ci                        REPORTER_ASSERT(reporter,
252cb93a386Sopenharmony_ci                                        origImageInfo.fResource == genImageInfo.fResource);
253cb93a386Sopenharmony_ci                    }
254cb93a386Sopenharmony_ci                } else {
255cb93a386Sopenharmony_ci                    ERRORF(reporter, "Failed to get GrMtlTextureInfo");
256cb93a386Sopenharmony_ci                }
257cb93a386Sopenharmony_ci#endif
258cb93a386Sopenharmony_ci#ifdef SK_DAWN
259cb93a386Sopenharmony_ci            } else if (GrBackendApi::kDawn == genBackendTex.backend()) {
260cb93a386Sopenharmony_ci                GrDawnTextureInfo genImageInfo;
261cb93a386Sopenharmony_ci                GrDawnTextureInfo origImageInfo;
262cb93a386Sopenharmony_ci                if (genBackendTex.getDawnTextureInfo(&genImageInfo) &&
263cb93a386Sopenharmony_ci                    backendTex.getDawnTextureInfo(&origImageInfo)) {
264cb93a386Sopenharmony_ci                    if (requestMipmapped == GrMipmapped::kYes && betMipmapped == GrMipmapped::kNo) {
265cb93a386Sopenharmony_ci                        // We did a copy so the texture IDs should be different
266cb93a386Sopenharmony_ci                        REPORTER_ASSERT(reporter,
267cb93a386Sopenharmony_ci                            origImageInfo.fTexture.Get() != genImageInfo.fTexture.Get());
268cb93a386Sopenharmony_ci                    } else {
269cb93a386Sopenharmony_ci                        REPORTER_ASSERT(reporter,
270cb93a386Sopenharmony_ci                            origImageInfo.fTexture.Get() == genImageInfo.fTexture.Get());
271cb93a386Sopenharmony_ci                    }
272cb93a386Sopenharmony_ci                } else {
273cb93a386Sopenharmony_ci                    ERRORF(reporter, "Failed to get GrDawnTextureInfo");
274cb93a386Sopenharmony_ci                }
275cb93a386Sopenharmony_ci#endif
276cb93a386Sopenharmony_ci            } else {
277cb93a386Sopenharmony_ci                REPORTER_ASSERT(reporter, false);
278cb93a386Sopenharmony_ci            }
279cb93a386Sopenharmony_ci        }
280cb93a386Sopenharmony_ci    }
281cb93a386Sopenharmony_ci}
282cb93a386Sopenharmony_ci
283cb93a386Sopenharmony_ci// Test that when we call makeImageSnapshot on an SkSurface we retains the same mip status as the
284cb93a386Sopenharmony_ci// resource we took the snapshot of.
285cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrImageSnapshotMipMappedTest, reporter, ctxInfo) {
286cb93a386Sopenharmony_ci    auto dContext = ctxInfo.directContext();
287cb93a386Sopenharmony_ci    if (!dContext->priv().caps()->mipmapSupport()) {
288cb93a386Sopenharmony_ci        return;
289cb93a386Sopenharmony_ci    }
290cb93a386Sopenharmony_ci
291cb93a386Sopenharmony_ci    auto resourceProvider = dContext->priv().resourceProvider();
292cb93a386Sopenharmony_ci
293cb93a386Sopenharmony_ci    for (auto willUseMips : {false, true}) {
294cb93a386Sopenharmony_ci        for (auto isWrapped : {false, true}) {
295cb93a386Sopenharmony_ci            GrMipmapped mipmapped = willUseMips ? GrMipmapped::kYes : GrMipmapped::kNo;
296cb93a386Sopenharmony_ci            sk_sp<SkSurface> surface;
297cb93a386Sopenharmony_ci            SkImageInfo info =
298cb93a386Sopenharmony_ci                    SkImageInfo::Make(kSize, kSize, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
299cb93a386Sopenharmony_ci            if (isWrapped) {
300cb93a386Sopenharmony_ci                surface = sk_gpu_test::MakeBackendTextureSurface(dContext,
301cb93a386Sopenharmony_ci                                                                 info,
302cb93a386Sopenharmony_ci                                                                 kTopLeft_GrSurfaceOrigin,
303cb93a386Sopenharmony_ci                                                                 /* sample count */ 1,
304cb93a386Sopenharmony_ci                                                                 mipmapped);
305cb93a386Sopenharmony_ci            } else {
306cb93a386Sopenharmony_ci                surface = SkSurface::MakeRenderTarget(dContext,
307cb93a386Sopenharmony_ci                                                      SkBudgeted::kYes,
308cb93a386Sopenharmony_ci                                                      info,
309cb93a386Sopenharmony_ci                                                      /* sample count */ 1,
310cb93a386Sopenharmony_ci                                                      kTopLeft_GrSurfaceOrigin,
311cb93a386Sopenharmony_ci                                                      nullptr,
312cb93a386Sopenharmony_ci                                                      willUseMips);
313cb93a386Sopenharmony_ci            }
314cb93a386Sopenharmony_ci            REPORTER_ASSERT(reporter, surface);
315cb93a386Sopenharmony_ci            auto device = ((SkSurface_Gpu*)surface.get())->getDevice();
316cb93a386Sopenharmony_ci            GrTextureProxy* texProxy = device->readSurfaceView().asTextureProxy();
317cb93a386Sopenharmony_ci            REPORTER_ASSERT(reporter, mipmapped == texProxy->mipmapped());
318cb93a386Sopenharmony_ci
319cb93a386Sopenharmony_ci            texProxy->instantiate(resourceProvider);
320cb93a386Sopenharmony_ci            GrTexture* texture = texProxy->peekTexture();
321cb93a386Sopenharmony_ci            REPORTER_ASSERT(reporter, mipmapped == texture->mipmapped());
322cb93a386Sopenharmony_ci
323cb93a386Sopenharmony_ci            sk_sp<SkImage> image = surface->makeImageSnapshot();
324cb93a386Sopenharmony_ci            REPORTER_ASSERT(reporter, willUseMips == image->hasMipmaps());
325cb93a386Sopenharmony_ci            REPORTER_ASSERT(reporter, image);
326cb93a386Sopenharmony_ci            texProxy = sk_gpu_test::GetTextureImageProxy(image.get(), dContext);
327cb93a386Sopenharmony_ci            REPORTER_ASSERT(reporter, mipmapped == texProxy->mipmapped());
328cb93a386Sopenharmony_ci
329cb93a386Sopenharmony_ci            texProxy->instantiate(resourceProvider);
330cb93a386Sopenharmony_ci            texture = texProxy->peekTexture();
331cb93a386Sopenharmony_ci            REPORTER_ASSERT(reporter, mipmapped == texture->mipmapped());
332cb93a386Sopenharmony_ci        }
333cb93a386Sopenharmony_ci    }
334cb93a386Sopenharmony_ci}
335cb93a386Sopenharmony_ci
336cb93a386Sopenharmony_ci// Test that we don't create a mip mapped texture if the size is 1x1 even if the filter mode is set
337cb93a386Sopenharmony_ci// to use mips. This test passes by not crashing or hitting asserts in code.
338cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_RENDERING_CONTEXTS(Gr1x1TextureMipMappedTest, reporter, ctxInfo) {
339cb93a386Sopenharmony_ci    auto dContext = ctxInfo.directContext();
340cb93a386Sopenharmony_ci    if (!dContext->priv().caps()->mipmapSupport()) {
341cb93a386Sopenharmony_ci        return;
342cb93a386Sopenharmony_ci    }
343cb93a386Sopenharmony_ci
344cb93a386Sopenharmony_ci    // Make surface to draw into
345cb93a386Sopenharmony_ci    SkImageInfo info = SkImageInfo::MakeN32(16, 16, kPremul_SkAlphaType);
346cb93a386Sopenharmony_ci    sk_sp<SkSurface> surface = SkSurface::MakeRenderTarget(dContext, SkBudgeted::kNo, info);
347cb93a386Sopenharmony_ci
348cb93a386Sopenharmony_ci    // Make 1x1 raster bitmap
349cb93a386Sopenharmony_ci    SkBitmap bmp;
350cb93a386Sopenharmony_ci    bmp.allocN32Pixels(1, 1);
351cb93a386Sopenharmony_ci    SkPMColor* pixel = reinterpret_cast<SkPMColor*>(bmp.getPixels());
352cb93a386Sopenharmony_ci    *pixel = 0;
353cb93a386Sopenharmony_ci
354cb93a386Sopenharmony_ci    sk_sp<SkImage> bmpImage = bmp.asImage();
355cb93a386Sopenharmony_ci
356cb93a386Sopenharmony_ci    // Make sure we scale so we don't optimize out the use of mips.
357cb93a386Sopenharmony_ci    surface->getCanvas()->scale(0.5f, 0.5f);
358cb93a386Sopenharmony_ci
359cb93a386Sopenharmony_ci    // This should upload the image to a non mipped GrTextureProxy.
360cb93a386Sopenharmony_ci    surface->getCanvas()->drawImage(bmpImage, 0, 0);
361cb93a386Sopenharmony_ci    surface->flushAndSubmit();
362cb93a386Sopenharmony_ci
363cb93a386Sopenharmony_ci    // Now set the filter quality to high so we use mip maps. We should find the non mipped texture
364cb93a386Sopenharmony_ci    // in the cache for the SkImage. Since the texture is 1x1 we should just use that texture
365cb93a386Sopenharmony_ci    // instead of trying to do a copy to a mipped texture.
366cb93a386Sopenharmony_ci    surface->getCanvas()->drawImage(bmpImage, 0, 0, SkSamplingOptions({1.0f/3, 1.0f/3}));
367cb93a386Sopenharmony_ci    surface->flushAndSubmit();
368cb93a386Sopenharmony_ci}
369cb93a386Sopenharmony_ci
370cb93a386Sopenharmony_ci// Create a new render target and draw 'mipmapView' into it using the provided 'filter'.
371cb93a386Sopenharmony_cistatic std::unique_ptr<skgpu::v1::SurfaceDrawContext> draw_mipmap_into_new_render_target(
372cb93a386Sopenharmony_ci        GrRecordingContext* rContext,
373cb93a386Sopenharmony_ci        GrColorType colorType,
374cb93a386Sopenharmony_ci        SkAlphaType alphaType,
375cb93a386Sopenharmony_ci        GrSurfaceProxyView mipmapView,
376cb93a386Sopenharmony_ci        GrSamplerState::MipmapMode mm) {
377cb93a386Sopenharmony_ci    auto proxyProvider = rContext->priv().proxyProvider();
378cb93a386Sopenharmony_ci    sk_sp<GrSurfaceProxy> renderTarget =
379cb93a386Sopenharmony_ci            proxyProvider->createProxy(mipmapView.proxy()->backendFormat(),
380cb93a386Sopenharmony_ci                                       {1, 1},
381cb93a386Sopenharmony_ci                                       GrRenderable::kYes,
382cb93a386Sopenharmony_ci                                       1,
383cb93a386Sopenharmony_ci                                       GrMipmapped::kNo,
384cb93a386Sopenharmony_ci                                       SkBackingFit::kApprox,
385cb93a386Sopenharmony_ci                                       SkBudgeted::kYes,
386cb93a386Sopenharmony_ci                                       GrProtected::kNo);
387cb93a386Sopenharmony_ci
388cb93a386Sopenharmony_ci    auto sdc = skgpu::v1::SurfaceDrawContext::Make(rContext,
389cb93a386Sopenharmony_ci                                                   colorType,
390cb93a386Sopenharmony_ci                                                   std::move(renderTarget),
391cb93a386Sopenharmony_ci                                                   nullptr,
392cb93a386Sopenharmony_ci                                                   kTopLeft_GrSurfaceOrigin,
393cb93a386Sopenharmony_ci                                                   SkSurfaceProps(),
394cb93a386Sopenharmony_ci                                                   false);
395cb93a386Sopenharmony_ci
396cb93a386Sopenharmony_ci    sdc->drawTexture(nullptr,
397cb93a386Sopenharmony_ci                     std::move(mipmapView),
398cb93a386Sopenharmony_ci                     alphaType,
399cb93a386Sopenharmony_ci                     GrSamplerState::Filter::kLinear,
400cb93a386Sopenharmony_ci                     mm,
401cb93a386Sopenharmony_ci                     SkBlendMode::kSrcOver,
402cb93a386Sopenharmony_ci                     {1, 1, 1, 1},
403cb93a386Sopenharmony_ci                     SkRect::MakeWH(4, 4),
404cb93a386Sopenharmony_ci                     SkRect::MakeWH(1, 1),
405cb93a386Sopenharmony_ci                     GrAA::kYes,
406cb93a386Sopenharmony_ci                     GrQuadAAFlags::kAll,
407cb93a386Sopenharmony_ci                     SkCanvas::kFast_SrcRectConstraint,
408cb93a386Sopenharmony_ci                     SkMatrix::I(),
409cb93a386Sopenharmony_ci                     nullptr);
410cb93a386Sopenharmony_ci    return sdc;
411cb93a386Sopenharmony_ci}
412cb93a386Sopenharmony_ci
413cb93a386Sopenharmony_ci// Test that two opsTasks using the same mipmaps both depend on the same GrTextureResolveRenderTask.
414cb93a386Sopenharmony_ciDEF_GPUTEST(GrManyDependentsMipMappedTest, reporter, /* options */) {
415cb93a386Sopenharmony_ci    using Enable = GrContextOptions::Enable;
416cb93a386Sopenharmony_ci    using MipmapMode = GrSamplerState::MipmapMode;
417cb93a386Sopenharmony_ci
418cb93a386Sopenharmony_ci    for (auto enableSortingAndReduction : {Enable::kYes, Enable::kNo}) {
419cb93a386Sopenharmony_ci        GrMockOptions mockOptions;
420cb93a386Sopenharmony_ci        mockOptions.fMipmapSupport = true;
421cb93a386Sopenharmony_ci        GrContextOptions ctxOptions;
422cb93a386Sopenharmony_ci        ctxOptions.fReduceOpsTaskSplitting = enableSortingAndReduction;
423cb93a386Sopenharmony_ci        sk_sp<GrDirectContext> dContext = GrDirectContext::MakeMock(&mockOptions, ctxOptions);
424cb93a386Sopenharmony_ci        GrDrawingManager* drawingManager = dContext->priv().drawingManager();
425cb93a386Sopenharmony_ci        if (!dContext) {
426cb93a386Sopenharmony_ci            ERRORF(reporter, "could not create mock dContext with fReduceOpsTaskSplitting %s.",
427cb93a386Sopenharmony_ci                   (Enable::kYes == enableSortingAndReduction) ? "enabled" : "disabled");
428cb93a386Sopenharmony_ci            continue;
429cb93a386Sopenharmony_ci        }
430cb93a386Sopenharmony_ci
431cb93a386Sopenharmony_ci        SkASSERT(dContext->priv().caps()->mipmapSupport());
432cb93a386Sopenharmony_ci
433cb93a386Sopenharmony_ci        GrBackendFormat format = dContext->defaultBackendFormat(
434cb93a386Sopenharmony_ci                kRGBA_8888_SkColorType, GrRenderable::kYes);
435cb93a386Sopenharmony_ci        GrColorType colorType = GrColorType::kRGBA_8888;
436cb93a386Sopenharmony_ci        SkAlphaType alphaType = kPremul_SkAlphaType;
437cb93a386Sopenharmony_ci
438cb93a386Sopenharmony_ci        GrProxyProvider* proxyProvider = dContext->priv().proxyProvider();
439cb93a386Sopenharmony_ci
440cb93a386Sopenharmony_ci        // Create a mipmapped render target.
441cb93a386Sopenharmony_ci
442cb93a386Sopenharmony_ci        sk_sp<GrTextureProxy> mipmapProxy = proxyProvider->createProxy(
443cb93a386Sopenharmony_ci                format, {4, 4}, GrRenderable::kYes, 1, GrMipmapped::kYes, SkBackingFit::kExact,
444cb93a386Sopenharmony_ci                SkBudgeted::kYes, GrProtected::kNo);
445cb93a386Sopenharmony_ci
446cb93a386Sopenharmony_ci        // Mark the mipmaps clean to ensure things still work properly when they won't be marked
447cb93a386Sopenharmony_ci        // dirty again until GrRenderTask::makeClosed().
448cb93a386Sopenharmony_ci        mipmapProxy->markMipmapsClean();
449cb93a386Sopenharmony_ci
450cb93a386Sopenharmony_ci        auto mipmapSDC = skgpu::v1::SurfaceDrawContext::Make(
451cb93a386Sopenharmony_ci            dContext.get(), colorType, mipmapProxy, nullptr, kTopLeft_GrSurfaceOrigin,
452cb93a386Sopenharmony_ci            SkSurfaceProps(), false);
453cb93a386Sopenharmony_ci
454cb93a386Sopenharmony_ci        mipmapSDC->clear(SkPMColor4f{.1f, .2f, .3f, .4f});
455cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, drawingManager->getLastRenderTask(mipmapProxy.get()));
456cb93a386Sopenharmony_ci        // mipmapProxy's last render task should now just be the opsTask containing the clear.
457cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter,
458cb93a386Sopenharmony_ci                mipmapSDC->testingOnly_PeekLastOpsTask() ==
459cb93a386Sopenharmony_ci                        drawingManager->getLastRenderTask(mipmapProxy.get()));
460cb93a386Sopenharmony_ci
461cb93a386Sopenharmony_ci        // Mipmaps don't get marked dirty until makeClosed().
462cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, !mipmapProxy->mipmapsAreDirty());
463cb93a386Sopenharmony_ci
464cb93a386Sopenharmony_ci        GrSwizzle swizzle = dContext->priv().caps()->getReadSwizzle(format, colorType);
465cb93a386Sopenharmony_ci        GrSurfaceProxyView mipmapView(mipmapProxy, kTopLeft_GrSurfaceOrigin, swizzle);
466cb93a386Sopenharmony_ci
467cb93a386Sopenharmony_ci        // Draw the dirty mipmap texture into a render target.
468cb93a386Sopenharmony_ci        auto sdc1 = draw_mipmap_into_new_render_target(dContext.get(), colorType, alphaType,
469cb93a386Sopenharmony_ci                                                       mipmapView, MipmapMode::kLinear);
470cb93a386Sopenharmony_ci        auto sdc1Task = sk_ref_sp(sdc1->testingOnly_PeekLastOpsTask());
471cb93a386Sopenharmony_ci
472cb93a386Sopenharmony_ci        // Mipmaps should have gotten marked dirty during makeClosed, then marked clean again as
473cb93a386Sopenharmony_ci        // soon as a GrTextureResolveRenderTask was inserted. The way we know they were resolved is
474cb93a386Sopenharmony_ci        // if mipmapProxy->getLastRenderTask() has switched from the opsTask that drew to it, to the
475cb93a386Sopenharmony_ci        // task that resolved its mips.
476cb93a386Sopenharmony_ci        GrRenderTask* initialMipmapRegenTask = drawingManager->getLastRenderTask(mipmapProxy.get());
477cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, initialMipmapRegenTask);
478cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter,
479cb93a386Sopenharmony_ci                initialMipmapRegenTask != mipmapSDC->testingOnly_PeekLastOpsTask());
480cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, !mipmapProxy->mipmapsAreDirty());
481cb93a386Sopenharmony_ci
482cb93a386Sopenharmony_ci        // Draw the now-clean mipmap texture into a second target.
483cb93a386Sopenharmony_ci        auto sdc2 = draw_mipmap_into_new_render_target(dContext.get(), colorType, alphaType,
484cb93a386Sopenharmony_ci                                                       mipmapView, MipmapMode::kLinear);
485cb93a386Sopenharmony_ci        auto sdc2Task = sk_ref_sp(sdc2->testingOnly_PeekLastOpsTask());
486cb93a386Sopenharmony_ci
487cb93a386Sopenharmony_ci        // Make sure the mipmap texture still has the same regen task.
488cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter,
489cb93a386Sopenharmony_ci                    drawingManager->getLastRenderTask(mipmapProxy.get()) == initialMipmapRegenTask);
490cb93a386Sopenharmony_ci        SkASSERT(!mipmapProxy->mipmapsAreDirty());
491cb93a386Sopenharmony_ci
492cb93a386Sopenharmony_ci        // Reset everything so we can go again, this time with the first draw not mipmapped.
493cb93a386Sopenharmony_ci        dContext->flushAndSubmit();
494cb93a386Sopenharmony_ci
495cb93a386Sopenharmony_ci        // Mip regen tasks don't get added as dependencies until makeClosed().
496cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, sdc1Task->dependsOn(initialMipmapRegenTask));
497cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, sdc2Task->dependsOn(initialMipmapRegenTask));
498cb93a386Sopenharmony_ci
499cb93a386Sopenharmony_ci        // Render something to dirty the mips.
500cb93a386Sopenharmony_ci        mipmapSDC->clear(SkPMColor4f{.1f, .2f, .3f, .4f});
501cb93a386Sopenharmony_ci        auto mipmapRTCTask = sk_ref_sp(mipmapSDC->testingOnly_PeekLastOpsTask());
502cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, mipmapRTCTask);
503cb93a386Sopenharmony_ci
504cb93a386Sopenharmony_ci        // mipmapProxy's last render task should now just be the opsTask containing the clear.
505cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter,
506cb93a386Sopenharmony_ci                    mipmapRTCTask.get() == drawingManager->getLastRenderTask(mipmapProxy.get()));
507cb93a386Sopenharmony_ci
508cb93a386Sopenharmony_ci        // Mipmaps don't get marked dirty until makeClosed().
509cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, !mipmapProxy->mipmapsAreDirty());
510cb93a386Sopenharmony_ci
511cb93a386Sopenharmony_ci        // Draw the dirty mipmap texture into a render target, but don't do mipmap filtering.
512cb93a386Sopenharmony_ci        sdc1 = draw_mipmap_into_new_render_target(dContext.get(), colorType, alphaType,
513cb93a386Sopenharmony_ci                                                  mipmapView, MipmapMode::kNone);
514cb93a386Sopenharmony_ci
515cb93a386Sopenharmony_ci        // Mipmaps should have gotten marked dirty during makeClosed() when adding the dependency.
516cb93a386Sopenharmony_ci        // Since the last draw did not use mips, they will not have been regenerated and should
517cb93a386Sopenharmony_ci        // therefore still be dirty.
518cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, mipmapProxy->mipmapsAreDirty());
519cb93a386Sopenharmony_ci
520cb93a386Sopenharmony_ci        // Since mips weren't regenerated, the last render task shouldn't have changed.
521cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter,
522cb93a386Sopenharmony_ci                    mipmapRTCTask.get() == drawingManager->getLastRenderTask(mipmapProxy.get()));
523cb93a386Sopenharmony_ci
524cb93a386Sopenharmony_ci        // Draw the stil-dirty mipmap texture into a second target with mipmap filtering.
525cb93a386Sopenharmony_ci        sdc2 = draw_mipmap_into_new_render_target(dContext.get(), colorType, alphaType,
526cb93a386Sopenharmony_ci                                                  std::move(mipmapView), MipmapMode::kLinear);
527cb93a386Sopenharmony_ci        sdc2Task = sk_ref_sp(sdc2->testingOnly_PeekLastOpsTask());
528cb93a386Sopenharmony_ci
529cb93a386Sopenharmony_ci        // Make sure the mipmap texture now has a new last render task that regenerates the mips,
530cb93a386Sopenharmony_ci        // and that the mipmaps are now clean.
531cb93a386Sopenharmony_ci        auto mipRegenTask2 = drawingManager->getLastRenderTask(mipmapProxy.get());
532cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, mipRegenTask2);
533cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, mipmapRTCTask.get() != mipRegenTask2);
534cb93a386Sopenharmony_ci        SkASSERT(!mipmapProxy->mipmapsAreDirty());
535cb93a386Sopenharmony_ci
536cb93a386Sopenharmony_ci        // Mip regen tasks don't get added as dependencies until makeClosed().
537cb93a386Sopenharmony_ci        dContext->flushAndSubmit();
538cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, sdc2Task->dependsOn(mipRegenTask2));
539cb93a386Sopenharmony_ci    }
540cb93a386Sopenharmony_ci}
541