1/*
2 * Copyright 2015 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#ifndef GrVkImage_DEFINED
9#define GrVkImage_DEFINED
10
11#include "GrVkResource.h"
12
13#include "GrTypesPriv.h"
14#include "SkTypes.h"
15
16#include "vk/GrVkDefines.h"
17#include "vk/GrVkTypes.h"
18
19class GrVkGpu;
20
21class GrVkImage : SkNoncopyable {
22private:
23    class Resource;
24
25public:
26    GrVkImage(const GrVkImageInfo& info, GrBackendObjectOwnership ownership)
27        : fInfo(info)
28        , fIsBorrowed(GrBackendObjectOwnership::kBorrowed == ownership) {
29        if (fIsBorrowed) {
30            fResource = new BorrowedResource(info.fImage, info.fAlloc, info.fImageTiling);
31        } else {
32            fResource = new Resource(info.fImage, info.fAlloc, info.fImageTiling);
33        }
34    }
35    virtual ~GrVkImage();
36
37    VkImage image() const { return fInfo.fImage; }
38    const GrVkAlloc& alloc() const { return fInfo.fAlloc; }
39    VkFormat imageFormat() const { return fInfo.fFormat; }
40    uint32_t mipLevels() const { return fInfo.fLevelCount; }
41    const Resource* resource() const { return fResource; }
42    bool isLinearTiled() const {
43        return SkToBool(VK_IMAGE_TILING_LINEAR == fInfo.fImageTiling);
44    }
45    bool isBorrowed() const { return fIsBorrowed; }
46
47    VkImageLayout currentLayout() const { return fInfo.fImageLayout; }
48
49    void setImageLayout(const GrVkGpu* gpu,
50                        VkImageLayout newLayout,
51                        VkAccessFlags dstAccessMask,
52                        VkPipelineStageFlags dstStageMask,
53                        bool byRegion);
54
55    struct ImageDesc {
56        VkImageType         fImageType;
57        VkFormat            fFormat;
58        uint32_t            fWidth;
59        uint32_t            fHeight;
60        uint32_t            fLevels;
61        uint32_t            fSamples;
62        VkImageTiling       fImageTiling;
63        VkImageUsageFlags   fUsageFlags;
64        VkFlags             fMemProps;
65
66        ImageDesc()
67            : fImageType(VK_IMAGE_TYPE_2D)
68            , fFormat(VK_FORMAT_UNDEFINED)
69            , fWidth(0)
70            , fHeight(0)
71            , fLevels(1)
72            , fSamples(1)
73            , fImageTiling(VK_IMAGE_TILING_OPTIMAL)
74            , fUsageFlags(0)
75            , fMemProps(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) {}
76    };
77
78    static bool InitImageInfo(const GrVkGpu* gpu, const ImageDesc& imageDesc, GrVkImageInfo*);
79    // Destroys the internal VkImage and VkDeviceMemory in the GrVkImageInfo
80    static void DestroyImageInfo(const GrVkGpu* gpu, GrVkImageInfo*);
81
82    // These match the definitions in SkImage, for whence they came
83    typedef void* ReleaseCtx;
84    typedef void (*ReleaseProc)(ReleaseCtx);
85
86    void setResourceRelease(sk_sp<GrReleaseProcHelper> releaseHelper);
87
88protected:
89    void releaseImage(const GrVkGpu* gpu);
90    void abandonImage();
91
92    void setNewResource(VkImage image, const GrVkAlloc& alloc, VkImageTiling tiling);
93
94    GrVkImageInfo   fInfo;
95    bool            fIsBorrowed;
96
97private:
98    class Resource : public GrVkResource {
99    public:
100        Resource()
101                : fImage(VK_NULL_HANDLE) {
102            fAlloc.fMemory = VK_NULL_HANDLE;
103            fAlloc.fOffset = 0;
104        }
105
106        Resource(VkImage image, const GrVkAlloc& alloc, VkImageTiling tiling)
107            : fImage(image)
108            , fAlloc(alloc)
109            , fImageTiling(tiling) {}
110
111        ~Resource() override {
112            SkASSERT(!fReleaseHelper);
113        }
114
115#ifdef SK_TRACE_VK_RESOURCES
116        void dumpInfo() const override {
117            SkDebugf("GrVkImage: %d (%d refs)\n", fImage, this->getRefCnt());
118        }
119#endif
120        void setRelease(sk_sp<GrReleaseProcHelper> releaseHelper) {
121            fReleaseHelper = std::move(releaseHelper);
122        }
123    protected:
124        mutable sk_sp<GrReleaseProcHelper> fReleaseHelper;
125
126    private:
127        void freeGPUData(const GrVkGpu* gpu) const override;
128        void abandonGPUData() const override {
129            SkASSERT(!fReleaseHelper);
130        }
131
132        VkImage        fImage;
133        GrVkAlloc      fAlloc;
134        VkImageTiling  fImageTiling;
135
136        typedef GrVkResource INHERITED;
137    };
138
139    // for wrapped textures
140    class BorrowedResource : public Resource {
141    public:
142        BorrowedResource(VkImage image, const GrVkAlloc& alloc, VkImageTiling tiling)
143            : Resource(image, alloc, tiling) {
144        }
145    private:
146        void invokeReleaseProc() const {
147            if (fReleaseHelper) {
148                // Depending on the ref count of fReleaseHelper this may or may not actually trigger
149                // the ReleaseProc to be called.
150                fReleaseHelper.reset();
151            }
152        }
153
154        void freeGPUData(const GrVkGpu* gpu) const override;
155        void abandonGPUData() const override;
156    };
157
158    Resource* fResource;
159
160    friend class GrVkRenderTarget;
161};
162
163#endif
164