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/SkBitmap.h"
9cb93a386Sopenharmony_ci#include "include/core/SkCanvas.h"
10cb93a386Sopenharmony_ci#include "include/core/SkColor.h"
11cb93a386Sopenharmony_ci#include "include/core/SkColorSpace.h"
12cb93a386Sopenharmony_ci#include "include/core/SkDeferredDisplayList.h"
13cb93a386Sopenharmony_ci#include "include/core/SkDeferredDisplayListRecorder.h"
14cb93a386Sopenharmony_ci#include "include/core/SkImage.h"
15cb93a386Sopenharmony_ci#include "include/core/SkImageInfo.h"
16cb93a386Sopenharmony_ci#include "include/core/SkPaint.h"
17cb93a386Sopenharmony_ci#include "include/core/SkPromiseImageTexture.h"
18cb93a386Sopenharmony_ci#include "include/core/SkRect.h"
19cb93a386Sopenharmony_ci#include "include/core/SkRefCnt.h"
20cb93a386Sopenharmony_ci#include "include/core/SkSurface.h"
21cb93a386Sopenharmony_ci#include "include/core/SkSurfaceCharacterization.h"
22cb93a386Sopenharmony_ci#include "include/core/SkSurfaceProps.h"
23cb93a386Sopenharmony_ci#include "include/core/SkTypes.h"
24cb93a386Sopenharmony_ci#include "include/gpu/GrBackendSurface.h"
25cb93a386Sopenharmony_ci#include "include/gpu/GrContextThreadSafeProxy.h"
26cb93a386Sopenharmony_ci#include "include/gpu/GrDirectContext.h"
27cb93a386Sopenharmony_ci#include "include/gpu/GrRecordingContext.h"
28cb93a386Sopenharmony_ci#include "include/gpu/GrTypes.h"
29cb93a386Sopenharmony_ci#include "include/gpu/gl/GrGLTypes.h"
30cb93a386Sopenharmony_ci#include "include/private/GrTypesPriv.h"
31cb93a386Sopenharmony_ci#include "src/core/SkDeferredDisplayListPriv.h"
32cb93a386Sopenharmony_ci#include "src/gpu/GrCaps.h"
33cb93a386Sopenharmony_ci#include "src/gpu/GrDirectContextPriv.h"
34cb93a386Sopenharmony_ci#include "src/gpu/GrGpu.h"
35cb93a386Sopenharmony_ci#include "src/gpu/GrRecordingContextPriv.h"
36cb93a386Sopenharmony_ci#include "src/gpu/GrRenderTargetProxy.h"
37cb93a386Sopenharmony_ci#include "src/gpu/GrTextureProxy.h"
38cb93a386Sopenharmony_ci#include "src/gpu/gl/GrGLDefines.h"
39cb93a386Sopenharmony_ci#include "src/image/SkImage_GpuBase.h"
40cb93a386Sopenharmony_ci#include "src/image/SkSurface_Gpu.h"
41cb93a386Sopenharmony_ci#include "tests/Test.h"
42cb93a386Sopenharmony_ci#include "tests/TestUtils.h"
43cb93a386Sopenharmony_ci#include "tools/gpu/BackendSurfaceFactory.h"
44cb93a386Sopenharmony_ci#include "tools/gpu/GrContextFactory.h"
45cb93a386Sopenharmony_ci#include "tools/gpu/ManagedBackendTexture.h"
46cb93a386Sopenharmony_ci#include "tools/gpu/ProxyUtils.h"
47cb93a386Sopenharmony_ci
48cb93a386Sopenharmony_ci#include <initializer_list>
49cb93a386Sopenharmony_ci#include <memory>
50cb93a386Sopenharmony_ci#include <utility>
51cb93a386Sopenharmony_ci
52cb93a386Sopenharmony_ci#ifdef SK_VULKAN
53cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkCaps.h"
54cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkSecondaryCBDrawContext.h"
55cb93a386Sopenharmony_ci#endif
56cb93a386Sopenharmony_ci
57cb93a386Sopenharmony_ciclass SurfaceParameters {
58cb93a386Sopenharmony_cipublic:
59cb93a386Sopenharmony_ci    static const int kNumParams      = 13;
60cb93a386Sopenharmony_ci    static const int kFBO0Count      = 9;
61cb93a386Sopenharmony_ci    static const int kVkSCBCount     = 12;
62cb93a386Sopenharmony_ci
63cb93a386Sopenharmony_ci    SurfaceParameters(GrRecordingContext* rContext)
64cb93a386Sopenharmony_ci            : fBackend(rContext->backend())
65cb93a386Sopenharmony_ci            , fCanBeProtected(false)
66cb93a386Sopenharmony_ci            , fWidth(64)
67cb93a386Sopenharmony_ci            , fHeight(64)
68cb93a386Sopenharmony_ci            , fOrigin(kTopLeft_GrSurfaceOrigin)
69cb93a386Sopenharmony_ci            , fColorType(kRGBA_8888_SkColorType)
70cb93a386Sopenharmony_ci            , fColorSpace(SkColorSpace::MakeSRGB())
71cb93a386Sopenharmony_ci            , fSampleCount(1)
72cb93a386Sopenharmony_ci            , fSurfaceProps(0x0, kUnknown_SkPixelGeometry)
73cb93a386Sopenharmony_ci            , fShouldCreateMipMaps(true)
74cb93a386Sopenharmony_ci            , fUsesGLFBO0(false)
75cb93a386Sopenharmony_ci            , fIsTextureable(true)
76cb93a386Sopenharmony_ci            , fIsProtected(GrProtected::kNo)
77cb93a386Sopenharmony_ci            , fVkRTSupportsInputAttachment(false)
78cb93a386Sopenharmony_ci            , fForVulkanSecondaryCommandBuffer(false) {
79cb93a386Sopenharmony_ci#ifdef SK_VULKAN
80cb93a386Sopenharmony_ci        if (rContext->backend() == GrBackendApi::kVulkan) {
81cb93a386Sopenharmony_ci            auto vkCaps = static_cast<const GrVkCaps*>(rContext->priv().caps());
82cb93a386Sopenharmony_ci            fCanBeProtected = vkCaps->supportsProtectedMemory();
83cb93a386Sopenharmony_ci            if (fCanBeProtected) {
84cb93a386Sopenharmony_ci                fIsProtected = GrProtected::kYes;
85cb93a386Sopenharmony_ci            }
86cb93a386Sopenharmony_ci        }
87cb93a386Sopenharmony_ci#endif
88cb93a386Sopenharmony_ci        if (!rContext->priv().caps()->mipmapSupport()) {
89cb93a386Sopenharmony_ci            fShouldCreateMipMaps = false;
90cb93a386Sopenharmony_ci        }
91cb93a386Sopenharmony_ci    }
92cb93a386Sopenharmony_ci
93cb93a386Sopenharmony_ci    int sampleCount() const { return fSampleCount; }
94cb93a386Sopenharmony_ci
95cb93a386Sopenharmony_ci    void setColorType(SkColorType ct) { fColorType = ct; }
96cb93a386Sopenharmony_ci    SkColorType colorType() const { return fColorType; }
97cb93a386Sopenharmony_ci    void setColorSpace(sk_sp<SkColorSpace> cs) { fColorSpace = std::move(cs); }
98cb93a386Sopenharmony_ci    void disableTextureability() {
99cb93a386Sopenharmony_ci        fIsTextureable = false;
100cb93a386Sopenharmony_ci        fShouldCreateMipMaps = false;
101cb93a386Sopenharmony_ci    }
102cb93a386Sopenharmony_ci    void setShouldCreateMipMaps(bool shouldCreateMipMaps) {
103cb93a386Sopenharmony_ci        fShouldCreateMipMaps = shouldCreateMipMaps;
104cb93a386Sopenharmony_ci    }
105cb93a386Sopenharmony_ci    void setVkRTInputAttachmentSupport(bool inputSupport) {
106cb93a386Sopenharmony_ci        fVkRTSupportsInputAttachment = inputSupport;
107cb93a386Sopenharmony_ci    }
108cb93a386Sopenharmony_ci    void setForVulkanSecondaryCommandBuffer(bool forVkSCB) {
109cb93a386Sopenharmony_ci        fForVulkanSecondaryCommandBuffer = forVkSCB;
110cb93a386Sopenharmony_ci    }
111cb93a386Sopenharmony_ci
112cb93a386Sopenharmony_ci    // Modify the SurfaceParameters in just one way. Returns false if the requested modification had
113cb93a386Sopenharmony_ci    // no effect.
114cb93a386Sopenharmony_ci    bool modify(int i) {
115cb93a386Sopenharmony_ci        bool changed = false;
116cb93a386Sopenharmony_ci        auto set = [&changed](auto& var, auto value) {
117cb93a386Sopenharmony_ci            if (var != value) {
118cb93a386Sopenharmony_ci                changed = true;
119cb93a386Sopenharmony_ci            }
120cb93a386Sopenharmony_ci            var = value;
121cb93a386Sopenharmony_ci        };
122cb93a386Sopenharmony_ci        switch (i) {
123cb93a386Sopenharmony_ci        case 0:
124cb93a386Sopenharmony_ci            set(fWidth, 63);
125cb93a386Sopenharmony_ci            break;
126cb93a386Sopenharmony_ci        case 1:
127cb93a386Sopenharmony_ci            set(fHeight, 63);
128cb93a386Sopenharmony_ci            break;
129cb93a386Sopenharmony_ci        case 2:
130cb93a386Sopenharmony_ci            set(fOrigin, kBottomLeft_GrSurfaceOrigin);
131cb93a386Sopenharmony_ci            break;
132cb93a386Sopenharmony_ci        case 3:
133cb93a386Sopenharmony_ci            set(fColorType, kRGBA_F16_SkColorType);
134cb93a386Sopenharmony_ci            break;
135cb93a386Sopenharmony_ci        case 4:
136cb93a386Sopenharmony_ci            // This just needs to be a colorSpace different from that returned by MakeSRGB().
137cb93a386Sopenharmony_ci            // In this case we just change the gamut.
138cb93a386Sopenharmony_ci            set(fColorSpace, SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB,
139cb93a386Sopenharmony_ci                                                   SkNamedGamut::kAdobeRGB));
140cb93a386Sopenharmony_ci            break;
141cb93a386Sopenharmony_ci        case 5:
142cb93a386Sopenharmony_ci            set(fSampleCount, 4);
143cb93a386Sopenharmony_ci            break;
144cb93a386Sopenharmony_ci        case 6:
145cb93a386Sopenharmony_ci            set(fSurfaceProps, SkSurfaceProps(0x0, kRGB_H_SkPixelGeometry));
146cb93a386Sopenharmony_ci            break;
147cb93a386Sopenharmony_ci        case 7:
148cb93a386Sopenharmony_ci            set(fSurfaceProps, SkSurfaceProps(SkSurfaceProps::kUseDeviceIndependentFonts_Flag,
149cb93a386Sopenharmony_ci                                              kUnknown_SkPixelGeometry));
150cb93a386Sopenharmony_ci            break;
151cb93a386Sopenharmony_ci        case 8:
152cb93a386Sopenharmony_ci            set(fShouldCreateMipMaps, false);
153cb93a386Sopenharmony_ci            break;
154cb93a386Sopenharmony_ci        case 9:
155cb93a386Sopenharmony_ci            if (GrBackendApi::kOpenGL == fBackend) {
156cb93a386Sopenharmony_ci                set(fUsesGLFBO0, true);
157cb93a386Sopenharmony_ci                set(fShouldCreateMipMaps, false);  // needs to changed in tandem w/ textureability
158cb93a386Sopenharmony_ci                set(fIsTextureable, false);
159cb93a386Sopenharmony_ci            }
160cb93a386Sopenharmony_ci            break;
161cb93a386Sopenharmony_ci        case 10:
162cb93a386Sopenharmony_ci            set(fShouldCreateMipMaps, false);  // needs to changed in tandem w/ textureability
163cb93a386Sopenharmony_ci            set(fIsTextureable, false);
164cb93a386Sopenharmony_ci            break;
165cb93a386Sopenharmony_ci        case 11:
166cb93a386Sopenharmony_ci            if (fCanBeProtected) {
167cb93a386Sopenharmony_ci                set(fIsProtected, GrProtected(!static_cast<bool>(fIsProtected)));
168cb93a386Sopenharmony_ci            }
169cb93a386Sopenharmony_ci            break;
170cb93a386Sopenharmony_ci        case 12:
171cb93a386Sopenharmony_ci            if (GrBackendApi::kVulkan == fBackend) {
172cb93a386Sopenharmony_ci                set(fForVulkanSecondaryCommandBuffer, true);
173cb93a386Sopenharmony_ci                set(fUsesGLFBO0, false);
174cb93a386Sopenharmony_ci                set(fShouldCreateMipMaps, false);  // needs to changed in tandem w/ textureability
175cb93a386Sopenharmony_ci                set(fIsTextureable, false);
176cb93a386Sopenharmony_ci                set(fVkRTSupportsInputAttachment, false);
177cb93a386Sopenharmony_ci            }
178cb93a386Sopenharmony_ci            break;
179cb93a386Sopenharmony_ci        }
180cb93a386Sopenharmony_ci        return changed;
181cb93a386Sopenharmony_ci    }
182cb93a386Sopenharmony_ci
183cb93a386Sopenharmony_ci    SkSurfaceCharacterization createCharacterization(GrDirectContext* dContext) const {
184cb93a386Sopenharmony_ci        size_t maxResourceBytes = dContext->getResourceCacheLimit();
185cb93a386Sopenharmony_ci
186cb93a386Sopenharmony_ci        if (!dContext->colorTypeSupportedAsSurface(fColorType)) {
187cb93a386Sopenharmony_ci            return SkSurfaceCharacterization();
188cb93a386Sopenharmony_ci        }
189cb93a386Sopenharmony_ci
190cb93a386Sopenharmony_ci        // Note that Ganesh doesn't make use of the SkImageInfo's alphaType
191cb93a386Sopenharmony_ci        SkImageInfo ii = SkImageInfo::Make(fWidth, fHeight, fColorType,
192cb93a386Sopenharmony_ci                                           kPremul_SkAlphaType, fColorSpace);
193cb93a386Sopenharmony_ci
194cb93a386Sopenharmony_ci        GrBackendFormat backendFormat = dContext->defaultBackendFormat(fColorType,
195cb93a386Sopenharmony_ci                                                                       GrRenderable::kYes);
196cb93a386Sopenharmony_ci        if (!backendFormat.isValid()) {
197cb93a386Sopenharmony_ci            return SkSurfaceCharacterization();
198cb93a386Sopenharmony_ci        }
199cb93a386Sopenharmony_ci
200cb93a386Sopenharmony_ci        SkSurfaceCharacterization c = dContext->threadSafeProxy()->createCharacterization(
201cb93a386Sopenharmony_ci                                                maxResourceBytes, ii, backendFormat, fSampleCount,
202cb93a386Sopenharmony_ci                                                fOrigin, fSurfaceProps, fShouldCreateMipMaps,
203cb93a386Sopenharmony_ci                                                fUsesGLFBO0, fIsTextureable, fIsProtected,
204cb93a386Sopenharmony_ci                                                fVkRTSupportsInputAttachment,
205cb93a386Sopenharmony_ci                                                fForVulkanSecondaryCommandBuffer);
206cb93a386Sopenharmony_ci        return c;
207cb93a386Sopenharmony_ci    }
208cb93a386Sopenharmony_ci
209cb93a386Sopenharmony_ci    // Create a DDL whose characterization captures the current settings
210cb93a386Sopenharmony_ci    sk_sp<SkDeferredDisplayList> createDDL(GrDirectContext* dContext) const {
211cb93a386Sopenharmony_ci        SkSurfaceCharacterization c = this->createCharacterization(dContext);
212cb93a386Sopenharmony_ci        SkAssertResult(c.isValid());
213cb93a386Sopenharmony_ci
214cb93a386Sopenharmony_ci        SkDeferredDisplayListRecorder r(c);
215cb93a386Sopenharmony_ci        SkCanvas* canvas = r.getCanvas();
216cb93a386Sopenharmony_ci        if (!canvas) {
217cb93a386Sopenharmony_ci            return nullptr;
218cb93a386Sopenharmony_ci        }
219cb93a386Sopenharmony_ci
220cb93a386Sopenharmony_ci        canvas->drawRect(SkRect::MakeXYWH(10, 10, 10, 10), SkPaint());
221cb93a386Sopenharmony_ci        return r.detach();
222cb93a386Sopenharmony_ci    }
223cb93a386Sopenharmony_ci
224cb93a386Sopenharmony_ci    // Create the surface with the current set of parameters
225cb93a386Sopenharmony_ci    sk_sp<SkSurface> make(GrDirectContext* dContext) const {
226cb93a386Sopenharmony_ci        const SkSurfaceCharacterization c = this->createCharacterization(dContext);
227cb93a386Sopenharmony_ci
228cb93a386Sopenharmony_ci#ifdef SK_GL
229cb93a386Sopenharmony_ci        if (fUsesGLFBO0) {
230cb93a386Sopenharmony_ci            if (GrBackendApi::kOpenGL != dContext->backend()) {
231cb93a386Sopenharmony_ci                return nullptr;
232cb93a386Sopenharmony_ci            }
233cb93a386Sopenharmony_ci
234cb93a386Sopenharmony_ci            GrGLFramebufferInfo fboInfo;
235cb93a386Sopenharmony_ci            fboInfo.fFBOID = 0;
236cb93a386Sopenharmony_ci            fboInfo.fFormat = GR_GL_RGBA8;
237cb93a386Sopenharmony_ci            static constexpr int kStencilBits = 8;
238cb93a386Sopenharmony_ci            GrBackendRenderTarget backendRT(fWidth, fHeight, 1, kStencilBits, fboInfo);
239cb93a386Sopenharmony_ci
240cb93a386Sopenharmony_ci            if (!backendRT.isValid()) {
241cb93a386Sopenharmony_ci                return nullptr;
242cb93a386Sopenharmony_ci            }
243cb93a386Sopenharmony_ci
244cb93a386Sopenharmony_ci            sk_sp<SkSurface> result = SkSurface::MakeFromBackendRenderTarget(dContext, backendRT,
245cb93a386Sopenharmony_ci                                                                             fOrigin, fColorType,
246cb93a386Sopenharmony_ci                                                                             fColorSpace,
247cb93a386Sopenharmony_ci                                                                             &fSurfaceProps);
248cb93a386Sopenharmony_ci            SkASSERT(result->isCompatible(c));
249cb93a386Sopenharmony_ci            return result;
250cb93a386Sopenharmony_ci        }
251cb93a386Sopenharmony_ci#endif
252cb93a386Sopenharmony_ci
253cb93a386Sopenharmony_ci        // We can't make SkSurfaces for vulkan secondary command buffers.
254cb93a386Sopenharmony_ci        if (fForVulkanSecondaryCommandBuffer) {
255cb93a386Sopenharmony_ci            return nullptr;
256cb93a386Sopenharmony_ci        }
257cb93a386Sopenharmony_ci
258cb93a386Sopenharmony_ci        sk_sp<SkSurface> surface;
259cb93a386Sopenharmony_ci        if (fIsTextureable) {
260cb93a386Sopenharmony_ci            surface = sk_gpu_test::MakeBackendTextureSurface(dContext,
261cb93a386Sopenharmony_ci                                                             {fWidth, fHeight},
262cb93a386Sopenharmony_ci                                                             fOrigin,
263cb93a386Sopenharmony_ci                                                             fSampleCount,
264cb93a386Sopenharmony_ci                                                             fColorType,
265cb93a386Sopenharmony_ci                                                             fColorSpace,
266cb93a386Sopenharmony_ci                                                             GrMipmapped(fShouldCreateMipMaps),
267cb93a386Sopenharmony_ci                                                             fIsProtected,
268cb93a386Sopenharmony_ci                                                             &fSurfaceProps);
269cb93a386Sopenharmony_ci        } else {
270cb93a386Sopenharmony_ci            // Create a surface w/ the current parameters but make it non-textureable
271cb93a386Sopenharmony_ci            SkASSERT(!fShouldCreateMipMaps);
272cb93a386Sopenharmony_ci            surface = sk_gpu_test::MakeBackendRenderTargetSurface(dContext,
273cb93a386Sopenharmony_ci                                                                  {fWidth, fHeight},
274cb93a386Sopenharmony_ci                                                                  fOrigin,
275cb93a386Sopenharmony_ci                                                                  fSampleCount,
276cb93a386Sopenharmony_ci                                                                  fColorType,
277cb93a386Sopenharmony_ci                                                                  fColorSpace,
278cb93a386Sopenharmony_ci                                                                  fIsProtected,
279cb93a386Sopenharmony_ci                                                                  &fSurfaceProps);
280cb93a386Sopenharmony_ci        }
281cb93a386Sopenharmony_ci
282cb93a386Sopenharmony_ci        if (!surface) {
283cb93a386Sopenharmony_ci            SkASSERT(!c.isValid());
284cb93a386Sopenharmony_ci            return nullptr;
285cb93a386Sopenharmony_ci        }
286cb93a386Sopenharmony_ci
287cb93a386Sopenharmony_ci        GrBackendTexture texture =
288cb93a386Sopenharmony_ci                surface->getBackendTexture(SkSurface::kFlushRead_BackendHandleAccess);
289cb93a386Sopenharmony_ci        if (texture.isValid()) {
290cb93a386Sopenharmony_ci            SkASSERT(c.isCompatible(texture));
291cb93a386Sopenharmony_ci        }
292cb93a386Sopenharmony_ci        SkASSERT(c.isValid());
293cb93a386Sopenharmony_ci        SkASSERT(surface->isCompatible(c));
294cb93a386Sopenharmony_ci        return surface;
295cb93a386Sopenharmony_ci    }
296cb93a386Sopenharmony_ci
297cb93a386Sopenharmony_ci#ifdef SK_VULKAN
298cb93a386Sopenharmony_ci    sk_sp<GrVkSecondaryCBDrawContext> makeVkSCB(GrDirectContext* dContext) {
299cb93a386Sopenharmony_ci        const SkSurfaceCharacterization c = this->createCharacterization(dContext);
300cb93a386Sopenharmony_ci        SkImageInfo imageInfo = SkImageInfo::Make({fWidth, fHeight},
301cb93a386Sopenharmony_ci                                                  {fColorType, kPremul_SkAlphaType, fColorSpace});
302cb93a386Sopenharmony_ci        GrVkDrawableInfo vkInfo;
303cb93a386Sopenharmony_ci        // putting in a bunch of placeholder values here
304cb93a386Sopenharmony_ci        vkInfo.fSecondaryCommandBuffer = (VkCommandBuffer)1;
305cb93a386Sopenharmony_ci        vkInfo.fColorAttachmentIndex = 0;
306cb93a386Sopenharmony_ci        vkInfo.fCompatibleRenderPass = (VkRenderPass)1;
307cb93a386Sopenharmony_ci        vkInfo.fFormat = VK_FORMAT_R8G8B8A8_UNORM;
308cb93a386Sopenharmony_ci        vkInfo.fDrawBounds = nullptr;
309cb93a386Sopenharmony_ci        vkInfo.fImage = (VkImage)1;
310cb93a386Sopenharmony_ci
311cb93a386Sopenharmony_ci        return GrVkSecondaryCBDrawContext::Make(dContext, imageInfo, vkInfo, &fSurfaceProps);
312cb93a386Sopenharmony_ci    }
313cb93a386Sopenharmony_ci#endif
314cb93a386Sopenharmony_ci
315cb93a386Sopenharmony_ciprivate:
316cb93a386Sopenharmony_ci    GrBackendApi        fBackend;
317cb93a386Sopenharmony_ci    bool                fCanBeProtected;
318cb93a386Sopenharmony_ci
319cb93a386Sopenharmony_ci    int                 fWidth;
320cb93a386Sopenharmony_ci    int                 fHeight;
321cb93a386Sopenharmony_ci    GrSurfaceOrigin     fOrigin;
322cb93a386Sopenharmony_ci    SkColorType         fColorType;
323cb93a386Sopenharmony_ci    sk_sp<SkColorSpace> fColorSpace;
324cb93a386Sopenharmony_ci    int                 fSampleCount;
325cb93a386Sopenharmony_ci    SkSurfaceProps      fSurfaceProps;
326cb93a386Sopenharmony_ci    bool                fShouldCreateMipMaps;
327cb93a386Sopenharmony_ci    bool                fUsesGLFBO0;
328cb93a386Sopenharmony_ci    bool                fIsTextureable;
329cb93a386Sopenharmony_ci    GrProtected         fIsProtected;
330cb93a386Sopenharmony_ci    bool                fVkRTSupportsInputAttachment;
331cb93a386Sopenharmony_ci    bool                fForVulkanSecondaryCommandBuffer;
332cb93a386Sopenharmony_ci};
333cb93a386Sopenharmony_ci
334cb93a386Sopenharmony_ci// Test out operator== && operator!=
335cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLOperatorEqTest, reporter, ctxInfo) {
336cb93a386Sopenharmony_ci    auto context = ctxInfo.directContext();
337cb93a386Sopenharmony_ci
338cb93a386Sopenharmony_ci    for (int i = -1; i < SurfaceParameters::kNumParams; ++i) {
339cb93a386Sopenharmony_ci        SurfaceParameters params1(context);
340cb93a386Sopenharmony_ci        bool didModify1 = i >= 0 && params1.modify(i);
341cb93a386Sopenharmony_ci
342cb93a386Sopenharmony_ci        SkSurfaceCharacterization char1 = params1.createCharacterization(context);
343cb93a386Sopenharmony_ci        if (!char1.isValid()) {
344cb93a386Sopenharmony_ci            continue;  // can happen on some platforms (ChromeOS)
345cb93a386Sopenharmony_ci        }
346cb93a386Sopenharmony_ci
347cb93a386Sopenharmony_ci        for (int j = -1; j < SurfaceParameters::kNumParams; ++j) {
348cb93a386Sopenharmony_ci            SurfaceParameters params2(context);
349cb93a386Sopenharmony_ci            bool didModify2 = j >= 0 && params2.modify(j);
350cb93a386Sopenharmony_ci
351cb93a386Sopenharmony_ci            SkSurfaceCharacterization char2 = params2.createCharacterization(context);
352cb93a386Sopenharmony_ci            if (!char2.isValid()) {
353cb93a386Sopenharmony_ci                continue;  // can happen on some platforms (ChromeOS)
354cb93a386Sopenharmony_ci            }
355cb93a386Sopenharmony_ci
356cb93a386Sopenharmony_ci            if (i == j || (!didModify1 && !didModify2)) {
357cb93a386Sopenharmony_ci                REPORTER_ASSERT(reporter, char1 == char2);
358cb93a386Sopenharmony_ci            } else {
359cb93a386Sopenharmony_ci                REPORTER_ASSERT(reporter, char1 != char2);
360cb93a386Sopenharmony_ci            }
361cb93a386Sopenharmony_ci        }
362cb93a386Sopenharmony_ci    }
363cb93a386Sopenharmony_ci
364cb93a386Sopenharmony_ci    {
365cb93a386Sopenharmony_ci        SurfaceParameters params(context);
366cb93a386Sopenharmony_ci
367cb93a386Sopenharmony_ci        SkSurfaceCharacterization valid = params.createCharacterization(context);
368cb93a386Sopenharmony_ci        SkASSERT(valid.isValid());
369cb93a386Sopenharmony_ci
370cb93a386Sopenharmony_ci        SkSurfaceCharacterization inval1, inval2;
371cb93a386Sopenharmony_ci        SkASSERT(!inval1.isValid() && !inval2.isValid());
372cb93a386Sopenharmony_ci
373cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, inval1 != inval2);
374cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, valid != inval1);
375cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, inval1 != valid);
376cb93a386Sopenharmony_ci    }
377cb93a386Sopenharmony_ci}
378cb93a386Sopenharmony_ci
379cb93a386Sopenharmony_ci////////////////////////////////////////////////////////////////////////////////
380cb93a386Sopenharmony_ci// This tests SkSurfaceCharacterization/SkSurface compatibility
381cb93a386Sopenharmony_civoid DDLSurfaceCharacterizationTestImpl(GrDirectContext* dContext, skiatest::Reporter* reporter) {
382cb93a386Sopenharmony_ci    // Create a bitmap that we can readback into
383cb93a386Sopenharmony_ci    SkImageInfo imageInfo = SkImageInfo::Make(64, 64, kRGBA_8888_SkColorType,
384cb93a386Sopenharmony_ci                                              kPremul_SkAlphaType);
385cb93a386Sopenharmony_ci    SkBitmap bitmap;
386cb93a386Sopenharmony_ci    bitmap.allocPixels(imageInfo);
387cb93a386Sopenharmony_ci
388cb93a386Sopenharmony_ci    sk_sp<SkDeferredDisplayList> ddl;
389cb93a386Sopenharmony_ci
390cb93a386Sopenharmony_ci    // First, create a DDL using the stock SkSurface parameters
391cb93a386Sopenharmony_ci    {
392cb93a386Sopenharmony_ci        SurfaceParameters params(dContext);
393cb93a386Sopenharmony_ci        if (dContext->backend() == GrBackendApi::kVulkan) {
394cb93a386Sopenharmony_ci            params.setVkRTInputAttachmentSupport(true);
395cb93a386Sopenharmony_ci        }
396cb93a386Sopenharmony_ci        ddl = params.createDDL(dContext);
397cb93a386Sopenharmony_ci        SkAssertResult(ddl);
398cb93a386Sopenharmony_ci
399cb93a386Sopenharmony_ci        // The DDL should draw into an SkSurface created with the same parameters
400cb93a386Sopenharmony_ci        sk_sp<SkSurface> s = params.make(dContext);
401cb93a386Sopenharmony_ci        if (!s) {
402cb93a386Sopenharmony_ci            return;
403cb93a386Sopenharmony_ci        }
404cb93a386Sopenharmony_ci
405cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, s->draw(ddl));
406cb93a386Sopenharmony_ci        s->readPixels(imageInfo, bitmap.getPixels(), bitmap.rowBytes(), 0, 0);
407cb93a386Sopenharmony_ci
408cb93a386Sopenharmony_ci        dContext->flush();
409cb93a386Sopenharmony_ci    }
410cb93a386Sopenharmony_ci
411cb93a386Sopenharmony_ci    // Then, alter each parameter in turn and check that the DDL & surface are incompatible
412cb93a386Sopenharmony_ci    for (int i = 0; i < SurfaceParameters::kNumParams; ++i) {
413cb93a386Sopenharmony_ci        SurfaceParameters params(dContext);
414cb93a386Sopenharmony_ci        if (!params.modify(i)) {
415cb93a386Sopenharmony_ci            continue;
416cb93a386Sopenharmony_ci        }
417cb93a386Sopenharmony_ci
418cb93a386Sopenharmony_ci        sk_sp<SkSurface> s = params.make(dContext);
419cb93a386Sopenharmony_ci        if (!s) {
420cb93a386Sopenharmony_ci            continue;
421cb93a386Sopenharmony_ci        }
422cb93a386Sopenharmony_ci
423cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, !s->draw(ddl),
424cb93a386Sopenharmony_ci                        "DDLSurfaceCharacterizationTest failed on parameter: %d\n", i);
425cb93a386Sopenharmony_ci        dContext->flush();
426cb93a386Sopenharmony_ci    }
427cb93a386Sopenharmony_ci
428cb93a386Sopenharmony_ci    // Next test the compatibility of resource cache parameters
429cb93a386Sopenharmony_ci    {
430cb93a386Sopenharmony_ci        const SurfaceParameters params(dContext);
431cb93a386Sopenharmony_ci
432cb93a386Sopenharmony_ci        sk_sp<SkSurface> s = params.make(dContext);
433cb93a386Sopenharmony_ci
434cb93a386Sopenharmony_ci        size_t maxResourceBytes = dContext->getResourceCacheLimit();
435cb93a386Sopenharmony_ci
436cb93a386Sopenharmony_ci        dContext->setResourceCacheLimit(maxResourceBytes/2);
437cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, !s->draw(ddl));
438cb93a386Sopenharmony_ci
439cb93a386Sopenharmony_ci        // DDL TODO: once proxies/ops can be de-instantiated we can re-enable these tests.
440cb93a386Sopenharmony_ci        // For now, DDLs are drawn once.
441cb93a386Sopenharmony_ci#if 0
442cb93a386Sopenharmony_ci        // resource limits >= those at characterization time are accepted
443cb93a386Sopenharmony_ci        context->setResourceCacheLimits(2*maxResourceCount, maxResourceBytes);
444cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, s->draw(ddl));
445cb93a386Sopenharmony_ci        s->readPixels(imageInfo, bitmap.getPixels(), bitmap.rowBytes(), 0, 0);
446cb93a386Sopenharmony_ci
447cb93a386Sopenharmony_ci        context->setResourceCacheLimits(maxResourceCount, 2*maxResourceBytes);
448cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, s->draw(ddl));
449cb93a386Sopenharmony_ci        s->readPixels(imageInfo, bitmap.getPixels(), bitmap.rowBytes(), 0, 0);
450cb93a386Sopenharmony_ci
451cb93a386Sopenharmony_ci        context->setResourceCacheLimits(maxResourceCount, maxResourceBytes);
452cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, s->draw(ddl));
453cb93a386Sopenharmony_ci        s->readPixels(imageInfo, bitmap.getPixels(), bitmap.rowBytes(), 0, 0);
454cb93a386Sopenharmony_ci#endif
455cb93a386Sopenharmony_ci
456cb93a386Sopenharmony_ci        dContext->flush();
457cb93a386Sopenharmony_ci    }
458cb93a386Sopenharmony_ci
459cb93a386Sopenharmony_ci    // Test that the textureability of the DDL characterization can block a DDL draw
460cb93a386Sopenharmony_ci    {
461cb93a386Sopenharmony_ci        SurfaceParameters params(dContext);
462cb93a386Sopenharmony_ci        params.disableTextureability();
463cb93a386Sopenharmony_ci
464cb93a386Sopenharmony_ci        sk_sp<SkSurface> s = params.make(dContext);
465cb93a386Sopenharmony_ci        if (s) {
466cb93a386Sopenharmony_ci            REPORTER_ASSERT(reporter, !s->draw(ddl)); // bc the DDL was made w/ textureability
467cb93a386Sopenharmony_ci
468cb93a386Sopenharmony_ci            dContext->flush();
469cb93a386Sopenharmony_ci        }
470cb93a386Sopenharmony_ci    }
471cb93a386Sopenharmony_ci
472cb93a386Sopenharmony_ci    // Make sure non-GPU-backed surfaces fail characterization
473cb93a386Sopenharmony_ci    {
474cb93a386Sopenharmony_ci        SkImageInfo ii = SkImageInfo::MakeN32(64, 64, kOpaque_SkAlphaType);
475cb93a386Sopenharmony_ci
476cb93a386Sopenharmony_ci        sk_sp<SkSurface> rasterSurface = SkSurface::MakeRaster(ii);
477cb93a386Sopenharmony_ci        SkSurfaceCharacterization c;
478cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, !rasterSurface->characterize(&c));
479cb93a386Sopenharmony_ci    }
480cb93a386Sopenharmony_ci
481cb93a386Sopenharmony_ci    // Exercise the createResized method
482cb93a386Sopenharmony_ci    {
483cb93a386Sopenharmony_ci        SurfaceParameters params(dContext);
484cb93a386Sopenharmony_ci
485cb93a386Sopenharmony_ci        sk_sp<SkSurface> s = params.make(dContext);
486cb93a386Sopenharmony_ci        if (!s) {
487cb93a386Sopenharmony_ci            return;
488cb93a386Sopenharmony_ci        }
489cb93a386Sopenharmony_ci
490cb93a386Sopenharmony_ci        SkSurfaceCharacterization char0;
491cb93a386Sopenharmony_ci        SkAssertResult(s->characterize(&char0));
492cb93a386Sopenharmony_ci
493cb93a386Sopenharmony_ci        // Too small
494cb93a386Sopenharmony_ci        SkSurfaceCharacterization char1 = char0.createResized(-1, -1);
495cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, !char1.isValid());
496cb93a386Sopenharmony_ci
497cb93a386Sopenharmony_ci        // Too large
498cb93a386Sopenharmony_ci        SkSurfaceCharacterization char2 = char0.createResized(1000000, 32);
499cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, !char2.isValid());
500cb93a386Sopenharmony_ci
501cb93a386Sopenharmony_ci        // Just right
502cb93a386Sopenharmony_ci        SkSurfaceCharacterization char3 = char0.createResized(32, 32);
503cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, char3.isValid());
504cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, 32 == char3.width());
505cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, 32 == char3.height());
506cb93a386Sopenharmony_ci    }
507cb93a386Sopenharmony_ci
508cb93a386Sopenharmony_ci    // Exercise the createColorSpace method
509cb93a386Sopenharmony_ci    {
510cb93a386Sopenharmony_ci        SurfaceParameters params(dContext);
511cb93a386Sopenharmony_ci
512cb93a386Sopenharmony_ci        sk_sp<SkSurface> s = params.make(dContext);
513cb93a386Sopenharmony_ci        if (!s) {
514cb93a386Sopenharmony_ci            return;
515cb93a386Sopenharmony_ci        }
516cb93a386Sopenharmony_ci
517cb93a386Sopenharmony_ci        SkSurfaceCharacterization char0;
518cb93a386Sopenharmony_ci        SkAssertResult(s->characterize(&char0));
519cb93a386Sopenharmony_ci
520cb93a386Sopenharmony_ci        // The default params create an sRGB color space
521cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, char0.colorSpace()->isSRGB());
522cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, !char0.colorSpace()->gammaIsLinear());
523cb93a386Sopenharmony_ci
524cb93a386Sopenharmony_ci        {
525cb93a386Sopenharmony_ci            sk_sp<SkColorSpace> newCS = SkColorSpace::MakeSRGBLinear();
526cb93a386Sopenharmony_ci
527cb93a386Sopenharmony_ci            SkSurfaceCharacterization char1 = char0.createColorSpace(std::move(newCS));
528cb93a386Sopenharmony_ci            REPORTER_ASSERT(reporter, char1.isValid());
529cb93a386Sopenharmony_ci            REPORTER_ASSERT(reporter, !char1.colorSpace()->isSRGB());
530cb93a386Sopenharmony_ci            REPORTER_ASSERT(reporter, char1.colorSpace()->gammaIsLinear());
531cb93a386Sopenharmony_ci        }
532cb93a386Sopenharmony_ci
533cb93a386Sopenharmony_ci        {
534cb93a386Sopenharmony_ci            SkSurfaceCharacterization char2 = char0.createColorSpace(nullptr);
535cb93a386Sopenharmony_ci            REPORTER_ASSERT(reporter, char2.isValid());
536cb93a386Sopenharmony_ci            REPORTER_ASSERT(reporter, !char2.colorSpace());
537cb93a386Sopenharmony_ci        }
538cb93a386Sopenharmony_ci
539cb93a386Sopenharmony_ci        {
540cb93a386Sopenharmony_ci            sk_sp<SkColorSpace> newCS = SkColorSpace::MakeSRGBLinear();
541cb93a386Sopenharmony_ci
542cb93a386Sopenharmony_ci            SkSurfaceCharacterization invalid;
543cb93a386Sopenharmony_ci            REPORTER_ASSERT(reporter, !invalid.isValid());
544cb93a386Sopenharmony_ci            SkSurfaceCharacterization stillInvalid = invalid.createColorSpace(std::move(newCS));
545cb93a386Sopenharmony_ci            REPORTER_ASSERT(reporter, !stillInvalid.isValid());
546cb93a386Sopenharmony_ci        }
547cb93a386Sopenharmony_ci    }
548cb93a386Sopenharmony_ci
549cb93a386Sopenharmony_ci    // Exercise the createBackendFormat method
550cb93a386Sopenharmony_ci    {
551cb93a386Sopenharmony_ci        SurfaceParameters params(dContext);
552cb93a386Sopenharmony_ci
553cb93a386Sopenharmony_ci        sk_sp<SkSurface> s = params.make(dContext);
554cb93a386Sopenharmony_ci        if (!s) {
555cb93a386Sopenharmony_ci            return;
556cb93a386Sopenharmony_ci        }
557cb93a386Sopenharmony_ci
558cb93a386Sopenharmony_ci        SkSurfaceCharacterization char0;
559cb93a386Sopenharmony_ci        SkAssertResult(s->characterize(&char0));
560cb93a386Sopenharmony_ci
561cb93a386Sopenharmony_ci        // The default params create a renderable RGBA8 surface
562cb93a386Sopenharmony_ci        auto originalBackendFormat = dContext->defaultBackendFormat(kRGBA_8888_SkColorType,
563cb93a386Sopenharmony_ci                                                                    GrRenderable::kYes);
564cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, originalBackendFormat.isValid());
565cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, char0.backendFormat() == originalBackendFormat);
566cb93a386Sopenharmony_ci
567cb93a386Sopenharmony_ci        auto newBackendFormat = dContext->defaultBackendFormat(kRGB_565_SkColorType,
568cb93a386Sopenharmony_ci                                                               GrRenderable::kYes);
569cb93a386Sopenharmony_ci
570cb93a386Sopenharmony_ci        if (newBackendFormat.isValid()) {
571cb93a386Sopenharmony_ci            SkSurfaceCharacterization char1 = char0.createBackendFormat(kRGB_565_SkColorType,
572cb93a386Sopenharmony_ci                                                                        newBackendFormat);
573cb93a386Sopenharmony_ci            REPORTER_ASSERT(reporter, char1.isValid());
574cb93a386Sopenharmony_ci            REPORTER_ASSERT(reporter, char1.backendFormat() == newBackendFormat);
575cb93a386Sopenharmony_ci
576cb93a386Sopenharmony_ci            SkSurfaceCharacterization invalid;
577cb93a386Sopenharmony_ci            REPORTER_ASSERT(reporter, !invalid.isValid());
578cb93a386Sopenharmony_ci            auto stillInvalid = invalid.createBackendFormat(kRGB_565_SkColorType,
579cb93a386Sopenharmony_ci                                                            newBackendFormat);
580cb93a386Sopenharmony_ci            REPORTER_ASSERT(reporter, !stillInvalid.isValid());
581cb93a386Sopenharmony_ci        }
582cb93a386Sopenharmony_ci    }
583cb93a386Sopenharmony_ci
584cb93a386Sopenharmony_ci    // Exercise the createFBO0 method
585cb93a386Sopenharmony_ci    if (dContext->backend() == GrBackendApi::kOpenGL) {
586cb93a386Sopenharmony_ci        SurfaceParameters params(dContext);
587cb93a386Sopenharmony_ci        // If the original characterization is textureable then we will fail trying to make an
588cb93a386Sopenharmony_ci        // FBO0 characterization
589cb93a386Sopenharmony_ci        params.disableTextureability();
590cb93a386Sopenharmony_ci
591cb93a386Sopenharmony_ci        sk_sp<SkSurface> s = params.make(dContext);
592cb93a386Sopenharmony_ci        if (!s) {
593cb93a386Sopenharmony_ci            return;
594cb93a386Sopenharmony_ci        }
595cb93a386Sopenharmony_ci
596cb93a386Sopenharmony_ci        SkSurfaceCharacterization char0;
597cb93a386Sopenharmony_ci        SkAssertResult(s->characterize(&char0));
598cb93a386Sopenharmony_ci
599cb93a386Sopenharmony_ci        // The default params create a non-FBO0 surface
600cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, !char0.usesGLFBO0());
601cb93a386Sopenharmony_ci
602cb93a386Sopenharmony_ci        {
603cb93a386Sopenharmony_ci            SkSurfaceCharacterization char1 = char0.createFBO0(true);
604cb93a386Sopenharmony_ci            REPORTER_ASSERT(reporter, char1.isValid());
605cb93a386Sopenharmony_ci            REPORTER_ASSERT(reporter, char1.usesGLFBO0());
606cb93a386Sopenharmony_ci        }
607cb93a386Sopenharmony_ci
608cb93a386Sopenharmony_ci        {
609cb93a386Sopenharmony_ci            SkSurfaceCharacterization invalid;
610cb93a386Sopenharmony_ci            REPORTER_ASSERT(reporter, !invalid.isValid());
611cb93a386Sopenharmony_ci            SkSurfaceCharacterization stillInvalid = invalid.createFBO0(true);
612cb93a386Sopenharmony_ci            REPORTER_ASSERT(reporter, !stillInvalid.isValid());
613cb93a386Sopenharmony_ci        }
614cb93a386Sopenharmony_ci    }
615cb93a386Sopenharmony_ci}
616cb93a386Sopenharmony_ci
617cb93a386Sopenharmony_ci#ifdef SK_GL
618cb93a386Sopenharmony_ci
619cb93a386Sopenharmony_ci// Test out the surface compatibility checks regarding FBO0-ness. This test constructs
620cb93a386Sopenharmony_ci// two parallel arrays of characterizations and surfaces in the order:
621cb93a386Sopenharmony_ci//    FBO0 w/ MSAA, FBO0 w/o MSAA, not-FBO0 w/ MSAA, not-FBO0 w/o MSAA
622cb93a386Sopenharmony_ci// and then tries all sixteen combinations to check the expected compatibility.
623cb93a386Sopenharmony_ci// Note: this is a GL-only test
624cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(CharacterizationFBO0nessTest, reporter, ctxInfo) {
625cb93a386Sopenharmony_ci    auto context = ctxInfo.directContext();
626cb93a386Sopenharmony_ci    const GrCaps* caps = context->priv().caps();
627cb93a386Sopenharmony_ci    sk_sp<GrContextThreadSafeProxy> proxy = context->threadSafeProxy();
628cb93a386Sopenharmony_ci    const size_t resourceCacheLimit = context->getResourceCacheLimit();
629cb93a386Sopenharmony_ci
630cb93a386Sopenharmony_ci    GrBackendFormat format = GrBackendFormat::MakeGL(GR_GL_RGBA8, GR_GL_TEXTURE_2D);
631cb93a386Sopenharmony_ci
632cb93a386Sopenharmony_ci    int availableSamples = caps->getRenderTargetSampleCount(4, format);
633cb93a386Sopenharmony_ci    if (availableSamples <= 1) {
634cb93a386Sopenharmony_ci        // This context doesn't support MSAA for RGBA8
635cb93a386Sopenharmony_ci        return;
636cb93a386Sopenharmony_ci    }
637cb93a386Sopenharmony_ci
638cb93a386Sopenharmony_ci    SkImageInfo ii = SkImageInfo::Make({ 128, 128 }, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
639cb93a386Sopenharmony_ci
640cb93a386Sopenharmony_ci    static constexpr int kStencilBits = 8;
641cb93a386Sopenharmony_ci    static constexpr bool kNotMipMapped = false;
642cb93a386Sopenharmony_ci    static constexpr bool kNotTextureable = false;
643cb93a386Sopenharmony_ci    const SkSurfaceProps surfaceProps(0x0, kRGB_H_SkPixelGeometry);
644cb93a386Sopenharmony_ci
645cb93a386Sopenharmony_ci    // Rows are characterizations and columns are surfaces
646cb93a386Sopenharmony_ci    static const bool kExpectedCompatibility[4][4] = {
647cb93a386Sopenharmony_ci                    //  FBO0 & MSAA, FBO0 & not-MSAA, not-FBO0 & MSAA, not-FBO0 & not-MSAA
648cb93a386Sopenharmony_ci/* FBO0 & MSAA     */ { true,        false,           false,           false },
649cb93a386Sopenharmony_ci/* FBO0 & not-MSAA */ { false,       true,            false,           true  },
650cb93a386Sopenharmony_ci/* not-FBO0 & MSAA */ { false,       false,           true,            false },
651cb93a386Sopenharmony_ci/* not-FBO0 & not- */ { false,       false,           false,           true  }
652cb93a386Sopenharmony_ci    };
653cb93a386Sopenharmony_ci
654cb93a386Sopenharmony_ci    SkSurfaceCharacterization characterizations[4];
655cb93a386Sopenharmony_ci    sk_sp<SkSurface> surfaces[4];
656cb93a386Sopenharmony_ci
657cb93a386Sopenharmony_ci    int index = 0;
658cb93a386Sopenharmony_ci    for (bool isFBO0 : { true, false }) {
659cb93a386Sopenharmony_ci        for (int numSamples : { availableSamples, 1 }) {
660cb93a386Sopenharmony_ci            characterizations[index] = proxy->createCharacterization(resourceCacheLimit,
661cb93a386Sopenharmony_ci                                                                     ii, format, numSamples,
662cb93a386Sopenharmony_ci                                                                     kTopLeft_GrSurfaceOrigin,
663cb93a386Sopenharmony_ci                                                                     surfaceProps, kNotMipMapped,
664cb93a386Sopenharmony_ci                                                                     isFBO0, kNotTextureable);
665cb93a386Sopenharmony_ci            SkASSERT(characterizations[index].sampleCount() == numSamples);
666cb93a386Sopenharmony_ci            SkASSERT(characterizations[index].usesGLFBO0() == isFBO0);
667cb93a386Sopenharmony_ci
668cb93a386Sopenharmony_ci            GrGLFramebufferInfo fboInfo{ isFBO0 ? 0 : (GrGLuint) 1, GR_GL_RGBA8 };
669cb93a386Sopenharmony_ci            GrBackendRenderTarget backendRT(128, 128, numSamples, kStencilBits, fboInfo);
670cb93a386Sopenharmony_ci            SkAssertResult(backendRT.isValid());
671cb93a386Sopenharmony_ci
672cb93a386Sopenharmony_ci            surfaces[index] = SkSurface::MakeFromBackendRenderTarget(context, backendRT,
673cb93a386Sopenharmony_ci                                                                     kTopLeft_GrSurfaceOrigin,
674cb93a386Sopenharmony_ci                                                                     kRGBA_8888_SkColorType,
675cb93a386Sopenharmony_ci                                                                     nullptr, &surfaceProps);
676cb93a386Sopenharmony_ci            ++index;
677cb93a386Sopenharmony_ci        }
678cb93a386Sopenharmony_ci    }
679cb93a386Sopenharmony_ci
680cb93a386Sopenharmony_ci    for (int c = 0; c < 4; ++c) {
681cb93a386Sopenharmony_ci        for (int s = 0; s < 4; ++s) {
682cb93a386Sopenharmony_ci            REPORTER_ASSERT(reporter,
683cb93a386Sopenharmony_ci                            kExpectedCompatibility[c][s] ==
684cb93a386Sopenharmony_ci                                                 surfaces[s]->isCompatible(characterizations[c]));
685cb93a386Sopenharmony_ci        }
686cb93a386Sopenharmony_ci    }
687cb93a386Sopenharmony_ci}
688cb93a386Sopenharmony_ci#endif
689cb93a386Sopenharmony_ci
690cb93a386Sopenharmony_ci#ifdef SK_VULKAN
691cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_VULKAN_CONTEXT(CharacterizationVkSCBnessTest, reporter, ctxInfo) {
692cb93a386Sopenharmony_ci    auto dContext = ctxInfo.directContext();
693cb93a386Sopenharmony_ci
694cb93a386Sopenharmony_ci    SurfaceParameters params(dContext);
695cb93a386Sopenharmony_ci    params.modify(SurfaceParameters::kVkSCBCount);
696cb93a386Sopenharmony_ci    SkSurfaceCharacterization characterization = params.createCharacterization(dContext);
697cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, characterization.isValid());
698cb93a386Sopenharmony_ci
699cb93a386Sopenharmony_ci    sk_sp<SkDeferredDisplayList> ddl = params.createDDL(dContext);
700cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, ddl.get());
701cb93a386Sopenharmony_ci
702cb93a386Sopenharmony_ci    sk_sp<GrVkSecondaryCBDrawContext> scbDrawContext = params.makeVkSCB(dContext);
703cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, scbDrawContext->isCompatible(characterization));
704cb93a386Sopenharmony_ci
705cb93a386Sopenharmony_ci    scbDrawContext->releaseResources();
706cb93a386Sopenharmony_ci}
707cb93a386Sopenharmony_ci#endif
708cb93a386Sopenharmony_ci
709cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLSurfaceCharacterizationTest, reporter, ctxInfo) {
710cb93a386Sopenharmony_ci    auto context = ctxInfo.directContext();
711cb93a386Sopenharmony_ci
712cb93a386Sopenharmony_ci    DDLSurfaceCharacterizationTestImpl(context, reporter);
713cb93a386Sopenharmony_ci}
714cb93a386Sopenharmony_ci
715cb93a386Sopenharmony_ci// Test that a DDL created w/o textureability can be replayed into both a textureable and
716cb93a386Sopenharmony_ci// non-textureable destination. Note that DDLSurfaceCharacterizationTest tests that a
717cb93a386Sopenharmony_ci// textureable DDL cannot be played into a non-textureable destination but can be replayed
718cb93a386Sopenharmony_ci// into a textureable destination.
719cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLNonTextureabilityTest, reporter, ctxInfo) {
720cb93a386Sopenharmony_ci    auto context = ctxInfo.directContext();
721cb93a386Sopenharmony_ci
722cb93a386Sopenharmony_ci    // Create a bitmap that we can readback into
723cb93a386Sopenharmony_ci    SkImageInfo imageInfo = SkImageInfo::Make(64, 64, kRGBA_8888_SkColorType,
724cb93a386Sopenharmony_ci                                              kPremul_SkAlphaType);
725cb93a386Sopenharmony_ci    SkBitmap bitmap;
726cb93a386Sopenharmony_ci    bitmap.allocPixels(imageInfo);
727cb93a386Sopenharmony_ci
728cb93a386Sopenharmony_ci    for (bool textureability : { true, false }) {
729cb93a386Sopenharmony_ci        sk_sp<SkDeferredDisplayList> ddl;
730cb93a386Sopenharmony_ci
731cb93a386Sopenharmony_ci        // First, create a DDL w/o textureability (and thus no mipmaps). TODO: once we have
732cb93a386Sopenharmony_ci        // reusable DDLs, move this outside of the loop.
733cb93a386Sopenharmony_ci        {
734cb93a386Sopenharmony_ci            SurfaceParameters params(context);
735cb93a386Sopenharmony_ci            params.disableTextureability();
736cb93a386Sopenharmony_ci            if (context->backend() == GrBackendApi::kVulkan) {
737cb93a386Sopenharmony_ci                params.setVkRTInputAttachmentSupport(true);
738cb93a386Sopenharmony_ci            }
739cb93a386Sopenharmony_ci
740cb93a386Sopenharmony_ci            ddl = params.createDDL(context);
741cb93a386Sopenharmony_ci            SkAssertResult(ddl);
742cb93a386Sopenharmony_ci        }
743cb93a386Sopenharmony_ci
744cb93a386Sopenharmony_ci        // Then verify it can draw into either flavor of destination
745cb93a386Sopenharmony_ci        SurfaceParameters params(context);
746cb93a386Sopenharmony_ci        if (!textureability) {
747cb93a386Sopenharmony_ci            params.disableTextureability();
748cb93a386Sopenharmony_ci        }
749cb93a386Sopenharmony_ci        if (context->backend() == GrBackendApi::kVulkan) {
750cb93a386Sopenharmony_ci            params.setVkRTInputAttachmentSupport(true);
751cb93a386Sopenharmony_ci        }
752cb93a386Sopenharmony_ci
753cb93a386Sopenharmony_ci        sk_sp<SkSurface> s = params.make(context);
754cb93a386Sopenharmony_ci        if (!s) {
755cb93a386Sopenharmony_ci            continue;
756cb93a386Sopenharmony_ci        }
757cb93a386Sopenharmony_ci
758cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, s->draw(ddl));
759cb93a386Sopenharmony_ci        s->readPixels(imageInfo, bitmap.getPixels(), bitmap.rowBytes(), 0, 0);
760cb93a386Sopenharmony_ci
761cb93a386Sopenharmony_ci        context->flush();
762cb93a386Sopenharmony_ci    }
763cb93a386Sopenharmony_ci
764cb93a386Sopenharmony_ci}
765cb93a386Sopenharmony_ci
766cb93a386Sopenharmony_cistatic void test_make_render_target(skiatest::Reporter* reporter,
767cb93a386Sopenharmony_ci                                    GrDirectContext* dContext,
768cb93a386Sopenharmony_ci                                    const SurfaceParameters& params) {
769cb93a386Sopenharmony_ci    {
770cb93a386Sopenharmony_ci        const SkSurfaceCharacterization c = params.createCharacterization(dContext);
771cb93a386Sopenharmony_ci
772cb93a386Sopenharmony_ci        if (!c.isValid()) {
773cb93a386Sopenharmony_ci            sk_sp<SkSurface> tmp = params.make(dContext);
774cb93a386Sopenharmony_ci            // If we couldn't characterize the surface we shouldn't be able to create it either
775cb93a386Sopenharmony_ci            REPORTER_ASSERT(reporter, !tmp);
776cb93a386Sopenharmony_ci            return;
777cb93a386Sopenharmony_ci        }
778cb93a386Sopenharmony_ci    }
779cb93a386Sopenharmony_ci
780cb93a386Sopenharmony_ci    const SkSurfaceCharacterization c = params.createCharacterization(dContext);
781cb93a386Sopenharmony_ci    {
782cb93a386Sopenharmony_ci        sk_sp<SkSurface> s = params.make(dContext);
783cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, s);
784cb93a386Sopenharmony_ci        if (!s) {
785cb93a386Sopenharmony_ci            REPORTER_ASSERT(reporter, !c.isValid());
786cb93a386Sopenharmony_ci            return;
787cb93a386Sopenharmony_ci        }
788cb93a386Sopenharmony_ci
789cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, c.isValid());
790cb93a386Sopenharmony_ci        GrBackendTexture backend = s->getBackendTexture(SkSurface::kFlushRead_BackendHandleAccess);
791cb93a386Sopenharmony_ci        if (backend.isValid()) {
792cb93a386Sopenharmony_ci            REPORTER_ASSERT(reporter, c.isCompatible(backend));
793cb93a386Sopenharmony_ci        }
794cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, s->isCompatible(c));
795cb93a386Sopenharmony_ci        // Note that we're leaving 'backend' live here
796cb93a386Sopenharmony_ci    }
797cb93a386Sopenharmony_ci
798cb93a386Sopenharmony_ci    // Make an SkSurface from scratch
799cb93a386Sopenharmony_ci    {
800cb93a386Sopenharmony_ci        sk_sp<SkSurface> s = SkSurface::MakeRenderTarget(dContext, c, SkBudgeted::kYes);
801cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, s);
802cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, s->isCompatible(c));
803cb93a386Sopenharmony_ci    }
804cb93a386Sopenharmony_ci}
805cb93a386Sopenharmony_ci
806cb93a386Sopenharmony_ci////////////////////////////////////////////////////////////////////////////////
807cb93a386Sopenharmony_ci// This tests the SkSurface::MakeRenderTarget variants that take an SkSurfaceCharacterization.
808cb93a386Sopenharmony_ci// In particular, the SkSurface, backendTexture and SkSurfaceCharacterization
809cb93a386Sopenharmony_ci// should always be compatible.
810cb93a386Sopenharmony_civoid DDLMakeRenderTargetTestImpl(GrDirectContext* dContext, skiatest::Reporter* reporter) {
811cb93a386Sopenharmony_ci    for (int i = -1; i < SurfaceParameters::kNumParams; ++i) {
812cb93a386Sopenharmony_ci        if (i == SurfaceParameters::kFBO0Count || i == SurfaceParameters::kVkSCBCount) {
813cb93a386Sopenharmony_ci            // MakeRenderTarget doesn't support FBO0 or vulkan secondary command buffers
814cb93a386Sopenharmony_ci            continue;
815cb93a386Sopenharmony_ci        }
816cb93a386Sopenharmony_ci
817cb93a386Sopenharmony_ci        SurfaceParameters params(dContext);
818cb93a386Sopenharmony_ci        if (i >= 0 && !params.modify(i)) {
819cb93a386Sopenharmony_ci            continue;
820cb93a386Sopenharmony_ci        }
821cb93a386Sopenharmony_ci
822cb93a386Sopenharmony_ci        test_make_render_target(reporter, dContext, params);
823cb93a386Sopenharmony_ci    }
824cb93a386Sopenharmony_ci}
825cb93a386Sopenharmony_ci
826cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLMakeRenderTargetTest, reporter, ctxInfo) {
827cb93a386Sopenharmony_ci    auto context = ctxInfo.directContext();
828cb93a386Sopenharmony_ci
829cb93a386Sopenharmony_ci    DDLMakeRenderTargetTestImpl(context, reporter);
830cb93a386Sopenharmony_ci}
831cb93a386Sopenharmony_ci
832cb93a386Sopenharmony_ci////////////////////////////////////////////////////////////////////////////////
833cb93a386Sopenharmony_cistatic constexpr int kSize = 8;
834cb93a386Sopenharmony_ci
835cb93a386Sopenharmony_cistruct TextureReleaseChecker {
836cb93a386Sopenharmony_ci    TextureReleaseChecker() : fReleaseCount(0) {}
837cb93a386Sopenharmony_ci    int fReleaseCount;
838cb93a386Sopenharmony_ci    static void Release(void* self) {
839cb93a386Sopenharmony_ci        static_cast<TextureReleaseChecker*>(self)->fReleaseCount++;
840cb93a386Sopenharmony_ci    }
841cb93a386Sopenharmony_ci};
842cb93a386Sopenharmony_ci
843cb93a386Sopenharmony_cienum class DDLStage { kMakeImage, kDrawImage, kDetach, kDrawDDL };
844cb93a386Sopenharmony_ci
845cb93a386Sopenharmony_ci// This tests the ability to create and use wrapped textures in a DDL world
846cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLWrapBackendTest, reporter, ctxInfo) {
847cb93a386Sopenharmony_ci    auto dContext = ctxInfo.directContext();
848cb93a386Sopenharmony_ci
849cb93a386Sopenharmony_ci    auto mbet = sk_gpu_test::ManagedBackendTexture::MakeWithoutData(dContext,
850cb93a386Sopenharmony_ci                                                                    kSize,
851cb93a386Sopenharmony_ci                                                                    kSize,
852cb93a386Sopenharmony_ci                                                                    kRGBA_8888_SkColorType,
853cb93a386Sopenharmony_ci                                                                    GrMipmapped::kNo,
854cb93a386Sopenharmony_ci                                                                    GrRenderable::kNo,
855cb93a386Sopenharmony_ci                                                                    GrProtected::kNo);
856cb93a386Sopenharmony_ci    if (!mbet) {
857cb93a386Sopenharmony_ci        return;
858cb93a386Sopenharmony_ci    }
859cb93a386Sopenharmony_ci
860cb93a386Sopenharmony_ci    SurfaceParameters params(dContext);
861cb93a386Sopenharmony_ci
862cb93a386Sopenharmony_ci    sk_sp<SkSurface> s = params.make(dContext);
863cb93a386Sopenharmony_ci    if (!s) {
864cb93a386Sopenharmony_ci        return;
865cb93a386Sopenharmony_ci    }
866cb93a386Sopenharmony_ci
867cb93a386Sopenharmony_ci    SkSurfaceCharacterization c;
868cb93a386Sopenharmony_ci    SkAssertResult(s->characterize(&c));
869cb93a386Sopenharmony_ci
870cb93a386Sopenharmony_ci    SkDeferredDisplayListRecorder recorder(c);
871cb93a386Sopenharmony_ci
872cb93a386Sopenharmony_ci    SkCanvas* canvas = recorder.getCanvas();
873cb93a386Sopenharmony_ci    SkASSERT(canvas);
874cb93a386Sopenharmony_ci
875cb93a386Sopenharmony_ci    auto rContext = canvas->recordingContext();
876cb93a386Sopenharmony_ci    if (!rContext) {
877cb93a386Sopenharmony_ci        return;
878cb93a386Sopenharmony_ci    }
879cb93a386Sopenharmony_ci
880cb93a386Sopenharmony_ci    // Wrapped Backend Textures are not supported in DDL
881cb93a386Sopenharmony_ci    TextureReleaseChecker releaseChecker;
882cb93a386Sopenharmony_ci    sk_sp<SkImage> image = SkImage::MakeFromTexture(
883cb93a386Sopenharmony_ci            rContext,
884cb93a386Sopenharmony_ci            mbet->texture(),
885cb93a386Sopenharmony_ci            kTopLeft_GrSurfaceOrigin,
886cb93a386Sopenharmony_ci            kRGBA_8888_SkColorType,
887cb93a386Sopenharmony_ci            kPremul_SkAlphaType,
888cb93a386Sopenharmony_ci            nullptr,
889cb93a386Sopenharmony_ci            sk_gpu_test::ManagedBackendTexture::ReleaseProc,
890cb93a386Sopenharmony_ci            mbet->releaseContext(TextureReleaseChecker::Release, &releaseChecker));
891cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, !image);
892cb93a386Sopenharmony_ci}
893cb93a386Sopenharmony_ci
894cb93a386Sopenharmony_ci////////////////////////////////////////////////////////////////////////////////
895cb93a386Sopenharmony_ci// Test out the behavior of an invalid DDLRecorder
896cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLInvalidRecorder, reporter, ctxInfo) {
897cb93a386Sopenharmony_ci    auto dContext = ctxInfo.directContext();
898cb93a386Sopenharmony_ci
899cb93a386Sopenharmony_ci    {
900cb93a386Sopenharmony_ci        SkImageInfo ii = SkImageInfo::MakeN32Premul(32, 32);
901cb93a386Sopenharmony_ci        sk_sp<SkSurface> s = SkSurface::MakeRenderTarget(dContext, SkBudgeted::kNo, ii);
902cb93a386Sopenharmony_ci
903cb93a386Sopenharmony_ci        SkSurfaceCharacterization characterization;
904cb93a386Sopenharmony_ci        SkAssertResult(s->characterize(&characterization));
905cb93a386Sopenharmony_ci
906cb93a386Sopenharmony_ci        // never calling getCanvas means the backing surface is never allocated
907cb93a386Sopenharmony_ci        SkDeferredDisplayListRecorder recorder(characterization);
908cb93a386Sopenharmony_ci    }
909cb93a386Sopenharmony_ci
910cb93a386Sopenharmony_ci    {
911cb93a386Sopenharmony_ci        SkSurfaceCharacterization invalid;
912cb93a386Sopenharmony_ci
913cb93a386Sopenharmony_ci        SkDeferredDisplayListRecorder recorder(invalid);
914cb93a386Sopenharmony_ci
915cb93a386Sopenharmony_ci        const SkSurfaceCharacterization c = recorder.characterization();
916cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, !c.isValid());
917cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, !recorder.getCanvas());
918cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, !recorder.detach());
919cb93a386Sopenharmony_ci    }
920cb93a386Sopenharmony_ci}
921cb93a386Sopenharmony_ci
922cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLCreateCharacterizationFailures, reporter, ctxInfo) {
923cb93a386Sopenharmony_ci    auto dContext = ctxInfo.directContext();
924cb93a386Sopenharmony_ci    size_t maxResourceBytes = dContext->getResourceCacheLimit();
925cb93a386Sopenharmony_ci    auto proxy = dContext->threadSafeProxy().get();
926cb93a386Sopenharmony_ci
927cb93a386Sopenharmony_ci    auto check_create_fails =
928cb93a386Sopenharmony_ci            [proxy, reporter, maxResourceBytes](const GrBackendFormat& backendFormat,
929cb93a386Sopenharmony_ci                                                int width, int height,
930cb93a386Sopenharmony_ci                                                SkColorType ct, bool willUseGLFBO0,
931cb93a386Sopenharmony_ci                                                bool isTextureable,
932cb93a386Sopenharmony_ci                                                GrProtected prot,
933cb93a386Sopenharmony_ci                                                bool vkRTSupportsInputAttachment,
934cb93a386Sopenharmony_ci                                                bool forVulkanSecondaryCommandBuffer) {
935cb93a386Sopenharmony_ci        const SkSurfaceProps surfaceProps(0x0, kRGB_H_SkPixelGeometry);
936cb93a386Sopenharmony_ci
937cb93a386Sopenharmony_ci        SkImageInfo ii = SkImageInfo::Make(width, height, ct,
938cb93a386Sopenharmony_ci                                           kPremul_SkAlphaType, nullptr);
939cb93a386Sopenharmony_ci
940cb93a386Sopenharmony_ci        SkSurfaceCharacterization c = proxy->createCharacterization(
941cb93a386Sopenharmony_ci                                                maxResourceBytes, ii, backendFormat, 1,
942cb93a386Sopenharmony_ci                                                kBottomLeft_GrSurfaceOrigin, surfaceProps, false,
943cb93a386Sopenharmony_ci                                                willUseGLFBO0, isTextureable, prot,
944cb93a386Sopenharmony_ci                                                vkRTSupportsInputAttachment,
945cb93a386Sopenharmony_ci                                                forVulkanSecondaryCommandBuffer);
946cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, !c.isValid());
947cb93a386Sopenharmony_ci    };
948cb93a386Sopenharmony_ci
949cb93a386Sopenharmony_ci    GrBackendFormat goodBackendFormat = dContext->defaultBackendFormat(kRGBA_8888_SkColorType,
950cb93a386Sopenharmony_ci                                                                       GrRenderable::kYes);
951cb93a386Sopenharmony_ci    SkASSERT(goodBackendFormat.isValid());
952cb93a386Sopenharmony_ci
953cb93a386Sopenharmony_ci    GrBackendFormat badBackendFormat;
954cb93a386Sopenharmony_ci    SkASSERT(!badBackendFormat.isValid());
955cb93a386Sopenharmony_ci
956cb93a386Sopenharmony_ci    SkColorType kGoodCT = kRGBA_8888_SkColorType;
957cb93a386Sopenharmony_ci    SkColorType kBadCT = kUnknown_SkColorType;
958cb93a386Sopenharmony_ci
959cb93a386Sopenharmony_ci    static const bool kIsTextureable = true;
960cb93a386Sopenharmony_ci    static const bool kIsNotTextureable = false;
961cb93a386Sopenharmony_ci
962cb93a386Sopenharmony_ci    static const bool kGoodUseFBO0 = false;
963cb93a386Sopenharmony_ci    static const bool kBadUseFBO0 = true;
964cb93a386Sopenharmony_ci
965cb93a386Sopenharmony_ci    static const bool kGoodVkInputAttachment = false;
966cb93a386Sopenharmony_ci    static const bool kBadVkInputAttachment = true;
967cb93a386Sopenharmony_ci
968cb93a386Sopenharmony_ci    static const bool kGoodForVkSCB = false;
969cb93a386Sopenharmony_ci    static const bool kBadForVkSCB = true;
970cb93a386Sopenharmony_ci
971cb93a386Sopenharmony_ci    int goodWidth = 64;
972cb93a386Sopenharmony_ci    int goodHeight = 64;
973cb93a386Sopenharmony_ci    int badWidths[] = { 0, 1048576 };
974cb93a386Sopenharmony_ci    int badHeights[] = { 0, 1048576 };
975cb93a386Sopenharmony_ci
976cb93a386Sopenharmony_ci
977cb93a386Sopenharmony_ci    // In each of the check_create_fails calls there is one bad parameter that should cause the
978cb93a386Sopenharmony_ci    // creation of the characterization to fail.
979cb93a386Sopenharmony_ci    check_create_fails(goodBackendFormat, goodWidth, badHeights[0], kGoodCT, kGoodUseFBO0,
980cb93a386Sopenharmony_ci                       kIsTextureable, GrProtected::kNo, kGoodVkInputAttachment, kGoodForVkSCB);
981cb93a386Sopenharmony_ci    check_create_fails(goodBackendFormat, goodWidth, badHeights[1], kGoodCT, kGoodUseFBO0,
982cb93a386Sopenharmony_ci                       kIsTextureable, GrProtected::kNo, kGoodVkInputAttachment, kGoodForVkSCB);
983cb93a386Sopenharmony_ci    check_create_fails(goodBackendFormat, badWidths[0], goodHeight, kGoodCT, kGoodUseFBO0,
984cb93a386Sopenharmony_ci                       kIsTextureable, GrProtected::kNo, kGoodVkInputAttachment, kGoodForVkSCB);
985cb93a386Sopenharmony_ci    check_create_fails(goodBackendFormat, badWidths[1], goodHeight, kGoodCT, kGoodUseFBO0,
986cb93a386Sopenharmony_ci                       kIsTextureable, GrProtected::kNo, kGoodVkInputAttachment, kGoodForVkSCB);
987cb93a386Sopenharmony_ci    check_create_fails(badBackendFormat, goodWidth, goodHeight, kGoodCT, kGoodUseFBO0,
988cb93a386Sopenharmony_ci                       kIsTextureable, GrProtected::kNo, kGoodVkInputAttachment, kGoodForVkSCB);
989cb93a386Sopenharmony_ci    check_create_fails(goodBackendFormat, goodWidth, goodHeight, kBadCT, kGoodUseFBO0,
990cb93a386Sopenharmony_ci                       kIsTextureable, GrProtected::kNo, kGoodVkInputAttachment, kGoodForVkSCB);
991cb93a386Sopenharmony_ci    // This fails because we always try to make a characterization that is textureable and we can't
992cb93a386Sopenharmony_ci    // have UseFBO0 be true and textureable.
993cb93a386Sopenharmony_ci    check_create_fails(goodBackendFormat, goodWidth, goodHeight, kGoodCT, kBadUseFBO0,
994cb93a386Sopenharmony_ci                       kIsTextureable, GrProtected::kNo, kGoodVkInputAttachment, kGoodForVkSCB);
995cb93a386Sopenharmony_ci    if (dContext->backend() == GrBackendApi::kVulkan) {
996cb93a386Sopenharmony_ci        // The bad parameter in this case is the GrProtected::kYes since none of our test contexts
997cb93a386Sopenharmony_ci        // are made protected we can't have a protected surface.
998cb93a386Sopenharmony_ci        check_create_fails(goodBackendFormat, goodWidth, goodHeight, kGoodCT, kGoodUseFBO0,
999cb93a386Sopenharmony_ci                           kIsTextureable, GrProtected::kYes, kGoodVkInputAttachment,
1000cb93a386Sopenharmony_ci                           kGoodForVkSCB);
1001cb93a386Sopenharmony_ci        // The following fails because forVulkanSecondaryCommandBuffer is true and
1002cb93a386Sopenharmony_ci        // isTextureable is true. This is not a legal combination.
1003cb93a386Sopenharmony_ci        check_create_fails(goodBackendFormat, goodWidth, goodHeight, kGoodCT, kGoodUseFBO0,
1004cb93a386Sopenharmony_ci                           kIsTextureable, GrProtected::kNo, kGoodVkInputAttachment, kBadForVkSCB);
1005cb93a386Sopenharmony_ci        // The following fails because forVulkanSecondaryCommandBuffer is true and
1006cb93a386Sopenharmony_ci        // vkRTSupportsInputAttachment is true. This is not a legal combination.
1007cb93a386Sopenharmony_ci        check_create_fails(goodBackendFormat, goodWidth, goodHeight, kGoodCT, kGoodUseFBO0,
1008cb93a386Sopenharmony_ci                           kIsNotTextureable, GrProtected::kNo, kBadVkInputAttachment,
1009cb93a386Sopenharmony_ci                           kBadForVkSCB);
1010cb93a386Sopenharmony_ci        // The following fails because forVulkanSecondaryCommandBuffer is true and
1011cb93a386Sopenharmony_ci        // willUseGLFBO0 is true. This is not a legal combination.
1012cb93a386Sopenharmony_ci        check_create_fails(goodBackendFormat, goodWidth, goodHeight, kGoodCT, kBadUseFBO0,
1013cb93a386Sopenharmony_ci                           kIsNotTextureable, GrProtected::kNo, kGoodVkInputAttachment,
1014cb93a386Sopenharmony_ci                           kBadForVkSCB);
1015cb93a386Sopenharmony_ci    } else {
1016cb93a386Sopenharmony_ci        // The following set vulkan only flags on non vulkan backends.
1017cb93a386Sopenharmony_ci        check_create_fails(goodBackendFormat, goodWidth, goodHeight, kGoodCT, kGoodUseFBO0,
1018cb93a386Sopenharmony_ci                           kIsTextureable, GrProtected::kNo, kBadVkInputAttachment, kGoodForVkSCB);
1019cb93a386Sopenharmony_ci        check_create_fails(goodBackendFormat, goodWidth, goodHeight, kGoodCT, kGoodUseFBO0,
1020cb93a386Sopenharmony_ci                           kIsNotTextureable, GrProtected::kNo, kGoodVkInputAttachment,
1021cb93a386Sopenharmony_ci                           kBadForVkSCB);
1022cb93a386Sopenharmony_ci    }
1023cb93a386Sopenharmony_ci}
1024cb93a386Sopenharmony_ci
1025cb93a386Sopenharmony_ci////////////////////////////////////////////////////////////////////////////////
1026cb93a386Sopenharmony_ci// Test that flushing a DDL via SkSurface::flush works
1027cb93a386Sopenharmony_ci
1028cb93a386Sopenharmony_cistruct FulfillInfo {
1029cb93a386Sopenharmony_ci    sk_sp<SkPromiseImageTexture> fTex;
1030cb93a386Sopenharmony_ci    bool fFulfilled = false;
1031cb93a386Sopenharmony_ci    bool fReleased  = false;
1032cb93a386Sopenharmony_ci};
1033cb93a386Sopenharmony_ci
1034cb93a386Sopenharmony_cistatic sk_sp<SkPromiseImageTexture> tracking_fulfill_proc(void* context) {
1035cb93a386Sopenharmony_ci    FulfillInfo* info = (FulfillInfo*) context;
1036cb93a386Sopenharmony_ci    info->fFulfilled = true;
1037cb93a386Sopenharmony_ci    return info->fTex;
1038cb93a386Sopenharmony_ci}
1039cb93a386Sopenharmony_ci
1040cb93a386Sopenharmony_cistatic void tracking_release_proc(void* context) {
1041cb93a386Sopenharmony_ci    FulfillInfo* info = (FulfillInfo*) context;
1042cb93a386Sopenharmony_ci    info->fReleased = true;
1043cb93a386Sopenharmony_ci}
1044cb93a386Sopenharmony_ci
1045cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLSkSurfaceFlush, reporter, ctxInfo) {
1046cb93a386Sopenharmony_ci    auto context = ctxInfo.directContext();
1047cb93a386Sopenharmony_ci
1048cb93a386Sopenharmony_ci    SkImageInfo ii = SkImageInfo::Make(32, 32, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
1049cb93a386Sopenharmony_ci    sk_sp<SkSurface> s = SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, ii);
1050cb93a386Sopenharmony_ci
1051cb93a386Sopenharmony_ci    SkSurfaceCharacterization characterization;
1052cb93a386Sopenharmony_ci    SkAssertResult(s->characterize(&characterization));
1053cb93a386Sopenharmony_ci
1054cb93a386Sopenharmony_ci    auto mbet = sk_gpu_test::ManagedBackendTexture::MakeFromInfo(context, ii);
1055cb93a386Sopenharmony_ci    if (!mbet) {
1056cb93a386Sopenharmony_ci        ERRORF(reporter, "Could not make texture.");
1057cb93a386Sopenharmony_ci        return;
1058cb93a386Sopenharmony_ci    }
1059cb93a386Sopenharmony_ci
1060cb93a386Sopenharmony_ci    FulfillInfo fulfillInfo;
1061cb93a386Sopenharmony_ci    fulfillInfo.fTex = SkPromiseImageTexture::Make(mbet->texture());
1062cb93a386Sopenharmony_ci
1063cb93a386Sopenharmony_ci    sk_sp<SkDeferredDisplayList> ddl;
1064cb93a386Sopenharmony_ci
1065cb93a386Sopenharmony_ci    {
1066cb93a386Sopenharmony_ci        SkDeferredDisplayListRecorder recorder(characterization);
1067cb93a386Sopenharmony_ci
1068cb93a386Sopenharmony_ci        GrBackendFormat format = context->defaultBackendFormat(kRGBA_8888_SkColorType,
1069cb93a386Sopenharmony_ci                                                               GrRenderable::kNo);
1070cb93a386Sopenharmony_ci        SkASSERT(format.isValid());
1071cb93a386Sopenharmony_ci
1072cb93a386Sopenharmony_ci        SkCanvas* canvas = recorder.getCanvas();
1073cb93a386Sopenharmony_ci
1074cb93a386Sopenharmony_ci        sk_sp<SkImage> promiseImage = SkImage::MakePromiseTexture(
1075cb93a386Sopenharmony_ci                                                      canvas->recordingContext()->threadSafeProxy(),
1076cb93a386Sopenharmony_ci                                                      format,
1077cb93a386Sopenharmony_ci                                                      SkISize::Make(32, 32),
1078cb93a386Sopenharmony_ci                                                      GrMipmapped::kNo,
1079cb93a386Sopenharmony_ci                                                      kTopLeft_GrSurfaceOrigin,
1080cb93a386Sopenharmony_ci                                                      kRGBA_8888_SkColorType,
1081cb93a386Sopenharmony_ci                                                      kPremul_SkAlphaType,
1082cb93a386Sopenharmony_ci                                                      nullptr,
1083cb93a386Sopenharmony_ci                                                      tracking_fulfill_proc,
1084cb93a386Sopenharmony_ci                                                      tracking_release_proc,
1085cb93a386Sopenharmony_ci                                                      &fulfillInfo);
1086cb93a386Sopenharmony_ci
1087cb93a386Sopenharmony_ci        canvas->clear(SK_ColorRED);
1088cb93a386Sopenharmony_ci        canvas->drawImage(promiseImage, 0, 0);
1089cb93a386Sopenharmony_ci        ddl = recorder.detach();
1090cb93a386Sopenharmony_ci    }
1091cb93a386Sopenharmony_ci
1092cb93a386Sopenharmony_ci    context->flushAndSubmit();
1093cb93a386Sopenharmony_ci
1094cb93a386Sopenharmony_ci    s->draw(ddl);
1095cb93a386Sopenharmony_ci
1096cb93a386Sopenharmony_ci    GrFlushInfo flushInfo;
1097cb93a386Sopenharmony_ci    s->flush(SkSurface::BackendSurfaceAccess::kPresent, flushInfo);
1098cb93a386Sopenharmony_ci    context->submit();
1099cb93a386Sopenharmony_ci
1100cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, fulfillInfo.fFulfilled);
1101cb93a386Sopenharmony_ci
1102cb93a386Sopenharmony_ci    // In order to receive the done callback with the low-level APIs we need to re-flush
1103cb93a386Sopenharmony_ci    s->flush();
1104cb93a386Sopenharmony_ci    context->submit(true);
1105cb93a386Sopenharmony_ci
1106cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, fulfillInfo.fReleased);
1107cb93a386Sopenharmony_ci
1108cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, fulfillInfo.fTex->unique());
1109cb93a386Sopenharmony_ci    fulfillInfo.fTex.reset();
1110cb93a386Sopenharmony_ci}
1111cb93a386Sopenharmony_ci
1112cb93a386Sopenharmony_ci////////////////////////////////////////////////////////////////////////////////
1113cb93a386Sopenharmony_ci// Ensure that reusing a single DDLRecorder to create multiple DDLs works cleanly
1114cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLMultipleDDLs, reporter, ctxInfo) {
1115cb93a386Sopenharmony_ci    auto context = ctxInfo.directContext();
1116cb93a386Sopenharmony_ci
1117cb93a386Sopenharmony_ci    SkImageInfo ii = SkImageInfo::MakeN32Premul(32, 32);
1118cb93a386Sopenharmony_ci    sk_sp<SkSurface> s = SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, ii);
1119cb93a386Sopenharmony_ci
1120cb93a386Sopenharmony_ci    SkBitmap bitmap;
1121cb93a386Sopenharmony_ci    bitmap.allocPixels(ii);
1122cb93a386Sopenharmony_ci
1123cb93a386Sopenharmony_ci    SkSurfaceCharacterization characterization;
1124cb93a386Sopenharmony_ci    SkAssertResult(s->characterize(&characterization));
1125cb93a386Sopenharmony_ci
1126cb93a386Sopenharmony_ci    SkDeferredDisplayListRecorder recorder(characterization);
1127cb93a386Sopenharmony_ci
1128cb93a386Sopenharmony_ci    SkCanvas* canvas1 = recorder.getCanvas();
1129cb93a386Sopenharmony_ci
1130cb93a386Sopenharmony_ci    canvas1->clear(SK_ColorRED);
1131cb93a386Sopenharmony_ci
1132cb93a386Sopenharmony_ci    canvas1->save();
1133cb93a386Sopenharmony_ci    canvas1->clipRect(SkRect::MakeXYWH(8, 8, 16, 16));
1134cb93a386Sopenharmony_ci
1135cb93a386Sopenharmony_ci    sk_sp<SkDeferredDisplayList> ddl1 = recorder.detach();
1136cb93a386Sopenharmony_ci
1137cb93a386Sopenharmony_ci    SkCanvas* canvas2 = recorder.getCanvas();
1138cb93a386Sopenharmony_ci
1139cb93a386Sopenharmony_ci    SkPaint p;
1140cb93a386Sopenharmony_ci    p.setColor(SK_ColorGREEN);
1141cb93a386Sopenharmony_ci    canvas2->drawRect(SkRect::MakeWH(32, 32), p);
1142cb93a386Sopenharmony_ci
1143cb93a386Sopenharmony_ci    sk_sp<SkDeferredDisplayList> ddl2 = recorder.detach();
1144cb93a386Sopenharmony_ci
1145cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, ddl1->priv().lazyProxyData());
1146cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, ddl2->priv().lazyProxyData());
1147cb93a386Sopenharmony_ci
1148cb93a386Sopenharmony_ci    // The lazy proxy data being different ensures that the SkSurface, SkCanvas and backing-
1149cb93a386Sopenharmony_ci    // lazy proxy are all different between the two DDLs
1150cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, ddl1->priv().lazyProxyData() != ddl2->priv().lazyProxyData());
1151cb93a386Sopenharmony_ci
1152cb93a386Sopenharmony_ci    s->draw(ddl1);
1153cb93a386Sopenharmony_ci    s->draw(ddl2);
1154cb93a386Sopenharmony_ci
1155cb93a386Sopenharmony_ci    // Make sure the clipRect from DDL1 didn't percolate into DDL2
1156cb93a386Sopenharmony_ci    s->readPixels(ii, bitmap.getPixels(), bitmap.rowBytes(), 0, 0);
1157cb93a386Sopenharmony_ci    for (int y = 0; y < 32; ++y) {
1158cb93a386Sopenharmony_ci        for (int x = 0; x < 32; ++x) {
1159cb93a386Sopenharmony_ci            REPORTER_ASSERT(reporter, bitmap.getColor(x, y) == SK_ColorGREEN);
1160cb93a386Sopenharmony_ci            if (bitmap.getColor(x, y) != SK_ColorGREEN) {
1161cb93a386Sopenharmony_ci                return; // we only really need to report the error once
1162cb93a386Sopenharmony_ci            }
1163cb93a386Sopenharmony_ci        }
1164cb93a386Sopenharmony_ci    }
1165cb93a386Sopenharmony_ci}
1166cb93a386Sopenharmony_ci
1167cb93a386Sopenharmony_ci#ifdef SK_GL
1168cb93a386Sopenharmony_ci
1169cb93a386Sopenharmony_cistatic sk_sp<SkPromiseImageTexture> noop_fulfill_proc(void*) {
1170cb93a386Sopenharmony_ci    SkASSERT(0);
1171cb93a386Sopenharmony_ci    return nullptr;
1172cb93a386Sopenharmony_ci}
1173cb93a386Sopenharmony_ci
1174cb93a386Sopenharmony_ci////////////////////////////////////////////////////////////////////////////////
1175cb93a386Sopenharmony_ci// Check that the texture-specific flags (i.e., for external & rectangle textures) work
1176cb93a386Sopenharmony_ci// for promise images. As such, this is a GL-only test.
1177cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(DDLTextureFlagsTest, reporter, ctxInfo) {
1178cb93a386Sopenharmony_ci    auto context = ctxInfo.directContext();
1179cb93a386Sopenharmony_ci
1180cb93a386Sopenharmony_ci    SkImageInfo ii = SkImageInfo::MakeN32Premul(32, 32);
1181cb93a386Sopenharmony_ci    sk_sp<SkSurface> s = SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, ii);
1182cb93a386Sopenharmony_ci
1183cb93a386Sopenharmony_ci    SkSurfaceCharacterization characterization;
1184cb93a386Sopenharmony_ci    SkAssertResult(s->characterize(&characterization));
1185cb93a386Sopenharmony_ci
1186cb93a386Sopenharmony_ci    SkDeferredDisplayListRecorder recorder(characterization);
1187cb93a386Sopenharmony_ci
1188cb93a386Sopenharmony_ci    for (GrGLenum target : { GR_GL_TEXTURE_EXTERNAL, GR_GL_TEXTURE_RECTANGLE, GR_GL_TEXTURE_2D } ) {
1189cb93a386Sopenharmony_ci        for (auto mipMapped : { GrMipmapped::kNo, GrMipmapped::kYes }) {
1190cb93a386Sopenharmony_ci            GrBackendFormat format = GrBackendFormat::MakeGL(GR_GL_RGBA8, target);
1191cb93a386Sopenharmony_ci
1192cb93a386Sopenharmony_ci            sk_sp<SkImage> image = SkImage::MakePromiseTexture(
1193cb93a386Sopenharmony_ci                    recorder.getCanvas()->recordingContext()->threadSafeProxy(),
1194cb93a386Sopenharmony_ci                    format,
1195cb93a386Sopenharmony_ci                    SkISize::Make(32, 32),
1196cb93a386Sopenharmony_ci                    mipMapped,
1197cb93a386Sopenharmony_ci                    kTopLeft_GrSurfaceOrigin,
1198cb93a386Sopenharmony_ci                    kRGBA_8888_SkColorType,
1199cb93a386Sopenharmony_ci                    kPremul_SkAlphaType,
1200cb93a386Sopenharmony_ci                    /*color space*/nullptr,
1201cb93a386Sopenharmony_ci                    noop_fulfill_proc,
1202cb93a386Sopenharmony_ci                    /*release proc*/ nullptr,
1203cb93a386Sopenharmony_ci                    /*context*/nullptr);
1204cb93a386Sopenharmony_ci            if (GR_GL_TEXTURE_2D != target && mipMapped == GrMipmapped::kYes) {
1205cb93a386Sopenharmony_ci                REPORTER_ASSERT(reporter, !image);
1206cb93a386Sopenharmony_ci                continue;
1207cb93a386Sopenharmony_ci            }
1208cb93a386Sopenharmony_ci            REPORTER_ASSERT(reporter, image);
1209cb93a386Sopenharmony_ci
1210cb93a386Sopenharmony_ci            GrTextureProxy* backingProxy = sk_gpu_test::GetTextureImageProxy(image.get(), context);
1211cb93a386Sopenharmony_ci
1212cb93a386Sopenharmony_ci            REPORTER_ASSERT(reporter, backingProxy->mipmapped() == mipMapped);
1213cb93a386Sopenharmony_ci            if (GR_GL_TEXTURE_2D == target) {
1214cb93a386Sopenharmony_ci                REPORTER_ASSERT(reporter, !backingProxy->hasRestrictedSampling());
1215cb93a386Sopenharmony_ci            } else {
1216cb93a386Sopenharmony_ci                REPORTER_ASSERT(reporter, backingProxy->hasRestrictedSampling());
1217cb93a386Sopenharmony_ci            }
1218cb93a386Sopenharmony_ci        }
1219cb93a386Sopenharmony_ci    }
1220cb93a386Sopenharmony_ci}
1221cb93a386Sopenharmony_ci#endif  // SK_GL
1222cb93a386Sopenharmony_ci
1223cb93a386Sopenharmony_ci////////////////////////////////////////////////////////////////////////////////
1224cb93a386Sopenharmony_ci// Test colorType and pixelConfig compatibility.
1225cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(DDLCompatibilityTest, reporter, ctxInfo) {
1226cb93a386Sopenharmony_ci    auto context = ctxInfo.directContext();
1227cb93a386Sopenharmony_ci
1228cb93a386Sopenharmony_ci    for (int ct = 0; ct <= kLastEnum_SkColorType; ++ct) {
1229cb93a386Sopenharmony_ci        SkColorType colorType = static_cast<SkColorType>(ct);
1230cb93a386Sopenharmony_ci
1231cb93a386Sopenharmony_ci        SurfaceParameters params(context);
1232cb93a386Sopenharmony_ci        params.setColorType(colorType);
1233cb93a386Sopenharmony_ci        params.setColorSpace(nullptr);
1234cb93a386Sopenharmony_ci
1235cb93a386Sopenharmony_ci        test_make_render_target(reporter, context, params);
1236cb93a386Sopenharmony_ci    }
1237cb93a386Sopenharmony_ci
1238cb93a386Sopenharmony_ci}
1239