• 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->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