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 "GrVkTexture.h"
9#include "GrVkGpu.h"
10#include "GrVkImageView.h"
11#include "GrVkUtil.h"
12
13#define VK_CALL(GPU, X) GR_VK_CALL(GPU->vkInterface(), X)
14
15// Because this class is virtually derived from GrSurface we must explicitly call its constructor.
16GrVkTexture::GrVkTexture(GrVkGpu* gpu,
17                         const GrSurfaceDesc& desc,
18                         GrGpuResource::LifeCycle lifeCycle,
19                         const GrVkImage::Resource* imageResource,
20                         const GrVkImageView* view)
21    : GrSurface(gpu, lifeCycle, desc)
22    , GrVkImage(imageResource)
23    , INHERITED(gpu, lifeCycle, desc)
24    , fTextureView(view) {
25    this->registerWithCache();
26}
27
28// Because this class is virtually derived from GrSurface we must explicitly call its constructor.
29GrVkTexture::GrVkTexture(GrVkGpu* gpu,
30                         const GrSurfaceDesc& desc,
31                         GrGpuResource::LifeCycle lifeCycle,
32                         const GrVkImage::Resource* imageResource,
33                         const GrVkImageView* view,
34                         Derived)
35    : GrSurface(gpu, lifeCycle, desc)
36    , GrVkImage(imageResource)
37    , INHERITED(gpu, lifeCycle, desc)
38    , fTextureView(view) {}
39
40
41GrVkTexture* GrVkTexture::Create(GrVkGpu* gpu,
42                                 const GrSurfaceDesc& desc,
43                                 GrGpuResource::LifeCycle lifeCycle,
44                                 VkFormat format,
45                                 const GrVkImage::Resource* imageResource) {
46    VkImage image = imageResource->fImage;
47    const GrVkImageView* imageView = GrVkImageView::Create(gpu, image, format,
48                                                           GrVkImageView::kColor_Type);
49    if (!imageView) {
50        return nullptr;
51    }
52
53    return new GrVkTexture(gpu, desc, lifeCycle, imageResource, imageView);
54}
55
56GrVkTexture* GrVkTexture::CreateNewTexture(GrVkGpu* gpu, const GrSurfaceDesc& desc,
57                                           GrGpuResource::LifeCycle lifeCycle,
58                                           const GrVkImage::ImageDesc& imageDesc) {
59    SkASSERT(imageDesc.fUsageFlags & VK_IMAGE_USAGE_SAMPLED_BIT);
60
61    const GrVkImage::Resource* imageResource = GrVkImage::CreateResource(gpu, imageDesc);
62    if (!imageResource) {
63        return nullptr;
64    }
65
66    GrVkTexture* texture = Create(gpu, desc, lifeCycle, imageDesc.fFormat, imageResource);
67    // Create() will increment the refCount of the image resource if it succeeds
68    imageResource->unref(gpu);
69
70    return texture;
71}
72
73GrVkTexture* GrVkTexture::CreateWrappedTexture(GrVkGpu* gpu, const GrSurfaceDesc& desc,
74                                               GrGpuResource::LifeCycle lifeCycle,
75                                               VkFormat format,
76                                               const GrVkImage::Resource* imageResource) {
77    SkASSERT(imageResource);
78
79    // Note: we assume the caller will unref the imageResource
80    // Create() will increment the refCount, and we'll unref when we're done with it
81    return Create(gpu, desc, lifeCycle, format, imageResource);
82}
83
84GrVkTexture::~GrVkTexture() {
85    // either release or abandon should have been called by the owner of this object.
86    SkASSERT(!fTextureView);
87}
88
89void GrVkTexture::onRelease() {
90    // we create this and don't hand it off, so we should always destroy it
91    if (fTextureView) {
92        fTextureView->unref(this->getVkGpu());
93        fTextureView = nullptr;
94    }
95
96    if (this->shouldFreeResources()) {
97        this->releaseImage(this->getVkGpu());
98    } else {
99        this->abandonImage();
100    }
101
102    INHERITED::onRelease();
103}
104
105void GrVkTexture::onAbandon() {
106    if (fTextureView) {
107        fTextureView->unrefAndAbandon();
108        fTextureView = nullptr;
109    }
110
111    this->abandonImage();
112    INHERITED::onAbandon();
113}
114
115GrBackendObject GrVkTexture::getTextureHandle() const {
116    // Currently just passing back the pointer to the Resource as the handle
117    return (GrBackendObject)&fResource;
118}
119
120GrVkGpu* GrVkTexture::getVkGpu() const {
121    SkASSERT(!this->wasDestroyed());
122    return static_cast<GrVkGpu*>(this->getGpu());
123}
124
125