1 //
2 // Copyright 2016 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // ImageVk.cpp:
7 // Implements the class methods for ImageVk.
8 //
9
10 #include "libANGLE/renderer/vulkan/ImageVk.h"
11
12 #include "common/debug.h"
13 #include "libANGLE/Context.h"
14 #include "libANGLE/Display.h"
15 #include "libANGLE/renderer/vulkan/ContextVk.h"
16 #include "libANGLE/renderer/vulkan/DisplayVk.h"
17 #include "libANGLE/renderer/vulkan/RenderbufferVk.h"
18 #include "libANGLE/renderer/vulkan/TextureVk.h"
19 #include "libANGLE/renderer/vulkan/vk_utils.h"
20
21 namespace rx
22 {
23
ImageVk(const egl::ImageState & state,const gl::Context * context)24 ImageVk::ImageVk(const egl::ImageState &state, const gl::Context *context)
25 : ImageImpl(state), mOwnsImage(false), mImage(nullptr), mContext(context)
26 {}
27
~ImageVk()28 ImageVk::~ImageVk() {}
29
onDestroy(const egl::Display * display)30 void ImageVk::onDestroy(const egl::Display *display)
31 {
32 DisplayVk *displayVk = vk::GetImpl(display);
33 RendererVk *renderer = displayVk->getRenderer();
34
35 if (mImage != nullptr && mOwnsImage)
36 {
37 // TODO: We need to handle the case that EGLImage used in two context that aren't shared.
38 // https://issuetracker.google.com/169868803
39 mImage->releaseImage(renderer);
40 mImage->releaseStagedUpdates(renderer);
41 SafeDelete(mImage);
42 }
43 else if (egl::IsExternalImageTarget(mState.target))
44 {
45 ASSERT(mState.source != nullptr);
46 ExternalImageSiblingVk *externalImageSibling =
47 GetImplAs<ExternalImageSiblingVk>(GetAs<egl::ExternalImageSibling>(mState.source));
48 externalImageSibling->release(renderer);
49 mImage = nullptr;
50
51 // This is called as a special case where resources may be allocated by the caller, without
52 // the caller ever issuing a draw command to free them. Specifically, SurfaceFlinger
53 // optimistically allocates EGLImages that it may never draw to.
54 renderer->cleanupGarbage();
55 }
56 }
57
initialize(const egl::Display * display)58 egl::Error ImageVk::initialize(const egl::Display *display)
59 {
60 if (mContext != nullptr)
61 {
62 ContextVk *contextVk = vk::GetImpl(mContext);
63 ANGLE_TRY(ResultToEGL(contextVk->getShareGroup()->lockDefaultContextsPriority(contextVk)));
64 }
65
66 if (egl::IsTextureTarget(mState.target))
67 {
68 ASSERT(mContext != nullptr);
69 ContextVk *contextVk = vk::GetImpl(mContext);
70 TextureVk *textureVk = GetImplAs<TextureVk>(GetAs<gl::Texture>(mState.source));
71
72 // Make sure the texture uses renderable format
73 TextureUpdateResult updateResult = TextureUpdateResult::ImageUnaffected;
74 ANGLE_TRY(ResultToEGL(textureVk->ensureRenderable(contextVk, &updateResult)));
75
76 // Make sure the texture has created its backing storage
77 ANGLE_TRY(ResultToEGL(
78 textureVk->ensureImageInitialized(contextVk, ImageMipLevels::EnabledLevels)));
79
80 mImage = &textureVk->getImage();
81
82 // The staging buffer for a texture source should already be initialized
83
84 mOwnsImage = false;
85 }
86 else
87 {
88 if (egl::IsRenderbufferTarget(mState.target))
89 {
90 RenderbufferVk *renderbufferVk =
91 GetImplAs<RenderbufferVk>(GetAs<gl::Renderbuffer>(mState.source));
92 mImage = renderbufferVk->getImage();
93
94 ASSERT(mContext != nullptr);
95 }
96 else if (egl::IsExternalImageTarget(mState.target))
97 {
98 const ExternalImageSiblingVk *externalImageSibling =
99 GetImplAs<ExternalImageSiblingVk>(GetAs<egl::ExternalImageSibling>(mState.source));
100 mImage = externalImageSibling->getImage();
101
102 ASSERT(mContext == nullptr);
103 }
104 else
105 {
106 UNREACHABLE();
107 return egl::EglBadAccess();
108 }
109
110 mOwnsImage = false;
111 }
112
113 // mContext is no longer needed, make sure it's not used by accident.
114 mContext = nullptr;
115
116 return egl::NoError();
117 }
118
orphan(const gl::Context * context,egl::ImageSibling * sibling)119 angle::Result ImageVk::orphan(const gl::Context *context, egl::ImageSibling *sibling)
120 {
121 if (sibling == mState.source)
122 {
123 if (egl::IsTextureTarget(mState.target))
124 {
125 TextureVk *textureVk = GetImplAs<TextureVk>(GetAs<gl::Texture>(mState.source));
126 ASSERT(mImage == &textureVk->getImage());
127 textureVk->releaseOwnershipOfImage(context);
128 mOwnsImage = true;
129 }
130 else if (egl::IsRenderbufferTarget(mState.target))
131 {
132 RenderbufferVk *renderbufferVk =
133 GetImplAs<RenderbufferVk>(GetAs<gl::Renderbuffer>(mState.source));
134 ASSERT(mImage == renderbufferVk->getImage());
135 renderbufferVk->releaseOwnershipOfImage(context);
136 mOwnsImage = true;
137 }
138 else
139 {
140 ANGLE_VK_UNREACHABLE(vk::GetImpl(context));
141 return angle::Result::Stop;
142 }
143 }
144
145 return angle::Result::Continue;
146 }
147
exportVkImage(void * vkImage,void * vkImageCreateInfo)148 egl::Error ImageVk::exportVkImage(void *vkImage, void *vkImageCreateInfo)
149 {
150 *reinterpret_cast<VkImage *>(vkImage) = mImage->getImage().getHandle();
151 auto *info = reinterpret_cast<VkImageCreateInfo *>(vkImageCreateInfo);
152 *info = mImage->getVkImageCreateInfo();
153 return egl::NoError();
154 }
155
getImageTextureType() const156 gl::TextureType ImageVk::getImageTextureType() const
157 {
158 return mState.imageIndex.getType();
159 }
160
getImageLevel() const161 gl::LevelIndex ImageVk::getImageLevel() const
162 {
163 return gl::LevelIndex(mState.imageIndex.getLevelIndex());
164 }
165
getImageLayer() const166 uint32_t ImageVk::getImageLayer() const
167 {
168 return mState.imageIndex.hasLayer() ? mState.imageIndex.getLayerIndex() : 0;
169 }
170
171 } // namespace rx
172