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 #include "GrVkTextureRenderTarget.h"
9 
10 #include "GrRenderTargetPriv.h"
11 #include "GrVkGpu.h"
12 #include "GrVkImageView.h"
13 #include "GrVkUtil.h"
14 
15 #include "SkMipMap.h"
16 
17 #include "vk/GrVkTypes.h"
18 
19 #define VK_CALL(GPU, X) GR_VK_CALL(GPU->vkInterface(), X)
20 
Create(GrVkGpu * gpu,const GrSurfaceDesc & desc,const GrVkImageInfo & info,SkBudgeted budgeted,GrVkImage::Wrapped wrapped)21 GrVkTextureRenderTarget* GrVkTextureRenderTarget::Create(GrVkGpu* gpu,
22                                                          const GrSurfaceDesc& desc,
23                                                          const GrVkImageInfo& info,
24                                                          SkBudgeted budgeted,
25                                                          GrVkImage::Wrapped wrapped) {
26     VkImage image = info.fImage;
27     // Create the texture ImageView
28     const GrVkImageView* imageView = GrVkImageView::Create(gpu, image, info.fFormat,
29                                                            GrVkImageView::kColor_Type,
30                                                            info.fLevelCount);
31     if (!imageView) {
32         return nullptr;
33     }
34 
35     VkFormat pixelFormat;
36     GrPixelConfigToVkFormat(desc.fConfig, &pixelFormat);
37 
38     VkImage colorImage;
39 
40     // create msaa surface if necessary
41     GrVkImageInfo msInfo;
42     const GrVkImageView* resolveAttachmentView = nullptr;
43     if (desc.fSampleCnt) {
44         GrVkImage::ImageDesc msImageDesc;
45         msImageDesc.fImageType = VK_IMAGE_TYPE_2D;
46         msImageDesc.fFormat = pixelFormat;
47         msImageDesc.fWidth = desc.fWidth;
48         msImageDesc.fHeight = desc.fHeight;
49         msImageDesc.fLevels = 1;
50         msImageDesc.fSamples = desc.fSampleCnt;
51         msImageDesc.fImageTiling = VK_IMAGE_TILING_OPTIMAL;
52         msImageDesc.fUsageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
53                                   VK_IMAGE_USAGE_TRANSFER_DST_BIT |
54                                   VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
55         msImageDesc.fMemProps = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
56 
57         if (!GrVkImage::InitImageInfo(gpu, msImageDesc, &msInfo)) {
58             imageView->unref(gpu);
59             return nullptr;
60         }
61 
62         // Set color attachment image
63         colorImage = msInfo.fImage;
64 
65         // Create resolve attachment view.
66         resolveAttachmentView = GrVkImageView::Create(gpu, image, pixelFormat,
67                                                       GrVkImageView::kColor_Type,
68                                                       info.fLevelCount);
69         if (!resolveAttachmentView) {
70             GrVkImage::DestroyImageInfo(gpu, &msInfo);
71             imageView->unref(gpu);
72             return nullptr;
73         }
74     } else {
75         // Set color attachment image
76         colorImage = info.fImage;
77     }
78 
79     const GrVkImageView* colorAttachmentView = GrVkImageView::Create(gpu, colorImage, pixelFormat,
80                                                                      GrVkImageView::kColor_Type, 1);
81     if (!colorAttachmentView) {
82         if (desc.fSampleCnt) {
83             resolveAttachmentView->unref(gpu);
84             GrVkImage::DestroyImageInfo(gpu, &msInfo);
85         }
86         imageView->unref(gpu);
87         return nullptr;
88     }
89 
90     GrVkTextureRenderTarget* texRT;
91     if (desc.fSampleCnt) {
92         if (GrVkImage::kNot_Wrapped == wrapped) {
93             texRT = new GrVkTextureRenderTarget(gpu, budgeted, desc,
94                                                 info, imageView, msInfo,
95                                                 colorAttachmentView,
96                                                 resolveAttachmentView);
97         } else {
98             texRT = new GrVkTextureRenderTarget(gpu, desc,
99                                                 info, imageView, msInfo,
100                                                 colorAttachmentView,
101                                                 resolveAttachmentView, wrapped);
102         }
103     } else {
104         if (GrVkImage::kNot_Wrapped == wrapped) {
105             texRT = new GrVkTextureRenderTarget(gpu, budgeted, desc,
106                                                 info, imageView,
107                                                 colorAttachmentView);
108         } else {
109             texRT = new GrVkTextureRenderTarget(gpu, desc,
110                                                 info, imageView,
111                                                 colorAttachmentView, wrapped);
112         }
113     }
114     return texRT;
115 }
116 
117 GrVkTextureRenderTarget*
CreateNewTextureRenderTarget(GrVkGpu * gpu,SkBudgeted budgeted,const GrSurfaceDesc & desc,const GrVkImage::ImageDesc & imageDesc)118 GrVkTextureRenderTarget::CreateNewTextureRenderTarget(GrVkGpu* gpu,
119                                                       SkBudgeted budgeted,
120                                                       const GrSurfaceDesc& desc,
121                                                       const GrVkImage::ImageDesc& imageDesc) {
122     SkASSERT(imageDesc.fUsageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
123     SkASSERT(imageDesc.fUsageFlags & VK_IMAGE_USAGE_SAMPLED_BIT);
124 
125     GrVkImageInfo info;
126     if (!GrVkImage::InitImageInfo(gpu, imageDesc, &info)) {
127         return nullptr;
128     }
129 
130     GrVkTextureRenderTarget* trt = Create(gpu, desc, info, budgeted, GrVkImage::kNot_Wrapped);
131     if (!trt) {
132         GrVkImage::DestroyImageInfo(gpu, &info);
133     }
134 
135     return trt;
136 }
137 
138 sk_sp<GrVkTextureRenderTarget>
MakeWrappedTextureRenderTarget(GrVkGpu * gpu,const GrSurfaceDesc & desc,GrWrapOwnership ownership,const GrVkImageInfo * info)139 GrVkTextureRenderTarget::MakeWrappedTextureRenderTarget(GrVkGpu* gpu,
140                                                         const GrSurfaceDesc& desc,
141                                                         GrWrapOwnership ownership,
142                                                         const GrVkImageInfo* info) {
143     SkASSERT(info);
144     // Wrapped textures require both image and allocation (because they can be mapped)
145     SkASSERT(VK_NULL_HANDLE != info->fImage && VK_NULL_HANDLE != info->fAlloc.fMemory);
146     SkASSERT(kAdoptAndCache_GrWrapOwnership != ownership);  // Not supported
147 
148     GrVkImage::Wrapped wrapped = kBorrow_GrWrapOwnership == ownership ? GrVkImage::kBorrowed_Wrapped
149                                                                       : GrVkImage::kAdopted_Wrapped;
150 
151     return sk_sp<GrVkTextureRenderTarget>(Create(gpu, desc, *info, SkBudgeted::kNo, wrapped));
152 }
153 
updateForMipmap(GrVkGpu * gpu,const GrVkImageInfo & newInfo)154 bool GrVkTextureRenderTarget::updateForMipmap(GrVkGpu* gpu, const GrVkImageInfo& newInfo) {
155     VkFormat pixelFormat;
156     GrPixelConfigToVkFormat(fDesc.fConfig, &pixelFormat);
157     if (fDesc.fSampleCnt) {
158         const GrVkImageView* resolveAttachmentView =
159                 GrVkImageView::Create(gpu,
160                                       newInfo.fImage,
161                                       pixelFormat,
162                                       GrVkImageView::kColor_Type,
163                                       newInfo.fLevelCount);
164         if (!resolveAttachmentView) {
165             return false;
166         }
167         fResolveAttachmentView->unref(gpu);
168         fResolveAttachmentView = resolveAttachmentView;
169     } else {
170         const GrVkImageView* colorAttachmentView = GrVkImageView::Create(gpu,
171                                                                          newInfo.fImage,
172                                                                          pixelFormat,
173                                                                          GrVkImageView::kColor_Type,
174                                                                          1);
175         if (!colorAttachmentView) {
176             return false;
177         }
178         fColorAttachmentView->unref(gpu);
179         fColorAttachmentView = colorAttachmentView;
180     }
181 
182     this->createFramebuffer(gpu);
183     return true;
184 }
185 
186