• 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), mImageLevel(0), 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         mImage->releaseImage(renderer);
38         mImage->releaseStagingBuffer(renderer);
39         SafeDelete(mImage);
40     }
41     else if (egl::IsExternalImageTarget(mState.target))
42     {
43         ASSERT(mState.source != nullptr);
44         ExternalImageSiblingVk *externalImageSibling =
45             GetImplAs<ExternalImageSiblingVk>(GetAs<egl::ExternalImageSibling>(mState.source));
46         externalImageSibling->release(renderer);
47         mImage = nullptr;
48     }
49 }
50 
initialize(const egl::Display * display)51 egl::Error ImageVk::initialize(const egl::Display *display)
52 {
53     if (egl::IsTextureTarget(mState.target))
54     {
55         TextureVk *textureVk = GetImplAs<TextureVk>(GetAs<gl::Texture>(mState.source));
56 
57         // Make sure the texture has created its backing storage
58         ASSERT(mContext != nullptr);
59         ContextVk *contextVk = vk::GetImpl(mContext);
60         ANGLE_TRY(ResultToEGL(
61             textureVk->ensureImageInitialized(contextVk, ImageMipLevels::EnabledLevels)));
62 
63         mImage = &textureVk->getImage();
64 
65         // The staging buffer for a texture source should already be initialized
66 
67         mOwnsImage = false;
68 
69         mImageTextureType = mState.imageIndex.getType();
70         mImageLevel       = mState.imageIndex.getLevelIndex();
71         mImageLayer       = mState.imageIndex.hasLayer() ? mState.imageIndex.getLayerIndex() : 0;
72     }
73     else
74     {
75         RendererVk *renderer = nullptr;
76         if (egl::IsRenderbufferTarget(mState.target))
77         {
78             RenderbufferVk *renderbufferVk =
79                 GetImplAs<RenderbufferVk>(GetAs<gl::Renderbuffer>(mState.source));
80             mImage = renderbufferVk->getImage();
81 
82             ASSERT(mContext != nullptr);
83             renderer = vk::GetImpl(mContext)->getRenderer();
84         }
85         else if (egl::IsExternalImageTarget(mState.target))
86         {
87             const ExternalImageSiblingVk *externalImageSibling =
88                 GetImplAs<ExternalImageSiblingVk>(GetAs<egl::ExternalImageSibling>(mState.source));
89             mImage = externalImageSibling->getImage();
90 
91             ASSERT(mContext == nullptr);
92             renderer = vk::GetImpl(display)->getRenderer();
93         }
94         else
95         {
96             UNREACHABLE();
97             return egl::EglBadAccess();
98         }
99 
100         // Make sure a staging buffer is ready to use to upload data
101         mImage->initStagingBuffer(renderer, mImage->getFormat(), vk::kStagingBufferFlags,
102                                   vk::kStagingBufferSize);
103 
104         mOwnsImage = false;
105 
106         mImageTextureType = gl::TextureType::_2D;
107         mImageLevel       = 0;
108         mImageLayer       = 0;
109     }
110 
111     // mContext is no longer needed, make sure it's not used by accident.
112     mContext = nullptr;
113 
114     return egl::NoError();
115 }
116 
orphan(const gl::Context * context,egl::ImageSibling * sibling)117 angle::Result ImageVk::orphan(const gl::Context *context, egl::ImageSibling *sibling)
118 {
119     if (sibling == mState.source)
120     {
121         if (egl::IsTextureTarget(mState.target))
122         {
123             TextureVk *textureVk = GetImplAs<TextureVk>(GetAs<gl::Texture>(mState.source));
124             ASSERT(mImage == &textureVk->getImage());
125             textureVk->releaseOwnershipOfImage(context);
126             mOwnsImage = true;
127         }
128         else if (egl::IsRenderbufferTarget(mState.target))
129         {
130             RenderbufferVk *renderbufferVk =
131                 GetImplAs<RenderbufferVk>(GetAs<gl::Renderbuffer>(mState.source));
132             ASSERT(mImage == renderbufferVk->getImage());
133             renderbufferVk->releaseOwnershipOfImage(context);
134             mOwnsImage = true;
135         }
136         else
137         {
138             ANGLE_VK_UNREACHABLE(vk::GetImpl(context));
139             return angle::Result::Stop;
140         }
141     }
142 
143     // Grab a fence from the releasing context to know when the image is no longer used
144     ASSERT(context != nullptr);
145     ContextVk *contextVk = vk::GetImpl(context);
146 
147     // Flush the context to make sure the fence has been submitted.
148     ANGLE_TRY(contextVk->flushImpl(nullptr));
149 
150     return angle::Result::Continue;
151 }
152 
153 }  // namespace rx
154