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