• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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->cleanupCompletedCommandsGarbage();
55     }
56 }
57 
initialize(const egl::Display * display)58 egl::Error ImageVk::initialize(const egl::Display *display)
59 {
60     if (egl::IsTextureTarget(mState.target))
61     {
62         ASSERT(mContext != nullptr);
63         ContextVk *contextVk = vk::GetImpl(mContext);
64         TextureVk *textureVk = GetImplAs<TextureVk>(GetAs<gl::Texture>(mState.source));
65 
66         // Make sure the texture uses renderable format
67         TextureUpdateResult updateResult = TextureUpdateResult::ImageUnaffected;
68         ANGLE_TRY(ResultToEGL(textureVk->ensureRenderable(contextVk, &updateResult)));
69 
70         // Make sure the texture has created its backing storage
71         ANGLE_TRY(ResultToEGL(
72             textureVk->ensureImageInitialized(contextVk, ImageMipLevels::EnabledLevels)));
73 
74         mImage = &textureVk->getImage();
75 
76         // The staging buffer for a texture source should already be initialized
77 
78         mOwnsImage = false;
79     }
80     else
81     {
82         if (egl::IsRenderbufferTarget(mState.target))
83         {
84             RenderbufferVk *renderbufferVk =
85                 GetImplAs<RenderbufferVk>(GetAs<gl::Renderbuffer>(mState.source));
86             mImage = renderbufferVk->getImage();
87 
88             ASSERT(mContext != nullptr);
89         }
90         else if (egl::IsExternalImageTarget(mState.target))
91         {
92             const ExternalImageSiblingVk *externalImageSibling =
93                 GetImplAs<ExternalImageSiblingVk>(GetAs<egl::ExternalImageSibling>(mState.source));
94             mImage = externalImageSibling->getImage();
95 
96             ASSERT(mContext == nullptr);
97         }
98         else
99         {
100             UNREACHABLE();
101             return egl::EglBadAccess();
102         }
103 
104         mOwnsImage = false;
105     }
106 
107     // mContext is no longer needed, make sure it's not used by accident.
108     mContext = nullptr;
109 
110     return egl::NoError();
111 }
112 
orphan(const gl::Context * context,egl::ImageSibling * sibling)113 angle::Result ImageVk::orphan(const gl::Context *context, egl::ImageSibling *sibling)
114 {
115     if (sibling == mState.source)
116     {
117         if (egl::IsTextureTarget(mState.target))
118         {
119             TextureVk *textureVk = GetImplAs<TextureVk>(GetAs<gl::Texture>(mState.source));
120             ASSERT(mImage == &textureVk->getImage());
121             textureVk->releaseOwnershipOfImage(context);
122             mOwnsImage = true;
123         }
124         else if (egl::IsRenderbufferTarget(mState.target))
125         {
126             RenderbufferVk *renderbufferVk =
127                 GetImplAs<RenderbufferVk>(GetAs<gl::Renderbuffer>(mState.source));
128             ASSERT(mImage == renderbufferVk->getImage());
129             renderbufferVk->releaseOwnershipOfImage(context);
130             mOwnsImage = true;
131         }
132         else
133         {
134             ANGLE_VK_UNREACHABLE(vk::GetImpl(context));
135             return angle::Result::Stop;
136         }
137     }
138 
139     // Grab a fence from the releasing context to know when the image is no longer used
140     ASSERT(context != nullptr);
141     ContextVk *contextVk = vk::GetImpl(context);
142 
143     // Flush the context to make sure the fence has been submitted.
144     return contextVk->flushImpl(nullptr, RenderPassClosureReason::ImageOrphan);
145 }
146 
exportVkImage(void * vkImage,void * vkImageCreateInfo)147 egl::Error ImageVk::exportVkImage(void *vkImage, void *vkImageCreateInfo)
148 {
149     *reinterpret_cast<VkImage *>(vkImage) = mImage->getImage().getHandle();
150     auto *info = reinterpret_cast<VkImageCreateInfo *>(vkImageCreateInfo);
151     *info      = mImage->getVkImageCreateInfo();
152     return egl::NoError();
153 }
154 
getImageTextureType() const155 gl::TextureType ImageVk::getImageTextureType() const
156 {
157     return mState.imageIndex.getType();
158 }
159 
getImageLevel() const160 gl::LevelIndex ImageVk::getImageLevel() const
161 {
162     return gl::LevelIndex(mState.imageIndex.getLevelIndex());
163 }
164 
getImageLayer() const165 uint32_t ImageVk::getImageLayer() const
166 {
167     return mState.imageIndex.hasLayer() ? mState.imageIndex.getLayerIndex() : 0;
168 }
169 
170 }  // namespace rx
171