• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2016 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 "include/core/SkCanvas.h"
9 #include "include/core/SkSurface.h"
10 #include "include/gpu/GrDirectContext.h"
11 #include "src/gpu/GrDirectContextPriv.h"
12 #include "src/gpu/GrTexture.h"
13 #include "src/image/SkImage_Base.h"
14 #include "src/image/SkImage_GpuBase.h"
15 #include "tests/Test.h"
16 #include "tools/gpu/ProxyUtils.h"
17 
18 // Tests that MIP maps are created and invalidated as expected when drawing to and from GrTextures.
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrTextureMipMapInvalidationTest,reporter,ctxInfo)19 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrTextureMipMapInvalidationTest, reporter, ctxInfo) {
20     auto context = ctxInfo.directContext();
21     if (!context->priv().caps()->mipmapSupport()) {
22         return;
23     }
24 
25     auto isMipped = [reporter](SkSurface* surf) {
26         sk_sp<SkImage> image = surf->makeImageSnapshot();
27         GrTextureProxy* proxy = sk_gpu_test::GetTextureImageProxy(image.get(),
28                                                                   surf->recordingContext());
29         bool proxyIsMipmapped = proxy->mipmapped() == GrMipmapped::kYes;
30         REPORTER_ASSERT(reporter, proxyIsMipmapped == image->hasMipmaps());
31         return image->hasMipmaps();
32     };
33 
34     auto mipsAreDirty = [](SkSurface* surf) {
35         sk_sp<SkImage> image = surf->makeImageSnapshot();
36         GrTextureProxy* proxy = sk_gpu_test::GetTextureImageProxy(image.get(),
37                                                                   surf->recordingContext());
38         return proxy->peekTexture()->mipmapsAreDirty();
39     };
40 
41     auto info = SkImageInfo::MakeN32Premul(256, 256);
42     for (auto allocateMips : {false, true}) {
43         auto surf1 = SkSurface::MakeRenderTarget(context, SkBudgeted::kYes, info, 0,
44                                                  kBottomLeft_GrSurfaceOrigin, nullptr,
45                                                  allocateMips);
46         auto surf2 = SkSurface::MakeRenderTarget(context, SkBudgeted::kYes, info);
47         // Draw something just in case we ever had a solid color optimization
48         surf1->getCanvas()->drawCircle(128, 128, 50, SkPaint());
49         surf1->flushAndSubmit();
50 
51         // No mipmaps initially
52         REPORTER_ASSERT(reporter, isMipped(surf1.get()) == allocateMips);
53 
54         // Painting with downscale and medium filter quality should result in mipmap creation
55         // Flush the context rather than the canvas as flushing the canvas triggers MIP level
56         // generation.
57         SkSamplingOptions sampling(SkFilterMode::kLinear, SkMipmapMode::kLinear);
58 
59         surf2->getCanvas()->scale(0.2f, 0.2f);
60         surf2->getCanvas()->drawImage(surf1->makeImageSnapshot(), 0, 0, sampling);
61         context->flushAndSubmit();
62         REPORTER_ASSERT(reporter, isMipped(surf1.get()) == allocateMips);
63         REPORTER_ASSERT(reporter, !allocateMips || !mipsAreDirty(surf1.get()));
64 
65         // Changing the contents of the surface should invalidate the mipmap, but not de-allocate
66         surf1->getCanvas()->drawCircle(128, 128, 100, SkPaint());
67         context->flushAndSubmit();
68         REPORTER_ASSERT(reporter, isMipped(surf1.get()) == allocateMips);
69         REPORTER_ASSERT(reporter, mipsAreDirty(surf1.get()));
70     }
71 }
72 
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ReimportImageTextureWithMipLevels,reporter,ctxInfo)73 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ReimportImageTextureWithMipLevels, reporter, ctxInfo) {
74     auto dContext = ctxInfo.directContext();
75     if (!dContext->priv().caps()->mipmapSupport()) {
76         return;
77     }
78     static constexpr auto kCreateWithMipMaps = true;
79     auto surf = SkSurface::MakeRenderTarget(
80             dContext, SkBudgeted::kYes,
81             SkImageInfo::Make(100, 100, kRGBA_8888_SkColorType, kPremul_SkAlphaType), 1,
82             kTopLeft_GrSurfaceOrigin, nullptr, kCreateWithMipMaps);
83     if (!surf) {
84         return;
85     }
86     surf->getCanvas()->drawColor(SK_ColorDKGRAY);
87     auto img = surf->makeImageSnapshot();
88     if (!img) {
89         return;
90     }
91     surf.reset();
92     GrBackendTexture btex;
93     SkImage::BackendTextureReleaseProc texRelease;
94     if (!SkImage::MakeBackendTextureFromSkImage(dContext, std::move(img), &btex, &texRelease)) {
95         // Not all backends support stealing textures yet.
96         // ERRORF(reporter, "Could not turn image into texture");
97         return;
98     }
99     REPORTER_ASSERT(reporter, btex.hasMipmaps());
100     // Reimport the texture as an image and perform a downsampling draw with medium quality which
101     // should use the upper MIP levels.
102     img = SkImage::MakeFromTexture(dContext, btex, kTopLeft_GrSurfaceOrigin, kRGBA_8888_SkColorType,
103                                    kPremul_SkAlphaType, nullptr);
104     const auto singlePixelInfo =
105             SkImageInfo::Make(1, 1, kRGBA_8888_SkColorType, kPremul_SkAlphaType, nullptr);
106     surf = SkSurface::MakeRenderTarget(dContext, SkBudgeted::kYes, singlePixelInfo, 1,
107                                        kTopLeft_GrSurfaceOrigin, nullptr);
108 
109     surf->getCanvas()->drawImageRect(img, SkRect::MakeWH(1, 1),
110                                      SkSamplingOptions(SkFilterMode::kLinear,
111                                                        SkMipmapMode::kLinear));
112     uint32_t pixel;
113     surf->readPixels(singlePixelInfo, &pixel, sizeof(uint32_t), 0, 0);
114     REPORTER_ASSERT(reporter, pixel == SkPreMultiplyColor(SK_ColorDKGRAY));
115     img.reset();
116     texRelease(btex);
117 }
118